diff --git a/src/main/java/electroblob/wizardry/client/DrawingUtils.java b/src/main/java/electroblob/wizardry/client/DrawingUtils.java index d4cb332f..865718c4 100644 --- a/src/main/java/electroblob/wizardry/client/DrawingUtils.java +++ b/src/main/java/electroblob/wizardry/client/DrawingUtils.java @@ -286,4 +286,19 @@ public final class DrawingUtils { return s; } + /** + * Tests if the point with the given coordinates lies within the rectangle specified. The check is identical to + * {@link GuiContainer#isPointInRegion(int, int, int, int, int, int)}, but without the adjustment relative to the GUI. + * @param left The minimum x coordinate of the rectangle + * @param top The minimum y coordinate of the rectangle + * @param width The width of the rectangle + * @param height The height of the rectangle + * @param x The x coordinate of the point to test + * @param y The y coordinate of the point to test + * @return True if the given point is in the rectangle, false otherwise + */ + public static boolean isPointInRegion(int left, int top, int width, int height, int x, int y){ + return x >= left - 1 && x < left + width + 1 && y >= top - 1 && y < top + height + 1; + } + } diff --git a/src/main/java/electroblob/wizardry/client/gui/CustomCreativeSearchHandler.java b/src/main/java/electroblob/wizardry/client/gui/CustomCreativeSearchHandler.java index 3e96a9eb..59e5915d 100644 --- a/src/main/java/electroblob/wizardry/client/gui/CustomCreativeSearchHandler.java +++ b/src/main/java/electroblob/wizardry/client/gui/CustomCreativeSearchHandler.java @@ -1,14 +1,21 @@ package electroblob.wizardry.client.gui; +import electroblob.wizardry.Wizardry; +import electroblob.wizardry.client.DrawingUtils; import electroblob.wizardry.registry.WizardryTabs; import electroblob.wizardry.spell.Spell; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.gui.inventory.GuiContainerCreative; +import net.minecraft.client.resources.I18n; import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.Phase; import net.minecraftforge.fml.relauncher.Side; import java.lang.reflect.Field; @@ -17,11 +24,18 @@ import java.util.Locale; @EventBusSubscriber(Side.CLIENT) public class CustomCreativeSearchHandler { + private static final int SEARCH_TOOLTIP_HOVER_TIME = 20; + + private static final Style TOOLTIP_SYNTAX = new Style().setColor(TextFormatting.YELLOW); + private static final Style TOOLTIP_BODY = new Style().setColor(TextFormatting.WHITE); + /** Reflected into {@code GuiContainerCreative#searchField} */ private static final Field searchField; private static GuiTextField currentSearchField = null; + private static int searchBarHoverTime; + static { searchField = ObfuscationReflectionHelper.findField(GuiContainerCreative.class, "field_147062_A"); } @@ -62,4 +76,25 @@ public class CustomCreativeSearchHandler { } } + @SubscribeEvent + public static void onClientTickEvent(ClientTickEvent event){ + if(event.phase == Phase.END && searchBarHoverTime > 0 && searchBarHoverTime < SEARCH_TOOLTIP_HOVER_TIME){ + searchBarHoverTime++; + } + } + + @SubscribeEvent + public static void onDrawScreenPostEvent(GuiScreenEvent.DrawScreenEvent.Post event){ + if(currentSearchField != null && DrawingUtils.isPointInRegion(currentSearchField.x, currentSearchField.y, currentSearchField.width, currentSearchField.height, event.getMouseX(), event.getMouseY())){ + if(searchBarHoverTime == 0){ + searchBarHoverTime++; + }else if(searchBarHoverTime == SEARCH_TOOLTIP_HOVER_TIME){ + event.getGui().drawHoveringText(I18n.format("container." + Wizardry.MODID + ":arcane_workbench.search_tooltip", + TOOLTIP_SYNTAX.getFormattingCode(), TOOLTIP_BODY.getFormattingCode()), event.getMouseX(), event.getMouseY()); + } + }else{ + searchBarHoverTime = 0; + } + } + } diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java index 8b0ea1e8..8c8e5280 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiArcaneWorkbench.java @@ -83,6 +83,11 @@ public class GuiArcaneWorkbench extends GuiContainer { private static final int ANIMATION_DURATION = 20; + private static final int SEARCH_TOOLTIP_HOVER_TIME = 20; + + private static final Style TOOLTIP_SYNTAX = new Style().setColor(TextFormatting.YELLOW); + private static final Style TOOLTIP_BODY = new Style().setColor(TextFormatting.WHITE); + private InventoryPlayer playerInventory; private IInventory arcaneWorkbenchInventory; private ContainerArcaneWorkbench arcaneWorkbenchContainer; @@ -92,6 +97,7 @@ public class GuiArcaneWorkbench extends GuiContainer { private GuiTextField searchField; private boolean searchNeedsClearing; + private int searchBarHoverTime; private final List tooltipElements = new ArrayList<>(); @@ -155,6 +161,7 @@ public class GuiArcaneWorkbench extends GuiContainer { arcaneWorkbenchContainer.refreshBookshelfSlots(); arcaneWorkbenchContainer.needsRefresh = false; } + if(searchBarHoverTime > 0 && searchBarHoverTime < SEARCH_TOOLTIP_HOVER_TIME) searchBarHoverTime++; } @Override @@ -405,6 +412,18 @@ public class GuiArcaneWorkbench extends GuiContainer { } this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX - guiLeft, mouseY - guiTop)); + + // Search tooltip + if(isPointInRegion(searchField.x, searchField.y, searchField.width, searchField.height, mouseX + guiLeft, mouseY + guiTop)){ + if(searchBarHoverTime == 0){ + searchBarHoverTime++; + }else if(searchBarHoverTime == SEARCH_TOOLTIP_HOVER_TIME){ + drawHoveringText(I18n.format("container." + Wizardry.MODID + ":arcane_workbench.search_tooltip", + TOOLTIP_SYNTAX.getFormattingCode(), TOOLTIP_BODY.getFormattingCode()), mouseX - guiLeft, mouseY - guiTop); + } + }else{ + searchBarHoverTime = 0; + } } // Controls diff --git a/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java b/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java index 27bbf8fa..d46927c4 100644 --- a/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java +++ b/src/main/java/electroblob/wizardry/client/gui/GuiLectern.java @@ -32,6 +32,8 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.Style; +import net.minecraft.util.text.TextFormatting; import java.io.IOException; import java.util.ArrayList; @@ -59,6 +61,11 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable { private static final int SPELL_ROWS = 3, SPELL_COLUMNS = 3; public static final int SPELL_BUTTON_COUNT = SPELL_ROWS * SPELL_COLUMNS * 2; // x2 because there are 2 pages + private static final int SEARCH_TOOLTIP_HOVER_TIME = 20; + + private static final Style TOOLTIP_SYNTAX = new Style().setColor(TextFormatting.YELLOW); + private static final Style TOOLTIP_BODY = new Style().setColor(TextFormatting.WHITE); + private final TileEntityLectern lectern; private GuiButton nextPageButton; @@ -84,6 +91,7 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable { private GuiTextField searchField; private boolean searchNeedsClearing; + private int searchBarHoverTime; private int currentPage = 0; @@ -183,6 +191,12 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable { } + @Override + public void updateScreen(){ + super.updateScreen(); + if(searchBarHoverTime > 0 && searchBarHoverTime < SEARCH_TOOLTIP_HOVER_TIME) searchBarHoverTime++; + } + @Override public void onGuiClosed(){ WizardryPacketHandler.net.sendToServer(new PacketLectern.Message(lectern.getPos(), currentSpell)); @@ -209,6 +223,18 @@ public class GuiLectern extends GuiSpellInfo implements ISpellSortable { } this.buttonList.forEach(b -> b.drawButtonForegroundLayer(mouseX, mouseY)); + + // Search tooltip + if(DrawingUtils.isPointInRegion(searchField.x, searchField.y, searchField.width, searchField.height, mouseX, mouseY)){ + if(searchBarHoverTime == 0){ + searchBarHoverTime++; + }else if(searchBarHoverTime == SEARCH_TOOLTIP_HOVER_TIME){ + drawHoveringText(I18n.format("container." + Wizardry.MODID + ":arcane_workbench.search_tooltip", + TOOLTIP_SYNTAX.getFormattingCode(), TOOLTIP_BODY.getFormattingCode()), mouseX, mouseY); + } + }else{ + searchBarHoverTime = 0; + } } private void drawIndexPage(int left, int top){ diff --git a/src/main/resources/assets/ebwizardry/lang/en_gb.lang b/src/main/resources/assets/ebwizardry/lang/en_gb.lang index 45aa3391..bdcdd849 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_gb.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_gb.lang @@ -720,6 +720,7 @@ container.ebwizardry\:arcane_workbench.bookshelves=Bookshelves container.ebwizardry\:arcane_workbench.sort_tier=Sort by Tier container.ebwizardry\:arcane_workbench.sort_element=Sort by Element container.ebwizardry\:arcane_workbench.sort_alphabetical=Sort Alphabetically +container.ebwizardry\:arcane_workbench.search_tooltip=%1$sSearch Tips\n\ntier=%2$s, %1$st=%2$s: match tiers\n%1$selement=%2$s, %1$se=%2$s: match elements\n%1$stype=%2$s, %1$sp=%2$s: match spell types\n%1$sdiscovered=true/false%2$s, %1$sd=t/f%2$s: include only (un)discovered\n%1$smodid=%2$s, %1$sm=%2$s: match mod IDs\n\nSeparate multiple values with %1$s,%2$s\nSeparate multiple criteria with %1$s; container.ebwizardry\:bookshelf=Bookshelf diff --git a/src/main/resources/assets/ebwizardry/lang/en_us.lang b/src/main/resources/assets/ebwizardry/lang/en_us.lang index cac956ee..316dcd28 100644 --- a/src/main/resources/assets/ebwizardry/lang/en_us.lang +++ b/src/main/resources/assets/ebwizardry/lang/en_us.lang @@ -720,6 +720,7 @@ container.ebwizardry\:arcane_workbench.bookshelves=Bookshelves container.ebwizardry\:arcane_workbench.sort_tier=Sort by Tier container.ebwizardry\:arcane_workbench.sort_element=Sort by Element container.ebwizardry\:arcane_workbench.sort_alphabetical=Sort Alphabetically +container.ebwizardry\:arcane_workbench.search_tooltip=%1$sSearch Tips\n\ntier=%2$s, %1$st=%2$s: match tiers\n%1$selement=%2$s, %1$se=%2$s: match elements\n%1$stype=%2$s, %1$sp=%2$s: match spell types\n%1$sdiscovered=true/false%2$s, %1$sd=t/f%2$s: include only (un)discovered\n%1$smodid=%2$s, %1$sm=%2$s: match mod IDs\n\nSeparate multiple values with %1$s,%2$s\nSeparate multiple criteria with %1$s; container.ebwizardry\:bookshelf=Bookshelf