From 19cfcfa1c1e552898ce107c507ff7ea4a9591ff2 Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Sat, 12 Nov 2016 13:54:49 +0100 Subject: [PATCH] Added bookmarks and store page and bookmarks on close --- .../api/booklet/IBookletPage.java | 2 + .../mod/booklet/button/BookmarkButton.java | 112 ++++++++++++++++++ .../mod/booklet/gui/GuiBooklet.java | 54 ++++++++- .../mod/booklet/gui/GuiPage.java | 10 +- .../mod/booklet/misc/BookletUtils.java | 14 ++- .../mod/booklet/page/BookletPage.java | 5 + .../mod/data/PlayerData.java | 27 +++++ .../mod/inventory/GuiHandler.java | 9 +- .../gui/booklet/guiBookletGadgets.png | Bin 5822 -> 6561 bytes 9 files changed, 228 insertions(+), 5 deletions(-) create mode 100644 src/main/java/de/ellpeck/actuallyadditions/mod/booklet/button/BookmarkButton.java diff --git a/src/main/java/de/ellpeck/actuallyadditions/api/booklet/IBookletPage.java b/src/main/java/de/ellpeck/actuallyadditions/api/booklet/IBookletPage.java index 1b6925645..1b2f49f05 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/api/booklet/IBookletPage.java +++ b/src/main/java/de/ellpeck/actuallyadditions/api/booklet/IBookletPage.java @@ -56,4 +56,6 @@ public interface IBookletPage{ void drawScreenPost(GuiBookletBase gui, int startX, int startY, int mouseX, int mouseY, float partialTicks); boolean shouldBeOnLeftSide(); + + String getIdentifier(); } diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/button/BookmarkButton.java b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/button/BookmarkButton.java new file mode 100644 index 000000000..164f13f8d --- /dev/null +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/button/BookmarkButton.java @@ -0,0 +1,112 @@ +/* + * This file ("BookmarkButton.java") is part of the Actually Additions mod for Minecraft. + * It is created and owned by Ellpeck and distributed + * under the Actually Additions License to be found at + * http://ellpeck.de/actaddlicense + * View the source code at https://github.com/Ellpeck/ActuallyAdditions + * + * © 2015-2016 Ellpeck + */ + +package de.ellpeck.actuallyadditions.mod.booklet.button; + +import de.ellpeck.actuallyadditions.api.booklet.IBookletChapter; +import de.ellpeck.actuallyadditions.api.booklet.IBookletPage; +import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiBooklet; +import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiPage; +import de.ellpeck.actuallyadditions.mod.booklet.misc.BookletUtils; +import de.ellpeck.actuallyadditions.mod.util.AssetUtil; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.client.config.GuiUtils; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.ArrayList; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class BookmarkButton extends GuiButton{ + + private final GuiBooklet booklet; + public IBookletPage assignedPage; + + public BookmarkButton(int id, int x, int y, GuiBooklet booklet){ + super(id, x, y, 16, 16, ""); + this.booklet = booklet; + } + + public void onPressed(){ + if(this.assignedPage != null){ + if(GuiScreen.isShiftKeyDown()){ + this.assignedPage = null; + } + else{ + GuiPage gui = BookletUtils.createPageGui(this.booklet.previousScreen, this.booklet, this.assignedPage); + Minecraft.getMinecraft().displayGuiScreen(gui); + } + } + else{ + if(this.booklet instanceof GuiPage){ + this.assignedPage = ((GuiPage)this.booklet).pages[0]; + } + } + } + + @Override + public void drawButton(Minecraft minecraft, int x, int y){ + if(this.visible){ + minecraft.getTextureManager().bindTexture(GuiBooklet.RES_LOC_GADGETS); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + this.hovered = x >= this.xPosition && y >= this.yPosition && x < this.xPosition+this.width && y < this.yPosition+this.height; + int k = this.getHoverState(this.hovered); + if(k == 0){ + k = 1; + } + + GlStateManager.enableBlend(); + GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); + GlStateManager.blendFunc(770, 771); + int renderHeight = 25; + this.drawTexturedModalRect(this.xPosition, this.yPosition, 224+(this.assignedPage == null ? 0 : 16), 14-renderHeight+k*renderHeight, this.width, renderHeight); + this.mouseDragged(minecraft, x, y); + + if(this.assignedPage != null){ + ItemStack display = this.assignedPage.getChapter().getDisplayItemStack(); + if(display != null){ + GlStateManager.pushMatrix(); + AssetUtil.renderStackToGui(display, this.xPosition+2, this.yPosition+1, 0.725F); + GlStateManager.popMatrix(); + } + } + } + } + + public void drawHover(int mouseX, int mouseY){ + if(this.isMouseOver()){ + List list = new ArrayList(); + + if(this.assignedPage != null){ + IBookletChapter chapter = this.assignedPage.getChapter(); + + list.add(TextFormatting.GOLD+chapter.getLocalizedName()+", Page "+(chapter.getPageIndex(this.assignedPage)+1)); + list.add("Click to open"); + list.add(TextFormatting.ITALIC+"Shift-Click to remove"); + } + else{ + list.add(TextFormatting.GOLD+"None"); + + if(this.booklet instanceof GuiPage){ + list.add("Click to save current page"); + } + } + + Minecraft mc = Minecraft.getMinecraft(); + GuiUtils.drawHoveringText(list, mouseX, mouseY, mc.displayWidth, mc.displayHeight, -1, mc.fontRendererObj); + } + } +} diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiBooklet.java b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiBooklet.java index e502be321..4a928bd48 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiBooklet.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiBooklet.java @@ -12,6 +12,9 @@ package de.ellpeck.actuallyadditions.mod.booklet.gui; import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI; import de.ellpeck.actuallyadditions.api.booklet.internal.GuiBookletBase; +import de.ellpeck.actuallyadditions.mod.booklet.button.BookmarkButton; +import de.ellpeck.actuallyadditions.mod.data.PlayerData; +import de.ellpeck.actuallyadditions.mod.data.PlayerData.PlayerSave; import de.ellpeck.actuallyadditions.mod.inventory.gui.TexturedButton; import de.ellpeck.actuallyadditions.mod.util.AssetUtil; import de.ellpeck.actuallyadditions.mod.util.StringUtil; @@ -23,6 +26,7 @@ import net.minecraft.util.ResourceLocation; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.apache.commons.lang3.ArrayUtils; import org.lwjgl.input.Keyboard; import java.io.IOException; @@ -41,6 +45,7 @@ public abstract class GuiBooklet extends GuiBookletBase{ private GuiButton buttonLeft; private GuiButton buttonRight; private GuiButton buttonBack; + private final BookmarkButton[] bookmarkButtons = new BookmarkButton[12]; public GuiTextField searchField; @@ -84,10 +89,41 @@ public abstract class GuiBooklet extends GuiBookletBase{ this.searchField.setMaxStringLength(50); this.searchField.setEnableBackgroundDrawing(false); } + + if(this.hasBookmarkButtons()){ + PlayerSave data = PlayerData.getDataFromPlayer(this.mc.thePlayer); + for(int i = 0; i < this.bookmarkButtons.length; i++){ + this.bookmarkButtons[i] = new BookmarkButton(1337+i, this.guiLeft+12+i*16, this.guiTop+this.ySize, this); + this.buttonList.add(this.bookmarkButtons[i]); + + if(data.bookmarks[i] != null){ + this.bookmarkButtons[i].assignedPage = data.bookmarks[i]; + } + } + } + } + + @Override + public void onGuiClosed(){ + super.onGuiClosed(); + + PlayerSave data = PlayerData.getDataFromPlayer(this.mc.thePlayer); + + for(int i = 0; i < this.bookmarkButtons.length; i++){ + data.bookmarks[i] = this.bookmarkButtons[i].assignedPage; + } + + data.lastOpenBooklet = this; } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks){ + this.drawScreenPre(mouseX, mouseY, partialTicks); + super.drawScreen(mouseX, mouseY, partialTicks); + this.drawScreenPost(mouseX, mouseY, partialTicks); + } + + public void drawScreenPre(int mouseX, int mouseY, float partialTicks){ GlStateManager.color(1F, 1F, 1F); this.mc.getTextureManager().bindTexture(RES_LOC_GUI); drawModalRectWithCustomSizedTexture(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize, 512, 512); @@ -107,8 +143,14 @@ public abstract class GuiBooklet extends GuiBookletBase{ this.fontRendererObj.setUnicodeFlag(unicodeBefore); } + } - super.drawScreen(mouseX, mouseY, partialTicks); + public void drawScreenPost(int mouseX, int mouseY, float partialTicks){ + if(this.hasBookmarkButtons()){ + for(BookmarkButton button : this.bookmarkButtons){ + button.drawHover(mouseX, mouseY); + } + } } @Override @@ -162,6 +204,10 @@ public abstract class GuiBooklet extends GuiBookletBase{ return true; } + public boolean hasBookmarkButtons(){ + return true; + } + public void onSearchBarChanged(String searchBarText){ GuiBookletBase parent = !(this instanceof GuiEntry) ? this : this.parentPage; this.mc.displayGuiScreen(new GuiEntry(this.previousScreen, parent, ActuallyAdditionsAPI.allAndSearch, 0, searchBarText, true)); @@ -178,6 +224,12 @@ public abstract class GuiBooklet extends GuiBookletBase{ else if(this.hasBackButton() && button == this.buttonBack){ this.onBackButtonPressed(); } + else if(this.hasBookmarkButtons() && button instanceof BookmarkButton){ + int index = ArrayUtils.indexOf(this.bookmarkButtons, button); + if(index >= 0){ + this.bookmarkButtons[index].onPressed(); + } + } else{ super.actionPerformed(button); } diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiPage.java b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiPage.java index dc55c6c3a..6ed441d9a 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiPage.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/gui/GuiPage.java @@ -19,6 +19,7 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -116,8 +117,8 @@ public class GuiPage extends GuiBooklet{ } @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks){ - super.drawScreen(mouseX, mouseY, partialTicks); + public void drawScreenPre(int mouseX, int mouseY, float partialTicks){ + super.drawScreenPre(mouseX, mouseY, partialTicks); for(int i = 0; i < this.pages.length; i++){ IBookletPage page = this.pages[i]; @@ -129,6 +130,11 @@ public class GuiPage extends GuiBooklet{ for(ItemDisplay display : this.itemDisplays){ display.drawPre(); } + } + + @Override + public void drawScreenPost(int mouseX, int mouseY, float partialTicks){ + super.drawScreenPost(mouseX, mouseY, partialTicks); for(int i = 0; i < this.pages.length; i++){ IBookletPage page = this.pages[i]; diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/misc/BookletUtils.java b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/misc/BookletUtils.java index bc299d41d..093fe7ed1 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/misc/BookletUtils.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/misc/BookletUtils.java @@ -14,7 +14,6 @@ import de.ellpeck.actuallyadditions.api.ActuallyAdditionsAPI; import de.ellpeck.actuallyadditions.api.booklet.IBookletChapter; import de.ellpeck.actuallyadditions.api.booklet.IBookletPage; import de.ellpeck.actuallyadditions.api.booklet.internal.GuiBookletBase; -import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiBooklet; import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiEntry; import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiMainPage; import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiPage; @@ -70,4 +69,17 @@ public final class BookletUtils{ return new GuiPage(previousScreen, parentPage, page1, page2); } + + public static IBookletPage getBookletPageById(String id){ + if(id != null){ + for(IBookletChapter chapter : ActuallyAdditionsAPI.ALL_CHAPTERS){ + for(IBookletPage page : chapter.getAllPages()){ + if(id.equals(page.getIdentifier())){ + return page; + } + } + } + } + return null; + } } diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/page/BookletPage.java b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/page/BookletPage.java index 1e4e31cf7..d691fc7d3 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/page/BookletPage.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/booklet/page/BookletPage.java @@ -136,6 +136,11 @@ public class BookletPage implements IBookletPage{ return (this.chapter.getPageIndex(this)+1)%2 != 0; } + @Override + public String getIdentifier(){ + return this.chapter.getIdentifier()+"."+this.chapter.getPageIndex(this); + } + public BookletPage setNoText(){ this.hasNoText = true; return this; diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/data/PlayerData.java b/src/main/java/de/ellpeck/actuallyadditions/mod/data/PlayerData.java index 404f71c20..bbedc08e8 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/data/PlayerData.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/data/PlayerData.java @@ -10,8 +10,15 @@ package de.ellpeck.actuallyadditions.mod.data; +import de.ellpeck.actuallyadditions.api.booklet.IBookletPage; +import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiBooklet; +import de.ellpeck.actuallyadditions.mod.booklet.misc.BookletUtils; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagString; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; import java.util.UUID; @@ -44,6 +51,11 @@ public final class PlayerData{ public boolean displayTesla; public boolean bookGottenAlready; + public IBookletPage[] bookmarks = new IBookletPage[12]; + + @SideOnly(Side.CLIENT) + public GuiBooklet lastOpenBooklet; + public PlayerSave(UUID id){ this.id = id; } @@ -51,11 +63,26 @@ public final class PlayerData{ public void readFromNBT(NBTTagCompound compound){ this.displayTesla = compound.getBoolean("DisplayTesla"); this.bookGottenAlready = compound.getBoolean("BookGotten"); + + NBTTagList bookmarks = compound.getTagList("Bookmarks", 8); + for(int i = 0; i < bookmarks.tagCount(); i++){ + String strg = bookmarks.getStringTagAt(i); + if(strg != null && !strg.isEmpty()){ + IBookletPage page = BookletUtils.getBookletPageById(strg); + this.bookmarks[i] = page; + } + } } public void writeToNBT(NBTTagCompound compound){ compound.setBoolean("DisplayTesla", this.displayTesla); compound.setBoolean("BookGotten", this.bookGottenAlready); + + NBTTagList bookmarks = new NBTTagList(); + for(IBookletPage bookmark : this.bookmarks){ + bookmarks.appendTag(new NBTTagString(bookmark == null ? "" : bookmark.getIdentifier())); + } + compound.setTag("Bookmarks", bookmarks); } } diff --git a/src/main/java/de/ellpeck/actuallyadditions/mod/inventory/GuiHandler.java b/src/main/java/de/ellpeck/actuallyadditions/mod/inventory/GuiHandler.java index 29a7b81c0..82e915bc6 100644 --- a/src/main/java/de/ellpeck/actuallyadditions/mod/inventory/GuiHandler.java +++ b/src/main/java/de/ellpeck/actuallyadditions/mod/inventory/GuiHandler.java @@ -14,6 +14,7 @@ import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiBooklet; import de.ellpeck.actuallyadditions.mod.booklet.gui.GuiMainPage; import de.ellpeck.actuallyadditions.mod.booklet.misc.BookletUtils; +import de.ellpeck.actuallyadditions.mod.data.PlayerData; import de.ellpeck.actuallyadditions.mod.inventory.gui.*; import de.ellpeck.actuallyadditions.mod.items.ItemBooklet; import de.ellpeck.actuallyadditions.mod.tile.TileEntityBase; @@ -177,7 +178,13 @@ public class GuiHandler implements IGuiHandler{ return gui; } else{ - return new GuiMainPage(null); + PlayerData.PlayerSave data = PlayerData.getDataFromPlayer(player); + if(data.lastOpenBooklet != null){ + return data.lastOpenBooklet; + } + else{ + return new GuiMainPage(null); + } } case DIRECTIONAL_BREAKER: return new GuiDirectionalBreaker(player.inventory, tile); diff --git a/src/main/resources/assets/actuallyadditions/textures/gui/booklet/guiBookletGadgets.png b/src/main/resources/assets/actuallyadditions/textures/gui/booklet/guiBookletGadgets.png index a5842423facaaca1f7a2e1ba88e0199b13ad8c48..6e1af9b4f9964ab5b973eb278cea58ec2dd37151 100644 GIT binary patch literal 6561 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