/*
* Copyright (C) 2004-2015 L2J Server
*
* This file is part of L2J Server.
*
* L2J Server is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* L2J Server is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package com.l2jserver.gameserver.data.xml.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import com.l2jserver.gameserver.model.L2RecipeInstance;
import com.l2jserver.gameserver.model.L2RecipeList;
import com.l2jserver.gameserver.model.L2RecipeStatInstance;
import com.l2jserver.gameserver.model.StatsSet;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;
import com.l2jserver.util.data.xml.IXmlReader;
/**
* The Class RecipeData.
* @author Zoey76
*/
public class RecipeData implements IXmlReader
{
private final Map _recipes = new HashMap<>();
/**
* Instantiates a new recipe data.
*/
protected RecipeData()
{
load();
}
@Override
public void load()
{
_recipes.clear();
parseDatapackFile("data/recipes.xml");
LOGGER.info("{}: Loaded {} recipes.", getClass().getSimpleName(), _recipes.size());
}
@Override
public void parseDocument(Document doc)
{
// TODO: Cleanup checks enforced by XSD.
final List recipePartList = new ArrayList<>();
final List recipeStatUseList = new ArrayList<>();
final List recipeAltStatChangeList = new ArrayList<>();
for (Node n = doc.getFirstChild(); n != null; n = n.getNextSibling())
{
if ("list".equalsIgnoreCase(n.getNodeName()))
{
RECIPES_FILE: for (Node d = n.getFirstChild(); d != null; d = d.getNextSibling())
{
if ("item".equalsIgnoreCase(d.getNodeName()))
{
recipePartList.clear();
recipeStatUseList.clear();
recipeAltStatChangeList.clear();
NamedNodeMap attrs = d.getAttributes();
Node att;
int id = -1;
boolean haveRare = false;
StatsSet set = new StatsSet();
att = attrs.getNamedItem("id");
if (att == null)
{
LOGGER.error("{}: Missing id for recipe item, skipping!", getClass().getSimpleName());
continue;
}
id = Integer.parseInt(att.getNodeValue());
set.set("id", id);
att = attrs.getNamedItem("recipeId");
if (att == null)
{
LOGGER.error("{}: Missing recipeId for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue;
}
set.set("recipeId", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("name");
if (att == null)
{
LOGGER.error("{}: Missing name for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue;
}
set.set("recipeName", att.getNodeValue());
att = attrs.getNamedItem("craftLevel");
if (att == null)
{
LOGGER.error("{}: Missing level for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue;
}
set.set("craftLevel", Integer.parseInt(att.getNodeValue()));
att = attrs.getNamedItem("type");
if (att == null)
{
LOGGER.error("{}: Missing type for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue;
}
set.set("isDwarvenRecipe", att.getNodeValue().equalsIgnoreCase("dwarven"));
att = attrs.getNamedItem("successRate");
if (att == null)
{
LOGGER.error("{}: Missing successRate for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue;
}
set.set("successRate", Integer.parseInt(att.getNodeValue()));
for (Node c = d.getFirstChild(); c != null; c = c.getNextSibling())
{
if ("statUse".equalsIgnoreCase(c.getNodeName()))
{
String statName = c.getAttributes().getNamedItem("name").getNodeValue();
int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
{
recipeStatUseList.add(new L2RecipeStatInstance(statName, value));
}
catch (Exception e)
{
LOGGER.error("{}: Error in StatUse parameter for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue RECIPES_FILE;
}
}
else if ("altStatChange".equalsIgnoreCase(c.getNodeName()))
{
String statName = c.getAttributes().getNamedItem("name").getNodeValue();
int value = Integer.parseInt(c.getAttributes().getNamedItem("value").getNodeValue());
try
{
recipeAltStatChangeList.add(new L2RecipeStatInstance(statName, value));
}
catch (Exception e)
{
LOGGER.error("{}: Error in AltStatChange parameter for recipe item ID: {}, skipping!", getClass().getSimpleName(), id);
continue RECIPES_FILE;
}
}
else if ("ingredient".equalsIgnoreCase(c.getNodeName()))
{
int ingId = Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue());
int ingCount = Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue());
recipePartList.add(new L2RecipeInstance(ingId, ingCount));
}
else if ("production".equalsIgnoreCase(c.getNodeName()))
{
set.set("itemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
set.set("count", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
}
else if ("productionRare".equalsIgnoreCase(c.getNodeName()))
{
set.set("rareItemId", Integer.parseInt(c.getAttributes().getNamedItem("id").getNodeValue()));
set.set("rareCount", Integer.parseInt(c.getAttributes().getNamedItem("count").getNodeValue()));
set.set("rarity", Integer.parseInt(c.getAttributes().getNamedItem("rarity").getNodeValue()));
haveRare = true;
}
}
L2RecipeList recipeList = new L2RecipeList(set, haveRare);
for (L2RecipeInstance recipePart : recipePartList)
{
recipeList.addRecipe(recipePart);
}
for (L2RecipeStatInstance recipeStatUse : recipeStatUseList)
{
recipeList.addStatUse(recipeStatUse);
}
for (L2RecipeStatInstance recipeAltStatChange : recipeAltStatChangeList)
{
recipeList.addAltStatChange(recipeAltStatChange);
}
_recipes.put(id, recipeList);
}
}
}
}
}
/**
* Gets the recipe list.
* @param listId the list id
* @return the recipe list
*/
public L2RecipeList getRecipeList(int listId)
{
return _recipes.get(listId);
}
/**
* Gets the recipe by item id.
* @param itemId the item id
* @return the recipe by item id
*/
public L2RecipeList getRecipeByItemId(int itemId)
{
for (L2RecipeList find : _recipes.values())
{
if (find.getRecipeId() == itemId)
{
return find;
}
}
return null;
}
/**
* Gets the all item ids.
* @return the all item ids
*/
public int[] getAllItemIds()
{
int[] idList = new int[_recipes.size()];
int i = 0;
for (L2RecipeList rec : _recipes.values())
{
idList[i++] = rec.getRecipeId();
}
return idList;
}
/**
* Gets the valid recipe list.
* @param player the player
* @param id the recipe list id
* @return the valid recipe list
*/
public L2RecipeList getValidRecipeList(L2PcInstance player, int id)
{
L2RecipeList recipeList = _recipes.get(id);
if ((recipeList == null) || (recipeList.getRecipes().length == 0))
{
player.sendMessage(getClass().getSimpleName() + ": No recipe for: " + id);
player.isInCraftMode(false);
return null;
}
return recipeList;
}
/**
* Gets the single instance of RecipeData.
* @return single instance of RecipeData
*/
public static RecipeData getInstance()
{
return SingletonHolder._instance;
}
/**
* The Class SingletonHolder.
*/
private static class SingletonHolder
{
protected static final RecipeData _instance = new RecipeData();
}
}