package net.tropicraft.encyclopedia;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.ShapedRecipes;
public class Encyclopedia extends TropicalBook {
/*
* Holds references from each item stack to all of the recipes it is related
* to (either as result or as an ingredient)
*/
private HashMap<ItemStack, List<ShapedRecipes>> recipes = new HashMap<ItemStack, List<ShapedRecipes>>();
/*
* A mapping of page names to each item that should be included in the
* Encyclopedia
*/
private HashMap<String, List<ItemStack>> itemEntries = new HashMap<String, List<ItemStack>>();
public Encyclopedia(String savedDataFile, String contentsFile, String outsideTexture, String insideTexture) {
super(savedDataFile, contentsFile, outsideTexture, insideTexture);
}
@Override
public boolean hasRecipeList() {
return true;
}
/*
* Adds an item name to ItemStack mapping for this encyclopedia. Multiple
* items can be registered with the same name, so that having any of them
* will make the given page visible
* Note: the item name should match the page name given in the text file
*/
public void includeItem(String itemname, ItemStack item) {
if (!itemEntries.containsKey(itemname)) {
itemEntries.put(itemname, new ArrayList<ItemStack>());
}
itemEntries.get(itemname).add(item);
}
/*
* Creates a new ShapedRecipe from the given args, and registers it with any
* Encyclopedia entries related to it
* Note: This method is borrowed/modified from CraftingManager
*/
public void includeRecipe(ItemStack result, Object aobj[]) {
// Note: Must use TreeSet for guaranteed ordering of elements
Set<ItemStack> recipeContents = new HashSet<ItemStack>();
addItemToRecipeContents(recipeContents, result);
String recipeString = "";
int i = 0;
int width = 0;
int height = 0;
if (aobj[i] instanceof String[]) {
String[] cols = (String[]) ((String[]) aobj[i++]);
for (int j = 0; j < cols.length; ++j) {
String row = cols[j];
++height;
width = row.length();
recipeString = recipeString + row;
}
} else {
while (aobj[i] instanceof String) {
String row = (String) aobj[i++];
++height;
width = row.length();
recipeString = recipeString + row;
}
}
HashMap<Character, ItemStack> charMap;
for (charMap = new HashMap(); i < aobj.length; i += 2) {
Character itemChar = (Character) aobj[i];
ItemStack itemStack = null;
if (aobj[i + 1] instanceof Item) {
itemStack = new ItemStack((Item) aobj[i + 1]);
} else if (aobj[i + 1] instanceof Block) {
itemStack = new ItemStack((Block) aobj[i + 1], 1, -1);
} else if (aobj[i + 1] instanceof ItemStack) {
itemStack = (ItemStack) aobj[i + 1];
}
charMap.put(itemChar, itemStack);
addItemToRecipeContents(recipeContents, itemStack);
}
ItemStack[] slotArray = new ItemStack[width * height];
for (int slots = 0; slots < width * height; slots++) {
char itemChar = recipeString.charAt(slots);
if (charMap.containsKey(itemChar)) {
slotArray[slots] = ((ItemStack) charMap.get(itemChar)).copy();
} else {
slotArray[slots] = null;
}
}
// Added code to register this recipe with the ingredient lookup
ShapedRecipes recipe = new ShapedRecipes(width, height, slotArray, result);
for (ItemStack item : recipeContents) {
boolean foundKey = false;
for (ItemStack key : recipes.keySet()) {
if (item.isItemEqual(key)) {
foundKey = true;
recipes.get(key).add(recipe);
break;
}
}
if (foundKey == false) {
recipes.put(item, new ArrayList<ShapedRecipes>());
recipes.get(item).add(recipe);
}
}
}
/*
* Returns all recipes related to a given entry page
*/
public List<ShapedRecipes> getRecipesForEntry(int page) {
List<ItemStack> entryItems = itemEntries.get(getPageName(page));
List<ShapedRecipes> recipeList = new ArrayList<ShapedRecipes>();
if (entryItems != null) {
for (ItemStack item : entryItems) {
//System.out.println();
for (ItemStack recipeItem : recipes.keySet()) {
if (recipeItem.isItemEqual(item)) {
List<ShapedRecipes> itemRecipes = recipes.get(recipeItem);
if (itemRecipes != null) {
recipeList.addAll(itemRecipes);
}
}
}
}
}
return recipeList;
}
/*
* Returns the number of content pages associated with the given entry and
* content type
* Note: Individual recipes are counted as 1 page each - the GUI must
* join them up according to the number of recipes to display per page
*/
@Override
public int getContentPageCount(int page, ContentMode mode) {
if (page >= 0 && page < getPageCount()) {
if (mode == ContentMode.INFO) {
return 1;
} else if (mode == ContentMode.RECIPE) {
List<ShapedRecipes> recipeList = getRecipesForEntry(page);
if (recipeList != null) {
return recipeList.size();
}
}
}
return 0;
}
@Override
public int entriesPerContentPage(ContentMode mode) {
if (mode == ContentMode.RECIPE) {
return 3;
}
return super.entriesPerContentPage(mode);
}
@Override
public boolean hasIndexIcons() {
return true;
}
@Override
public ItemStack getPageItemStack(int page) {
if (page >= 0 && page < getPageCount()) {
List<ItemStack> items = itemEntries.get(getPageName(page));
if (items != null && !items.isEmpty()) {
return items.get(0);
}
}
return null;
}
@Override
public void updatePagesFromInventory(InventoryPlayer inv) {
for (ItemStack is : inv.mainInventory) {
if (is != null) {
ItemStack comparison = new ItemStack(is.getItem(), 1, is.getItemDamage());
for (String entry : itemEntries.keySet()) {
if (!isPageVisible(entry)) {
List<ItemStack> itemsInBook = itemEntries.get(entry);
for (ItemStack itemInBook : itemsInBook) {
if (ItemStack.areItemStacksEqual(itemInBook, comparison)) {
markPageAsNewlyVisible(entry);
}
}
}
}
}
}
}
/*
* Adds an ItemStack to the given set, as long as an equivalent item isn't
* already in the set
*/
private void addItemToRecipeContents(Set<ItemStack> items, ItemStack i) {
boolean shouldAdd = !(items.contains(i));
for (ItemStack listItem : items) {
if (listItem.isItemEqual(i)) {
shouldAdd = false;
break;
}
}
if (shouldAdd) {
items.add(i);
}
}
public RecipeEntry getFormattedRecipe(ShapedRecipes recipe) {
try {
int width = recipe.recipeWidth;//(Integer) TropicraftMod.getPrivateValueBoth(ShapedRecipes.class, recipe, "b", "recipeWidth");
int height = recipe.recipeHeight;//(Integer) TropicraftMod.getPrivateValueBoth(ShapedRecipes.class, recipe, "c", "recipeHeight");
ItemStack[] items = recipe.recipeItems;//(ItemStack[]) TropicraftMod.getPrivateValueBoth(ShapedRecipes.class, recipe, "d", "recipeItems");
ItemStack output = recipe.getRecipeOutput();//(ItemStack) TropicraftMod.getPrivateValueBoth(ShapedRecipes.class, recipe, "e", "recipeOutput");
return new RecipeEntry(width, height, items, output);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public class RecipeEntry {
public int width;
public int height;
public ItemStack[] ingredients;
public ItemStack output;
public RecipeEntry(int width, int height, ItemStack[] ingredients, ItemStack output) {
this.width = width;
this.height = height;
this.ingredients = ingredients;
this.output = output;
}
}
}