package eiteam.esteemedinnovation.book; import eiteam.esteemedinnovation.api.Constants; import eiteam.esteemedinnovation.api.book.*; import eiteam.esteemedinnovation.commons.CrossMod; import eiteam.esteemedinnovation.commons.EsteemedInnovation; import eiteam.esteemedinnovation.commons.util.MathUtility; import eiteam.esteemedinnovation.misc.integration.EnchiridionIntegration; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.TextFormatting; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.input.Mouse; import java.io.IOException; import java.util.ArrayList; import java.util.List; import static eiteam.esteemedinnovation.book.BookModule.BOOK; public class GuiJournal extends GuiScreen implements eiteam.esteemedinnovation.api.book.GuiJournal { private static final ResourceLocation BOOK_RIGHT_GUI_TEXTURES = new ResourceLocation(Constants.API_MODID, "textures/gui/book_right.png"); private static final ResourceLocation BOOK_FRONT_TEXTURES = new ResourceLocation(Constants.API_MODID, "textures/gui/book_front.png"); private static final ResourceLocation BOOK_LEFT_GUI_TEXTURES = new ResourceLocation(Constants.API_MODID, "textures/gui/book_left.png"); private int bookTotalPages = 1; private int currPage; private int lastIndexPage; public String viewing = ""; private ItemStack book; private boolean mustReleaseMouse; public static final int BOOK_IMAGE_WIDTH = 192; public static final int BOOK_IMAGE_HEIGHT = 192; private GuiJournal.NextPageButton buttonNextPage; private GuiJournal.NextPageButton buttonPreviousPage; private final List<String> sections; /** * The Ideas section is generated every time you open the book to that section, not during game load, so it cannot * be a real section. It is handled as a special case. */ private static final String FAKE_SECTION_IDEAS = "section.Ideas.name"; public GuiJournal(EntityPlayer player) { sections = new ArrayList<>(); for (BookSection section : BookPageRegistry.sections.values()) { if (section.isHidden(player)) { continue; } if (section.isUnlocked(player)) { int pages = section.getCategories().size(); for (int s = 0; s < MathHelper.ceiling_float_int(pages / 9.0F); s++) { sections.add(section.getName() + (s == 0 ? "" : s)); } } } sections.add(FAKE_SECTION_IDEAS); bookTotalPages = MathHelper.ceiling_float_int(sections.size() / 2F) + 1; if (!viewing.isEmpty()) { BookEntry entry = BookPageRegistry.getEntryFromName(viewing); if (entry != null) { bookTotalPages = MathHelper.ceiling_float_int(entry.getPages().size() / 2F); } } ItemStack active = player.getHeldItemMainhand(); if (active != null && active.getItem() instanceof ItemEsteemedInnovationJournal) { book = active; } else { if (CrossMod.ENCHIRIDION) { book = EnchiridionIntegration.findBook(BOOK, player); } for (int i = 0; i < player.inventory.getSizeInventory(); i++) { ItemStack stack = player.inventory.getStackInSlot(i); if (stack != null && stack.getItem() instanceof ItemEsteemedInnovationJournal) { book = stack; break; } } } } private int getWidth() { return (width - BOOK_IMAGE_WIDTH) / 2; } private int getHeight() { return (height - BOOK_IMAGE_HEIGHT) / 2; } @Override public Minecraft getMC() { return mc; } @Override public String getCurrentEntry() { return viewing; } @Override public boolean doesGuiPauseGame() { return false; } @Override public void updateScreen() { super.updateScreen(); } @Override public void initGui() { buttonList.clear(); int i = (width - BOOK_IMAGE_WIDTH) / 2; int b0 = (height - BOOK_IMAGE_HEIGHT) / 2; buttonNextPage = new GuiJournal.NextPageButton(1, i + 120 + 67, b0 + 154, true); buttonPreviousPage = new GuiJournal.NextPageButton(2, i + 38 - 67, b0 + 154, false); buttonList.add(buttonNextPage); buttonList.add(buttonPreviousPage); updateButtons(); } public void updateButtons() { buttonNextPage.visible = (currPage < bookTotalPages - 1); buttonPreviousPage.visible = currPage > 0; } @Override protected void actionPerformed(GuiButton button) { if (button.enabled) { if (button.id == 0) { mc.displayGuiScreen(null); } else if (button.id == 1) { if (currPage < bookTotalPages - 1) { ++currPage; } } else if (button.id == 2) { if (currPage > 0) { --currPage; } } // else if (button.id == 3) // { // this.viewing = ""; // this.currPage = lastIndexPage; // int i = 0; // String lastCategory = ""; // boolean canDo = true; // this.bookTotalPages = MathHelper.ceiling_float_int(GeneralRegistry.categories.size()/2F)+1; // this.updateButtons(); // } if (button instanceof GuiButtonSelect) { GuiButtonSelect buttonSelect = (GuiButtonSelect) button; viewing = buttonSelect.name.substring(0, 1).equals("#") ? buttonSelect.name.substring(1) : buttonSelect.name; int numPages = -1; BookCategory category = BookPageRegistry.getCategoryFromName(viewing); if (category != null && category.isUnlocked(mc.thePlayer)) { numPages = category.getAllVisiblePages(mc.thePlayer).length; } if (numPages != -1) { lastIndexPage = currPage; currPage = 0; bookTotalPages = MathHelper.ceiling_float_int(numPages / 2F); updateButtons(); mustReleaseMouse = true; } } initGui(); } } @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { if (keyCode == 1 && !viewing.isEmpty()) { viewing = ""; currPage = lastIndexPage; bookTotalPages = MathHelper.ceiling_float_int(sections.size() / 2F) + 1; updateButtons(); } else { super.keyTyped(typedChar, keyCode); } } private void handleDWheelMovement() { int dWheelRecentMovement = Mouse.getDWheel(); if (dWheelRecentMovement < 0 && buttonNextPage.visible) { actionPerformed(buttonNextPage); } if (dWheelRecentMovement > 0 && buttonPreviousPage.visible) { actionPerformed(buttonPreviousPage); } } private boolean isOnFrontPage() { return currPage == 0 && viewing.isEmpty(); } private void drawBookCover(int width, int height) { mc.getTextureManager().bindTexture(BOOK_FRONT_TEXTURES); drawTexturedModalRect(width + 67, height, 0, 0, BOOK_IMAGE_WIDTH, BOOK_IMAGE_HEIGHT); String bookTitle = book.getDisplayName(); int titleWidth = fontRendererObj.getStringWidth(bookTitle); fontRendererObj.drawStringWithShadow(bookTitle, width + 67 + BOOK_IMAGE_WIDTH / 2 - titleWidth / 2 - 3, height + 80, 0xC19E51); String bookSubtitle = I18n.format(Constants.EI_MODID + ".book.info"); int subtitleWidth = fontRendererObj.getStringWidth(bookSubtitle); fontRendererObj.drawString("\u00A7o" + bookSubtitle, width + 67 + BOOK_IMAGE_WIDTH / 2 - subtitleWidth / 2 - 3, height + 90, 0xC19E51); String author = I18n.format(Constants.EI_MODID + ".book.by", mc.thePlayer.getDisplayNameString()); int authorWidth = fontRendererObj.getStringWidth(author); fontRendererObj.drawString("\u00A7o" + author, width + 67 + BOOK_IMAGE_WIDTH / 2 - authorWidth / 2 - 3, height + 105, 0xC19E51); } private void drawBookPagesBase(int width, int height) { mc.getTextureManager().bindTexture(BOOK_LEFT_GUI_TEXTURES); drawTexturedModalRect(width - 67, height, 0, 0, BOOK_IMAGE_WIDTH, BOOK_IMAGE_HEIGHT); mc.getTextureManager().bindTexture(BOOK_RIGHT_GUI_TEXTURES); drawTexturedModalRect(width + 67, height, 0, 0, BOOK_IMAGE_WIDTH, BOOK_IMAGE_HEIGHT); int pageIncr = viewing.isEmpty() ? -2 : 0; String pageOfLeft = I18n.format("book.pageIndicator", (currPage - 1) * 2 + 3 + pageIncr, bookTotalPages * 2 + pageIncr); int pageOfLeftWidth = fontRendererObj.getStringWidth(pageOfLeft); fontRendererObj.drawString(pageOfLeft, width + pageOfLeftWidth - BOOK_IMAGE_WIDTH + 54 + 67, height + 16, 0x3F3F3F); String pageOfRight = I18n.format("book.pageIndicator", (currPage - 1) * 2 + 4 + pageIncr, bookTotalPages * 2 + pageIncr); int pageOfRightWidth = fontRendererObj.getStringWidth(pageOfRight); fontRendererObj.drawString(pageOfRight, width - pageOfRightWidth + BOOK_IMAGE_WIDTH - 44 + 67, height + 16, 0x3F3F3F); } private void drawTitleOnTopOfScreen(int width, int height) { String title = book.getDisplayName(); int titleWidth = fontRendererObj.getStringWidth(title); fontRendererObj.drawStringWithShadow(title, width + BOOK_IMAGE_WIDTH / 2 - titleWidth / 2 - 3, height - 15, 0xFFFFFF); } private void drawIndexString(int width, int height) { String indexString = I18n.format("esteemedinnovation.book.index"); int indexWidth = fontRendererObj.getStringWidth(indexString); fontRendererObj.drawString("\u00A7l" + "\u00A7n" + indexString, width - 67 + BOOK_IMAGE_WIDTH / 2 - indexWidth / 2 - 5, height + 30, 0x3F3F3F); fontRendererObj.drawString("\u00A7l" + "\u00A7n" + indexString, width + 67 + BOOK_IMAGE_WIDTH / 2 - indexWidth / 2 - 5, height + 30, 0x3F3F3F); } private void populateButtonListWithCategories(boolean isRightPage, int width, int height) { String sectionName = sections.get(((currPage - 1) * 2) + (isRightPage ? 1 : 0)); int offset = 0; if (Character.isDigit(sectionName.charAt(sectionName.length() - 1))) { offset = 9 * Integer.parseInt(String.valueOf(sectionName.charAt(sectionName.length() - 1))); sectionName = sectionName.substring(0, sectionName.length() - 1); } String s = I18n.format(sectionName); int widthOffset = isRightPage ? 67 : -67; fontRendererObj.drawString("\u00A7n" + s, width + 40 + widthOffset, 44 + height, 0x3F3F3F); if (sectionName.equals(FAKE_SECTION_IDEAS)) { int hintNum = 1; for (String hint : BookModule.ALL_UNLOCALIZED_PIECES_WITH_HINTS) { String name = hint + ".name"; BookPiece piece = BookPageRegistry.getFirstPieceFromName(name); StringBuilder hintBuilder = new StringBuilder() .append("\u2022 "); if (piece != null && piece.isUnlocked(mc.thePlayer)) { hintBuilder.append(TextFormatting.STRIKETHROUGH); } hintBuilder.append(TextFormatting.ITALIC) .append(I18n.format(hint + ".hint")); List<String> splitHint = fontRendererObj.listFormattedStringToWidth(hintBuilder.toString(), 100); int i = 10 * hintNum; for (String splitHintStr : splitHint) { fontRendererObj.drawString(splitHintStr, width + 50 + widthOffset, height + 44 + i, 0x3F3F3F); i += 10; } hintNum++; } } else { BookSection section = BookPageRegistry.getSectionFromName(sectionName); if (section != null && section.isUnlocked(mc.thePlayer)) { int offsetCounter = 0; int i = 10; for (BookCategory cat : section.getCategories()) { if (!cat.isUnlocked(mc.thePlayer)) { continue; } offsetCounter++; if (offsetCounter > offset && offsetCounter < offset + 10) { s = cat.getName(); buttonList.add(new GuiButtonSelect(4, width + 50 + widthOffset, height + 44 + i, 110, 10, s)); i += 10; } } } } } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { handleDWheelMovement(); if (mustReleaseMouse && !Mouse.isButtonDown(0)) { mustReleaseMouse = false; } GlStateManager.color(1, 1, 1, 1); int width = getWidth(); int height = getHeight(); boolean prevUnicode = fontRendererObj.getUnicodeFlag(); fontRendererObj.setUnicodeFlag(true); if (isOnFrontPage()) { drawBookCover(width, height); } else { drawBookPagesBase(width, height); } if (viewing.isEmpty()) { if (currPage > 0) { drawIndexString(width, height); // Remove and replace category buttons. buttonList.removeIf(button -> button instanceof GuiButtonSelect); populateButtonListWithCategories(false, width, height); if (sections.size() > 1 + ((currPage - 1) * 2)) { populateButtonListWithCategories(true, width, height); } } fontRendererObj.setUnicodeFlag(prevUnicode); super.drawScreen(mouseX, mouseY, partialTicks); } else { fontRendererObj.setUnicodeFlag(prevUnicode); super.drawScreen(mouseX, mouseY, partialTicks); fontRendererObj.setUnicodeFlag(true); BookCategory category = BookPageRegistry.getCategoryFromName(viewing); BookPage[] pages = null; if (category == null) { BookEntry entry = BookPageRegistry.getEntryFromName(viewing); if (entry != null) { pages = entry.getPages().toArray(new BookPage[entry.getPages().size()]); } } else { pages = category.getAllVisiblePages(mc.thePlayer); } int leftPageIndex = currPage * 2; if (pages != null && pages.length > leftPageIndex) { bookTotalPages = MathHelper.ceiling_float_int(pages.length / 2F); GlStateManager.enableBlend(); BookPage leftPage = pages[leftPageIndex]; GlStateManager.enableBlend(); GlStateManager.pushMatrix(); leftPage.renderPage(width - 67, height, fontRendererObj, this, itemRender, currPage == 0, mouseX, mouseY); GlStateManager.popMatrix(); GlStateManager.enableBlend(); int rightPageIndex = leftPageIndex + 1; if (pages.length > rightPageIndex) { BookPage rightPage = pages[rightPageIndex]; GlStateManager.pushMatrix(); rightPage.renderPage(width + 67, height, fontRendererObj, this, itemRender, false, mouseX, mouseY); GlStateManager.popMatrix(); rightPage.renderPageAfter(width + 67, height, fontRendererObj, this, itemRender, false, mouseX, mouseY); } leftPage.renderPageAfter(width - 67, height, fontRendererObj, this, itemRender, currPage == 0, mouseX, mouseY); updateButtons(); } fontRendererObj.setUnicodeFlag(prevUnicode); } drawTitleOnTopOfScreen(width, height); } @Override public void renderToolTip(ItemStack stack0, int mouseX, int mouseY, boolean renderHyperlink) { List<String> list = stack0.getTooltip(mc.thePlayer, mc.gameSettings.advancedItemTooltips); zLevel = 1.0F; for (int k = 0; k < list.size(); ++k) { if (k == 0) { list.set(k, stack0.getRarity().rarityColor + list.get(k)); } else { list.set(k, TextFormatting.GRAY + list.get(k)); } } if (renderHyperlink) { for (ItemStack stack : BookPageRegistry.bookRecipes.keySet()) { if (stack.getItem() == stack0.getItem() && stack.getItemDamage() == stack0.getItemDamage()) { list.add(TextFormatting.ITALIC + "" + TextFormatting.GRAY + I18n.format("esteemedinnovation.book.clickme")); } } } FontRenderer font = stack0.getItem().getFontRenderer(stack0); drawHoveringText(list, mouseX, mouseY); drawHoveringText(list, mouseX, mouseY, (font == null ? fontRendererObj : font)); zLevel = 0.0F; } @Override public void renderText(String str, int mouseX, int mouseY) { List<String> list = new ArrayList<>(); list.add(I18n.format(str)); drawHoveringText(list, mouseX, mouseY); drawHoveringText(list, mouseX, mouseY, fontRendererObj); } @Override public void itemClicked(ItemStack itemStack) { for (ItemStack stack : BookPageRegistry.bookRecipes.keySet()) { if (!mustReleaseMouse && stack.getItem() == itemStack.getItem() && stack.getItemDamage() == itemStack.getItemDamage()) { BookEntry entry = BookPageRegistry.getEntryFromName(viewing); if (entry != null && entry.isUnlocked(mc.thePlayer)) { viewing = BookPageRegistry.bookRecipes.get(stack).getLeft(); currPage = MathHelper.floor_float(BookPageRegistry.bookRecipes.get(stack).getRight() / 2.0F); bookTotalPages = MathHelper.ceiling_float_int(entry.getPages().size() / 2F); mustReleaseMouse = true; updateButtons(); } } } } private static class NextPageButton extends GuiButton { /** * True if it is the next page button, false if it is the previous page button. */ private final boolean isNext; NextPageButton(int buttonID, int x, int y, boolean isNext) { super(buttonID, x, y, 23, 13, ""); this.isNext = isNext; } @Override public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { if (visible) { boolean isMouseInBookBounds = MathUtility.isBetweenMinInclusive(xPosition, mouseX, xPosition + width) && MathUtility.isBetweenMinInclusive(yPosition, mouseY, yPosition + height); GlStateManager.color(1, 1, 1, 1); minecraft.getTextureManager().bindTexture(BOOK_RIGHT_GUI_TEXTURES); int k = 0; int l = 192; if (isMouseInBookBounds) { k += 23; } if (!isNext) { l += 13; } drawTexturedModalRect(xPosition, yPosition, k, l, 23, 13); } } } private class GuiButtonSelect extends GuiButton { public String name; GuiButtonSelect(int buttonID, int x, int y, int width, int height, String buttonText) { super(buttonID, x, y, width, height, I18n.format(buttonText.contains("#") ? buttonText.substring(1) : buttonText)); name = buttonText; } void drawCenteredStringWithoutShadow(FontRenderer fontRenderer, String str, int x, int y, int color) { fontRenderer.drawString(str, x, y, color); } @Override public void drawButton(Minecraft mc, int mouseX, int mouseY) { if (visible) { FontRenderer fontRenderer = mc.fontRendererObj; GlStateManager.color(1, 1, 1, 1); boolean isMouseOverBook = MathUtility.isBetweenMinInclusive(xPosition, mouseX, xPosition + width) && MathUtility.isBetweenMinInclusive(yPosition, mouseY, yPosition + height); mouseDragged(mc, mouseX, mouseY); boolean unicodeBeforeSet = fontRendererObj.getUnicodeFlag(); fontRendererObj.setUnicodeFlag(true); drawCenteredStringWithoutShadow(fontRenderer, "\u2022 " + displayString, xPosition + (isMouseOverBook ? 1 : 0), yPosition + (height - 8) / 2, 0x3F3F3F); fontRendererObj.setUnicodeFlag(unicodeBeforeSet); } } } /** * Opens the entry for the ItemStack * @param recipeStack The ItemStack to get the recipe entry for. * @param player The player opening the GUI. */ public static void openRecipeFor(ItemStack recipeStack, EntityPlayer player) { player.openGui(EsteemedInnovation.instance, 1, player.worldObj, 0, 0, 0); GuiScreen gui = Minecraft.getMinecraft().currentScreen; if (!(gui instanceof GuiJournal)) { return; } GuiJournal journal = (GuiJournal) gui; Pair<String, Integer> page = BookPageRegistry.bookRecipes.get(recipeStack); String pageName = page.getLeft(); BookEntry entry = BookPageRegistry.getEntryFromName(pageName); if (entry != null) { journal.viewing = pageName; int pageNumber = page.getRight(); journal.currPage = 0; journal.lastIndexPage = 1; journal.bookTotalPages = pageNumber; journal.updateButtons(); } } }