/** * Set the contents of an ItemArray. * * @param itemArray * @param contents */ public static void setContents(ItemArray<?> itemArray, Item[] contents) { int size = itemArray.getContentsSize(); for (int i = 0; i < size; i++) { if (contents[i] == null) { itemArray.removeItem(i); } else { itemArray.setSlot(contents[i], i); } } }
/** * The class is called to determine behavior of program based on instruction at current position. * The function is part of indirect recursion with method runInstructions which is called when the * conditional split is required. * * <p>The function covers basic operands for pushing integers and (string) objects stack as long * as retrieving them back. Also it covers conditions for not null and null operations which * results into separate execution of both branches conditioned on item on stack. * * @param instruction "on the stack" * @return 0 - no dangerous, end; 1 - continue in check * @throws DangerousPatternException when dangerous pattern found */ private int watchOpcode(InstructionHandle instruction) throws DangerousPatternException { short opcode = instruction.getInstruction().getOpcode(); ItemInt tempItemInt; Item temp; switch (opcode) { case ICONST_0: tempItemInt = new ItemInt(false); tempItemInt.setValue(0); this.push(tempItemInt); break; case ICONST_1: tempItemInt = new ItemInt(false); tempItemInt.setValue(1); this.push(tempItemInt); break; case ICONST_2: tempItemInt = new ItemInt(false); tempItemInt.setValue(2); this.push(tempItemInt); break; case ICONST_M1: tempItemInt = new ItemInt(false); tempItemInt.setValue(-1); this.push(tempItemInt); break; case RETURN: return 0; case ARETURN: case IRETURN: this.pop(); return 0; case ACONST_NULL: temp = new Item(true); this.push(temp); break; case ALOAD_1: this.push(this.takeFromItemPool(1)); break; case ALOAD_2: this.push(this.takeFromItemPool(2)); break; case ALOAD_3: this.push(this.takeFromItemPool(3)); break; case ALOAD: this.push(this.takeFromItemPool(this.parseValue(instruction, " "))); break; case AALOAD: // TODO: Rework. Outer variables would be nicer! tempItemInt = (ItemInt) this.pop(); temp = this.pop(); ItemArray list; if (temp instanceof ItemArray) { list = (ItemArray) temp; this.push(list.getItem(tempItemInt.getValue())); } else { list = new ItemArray(); list.setAddress(temp.getAddress()); this.putToItemPool(list); temp.setAddress(-1); this.push(temp); } break; case AASTORE: Item value = this.pop(); tempItemInt = (ItemInt) this.pop(); temp = this.pop(); ItemArray list2; if (temp instanceof ItemArray) { list2 = (ItemArray) temp; list2.putItem(tempItemInt.getValue(), value); } else { list2 = new ItemArray(); list2.setAddress(temp.getAddress()); list2.putItem(tempItemInt.getValue(), value); this.putToItemPool(list2); } break; case LDC: temp = new Item(false); this.push(temp); break; case ASTORE_1: temp = this.pop(); temp.setAddress(1); this.putToItemPool(temp); break; case ASTORE_2: temp = this.pop(); temp.setAddress(2); this.putToItemPool(temp); break; case ASTORE_3: temp = this.pop(); temp.setAddress(3); this.putToItemPool(temp); break; case ASTORE: temp = this.pop(); temp.setAddress(this.parseValue(instruction, " ")); this.putToItemPool(temp); break; case INVOKEVIRTUAL: if (this.lookAtStack().isDangerous()) { throw new DangerousPatternException("Possibility of invoking method on null object"); } break; case IFNONNULL: temp = this.pop(); // TODO: make local variable fot that item, this is ugly if (temp.isDangerous()) { temp.setDangerous(false); this.putToItemPool(temp); this.runInstructions(this.parseValue(instruction, " -> ")); temp.setDangerous(true); } else { this.putToItemPool(temp); this.runInstructions(this.parseValue(instruction, " -> ")); return 0; } break; case IFNULL: temp = this.pop(); if (temp.isDangerous()) { this.putToItemPool(temp); this.runInstructions(this.parseValue(instruction, " -> ")); return 0; } else { this.putToItemPool(temp); } break; case POP: this.pop(); break; default: Logger.getLogger(BugPatternDetectorImpl.class.getName()) .log( Level.WARNING, "The unknown opcode called: " + instruction.getInstruction().getName()); break; } return 1; }
public static void moveItemArrayToChestBag( ItemArray<?> from, NearbyChestBlockBag bag, int itemType, int itemColor, int itemAmount) { Item[] fromItems = from.getContents(); Inventory[] inventories = bag.getInventories(); int invenIndex = 0; boolean changed = false; int currentAmount = 0; try { for (int cartSlot = 0; cartSlot < fromItems.length; cartSlot++) { Item cartItem = fromItems[cartSlot]; if (cartItem == null || cartItem.getAmount() == 0 || (itemType > 0 && (itemType != cartItem.getItemId() || (itemColor != -1 && itemColor != cartItem.getDamage())))) { continue; } currentAmount += cartItem.getAmount(); Item itemCopy = null; if (itemAmount > 0 && currentAmount > itemAmount) { itemCopy = new Item( cartItem.getItemId(), currentAmount - itemAmount, cartItem.getSlot(), cartItem.getDamage()); cartItem.setAmount(cartItem.getAmount() - itemCopy.getAmount()); } try { for (; invenIndex < inventories.length; invenIndex++) { Item[] chestItems = inventories[invenIndex].getContents(); for (int chestSlot = 0; chestSlot < chestItems.length; chestSlot++) { Item chestItem = chestItems[chestSlot]; if (chestItem == null) { chestItems[chestSlot] = cartItem; fromItems[cartSlot] = null; setContents(inventories[invenIndex], chestItems); changed = true; throw new TransferredItemException(); } else { int maxStack = getStackMax(chestItem); if (chestItem.getItemId() == cartItem.getItemId() && isSameColor(chestItem, cartItem) && chestItem.getAmount() < maxStack && chestItem.getAmount() >= 0) { int spaceAvailable = maxStack - chestItem.getAmount(); if (spaceAvailable >= cartItem.getAmount()) { chestItem.setAmount(chestItem.getAmount() + cartItem.getAmount()); fromItems[cartSlot] = null; setContents(inventories[invenIndex], chestItems); changed = true; throw new TransferredItemException(); } else { cartItem.setAmount(cartItem.getAmount() - spaceAvailable); chestItem.setAmount(maxStack); changed = true; } } } } if (changed) { setContents(inventories[invenIndex], chestItems); } } throw new TargetFullException(); } catch (TransferredItemException e) { } if (itemAmount > 0 && currentAmount >= itemAmount) { if (itemCopy != null) { if (fromItems[cartSlot] != null) { itemCopy.setAmount(itemCopy.getAmount() + fromItems[cartSlot].getAmount()); } fromItems[cartSlot] = itemCopy; } break; } } } catch (TargetFullException e) { } if (changed) { setContents(from, fromItems); } }
/* * M4411K4: redoing code here because the last code from * I guess sk89q, didn't work properly and used more resources * than should have (using exceptions to break? o_O) */ public static void moveChestBagToItemArray( ItemArray<?> to, NearbyChestBlockBag bag, int itemType, int itemColor, int itemAmount) { Item[] toItems = to.getContents(); Inventory[] bags = bag.getInventories(); boolean changed = false; int currentAmount = 0; for (int toSlot = 0; toSlot < toItems.length; toSlot++) { Item toItem = toItems[toSlot]; int maxStack = 0; if (toItem != null) { maxStack = getStackMax(toItem); if (toItem.getAmount() >= maxStack || (itemType > 0 && (itemType != toItem.getItemId() || (itemColor != -1 && itemColor != toItem.getDamage())))) { continue; } } boolean moved = false; for (Inventory inventory : bags) { Item[] chestItems = inventory.getContents(); for (int chestSlot = 0; chestSlot < chestItems.length; chestSlot++) { Item chestItem = chestItems[chestSlot]; if (chestItem == null || chestItem.getAmount() == 0 || (toItem != null && (chestItem.getItemId() != toItem.getItemId() || chestItem.getDamage() != toItem.getDamage())) || (itemType > 0 && (itemType != chestItem.getItemId() || (itemColor != -1 && itemColor != chestItem.getDamage())))) { // empty or not the same item so move on to next slot continue; } currentAmount += chestItem.getAmount(); Item itemCopy = null; if (itemAmount > 0 && currentAmount > itemAmount) { itemCopy = new Item( chestItem.getItemId(), currentAmount - itemAmount, chestItem.getSlot(), chestItem.getDamage()); chestItem.setAmount(chestItem.getAmount() - itemCopy.getAmount()); } // can move to slot if (toItem == null) { toItems[toSlot] = chestItem; chestItems[chestSlot] = null; } else { // maxStack should have correct value since toItem is not null int spaceAvailable = maxStack - toItem.getAmount(); if (spaceAvailable >= chestItem.getAmount()) { // everything fits toItem.setAmount(toItem.getAmount() + chestItem.getAmount()); chestItems[chestSlot] = null; } else { // doesn't fit into slot toItem.setAmount(maxStack); chestItem.setAmount(chestItem.getAmount() - spaceAvailable); } } // if not max, re-check slot maxStack = getStackMax(toItems[toSlot]); if (toItems[toSlot].getAmount() < maxStack) { toSlot--; } if (itemCopy != null) { if (chestItems[chestSlot] != null) { itemCopy.setAmount(itemCopy.getAmount() + chestItems[chestSlot].getAmount()); } chestItems[chestSlot] = itemCopy; } moved = true; changed = true; break; } if (moved || (itemAmount > 0 && currentAmount >= itemAmount)) { // set chest items with new values setContents(inventory, chestItems); // go to next item slot break; } } if (itemAmount > 0 && currentAmount >= itemAmount) { break; } } if (changed) { setContents(to, toItems); } }