private final void verify() { ListContainer list; final Iterator<ListContainer> iter = _entries.values().iterator(); while (iter.hasNext()) { list = iter.next(); for (Entry ent : list.getEntries()) { for (Ingredient ing : ent.getIngredients()) { if (!verifyIngredient(ing)) { LOG.warn( "{}: Cannot find ingredient with item ID: {} in list: {}!", getClass().getSimpleName(), ing.getItemId(), list.getListId()); } } for (Ingredient ing : ent.getProducts()) { if (!verifyIngredient(ing)) { LOG.warn( "{}: Cannot find product with item ID: {} in list: {}!", getClass().getSimpleName(), ing.getItemId(), list.getListId()); } } } } }
@Override public void parseDocument(Document doc, File f) { try { int id = Integer.parseInt(f.getName().replaceAll(".xml", "")); int entryId = 1; Node att; final ListContainer list = new ListContainer(id); for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling()) { if ("list".equalsIgnoreCase(n.getNodeName())) { att = n.getAttributes().getNamedItem("applyTaxes"); list.setApplyTaxes((att != null) && Boolean.parseBoolean(att.getNodeValue())); att = n.getAttributes().getNamedItem("useRate"); if (att != null) { try { list.setUseRate(Double.valueOf(att.getNodeValue())); if (list.getUseRate() <= 1e-6) { throw new NumberFormatException( "The value cannot be 0"); // threat 0 as invalid value } } catch (NumberFormatException e) { try { list.setUseRate(Config.class.getField(att.getNodeValue()).getDouble(Config.class)); } catch (Exception e1) { LOG.warn( "{}: Unable to parse {}", getClass().getSimpleName(), doc.getLocalName(), e1); list.setUseRate(1.0); } } catch (DOMException e) { LOG.warn("{}: Unable to parse {}", getClass().getSimpleName(), doc.getLocalName(), e); } } att = n.getAttributes().getNamedItem("maintainEnchantment"); list.setMaintainEnchantment((att != null) && Boolean.parseBoolean(att.getNodeValue())); for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling()) { if ("item".equalsIgnoreCase(d.getNodeName())) { Entry e = parseEntry(d, entryId++, list); list.getEntries().add(e); } else if ("npcs".equalsIgnoreCase(d.getNodeName())) { for (Node b = d.getFirstChild(); b != null; b = b.getNextSibling()) { if ("npc".equalsIgnoreCase(b.getNodeName())) { if (Util.isDigit(b.getTextContent())) { list.allowNpc(Integer.parseInt(b.getTextContent())); } } } } } } } _entries.put(id, list); } catch (Exception e) { LOG.error("{}: Error in file {}", getClass().getSimpleName(), f, e); } }
/** * This will generate the multisell list for the items.<br> * There exist various parameters in multisells that affect the way they will appear: * * <ol> * <li>Inventory only: * <ul> * <li>If true, only show items of the multisell for which the "primary" ingredients are * already in the player's inventory. By "primary" ingredients we mean weapon and * armor. * <li>If false, show the entire list. * </ul> * <li>Maintain enchantment: presumably, only lists with "inventory only" set to true should * sometimes have this as true. This makes no sense otherwise... * <ul> * <li>If true, then the product will match the enchantment level of the ingredient.<br> * If the player has multiple items that match the ingredient list but the enchantment * levels differ, then the entries need to be duplicated to show the products and * ingredients for each enchantment level.<br> * For example: If the player has a crystal staff +1 and a crystal staff +3 and goes * to exchange it at the mammon, the list should have all exchange possibilities for * the +1 staff, followed by all possibilities for the +3 staff. * <li>If false, then any level ingredient will be considered equal and product will * always be at +0 * </ul> * <li>Apply taxes: Uses the "taxIngredient" entry in order to add a certain amount of adena to * the ingredients. * <li> * <li>Additional product and ingredient multipliers. * </ol> * * @param listId * @param player * @param npc * @param inventoryOnly * @param productMultiplier * @param ingredientMultiplier */ public final void separateAndSend( int listId, L2PcInstance player, L2Npc npc, boolean inventoryOnly, double productMultiplier, double ingredientMultiplier) { ListContainer template = _entries.get(listId); if (template == null) { LOG.warn( "{}: Cannot find list ID: {} requested by player: {}, NPC ID: {}!", getClass().getSimpleName(), listId, player, (npc != null ? npc.getId() : 0)); return; } if (((npc != null) && !template.isNpcAllowed(npc.getId())) || ((npc == null) && template.isNpcOnly())) { LOG.warn( "{}: Player {} attempted to open multisell {} from npc {} which is not allowed!", getClass().getSimpleName(), player, listId, npc); return; } final PreparedListContainer list = new PreparedListContainer(template, inventoryOnly, player, npc); // Pass through this only when multipliers are different from 1 if ((productMultiplier != 1) || (ingredientMultiplier != 1)) { list.getEntries() .forEach( entry -> { // Math.max used here to avoid dropping count to 0 entry .getProducts() .forEach( product -> product.setItemCount( (long) Math.max(product.getItemCount() * productMultiplier, 1))); // Math.max used here to avoid dropping count to 0 entry .getIngredients() .forEach( ingredient -> ingredient.setItemCount( (long) Math.max(ingredient.getItemCount() * ingredientMultiplier, 1))); }); } int index = 0; do { // send list at least once even if size = 0 player.sendPacket(new MultiSellList(list, index)); index += PAGE_SIZE; } while (index < list.getEntries().size()); player.setMultiSell(list); }