/******************************************************************************* * AbyssalCraft * Copyright (c) 2012 - 2017 Shinoow. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/lgpl-3.0.txt * * Contributors: * Shinoow - implementation ******************************************************************************/ package com.shinoow.abyssalcraft.api.necronomicon; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.NavigableMap; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.texture.TextureUtil; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.FMLLog; import org.apache.logging.log4j.Level; import com.google.common.collect.Maps; import com.shinoow.abyssalcraft.api.AbyssalCraftAPI; import com.shinoow.abyssalcraft.api.necronomicon.condition.DefaultCondition; import com.shinoow.abyssalcraft.api.necronomicon.condition.IUnlockCondition; /** * Base data structure for Necronomicon information pages * @author shinoow * * @since 1.2 */ public class NecroData { private String identifier; private String title; private String information; private Chapter[] chapters; /** * The base data structure for Necronomicon information pages * @param title Title to display on the "Index" for the information page * @param info Optional text to write beside buttons for sub-category pages * @param chapters Chapters for sub-category pages */ public NecroData(String identifier, String title, String info,Chapter...chapters){ this.identifier = identifier; this.title = title; this.chapters = chapters; information = info; } /** * The base data structure for Necronomicon information pages * @param title Title to display on the "Index" for the information page * @param chapters Chapters for sub-category pages */ public NecroData(String identifier, String title,Chapter...chapters){ this(identifier, title, null, chapters); } /** * Getter for the NecroData title * @return A string representing the Title of the information page */ public String getTitle(){ return title; } /** * Getter for the category information * @return A specified string used to display on the information page */ public String getInformation(){ return information; } /** * Getter for the NecroData identifier * @return A unique string representing this NecroData */ public String getIdentifier(){ return identifier; } /** * Getter for the Chapter array * @return An array of stored Chapters */ public Chapter[] getChapters(){ return chapters; } /** * Method for getting the title of a specific sub-category * @param index Position in the index to check * @return A string representing the Chapter title */ public String getChapterTitle(int index){ return chapters[index].title; } /** * Adds a Chapter (or overrides one that already exists) * @param chapter Chapter to add */ public void addChapter(Chapter chapter){ for(Chapter chap : chapters) if(chap.identifier.equals(chapter.identifier)){ chap = chapter; return; } if(chapters.length < 7){ Chapter[] newchap = new Chapter[chapters.length + 1]; for(int i = 0; i < chapters.length; i++) newchap[i] = chapters[i]; newchap[chapters.length] = chapter; chapters = newchap; } else FMLLog.log("AbyssalCraftAPI", Level.ERROR, "NecroData instance is already full, can't add a new Chapter!"); } /** * Removes a Chapter (if it exists) * @param identifier Chapter identifier */ public void removeChapter(String identifier){ Chapter[] newchap = new Chapter[chapters.length -1]; Chapter[] oldchap = chapters.clone(); for(Chapter chap : oldchap) if(chap.identifier.equals(identifier)){ for(Chapter chapnew : newchap) for(Chapter chap2 : oldchap) if(chap2 != null && !chap2.identifier.equals(identifier)){ chapnew = chap2; chap2 = null; break; } chapters = newchap; return; } } /** * A Necronomicon Chapter (collection of pages) * @author shinoow * * @since 1.6 */ public static class Chapter{ private NavigableMap<Integer, Page> pages = Maps.newTreeMap((o1, o2) -> { if(o1 > o2) return 1; if(o1 < o2) return -1; return 0; }); private String identifier; private String title; /** * A Necronomicon Chapter * @param identifier Identifier (used to locate the chapter, should be unique for every NecroData) * @param title Title to display on pages in the Chapter */ public Chapter(String identifier, String title){ this.identifier = identifier; this.title = title; } /** * A Necronomicon Chapter * @param identifier Identifier (used to locate the chapter, should be unique for every NecroData) * @param title Title to display on pages in the Chapter * @param pages an array of Pages (it is optional to do it this way) */ public Chapter(String identifier, String title, Page...pages){ this(identifier, title); for(Page page : pages) addPage(page); } /** * Getter for the Chapter identifier */ public String getIdentifier(){ return identifier; } /** * Getter for the Chapter title */ public String getTitle(){ return title; } /** * Fetches a unmodifiable Map of all the Pages contained in this Chapter */ public Map<Integer, Page> getPages(){ return Collections.unmodifiableMap(pages); } /** * Getter for the page amount */ public int getPageAmount(){ return pages.size(); } /** * Getter for the turn-up amount (last page number evenly divided by 2) */ public int getTurnupAmount(){ return pages.lastKey() / 2 + (pages.lastKey() % 2 == 0 ? 0 : 1); } /** * Adds a page to the Chapter * @param page Page to add */ public void addPage(Page page){ pages.put(page.pageNum, page); } /** * Removes a Page (if it exists) * @param pageNum Page number */ public void removePage(int pageNum){ pages.remove(pageNum); } /** * Fetches a page (if it exists) * @param pageNum Page number */ public Page getPage(int pageNum){ return pages.get(pageNum); } /** * Checks if a Page exists * @param pageNum Page number */ public boolean hasPage(int pageNum){ return pages.containsKey(pageNum); } } /** * A Necronomicon Page * @author shinoow * * @since 1.6 */ public static class Page{ private Object icon; private int pageNum; private String text; private IUnlockCondition condition; /** * A Necronomicon Page * @param pageNum Page number * @param text Text to display on the Page */ public Page(int pageNum, String text){ this(pageNum, null, text, new DefaultCondition()); } /** * A Necronomicon Page * @param pageNum Page number * @param text Text to display on the Page * @param condition Condition to determine whether or not this page can be read */ public Page(int pageNum, String text, IUnlockCondition condition){ this(pageNum, null, text, condition); } /** * A Necronomicon Page * @param pageNum Page number * @param icon ResourceLocation/ItemStack/CraftingStack to display on the Page * @param text Text to display on the Page */ public Page(int pageNum, Object icon, String text){ this(pageNum, icon, text, new DefaultCondition()); } /** * A Necronomicon Page * @param pageNum Page number * @param icon ResourceLocation/ItemStack/CraftingStack to display on the Page * @param text Text to display on the Page */ public Page(int pageNum, Object icon, String text, IUnlockCondition condition){ if(pageNum == 0) throw new ArithmeticException("The Page number can't be zero"); this.pageNum = pageNum; if(icon != null) if(!(icon instanceof ResourceLocation) && !(icon instanceof ItemStack) && !(icon instanceof CraftingStack) && !(icon instanceof String)) throw new IllegalArgumentException("Icon isn't a ResourceLocation, ItemStack, CraftingStack or URL String!"); this.icon = verify(icon); this.text = text; this.condition = condition; } private Object verify(Object obj){ if(obj instanceof String) AbyssalCraftAPI.getInternalNDHandler().verifyImageURL((String)obj); if(!(obj instanceof ResourceLocation)) return obj; if(FMLCommonHandler.instance().getSide().isServer()) return obj; ResourceLocation res = (ResourceLocation)obj; if(res.toString().equals("abyssalcraft:textures/gui/necronomicon/missing.png")) return obj; try { TextureUtil.readBufferedImage(Minecraft.getMinecraft().getResourceManager().getResource(res).getInputStream()); } catch (IOException e) { return new ResourceLocation("abyssalcraft", "textures/gui/necronomicon/missing.png"); } return res; } /** * Fetches the page's number (used for ordering and overriding/removing/replacing pages). */ public int getPageNumber(){ return pageNum; } /** * Fetches the ResourceLocation/ItemStack/CraftingStack to display on the page (if any exist). */ public Object getIcon(){ return icon; } /** * Fetches the text to display on the page. */ public String getText(){ return text; } /** * Fetches the unlocking condition (determines if the page can be read) */ public IUnlockCondition getCondition(){ return condition; } @Override public boolean equals(Object obj){ if(!(obj instanceof Page)) return false; Page page = (Page)obj; boolean test1 = page.pageNum == pageNum; boolean test2 = page.icon == null && icon == null || page.icon.equals(icon); boolean test3 = page.text.equals(text); boolean test4 = page.condition.areConditionObjectsEqual(condition.getConditionObject()); return test1 && test2 && test3 && test4; } } }