aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/NotSkyblockAddonsInstallerFrame.java27
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java72
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java187
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java2842
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java655
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java724
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java99
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java279
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java218
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java80
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java111
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java52
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java100
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java134
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java134
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/EnableStorageCommand.java39
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java303
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ReloadRepoCommand.java39
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ResetRepoCommand.java42
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java30
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java75
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java94
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java78
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java81
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java39
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java18
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java69
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/MoulConfigGuiForgeInterop.java69
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java44
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java54
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java27
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java115
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java68
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/Vec3Comparable.java148
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java91
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java91
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java42
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java78
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java43
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java1719
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java85
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java26
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java46
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/GuiInventoryBackgroundDrawnEvent.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/NEUEvent.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/OnBlockBreakSoundEffect.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/SignSubmitEvent.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/events/SlotClickEvent.java51
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java323
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java374
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java534
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java163
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/ScrollableInfoPane.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElement.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementButton.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementText.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java217
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java258
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java84
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java887
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java387
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java277
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java68
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java1718
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java49
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java215
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java62
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java158
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java178
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java107
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java44
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java115
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java573
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java1108
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java147
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomSkulls.java38
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java48
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java210
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java492
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java293
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java157
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java27
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemRarityHalo.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java418
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java43
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java489
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java173
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java118
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java126
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StreamerMode.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CrystalHollowsTextures.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBlockSounds.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/IslandZoneSubdivider.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/LocationChangeEvent.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/SpecialBlockZone.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java49
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java245
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java27
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java91
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java70
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java85
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/NameModifier.java34
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java65
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java48
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java256
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java47
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java100
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java141
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java76
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java74
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiCustomEnchant.java349
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiEnchantColour.java74
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java120
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemCustomize.java29
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java252
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java173
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiPriceGraph.java243
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java43
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/NEUOverlayPlacements.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/NeuSearchCalculator.java55
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java117
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java448
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/TradeWindow.java107
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java274
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/EnchantState.java37
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/GuiCustomHex.java4885
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/HexItem.java264
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/ItemType.java84
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/ExperienceOrb.java32
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/OrbDisplay.java142
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityAgeable.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityArmorStand.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiContainer.java52
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiEditSign.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiPlayerTabOverlay.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorMinecraft.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinAbstractClientPlayer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityHorse.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java64
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntitySkeleton.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java99
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiEditSign.java50
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java30
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiScreen.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemCameraTransforms.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemRenderer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerArmorBase.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCustomHead.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java18
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMinecraft.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java23
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java60
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java28
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRendererLivingEntity.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTextureManager.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySkullRenderer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorld.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java145
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java127
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java73
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHGraph.java28
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHTweaks.java64
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AccessoryBag.java49
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiData.java106
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiKey.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java73
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Calendar.java125
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/CustomArmour.java32
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/DungeonMapConfig.java303
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java504
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Enchanting.java56
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Fishing.java508
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ImprovedSBMenu.java119
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/InventoryButtons.java89
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java748
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Itemlist.java262
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/LocationEdit.java35
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java1492
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java384
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MiscOverlays.java64
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java118
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java121
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/PetOverlay.java259
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java97
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java663
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlayerOverlay.java26
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlotLocking.java205
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java547
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Toolbar.java227
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java367
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TradeMenu.java71
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java128
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java572
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/BonemerangOverlay.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/CombatSkillOverlay.java107
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java81
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java461
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/FarmingOverlay.java34
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/FishingSkillOverlay.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java214
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningSkillOverlay.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/RancherBootOverlay.java22
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/SlayerOverlay.java35
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlay.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlayStyle.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/TextTabOverlay.java79
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java148
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java841
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java346
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java495
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java841
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java542
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java5114
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java816
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java1534
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java85
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java389
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java485
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java1572
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java1093
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java302
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java62
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java71
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java480
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java148
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java89
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java92
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java50
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java66
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java66
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java67
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java51
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java42
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java42
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java70
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/WeightStruct.java54
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java32
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java33
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/Ingredient.java26
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java208
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java352
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java60
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java188
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeSlot.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java79
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java56
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/AllowEmptyHTMLTag.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java203
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java55
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java59
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java302
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java46
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Debouncer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/GuiTextures.java48
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java188
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java282
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java402
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/IteratorUtils.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java84
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/LerpingFloat.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java37
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java80
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java55
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/NEUResourceManager.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java51
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java138
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java178
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/RequestFocusListener.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java28
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java99
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SkytilsCompat.java115
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java19
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java395
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java59
406 files changed, 45510 insertions, 17904 deletions
diff --git a/src/main/java/NotSkyblockAddonsInstallerFrame.java b/src/main/java/NotSkyblockAddonsInstallerFrame.java
index e6543617..969e6c28 100644
--- a/src/main/java/NotSkyblockAddonsInstallerFrame.java
+++ b/src/main/java/NotSkyblockAddonsInstallerFrame.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
@@ -6,7 +25,13 @@ import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java b/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java
new file mode 100644
index 00000000..d997d980
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/BuildFlags.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * For storage of compile-time configuration flags
+ */
+public class BuildFlags {
+
+ private static final Properties properties = new Properties();
+
+ static {
+ try {
+ properties.load(BuildFlags.class.getResourceAsStream("/buildflags.properties"));
+ } catch (IOException | NullPointerException e) {
+ System.out.println("Failed to load build properties: " + e);
+ }
+ }
+
+ private static boolean getBuildFlag(String flag) {
+ return Boolean.parseBoolean(properties.getProperty("neu.buildflags." + flag));
+ }
+
+ public static Map<String, Boolean> getAllFlags() {
+ return Holder.ALL_FLAGS;
+ }
+
+ public static final boolean ENABLE_PRONOUNS_IN_PV_BY_DEFAULT = getBuildFlag("pronouns");
+
+ private static class Holder {
+ static Map<String, Boolean> ALL_FLAGS = new HashMap<>();
+
+ static {
+ for (Field declaredField : BuildFlags.class.getDeclaredFields()) {
+ if (Boolean.TYPE.equals(declaredField.getType())
+ && (declaredField.getModifiers() & Modifier.STATIC) != 0) {
+ try {
+ declaredField.setAccessible(true);
+ ALL_FLAGS.put(declaredField.getName(), (Boolean) declaredField.get(null));
+ } catch (IllegalAccessException | ClassCastException | SecurityException e) {
+ System.err.println("Failed to access BuildFlag: " + e);
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
index 28686073..3911396f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates;
import com.google.gson.JsonArray;
@@ -91,11 +110,11 @@ public class CustomItems {
* SHAAAAAAAAAAAAAAAAAAME
*/
- private static JsonObject create(String internalname, String itemid, String displayname, String... lore) {
+ private static JsonObject create(String internalname, String itemid, String displayName, String... lore) {
JsonObject json = new JsonObject();
json.addProperty("itemid", itemid);
json.addProperty("internalname", internalname);
- json.addProperty("displayname", EnumChatFormatting.RED + displayname);
+ json.addProperty("displayname", EnumChatFormatting.RED + displayName);
JsonArray jsonlore = new JsonArray();
for (String line : lore) {
jsonlore.add(new JsonPrimitive(EnumChatFormatting.GRAY + line));
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
index 1804831b..a773abdc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemPriceInformation.java
@@ -1,18 +1,46 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates;
import com.google.gson.Gson;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.HashSet;
import java.util.List;
@@ -23,6 +51,7 @@ public class ItemPriceInformation {
private static File file;
private static HashSet<String> auctionableItems = null;
private static Gson gson;
+ private static final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US));
public static boolean addToTooltip(List<String> tooltip, String internalname, ItemStack stack) {
return addToTooltip(tooltip, internalname, stack, true);
@@ -75,27 +104,24 @@ public class ItemPriceInformation {
}
JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
- float lowestBinAvg = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname);
+ double lowestBinAvg = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname);
- int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
+ double lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname);
+ boolean bazaarItem = bazaarInfo != null;
- boolean auctionItem = lowestBin > 0 || lowestBinAvg > 0;
+ boolean auctionItem = !bazaarItem;
boolean auctionInfoErrored = auctionInfo == null;
if (auctionItem) {
long currentTime = System.currentTimeMillis();
long lastUpdate = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLastLowestBinUpdateTime();
//check if info is older than 10 minutes
- if (currentTime - lastUpdate > 600 * 1000) {
+ if (currentTime - lastUpdate > 600 * 1000 && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
tooltip.add(EnumChatFormatting.RED + "[NEU] Price info is outdated.");
tooltip.add(EnumChatFormatting.RED + "It will be updated again as soon as possible.");
}
}
- boolean bazaarItem = bazaarInfo != null;
-
- NumberFormat format = NumberFormat.getInstance(Locale.US);
- boolean shortNumber = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.shortNumberFormatPrices;
if (bazaarItem) {
List<Integer> lines = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.priceInfoBaz;
@@ -120,11 +146,8 @@ public class ItemPriceInformation {
tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]");
added = true;
}
- int bazaarBuyPrice = (int) bazaarInfo.get("avg_buy").getAsFloat() * stackMultiplier;
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Buy: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarBuyPrice > 1000
- ? Utils.shortNumberFormat(bazaarBuyPrice, 0)
- : format.format(bazaarBuyPrice)) + " coins");
+ double bazaarBuyPrice = bazaarInfo.get("avg_buy").getAsFloat() * stackMultiplier;
+ tooltip.add(formatPrice("Bazaar Buy: ", bazaarBuyPrice));
}
break;
case 1:
@@ -135,11 +158,8 @@ public class ItemPriceInformation {
tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]");
added = true;
}
- int bazaarSellPrice = (int) bazaarInfo.get("avg_sell").getAsFloat() * stackMultiplier;
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Sell: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarSellPrice > 1000
- ? Utils.shortNumberFormat(bazaarSellPrice, 0)
- : format.format(bazaarSellPrice)) + " coins");
+ double bazaarSellPrice = bazaarInfo.get("avg_sell").getAsDouble() * stackMultiplier;
+ tooltip.add(formatPrice("Bazaar Sell: ", bazaarSellPrice));
}
break;
case 2:
@@ -150,12 +170,8 @@ public class ItemPriceInformation {
tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]");
added = true;
}
- int bazaarInstantBuyPrice = (int) bazaarInfo.get("curr_buy").getAsFloat() * stackMultiplier;
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Buy: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarInstantBuyPrice > 1000
- ? Utils.shortNumberFormat(bazaarInstantBuyPrice, 0)
- : format.format(bazaarInstantBuyPrice)) +
- " coins");
+ double bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat() * stackMultiplier;
+ tooltip.add(formatPrice("Bazaar Insta-Buy: ", bazaarInstantBuyPrice));
}
break;
case 3:
@@ -166,32 +182,22 @@ public class ItemPriceInformation {
tooltip.add(EnumChatFormatting.DARK_GRAY + "[SHIFT show x" + shiftStackMultiplier + "]");
added = true;
}
- int bazaarInstantSellPrice = (int) bazaarInfo.get("curr_sell").getAsFloat() * stackMultiplier;
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Bazaar Insta-Sell: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + (shortNumber && bazaarInstantSellPrice > 1000
- ? Utils.shortNumberFormat(
- bazaarInstantSellPrice,
- 0
- )
- : format.format(bazaarInstantSellPrice)) +
- " coins");
+ double bazaarInstantSellPrice = bazaarInfo.get("curr_sell").getAsFloat() * stackMultiplier;
+ tooltip.add(formatPrice("Bazaar Insta-Sell: ", bazaarInstantSellPrice));
}
break;
case 4:
if (craftCost != null && craftCost.fromRecipe) {
- if ((int) craftCost.craftCost == 0) {
+ if (craftCost.craftCost == 0) {
continue;
}
if (!added) {
tooltip.add("");
added = true;
}
- float cost = craftCost.craftCost;
+ double cost = craftCost.craftCost;
if (shiftPressed) cost = cost * shiftStackMultiplier;
-
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD +
- (shortNumber && cost > 1000 ? Utils.shortNumberFormat(cost, 0) : format.format((int) cost)) + " coins");
+ tooltip.add(formatPrice("Raw Craft Cost: ", cost));
}
break;
}
@@ -211,8 +217,7 @@ public class ItemPriceInformation {
tooltip.add("");
added = true;
}
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Lowest BIN: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + format.format(lowestBin) + " coins");
+ tooltip.add(formatPrice("Lowest BIN: ", lowestBin));
}
break;
case 1:
@@ -223,21 +228,11 @@ public class ItemPriceInformation {
}
if (auctionInfo.has("clean_price")) {
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price (Clean): " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD +
- (shortNumber && auctionInfo.get("clean_price").getAsFloat() > 1000 ? Utils.shortNumberFormat(
- auctionInfo.get("clean_price").getAsFloat(),
- 0
- ) : format.format((int) auctionInfo.get("clean_price").getAsFloat())
- + " coins"));
+ double cleanPrice = auctionInfo.get("clean_price").getAsDouble();
+ tooltip.add(formatPrice("AH Price (Clean): ", cleanPrice));
} else {
- int auctionPrice =
- (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AH Price: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD +
- (shortNumber && auctionPrice > 1000
- ? Utils.shortNumberFormat(auctionPrice, 0)
- : format.format(auctionPrice)) + " coins");
+ double auctionPrice = auctionInfo.get("price").getAsDouble() / auctionInfo.get("count").getAsFloat();
+ tooltip.add(formatPrice("AH Price: ", auctionPrice));
}
}
@@ -267,18 +262,14 @@ public class ItemPriceInformation {
break;
case 3:
if (craftCost != null && craftCost.fromRecipe) {
- if ((int) craftCost.craftCost == 0) {
+ if (craftCost.craftCost == 0) {
continue;
}
if (!added) {
tooltip.add("");
added = true;
}
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Raw Craft Cost: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD +
- (shortNumber && craftCost.craftCost > 1000
- ? Utils.shortNumberFormat(craftCost.craftCost, 0)
- : format.format((int) craftCost.craftCost)) + " coins");
+ tooltip.add(formatPrice("Raw Craft Cost: ", craftCost.craftCost));
}
break;
case 4:
@@ -287,11 +278,7 @@ public class ItemPriceInformation {
tooltip.add("");
added = true;
}
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "AVG Lowest BIN: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD +
- (shortNumber && lowestBinAvg > 1000
- ? Utils.shortNumberFormat(lowestBinAvg, 0)
- : format.format(lowestBinAvg)) + " coins");
+ tooltip.add(formatPrice("AVG Lowest BIN: ", lowestBinAvg));
}
break;
case 5:
@@ -302,41 +289,56 @@ public class ItemPriceInformation {
}
JsonObject itemCosts = essenceCosts.get(internalname).getAsJsonObject();
String essenceType = itemCosts.get("type").getAsString();
+ boolean requiresItems = false;
+ JsonObject itemsObject = null;
+ if (itemCosts.has("items")) {
+ requiresItems = true;
+ itemsObject = itemCosts.get("items").getAsJsonObject();
+ }
- int dungeonItemLevel = -1;
- if (stack != null && stack.hasTagCompound() &&
- stack.getTagCompound().hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = stack.getTagCompound().getCompoundTag("ExtraAttributes");
+ int dungeonItemLevel = Utils.getNumberOfStars(stack);
- if (ea.hasKey("dungeon_item_level", 99)) {
- dungeonItemLevel = ea.getInteger("dungeon_item_level");
- }
- }
if (dungeonItemLevel == -1) {
int dungeonizeCost = 0;
if (itemCosts.has("dungeonize")) {
dungeonizeCost = itemCosts.get("dungeonize").getAsInt();
}
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Dungeonize Cost: " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + dungeonizeCost + " " + essenceType);
- } else if (dungeonItemLevel >= 0 && dungeonItemLevel <= 4) {
- String costType = (dungeonItemLevel + 1) + "";
- int upgradeCost = itemCosts.get(costType).getAsInt();
- StringBuilder star = new StringBuilder();
- for (int i = 0; i <= dungeonItemLevel; i++) {
- star.append('\u272A');
+ if (dungeonizeCost > 0) {
+ tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Dungeonize Cost: " +
+ EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + dungeonizeCost + " " + essenceType);
+ }
+ } else if (dungeonItemLevel >= 0) {
+ String nextStarLevelString = (dungeonItemLevel + 1) + "";
+ int nextStarLevelInt = Integer.parseInt(nextStarLevelString);
+
+ if (itemCosts.has(nextStarLevelString)) {
+ int upgradeCost = itemCosts.get(nextStarLevelString).getAsInt();
+ String starString = Utils.getStarsString(nextStarLevelInt);
+ tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Upgrade to " +
+ starString + EnumChatFormatting.YELLOW + EnumChatFormatting.BOLD + ": " +
+ EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + upgradeCost + " " + essenceType);
+ if (requiresItems && itemsObject.has(nextStarLevelString)) {
+ boolean shouldShow = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) ||
+ NotEnoughUpdates.INSTANCE.config.tooltipTweaks.alwaysShowRequiredItems;
+
+ if (shouldShow) {
+ tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Required Items:");
+ for (JsonElement item : itemsObject.get(nextStarLevelString).getAsJsonArray()) {
+ tooltip.add(" - " + item.getAsString());
+ }
+ } else {
+ tooltip.add(EnumChatFormatting.DARK_GRAY + "[CTRL to show required items]");
+ }
+ }
}
- tooltip.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Upgrade to " +
- EnumChatFormatting.GOLD + star + EnumChatFormatting.YELLOW + EnumChatFormatting.BOLD + ": " +
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + upgradeCost + " " + essenceType);
}
break;
}
}
return added;
- } else if (auctionInfoErrored) {
+ } else if (auctionInfoErrored && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
String message = EnumChatFormatting.RED.toString() + EnumChatFormatting.BOLD + "[NEU] API is down";
if (auctionableItems != null && !auctionableItems.isEmpty()) {
if (auctionableItems.contains(internalname)) {
@@ -351,4 +353,13 @@ public class ItemPriceInformation {
return false;
}
+
+ private static String formatPrice(String label, double price) {
+ boolean shortNumber = NotEnoughUpdates.INSTANCE.config.tooltipTweaks.shortNumberFormatPrices;
+ String number = (shortNumber && price > 1000
+ ? Utils.shortNumberFormat(price, 0)
+ : price > 5 ? format.format((int) price) : format.format(price));
+ return "§e§l" + label + "§6§l" + number + " coins";
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java
index d83035d0..6cdeb474 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUApi.java
@@ -1,9 +1,27 @@
-package io.github.moulberry.notenoughupdates;
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+package io.github.moulberry.notenoughupdates;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
public class NEUApi {
- static boolean disableInventoryButtons = false;
+ public static boolean disableInventoryButtons = false;
public static void setInventoryButtonsToDisabled() {
disableInventoryButtons = true;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
deleted file mode 100644
index 84289e34..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
+++ /dev/null
@@ -1,2842 +0,0 @@
-package io.github.moulberry.notenoughupdates;
-
-import com.google.common.collect.Lists;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import com.mojang.authlib.GameProfile;
-import com.mojang.authlib.minecraft.MinecraftProfileTexture;
-import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
-import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand;
-import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
-import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
-import io.github.moulberry.notenoughupdates.core.util.MiscUtils;
-import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
-import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
-import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
-import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
-import io.github.moulberry.notenoughupdates.miscfeatures.*;
-import io.github.moulberry.notenoughupdates.miscgui.*;
-import io.github.moulberry.notenoughupdates.options.NEUConfig;
-import io.github.moulberry.notenoughupdates.overlays.*;
-import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
-import io.github.moulberry.notenoughupdates.util.*;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.*;
-import net.minecraft.client.gui.inventory.GuiChest;
-import net.minecraft.client.gui.inventory.GuiContainer;
-import net.minecraft.client.gui.inventory.GuiEditSign;
-import net.minecraft.client.gui.inventory.GuiInventory;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.event.ClickEvent;
-import net.minecraft.init.Items;
-import net.minecraft.inventory.ContainerChest;
-import net.minecraft.inventory.IInventory;
-import net.minecraft.inventory.Slot;
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.nbt.NBTUtil;
-import net.minecraft.util.*;
-import net.minecraftforge.client.ClientCommandHandler;
-import net.minecraftforge.client.event.*;
-import net.minecraftforge.event.entity.player.ItemTooltipEvent;
-import net.minecraftforge.event.world.WorldEvent;
-import net.minecraftforge.fml.common.Loader;
-import net.minecraftforge.fml.common.eventhandler.EventPriority;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import org.apache.commons.lang3.text.WordUtils;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
-import org.lwjgl.opengl.GL11;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.datatransfer.StringSelection;
-import java.io.File;
-import java.io.IOException;
-import java.text.DecimalFormat;
-import java.text.NumberFormat;
-import java.util.List;
-import java.util.*;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.*;
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth;
-
-public class NEUEventListener {
-
- private final NotEnoughUpdates neu;
-
- private boolean hoverInv = false;
- private boolean focusInv = false;
-
- private boolean joinedSB = false;
-
- public NEUEventListener(NotEnoughUpdates neu) {
- this.neu = neu;
- }
-
- private void displayUpdateMessageIfOutOfDate() {
- File repo = neu.manager.repoLocation;
- if (repo.exists()) {
- File updateJson = new File(repo, "update.json");
- try {
- JsonObject o = neu.manager.getJsonFromFile(updateJson);
-
- String version = o.get("version").getAsString();
- String preVersion = o.get("pre_version").getAsString();
-
- boolean shouldUpdate = !NotEnoughUpdates.VERSION.equalsIgnoreCase(version);
- boolean shouldPreUpdate = !NotEnoughUpdates.PRE_VERSION.equalsIgnoreCase(preVersion);
-
- if (o.has("version_id") && o.get("version_id").isJsonPrimitive()) {
- int version_id = o.get("version_id").getAsInt();
- shouldUpdate = version_id > NotEnoughUpdates.VERSION_ID;
- }
- if (o.has("pre_version_id") && o.get("pre_version_id").isJsonPrimitive()) {
- int pre_version_id = o.get("pre_version_id").getAsInt();
- shouldPreUpdate = pre_version_id > NotEnoughUpdates.PRE_VERSION_ID;
- }
-
- if (shouldUpdate) {
- String update_msg = o.get("update_msg").getAsString();
-
- int first_len = -1;
- for (String line : update_msg.split("\n")) {
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int len = fr.getStringWidth(line);
- if (first_len == -1) {
- first_len = len;
- }
- int missing_len = first_len - len;
- if (missing_len > 0) {
- StringBuilder sb = new StringBuilder(line);
- for (int i = 0; i < missing_len / 8; i++) {
- sb.insert(0, " ");
- }
- line = sb.toString();
- }
- line = line.replaceAll("\\{version}", version);
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line));
- }
-
- neu.displayLinks(o);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- } else if (shouldPreUpdate && NotEnoughUpdates.VERSION_ID == o.get("version").getAsInt()) {
- String pre_update_msg = o.get("pre_update_msg").getAsString();
-
- int first_len = -1;
- for (String line : pre_update_msg.split("\n")) {
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int len = fr.getStringWidth(line);
- if (first_len == -1) {
- first_len = len;
- }
- int missing_len = first_len - len;
- if (missing_len > 0) {
- StringBuilder sb = new StringBuilder(line);
- for (int i = 0; i < missing_len / 8; i++) {
- sb.insert(0, " ");
- }
- line = sb.toString();
- }
- line = line.replaceAll("\\{pre_version}", preVersion);
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(line));
- }
-
- neu.displayLinks(o);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- }
- } catch (Exception ignored) {
- }
- }
- }
-
- @SubscribeEvent
- public void onWorldLoad(WorldEvent.Unload event) {
- NotEnoughUpdates.INSTANCE.saveConfig();
- CrystalMetalDetectorSolver.reset(false);
- }
-
- private static long notificationDisplayMillis = 0;
- private static List<String> notificationLines = null;
- private static boolean showNotificationOverInv = false;
-
- private static final Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$");
- private static final Pattern SLAYER_XP =
- Pattern.compile(" (Spider|Zombie|Wolf|Enderman) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)");
-
- /**
- * 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message.
- * This is used in order to prevent the mod spamming messages.
- * 2)Adds unique items to the collection log
- */
- private boolean preloadedItems = false;
- private long lastLongUpdate = 0;
- private long lastSkyblockScoreboard = 0;
-
- private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10);
- private final List<ItemStack> toPreload = new ArrayList<>();
-
- private int inventoryLoadedTicks = 0;
- private String loadedInvName = "";
- public static boolean inventoryLoaded = false;
-
- public static void displayNotification(List<String> lines, boolean showForever) {
- displayNotification(lines, showForever, false);
- }
-
- public static void displayNotification(List<String> lines, boolean showForever, boolean overInventory) {
- if (showForever) {
- notificationDisplayMillis = -420;
- } else {
- notificationDisplayMillis = System.currentTimeMillis();
- }
- notificationLines = lines;
- showNotificationOverInv = overInventory;
- }
-
- @SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent event) {
- Keyboard.enableRepeatEvents(
- Minecraft.getMinecraft().currentScreen != null && (Minecraft.getMinecraft().currentScreen instanceof GuiChat
- || Minecraft.getMinecraft().currentScreen instanceof GuiEditSign ||
- Minecraft.getMinecraft().currentScreen instanceof GuiScreenBook));
- if (event.phase != TickEvent.Phase.START) return;
- if (Minecraft.getMinecraft().theWorld == null) return;
- if (Minecraft.getMinecraft().thePlayer == null) return;
-
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest cc = (ContainerChest) chest.inventorySlots;
-
- if (!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) {
- loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
- inventoryLoaded = false;
- inventoryLoadedTicks = 3;
- }
-
- if (!inventoryLoaded) {
- if (cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory() - 1) != null) {
- inventoryLoaded = true;
- } else {
- for (ItemStack stack : chest.inventorySlots.getInventory()) {
- if (stack != null) {
- if (--inventoryLoadedTicks <= 0) {
- inventoryLoaded = true;
- }
- break;
- }
- }
- }
- }
- } else {
- inventoryLoaded = false;
- inventoryLoadedTicks = 3;
- }
-
- if ((Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) &&
- Keyboard.isKeyDown(Keyboard.KEY_NUMPAD9))) {
- ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!");
- component.appendText("\n");
- component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other");
- component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal");
- component.appendText("\n");
- component.appendText("\n\u00a77Ban ID: \u00a7r#49871982");
- component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!");
- Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component);
- return;
- }
-
- if (neu.hasSkyblockScoreboard()) {
- if (!preloadedItems) {
- preloadedItems = true;
- List<JsonObject> list = new ArrayList<>(neu.manager.getItemInformation().values());
- for (JsonObject json : list) {
- itemPreloader.submit(() -> {
- ItemStack stack = neu.manager.jsonToStack(json, true, true);
- if (stack.getItem() == Items.skull) toPreload.add(stack);
- });
- }
- } else if (!toPreload.isEmpty()) {
- Utils.drawItemStack(toPreload.get(0), -100, -100);
- toPreload.remove(0);
- } else {
- itemPreloader.shutdown();
- }
-
- for (TextOverlay overlay : OverlayManager.textOverlays) {
- overlay.shouldUpdateFrequent = true;
- }
- }
-
- boolean longUpdate = false;
- long currentTime = System.currentTimeMillis();
- if (currentTime - lastLongUpdate > 1000) {
- longUpdate = true;
- lastLongUpdate = currentTime;
- }
- if (!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) {
- DungeonBlocks.tick();
- }
- DungeonWin.tick();
-
- String containerName = null;
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) {
- GuiCustomEnchant.getInstance().tick();
- }
- }
-
- if (longUpdate) {
- CrystalOverlay.tick();
- FairySouls.tick();
- XPInformation.getInstance().tick();
- ProfileApiSyncer.getInstance().tick();
- ItemCustomizeManager.tick();
- BackgroundBlur.markDirty();
- NPCRetexturing.getInstance().tick();
- StorageOverlay.getInstance().markDirty();
-
- if (neu.hasSkyblockScoreboard()) {
- for (TextOverlay overlay : OverlayManager.textOverlays) {
- overlay.tick();
- }
- }
-
- NotEnoughUpdates.INSTANCE.overlay.redrawItems();
- CapeManager.onTickSlow();
-
- NotEnoughUpdates.profileViewer.putNameUuid(
- Minecraft.getMinecraft().thePlayer.getName(),
- Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")
- );
-
- if (NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) {
- DungeonBlocks.tick();
- }
-
- if (System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 &&
- System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) {
- neu.updateSkyblockScoreboard();
- }
- CapeManager.getInstance().tick();
-
- if (containerName != null) {
- if (!containerName.trim().startsWith("Accessory Bag")) {
- AccessoryBagOverlay.resetCache();
- }
- } else {
- AccessoryBagOverlay.resetCache();
- }
-
- if (neu.hasSkyblockScoreboard()) {
- SBInfo.getInstance().tick();
- lastSkyblockScoreboard = currentTime;
- if (!joinedSB) {
- joinedSB = true;
-
- //SBGamemodes.loadFromFile();
-
- if (NotEnoughUpdates.INSTANCE.config.notifications.showUpdateMsg) {
- displayUpdateMessageIfOutOfDate();
- }
-
- if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) {
- long maxMemoryMB = Runtime.getRuntime().maxMemory() / 1024L / 1024L;
- if (maxMemoryMB > 4100) {
- notificationDisplayMillis = System.currentTimeMillis();
- notificationLines = new ArrayList<>();
- notificationLines.add(EnumChatFormatting.GRAY + "Too much memory allocated!");
- notificationLines.add(String.format(
- EnumChatFormatting.DARK_GRAY + "NEU has detected %03dMB of memory allocated to Minecraft!",
- maxMemoryMB
- ));
- notificationLines.add(EnumChatFormatting.GRAY + "It is recommended to allocated between 2-4GB of memory");
- notificationLines.add(
- EnumChatFormatting.GRAY + "More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available");
- notificationLines.add("");
- notificationLines.add(
- EnumChatFormatting.GRAY + "For more information, visit #ram-info in discord.gg/moulberry");
- }
- }
-
- if (!NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore) {
- NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore = true;
- if (Constants.MISC == null || !Constants.MISC.has("featureslist")) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET +
- EnumChatFormatting.RED + "Could not load Feature List URL from repo."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" +
- EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD +
- "restart your game" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " +
- EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "If that doesn't fix it" +
- EnumChatFormatting.RESET + EnumChatFormatting.RED +
- ", please join discord.gg/moulberry and post in #neu-support"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- "" + EnumChatFormatting.GOLD + "To view the feature list after restarting type /neufeatures"));
- } else {
- String url = Constants.MISC.get("featureslist").getAsString();
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates."));
- ChatComponentText clickTextFeatures = new ChatComponentText(
- EnumChatFormatting.YELLOW +
- "Click this message if you would like to view a list of NotEnoughUpdate's Features.");
- clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url));
- Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures);
- }
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- ChatComponentText clickTextHelp = new ChatComponentText(
- EnumChatFormatting.YELLOW +
- "Click this message if you would like to view a list of NotEnoughUpdate's commands.");
- clickTextHelp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuhelp"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextHelp);
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- }
- }
- }
- if (currentTime - lastSkyblockScoreboard < 5 * 60 * 1000) { //5 minutes
- neu.manager.auctionManager.tick();
- } else {
- neu.manager.auctionManager.markNeedsUpdate();
- }
- }
-
- /*if(longUpdate && neu.hasSkyblockScoreboard()) {
- if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) {
- ProfileViewer.Profile profile = NotEnoughUpdates.profileViewer.getProfile(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
- callback->{});
- if(profile != null) {
- String latest = profile.getLatestProfile();
- if(latest != null) {
- neu.manager.setCurrentProfileBackup(profile.getLatestProfile());
- }
- }
- }*/
- /*if(neu.manager.getCurrentProfile() != null && neu.manager.getCurrentProfile().length() > 0) {
- HashSet<String> newItem = new HashSet<>();
- if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer &&
- !(Minecraft.getMinecraft().currentScreen instanceof GuiCrafting)) {
- boolean usableContainer = true;
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) {
- if(stack == null) {
- continue;
- }
- if(stack.hasTagCompound()) {
- NBTTagCompound tag = stack.getTagCompound();
- if(tag.hasKey("ExtraAttributes", 10)) {
- continue;
- }
- }
- usableContainer = false;
- break;
- }
- if(!usableContainer) {
- if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- if(containerName.equals("Accessory Bag") || containerName.startsWith("Wardrobe")) {
- usableContainer = true;
- }
- }
- }
- if(usableContainer) {
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
- processUniqueStack(stack, newItem);
- }
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) {
- processUniqueStack(stack, newItem);
- }
- }
- } else {
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
- processUniqueStack(stack, newItem);
- }
- }
- newItemAddMap.keySet().retainAll(newItem);
- }
- }*/
- }
-
- /*private void processUniqueStack(ItemStack stack, HashSet<String> newItem) {
- if(stack != null && stack.hasTagCompound()) {
- String internalname = neu.manager.getInternalNameForItem(stack);
- if(internalname != null) {
- /*ArrayList<String> log = neu.manager.config.collectionLog.value.computeIfAbsent(
- neu.manager.getCurrentProfile(), k -> new ArrayList<>());
- if(!log.contains(internalname)) {
- newItem.add(internalname);
- if(newItemAddMap.containsKey(internalname)) {
- if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) {
- log.add(internalname);
- try { neu.manager.saveConfig(); } catch(IOException ignored) {}
- }
- } else {
- newItemAddMap.put(internalname, System.currentTimeMillis());
- }
- }
- }
- }
- }*/
-
- @SubscribeEvent(priority = EventPriority.HIGHEST)
- public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre<EntityPlayer> event) {
- if (Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) {
- if (((GuiProfileViewer) Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) {
- event.setCanceled(true);
- }
- }
- }
-
- @SubscribeEvent
- public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) {
- if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) &&
- Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) {
- event.setCanceled(true);
- }
- if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) {
- GlStateManager.enableDepth();
- }
- }
-
- @SubscribeEvent
- public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) {
- if (neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) {
- DungeonWin.render(event.partialTicks);
- GlStateManager.pushMatrix();
- GlStateManager.translate(0, 0, -200);
- for (TextOverlay overlay : OverlayManager.textOverlays) {
- if (OverlayManager.dontRenderOverlay != null &&
- OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) {
- continue;
- }
- GlStateManager.translate(0, 0, -1);
- GlStateManager.enableDepth();
- overlay.render();
- }
- GlStateManager.popMatrix();
- OverlayManager.dontRenderOverlay = null;
- }
- if (Keyboard.isKeyDown(Keyboard.KEY_X)) {
- notificationDisplayMillis = 0;
- }
-
- if (event.type == RenderGameOverlayEvent.ElementType.ALL) {
- renderNotification();
- }
-
- }
-
- private static void renderNotification() {
-
- long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis);
- boolean display = timeRemaining > 0 || notificationDisplayMillis == -420;
- if (display && notificationLines != null && notificationLines.size() > 0) {
- int width = 0;
- int height = notificationLines.size() * 10 + 10;
-
- for (String line : notificationLines) {
- int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8;
- if (len > width) {
- width = len;
- }
- }
-
- ScaledResolution sr = Utils.pushGuiScale(2);
-
- int midX = sr.getScaledWidth() / 2;
- int topY = sr.getScaledHeight() * 3 / 4 - height / 2;
- RenderUtils.drawFloatingRectDark(midX - width / 2, sr.getScaledHeight() * 3 / 4 - height / 2, width, height);
- /*Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2,
- midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C);
- Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2,
- midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);*/
-
- int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close");
- Minecraft.getMinecraft().fontRendererObj.drawString("[X] Close", midX + width / 2f - 3 - xLen,
- topY + 3, 0xFFFF5555, false
- );
-
- if (notificationDisplayMillis > 0) {
- Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining / 1000) + "s", midX - width / 2f + 3,
- topY + 3, 0xFFaaaaaa, false
- );
- }
-
- Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj,
- midX, topY + 4 + 5, false, -1
- );
- for (int i = 1; i < notificationLines.size(); i++) {
- String line = notificationLines.get(i);
- Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj,
- midX, topY + 4 + 5 + 2 + i * 10, false, -1
- );
- }
-
- Utils.pushGuiScale(-1);
- }
- }
-
- public static long lastGuiClosed = 0;
-
- /**
- * When opening a GuiContainer, will reset the overlay and load the config.
- * When closing a GuiContainer, will save the config.
- * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI.
- */
- AtomicBoolean missingRecipe = new AtomicBoolean(false);
-
- @SubscribeEvent
- public void onGuiOpen(GuiOpenEvent event) {
- NEUApi.disableInventoryButtons = false;
-
- if ((Minecraft.getMinecraft().currentScreen instanceof GuiScreenElementWrapper ||
- Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe) &&
- event.gui == null && !(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) &&
- System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.lastOpenedGui < 500) {
- NotEnoughUpdates.INSTANCE.lastOpenedGui = 0;
- event.setCanceled(true);
- return;
- }
-
- if (!(event.gui instanceof GuiContainer) && Minecraft.getMinecraft().currentScreen != null) {
- CalendarOverlay.setEnabled(false);
- }
-
- if (Minecraft.getMinecraft().currentScreen != null) {
- lastGuiClosed = System.currentTimeMillis();
- }
-
- neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis();
- BetterContainers.reset();
- inventoryLoaded = false;
- inventoryLoadedTicks = 3;
-
- if (event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() &&
- !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
- event.gui = new CustomAHGui();
- }
-
- if (!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) {
- neu.manager.auctionManager.customAH.setRenderOverAuctionView(false);
- } else if (event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() ||
- Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
- GuiChest chest = (GuiChest) event.gui;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- neu.manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") ||
- containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid") ||
- containerName.trim().equals("Confirm Purchase"));
- }
-
- //OPEN
- if (Minecraft.getMinecraft().currentScreen == null
- && event.gui instanceof GuiContainer) {
- neu.overlay.reset();
- }
- if (event.gui != null && NotEnoughUpdates.INSTANCE.config.hidden.dev) {
- if (event.gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) event.gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
- ses.schedule(() -> {
- if (Minecraft.getMinecraft().currentScreen != event.gui) {
- return;
- }
- if (lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
- try {
- ItemStack res = lower.getStackInSlot(25);
- String resInternalname = neu.manager.getInternalNameForItem(res);
-
- if (lower.getStackInSlot(48) != null) {
- String backName = null;
- NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound();
- if (tag.hasKey("display", 10)) {
- NBTTagCompound nbttagcompound = tag.getCompoundTag("display");
- if (nbttagcompound.getTagId("Lore") == 9) {
- NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8);
- backName = nbttaglist1.getStringTagAt(0);
- }
- }
-
- if (backName != null) {
- String[] split = backName.split(" ");
- if (split[split.length - 1].contains("Rewards")) {
- String col = backName.substring(
- split[0].length() + 1,
- backName.length() - split[split.length - 1].length() - 1
- );
-
- JsonObject json = neu.manager.getItemInformation().get(resInternalname);
- json.addProperty("crafttext", "Requires: " + col);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- "Added: " + resInternalname));
- neu.manager.writeJsonDefaultDir(json, resInternalname + ".json");
- neu.manager.loadItem(resInternalname);
- }
- }
- }
-
- /*JsonArray arr = null;
- File f = new File(neu.manager.configLocation, "missing.json");
- try(InputStream instream = new FileInputStream(f)) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
- JsonObject json = neu.manager.gson.fromJson(reader, JsonObject.class);
- arr = json.getAsJsonArray("missing");
- } catch(IOException e) {}
- try {
- JsonObject json = new JsonObject();
- JsonArray newArr = new JsonArray();
- for(JsonElement e : arr) {
- if(!e.getAsString().equals(resInternalname)) {
- newArr.add(e);
- }
- }
- json.add("missing", newArr);
- neu.manager.writeJson(json, f);
- } catch(IOException e) {}*/
-
-
-
- /*JsonObject recipe = new JsonObject();
-
- String[] x = {"1","2","3"};
- String[] y = {"A","B","C"};
-
- for(int i=0; i<=18; i+=9) {
- for(int j=0; j<3; j++) {
- ItemStack stack = lower.getStackInSlot(10+i+j);
- String internalname = "";
- if(stack != null) {
- internalname = neu.manager.getInternalNameForItem(stack);
- if(!neu.manager.getItemInformation().containsKey(internalname)) {
- neu.manager.writeItemToFile(stack);
- }
- internalname += ":"+stack.stackSize;
- }
- recipe.addProperty(y[i/9]+x[j], internalname);
- }
- }
-
- JsonObject json = neu.manager.getJsonForItem(res);
- json.add("recipe", recipe);
- json.addProperty("internalname", resInternalname);
- json.addProperty("clickcommand", "viewrecipe");
- json.addProperty("modver", NotEnoughUpdates.VERSION);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
- neu.manager.writeJsonDefaultDir(json, resInternalname+".json");
- neu.manager.loadItem(resInternalname);*/
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }, 200, TimeUnit.MILLISECONDS);
- }
- }
- }
-
- /*@SubscribeEvent
- public void onPlayerInteract(EntityInteractEvent event) {
- if(!event.isCanceled() && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() &&
- Minecraft.getMinecraft().thePlayer.isSneaking() &&
- Minecraft.getMinecraft().ingameGUI != null) {
- if(event.target instanceof EntityPlayer) {
- for(NetworkPlayerInfo info : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) {
- String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info);
- if(name.contains("Status: "+EnumChatFormatting.RESET+EnumChatFormatting.BLUE+"Guest")) {
- NotEnoughUpdates.INSTANCE.sendChatMessage("/trade " + event.target.getName());
- event.setCanceled(true);
- break;
- }
- }
- }
- }
- }*/
-
- private IChatComponent processChatComponent(IChatComponent chatComponent) {
- IChatComponent newComponent;
- if (chatComponent instanceof ChatComponentText) {
- ChatComponentText text = (ChatComponentText) chatComponent;
-
- newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat()));
- newComponent.setChatStyle(text.getChatStyle().createShallowCopy());
-
- for (IChatComponent sibling : text.getSiblings()) {
- newComponent.appendSibling(processChatComponent(sibling));
- }
- } else if (chatComponent instanceof ChatComponentTranslation) {
- ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent;
-
- Object[] args = trans.getFormatArgs();
- Object[] newArgs = new Object[args.length];
- for (int i = 0; i < trans.getFormatArgs().length; i++) {
- if (args[i] instanceof IChatComponent) {
- newArgs[i] = processChatComponent((IChatComponent) args[i]);
- } else {
- newArgs[i] = args[i];
- }
- }
- newComponent = new ChatComponentTranslation(trans.getKey(), newArgs);
-
- for (IChatComponent sibling : trans.getSiblings()) {
- newComponent.appendSibling(processChatComponent(sibling));
- }
- } else {
- newComponent = chatComponent.createCopy();
- }
-
- return newComponent;
- }
-
- private String processText(String text) {
- if (SBInfo.getInstance().getLocation() == null) return text;
- if (!SBInfo.getInstance().getLocation().startsWith("mining_") &&
- !SBInfo.getInstance().getLocation().equals("crystal_hollows"))
- return text;
-
- if (Minecraft.getMinecraft().thePlayer == null) return text;
- if (!NotEnoughUpdates.INSTANCE.config.mining.drillFuelBar) return text;
-
- return Utils.trimIgnoreColour(text.replaceAll(EnumChatFormatting.DARK_GREEN + "\\S+ Drill Fuel", ""));
- }
-
- private IChatComponent replaceSocialControlsWithPV(IChatComponent chatComponent) {
-
- if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 > 0 && chatComponent.getChatStyle() != null &&
- chatComponent.getChatStyle().getChatClickEvent() != null &&
- chatComponent.getChatStyle().getChatClickEvent().getAction() == ClickEvent.Action.RUN_COMMAND &&
- NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- if (chatComponent.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) {
- String username = chatComponent.getChatStyle().getChatClickEvent().getValue().substring(15);
- if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 1) {
- chatComponent.setChatStyle(Utils.createClickStyle(
- ClickEvent.Action.RUN_COMMAND,
- "/pv " + username,
- "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD +
- username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s profile in " +
- EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD + "NEU's" + EnumChatFormatting.RESET +
- EnumChatFormatting.YELLOW + " profile viewer."
- ));
- return chatComponent;
- } else if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 2) {
- chatComponent.setChatStyle(Utils.createClickStyle(
- ClickEvent.Action.RUN_COMMAND,
- "/ah " + username,
- "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD +
- username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s /ah page"
- ));
- return chatComponent;
- }
- } // wanted to add this for guild but guild uses uuid :sad:
- }
- return chatComponent;
- }
-
- /**
- * 1) When receiving "You are playing on profile" messages, will set the current profile.
- * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI)
- * 3) Replaces lobby join notifications when streamer mode is active
- */
- @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
- public void onGuiChat(ClientChatReceivedEvent e) {
- if (e.type == 2) {
- CrystalMetalDetectorSolver.process(e.message);
- e.message = processChatComponent(e.message);
- return;
- } else if (e.type == 0) {
- e.message = replaceSocialControlsWithPV(e.message);
- }
-
- DungeonWin.onChatMessage(e);
-
- String r = null;
- String unformatted = Utils.cleanColour(e.message.getUnformattedText());
- Matcher matcher = SLAYER_XP.matcher(unformatted);
- if (unformatted.startsWith("You are playing on profile: ")) {
- neu.manager.setCurrentProfile(unformatted
- .substring("You are playing on profile: ".length())
- .split(" ")[0].trim());
- } else if (unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to:
- neu.manager.setCurrentProfile(unformatted
- .substring("Your profile was changed to: ".length())
- .split(" ")[0].trim());
- } else if (unformatted.startsWith("Your new API key is ")) {
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = unformatted.substring("Your new API key is ".length());
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
- "[NEU] API Key automatically configured"));
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey = NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.substring(0, 36);
- } else if (unformatted.startsWith("Player List Info is now disabled!")) {
- SBInfo.getInstance().hasNewTab = false;
- } else if (unformatted.startsWith("Player List Info is now enabled!")) {
- SBInfo.getInstance().hasNewTab = true;
- }
- if (e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString() +
- EnumChatFormatting.RED + "You haven't unlocked this recipe!" + EnumChatFormatting.RESET)) {
- r = EnumChatFormatting.RED + "You haven't unlocked this recipe!";
- } else if (e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString() +
- EnumChatFormatting.RED + "Invalid recipe ")) {
- r = "";
- } else if (unformatted.equals(" NICE! SLAYER BOSS SLAIN!")) {
- SlayerOverlay.isSlain = true;
- } else if (unformatted.equals(" SLAYER QUEST STARTED!")) {
- SlayerOverlay.isSlain = false;
- if (timeSinceLastBoss == 0) {
- SlayerOverlay.timeSinceLastBoss = System.currentTimeMillis();
- } else {
- timeSinceLastBoss2 = timeSinceLastBoss;
- timeSinceLastBoss = System.currentTimeMillis();
- }
- } else if (unformatted.startsWith(" RNGesus Meter:")) {
- RNGMeter = unformatted.substring(" RNGesus Meter: -------------------- ".length());
- } else if (matcher.matches()) {
- //matcher.group(1);
- SlayerOverlay.slayerLVL = matcher.group(2);
- if (!SlayerOverlay.slayerLVL.equals("9")) {
- SlayerOverlay.slayerXp = matcher.group(3);
- } else {
- slayerXp = "maxed";
- }
- } else if (unformatted.startsWith("Sending to server") ||
- (unformatted.startsWith("Your Slayer Quest has been cancelled!"))) {
- SlayerOverlay.slayerQuest = false;
- SlayerOverlay.unloadOverlayTimer = System.currentTimeMillis();
- }
- if (e.message
- .getFormattedText()
- .contains(EnumChatFormatting.YELLOW + "Visit the Auction House to collect your item!")) {
- if (NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null &&
- System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) {
- NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " +
- NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId(
- NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid));
- }
- }
- if (r != null) {
- if (neu.manager.failViewItem(r)) {
- e.setCanceled(true);
- }
- missingRecipe.set(true);
- }
- //System.out.println(e.message);
- if (unformatted.startsWith("Sending to server") &&
- neu.isOnSkyblock() && NotEnoughUpdates.INSTANCE.config.misc.streamerMode &&
- e.message instanceof ChatComponentText) {
- String m = e.message.getFormattedText();
- String m2 = StreamerMode.filterChat(e.message.getFormattedText());
- if (!m.equals(m2)) {
- e.message = new ChatComponentText(m2);
- }
- }
- if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null &&
- SBInfo.getInstance().getLocation().equals("crystal_hollows")) {
- CrystalMetalDetectorSolver.reset(true);
- }
- if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") ||
- unformatted.startsWith(" ") || unformatted.startsWith("✦") ||
- unformatted.equals(" You've earned a Crystal Loot Bundle!"))
- OverlayManager.crystalHollowOverlay.message(unformatted);
- }
-
- public static boolean drawingGuiScreen = false;
-
- /**
- * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
- * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
- * <p>
- * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI)
- * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv)
- * <p>
- * All of this only matters if players are using gui scale auto which may result in the inventory being drawn
- * over the various panes.
- */
- @SubscribeEvent
- public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
- if (showNotificationOverInv) {
-
- renderNotification();
-
- }
- if ((shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && neu.isOnSkyblock()) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledresolution.getScaledWidth();
-
- boolean hoverPane = event.getMouseX() < width * neu.overlay.getInfoPaneOffsetFactor() ||
- event.getMouseX() > width * neu.overlay.getItemPaneOffsetFactor();
-
- if (event.gui instanceof GuiContainer) {
- try {
- int xSize = ((GuiContainer) event.gui).xSize;
- int ySize = ((GuiContainer) event.gui).ySize;
- int guiLeft = ((GuiContainer) event.gui).guiLeft;
- int guiTop = ((GuiContainer) event.gui).guiTop;
-
- hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize &&
- event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize;
-
- if (hoverPane) {
- if (!hoverInv) focusInv = false;
- } else {
- focusInv = true;
- }
- } catch (NullPointerException npe) {
- focusInv = !hoverPane;
- }
- }
- if (event.gui instanceof GuiItemRecipe) {
- GuiItemRecipe guiItemRecipe = ((GuiItemRecipe) event.gui);
- hoverInv = event.getMouseX() > guiItemRecipe.guiLeft &&
- event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize &&
- event.getMouseY() > guiItemRecipe.guiTop && event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize;
-
- if (hoverPane) {
- if (!hoverInv) focusInv = false;
- } else {
- focusInv = true;
- }
- }
- if (focusInv) {
- try {
- neu.overlay.render(hoverInv);
- } catch (ConcurrentModificationException e) {
- e.printStackTrace();
- }
- GL11.glTranslatef(0, 0, 10);
- }
- if (hoverInv) {
- renderDungeonChestOverlay(event.gui);
- if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) {
- AccessoryBagOverlay.renderOverlay();
- }
- }
- }
-
- drawingGuiScreen = true;
- }
-
- private boolean doInventoryButtons = false;
-
- @SubscribeEvent
- public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
- doInventoryButtons = false;
-
- if (AuctionSearchOverlay.shouldReplace()) {
- AuctionSearchOverlay.render();
- event.setCanceled(true);
- return;
- }
- if (RancherBootOverlay.shouldReplace()) {
- RancherBootOverlay.render();
- event.setCanceled(true);
- return;
- }
-
- String containerName = null;
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) guiScreen;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
- }
-
- if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) {
- GuiCustomEnchant.getInstance().render(event.renderPartialTicks);
- event.setCanceled(true);
- return;
- }
-
- boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
- boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
- boolean customAhActive =
- event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
-
- if (storageOverlayActive) {
- StorageOverlay.getInstance().render();
- event.setCanceled(true);
- return;
- }
-
- if (tradeWindowActive || customAhActive) {
- event.setCanceled(true);
-
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledResolution.getScaledWidth();
- int height = scaledResolution.getScaledHeight();
-
- //Dark background
- Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
-
- if (event.mouseX < width * neu.overlay.getWidthMult() / 3 ||
- event.mouseX > width - width * neu.overlay.getWidthMult() / 3) {
- if (customAhActive) {
- neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
- } else if (tradeWindowActive) {
- TradeWindow.render(event.mouseX, event.mouseY);
- }
- neu.overlay.render(false);
- } else {
- neu.overlay.render(false);
- if (customAhActive) {
- neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
- } else if (tradeWindowActive) {
- TradeWindow.render(event.mouseX, event.mouseY);
- }
- }
- }
-
- if (CalendarOverlay.isEnabled() || event.isCanceled()) return;
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui)
- && event.gui instanceof GuiContainer) {
- doInventoryButtons = true;
-
- int zOffset = 50;
-
- GlStateManager.translate(0, 0, zOffset);
-
- int xSize = ((GuiContainer) event.gui).xSize;
- int ySize = ((GuiContainer) event.gui).ySize;
- int guiLeft = ((GuiContainer) event.gui).guiLeft;
- int guiTop = ((GuiContainer) event.gui).guiTop;
-
- if (!NEUApi.disableInventoryButtons) {
- for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
- if (!button.isActive()) continue;
- if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
-
- int x = guiLeft + button.x;
- int y = guiTop + button.y;
- if (button.anchorRight) {
- x += xSize;
- }
- if (button.anchorBottom) {
- y += ySize;
- }
- if (AccessoryBagOverlay.isInAccessoryBag()) {
- if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
- x += 80 + 28;
- }
- }
- if (NEUOverlay.isRenderingArmorHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
- x -= 25;
- }
- }
- if (NEUOverlay.isRenderingPetHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
- x -= 25;
- }
- }
-
- GlStateManager.color(1, 1, 1, 1f);
-
- GlStateManager.enableDepth();
- GlStateManager.enableAlpha();
- Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
- Utils.drawTexturedRect(x, y, 18, 18,
- button.backgroundIndex * 18 / 256f, (button.backgroundIndex * 18 + 18) / 256f,
- 18 / 256f, 36 / 256f, GL11.GL_NEAREST
- );
-
- if (button.icon != null && !button.icon.trim().isEmpty()) {
- GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1);
- }
- }
- }
- GlStateManager.translate(0, 0, -zOffset);
- }
- }
-
- private static boolean shouldRenderOverlay(Gui gui) {
- boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe;
- if (gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
- if (containerName.trim().equals("Fast Travel")) {
- validGui = false;
- }
- }
- return validGui;
- }
-
- private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png");
- private NEUConfig.InventoryButton buttonHovered = null;
- private long buttonHoveredMillis = 0;
- public static boolean disableCraftingText = false;
-
- /**
- * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay
- * will draw over Items in the inventory (which render at a z value of about 250))
- */
- @SubscribeEvent
- public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
- drawingGuiScreen = false;
- disableCraftingText = false;
-
- String containerName = null;
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) guiScreen;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- if (GuiCustomEnchant.getInstance().shouldOverride(containerName))
- return;
- }
-
- boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
- boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
- boolean customAhActive =
- event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
-
- if (!(tradeWindowActive || storageOverlayActive || customAhActive)) {
- if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
- GlStateManager.pushMatrix();
- if (!focusInv) {
- GL11.glTranslatef(0, 0, 300);
- neu.overlay.render(hoverInv && focusInv);
- GL11.glTranslatef(0, 0, -300);
- }
- GlStateManager.popMatrix();
- }
- }
-
- if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) {
- renderDungeonChestOverlay(event.gui);
- if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) {
- AccessoryBagOverlay.renderOverlay();
- }
- }
-
- boolean hoveringButton = false;
- if (!doInventoryButtons) return;
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) &&
- event.gui instanceof GuiContainer) {
- int xSize = ((GuiContainer) event.gui).xSize;
- int ySize = ((GuiContainer) event.gui).ySize;
- int guiLeft = ((GuiContainer) event.gui).guiLeft;
- int guiTop = ((GuiContainer) event.gui).guiTop;
-
- if (!NEUApi.disableInventoryButtons) {
- for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
- if (!button.isActive()) continue;
- if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
-
- int x = guiLeft + button.x;
- int y = guiTop + button.y;
- if (button.anchorRight) {
- x += xSize;
- }
- if (button.anchorBottom) {
- y += ySize;
- }
- if (AccessoryBagOverlay.isInAccessoryBag()) {
- if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
- x += 80 + 28;
- }
- }
- if (NEUOverlay.isRenderingArmorHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
- x -= 25;
- }
- }
- if (NEUOverlay.isRenderingPetHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
- x -= 25;
- }
- }
-
- if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) {
- disableCraftingText = true;
- }
-
- if (event.mouseX >= x && event.mouseX <= x + 18 &&
- event.mouseY >= y && event.mouseY <= y + 18) {
- hoveringButton = true;
- long currentTime = System.currentTimeMillis();
-
- if (buttonHovered != button) {
- buttonHoveredMillis = currentTime;
- buttonHovered = button;
- }
-
- if (currentTime - buttonHoveredMillis > 600) {
- String command = button.command.trim();
- if (!command.startsWith("/")) {
- command = "/" + command;
- }
-
- Utils.drawHoveringText(Lists.newArrayList("\u00a77" + command), event.mouseX, event.mouseY,
- event.gui.width, event.gui.height, -1, Minecraft.getMinecraft().fontRendererObj
- );
- }
- }
- }
- }
- }
- if (!hoveringButton) buttonHovered = null;
-
- if (AuctionBINWarning.getInstance().shouldShow()) {
- AuctionBINWarning.getInstance().render();
- }
- }
-
- private void renderDungeonChestOverlay(GuiScreen gui) {
- if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return;
-
- if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) {
- try {
- int xSize = ((GuiContainer) gui).xSize;
- int ySize = ((GuiContainer) gui).ySize;
- int guiLeft = ((GuiContainer) gui).guiLeft;
- int guiTop = ((GuiContainer) gui).guiTop;
-
- GuiChest eventGui = (GuiChest) gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- ItemStack rewardChest = lower.getStackInSlot(31);
- if (rewardChest != null &&
- rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN + "Open Reward Chest")) {
- int chestCost = 0;
- try {
- String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]);
- StringBuilder cost = new StringBuilder();
- for (int i = 0; i < line6.length(); i++) {
- char c = line6.charAt(i);
- if ("0123456789".indexOf(c) >= 0) {
- cost.append(c);
- }
- }
- if (cost.length() > 0) {
- chestCost = Integer.parseInt(cost.toString());
- }
- } catch (Exception ignored) {
- }
-
- String missingItem = null;
- int totalValue = 0;
- HashMap<String, Float> itemValues = new HashMap<>();
- for (int i = 0; i < 5; i++) {
- ItemStack item = lower.getStackInSlot(11 + i);
- String internal = neu.manager.getInternalNameForItem(item);
- if (internal != null) {
- internal = internal.replace("\u00CD", "I").replace("\u0130", "I");
- float bazaarPrice = -1;
- JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
- if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
- bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
- }
- if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000;
-
- float worth = -1;
- if (bazaarPrice > 0) {
- worth = bazaarPrice;
- } else {
- switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) {
- case 1:
- worth = neu.manager.auctionManager.getItemAvgBin(internal);
- break;
- case 2:
- JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
- if (auctionInfo != null) {
- if (auctionInfo.has("clean_price")) {
- worth = (int) auctionInfo.get("clean_price").getAsFloat();
- } else {
- worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- }
- }
- break;
- default:
- worth = neu.manager.auctionManager.getLowestBin(internal);
- }
- if (worth <= 0) {
- worth = neu.manager.auctionManager.getLowestBin(internal);
- if (worth <= 0) {
- worth = neu.manager.auctionManager.getItemAvgBin(internal);
- if (worth <= 0) {
- JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
- if (auctionInfo != null) {
- if (auctionInfo.has("clean_price")) {
- worth = (int) auctionInfo.get("clean_price").getAsFloat();
- } else {
- worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- }
- }
- }
- }
- }
- }
-
- if (worth > 0 && totalValue >= 0) {
- totalValue += worth;
- String display = item.getDisplayName();
-
- if (display.contains("Enchanted Book")) {
- NBTTagCompound tag = item.getTagCompound();
- if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
- NBTTagCompound enchants = ea.getCompoundTag("enchantments");
-
- int highestLevel = -1;
- for (String enchname : enchants.getKeySet()) {
- int level = enchants.getInteger(enchname);
- if (level > highestLevel) {
- display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(
- enchname.replace("_", " ")
- .replace("Ultimate", "")
- .trim()) + " " + level;
- }
- }
- }
- }
-
- itemValues.put(display, worth);
- } else {
- if (totalValue != -1) {
- missingItem = internal;
- }
- totalValue = -1;
- }
- }
- }
-
- NumberFormat format = NumberFormat.getInstance(Locale.US);
- String valueStringBIN1;
- String valueStringBIN2;
- if (totalValue >= 0) {
- valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): ";
- valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins";
- } else {
- valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: ";
- valueStringBIN2 = missingItem;
- }
-
- int profitLossBIN = totalValue - chestCost;
-
- boolean kismetUsed = false;
- // checking for kismet
- Slot slot = (eventGui.inventorySlots.getSlot(50));
- if (slot.getHasStack()) {
- String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(slot.getStack().getTagCompound());
- for (String line : lore) {
- if (line.contains("You already rerolled a chest!")) {
- kismetUsed = true;
- break;
- }
- }
- }
- int kismetPrice = neu.manager.auctionManager.getLowestBin("KISMET_FEATHER");
- String kismetStr = EnumChatFormatting.RED + format.format(kismetPrice) + " coins";
- if (neu.config.dungeons.useKismetOnDungeonProfit)
- profitLossBIN = kismetUsed ? profitLossBIN - kismetPrice : profitLossBIN;
-
- String profitPrefix = EnumChatFormatting.DARK_GREEN.toString();
- String lossPrefix = EnumChatFormatting.RED.toString();
- String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix;
-
- String plStringBIN;
- if (profitLossBIN >= 0) {
- plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins";
- } else {
- plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins";
- }
-
- if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) {
- int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN);
- GlStateManager.disableLighting();
- GlStateManager.translate(0, 0, 200);
- Minecraft.getMinecraft().fontRendererObj.drawString(plStringBIN, guiLeft + xSize - 5 - w, guiTop + 5,
- 0xffffffff, true
- );
- GlStateManager.translate(0, 0, -200);
- return;
- }
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth);
- GL11.glColor4f(1, 1, 1, 1);
- GlStateManager.disableLighting();
- Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST);
-
- Utils.renderAlignedString(valueStringBIN1, valueStringBIN2,
- guiLeft + xSize + 4 + 10, guiTop + 14, 160
- );
- if (neu.config.dungeons.useKismetOnDungeonProfit && kismetUsed) {
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Kismet Feather: ", kismetStr,
- guiLeft + xSize + 4 + 10, guiTop + 24, 160
- );
- }
- if (totalValue >= 0) {
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Profit/Loss: ",
- plStringBIN,
- guiLeft + xSize + 4 + 10,
- guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 34 : 24) : 24),
- 160
- );
- }
-
- int index = 0;
- for (Map.Entry<String, Float> entry : itemValues.entrySet()) {
- Utils.renderAlignedString(
- entry.getKey(),
- prefix +
- format.format(entry.getValue().intValue()),
- guiLeft + xSize + 4 + 10,
- guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 39 : 29) : 29) + (++index) * 10,
- 160
- );
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
-
- public void drawStringShadow(String str, float x, float y, int len) {
- for (int xOff = -2; xOff <= 2; xOff++) {
- for (int yOff = -2; yOff <= 2; yOff++) {
- if (Math.abs(xOff) != Math.abs(yOff)) {
- Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str),
- Minecraft.getMinecraft().fontRendererObj,
- x + xOff / 2f, y + yOff / 2f, false, len,
- new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB()
- );
- }
- }
- }
-
- Utils.drawStringCenteredScaledMaxWidth(str,
- Minecraft.getMinecraft().fontRendererObj,
- x, y, false, len,
- new Color(64, 64, 64, 255).getRGB()
- );
- }
-
- /**
- * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused.
- * Will also cancel the event if if NEUOverlay#mouseInput returns true.
- */
- @SubscribeEvent(priority = EventPriority.LOW)
- public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
- if (Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) {
- event.setCanceled(true);
- return;
- }
-
- final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- final int scaledWidth = scaledresolution.getScaledWidth();
- final int scaledHeight = scaledresolution.getScaledHeight();
- int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
- int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
-
- if (AuctionBINWarning.getInstance().shouldShow()) {
- AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY);
- event.setCanceled(true);
- return;
- }
-
- if (!event.isCanceled()) {
- Utils.scrollTooltip(Mouse.getEventDWheel());
- }
- if (AuctionSearchOverlay.shouldReplace()) {
- AuctionSearchOverlay.mouseEvent();
- event.setCanceled(true);
- return;
- }
- if (RancherBootOverlay.shouldReplace()) {
- RancherBootOverlay.mouseEvent();
- event.setCanceled(true);
- return;
- }
-
- String containerName = null;
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) guiScreen;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
- if (containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 &&
- eventGui.isMouseOverSlot(cc.inventorySlots.get(BetterContainers.profileViewerStackIndex), mouseX, mouseY) &&
- Mouse.getEventButton() >= 0) {
- event.setCanceled(true);
- if (Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null &&
- eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null) {
- NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound();
- if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) {
- String username = tag.getCompoundTag("SkullOwner").getString("Name");
- Utils.playPressSound();
- ViewProfileCommand.RUNNABLE.accept(new String[]{username});
- }
- }
- }
- }
-
- if (GuiCustomEnchant.getInstance().shouldOverride(containerName) &&
- GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) {
- event.setCanceled(true);
- return;
- }
-
- boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
- boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
- boolean customAhActive =
- event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
-
- if (storageOverlayActive) {
- if (StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) {
- event.setCanceled(true);
- }
- return;
- }
-
- if (tradeWindowActive || customAhActive) {
- event.setCanceled(true);
- if (customAhActive) {
- neu.manager.auctionManager.customAH.handleMouseInput();
- } else if (tradeWindowActive) {
- TradeWindow.handleMouseInput();
- }
- neu.overlay.mouseInput();
- return;
- }
-
- if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
- if (!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) {
- if (!(hoverInv && focusInv)) {
- if (neu.overlay.mouseInput()) {
- event.setCanceled(true);
- }
- } else {
- neu.overlay.mouseInputInv();
- }
- }
- }
- if (event.isCanceled()) return;
- if (!doInventoryButtons) return;
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && shouldRenderOverlay(event.gui) &&
- Mouse.getEventButton() >= 0
- && event.gui instanceof GuiContainer) {
- int xSize = ((GuiContainer) event.gui).xSize;
- int ySize = ((GuiContainer) event.gui).ySize;
- int guiLeft = ((GuiContainer) event.gui).guiLeft;
- int guiTop = ((GuiContainer) event.gui).guiTop;
- if (!NEUApi.disableInventoryButtons) {
- for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
- if (!button.isActive()) continue;
- if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
-
- int x = guiLeft + button.x;
- int y = guiTop + button.y;
- if (button.anchorRight) {
- x += xSize;
- }
- if (button.anchorBottom) {
- y += ySize;
- }
- if (AccessoryBagOverlay.isInAccessoryBag()) {
- if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
- x += 80 + 28;
- }
- }
- if (NEUOverlay.isRenderingArmorHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
- x -= 25;
- }
- }
- if (NEUOverlay.isRenderingPetHud()) {
- if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
- x -= 25;
- }
- }
-
- if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) {
- if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
- int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType;
- if ((clickType == 0 && Mouse.getEventButtonState()) || (clickType == 1 && !Mouse.getEventButtonState())) {
- String command = button.command.trim();
- if (!command.startsWith("/")) {
- command = "/" + command;
- }
- if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) {
- NotEnoughUpdates.INSTANCE.sendChatMessage(command);
- }
- }
- } else {
- event.setCanceled(true);
- }
- return;
- }
- }
- }
- }
- }
-
- ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
-
- JsonObject essenceJson = new JsonObject();
-
- /**
- * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true.
- * Also includes a dev function used for creating custom named json files with recipes.
- */
- @SubscribeEvent
- public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
- if (AuctionBINWarning.getInstance().shouldShow()) {
- AuctionBINWarning.getInstance().keyboardInput();
- event.setCanceled(true);
- return;
- }
-
- if (AuctionSearchOverlay.shouldReplace()) {
- AuctionSearchOverlay.keyEvent();
- event.setCanceled(true);
- return;
- }
- if (RancherBootOverlay.shouldReplace()) {
- RancherBootOverlay.keyEvent();
- event.setCanceled(true);
- return;
- }
-
- String containerName = null;
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
-
- if (guiScreen instanceof GuiChest) {
- containerName = ((ContainerChest) ((GuiChest) guiScreen).inventorySlots)
- .getLowerChestInventory()
- .getDisplayName()
- .getUnformattedText();
- }
-
- if (GuiCustomEnchant.getInstance().shouldOverride(containerName) &&
- GuiCustomEnchant.getInstance().keyboardInput()) {
- event.setCanceled(true);
- return;
- }
-
- boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
- boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
- boolean customAhActive =
- event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
-
- if (storageOverlayActive) {
- if (StorageOverlay.getInstance().keyboardInput()) {
- event.setCanceled(true);
- return;
- }
- }
-
- if (tradeWindowActive || customAhActive) {
- if (customAhActive) {
- if (neu.manager.auctionManager.customAH.keyboardInput()) {
- event.setCanceled(true);
- Minecraft.getMinecraft().dispatchKeypresses();
- } else if (neu.overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
- }
- } else if (tradeWindowActive) {
- TradeWindow.keyboardInput();
- if (Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) {
- event.setCanceled(true);
- Minecraft.getMinecraft().dispatchKeypresses();
- neu.overlay.keyboardInput(focusInv);
- }
- }
- return;
- }
-
- if (shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
- if (neu.overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
- }
- }
- if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing &&
- Minecraft.getMinecraft().theWorld != null &&
- Keyboard.getEventKey() == Keyboard.KEY_N && Keyboard.getEventKeyState()) {
- GuiScreen gui = Minecraft.getMinecraft().currentScreen;
- if (gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) event.gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- if (!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return;
-
- for (int i = 0; i < lower.getSizeInventory(); i++) {
- ItemStack stack = lower.getStackInSlot(i);
-
- String internalname = neu.manager.getInternalNameForItem(stack);
- if (internalname != null) {
- String[] lore = neu.manager.getLoreFromNBT(stack.getTagCompound());
-
- for (String line : lore) {
- if (line.contains(":") && (line.startsWith("\u00A77Upgrade to") ||
- line.startsWith("\u00A77Convert to Dungeon Item"))) {
- String[] split = line.split(":");
- String after = Utils.cleanColour(split[1]);
- StringBuilder costS = new StringBuilder();
- for (char c : after.toCharArray()) {
- if (c >= '0' && c <= '9') {
- costS.append(c);
- }
- }
- int cost = Integer.parseInt(costS.toString());
- String[] afterSplit = after.split(" ");
- String type = afterSplit[afterSplit.length - 2];
-
- if (!essenceJson.has(internalname)) {
- essenceJson.add(internalname, new JsonObject());
- }
- JsonObject obj = essenceJson.get(internalname).getAsJsonObject();
- obj.addProperty("type", type);
-
- if (line.startsWith("\u00A77Convert to Dungeon Item")) {
- obj.addProperty("dungeonize", cost);
- } else if (line.startsWith("\u00A77Upgrade to")) {
- int stars = 0;
- for (char c : line.toCharArray()) {
- if (c == '\u272A') stars++;
- }
- if (stars > 0) {
- obj.addProperty(stars + "", cost);
- }
- }
- }
- }
- }
- }
- System.out.println(essenceJson);
- }
- }
- if (NotEnoughUpdates.INSTANCE.config.hidden.dev && NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing &&
- Minecraft.getMinecraft().theWorld != null &&
- Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) {
- GuiScreen gui = Minecraft.getMinecraft().currentScreen;
- if (gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) event.gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- if (lower.getStackInSlot(23) != null &&
- lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
- ItemStack res = lower.getStackInSlot(25);
- String resInternalname = neu.manager.getInternalNameForItem(res);
- JTextField tf = new JTextField();
- tf.setText(resInternalname);
- tf.addAncestorListener(new RequestFocusListener());
- JOptionPane.showOptionDialog(null,
- tf,
- "Enter Name:",
- JOptionPane.NO_OPTION,
- JOptionPane.PLAIN_MESSAGE,
- null, new String[]{"Enter"}, "Enter"
- );
- resInternalname = tf.getText();
- if (resInternalname.trim().length() == 0) {
- return;
- }
-
- JsonObject recipe = new JsonObject();
-
- String[] x = {"1", "2", "3"};
- String[] y = {"A", "B", "C"};
-
- for (int i = 0; i <= 18; i += 9) {
- for (int j = 0; j < 3; j++) {
- ItemStack stack = lower.getStackInSlot(10 + i + j);
- String internalname = "";
- if (stack != null) {
- internalname = neu.manager.getInternalNameForItem(stack);
- if (!neu.manager.getItemInformation().containsKey(internalname)) {
- neu.manager.writeItemToFile(stack);
- }
- internalname += ":" + stack.stackSize;
- }
- recipe.addProperty(y[i / 9] + x[j], internalname);
- }
- }
-
- JsonObject json = neu.manager.getJsonForItem(res);
- json.add("recipe", recipe);
- json.addProperty("internalname", resInternalname);
- json.addProperty("clickcommand", "viewrecipe");
- json.addProperty("modver", NotEnoughUpdates.VERSION);
- try {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
- neu.manager.writeJsonDefaultDir(json, resInternalname + ".json");
- neu.manager.loadItem(resInternalname);
- } catch (IOException ignored) {
- }
- }
- }
- }
- }
-
- private final HashSet<String> percentStats = new HashSet<>();
-
- {
- percentStats.add("bonus_attack_speed");
- percentStats.add("crit_damage");
- percentStats.add("crit_chance");
- percentStats.add("sea_creature_chance");
- percentStats.add("ability_damage");
- }
-
- private String currentRarity = "COMMON";
- private boolean showReforgeStoneStats = true;
- private boolean pressedArrowLast = false;
- private boolean pressedShiftLast = false;
-
- private boolean copied = false;
-
- //just to try and optimize it a bit
- private int sbaloaded = -1;
-
- private boolean isSbaloaded() {
- if (sbaloaded == -1) {
- if (Loader.isModLoaded("skyblockaddons")) {
- sbaloaded = 1;
- } else {
- sbaloaded = 0;
- }
- }
- return sbaloaded == 1;
- }
-
- @SubscribeEvent(priority = EventPriority.LOW)
- public void onItemTooltipLow(ItemTooltipEvent event) {
- if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return;
-
- String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
- if (internalname == null) {
- onItemToolTipInternalNameNull(event);
- return;
- }
-
- boolean hasEnchantments =
- event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("enchantments", 10);
- Set<String> enchantIds = new HashSet<>();
- if (hasEnchantments)
- enchantIds =
- event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet();
-
- JsonObject enchantsConst = Constants.ENCHANTS;
- JsonArray allItemEnchs = null;
- Set<String> ignoreFromPool = new HashSet<>();
- if (enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) {
- try {
- JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray();
- for (JsonElement element : enchantPools) {
- Set<String> currentPool = new HashSet<>();
- for (JsonElement poolElement : element.getAsJsonArray()) {
- String poolS = poolElement.getAsString();
- currentPool.add(poolS);
- }
- for (JsonElement poolElement : element.getAsJsonArray()) {
- String poolS = poolElement.getAsString();
- if (enchantIds.contains(poolS)) {
- ignoreFromPool.addAll(currentPool);
- break;
- }
- }
- }
-
- JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject();
- NBTTagCompound tag = event.itemStack.getTagCompound();
- if (tag != null) {
- NBTTagCompound display = tag.getCompoundTag("display");
- if (display.hasKey("Lore", 9)) {
- NBTTagList list = display.getTagList("Lore", 8);
- out:
- for (int i = list.tagCount(); i >= 0; i--) {
- String line = list.getStringTagAt(i);
- for (int j = 0; j < Utils.rarityArrC.length; j++) {
- for (Map.Entry<String, JsonElement> entry : enchantsObj.entrySet()) {
- if (line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) ||
- line.contains(Utils.rarityArrC[j] + " DUNGEON " + entry.getKey())) {
- allItemEnchs = entry.getValue().getAsJsonArray();
- break out;
- }
- }
- }
- }
- }
- }
- } catch (Exception ignored) {
- }
- }
-
- boolean gotToEnchants = false;
- boolean passedEnchants = false;
-
- boolean dungeonProfit = false;
- int index = 0;
- List<String> newTooltip = new ArrayList<>();
-
- for (String line : event.toolTip) {
- if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") &&
- NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) {
- JsonObject reforgeStones = Constants.REFORGESTONES;
-
- if (reforgeStones != null && reforgeStones.has(internalname)) {
- boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
- if (!pressedShiftLast && shift) {
- showReforgeStoneStats = !showReforgeStoneStats;
- }
- pressedShiftLast = shift;
-
- newTooltip.add(line);
- newTooltip.add("");
- if (!showReforgeStoneStats) {
- newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to show extra info]");
- } else {
- newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to hide extra info]");
- }
-
- JsonObject reforgeInfo = reforgeStones.get(internalname).getAsJsonObject();
- JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray();
-
- if (showReforgeStoneStats && requiredRaritiesArray.size() > 0) {
- String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), "");
-
- String[] requiredRarities = new String[requiredRaritiesArray.size()];
- for (int i = 0; i < requiredRaritiesArray.size(); i++) {
- requiredRarities[i] = requiredRaritiesArray.get(i).getAsString();
- }
-
- int rarityIndex = requiredRarities.length - 1;
- String rarity = requiredRarities[rarityIndex];
- for (int i = 0; i < requiredRarities.length; i++) {
- String rar = requiredRarities[i];
- if (rar.equalsIgnoreCase(currentRarity)) {
- rarity = rar;
- rarityIndex = i;
- break;
- }
- }
-
- boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT);
- boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
- if (!pressedArrowLast && (left || right)) {
- if (left) {
- rarityIndex--;
- } else if (right) {
- rarityIndex++;
- }
- if (rarityIndex < 0) rarityIndex = 0;
- if (rarityIndex >= requiredRarities.length) rarityIndex = requiredRarities.length - 1;
- currentRarity = requiredRarities[rarityIndex];
- rarity = currentRarity;
- }
- pressedArrowLast = left || right;
-
- JsonElement statsE = reforgeInfo.get("reforgeStats");
-
- String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity);
-
- JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility");
- String reforgeAbility = null;
- if (reforgeAbilityE != null) {
- if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) {
- reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), "");
-
- } else if (reforgeAbilityE.isJsonObject()) {
- if (reforgeAbilityE.getAsJsonObject().has(rarity)) {
- reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString();
- }
- }
- }
-
- if (reforgeAbility != null && !reforgeAbility.isEmpty()) {
- String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") +
- EnumChatFormatting.GRAY + reforgeAbility;
- boolean first = true;
- for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) {
- newTooltip.add((first ? "" : " ") + s);
- first = false;
- }
- newTooltip.add("");
- }
-
- newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted +
- "\u00a79: [\u00a7l\u00a7m< \u00a79Switch\u00a7l\u27a1\u00a79]");
-
- if (statsE != null && statsE.isJsonObject()) {
- JsonObject stats = statsE.getAsJsonObject();
-
- JsonElement statsRarE = stats.get(rarity);
- if (statsRarE != null && statsRarE.isJsonObject()) {
-
- JsonObject statsRar = statsRarE.getAsJsonObject();
-
- TreeSet<Map.Entry<String, JsonElement>> sorted = new TreeSet<>(Map.Entry.comparingByKey());
- sorted.addAll(statsRar.entrySet());
-
- for (Map.Entry<String, JsonElement> entry : sorted) {
- if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) {
- float statNumF = entry.getValue().getAsFloat();
- String statNumS;
- if (statNumF % 1 == 0) {
- statNumS = String.valueOf(Math.round(statNumF));
- } else {
- statNumS = Utils.floatToString(statNumF, 1);
- }
- String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " "));
- String text =
- EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS;
- if (percentStats.contains(entry.getKey())) {
- text += "%";
- }
- newTooltip.add(" " + text);
- }
- }
- }
- }
-
- JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts");
- int reforgeCost = -1;
- if (reforgeCostsE != null) {
- if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) {
- reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1);
-
- } else if (reforgeCostsE.isJsonObject()) {
- if (reforgeCostsE.getAsJsonObject().has(rarity)) {
- reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1);
- }
- }
- }
-
- if (reforgeCost >= 0) {
- String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD +
- NumberFormat.getNumberInstance().format(reforgeCost) + " coins";
- newTooltip.add("");
- newTooltip.add(text);
- }
-
- }
-
- continue;
- }
-
- } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) {
- line = line.replace(
- "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune",
- Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE
- );
- } else if (hasEnchantments) {
- if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) &&
- NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) {
- boolean lineHasEnch = false;
- for (String s : enchantIds) {
- String enchantName = WordUtils.capitalizeFully(s.replace("_", " "));
- if (line.contains(enchantName)) {
- lineHasEnch = true;
- break;
- }
- }
- if (lineHasEnch) {
- gotToEnchants = true;
- } else {
- if (gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) {
- if (enchantsConst != null && allItemEnchs != null) {
- List<String> missing = new ArrayList<>();
- for (JsonElement enchIdElement : allItemEnchs) {
- String enchId = enchIdElement.getAsString();
- if (!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) &&
- !enchantIds.contains(enchId)) {
- missing.add(enchId);
- }
- }
- if (!missing.isEmpty()) {
- newTooltip.add("");
- StringBuilder currentLine =
- new StringBuilder(EnumChatFormatting.RED + "Missing: " + EnumChatFormatting.GRAY);
- for (int i = 0; i < missing.size(); i++) {
- String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " "));
- if (currentLine.length() != 0 &&
- (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) {
- newTooltip.add(currentLine.toString());
- currentLine = new StringBuilder();
- }
- if (currentLine.length() != 0 && i != 0) {
- currentLine.append(", ").append(enchName);
- } else {
- currentLine.append(EnumChatFormatting.GRAY).append(enchName);
- }
- }
- if (currentLine.length() != 0) {
- newTooltip.add(currentLine.toString());
- }
- }
- }
- passedEnchants = true;
- }
- }
- }
- for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) {
- List<String> colourOps = GuiEnchantColour.splitter.splitToList(op);
- String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0);
- String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1);
- String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2);
- String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3);
- String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4);
-
- int modifierI = GuiEnchantColour.getIntModifier(modifier);
-
- if (enchantName.length() == 0) continue;
- if (comparator.length() == 0) continue;
- if (comparison.length() == 0) continue;
- if (colourCode.length() == 0) continue;
-
- int comparatorI = ">=<".indexOf(comparator.charAt(0));
-
- int levelToFind = -1;
- try {
- levelToFind = Integer.parseInt(comparison);
- } catch (Exception e) {
- continue;
- }
-
- if (comparatorI < 0) continue;
- String regexText = "0123456789abcdefz";
- if (isSbaloaded()) {
- regexText = regexText + "Z";
- }
-
- if (regexText.indexOf(colourCode.charAt(0)) < 0) continue;
-
- //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1");
- //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$)
- Pattern pattern;
- try {
- pattern = Pattern.compile("(\\u00A79|\\u00A7(9|l)\\u00A7d\\u00A7l)(?<enchantName>" + enchantName + ") " +
- "(?<level>[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)");
- } catch (Exception e) {
- continue;
- } //malformed regex
- Matcher matcher = pattern.matcher(line);
- int matchCount = 0;
- while (matcher.find() && matchCount < 5) {
- if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue;
-
- matchCount++;
- int level = -1;
- String levelStr = matcher.group("level");
- if (levelStr == null) continue;
- try {
- level = Integer.parseInt(levelStr);
- } catch (Exception e) {
- switch (levelStr) {
- case "I":
- level = 1;
- break;
- case "II":
- level = 2;
- break;
- case "III":
- level = 3;
- break;
- case "IV":
- level = 4;
- break;
- case "V":
- level = 5;
- break;
- case "VI":
- level = 6;
- break;
- case "VII":
- level = 7;
- break;
- case "VIII":
- level = 8;
- break;
- case "IX":
- level = 9;
- break;
- case "X":
- level = 10;
- break;
- case "XI":
- level = 11;
- break;
- case "XII":
- level = 12;
- break;
- case "XIII":
- level = 13;
- break;
- case "XIV":
- level = 14;
- break;
- case "XV":
- level = 15;
- break;
- case "XVI":
- level = 16;
- break;
- case "XVII":
- level = 17;
- break;
- case "XVIII":
- level = 18;
- break;
- case "XIX":
- level = 19;
- break;
- case "XX":
- level = 20;
- break;
- }
- }
- boolean matches = false;
- if (level > 0) {
- switch (comparator) {
- case ">":
- matches = level > levelToFind;
- break;
- case "=":
- matches = level == levelToFind;
- break;
- case "<":
- matches = level < levelToFind;
- break;
- }
- }
- if (matches) {
- String enchantText = matcher.group("enchantName");
- StringBuilder extraModifiersBuilder = new StringBuilder();
-
- if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) {
- extraModifiersBuilder.append(EnumChatFormatting.BOLD);
- }
- if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) {
- extraModifiersBuilder.append(EnumChatFormatting.ITALIC);
- }
- if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) {
- extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE);
- }
- if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) {
- extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED);
- }
- if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) {
- extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH);
- }
-
- String extraMods = extraModifiersBuilder.toString();
-
- if (!colourCode.equals("z")) {
- line = line.replace(
- "\u00A79" + enchantText,
- "\u00A7" + colourCode + extraMods + enchantText
- );
- line = line.replace(
- "\u00A79\u00A7d\u00A7l" + enchantText,
- "\u00A7" + colourCode + extraMods + enchantText
- );
- line = line.replace(
- "\u00A7l\u00A7d\u00A7l" + enchantText,
- "\u00A7" + colourCode + extraMods + enchantText
- );
- } else {
- int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
- "\\u00A79" + enchantText + ".*", ""));
- line =
- line.replace("\u00A79" + enchantText, Utils.chromaString(enchantText, offset / 12f + index, false));
-
- offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
- "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*", ""));
- line = line.replace("\u00A79\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText,
- offset / 12f + index, true
- ));
- offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
- "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*", ""));
- line = line.replace("\u00A7l\u00A7d\u00A7l" + enchantText, Utils.chromaString(enchantText,
- offset / 12f + index, true
- ));
- }
- }
- }
- }
- }
-
- newTooltip.add(line);
-
- if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) {
- if (line.contains(EnumChatFormatting.GRAY + "Buy it now: ") ||
- line.contains(EnumChatFormatting.GRAY + "Bidder: ") ||
- line.contains(EnumChatFormatting.GRAY + "Starting bid: ")) {
-
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
- newTooltip.add("");
- newTooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]");
- } else {
- ItemPriceInformation.addToTooltip(newTooltip, internalname, event.itemStack);
- }
- }
- }
-
- if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 &&
- Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) {
- dungeonProfit = true;
- } else if (index == 7 && dungeonProfit) {
- GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- int chestCost = 0;
- try {
- String line6 = Utils.cleanColour(line);
- StringBuilder cost = new StringBuilder();
- for (int i = 0; i < line6.length(); i++) {
- char c = line6.charAt(i);
- if ("0123456789".indexOf(c) >= 0) {
- cost.append(c);
- }
- }
- if (cost.length() > 0) {
- chestCost = Integer.parseInt(cost.toString());
- }
- } catch (Exception ignored) {
- }
-
- String missingItem = null;
- int totalValue = 0;
- HashMap<String, Float> itemValues = new HashMap<>();
- for (int i = 0; i < 5; i++) {
- ItemStack item = lower.getStackInSlot(11 + i);
- String internal = neu.manager.getInternalNameForItem(item);
- if (internal != null) {
- internal = internal.replace("\u00CD", "I").replace("\u0130", "I");
- float bazaarPrice = -1;
- JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
- if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
- bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
- }
- if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000;
-
- float worth = -1;
- if (bazaarPrice > 0) {
- worth = bazaarPrice;
- } else {
- switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) {
- case 1:
- worth = neu.manager.auctionManager.getItemAvgBin(internal);
- break;
- case 2:
- JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
- if (auctionInfo != null) {
- if (auctionInfo.has("clean_price")) {
- worth = (int) auctionInfo.get("clean_price").getAsFloat();
- } else {
- worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- }
- }
- break;
- default:
- worth = neu.manager.auctionManager.getLowestBin(internal);
- }
- if (worth <= 0) {
- worth = neu.manager.auctionManager.getLowestBin(internal);
- if (worth <= 0) {
- worth = neu.manager.auctionManager.getItemAvgBin(internal);
- if (worth <= 0) {
- JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
- if (auctionInfo != null) {
- if (auctionInfo.has("clean_price")) {
- worth = (int) auctionInfo.get("clean_price").getAsFloat();
- } else {
- worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- }
- }
- }
- }
- }
- }
-
- if (worth > 0 && totalValue >= 0) {
- totalValue += worth;
-
- String display = item.getDisplayName();
-
- if (display.contains("Enchanted Book")) {
- NBTTagCompound tag = item.getTagCompound();
- if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
- NBTTagCompound enchants = ea.getCompoundTag("enchantments");
-
- int highestLevel = -1;
- for (String enchname : enchants.getKeySet()) {
- int level = enchants.getInteger(enchname);
- if (level > highestLevel) {
- display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(
- enchname.replace("_", " ")
- .replace("Ultimate", "")
- .trim()) + " " + level;
- }
- }
- }
- }
-
- itemValues.put(display, worth);
- } else {
- if (totalValue != -1) {
- missingItem = internal;
- }
- totalValue = -1;
- }
- }
- }
-
- NumberFormat format = NumberFormat.getInstance(Locale.US);
- String valueStringBIN1;
- String valueStringBIN2;
- if (totalValue >= 0) {
- valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): ";
- valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins";
- } else {
- valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: ";
- valueStringBIN2 = missingItem;
- }
-
- int profitLossBIN = totalValue - chestCost;
- String profitPrefix = EnumChatFormatting.DARK_GREEN.toString();
- String lossPrefix = EnumChatFormatting.RED.toString();
- String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix;
-
- String plStringBIN;
- if (profitLossBIN >= 0) {
- plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins";
- } else {
- plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins";
- }
-
- String neu = EnumChatFormatting.YELLOW + "[NEU] ";
-
- newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2);
- if (totalValue >= 0) {
- newTooltip.add(neu + EnumChatFormatting.YELLOW + "Profit/Loss: " + plStringBIN);
- }
-
- for (Map.Entry<String, Float> entry : itemValues.entrySet()) {
- newTooltip.add(neu + entry.getKey() + prefix + "+" +
- format.format(entry.getValue().intValue()));
- }
- }
- }
-
- index++;
- }
-
- for (int i = newTooltip.size() - 1; i >= 0; i--) {
- String line = Utils.cleanColour(newTooltip.get(i));
- for (int i1 = 0; i1 < Utils.rarityArr.length; i1++) {
- if (line.equals(Utils.rarityArr[i1])) {
- if (i - 2 < 0) {
- break;
- }
- newTooltip.addAll(i - 1, petToolTipXPExtend(event));
- break;
- }
- }
- }
-
- pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
- pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
-
- event.toolTip.clear();
- event.toolTip.addAll(newTooltip);
-
- HashMap<String, List<String>> loreBuckets = new HashMap<>();
-
- List<String> hypixelOrder = new ArrayList<>();
-
- hypixelOrder.add("attributes");
- hypixelOrder.add("enchants");
- hypixelOrder.add("ability");
- hypixelOrder.add("reforge_bonus");
- hypixelOrder.add("rarity");
-
- if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) {
- ItemPriceInformation.addToTooltip(event.toolTip, internalname, event.itemStack);
- }
-
- if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUHIDEPETTOOLTIP") &&
- NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) {
- event.toolTip.clear();
- }
- }
-
- private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))");
-
- private void onItemToolTipInternalNameNull(ItemTooltipEvent event) {
- petToolTipXPExtendPetMenu(event);
- }
-
- private List<String> petToolTipXPExtend(ItemTooltipEvent event) {
- List<String> tooltipText = new ArrayList<>();
- if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) {
- if (event.itemStack.getTagCompound().hasKey("DisablePetExp")) {
- if (event.itemStack.getTagCompound().getBoolean("DisablePetExp")) {
- return tooltipText;
- }
- }
- //7 is just a random number i chose, prob no pets with less lines than 7
- if (event.toolTip.size() > 7) {
- if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) {
-
- GuiProfileViewer.PetLevel petlevel = null;
-
- //this is the item itself
- NBTTagCompound tag = event.itemStack.getTagCompound();
- if (tag.hasKey("ExtraAttributes")) {
- if (tag.getCompoundTag("ExtraAttributes").hasKey("petInfo")) {
- JsonObject petInfo = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(
- tag.getCompoundTag("ExtraAttributes").getString("petInfo"), JsonObject.class);
- if (petInfo.has("exp") && petInfo.get("exp").isJsonPrimitive()) {
- JsonPrimitive exp = petInfo.getAsJsonPrimitive("exp");
- String petName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
- //Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip))).getAsInt();
- petlevel = GuiProfileViewer.getPetLevel(
- petName,
- Utils.getRarityFromInt(Utils.checkItemTypePet(event.toolTip)),
- exp.getAsLong()
- );
- }
- }
- }
-
- if (petlevel != null) {
- tooltipText.add("");
- if (petlevel.totalXp > petlevel.maxXP) {
- tooltipText.add(EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL");
- } else {
- tooltipText.add(
- EnumChatFormatting.GRAY + "Progress to Level " + (int) Math.floor(petlevel.level + 1) + ": " +
- EnumChatFormatting.YELLOW + Utils.round(petlevel.levelPercentage * 100, 1) + "%");
- int levelpercentage = Math.round(petlevel.levelPercentage * 20);
- tooltipText.add(
- EnumChatFormatting.DARK_GREEN + String.join("", Collections.nCopies(levelpercentage, "-")) +
- EnumChatFormatting.WHITE + String.join("", Collections.nCopies(20 - levelpercentage, "-")));
- tooltipText.add(
- EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) +
- EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW +
- myFormatter.format(petlevel.currentLevelRequirement) + " EXP");
- }
- }
- }
- }
- }
- return tooltipText;
- }
-
- private static final String petToolTipRegex =
- "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*";
-
- private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) {
- if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) {
- //7 is just a random number i chose, prob no pets with less lines than 7
- if (event.toolTip.size() > 7) {
- if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) {
- GuiProfileViewer.PetLevel petlevel = null;
-
- int xpLine = -1;
- for (int i = event.toolTip.size() - 1; i >= 0; i--) {
- Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i));
- if (matcher.matches()) {
- xpLine = i;
- event.toolTip.set(xpLine, matcher.group(1));
- break;
- } else if (event.toolTip.get(i).matches("MAX LEVEL")) {
- return;
- }
- }
-
- PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack(
- event.itemStack.getDisplayName(),
- NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(event.itemStack.getTagCompound())
- );
- if (pet == null) {
- return;
- }
- petlevel = pet.petLevel;
-
- if (petlevel == null || xpLine == -1) {
- return;
- }
-
- event.toolTip.add(
- xpLine + 1,
- EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petlevel.levelXp) +
- EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW +
- myFormatter.format(petlevel.currentLevelRequirement)
- );
-
- }
- }
- }
- }
-
- DecimalFormat myFormatter = new DecimalFormat("###,###.###");
-
- /**
- * This method does the following:
- * Move the pet inventory display tooltip to the left to avoid conflicts
- * Remove reforge stats for Legendary items from Hypixel if enabled
- * Show NBT data when holding LCONTROL
- */
- @SubscribeEvent
- public void onItemTooltip(ItemTooltipEvent event) {
- if (!neu.isOnSkyblock()) return;
- if (event.toolTip == null) return;
- //Render the pet inventory display tooltip to the left to avoid things from other mods rendering over the tooltip
- if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUPETINVDISPLAY")) {
- GlStateManager.translate(-200, 0, 0);
- }
-
- if (event.toolTip.size() > 2 && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.hideDefaultReforgeStats) {
- String secondLine = StringUtils.stripControlCodes(event.toolTip.get(1));
- if (secondLine.equals("Reforge Stone")) {
- Integer startIndex = null;
- Integer cutoffIndex = null;
- //loop from the back of the List to find the wanted index sooner
- for (int i = event.toolTip.size() - 1; i >= 0; i--) {
- //rarity or mining level requirement
- String line = StringUtils.stripControlCodes(event.toolTip.get(i));
- if (line.contains("REFORGE STONE") || line.contains("Requires Mining Skill Level")) {
- cutoffIndex = i;
- }
-
- //The line where the Hypixel stats start
- if (line.contains("(Legendary):")) {
- startIndex = i;
- break;
- }
- }
- if (startIndex != null && cutoffIndex != null && startIndex < cutoffIndex) {
- event.toolTip.subList(startIndex, cutoffIndex).clear();
- }
- }
- }
-
- if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev &&
- event.toolTip.size() > 0 &&
- event.toolTip.get(event.toolTip.size() - 1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) {
- event.toolTip.remove(event.toolTip.size() - 1);
-
- StringBuilder sb = new StringBuilder();
- String nbt = event.itemStack.getTagCompound().toString();
- int indent = 0;
- for (char c : nbt.toCharArray()) {
- boolean newline = false;
- if (c == '{' || c == '[') {
- indent++;
- newline = true;
- } else if (c == '}' || c == ']') {
- indent--;
- sb.append("\n");
- for (int i = 0; i < indent; i++) sb.append(" ");
- } else if (c == ',') {
- newline = true;
- } else if (c == '\"') {
- sb.append(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY);
- }
-
- sb.append(c);
- if (newline) {
- sb.append("\n");
- for (int i = 0; i < indent; i++) sb.append(" ");
- }
- }
- event.toolTip.add(sb.toString());
- if (Keyboard.isKeyDown(Keyboard.KEY_H)) {
- if (!copied) {
- copied = true;
- StringSelection selection = new StringSelection(sb.toString());
- Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
- }
- } else {
- copied = false;
- }
- } else if (NotEnoughUpdates.INSTANCE.packDevEnabled) {
- event.toolTip.add("");
- event.toolTip.add(EnumChatFormatting.AQUA + "NEU Pack Dev Info:");
- event.toolTip.add("Press " + EnumChatFormatting.GOLD + "[KEY]" + EnumChatFormatting.GRAY + " to copy line");
-
- String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
-
- boolean k = Keyboard.isKeyDown(Keyboard.KEY_K);
- boolean m = Keyboard.isKeyDown(Keyboard.KEY_M);
- boolean n = Keyboard.isKeyDown(Keyboard.KEY_N);
-
- event.toolTip.add(
- EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD +
- " [K]");
- if (!copied && k) {
- MiscUtils.copyToClipboard(internal);
- }
-
- if (event.itemStack.getTagCompound() != null) {
- NBTTagCompound tag = event.itemStack.getTagCompound();
-
- if (tag.hasKey("SkullOwner", 10)) {
- GameProfile gameprofile = NBTUtil.readGameProfileFromNBT(tag.getCompoundTag("SkullOwner"));
-
- if (gameprofile != null) {
- event.toolTip.add(EnumChatFormatting.AQUA + "Skull UUID: " + EnumChatFormatting.GRAY + gameprofile.getId() +
- EnumChatFormatting.GOLD + " [M]");
- if (!copied && m) {
- MiscUtils.copyToClipboard(gameprofile.getId().toString());
- }
-
- Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> map =
- Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile);
-
- if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) {
- MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN);
- event.toolTip.add(
- EnumChatFormatting.AQUA + "Skull Texture Link: " + EnumChatFormatting.GRAY + profTex.getUrl() +
- EnumChatFormatting.GOLD + " [N]");
-
- if (!copied && n) {
- MiscUtils.copyToClipboard(profTex.getUrl());
- }
- }
- }
- }
- }
-
- copied = k || m || n;
- }
- }
-
- @SubscribeEvent
- public void onRenderLast(RenderWorldLastEvent event) {
- CrystalMetalDetectorSolver.render(event.partialTicks);
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index df31834f..598ecc2e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -1,14 +1,46 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates;
-import com.google.gson.*;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.auction.APIManager;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
import io.github.moulberry.notenoughupdates.miscgui.KatSitterOverlay;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay;
import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe;
import io.github.moulberry.notenoughupdates.recipes.Ingredient;
import io.github.moulberry.notenoughupdates.recipes.NeuRecipe;
-import io.github.moulberry.notenoughupdates.util.*;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.HotmInformation;
+import io.github.moulberry.notenoughupdates.util.ApiUtil;
+import io.github.moulberry.notenoughupdates.util.ItemResolutionQuery;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.init.Blocks;
@@ -16,23 +48,48 @@ import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.*;
+import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.JsonToNBT;
+import net.minecraft.nbt.NBTException;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.fml.common.ProgressManager;
import org.apache.commons.io.FileUtils;
import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.Display;
-import javax.swing.JDialog;
-import javax.swing.JOptionPane;
-import java.io.*;
+import javax.net.ssl.HttpsURLConnection;
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.Optional;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -43,6 +100,7 @@ public class NEUManager {
public final APIManager auctionManager;
private final TreeMap<String, JsonObject> itemMap = new TreeMap<>();
+ private boolean hasBeenLoadedBefore = false;
private final TreeMap<String, HashMap<String, List<Integer>>> titleWordMap = new TreeMap<>();
private final TreeMap<String, HashMap<String, List<Integer>>> loreWordMap = new TreeMap<>();
@@ -66,18 +124,10 @@ public class NEUManager {
public String viewItemAttemptID = null;
public long viewItemAttemptTime = 0;
- private final String currentProfile = "";
- private final String currentProfileBackup = "";
- public final HypixelApi hypixelApi = new HypixelApi();
+ public final ApiUtil apiUtils = new ApiUtil();
private final Map<String, ItemStack> itemstackCache = new HashMap<>();
- private final ExecutorService repoLoaderES = Executors.newSingleThreadExecutor();
-
- private static String GIT_COMMITS_URL;
-
- // TODO: private final Map<String, NeuItem>
-
private final Set<NeuRecipe> recipes = new HashSet<>();
private final HashMap<String, Set<NeuRecipe>> recipesMap = new HashMap<>();
private final HashMap<String, Set<NeuRecipe>> usagesMap = new HashMap<>();
@@ -101,8 +151,6 @@ public class NEUManager {
this.craftingOverlay = new CraftingOverlay(this);
this.katSitterOverlay = new KatSitterOverlay();
- GIT_COMMITS_URL = neu.config.hidden.repoCommitsURL;
-
gson = new GsonBuilder().setPrettyPrinting().create();
this.repoLocation = new File(configLocation, "repo");
@@ -159,186 +207,74 @@ public class NEUManager {
}
}
- /**
- * Called when the game is first loaded. Compares the local repository to the github repository and handles the
- * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository.
- */
- public void loadItemInformation() {
- /*File repoFile = new File(configLocation, "repo2");
- repoFile.mkdirs();
-
- try(Git git = Git.init().setDirectory(repoFile).call()) {
- StoredConfig config = git.getRepository().getConfig();
- config.setString("branch", "master", "merge", "refs/heads/master");
- config.setString("branch", "master", "remote", "origin");
- config.setString("remote", "origin", "fetch", "+refs/heads/*:refs/remotes/origin/*");
- config.setString("remote", "origin", "url", "https://github.com/Moulberry/NotEnoughUpdates-REPO.git");
- config.save();
-
- git.remoteAdd().setName("origin").setUri(new URIish("https://github.com/Moulberry/NotEnoughUpdates-REPO.git")).call();
- PullResult result = git.pull().setRemote("origin").setTimeout(30000).call();
- System.out.println("successful pull: " + result.isSuccessful());
- } catch(Exception e) {
- e.printStackTrace();
- }*/
-
- /*if(repoFile.mkdirs()) {
- try {
- Git.cloneRepository()
- .setURI("https://github.com/Moulberry/NotEnoughUpdates-REPO.git")
- .setDirectory(repoFile)
- .call();
- } catch(Exception e) {
- e.printStackTrace();
- }
- } else {
-
- }*/
-
- repoLoaderES.submit(() -> {
- JDialog dialog = null;
+ public CompletableFuture<Boolean> fetchRepository() {
+ return CompletableFuture.supplyAsync(() -> {
try {
- if (NotEnoughUpdates.INSTANCE.config.hidden.autoupdate) {
- JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
- dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
- dialog.setModal(false);
- if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true);
-
- if (Display.isActive()) dialog.toFront();
-
- JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json"));
-
- latestRepoCommit = null;
- try (Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) {
- JsonObject commits = gson.fromJson(inReader, JsonObject.class);
- latestRepoCommit = commits.get("sha").getAsString();
- } catch (Exception e) {
- e.printStackTrace();
- }
- if (latestRepoCommit == null || latestRepoCommit.isEmpty()) return;
+ JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json"));
+
+ latestRepoCommit = null;
+ try (Reader inReader = new InputStreamReader(new URL(neu.config.apiData.getCommitApiUrl()).openStream())) {
+ JsonObject commits = gson.fromJson(inReader, JsonObject.class);
+ latestRepoCommit = commits.get("sha").getAsString();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (latestRepoCommit == null || latestRepoCommit.isEmpty()) return false;
- if (new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) {
- if (currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
- dialog.setVisible(false);
- return;
- }
+ if (new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) {
+ if (currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
+ return false;
}
+ }
+ Utils.recursiveDelete(repoLocation);
+ repoLocation.mkdirs();
- if (Display.isActive()) dialog.toFront();
-
- Utils.recursiveDelete(repoLocation);
- repoLocation.mkdirs();
+ File itemsZip = new File(repoLocation, "neu-items-master.zip");
+ try {
+ itemsZip.createNewFile();
+ } catch (IOException e) {
+ return false;
+ }
- String dlUrl = neu.config.hidden.repoURL;
+ URL url = new URL(neu.config.apiData.getDownloadUrl(latestRepoCommit));
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setConnectTimeout(15000);
+ urlConnection.setReadTimeout(30000);
+
+ try (InputStream is = urlConnection.getInputStream()) {
+ FileUtils.copyInputStreamToFile(is, itemsZip);
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator");
+ return false;
+ }
- pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
- dialog.pack();
- if (NotEnoughUpdates.INSTANCE.config.hidden.dev) dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
+ unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath());
- File itemsZip = new File(repoLocation, "neu-items-master.zip");
+ if (currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
+ JsonObject newCurrentCommitJSON = new JsonObject();
+ newCurrentCommitJSON.addProperty("sha", latestRepoCommit);
try {
- itemsZip.createNewFile();
- } catch (IOException e) {
- return;
- }
-
- URL url = new URL(dlUrl);
- URLConnection urlConnection = url.openConnection();
- urlConnection.setConnectTimeout(15000);
- urlConnection.setReadTimeout(30000);
-
- try (InputStream is = urlConnection.getInputStream()) {
- FileUtils.copyInputStreamToFile(is, itemsZip);
- } catch (IOException e) {
- dialog.dispose();
- e.printStackTrace();
- System.err.println("Failed to download NEU Repo! Please report this issue to the mod creator");
- return;
- }
- /*try (
- BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream());
- FileOutputStream fileOutputStream = new FileOutputStream(itemsZip)
- ) {
- byte dataBuffer[] = new byte[1024];
- int bytesRead;
- while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
- fileOutputStream.write(dataBuffer, 0, bytesRead);
- }
- } catch (IOException e) {
- dialog.dispose();
- return;
- }*/
-
- pane.setMessage("Unzipping NEU Master Archive.");
- dialog.pack();
- //dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
-
- unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath());
-
- if (currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
- JsonObject newCurrentCommitJSON = new JsonObject();
- newCurrentCommitJSON.addProperty("sha", latestRepoCommit);
- try {
- writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json"));
- } catch (IOException ignored) {
- }
+ writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json"));
+ } catch (IOException ignored) {
}
}
} catch (Exception e) {
e.printStackTrace();
- } finally {
- if (dialog != null) dialog.dispose();
- }
-
- File items = new File(repoLocation, "items");
- if (items.exists()) {
- File[] itemFiles = new File(repoLocation, "items").listFiles();
- if (itemFiles != null) {
- ProgressManager.ProgressBar bar = ProgressManager.push("Loading recipes", itemFiles.length);
- for (File f : itemFiles) {
- String internalname = f.getName().substring(0, f.getName().length() - 5);
- bar.step(internalname);
- synchronized (itemMap) {
- if (!itemMap.containsKey(internalname)) {
- loadItem(internalname);
- }
- }
- }
- ProgressManager.pop(bar);
- }
- }
-
- try {
- Constants.reload();
- } catch (Exception e) {
- e.printStackTrace();
}
+ return true;
});
+ }
- File items = new File(repoLocation, "items");
- if (items.exists()) {
- File[] itemFiles = new File(repoLocation, "items").listFiles();
- if (itemFiles != null) {
- ProgressManager.ProgressBar bar = ProgressManager.push("Loading items", itemFiles.length);
- for (File f : itemFiles) {
- String internalname = f.getName().substring(0, f.getName().length() - 5);
- bar.step(internalname);
- synchronized (itemMap) {
- if (!itemMap.containsKey(internalname)) {
- loadItem(internalname);
- }
- }
- }
- ProgressManager.pop(bar);
- }
- }
-
- try {
- Constants.reload();
- } catch (Exception e) {
- e.printStackTrace();
+ /**
+ * Called when the game is first loaded. Compares the local repository to the github repository and handles the
+ * downloading of new/updated files. This then calls the "loadItem" method for every item in the local repository.
+ */
+ public void loadItemInformation() {
+ if (NotEnoughUpdates.INSTANCE.config.apiData.autoupdate) {
+ fetchRepository().thenRun(this::reloadRepository);
+ } else {
+ reloadRepository();
}
}
@@ -435,6 +371,10 @@ public class NEUManager {
for (Ingredient input : recipe.getIngredients()) {
usagesMap.computeIfAbsent(input.getInternalItemId(), ignored -> new HashSet<>()).add(recipe);
}
+ for (Ingredient catalystItem : recipe.getCatalystItems()) {
+ recipesMap.computeIfAbsent(catalystItem.getInternalItemId(), ignored -> new HashSet<>()).add(recipe);
+ usagesMap.computeIfAbsent(catalystItem.getInternalItemId(), ignored -> new HashSet<>()).add(recipe);
+ }
}
public Set<NeuRecipe> getRecipesFor(String internalName) {
@@ -453,29 +393,94 @@ public class NEUManager {
return getUsagesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList());
}
+ private static class DebugMatch {
+ int index;
+ String match;
+
+ DebugMatch(int index, String match) {
+ this.index = index;
+ this.match = match;
+ }
+ }
+
+
+ private String searchDebug(String[] searchArray, ArrayList<DebugMatch> debugMatches) {
+ //splitToSearch, debugMatches and query
+ final String ANSI_RED = "\u001B[31m";
+ final String ANSI_RESET = "\u001B[0m";
+ final String ANSI_YELLOW = "\u001B[33m";
+
+ //create debug message
+ StringBuilder debugBuilder = new StringBuilder();
+ for (int i = 0; i < searchArray.length; i++) {
+ final int fi = i;
+ Object[] matches = debugMatches.stream().filter((d) -> d.index == fi).toArray();
+
+ if (matches.length > 0) {
+ debugBuilder.append(ANSI_YELLOW + "[").append(((DebugMatch) matches[0]).match).append("]");
+ debugBuilder.append(ANSI_RED + "[").append(searchArray[i]).append("]").append(ANSI_RESET).append(" ");
+ } else {
+ debugBuilder.append(searchArray[i]).append(" ");
+ }
+ }
+
+ //yellow = query match and red = string match
+ return debugBuilder.toString();
+ }
+
/**
* Searches a string for a query. This method is used to mimic the behaviour of the more complex map-based search
* function. This method is used for the chest-item-search feature.
*/
public boolean searchString(String toSearch, String query) {
- int lastMatch = -1;
+ final String ANSI_RESET = "\u001B[0m";
+ final String ANSI_YELLOW = "\u001B[33m";
+
+ int lastStringMatch = -1;
+ ArrayList<DebugMatch> debugMatches = new ArrayList<>();
toSearch = clean(toSearch).toLowerCase();
query = clean(query).toLowerCase();
- String[] splitToSeach = toSearch.split(" ");
- out:
- for (String s : query.split(" ")) {
- for (int i = 0; i < splitToSeach.length; i++) {
- if (!(lastMatch == -1 || lastMatch == i - 1)) continue;
- if (splitToSeach[i].startsWith(s)) {
- lastMatch = i;
- continue out;
+ String[] splitToSearch = toSearch.split(" ");
+ String[] queryArray = query.split(" ");
+
+ {
+ String currentSearch = queryArray[0];
+ int queryIndex = 0;
+ boolean matchedLastQueryItem = false;
+
+ for (int k = 0; k < splitToSearch.length; k++) {
+ if (queryIndex - 1 != -1 && (queryArray.length - queryIndex) > (splitToSearch.length - k)) continue;
+ if (splitToSearch[k].startsWith(currentSearch)) {
+ if (((lastStringMatch != -1 ? lastStringMatch : k-1) == k-1)) {
+ debugMatches.add(new DebugMatch(k, currentSearch));
+ lastStringMatch = k;
+ if (queryIndex+1 != queryArray.length) {
+ queryIndex++;
+ currentSearch = queryArray[queryIndex];
+ } else {
+ matchedLastQueryItem = true;
+ }
+ }
+ } else if (queryIndex != 0) {
+ queryIndex = 0;
+ currentSearch = queryArray[queryIndex];
+ lastStringMatch = -1;
}
}
- return false;
- }
- return true;
+ if (matchedLastQueryItem) {
+ if (NEUDebugFlag.SEARCH.isSet()) {
+ NotEnoughUpdates.LOGGER.info("Found match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + searchDebug(splitToSearch, debugMatches));
+ }
+ } else {
+ if (NEUDebugFlag.SEARCH.isSet() && lastStringMatch != -1) {
+ NotEnoughUpdates.LOGGER.info("Found partial match for \"" + ANSI_YELLOW + query + ANSI_RESET + "\":\n\t" + searchDebug(splitToSearch, debugMatches));
+ }
+ }
+
+ return matchedLastQueryItem;
+ }
}
/**
@@ -723,82 +728,35 @@ public class NEUManager {
return uuid;
}
- public String getInternalnameFromNBT(NBTTagCompound tag) {
- String internalname = null;
- if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
-
- if (ea.hasKey("id", 8)) {
- internalname = ea.getString("id").replaceAll(":", "-");
- } else {
- return null;
- }
-
- if ("PET".equals(internalname)) {
- String petInfo = ea.getString("petInfo");
- if (petInfo.length() > 0) {
- JsonObject petInfoObject = gson.fromJson(petInfo, JsonObject.class);
- internalname = petInfoObject.get("type").getAsString();
- String tier = petInfoObject.get("tier").getAsString();
- switch (tier) {
- case "COMMON":
- internalname += ";0";
- break;
- case "UNCOMMON":
- internalname += ";1";
- break;
- case "RARE":
- internalname += ";2";
- break;
- case "EPIC":
- internalname += ";3";
- break;
- case "LEGENDARY":
- internalname += ";4";
- break;
- case "MYTHIC":
- internalname += ";5";
- break;
- }
- }
- }
- if ("ENCHANTED_BOOK".equals(internalname) && ea.hasKey("enchantments", 10)) {
- NBTTagCompound enchants = ea.getCompoundTag("enchantments");
-
- for (String enchname : enchants.getKeySet()) {
- internalname = enchname.toUpperCase() + ";" + enchants.getInteger(enchname);
- break;
- }
- }
- if ("RUNE".equals(internalname) && ea.hasKey("runes", 10)) {
- NBTTagCompound rune = ea.getCompoundTag("runes");
-
- for (String runename : rune.getKeySet()) {
- internalname = runename.toUpperCase() + "_RUNE" + ";" + rune.getInteger(runename);
- break;
- }
- }
- if ("PARTY_HAT_CRAB".equals(internalname) && (ea.getString("party_hat_color") != null)) {
- String crabhat = ea.getString("party_hat_color");
- internalname = "PARTY_HAT_CRAB" + "_" + crabhat.toUpperCase();
+ public String getSkullValueFromNBT(NBTTagCompound tag) {
+ if (tag != null && tag.hasKey("SkullOwner", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("SkullOwner");
+ NBTTagCompound ea3 = tag.getCompoundTag("display");
+
+ if (ea.hasKey("Properties", 10)) {
+ NBTTagCompound ea2 = ea;
+ ea = ea.getCompoundTag("Properties");
+ ea = ea.getTagList("textures", 10).getCompoundTagAt(0);
+ String name = ea3.getString("Name").replaceAll(" M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$", "");
+ return "put(\"ID\", Utils.createSkull(EnumChatFormatting.AQUA + \"" + name + "\" ,\"" + ea2.getString("Id") +
+ "\", \"" + ea.getString("Value") + "\"));";
}
}
+ return null;
+ }
- return internalname;
+ /**
+ * Replaced with {@link #createItemResolutionQuery()}
+ */
+ @Deprecated
+ public String getInternalnameFromNBT(NBTTagCompound tag) {
+ return createItemResolutionQuery()
+ .withItemNBT(tag)
+ .resolveInternalName();
}
public String[] getLoreFromNBT(NBTTagCompound tag) {
- String[] lore = new String[0];
- NBTTagCompound display = tag.getCompoundTag("display");
-
- if (display.hasKey("Lore", 9)) {
- NBTTagList list = display.getTagList("Lore", 8);
- lore = new String[list.tagCount()];
- for (int k = 0; k < list.tagCount(); k++) {
- lore[k] = list.getStringTagAt(k);
- }
- }
- return lore;
+ return ItemUtils.getLore(tag).toArray(new String[0]);
}
public JsonObject getJsonFromNBT(NBTTagCompound tag) {
@@ -826,14 +784,14 @@ public class NEUManager {
if (itemMc != null) {
itemid = itemMc.getRegistryName();
}
- String displayname = display.getString("Name");
+ String displayName = display.getString("Name");
String[] info = new String[0];
String clickcommand = "";
JsonObject item = new JsonObject();
item.addProperty("internalname", internalname);
item.addProperty("itemid", itemid);
- item.addProperty("displayname", displayname);
+ item.addProperty("displayname", displayName);
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
@@ -894,12 +852,12 @@ public class NEUManager {
String clickcommand = item.get("clickcommand").getAsString();
switch (clickcommand.intern()) {
case "viewrecipe":
- displayGuiItemRecipe(internalName, null);
+ displayGuiItemRecipe(internalName);
break;
- case "viewoption":
+ case "viewpotion":
neu.sendChatMessage("/viewpotion " + internalName.split(";")[0].toLowerCase(Locale.ROOT));
}
- displayGuiItemRecipe(internalName, "");
+ displayGuiItemRecipe(internalName);
}
public void showRecipe(String internalName) {
@@ -952,10 +910,24 @@ public class NEUManager {
return json;
}
- public String getInternalNameForItem(ItemStack stack) {
+ public String getSkullValueForItem(ItemStack stack) {
if (stack == null) return null;
NBTTagCompound tag = stack.getTagCompound();
- return getInternalnameFromNBT(tag);
+ return getSkullValueFromNBT(tag);
+ }
+
+ public ItemResolutionQuery createItemResolutionQuery() {
+ return new ItemResolutionQuery(this);
+ }
+
+ /**
+ * Replaced with {@link #createItemResolutionQuery()}
+ */
+ @Deprecated
+ public String getInternalNameForItem(ItemStack stack) {
+ return createItemResolutionQuery()
+ .withItemStack(stack)
+ .resolveInternalName();
}
public String getUUIDForItem(ItemStack stack) {
@@ -988,17 +960,15 @@ public class NEUManager {
if (!usagesMap.containsKey(internalName)) return false;
List<NeuRecipe> usages = getAvailableUsagesFor(internalName);
if (usages.isEmpty()) return false;
- Minecraft.getMinecraft().displayGuiScreen(
- new GuiItemRecipe("Item Usages", usages, this));
+ NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(usages, this));
return true;
}
- public boolean displayGuiItemRecipe(String internalName, String text) {
+ public boolean displayGuiItemRecipe(String internalName) {
if (!recipesMap.containsKey(internalName)) return false;
List<NeuRecipe> recipes = getAvailableRecipesFor(internalName);
if (recipes.isEmpty()) return false;
- Minecraft.getMinecraft().displayGuiScreen(
- new GuiItemRecipe(text != null ? text : "Item Recipe", recipes, this));
+ NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(recipes, this));
return true;
}
@@ -1009,7 +979,7 @@ public class NEUManager {
public boolean failViewItem(String text) {
if (viewItemAttemptID != null && !viewItemAttemptID.isEmpty()) {
if (System.currentTimeMillis() - viewItemAttemptTime < 500) {
- return displayGuiItemRecipe(viewItemAttemptID, text);
+ return displayGuiItemRecipe(viewItemAttemptID);
}
}
return false;
@@ -1032,11 +1002,12 @@ public class NEUManager {
} catch (IOException e) {
return null;
}
- try (
- BufferedInputStream inStream = new BufferedInputStream(new URL(
- url + "?action=raw&templates=expand").openStream());
- FileOutputStream fileOutputStream = new FileOutputStream(f)
- ) {
+ try {
+ HttpsURLConnection con = (HttpsURLConnection) new URL(url + "?action=raw&templates=expand").openConnection();
+ con.setRequestMethod("GET");
+ con.setRequestProperty("User-Agent", "NotEnoughUpdates");
+ BufferedInputStream inStream = new BufferedInputStream(con.getInputStream());
+ FileOutputStream fileOutputStream = new FileOutputStream(f);
byte[] dataBuffer = new byte[1024];
int bytesRead;
while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
@@ -1149,7 +1120,7 @@ public class NEUManager {
* json files representing skyblock item data.
*/
public JsonObject createItemJson(
- String internalname, String itemid, String displayname, String[] lore,
+ String internalname, String itemid, String displayName, String[] lore,
String crafttext, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag
) {
@@ -1157,7 +1128,7 @@ public class NEUManager {
new JsonObject(),
internalname,
itemid,
- displayname,
+ displayName,
lore,
crafttext,
infoType,
@@ -1169,7 +1140,7 @@ public class NEUManager {
}
public JsonObject createItemJson(
- JsonObject base, String internalname, String itemid, String displayname, String[] lore,
+ JsonObject base, String internalname, String itemid, String displayName, String[] lore,
String crafttext, String infoType, String[] info,
String clickcommand, int damage, NBTTagCompound nbttag
) {
@@ -1180,7 +1151,7 @@ public class NEUManager {
JsonObject json = gson.fromJson(gson.toJson(base, JsonObject.class), JsonObject.class);
json.addProperty("internalname", internalname);
json.addProperty("itemid", itemid);
- json.addProperty("displayname", displayname);
+ json.addProperty("displayname", displayName);
json.addProperty("crafttext", crafttext);
json.addProperty("clickcommand", clickcommand);
json.addProperty("damage", damage);
@@ -1206,14 +1177,14 @@ public class NEUManager {
}
public boolean writeItemJson(
- String internalname, String itemid, String displayname, String[] lore, String crafttext,
+ String internalname, String itemid, String displayName, String[] lore, String crafttext,
String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag
) {
return writeItemJson(
new JsonObject(),
internalname,
itemid,
- displayname,
+ displayName,
lore,
crafttext,
infoType,
@@ -1225,14 +1196,14 @@ public class NEUManager {
}
public boolean writeItemJson(
- JsonObject base, String internalname, String itemid, String displayname, String[] lore,
+ JsonObject base, String internalname, String itemid, String displayName, String[] lore,
String crafttext, String infoType, String[] info, String clickcommand, int damage, NBTTagCompound nbttag
) {
JsonObject json = createItemJson(
base,
internalname,
itemid,
- displayname,
+ displayName,
lore,
crafttext,
infoType,
@@ -1294,7 +1265,7 @@ public class NEUManager {
}
}
- public HashMap<String, String> getLoreReplacements(String petname, String tier, int level) {
+ public HashMap<String, String> getPetLoreReplacements(String petname, String tier, int level) {
JsonObject petnums = null;
if (petname != null && tier != null) {
petnums = Constants.PETNUMS;
@@ -1407,7 +1378,7 @@ public class NEUManager {
float statMax = entry.getValue().getAsFloat();
float statMin = min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat();
float val = statMin * minMix + statMax * maxMix;
- String statStr = (statMin > 0 ? "+" : "") + (int) Math.floor(val);
+ String statStr = (statMin > 0 ? "+" : "") + removeUnusedDecimal(Math.floor(val * 10) / 10);
replacements.put(entry.getKey(), statStr);
}
}
@@ -1419,7 +1390,7 @@ public class NEUManager {
return replacements;
}
- public HashMap<String, String> getLoreReplacements(NBTTagCompound tag, int level) {
+ public HashMap<String, String> getPetLoreReplacements(NBTTagCompound tag, int level) {
String petname = null;
String tier = null;
if (tag != null && tag.hasKey("ExtraAttributes")) {
@@ -1453,7 +1424,7 @@ public class NEUManager {
}
}
}
- return getLoreReplacements(petname, tier, level);
+ return getPetLoreReplacements(petname, tier, level);
}
public NBTTagList processLore(JsonArray lore, HashMap<String, String> replacements) {
@@ -1484,6 +1455,7 @@ public class NEUManager {
}
public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements, boolean copyStack) {
+ if (useReplacements) useCache = false;
if (json == null) return new ItemStack(Items.painting, 1, 10);
String internalname = json.get("internalname").getAsString();
@@ -1523,13 +1495,13 @@ public class NEUManager {
HashMap<String, String> replacements = new HashMap<>();
if (useReplacements) {
- replacements = getLoreReplacements(stack.getTagCompound(), -1);
+ replacements = getPetLoreReplacements(stack.getTagCompound(), -1);
- String displayname = json.get("displayname").getAsString();
+ String displayName = json.get("displayname").getAsString();
for (Map.Entry<String, String> entry : replacements.entrySet()) {
- displayname = displayname.replace("{" + entry.getKey() + "}", entry.getValue());
+ displayName = displayName.replace("{" + entry.getKey() + "}", entry.getValue());
}
- stack.setStackDisplayName(displayname);
+ stack.setStackDisplayName(displayName);
}
if (json.has("lore")) {
@@ -1552,20 +1524,73 @@ public class NEUManager {
}
}
- public void reloadRepository() {
- File items = new File(repoLocation, "items");
- if (items.exists()) {
- recipes.clear();
- recipesMap.clear();
- usagesMap.clear();
+ public CompletableFuture<List<String>> userFacingRepositoryReload() {
+ String lastCommit = NotEnoughUpdates.INSTANCE.manager.latestRepoCommit;
+ NotEnoughUpdates.INSTANCE.manager.resetRepo();
+ return NotEnoughUpdates.INSTANCE.manager
+ .fetchRepository()
+ .thenCompose(ignored -> NotEnoughUpdates.INSTANCE.manager.reloadRepository())
+ .thenApply(ignored -> {
+ String newCommitHash = NotEnoughUpdates.INSTANCE.manager.latestRepoCommit;
+ String newCommitShortHash = (newCommitHash == null ? "MISSING" : newCommitHash.substring(0, 7));
+ return Arrays.asList(
+ "§aRepository reloaded.",
+ (lastCommit == null
+ ? "§eYou downloaded the repository version §b" + newCommitShortHash + "§e."
+ : "§eYou updated your repository from §b" + lastCommit.substring(0, 7) + "§e to §b" +
+ newCommitShortHash + "§e."
+ )
+ );
+ })
+ .exceptionally(ex -> {
+ ex.printStackTrace();
+ return Arrays.asList(
+ "§cRepository not fully reloaded.",
+ "§cThere was an error reloading your repository.",
+ "§cThis might be caused by an outdated version of neu",
+ "§c(or by not using the dangerous repository if you are using a prerelease of neu).",
+ "§aYour repository will still work, but is in a suboptimal state.",
+ "§eJoin §bdiscord.gg/moulberry §efor help."
+ );
+ });
+ }
- File[] itemFiles = new File(repoLocation, "items").listFiles();
- if (itemFiles != null) {
- for (File f : itemFiles) {
- String internalname = f.getName().substring(0, f.getName().length() - 5);
- loadItem(internalname);
+ public CompletableFuture<Void> reloadRepository() {
+ CompletableFuture<Void> comp = new CompletableFuture<>();
+ Minecraft.getMinecraft().addScheduledTask(() -> {
+ try {
+ File items = new File(repoLocation, "items");
+ if (items.exists()) {
+ recipes.clear();
+ recipesMap.clear();
+ usagesMap.clear();
+
+ File[] itemFiles = new File(repoLocation, "items").listFiles();
+ if (itemFiles != null) {
+ for (File f : itemFiles) {
+ String internalname = f.getName().substring(0, f.getName().length() - 5);
+ loadItem(internalname);
+ }
+ }
}
+
+ new RepositoryReloadEvent(repoLocation, !hasBeenLoadedBefore).post();
+ hasBeenLoadedBefore = true;
+ comp.complete(null);
+ } catch (Exception e) {
+ comp.completeExceptionally(e);
}
- }
+ });
+ return comp;
+ }
+
+ public ItemStack createItem(String internalName) {
+ return createItemResolutionQuery()
+ .withKnownInternalName(internalName)
+ .resolveToItemStack();
+ }
+
+ public boolean isValidInternalName(String internalName) {
+ return itemMap.containsKey(internalName);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
index d1bfed14..14078069 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates;
import com.google.common.collect.Lists;
@@ -16,23 +35,27 @@ import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupAligned;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating;
-import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu;
import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph;
+import io.github.moulberry.notenoughupdates.miscgui.NeuSearchCalculator;
import io.github.moulberry.notenoughupdates.options.NEUConfigEditor;
import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.GuiTextures;
import io.github.moulberry.notenoughupdates.util.LerpingFloat;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
-import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
-import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.gui.inventory.GuiContainer;
-import net.minecraft.client.gui.inventory.GuiInventory;
-import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
@@ -43,8 +66,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.init.Items;
-import net.minecraft.inventory.ContainerChest;
-import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@@ -62,82 +83,61 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.vector.Vector2f;
-import java.awt.Color;
+import java.awt.*;
import java.lang.reflect.InvocationTargetException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
-
public class NEUOverlay extends Gui {
- private static final ResourceLocation SUPERGEHEIMNISVERMOGEN =
- new ResourceLocation("notenoughupdates:supersecretassets/bald.png");
+ private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation(
+ "notenoughupdates:supersecretassets/bald.png");
+
+ private static final ResourceLocation ATMOULBERRYWHYISMYLUNARCLIENTBUGGING = new ResourceLocation(
+ "notenoughupdates:supersecretassets/lunar.png");
private static final ResourceLocation SEARCH_BAR = new ResourceLocation("notenoughupdates:search_bar.png");
private static final ResourceLocation SEARCH_BAR_GOLD = new ResourceLocation("notenoughupdates:search_bar_gold.png");
- private static final ResourceLocation ARMOR_DISPLAY =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay.png");
- private static final ResourceLocation ARMOR_DISPLAY_GREY =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay_grey.png");
- private static final ResourceLocation ARMOR_DISPLAY_DARK =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay_phq_dark.png");
- private static final ResourceLocation ARMOR_DISPLAY_FSR =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay_fsr.png");
- private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent.png");
- private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT_PET =
- new ResourceLocation("notenoughupdates:armordisplay/armordisplay_transparent_pet.png");
-
- private static final ResourceLocation QUESTION_MARK = new ResourceLocation("notenoughupdates:pv_unknown.png");
-
- private static final ResourceLocation PET_DISPLAY =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo.png");
- private static final ResourceLocation PET_DISPLAY_GREY =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_dark.png");
- private static final ResourceLocation PET_DISPLAY_DARK =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_phqdark.png");
- private static final ResourceLocation PET_DISPLAY_FSR =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_fsr.png");
- private static final ResourceLocation PET_DISPLAY_TRANSPARENT =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplaysolo_transparent.png");
-
- private static final ResourceLocation PET_ARMOR_DISPLAY =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor.png");
- private static final ResourceLocation PET_ARMOR_DISPLAY_GREY =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_dark.png");
- private static final ResourceLocation PET_ARMOR_DISPLAY_DARK =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_phqdark.png");
- private static final ResourceLocation PET_ARMOR_DISPLAY_FSR =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_fsr.png");
- private static final ResourceLocation PET_ARMOR_DISPLAY_TRANSPARENT =
- new ResourceLocation("notenoughupdates:petdisplay/petdisplayarmor_transparent.png");
-
- private static boolean renderingArmorHud;
- private static boolean renderingPetHud;
- public static boolean shouldUseCachedPet;
- public static long cachedPetTimer;
-
private final NEUManager manager;
- private final String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$";
+ private final String mobRegex = ".*?((_MONSTER)|(_NPC)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$";
private final String petRegex = ".*?;[0-5]$";
private final ResourceLocation[] sortIcons = new ResourceLocation[]{
- sort_all, sort_mob, sort_pet, sort_tool, sort_armor, sort_accessory
+ GuiTextures.sort_all,
+ GuiTextures.sort_mob,
+ GuiTextures.sort_pet,
+ GuiTextures.sort_tool,
+ GuiTextures.sort_armor,
+ GuiTextures.sort_accessory
};
private final ResourceLocation[] sortIconsActive = new ResourceLocation[]{
- sort_all_active, sort_mob_active, sort_pet_active, sort_tool_active, sort_armor_active, sort_accessory_active
+ GuiTextures.sort_all_active,
+ GuiTextures.sort_mob_active,
+ GuiTextures.sort_pet_active,
+ GuiTextures.sort_tool_active,
+ GuiTextures.sort_armor_active,
+ GuiTextures.sort_accessory_active
};
private final ResourceLocation[] orderIcons = new ResourceLocation[]{
- order_alphabetical, order_rarity, order_value
+ GuiTextures.order_alphabetical, GuiTextures.order_rarity, GuiTextures.order_value
};
private final ResourceLocation[] orderIconsActive = new ResourceLocation[]{
- order_alphabetical_active, order_rarity_active, order_value_active
+ GuiTextures.order_alphabetical_active, GuiTextures.order_rarity_active, GuiTextures.order_value_active
};
//Various constants used for GUI structure
@@ -166,6 +166,7 @@ public class NEUOverlay extends Gui {
private List<JsonObject> selectedItemGroup = null;
private boolean itemPaneOpen = false;
+ private long itemPaneShouldOpen = -1;
private int page = 0;
@@ -186,8 +187,8 @@ public class NEUOverlay extends Gui {
private boolean redrawItems = false;
- private boolean searchBarHasFocus = false;
- private final GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0);
+ public static boolean searchBarHasFocus = false;
+ private static final GuiTextField textField = new GuiTextField(0, null, 0, 0, 0, 0);
private static final int COMPARE_MODE_ALPHABETICAL = 0;
private static final int COMPARE_MODE_RARITY = 1;
@@ -241,15 +242,17 @@ public class NEUOverlay extends Gui {
}
if (Mouse.getEventButtonState()) {
setSearchBarFocus(true);
+
if (Mouse.getEventButton() == 1) { //Right mouse button down
textField.setText("");
updateSearch();
} else {
if (System.currentTimeMillis() - millisLastLeftClick < 300) {
searchMode = !searchMode;
+ itemPaneShouldOpen = -1;
lastSearchMode = System.currentTimeMillis();
if (searchMode && NotEnoughUpdates.INSTANCE.config.hidden.firstTimeSearchFocus) {
- NEUEventListener.displayNotification(Lists.newArrayList(
+ NotificationHandler.displayNotification(Lists.newArrayList(
"\u00a7eSearch Highlight",
"\u00a77In this mode NEU will gray out non matching items in",
"\u00a77your inventory or chests.",
@@ -328,7 +331,7 @@ public class NEUOverlay extends Gui {
}
//Search bar text
- fr.drawString(textField.getText(), (int) x + 5,
+ fr.drawString(NeuSearchCalculator.format(textField.getText()), (int) x + 5,
(int) y - 4 + getHeight() / 2, Color.WHITE.getRGB()
);
@@ -366,8 +369,7 @@ public class NEUOverlay extends Gui {
}
@Override
- public void recalculate() {
- }
+ public void recalculate() {}
};
}
@@ -384,8 +386,7 @@ public class NEUOverlay extends Gui {
}
@Override
- public void recalculate() {
- }
+ public void recalculate() {}
@Override
public void mouseClick(float x, float y, int mouseX, int mouseY) {
@@ -398,8 +399,7 @@ public class NEUOverlay extends Gui {
}
@Override
- public void mouseClickOutside() {
- }
+ public void mouseClickOutside() {}
@Override
public void render(float x, float y) {
@@ -409,13 +409,13 @@ public class NEUOverlay extends Gui {
if (!NotEnoughUpdates.INSTANCE.config.toolbar.enableSettingsButton) {
return;
}
- Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.quickcommand_background);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(x, y,
searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST
);
- Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.settings);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled,
searchYSize, searchYSize
@@ -439,8 +439,7 @@ public class NEUOverlay extends Gui {
}
@Override
- public void recalculate() {
- }
+ public void recalculate() {}
@Override
public void mouseClick(float x, float y, int mouseX, int mouseY) {
@@ -457,8 +456,7 @@ public class NEUOverlay extends Gui {
}
@Override
- public void mouseClickOutside() {
- }
+ public void mouseClickOutside() {}
@Override
public void render(float x, float y) {
@@ -469,13 +467,13 @@ public class NEUOverlay extends Gui {
return;
}
- Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.quickcommand_background);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(x, y,
searchYSize + paddingUnscaled * 2, searchYSize + paddingUnscaled * 2, GL11.GL_NEAREST
);
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.help);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect((int) x + paddingUnscaled, (int) y + paddingUnscaled,
getSearchBarYSize(), getSearchBarYSize()
@@ -499,16 +497,15 @@ public class NEUOverlay extends Gui {
}
@Override
- public void recalculate() {
- }
+ public void recalculate() {}
@Override
public void mouseClick(float x, float y, int mouseX, int mouseY) {
if (!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return;
+ if (EnchantingSolvers.disableButtons()) return;
if ((NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType != 0 && Mouse.getEventButtonState()) ||
- (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 &&
- !Mouse.getEventButtonState() &&
+ (NotEnoughUpdates.INSTANCE.config.toolbar.quickCommandsClickType == 0 && !Mouse.getEventButtonState() &&
Mouse.getEventButton() != -1)) {
if (quickCommandStr.contains(":")) {
String command = quickCommandStr.split(":")[0].trim();
@@ -523,12 +520,12 @@ public class NEUOverlay extends Gui {
}
@Override
- public void mouseClickOutside() {
- }
+ public void mouseClickOutside() {}
@Override
public void render(float x, float y) {
if (!NotEnoughUpdates.INSTANCE.config.toolbar.quickCommands) return;
+ if (EnchantingSolvers.disableButtons()) return;
int paddingUnscaled = getPaddingUnscaled();
int bigItemSize = getSearchBarYSize();
@@ -574,7 +571,7 @@ public class NEUOverlay extends Gui {
tag.setString("qc_id", quickCommandStrSplit[0].toLowerCase().trim());
render.setTagCompound(tag);
- Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.quickcommand_background);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(x, y,
bigItemSize + paddingUnscaled * 2, bigItemSize + paddingUnscaled * 2, GL11.GL_NEAREST
@@ -582,8 +579,7 @@ public class NEUOverlay extends Gui {
int mouseX = Mouse.getX() * Utils.peekGuiScale().getScaledWidth() / Minecraft.getMinecraft().displayWidth;
int mouseY = Utils.peekGuiScale().getScaledHeight() -
- Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight -
- 1;
+ Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1;
if (mouseX > x && mouseX < x + bigItemSize) {
if (mouseY > y && mouseY < y + bigItemSize) {
@@ -619,8 +615,11 @@ public class NEUOverlay extends Gui {
}
private MBGuiGroupAligned createSearchBarGroup() {
- List<MBGuiElement> children =
- Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this));
+ List<MBGuiElement> children = Lists.newArrayList(
+ createSettingsButton(this),
+ createSearchBar(),
+ createHelpButton(this)
+ );
return new MBGuiGroupAligned(children, false) {
public int getPadding() {
return getPaddingUnscaled() * 4;
@@ -714,19 +713,33 @@ public class NEUOverlay extends Gui {
public void showInfo(JsonObject item) {
if (item.has("info") && item.has("infoType")) {
JsonArray lore = item.get("info").getAsJsonArray();
- StringBuilder loreBuilder = new StringBuilder();
- for (int i = 0; i < lore.size(); i++) {
- loreBuilder.append(lore.get(i).getAsString());
- if (i != lore.size() - 1)
- loreBuilder.append("\n");
+ String infoType = item.get("infoType").getAsString();
+ String infoText = "";
+ if (infoType.equals("WIKI_URL")) {
+ for (JsonElement url : lore) {
+ infoText = url.getAsString();
+ if (
+ url.getAsString().startsWith("https://wiki.hypixel.net/") && NotEnoughUpdates.INSTANCE.config.misc.wiki == 0
+ || url.getAsString().startsWith("https://hypixel-skyblock.fandom.com/") &&
+ NotEnoughUpdates.INSTANCE.config.misc.wiki == 1) break;
+ }
+ } else {
+ StringBuilder loreBuilder = new StringBuilder();
+ for (int i = 0; i < lore.size(); i++) {
+ loreBuilder.append(lore.get(i).getAsString());
+ if (i != lore.size() - 1)
+ loreBuilder.append("\n");
+ }
+ infoText = loreBuilder.toString();
}
- String infoText = loreBuilder.toString();
String internalname = item.get("internalname").getAsString();
String name = item.get("displayname").getAsString();
- String infoType = item.get("infoType").getAsString();
- displayInformationPane(new TextInfoPane(this, manager, "Loading", "Loading your requested information about " +
- name +
- "."));
+ displayInformationPane(new TextInfoPane(
+ this,
+ manager,
+ EnumChatFormatting.GRAY + "Loading",
+ EnumChatFormatting.GRAY + "Loading your requested information about " + name + EnumChatFormatting.GRAY + "."
+ ));
infoPaneLoadingJob = InfoPane.create(this, manager, infoType, name, internalname, infoText)
.thenAccept(this::displayInformationPane);
}
@@ -740,7 +753,9 @@ public class NEUOverlay extends Gui {
if (slot != null) {
ItemStack hover = slot.getStack();
if (hover != null) {
- textField.setText("id:" + manager.getInternalNameForItem(hover));
+ if (manager.getInternalNameForItem(hover) != null) {
+ textField.setText("id:" + manager.getInternalNameForItem(hover));
+ }
itemPaneOpen = true;
updateSearch();
}
@@ -752,7 +767,7 @@ public class NEUOverlay extends Gui {
/**
* Handles the mouse input, cancelling the forge event if a NEU gui element is clicked.
*/
- public boolean mouseInput() {
+ public synchronized boolean mouseInput() {
if (disabled) {
return false;
}
@@ -785,6 +800,10 @@ public class NEUOverlay extends Gui {
if (selectedItemGroup != null) {
int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size());
if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) {
+ if (!Mouse.getEventButtonState()) {
+ Utils.pushGuiScale(-1);
+ return true; //End early if the mouse isn't pressed, but still cancel event.
+ }
for (int i = 0; i < selectedItemGroup.size(); i++) {
if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) {
JsonObject item = selectedItemGroup.get(i);
@@ -941,7 +960,7 @@ public class NEUOverlay extends Gui {
return paddingUnscaled;
}
- public GuiTextField getTextField() {
+ public static GuiTextField getTextField() {
return textField;
}
@@ -1006,7 +1025,6 @@ public class NEUOverlay extends Gui {
*/
public boolean keyboardInput(boolean hoverInv) {
if (Minecraft.getMinecraft().currentScreen == null) return false;
- Keyboard.enableRepeatEvents(true);
int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
@@ -1062,7 +1080,7 @@ public class NEUOverlay extends Gui {
internalname.set(manager.getInternalNameForItem(hover));
itemstack.set(hover);
}
- } else if (!hoverInv) {
+ } else {
Utils.pushGuiScale(NotEnoughUpdates.INSTANCE.config.itemlist.paneGuiScale);
int width = Utils.peekGuiScale().getScaledWidth();
@@ -1097,9 +1115,10 @@ public class NEUOverlay extends Gui {
}
if (internalname.get() != null) {
if (itemstack.get() != null) {
- if (NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing && Keyboard.getEventCharacter() == 'k') {
- Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager,
- internalname.get(), manager.getJsonForItem(itemstack.get())
+ if (NotEnoughUpdates.INSTANCE.config.apiData.repositoryEditing && Keyboard.getEventCharacter() == 'k') {
+ Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(
+ internalname.get(),
+ manager.getJsonForItem(itemstack.get())
));
return true;
}
@@ -1120,11 +1139,9 @@ public class NEUOverlay extends Gui {
Minecraft.getMinecraft().thePlayer.inventory.addItemStackToInventory(
manager.jsonToStack(item));
}
- } else if (NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing &&
+ } else if (NotEnoughUpdates.INSTANCE.config.apiData.repositoryEditing &&
Keyboard.getEventCharacter() == 'k') {
- Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(manager,
- internalname.get(), item
- ));
+ Minecraft.getMinecraft().displayGuiScreen(new NEUItemEditor(internalname.get(), item));
return true;
} else if (keyPressed == manager.keybindItemSelect.getKeyCode() &&
NotEnoughUpdates.INSTANCE.config.toolbar.searchBar) {
@@ -1153,40 +1170,6 @@ public class NEUOverlay extends Gui {
updateSearch();
}
- String[] rarityArr = new String[]{
- EnumChatFormatting.WHITE + EnumChatFormatting.BOLD.toString() + "COMMON",
- EnumChatFormatting.GREEN + EnumChatFormatting.BOLD.toString() + "UNCOMMON",
- EnumChatFormatting.BLUE + EnumChatFormatting.BOLD.toString() + "RARE",
- EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD.toString() + "EPIC",
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD.toString() + "LEGENDARY",
- EnumChatFormatting.LIGHT_PURPLE + EnumChatFormatting.BOLD.toString() + "MYTHIC",
- EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "SPECIAL",
- };
-
- /**
- * Finds the rarity from the lore of an item.
- * -1 = UNKNOWN
- * 0 = COMMON
- * 1 = UNCOMMON
- * 2 = RARE
- * 3 = EPIC
- * 4 = LEGENDARY
- * 5 = MYTHIC
- * 6 = SPECIAL
- */
- public int getRarity(JsonArray lore) {
- for (int i = lore.size() - 1; i >= 0; i--) {
- String line = lore.get(i).getAsString();
-
- for (int j = 0; j < rarityArr.length; j++) {
- if (line.startsWith(rarityArr[j])) {
- return j;
- }
- }
- }
- return -1;
- }
-
/**
* Convenience functions that get various compare/sort modes from the config.
*/
@@ -1214,19 +1197,21 @@ public class NEUOverlay extends Gui {
return (o1, o2) -> {
//1 (mult) if o1 should appear after o2
//-1 (-mult) if o2 should appear after o1
- if (getFavourites().contains(o1.get("internalname").getAsString()) &&
- !getFavourites().contains(o2.get("internalname").getAsString())) {
+ if (getFavourites().contains(o1.get("internalname").getAsString()) && !getFavourites().contains(o2
+ .get("internalname")
+ .getAsString())) {
return -1;
}
- if (!getFavourites().contains(o1.get("internalname").getAsString()) &&
- getFavourites().contains(o2.get("internalname").getAsString())) {
+ if (!getFavourites().contains(o1.get("internalname").getAsString()) && getFavourites().contains(o2
+ .get("internalname")
+ .getAsString())) {
return 1;
}
int mult = getCompareAscending().get(getCompareMode()) ? 1 : -1;
if (getCompareMode() == COMPARE_MODE_RARITY) {
- int rarity1 = getRarity(o1.get("lore").getAsJsonArray());
- int rarity2 = getRarity(o2.get("lore").getAsJsonArray());
+ int rarity1 = Utils.getRarityFromLore(o1.get("lore").getAsJsonArray());
+ int rarity2 = Utils.getRarityFromLore(o2.get("lore").getAsJsonArray());
if (rarity1 < rarity2) return mult;
if (rarity1 > rarity2) return -mult;
@@ -1234,8 +1219,8 @@ public class NEUOverlay extends Gui {
String internal1 = o1.get("internalname").getAsString();
String internal2 = o2.get("internalname").getAsString();
- float cost1 = manager.auctionManager.getLowestBin(internal1);
- float cost2 = manager.auctionManager.getLowestBin(internal2);
+ double cost1 = manager.auctionManager.getBazaarOrBin(internal1);
+ double cost2 = manager.auctionManager.getBazaarOrBin(internal2);
if (cost1 < cost2) return mult;
if (cost1 > cost2) return -mult;
@@ -1280,7 +1265,7 @@ public class NEUOverlay extends Gui {
for (int i = lore.size() - 1; i >= 0; i--) {
String line = lore.get(i).getAsString();
- for (String rarity : rarityArr) {
+ for (String rarity : Utils.rarityArrC) {
for (int j = 0; j < typeMatches.length; j++) {
if (line.trim().equals(rarity + " " + typeMatches[j])) {
return j;
@@ -1295,14 +1280,13 @@ public class NEUOverlay extends Gui {
* Checks whether an item matches the current sort mode.
*/
public boolean checkMatchesSort(String internalname, JsonObject item) {
- if (!NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems &&
- item.has("vanilla") &&
+ if (!NotEnoughUpdates.INSTANCE.config.itemlist.showVanillaItems && item.has("vanilla") &&
item.get("vanilla").getAsBoolean()) {
return false;
}
if (getSortMode() == SORT_MODE_ALL) {
- return !internalname.matches(mobRegex);
+ return NotEnoughUpdates.INSTANCE.config.itemlist.alwaysShowMonsters || !internalname.matches(mobRegex);
} else if (getSortMode() == SORT_MODE_MOB) {
return internalname.matches(mobRegex);
} else if (getSortMode() == SORT_MODE_PET) {
@@ -1321,13 +1305,13 @@ public class NEUOverlay extends Gui {
"DUNGEON SWORD",
"DUNGEON BOW",
"DRILL",
- "GAUNTLET"
+ "GAUNTLET",
+ "LONGSWORD",
+ "DEPLOYABLE"
) >= 0;
} else if (getSortMode() == SORT_MODE_ARMOR) {
return checkItemType(
- item
- .get("lore")
- .getAsJsonArray(),
+ item.get("lore").getAsJsonArray(),
"HELMET",
"CHESTPLATE",
"LEGGINGS",
@@ -1335,9 +1319,13 @@ public class NEUOverlay extends Gui {
"DUNGEON HELMET",
"DUNGEON CHESTPLATE",
"DUNGEON LEGGINGS",
- "DUNGEON BOOTS"
- ) >=
- 0;
+ "DUNGEON BOOTS",
+ "BELT",
+ "GLOVES",
+ "CLOAK",
+ "NECKLACE",
+ "BRACELET"
+ ) >= 0;
} else if (getSortMode() == SORT_MODE_ACCESSORY) {
return checkItemType(item.get("lore").getAsJsonArray(), "ACCESSORY", "HATCCESSORY", "DUNGEON ACCESSORY") >= 0;
}
@@ -1449,7 +1437,7 @@ public class NEUOverlay extends Gui {
* Returns an index-able array containing the elements in searchedItems.
* Whenever searchedItems is updated in updateSearch(), the array is recreated here.
*/
- public List<JsonObject> getSearchedItems() {
+ public synchronized List<JsonObject> getSearchedItems() {
if (searchedItems == null) {
updateSearch();
return new ArrayList<>();
@@ -1472,7 +1460,7 @@ public class NEUOverlay extends Gui {
if (index < getSlotsXSize() * getSlotsYSize()) {
int actualIndex = index + getSlotsXSize() * getSlotsYSize() * page;
List<JsonObject> searchedItems = getSearchedItems();
- if (actualIndex < searchedItems.size()) {
+ if (0 <= actualIndex && actualIndex < searchedItems.size()) {
return searchedItems.get(actualIndex);
} else {
return null;
@@ -1620,12 +1608,12 @@ public class NEUOverlay extends Gui {
drawRect(leftSide - 1, top, leftSide - 1 + buttonXSize, top + ySize, fg.getRGB());
GlStateManager.color(1f, 1f, 1f, 1f);
- Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.rightarrow);
Utils.drawTexturedRect(leftSide - 1 + leftPressed,
top + leftPressed,
buttonXSize, ySize, 1, 0, 0, 1
);
- Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.rightarrow_overlay);
Utils.drawTexturedRect(leftSide - 1,
top,
buttonXSize, ySize, 1 - leftPressed, leftPressed, 1 - leftPressed, leftPressed
@@ -1639,12 +1627,12 @@ public class NEUOverlay extends Gui {
drawRect(rightSide + 1 - buttonXSize, top, rightSide + 1, top + ySize, fg.getRGB());
GlStateManager.color(1f, 1f, 1f, 1f);
- Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.rightarrow);
Utils.drawTexturedRect(rightSide + 1 - buttonXSize + rightPressed,
top + rightPressed,
buttonXSize, ySize
);
- Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.rightarrow_overlay);
Utils.drawTexturedRect(rightSide + 1 - buttonXSize,
top,
buttonXSize, ySize, 1 - rightPressed, rightPressed, 1 - rightPressed, rightPressed
@@ -1802,129 +1790,13 @@ public class NEUOverlay extends Gui {
int guiScaleLast = 0;
private boolean showVanillaLast = false;
-
- private boolean wardrobeOpen = false;
-
- private boolean isInNamedGui(String guiName) {
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- IInventory lower = container.getLowerChestInventory();
- String containerName = lower.getDisplayName().getUnformattedText();
- wardrobeOpen = containerName.contains(guiName);
- }
- if (guiScreen instanceof GuiInventory) {
- wardrobeOpen = false;
- }
- return wardrobeOpen;
- }
-
- private int wardrobePage = -1;
-
- private int getWardrobePage() {
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- if (isInNamedGui("Wardrobe")) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- IInventory lower = container.getLowerChestInventory();
- String containerName = lower.getDisplayName().getUnformattedText();
- try {
- wardrobePage = Integer.parseInt(containerName.substring(10, 11));
- } catch (NumberFormatException e) {
- System.out.println(containerName.charAt(10));
- System.out.println("Did hypixel change the wardrobe string?");
- wardrobePage = -1;
- }
- } else wardrobePage = -1;
- }
- return wardrobePage;
- }
-
- private ItemStack getChestSlotsAsItemStack(int slot) {
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
- if (guiScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- return chest.inventorySlots.getSlot(slot).getStack();
- } else {
- return null;
- }
- }
-
- private int selectedArmor = 9;
-
- private int getEquippedArmor() {
- if (!isInNamedGui("Wardrobe")) return selectedArmor;
-
- ItemStack nullTest1 = getChestSlotsAsItemStack(8);
- ItemStack nullTest2 = getChestSlotsAsItemStack(17);
- ItemStack nullTest3 = getChestSlotsAsItemStack(26);
- ItemStack nullTest4 = getChestSlotsAsItemStack(35);
- ItemStack nullTest5 = getChestSlotsAsItemStack(44);
- if (nullTest1 != null || nullTest2 != null || nullTest3 != null || nullTest4 != null || nullTest5 != null) {
- selectedArmor = 9;
- }
- for (int ii = 1; ii < 5; ii++) {
- if (ii != 1 && selectedArmor != 9) continue;
- if (getWardrobePage() != ii) continue;
- for (int i = 8; i < 54; i += 9) {
- ItemStack stack1 = getChestSlotsAsItemStack(i);
- if (stack1 == null) continue;
- String[] lore1 = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack1.getTagCompound());
- for (String line : lore1) {
- if (line.contains("to unequip this armor")) {
- selectedArmor = i;
- break;
- }
- }
- }
- }
- return selectedArmor;
- }
-
- private ItemStack getWardrobeSlot(int armourSlot) {
- if (isInNamedGui("Wardrobe")) {
- if (getChestSlotsAsItemStack(getEquippedArmor() - armourSlot) != null && getEquippedArmor() != 9) {
- return getChestSlotsAsItemStack(getEquippedArmor() - armourSlot);
- } else return null;
- } else return null;
- }
-
- public boolean isWardrobeSystemOnMainServer() {
- JsonElement alphaWardrobeElement = Utils.getElement(Constants.DISABLE, "wardrobeFeature");
- if (alphaWardrobeElement == null || !alphaWardrobeElement.isJsonObject()) {
- return true;
- }
- JsonObject isWardrobe = alphaWardrobeElement.getAsJsonObject();
- if (isWardrobe.has("enableNewWardrob")) {
- return isWardrobe.get("enableNewWardrob").getAsBoolean();
- } else {
- return true;
- }
- }
-
- public ItemStack slot1 = null;
- public ItemStack slot2 = null;
- public ItemStack slot3 = null;
- public ItemStack slot4 = null;
- public ItemStack petSlot = null;
-
- public static boolean isRenderingArmorHud() {
- return renderingArmorHud;
- }
-
- public static boolean isRenderingPetHud() {
- return renderingPetHud;
- }
-
/**
* Renders the search bar, quick commands, item selection (right), item info (left) and armor hud gui elements.
*/
public void render(boolean hoverInv) {
- if (disabled) return;
- renderingArmorHud = false;
- renderingPetHud = false;
+ if (disabled) {
+ return;
+ }
GlStateManager.enableDepth();
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
@@ -1948,236 +1820,13 @@ public class NEUOverlay extends Gui {
Utils.drawTexturedRect((width - 64) / 2f, (height - 64) / 2f - 114, 64, 64, GL11.GL_LINEAR);
GlStateManager.bindTexture(0);
}
- GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
-
- if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud &&
- NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect
- &&
- NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() &&
- isWardrobeSystemOnMainServer()) {
- if (getWardrobeSlot(1) != null) {
- slot1 = getWardrobeSlot(4);
- slot2 = getWardrobeSlot(3);
- slot3 = getWardrobeSlot(2);
- slot4 = getWardrobeSlot(1);
- }
- if (guiScreen instanceof GuiInventory) {
- renderingArmorHud = true;
- selectedArmor = 9;
-
- List<String> tooltipToDisplay = null;
- if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 0) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY);
- }
- if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 1) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_GREY);
- }
- if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 2) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_DARK);
- }
- if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 3) {
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3 &&
- NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay &&
- petSlot != null) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT_PET);
- } else {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_TRANSPARENT);
- }
- }
- if (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle == 4) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(ARMOR_DISPLAY_FSR);
- }
-
- GlStateManager.color(1, 1, 1, 1);
- GL11.glTranslatef(0, 0, 401);
- float yNumber = (float) (height - 167) / 2f;
- Utils.drawTexturedRect((float) ((width - 224.1) / 2f), yNumber, 31, 86, GL11.GL_NEAREST);
- GlStateManager.bindTexture(0);
- Utils.drawItemStack(slot1, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105));
- Utils.drawItemStack(slot2, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 18);
- Utils.drawItemStack(slot3, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 36);
- Utils.drawItemStack(slot4, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 54);
- if (slot1 == null) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(QUESTION_MARK);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(((width - 208) / 2f), ((height + 60) / 2f - 105), 16, 16, GL11.GL_NEAREST);
- GlStateManager.bindTexture(0);
-
- tooltipToDisplay = Lists.newArrayList(
- EnumChatFormatting.RED + "Warning",
- EnumChatFormatting.GREEN + "You need to open /wardrobe",
- EnumChatFormatting.GREEN + "To cache your armour"
- );
- if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) {
- if (mouseY >= ((height + 60) / 2f - 105) &&
- mouseY <= ((height + 60) / 2f - 105) + 70 &&
- NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) {
- if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
- if (Mouse.getEventButtonState()) {
- if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/wardrobe") ==
- 0) {
- NotEnoughUpdates.INSTANCE.sendChatMessage("/wardrobe");
- }
- }
- }
- }
- if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 16) {
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- GL11.glTranslatef(0, 0, -401);
- }
- }
-
- }
- if (slot1 != null && slot2 != null && slot3 != null && slot4 != null) {
- if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) {
- if (mouseY >= ((height + 60) / 2f - 105) &&
- mouseY <= ((height + 60) / 2f - 105) + 70 &&
- NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand) {
- if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
- if (Mouse.getEventButtonState()) {
- if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/wardrobe") ==
- 0) {
- NotEnoughUpdates.INSTANCE.sendChatMessage("/wardrobe");
- }
- }
- }
- }
- //top slot
- if (mouseY >= ((height + 60) / 2f - 105) && mouseY <= ((height + 60) / 2f - 105) + 16) {
- tooltipToDisplay = slot1.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- tooltipToDisplay = null;
- GL11.glTranslatef(0, 0, -401);
- }
- if (mouseY >= ((height + 60) / 2f - 105) + 18 && mouseY <= ((height + 60) / 2f - 105) + 34) {
- tooltipToDisplay = slot2.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- tooltipToDisplay = null;
- GL11.glTranslatef(0, 0, -401);
- }
- if (mouseY >= ((height + 60) / 2f - 105) + 36 && mouseY <= ((height + 60) / 2f - 105) + 52) {
- tooltipToDisplay = slot3.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- tooltipToDisplay = null;
- GL11.glTranslatef(0, 0, -401);
- }
- if (mouseY >= ((height + 60) / 2f - 105) + 54 && mouseY <= ((height + 60) / 2f - 105) + 70) {
- tooltipToDisplay = slot4.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- tooltipToDisplay = null;
- GL11.glTranslatef(0, 0, -401);
- }
- }
- GL11.glTranslatef(0, 0, -401);
- }
- }
- }
- if (PetInfoOverlay.getCurrentPet() != null) {
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay
- &&
- (NotEnoughUpdates.INSTANCE.manager
- .jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId))
- .hasDisplayName()
- ||
- NotEnoughUpdates.INSTANCE.manager
- .jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get(PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1)))
- .hasDisplayName())
- &&
- NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect &&
- NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- if (!NotEnoughUpdates.INSTANCE.manager
- .jsonToStack(
- NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get(PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId))
- .hasDisplayName()) {
- petSlot = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
- PetInfoOverlay.getCurrentPet().petType + ";" + (PetInfoOverlay.getCurrentPet().rarity.petId - 1)));
- } else {
- petSlot = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
- PetInfoOverlay.getCurrentPet().petType + ";" + PetInfoOverlay.getCurrentPet().rarity.petId));
- }
- petSlot.getTagCompound().setBoolean("NEUPETINVDISPLAY", true);
- petSlot
- .getTagCompound()
- .setBoolean("NEUHIDEPETTOOLTIP", NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip);
- ItemStack petInfo = petSlot;
-
- if (guiScreen instanceof GuiInventory) {
- GL11.glTranslatef(0, 0, 401);
- if (!NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud || !isWardrobeSystemOnMainServer()) {
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 0) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 1) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_GREY);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 2) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_DARK);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_TRANSPARENT);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 4) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_DISPLAY_FSR);
- }
- } else {
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 0) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 1) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_GREY);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 2) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_DARK);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_TRANSPARENT);
- }
- if (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 4) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(PET_ARMOR_DISPLAY_FSR);
- }
- }
-
- GlStateManager.color(1, 1, 1, 1);
- float yNumber = (float) (height - 23) / 2f;
- Utils.drawTexturedRect((float) ((width - 224.1) / 2f), yNumber, 31, 32, GL11.GL_NEAREST);
- GlStateManager.bindTexture(0);
-
- Utils.drawItemStack(petInfo, (int) ((width - 208) / 2f), (int) ((height + 60) / 2f - 105) + 72);
- renderingPetHud = true;
-
- List<String> tooltipToDisplay = null;
- if (petInfo != null) {
- if (mouseX >= ((width - 208) / 2f) && mouseX < ((width - 208) / 2f) + 16) {
- if (mouseY >= ((height + 60) / 2f - 105) + 72 &&
- mouseY <= ((height + 60) / 2f - 105) + 88 &&
- NotEnoughUpdates.INSTANCE.config.petOverlay.sendPetsCommand) {
- if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
- if (Mouse.getEventButtonState()) {
- if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/pets") ==
- 0) {
- NotEnoughUpdates.INSTANCE.sendChatMessage("/pets");
- }
- }
- }
- tooltipToDisplay = petInfo.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
- tooltipToDisplay = null;
- GL11.glTranslatef(0, 0, -80);
- }
- }
-
- }
- }
- }
+ if (textField.getText().toLowerCase().contains("lunar")) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(ATMOULBERRYWHYISMYLUNARCLIENTBUGGING);
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.translate(0, 0, 100);
+ Utils.drawTexturedRect((width + 410) / 2f, (height + 450) / 2f - 114, 113, 64, GL11.GL_LINEAR);
+ GlStateManager.bindTexture(0);
}
SunTzu.setEnabled(textField.getText().toLowerCase().startsWith("potato"));
@@ -2208,6 +1857,13 @@ public class NEUOverlay extends Gui {
(int) (fgFavourite2.getBlue() * 0.8f), fgFavourite2.getAlpha()
);
+ if (!NotEnoughUpdates.INSTANCE.config.itemlist.openWhenSearching && searchMode) {
+ itemPaneOpen = false;
+ }
+ if (itemPaneShouldOpen != -1 && System.currentTimeMillis() > itemPaneShouldOpen) {
+ itemPaneOpen = true;
+ itemPaneShouldOpen = -1;
+ }
if (itemPaneOpen) {
if (itemPaneTabOffset.getValue() == 0) {
if (itemPaneOffsetFactor.getTarget() != 2 / 3f) {
@@ -2252,7 +1908,7 @@ public class NEUOverlay extends Gui {
//Tab
if (NotEnoughUpdates.INSTANCE.config.itemlist.tabOpen) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.itemPaneTabArrow);
GlStateManager.color(1f, 1f, 1f, 0.3f);
Utils.drawTexturedRect(width - itemPaneTabOffset.getValue() * 64 / 20f, height / 2f - 32, 64, 64);
GlStateManager.bindTexture(0);
@@ -2308,17 +1964,14 @@ public class NEUOverlay extends Gui {
int orderIconX = leftSide + getBoxPadding() + getItemBoxXPadding() + i * scaledItemPaddedSize;
drawRect(orderIconX, iconTop, scaledITEM_SIZE + orderIconX, iconTop + scaledITEM_SIZE, fg.getRGB());
- Minecraft
- .getMinecraft()
- .getTextureManager()
- .bindTexture(getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ getCompareMode() == i ? orderIconsActive[i] : orderIcons[i]);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST);
- Minecraft
- .getMinecraft()
- .getTextureManager()
- .bindTexture(getCompareAscending().get(i) ? ascending_overlay : descending_overlay);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(getCompareAscending().get(i)
+ ? GuiTextures.ascending_overlay
+ : GuiTextures.descending_overlay);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect(orderIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST);
GlStateManager.bindTexture(0);
@@ -2341,10 +1994,8 @@ public class NEUOverlay extends Gui {
for (int i = 0; i < sortIcons.length; i++) {
int sortIconX = rightSide - scaledITEM_SIZE - i * scaledItemPaddedSize;
drawRect(sortIconX, iconTop, scaledITEM_SIZE + sortIconX, iconTop + scaledITEM_SIZE, fg.getRGB());
- Minecraft
- .getMinecraft()
- .getTextureManager()
- .bindTexture(getSortMode() == i ? sortIconsActive[i] : sortIcons[i]);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ getSortMode() == i ? sortIconsActive[i] : sortIcons[i]);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect(sortIconX, iconTop, scaledITEM_SIZE, scaledITEM_SIZE, 0, 1, 0, 1, GL11.GL_NEAREST);
GlStateManager.bindTexture(0);
@@ -2504,7 +2155,7 @@ public class NEUOverlay extends Gui {
activeInfoPane.render(width, height, bg, fg, Utils.peekGuiScale(), mouseX, mouseY);
GlStateManager.color(1f, 1f, 1f, 1f);
- Minecraft.getMinecraft().getTextureManager().bindTexture(close);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.close);
Utils.drawTexturedRect(rightSide - getBoxPadding() - 8, getBoxPadding() - 8, 16, 16);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
@@ -2550,7 +2201,6 @@ public class NEUOverlay extends Gui {
GlStateManager.enableAlpha();
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.disableLighting();
-
Utils.pushGuiScale(-1);
if (System.currentTimeMillis() - lastSearchMode > 120000 &&
@@ -2560,6 +2210,7 @@ public class NEUOverlay extends Gui {
}
}
+
/**
* Used in SettingsInfoPane to redraw the items when a setting changes.
*/
@@ -2585,8 +2236,7 @@ public class NEUOverlay extends Gui {
int sw = width * Utils.peekGuiScale().getScaleFactor();
int sh = height * Utils.peekGuiScale().getScaleFactor();
for (int i = 0; i < itemFramebuffers.length; i++) {
- if (itemFramebuffers[i] == null ||
- itemFramebuffers[i].framebufferWidth != sw ||
+ if (itemFramebuffers[i] == null || itemFramebuffers[i].framebufferWidth != sw ||
itemFramebuffers[i].framebufferHeight != sh) {
if (itemFramebuffers[i] == null) {
itemFramebuffers[i] = new Framebuffer(sw, sh, true);
@@ -2772,7 +2422,7 @@ public class NEUOverlay extends Gui {
return;
}
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.item_mask);
if (getFavourites().contains(json.get("internalname").getAsString())) {
if (NotEnoughUpdates.INSTANCE.config.itemlist.itemStyle == 0) {
GlStateManager.color(fgFavourite2.getRed() / 255f, fgFavourite2.getGreen() / 255f,
@@ -2854,7 +2504,7 @@ public class NEUOverlay extends Gui {
GlStateManager.translate(0, 0, 50);
if (searchedItemsSubgroup.containsKey(json.get("internalname").getAsString())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_haschild);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiTextures.item_haschild);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(x - 1, y - 1, ITEM_SIZE + 2, ITEM_SIZE + 2, GL11.GL_NEAREST);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java b/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java
new file mode 100644
index 00000000..bc279188
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEURepoResourcePack.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonObject;
+import net.minecraft.client.resources.IResourcePack;
+import net.minecraft.client.resources.data.IMetadataSection;
+import net.minecraft.client.resources.data.IMetadataSerializer;
+import net.minecraft.util.ResourceLocation;
+
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+public class NEURepoResourcePack implements IResourcePack {
+
+ File repoLocation;
+ Set<String> resourceDomains = new HashSet<>();
+
+ public NEURepoResourcePack(File repoLocation, String domain) {
+ this.repoLocation = repoLocation;
+ resourceDomains.add(domain);
+ }
+
+ public boolean loadRepoLocation() {
+ if (repoLocation != null) return true;
+ NotEnoughUpdates instance = NotEnoughUpdates.INSTANCE;
+ if (instance == null) return false;
+ NEUManager manager = instance.manager;
+ if (manager == null) return false;
+ repoLocation = manager.repoLocation;
+ return repoLocation != null;
+ }
+
+ public File getFileForResource(ResourceLocation loc) {
+ if (repoLocation == null) {
+ if (!loadRepoLocation())
+ return null;
+ }
+ if (!"neurepo".equals(loc.getResourceDomain())) {
+ return null;
+ }
+ return new File(repoLocation, loc.getResourcePath());
+ }
+
+ @Override
+ public InputStream getInputStream(ResourceLocation resourceLocation) throws IOException {
+ return new BufferedInputStream(new FileInputStream(getFileForResource(resourceLocation)));
+ }
+
+ @Override
+ public boolean resourceExists(ResourceLocation resourceLocation) {
+ File file = getFileForResource(resourceLocation);
+ return file != null && file.exists();
+ }
+
+ @Override
+ public Set<String> getResourceDomains() {
+ return resourceDomains;
+ }
+
+ @Override
+ public <T extends IMetadataSection> T getPackMetadata(IMetadataSerializer iMetadataSerializer, String s)
+ throws IOException {
+ return iMetadataSerializer.parseMetadataSection(s, new JsonObject());
+ }
+
+ @Override
+ public BufferedImage getPackImage() throws IOException {
+ return null;
+ }
+
+ @Override
+ public String getPackName() {
+ return "NEU Repo Resources";
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index b6ac71a4..39826ded 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates;
import com.google.common.collect.Sets;
@@ -7,22 +26,60 @@ import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.commands.Commands;
import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager;
import io.github.moulberry.notenoughupdates.dungeons.DungeonMap;
-import io.github.moulberry.notenoughupdates.miscfeatures.*;
+import io.github.moulberry.notenoughupdates.listener.ChatListener;
+import io.github.moulberry.notenoughupdates.listener.ItemTooltipEssenceShopListener;
+import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener;
+import io.github.moulberry.notenoughupdates.listener.ItemTooltipRngListener;
+import io.github.moulberry.notenoughupdates.listener.NEUEventListener;
+import io.github.moulberry.notenoughupdates.listener.OldAnimationChecker;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
+import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AntiCoopAdd;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionProfit;
+import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
+import io.github.moulberry.notenoughupdates.miscfeatures.CustomSkulls;
+import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints;
+import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
+import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
+import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
+import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
+import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing;
+import io.github.moulberry.notenoughupdates.miscfeatures.Navigation;
+import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.miscfeatures.PowerStoneStatsDisplay;
+import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
+import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager;
+import io.github.moulberry.notenoughupdates.miscfeatures.SunTzu;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBlockSounds;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.DwarvenMinesTextures;
+import io.github.moulberry.notenoughupdates.miscfeatures.updater.AutoUpdater;
import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay;
import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector;
+import io.github.moulberry.notenoughupdates.miscgui.SignCalculator;
+import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay;
+import io.github.moulberry.notenoughupdates.mixins.AccessorMinecraft;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.overlays.EquipmentOverlay;
import io.github.moulberry.notenoughupdates.overlays.FuelBar;
import io.github.moulberry.notenoughupdates.overlays.OverlayManager;
import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator;
+import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.XPInformation;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.resources.IReloadableResourceManager;
import net.minecraft.client.settings.KeyBinding;
@@ -31,82 +88,46 @@ import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.world.biome.*;
+import net.minecraft.world.biome.BiomeGenBase;
+import net.minecraft.world.biome.BiomeGenHell;
+import net.minecraft.world.biome.BiomeGenJungle;
+import net.minecraft.world.biome.BiomeGenMesa;
+import net.minecraft.world.biome.BiomeGenSnow;
+import net.minecraftforge.client.ClientCommandHandler;
import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.client.FMLClientHandler;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import java.awt.*;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Set;
-@Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true)
+@Mod(
+ modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true, useMetadata = true,
+ guiFactory = "io.github.moulberry.notenoughupdates.core.config.MoulConfigGuiForgeInterop")
public class NotEnoughUpdates {
public static final String MODID = "notenoughupdates";
public static final String VERSION = "2.1.0-REL";
- public static final String PRE_VERSION = "0.0";
- public static final int VERSION_ID = 20100;
+ public static final int VERSION_ID = 20101; //2.1.1 only so update notif works
public static final int PRE_VERSION_ID = 0;
+ public static final int HOTFIX_VERSION_ID = 0;
- public static NotEnoughUpdates INSTANCE = null;
-
- public NEUManager manager;
- public NEUOverlay overlay;
- public NEUConfig config;
-
- private File configFile;
-
- public File getConfigFile() {
- return this.configFile;
- }
-
- public void newConfigFile() {
- this.configFile = new File(NotEnoughUpdates.INSTANCE.getNeuDir(), "configNew.json");
- }
-
- private static final long CHAT_MSG_COOLDOWN = 200;
- private long lastChatMessage = 0;
- private long secondLastChatMessage = 0;
- private String currChatMessage = null;
-
- //Stolen from Biscut and used for detecting whether in skyblock
- private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES =
- Sets.newHashSet("SKYBLOCK", "\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58");
-
- public GuiScreen openGui = null;
- public long lastOpenedGui = 0;
-
- public Commands commands;
-
- public static HashMap<String, String> petRarityToColourMap = new HashMap<String, String>() {{
- put("UNKNOWN", EnumChatFormatting.RED.toString());
- put("COMMON", EnumChatFormatting.WHITE.toString());
- put("UNCOMMON", EnumChatFormatting.GREEN.toString());
- put("RARE", EnumChatFormatting.BLUE.toString());
- put("EPIC", EnumChatFormatting.DARK_PURPLE.toString());
- put("LEGENDARY", EnumChatFormatting.GOLD.toString());
- put("MYTHIC", EnumChatFormatting.LIGHT_PURPLE.toString());
- }};
-
- public static ProfileViewer profileViewer;
-
- public boolean packDevEnabled = false;
-
- private final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
- private File neuDir;
-
- public File getNeuDir() {
- return this.neuDir;
- }
-
- public Color[][] colourMap = null;
-
+ public static final Logger LOGGER = LogManager.getLogger("NotEnoughUpdates");
/**
* Registers the biomes for the crystal hollows here so optifine knows they exists
*/
@@ -140,6 +161,57 @@ public class NotEnoughUpdates {
.setBiomeName("NeuCrystalHollowsCrystalNucleus")
.setFillerBlockMetadata(5470985)
.setTemperatureRainfall(0.95F, 0.9F);
+ private static final long CHAT_MSG_COOLDOWN = 200;
+ //Stolen from Biscut and used for detecting whether in skyblock
+ private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES =
+ Sets.newHashSet("SKYBLOCK", "\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58");
+ public static NotEnoughUpdates INSTANCE = null;
+ public static HashMap<String, String> petRarityToColourMap = new HashMap<String, String>() {{
+ put("UNKNOWN", EnumChatFormatting.RED.toString());
+ put("COMMON", EnumChatFormatting.WHITE.toString());
+ put("UNCOMMON", EnumChatFormatting.GREEN.toString());
+ put("RARE", EnumChatFormatting.BLUE.toString());
+ put("EPIC", EnumChatFormatting.DARK_PURPLE.toString());
+ put("LEGENDARY", EnumChatFormatting.GOLD.toString());
+ put("MYTHIC", EnumChatFormatting.LIGHT_PURPLE.toString());
+ }};
+ public static ProfileViewer profileViewer;
+ private final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
+ public NEUManager manager;
+ public NEUOverlay overlay;
+ public NEUConfig config;
+ public Navigation navigation = new Navigation(this);
+ public GuiScreen openGui = null;
+ public long lastOpenedGui = 0;
+ public Commands commands;
+ public boolean packDevEnabled = false;
+ public Color[][] colourMap = null;
+ public AutoUpdater autoUpdater = new AutoUpdater(this);
+ private File configFile;
+ private long lastChatMessage = 0;
+ private long secondLastChatMessage = 0;
+ private String currChatMessage = null;
+ private File neuDir;
+ private boolean hasSkyblockScoreboard;
+
+ public File getConfigFile() {
+ return this.configFile;
+ }
+
+ public void newConfigFile() {
+ this.configFile = new File(NotEnoughUpdates.INSTANCE.getNeuDir(), "configNew.json");
+ }
+
+ public File getNeuDir() {
+ return this.neuDir;
+ }
+
+ public NotEnoughUpdates() {
+ // Budget Construction Event
+ ((AccessorMinecraft) FMLClientHandler.instance().getClient())
+ .onGetDefaultResourcePacks()
+ .add(new NEURepoResourcePack(null, "neurepo"));
+ }
/**
* Instantiates NEUIo, NEUManager and NEUOverlay instances. Registers keybinds and adds a shutdown hook to clear tmp folder.
@@ -161,13 +233,14 @@ public class NotEnoughUpdates {
))
) {
config = gson.fromJson(reader, NEUConfig.class);
- } catch (Exception ignored) {
+ } catch (Exception exc) {
+ new RuntimeException("Invalid config file. This will reset the config to default", exc).printStackTrace();
}
}
ItemCustomizeManager.loadCustomization(new File(neuDir, "itemCustomization.json"));
StorageManager.getInstance().loadConfig(new File(neuDir, "storageItems.json"));
- FairySouls.load(new File(neuDir, "collected_fairy_souls.json"), gson);
+ FairySouls.getInstance().loadFoundSoulsForAllProfiles(new File(neuDir, "collected_fairy_souls.json"), gson);
PetInfoOverlay.loadConfig(new File(neuDir, "petCache.json"));
SlotLocking.getInstance().loadConfig(new File(neuDir, "slotLocking.json"));
ItemPriceInformation.init(new File(neuDir, "auctionable_items.json"), gson);
@@ -175,6 +248,28 @@ public class NotEnoughUpdates {
if (config == null) {
config = new NEUConfig();
saveConfig();
+ } else {
+ if (config.apiKey != null && config.apiKey.apiKey != null) {
+ config.apiData.apiKey = config.apiKey.apiKey;
+ config.apiKey = null;
+ }
+
+ //add the trophy fishing tab to the config
+ if (config.profileViewer.pageLayout.size() == 8) {
+ config.profileViewer.pageLayout.add(8);
+ }
+ if (config.profileViewer.pageLayout.size() == 9) {
+ config.profileViewer.pageLayout.add(9);
+ }
+
+ // Remove after 2.1 ig
+ if ("dangerous".equals(config.apiData.repoBranch) || "rune".equals(config.apiData.repoBranch)) {
+ config.apiData.repoBranch = "master";
+ } else if ("jani270".equals(config.apiData.repoUser)) {
+ config.apiData.repoUser = "NotEnoughUpdates";
+ }
+
+ saveConfig();
}
MinecraftForge.EVENT_BUS.register(this);
@@ -186,15 +281,16 @@ public class NotEnoughUpdates {
MinecraftForge.EVENT_BUS.register(new CalendarOverlay());
MinecraftForge.EVENT_BUS.register(SBInfo.getInstance());
MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE);
+ MinecraftForge.EVENT_BUS.register(new Constants());
MinecraftForge.EVENT_BUS.register(new DungeonMap());
MinecraftForge.EVENT_BUS.register(new SunTzu());
MinecraftForge.EVENT_BUS.register(new MiningStuff());
- MinecraftForge.EVENT_BUS.register(new FairySouls());
+ MinecraftForge.EVENT_BUS.register(FairySouls.getInstance());
MinecraftForge.EVENT_BUS.register(new CrystalOverlay());
MinecraftForge.EVENT_BUS.register(new ItemCooldowns());
MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints());
MinecraftForge.EVENT_BUS.register(new FuelBar());
- //MinecraftForge.EVENT_BUS.register(new FancyPortals());
+ MinecraftForge.EVENT_BUS.register(new AuctionProfit());
MinecraftForge.EVENT_BUS.register(XPInformation.getInstance());
MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay);
MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay);
@@ -202,13 +298,30 @@ public class NotEnoughUpdates {
MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance());
MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance());
MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance());
+ MinecraftForge.EVENT_BUS.register(CrystalWishingCompassSolver.getInstance());
MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures());
+ MinecraftForge.EVENT_BUS.register(EquipmentOverlay.INSTANCE);
MinecraftForge.EVENT_BUS.register(CustomBiomes.INSTANCE);
+ MinecraftForge.EVENT_BUS.register(new ChatListener(this));
+ MinecraftForge.EVENT_BUS.register(new ItemTooltipListener(this));
+ MinecraftForge.EVENT_BUS.register(new ItemTooltipRngListener(this));
+ MinecraftForge.EVENT_BUS.register(new ItemTooltipEssenceShopListener(this));
+ MinecraftForge.EVENT_BUS.register(new RenderListener(this));
+ MinecraftForge.EVENT_BUS.register(new OldAnimationChecker());
+ MinecraftForge.EVENT_BUS.register(new SignCalculator());
+ MinecraftForge.EVENT_BUS.register(TrophyRewardOverlay.getInstance());
+ MinecraftForge.EVENT_BUS.register(PowerStoneStatsDisplay.getInstance());
+ MinecraftForge.EVENT_BUS.register(new AntiCoopAdd());
+ MinecraftForge.EVENT_BUS.register(AbiphoneWarning.getInstance());
+ MinecraftForge.EVENT_BUS.register(new BetterContainers());
+ MinecraftForge.EVENT_BUS.register(AuctionBINWarning.getInstance());
+ MinecraftForge.EVENT_BUS.register(navigation);
if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) {
IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager();
manager.registerReloadListener(CustomSkulls.getInstance());
manager.registerReloadListener(NPCRetexturing.getInstance());
+ manager.registerReloadListener(ShaderManager.getInstance());
manager.registerReloadListener(new ItemCustomizeManager.ReloadListener());
manager.registerReloadListener(new CustomBlockSounds.ReloaderListener());
}
@@ -234,7 +347,6 @@ public class NotEnoughUpdates {
}
tmp.delete();
}
- //saveConfig();
}));
}
@@ -262,7 +374,7 @@ public class NotEnoughUpdates {
} catch (Exception ignored) {
}
try {
- FairySouls.save(new File(neuDir, "collected_fairy_souls.json"), gson);
+ FairySouls.getInstance().saveFoundSoulsForAllProfiles(new File(neuDir, "collected_fairy_souls.json"), gson);
} catch (Exception ignored) {
}
try {
@@ -290,11 +402,16 @@ public class NotEnoughUpdates {
}
}
- public void displayLinks(JsonObject update) {
+ public void trySendCommand(String message) {
+ if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, message) == 0) {
+ sendChatMessage(message);
+ }
+ }
+
+ public void displayLinks(JsonObject update, int totalWidth) {
String discord_link = update.get("discord_link").getAsString();
String youtube_link = update.get("youtube_link").getAsString();
String twitch_link = update.get("twitch_link").getAsString();
- String update_link = update.get("update_link").getAsString();
String github_link = update.get("github_link").getAsString();
String other_text = update.get("other_text").getAsString();
String other_link = update.get("other_link").getAsString();
@@ -307,8 +424,7 @@ public class NotEnoughUpdates {
}
ChatComponentText links = new ChatComponentText("");
ChatComponentText separator = new ChatComponentText(
- EnumChatFormatting.GRAY + EnumChatFormatting.BOLD.toString() + EnumChatFormatting.STRIKETHROUGH +
- (other == null ? "--" : "-"));
+ EnumChatFormatting.GRAY + EnumChatFormatting.BOLD.toString() + EnumChatFormatting.STRIKETHROUGH + "-");
ChatComponentText discord = new ChatComponentText(
EnumChatFormatting.GRAY + "[" + EnumChatFormatting.BLUE + "Discord" + EnumChatFormatting.GRAY + "]");
discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link));
@@ -318,9 +434,6 @@ public class NotEnoughUpdates {
ChatComponentText twitch = new ChatComponentText(
EnumChatFormatting.GRAY + "[" + EnumChatFormatting.DARK_PURPLE + "Twitch" + EnumChatFormatting.GRAY + "]");
twitch.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, twitch_link));
- ChatComponentText release = new ChatComponentText(
- EnumChatFormatting.GRAY + "[" + EnumChatFormatting.GREEN + "Release" + EnumChatFormatting.GRAY + "]");
- release.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, update_link));
ChatComponentText github = new ChatComponentText(
EnumChatFormatting.GRAY + "[" + EnumChatFormatting.DARK_PURPLE + "GitHub" + EnumChatFormatting.GRAY + "]");
github.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, github_link));
@@ -332,16 +445,28 @@ public class NotEnoughUpdates {
links.appendSibling(separator);
links.appendSibling(twitch);
links.appendSibling(separator);
- links.appendSibling(release);
- links.appendSibling(separator);
links.appendSibling(github);
links.appendSibling(separator);
if (other != null) {
links.appendSibling(other);
links.appendSibling(separator);
}
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(links);
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ int missingWidth = Math.max(0, totalWidth - fr.getStringWidth(links.getFormattedText()));
+ int missingCharsOnEitherSide = missingWidth / fr.getStringWidth(EnumChatFormatting.BOLD + "-") / 2;
+ StringBuilder sb = new StringBuilder(missingCharsOnEitherSide + 6);
+ sb.append(EnumChatFormatting.GRAY);
+ sb.append(EnumChatFormatting.BOLD);
+ sb.append(EnumChatFormatting.STRIKETHROUGH);
+ for (int i = 0; i < missingCharsOnEitherSide; i++) {
+ sb.append("-");
+ }
+ String padding = sb.toString();
+ ChatComponentText cp = new ChatComponentText("");
+ cp.appendText(padding);
+ cp.appendSibling(links);
+ cp.appendText(padding);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(cp);
}
@SubscribeEvent
@@ -374,8 +499,6 @@ public class NotEnoughUpdates {
return hasSkyblockScoreboard();
}
- private boolean hasSkyblockScoreboard;
-
public boolean hasSkyblockScoreboard() {
return hasSkyblockScoreboard;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
index c47e0844..1b6896db 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.auction;
import com.google.gson.JsonArray;
@@ -27,10 +46,21 @@ import net.minecraft.util.ResourceLocation;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.util.*;
+import java.util.Base64;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Consumer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class APIManager {
private final NEUManager manager;
@@ -41,6 +71,9 @@ public class APIManager {
private final HashSet<String> playerBids = new HashSet<>();
private final HashSet<String> playerBidsNotified = new HashSet<>();
private final HashSet<String> playerBidsFinishedNotified = new HashSet<>();
+ private final int LOWEST_BIN_UPDATE_INTERVAL = 2 * 60 * 1000; // 2 minutes
+ private final int AUCTION_AVG_UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes
+ private final int BAZAAR_UPDATE_INTERVAL = 5 * 60 * 1000; // 5 minutes
private JsonObject lowestBins = null;
private JsonObject auctionPricesAvgLowestBinJson = null;
@@ -92,7 +125,7 @@ public class APIManager {
public class Auction {
public String auctioneerUuid;
public long end;
- public int starting_bid;
+ public long starting_bid;
public int highest_bid_amount;
public int bid_count;
public boolean bin;
@@ -106,7 +139,7 @@ public class APIManager {
public int enchLevel = 0; //0 = clean, 1 = ench, 2 = ench/hpb
public Auction(
- String auctioneerUuid, long end, int starting_bid, int highest_bid_amount, int bid_count,
+ String auctioneerUuid, long end, long starting_bid, int highest_bid_amount, int bid_count,
boolean bin, String category, String rarity, int dungeonTier, String item_tag_str
) {
this.auctioneerUuid = auctioneerUuid;
@@ -135,6 +168,7 @@ public class APIManager {
return stack;
} else {
JsonObject item = manager.getJsonFromNBT(item_tag);
+ if (item == null) return null;
ItemStack stack = manager.jsonToStack(item, false);
JsonObject itemDefault = manager.getItemInformation().get(item.get("internalname").getAsString());
@@ -180,8 +214,8 @@ public class APIManager {
customAH.tick();
long currentTime = System.currentTimeMillis();
if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.enableNeuAuctionHouse &&
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey != null &&
- !NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty()) {
+ NotEnoughUpdates.INSTANCE.config.apiData.apiKey != null &&
+ !NotEnoughUpdates.INSTANCE.config.apiData.apiKey.isEmpty()) {
if (currentTime - lastAuctionUpdate > 60 * 1000) {
lastAuctionUpdate = currentTime;
updatePageTick();
@@ -203,15 +237,16 @@ public class APIManager {
}
}
}
- if (currentTime - lastAuctionAvgUpdate > 5 * 60 * 1000) { //5 minutes
- lastAuctionAvgUpdate = currentTime - 4 * 60 * 1000; //Try again in 1 minute if updateAvgPrices doesn't succeed
+ if (currentTime - lastAuctionAvgUpdate > AUCTION_AVG_UPDATE_INTERVAL) {
+ lastAuctionAvgUpdate = currentTime - AUCTION_AVG_UPDATE_INTERVAL + 60 * 1000; // Try again in 1 minute on failure
updateAvgPrices();
}
- if (currentTime - lastBazaarUpdate > 5 * 60 * 1000) { //5 minutes
- lastBazaarUpdate = currentTime;
+ if (currentTime - lastBazaarUpdate > BAZAAR_UPDATE_INTERVAL) {
+ lastBazaarUpdate = currentTime - BAZAAR_UPDATE_INTERVAL + 60 * 1000; // Try again in 1 minute on failure
updateBazaar();
}
- if (currentTime - lastLowestBinUpdate > 2 * 60 * 1000) {
+ if (currentTime - lastLowestBinUpdate > LOWEST_BIN_UPDATE_INTERVAL) {
+ lastLowestBinUpdate = currentTime - LOWEST_BIN_UPDATE_INTERVAL + 30 * 1000; // Try again in 30 seconds on failure
updateLowestBin();
}
}
@@ -241,34 +276,37 @@ public class APIManager {
return keys;
}
- public int getLowestBin(String internalname) {
- if (lowestBins != null && lowestBins.has(internalname)) {
- JsonElement e = lowestBins.get(internalname);
+ public long getLowestBin(String internalName) {
+ if (lowestBins != null && lowestBins.has(internalName)) {
+ JsonElement e = lowestBins.get(internalName);
if (e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) {
- return e.getAsInt();
+ return e.getAsBigDecimal().longValue();
}
}
return -1;
}
public void updateLowestBin() {
- manager.hypixelApi.getMyApiGZIPAsync("lowestbin.json.gz", (jsonObject) -> {
- if (lowestBins == null) {
- lowestBins = new JsonObject();
- }
- if (!jsonObject.entrySet().isEmpty()) {
- lastLowestBinUpdate = System.currentTimeMillis();
- }
- for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
- lowestBins.add(entry.getKey(), entry.getValue());
- }
- if (!didFirstUpdate) {
- ItemPriceInformation.updateAuctionableItemsList();
- didFirstUpdate = true;
- }
- GuiPriceGraph.addToCache(lowestBins, false);
- }, () -> {
- });
+ manager.apiUtils
+ .newMoulberryRequest("lowestbin.json.gz")
+ .gunzip()
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (lowestBins == null) {
+ lowestBins = new JsonObject();
+ }
+ if (!jsonObject.entrySet().isEmpty()) {
+ lastLowestBinUpdate = System.currentTimeMillis();
+ }
+ for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+ lowestBins.add(entry.getKey(), entry.getValue());
+ }
+ if (!didFirstUpdate) {
+ ItemPriceInformation.updateAuctionableItemsList();
+ didFirstUpdate = true;
+ }
+ GuiPriceGraph.addToCache(lowestBins, false);
+ });
}
private void ahNotification() {
@@ -377,6 +415,7 @@ public class APIManager {
int page = pagesToDownload.pop();
getPageFromAPI(page);
} catch (NoSuchElementException ignored) {
+ return;
} //Weird race condition?
}
}
@@ -424,20 +463,23 @@ public class APIManager {
}
};
- manager.hypixelApi.getMyApiGZIPAsync("auctionLast.json.gz", process, () ->
- System.out.println("Error downloading auction from Moulberry's jank API. :("));
+ manager.apiUtils.newMoulberryRequest("auctionLast.json.gz")
+ .gunzip().requestJson().thenAccept(process);
- manager.hypixelApi.getMyApiGZIPAsync("auction.json.gz", jsonObject -> {
- if (jsonObject.get("success").getAsBoolean()) {
- long apiUpdate = (long) jsonObject.get("time").getAsFloat();
- if (lastApiUpdate == apiUpdate) {
- lastAuctionUpdate -= 30 * 1000;
- }
- lastApiUpdate = apiUpdate;
+ manager.apiUtils
+ .newMoulberryRequest("auction.json.gz")
+ .gunzip().requestJson()
+ .thenAccept(jsonObject -> {
+ if (jsonObject.get("success").getAsBoolean()) {
+ long apiUpdate = (long) jsonObject.get("time").getAsFloat();
+ if (lastApiUpdate == apiUpdate) {
+ lastAuctionUpdate -= 30 * 1000;
+ }
+ lastApiUpdate = apiUpdate;
- process.accept(jsonObject);
- }
- }, () -> System.out.println("Error downloading auction from Moulberry's jank API. :("));
+ process.accept(jsonObject);
+ }
+ });
}
@@ -508,7 +550,7 @@ public class APIManager {
String auctionUuid = auction.get("uuid").getAsString();
String auctioneerUuid = auction.get("auctioneer").getAsString();
long end = auction.get("end").getAsLong();
- int starting_bid = auction.get("starting_bid").getAsInt();
+ long starting_bid = auction.get("starting_bid").getAsLong();
int highest_bid_amount = auction.get("highest_bid_amount").getAsInt();
int bid_count = auction.get("bids").getAsJsonArray().size();
boolean bin = false;
@@ -637,8 +679,10 @@ public class APIManager {
//System.out.println("Trying to update page: " + page);
HashMap<String, String> args = new HashMap<>();
args.put("page", "" + page);
- manager.hypixelApi.getHypixelApiAsync(null, "skyblock/auctions",
- args, jsonObject -> {
+ manager.apiUtils
+ .newAnonymousHypixelApiRequest("skyblock/auctions")
+ .requestJson()
+ .thenAccept(jsonObject -> {
if (jsonObject == null) return;
if (jsonObject.get("success").getAsBoolean()) {
@@ -665,16 +709,30 @@ public class APIManager {
} else {
pagesToDownload.addLast(page);
}
- }, () -> pagesToDownload.addLast(page)
- );
+ })
+ .handle((ignored, ex) -> {
+ if (ex != null) {
+ pagesToDownload.addLast(page);
+ }
+ return null;
+ });
+ }
+
+ private static final Pattern BAZAAR_ENCHANTMENT_PATTERN = Pattern.compile("ENCHANTMENT_(\\D*)_(\\d+)");
+
+ public String transformHypixelBazaarToNEUItemId(String hypixelId) {
+ Matcher matcher = BAZAAR_ENCHANTMENT_PATTERN.matcher(hypixelId);
+ if (matcher.matches()) {
+ return matcher.group(1) + ";" + matcher.group(2);
+ }
+ return hypixelId.replace(":", "-");
}
public void updateBazaar() {
- manager.hypixelApi.getHypixelApiAsync(
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey,
- "skyblock/bazaar",
- new HashMap<>(),
- (jsonObject) -> {
+ manager.apiUtils
+ .newHypixelApiRequest("skyblock/bazaar")
+ .requestJson()
+ .thenAccept(jsonObject -> {
if (!jsonObject.get("success").getAsBoolean()) return;
craftCost.clear();
@@ -705,24 +763,27 @@ public class APIManager {
}
}
- bazaarJson.add(entry.getKey().replace(":", "-"), productInfo);
+ bazaarJson.add(transformHypixelBazaarToNEUItemId(entry.getKey()), productInfo);
}
}
GuiPriceGraph.addToCache(bazaarJson, true);
- }
- );
+ });
}
public void updateAvgPrices() {
- manager.hypixelApi.getMyApiGZIPAsync("auction_averages/3day.json.gz", (jsonObject) -> {
- craftCost.clear();
- auctionPricesJson = jsonObject;
- lastAuctionAvgUpdate = System.currentTimeMillis();
- }, () -> {
- });
- manager.hypixelApi.getMyApiGZIPAsync("auction_averages_lbin/1day.json.gz", (jsonObject) ->
- auctionPricesAvgLowestBinJson = jsonObject, () -> {
- });
+ manager.apiUtils
+ .newMoulberryRequest("auction_averages/3day.json.gz")
+ .gunzip().requestJson().thenAccept((jsonObject) -> {
+ craftCost.clear();
+ auctionPricesJson = jsonObject;
+ lastAuctionAvgUpdate = System.currentTimeMillis();
+ });
+ manager.apiUtils
+ .newMoulberryRequest("auction_averages_lbin/1day.json.gz")
+ .gunzip().requestJson()
+ .thenAccept((jsonObject) -> {
+ auctionPricesAvgLowestBinJson = jsonObject;
+ });
}
public Set<String> getItemAuctionInfoKeySet() {
@@ -743,13 +804,13 @@ public class APIManager {
return e.getAsJsonObject();
}
- public float getItemAvgBin(String internalname) {
+ public double getItemAvgBin(String internalName) {
if (auctionPricesAvgLowestBinJson == null) return -1;
- JsonElement e = auctionPricesAvgLowestBinJson.get(internalname);
+ JsonElement e = auctionPricesAvgLowestBinJson.get(internalName);
if (e == null) {
return -1;
}
- return Math.round(e.getAsFloat());
+ return Math.round(e.getAsDouble());
}
public Set<String> getBazaarKeySet() {
@@ -761,9 +822,18 @@ public class APIManager {
return keys;
}
- public JsonObject getBazaarInfo(String internalname) {
+ public double getBazaarOrBin(String internalName) {
+ JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalName);
+ if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
+ return bazaarInfo.get("curr_buy").getAsFloat();
+ } else {
+ return manager.auctionManager.getLowestBin(internalName);
+ }
+ }
+
+ public JsonObject getBazaarInfo(String internalName) {
if (bazaarJson == null) return null;
- JsonElement e = bazaarJson.get(internalname);
+ JsonElement e = bazaarJson.get(internalName);
if (e == null) {
return null;
}
@@ -791,7 +861,7 @@ public class APIManager {
public static class CraftInfo {
public boolean fromRecipe = false;
public boolean vanillaItem = false;
- public float craftCost = -1;
+ public double craftCost = -1;
}
public CraftInfo getCraftCost(String internalname) {
@@ -807,10 +877,10 @@ public class APIManager {
visited.add(internalname);
boolean vanillaItem = isVanillaItem(internalname);
- float craftCost = Float.POSITIVE_INFINITY;
+ double craftCost = Double.POSITIVE_INFINITY;
JsonObject auctionInfo = getItemAuctionInfo(internalname);
- float lowestBin = getLowestBin(internalname);
+ double lowestBin = getLowestBin(internalname);
JsonObject bazaarInfo = getBazaarInfo(internalname);
if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
@@ -857,7 +927,7 @@ public class APIManager {
}
}
visited.remove(internalname);
- if (Float.isInfinite(craftCost)) {
+ if (Double.isInfinite(craftCost)) {
return null;
}
CraftInfo craftInfo = new CraftInfo();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
index 123da60a..7b4542d0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.auction;
import com.google.gson.JsonObject;
@@ -35,14 +54,23 @@ import org.lwjgl.opengl.GL14;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.*;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.auction_accept;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.auction_price;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.auction_view;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.auction_view_buttons;
public class CustomAH extends Gui {
private enum PriceFilter {
@@ -66,7 +94,7 @@ public class CustomAH extends Gui {
private boolean shouldUpdateSearch = false;
private boolean shouldSortItems = false;
- private int startingBid = 0;
+ private long startingBid = 0;
private String currentAucId = null;
private int clickedMainCategory = -1;
@@ -105,6 +133,8 @@ public class CustomAH extends Gui {
public int guiLeft = -1;
public int guiTop = -1;
+ private String lastSearch = "";
+
private final Category CATEGORY_SWORD = new Category("sword", "Swords", "diamond_sword");
private final Category CATEGORY_ARMOR = new Category("armor", "Armor", "diamond_chestplate");
private final Category CATEGORY_BOWS = new Category("bow", "Bows", "bow");
@@ -247,7 +277,11 @@ public class CustomAH extends Gui {
}
public void setSearch(String search) {
- searchField.setText(search);
+ if (search == null) {
+ searchField.setText(lastSearch);
+ } else {
+ searchField.setText(search);
+ }
updateSearch();
}
@@ -612,7 +646,7 @@ public class CustomAH extends Gui {
}
}
if (priceNumbers.length() > 0) {
- startingBid = Integer.parseInt(priceNumbers.toString());
+ startingBid = Long.parseLong(priceNumbers.toString());
}
}
}
@@ -651,7 +685,7 @@ public class CustomAH extends Gui {
boolean hasAuctionPrice = auctionInfo != null;
boolean hasBazaarPrice = bazaarInfo != null;
- int lowestBin = manager.auctionManager.getLowestBin(internalname);
+ long lowestBin = manager.auctionManager.getLowestBin(internalname);
NumberFormat format = NumberFormat.getInstance(Locale.US);
@@ -1347,7 +1381,7 @@ public class CustomAH extends Gui {
}
}
if (getBinPriceFilterAmount() > -1) {
- int lowestBin =
+ long lowestBin =
NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(
auc.getStack()));
if (lowestBin > 0) {
@@ -1459,8 +1493,15 @@ public class CustomAH extends Gui {
auctionIdsNew.add(entry.getKey());
}
}
+ if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) {
+ lastSearch = "";
+ }
} else {
String query = searchField.getText();
+
+ if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) {
+ lastSearch = query;
+ }
Set<String> dontMatch = new HashSet<>();
HashSet<String> allMatch = new HashSet<>();
@@ -1550,18 +1591,18 @@ public class CustomAH extends Gui {
if (auc2 == null) return -1;
if (sortMode == SORT_MODE_HIGH) {
- int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid);
- int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid);
- int diff = price2 - price1;
+ long price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid);
+ long price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid);
+ long diff = price2 - price1;
if (diff != 0) {
- return diff;
+ return Long.compare(price2, price1);
}
} else if (sortMode == SORT_MODE_LOW) {
- int price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid);
- int price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid);
- int diff = price1 - price2;
+ long price1 = Math.max(auc1.highest_bid_amount, auc1.starting_bid);
+ long price2 = Math.max(auc2.highest_bid_amount, auc2.starting_bid);
+ long diff = price1 - price2;
if (diff != 0) {
- return diff;
+ return Long.compare(price1, price2);
}
} else {
long end1 = auc1.end;
@@ -1589,7 +1630,6 @@ public class CustomAH extends Gui {
return false;
}
- Keyboard.enableRepeatEvents(true);
if (isEditingPrice() && Keyboard.getEventKey() == Keyboard.KEY_RETURN) {
Minecraft.getMinecraft().displayGuiScreen(null);
} else if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
@@ -1652,16 +1692,16 @@ public class CustomAH extends Gui {
priceField.setText((int) (priceI * factor) + end);
}
- private int getPriceFilterAmount() {
+ private long getPriceFilterAmount() {
return getNumberFromTextBox(priceFilterField);
}
- private int getNumberFromTextBox(GuiTextField textField) {
+ private long getNumberFromTextBox(GuiTextField textField) {
if (textField.getText().equals("")) {
return -2;
}
try {
- int parsed = Integer.parseInt(textField.getText());
+ long parsed = Long.parseLong(textField.getText());
if (parsed < 0) {
return -1;
}
@@ -1671,7 +1711,7 @@ public class CustomAH extends Gui {
}
}
- private int getBinPriceFilterAmount() {
+ private long getBinPriceFilterAmount() {
return getNumberFromTextBox(binPriceFilterField);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java
index 9311040d..ca85ca1c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAHGui.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.auction;
import net.minecraft.client.gui.GuiScreen;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java
deleted file mode 100644
index e789e882..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/CollectionConstant.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.github.moulberry.notenoughupdates.collectionlog;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.regex.Pattern;
-
-public class CollectionConstant {
- public static class DropEntry {
- public String type;
- public Pattern regex;
- public HashMap<String, String> items;
- }
-
- public List<DropEntry> dropdata;
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java b/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java
deleted file mode 100644
index dac104c6..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/collectionlog/GuiCollectionLog.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package io.github.moulberry.notenoughupdates.collectionlog;
-
-import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
-import io.github.moulberry.notenoughupdates.core.GlScissorStack;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.util.ResourceLocation;
-import org.lwjgl.opengl.GL11;
-
-public class GuiCollectionLog extends GuiScreen {
- private static final ResourceLocation COLLECTION_LOG_TEX = new ResourceLocation("notenoughupdates:collectionlog.png");
-
- @Override
- public void drawScreen(int mouseX, int mouseY, float partialTicks) {
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledResolution.getScaledWidth();
- int height = scaledResolution.getScaledHeight();
-
- int colwidth = 307;
- int colheight = 187;
-
- int left = width / 2 - colwidth / 2;
- int top = height / 2 - colheight / 2;
-
- BackgroundBlur.renderBlurredBackground(10, width, height, left, top, colwidth, colheight);
- super.drawDefaultBackground();
-
- Utils.drawStringCentered("\u00a7lCollection Log", fontRendererObj, width / 2, top - 27, true, 0xfff5aa00);
-
- String[] cats = {"Bosses", "Dragons", "Slayer", "Dungeons"};
-
- GlStateManager.enableDepth();
-
- GlStateManager.translate(0, 0, 2);
- for (int i = 0; i < 4; i++) {
- if (i == 0) {
- int offset = i == 0 ? 1 : 2;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(left + i * 71, top - 21, 71, 25,
- (71 * offset) / 512f, (71 + 71 * offset) / 512f, 211 / 512f, (211 + 25) / 512f, GL11.GL_NEAREST
- );
-
- Utils.drawStringCentered(cats[i], fontRendererObj, left + i * 71 + 71 / 2, top - 8, true, 0xfff5aa00);
- }
- }
-
- GlStateManager.translate(0, 0, -1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(left, top, colwidth, colheight,
- 0, colwidth / 512f, 0, colheight / 512f, GL11.GL_NEAREST
- );
-
- GlScissorStack.push(0, top + 3, width, top + colheight - 6, scaledResolution);
- int catIndex = 0;
- for (int h = top + 3; h < top + colheight - 6; h += 24) {
- catIndex += 2;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(left, h, 100, 24,
- 0, 100 / 512f, 187 / 512f, 211 / 512f, GL11.GL_NEAREST
- );
-
- fontRendererObj.drawString("Thing " + catIndex, left + 5, h + 2, 0xfff5aa00, true);
- fontRendererObj.drawString("Thing " + (catIndex + 1), left + 5, h + 14, 0xfff5aa00, true);
- }
- GlScissorStack.pop(scaledResolution);
-
- fontRendererObj.drawString("\u00a7lSuperior Dragon", left + 119, top + 8, 0xfff5aa00, true);
- fontRendererObj.drawString(
- "Obtained: " + EnumChatFormatting.YELLOW + "3/5",
- left + 122,
- top + 23,
- 0xfff5aa00,
- true
- );
-
- String killCountText = "Kills: " + EnumChatFormatting.WHITE + "3";
- //int killCountLen = fontRendererObj.getStringWidth(killCountText);
- fontRendererObj.drawString(killCountText, left + 122, top + 68, 0xfff5aa00, true);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(left + colwidth - 196, top, 196, colheight,
- (512 - 196) / 512f, 1, 0 / 512f, colheight / 512f, GL11.GL_NEAREST
- );
-
- GlStateManager.translate(0, 0, -1);
-
- for (int i = 0; i < 4; i++) {
- if (i != 0) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(COLLECTION_LOG_TEX);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(left + i * 71, top - 21, 71, 25,
- 0, 71 / 512f, 211 / 512f, (211 + 25) / 512f, GL11.GL_NEAREST
- );
-
- Utils.drawStringCentered(cats[i], fontRendererObj, left + i * 71 + 71 / 2, top - 8, true, 0xfff5aa00);
- }
- }
-
- super.drawScreen(mouseX, mouseY, partialTicks);
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java
index 8ba87ecd..e0ae7a1a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/ClientCommandBase.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands;
import net.minecraft.command.CommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
index de017cb5..62981a30 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
@@ -1,22 +1,54 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands;
-import io.github.moulberry.notenoughupdates.commands.dev.*;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.dev.DevTestCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.DiagCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.DungeonWinTestCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.EnableStorageCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.NullzeeSphereCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.PackDevCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.ReloadRepoCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.ResetRepoCommand;
+import io.github.moulberry.notenoughupdates.commands.dev.StatsCommand;
import io.github.moulberry.notenoughupdates.commands.dungeon.DhCommand;
import io.github.moulberry.notenoughupdates.commands.dungeon.DnCommand;
import io.github.moulberry.notenoughupdates.commands.dungeon.JoinDungeonCommand;
import io.github.moulberry.notenoughupdates.commands.dungeon.MapCommand;
-import io.github.moulberry.notenoughupdates.commands.help.*;
+import io.github.moulberry.notenoughupdates.commands.help.FeaturesCommand;
+import io.github.moulberry.notenoughupdates.commands.help.HelpCommand;
+import io.github.moulberry.notenoughupdates.commands.help.LinksCommand;
+import io.github.moulberry.notenoughupdates.commands.help.SettingsCommand;
+import io.github.moulberry.notenoughupdates.commands.help.StorageViewerWhyCommand;
import io.github.moulberry.notenoughupdates.commands.misc.AhCommand;
+import io.github.moulberry.notenoughupdates.commands.misc.CalculatorCommand;
import io.github.moulberry.notenoughupdates.commands.misc.CalendarCommand;
import io.github.moulberry.notenoughupdates.commands.misc.CosmeticsCommand;
import io.github.moulberry.notenoughupdates.commands.misc.CustomizeCommand;
+import io.github.moulberry.notenoughupdates.commands.misc.PronounsCommand;
+import io.github.moulberry.notenoughupdates.commands.misc.UpdateCommand;
import io.github.moulberry.notenoughupdates.commands.profile.CataCommand;
import io.github.moulberry.notenoughupdates.commands.profile.PeekCommand;
import io.github.moulberry.notenoughupdates.commands.profile.PvCommand;
import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand;
-import io.github.moulberry.notenoughupdates.commands.repo.ReloadRepoCommand;
-import io.github.moulberry.notenoughupdates.commands.repo.RepoModeCommand;
-import io.github.moulberry.notenoughupdates.commands.repo.ResetRepoCommand;
import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour;
import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor;
@@ -40,11 +72,10 @@ public class Commands {
ClientCommandHandler.instance.registerCommand(new StatsCommand());
ClientCommandHandler.instance.registerCommand(new DevTestCommand());
ClientCommandHandler.instance.registerCommand(new NullzeeSphereCommand());
-
- // Repo Commands
- ClientCommandHandler.instance.registerCommand(new ResetRepoCommand());
- ClientCommandHandler.instance.registerCommand(new RepoModeCommand());
+ ClientCommandHandler.instance.registerCommand(new DiagCommand());
ClientCommandHandler.instance.registerCommand(new ReloadRepoCommand());
+ ClientCommandHandler.instance.registerCommand(new ResetRepoCommand());
+ ClientCommandHandler.instance.registerCommand(new EnableStorageCommand());
// Profile Commands
ClientCommandHandler.instance.registerCommand(new PeekCommand());
@@ -66,7 +97,10 @@ public class Commands {
ClientCommandHandler.instance.registerCommand(new ScreenCommand("neuoverlay", NEUOverlayPlacements::new));
//ClientCommandHandler.instance.registerCommand(new ScreenCommand("neututorial", NeuTutorial::new));
ClientCommandHandler.instance.registerCommand(new AhCommand());
+ ClientCommandHandler.instance.registerCommand(new CalculatorCommand());
ClientCommandHandler.instance.registerCommand(new CalendarCommand());
+ ClientCommandHandler.instance.registerCommand(new UpdateCommand(NotEnoughUpdates.INSTANCE));
+ ClientCommandHandler.instance.registerCommand(new PronounsCommand());
// Fairy Soul Commands
ClientCommandHandler.instance.registerCommand(new FairySouls.FairySoulsCommand());
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java
new file mode 100644
index 00000000..e3738661
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/EntityViewerCommand.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands;
+
+import com.google.common.collect.Lists;
+import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.EntityViewer;
+import net.minecraft.client.Minecraft;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+public class EntityViewerCommand extends ClientCommandBase {
+ public EntityViewerCommand() {
+ super("neushowentity");
+ MinecraftForge.EVENT_BUS.register(this);
+ }
+
+ @Override
+ public List<String> getCommandAliases() {
+ return Lists.newArrayList("neuentityviewer");
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return EnumChatFormatting.RED + "Use /neushowentity list";
+ }
+
+ public void showUsage(ICommandSender sender) {
+ sender.addChatMessage(new ChatComponentText(getCommandUsage(sender)));
+ }
+
+ private final Queue<EntityViewer> queuedGUIS = new ConcurrentLinkedDeque<>();
+
+ @SubscribeEvent
+ public void onTick(TickEvent event) {
+ if (Minecraft.getMinecraft().currentScreen == null) {
+ EntityViewer poll = queuedGUIS.poll();
+ if (poll == null) return;
+ Minecraft.getMinecraft().displayGuiScreen(poll);
+ }
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] strings) throws CommandException {
+ if (strings.length == 0) {
+ showUsage(sender);
+ return;
+ }
+ if (strings[0].equals("list")) {
+ for (String label : EntityViewer.validEntities.keySet()) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.BLUE + " " + label)
+ .setChatStyle(new ChatStyle().setChatClickEvent(
+ new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/neuentityviewer " + label))));
+ }
+ return;
+ }
+ EntityLivingBase entityLivingBase;
+ if (strings[0].startsWith("@")) {
+ ResourceLocation resourceLocation = new ResourceLocation(strings[0].substring(1));
+ entityLivingBase = EntityViewer.constructEntity(resourceLocation);
+ } else {
+ entityLivingBase = EntityViewer.constructEntity(strings[0], Arrays.copyOfRange(strings, 1, strings.length));
+ }
+ if (entityLivingBase == null) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Could not create that entity"));
+ return;
+ }
+ queuedGUIS.add(new EntityViewer(strings[0], entityLivingBase));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java
index 29dd9d55..1b90e5df 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/ScreenCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
index 66da4f9f..972557c8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DevTestCommand.java
@@ -1,34 +1,66 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dev;
+import io.github.moulberry.notenoughupdates.BuildFlags;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
import io.github.moulberry.notenoughupdates.core.config.GuiPositionEditor;
-import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals;
import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone;
import io.github.moulberry.notenoughupdates.miscgui.GuiPriceGraph;
+import io.github.moulberry.notenoughupdates.util.PronounDB;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.GuiScreen;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
-import net.minecraft.util.*;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.EnumParticleTypes;
import net.minecraftforge.common.MinecraftForge;
-import java.io.File;
import java.util.Arrays;
import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
public class DevTestCommand extends ClientCommandBase {
private static final List<String> DEV_TESTERS =
- Arrays.asList("moulberry", "lucycoconut", "ironm00n", "ariyio", "throwpo", "lrg89", "dediamondpro");
+ Arrays.asList(
+ "moulberry",
+ "lucycoconut",
+ "ironm00n",
+ "ariyio",
+ "throwpo",
+ "lrg89",
+ "dediamondpro",
+ "lulonaut",
+ "craftyoldminer",
+ "eisengolem",
+ "whalker",
+ "ascynx"
+ );
private static final String[] DEV_FAIL_STRINGS = {
"No.",
@@ -48,9 +80,7 @@ public class DevTestCommand extends ClientCommandBase {
"",
"Ok, this is actually the last message, use the command again and you'll crash I promise"
};
-
private int devFailIndex = 0;
- private final ScheduledExecutorService devES = Executors.newSingleThreadScheduledExecutor();
public DevTestCommand() {
super("neudevtest");
@@ -84,10 +114,6 @@ public class DevTestCommand extends ClientCommandBase {
DEV_FAIL_STRINGS[devFailIndex++]));
return;
}
- /*if(args.length == 1) {
- DupePOC.doDupe(args[0]);
- return;
- }*/
if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) {
String currentProfile = SBInfo.getInstance().currentProfile;
SBInfo.Gamemode gamemode = SBInfo.getInstance().getGamemodeForProfile(currentProfile);
@@ -97,6 +123,14 @@ public class DevTestCommand extends ClientCommandBase {
" with the mode " +
gamemode));
}
+ if (args.length >= 1 && args[0].equalsIgnoreCase("buildflags")) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "BuildFlags: \n" +
+ BuildFlags.getAllFlags().entrySet().stream()
+ .map(it -> " + " + it.getKey() + " - " + it.getValue())
+ .collect(Collectors.joining("\n"))));
+ return;
+ }
if (args.length >= 1 && args[0].equalsIgnoreCase("pricetest")) {
if (args.length == 1) {
NotEnoughUpdates.INSTANCE.manager.auctionManager.updateBazaar();
@@ -142,66 +176,24 @@ public class DevTestCommand extends ClientCommandBase {
"I would never search"));
return;
}
+ if (args.length == 1 && args[0].equalsIgnoreCase("bluehair")) {
+ PronounDB.test();
+ return;
+ }
+ if (args.length == 2 && args[0].equalsIgnoreCase("openGui")) {
+ try {
+ NotEnoughUpdates.INSTANCE.openGui = (GuiScreen) Class.forName(args[1]).newInstance();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "Opening gui: " + NotEnoughUpdates.INSTANCE.openGui));
+ } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | ClassCastException e) {
+ e.printStackTrace();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Failed to open this gui."));
+ }
+ }
if (args.length == 1 && args[0].equalsIgnoreCase("center")) {
double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f;
double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f;
Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z);
- return;
}
- if (args.length == 1 && args[0].equalsIgnoreCase("pansc")) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN +
- "Taking panorama screenshot"));
-
- AtomicInteger perspective = new AtomicInteger(0);
- FancyPortals.perspectiveId = 0;
-
- EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
- p.prevRotationYaw = p.rotationYaw = 0;
- p.prevRotationPitch = p.rotationPitch = 90;
- devES.schedule(new Runnable() {
- @Override
- public void run() {
- Minecraft.getMinecraft().addScheduledTask(() -> {
- ScreenShotHelper.saveScreenshot(new File("C:/Users/James/Desktop/"), "pansc-" + perspective.get() + ".png",
- Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight,
- Minecraft.getMinecraft().getFramebuffer()
- );
- });
- if (perspective.incrementAndGet() >= 6) {
- FancyPortals.perspectiveId = -1;
- return;
- }
- devES.schedule(() -> {
- FancyPortals.perspectiveId = perspective.get();
- if (FancyPortals.perspectiveId == 5) {
- p.prevRotationYaw = p.rotationYaw = 0;
- p.prevRotationPitch = p.rotationPitch = -90;
- } else if (FancyPortals.perspectiveId >= 1 && FancyPortals.perspectiveId <= 4) {
- float yaw = 90 * FancyPortals.perspectiveId - 180;
- if (yaw > 180) yaw -= 360;
- p.prevRotationYaw = p.rotationYaw = yaw;
- p.prevRotationPitch = p.rotationPitch = 0;
- }
- devES.schedule(this, 3000L, TimeUnit.MILLISECONDS);
- }, 100L, TimeUnit.MILLISECONDS);
- }
- }, 3000L, TimeUnit.MILLISECONDS);
-
- return;
- }
-
- /* if(args.length == 1 && args[0].equalsIgnoreCase("update")) {
- NEUEventListener.displayUpdateMessageIfOutOfDate();
- } */
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN +
- "Executing dubious code"));
- /*Minecraft.getMinecraft().thePlayer.rotationYaw = 0;
- Minecraft.getMinecraft().thePlayer.rotationPitch = 0;
- Minecraft.getMinecraft().thePlayer.setPosition(
- Math.floor(Minecraft.getMinecraft().thePlayer.posX) + Float.parseFloat(args[0]),
- Minecraft.getMinecraft().thePlayer.posY,
- Minecraft.getMinecraft().thePlayer.posZ);*/
- //Hot reload me yay!
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java
new file mode 100644
index 00000000..fb546efb
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DiagCommand.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.dev;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+
+public class DiagCommand extends ClientCommandBase {
+ public DiagCommand() {
+ super("neudiag");
+ }
+
+ private static final String USAGE_TEXT = EnumChatFormatting.WHITE +
+ "Usage: /neudiag <metal | wishing | debug>\n\n" +
+ "/neudiag metal Metal Detector Solver diagnostics\n" +
+ " <no sub-command> Show current solution diags\n" +
+ " center=<off | on> Disable / enable using center\n" +
+ "/neudiag wishing Wishing Compass Solver diagnostics\n" +
+ "/neudiag debug\n" +
+ " <no sub-command> Show all enabled flags\n" +
+ " <list> Show all flags\n"+
+ " <enable | disable> <flag> Enable/disable flag\n";
+
+ private void showUsage(ICommandSender sender) {
+ sender.addChatMessage(new ChatComponentText(USAGE_TEXT));
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ if (args.length == 0) {
+ showUsage(sender);
+ return;
+ }
+
+ String command = args[0].toLowerCase();
+ switch (command) {
+ case "metal":
+ if (args.length == 1) {
+ CrystalMetalDetectorSolver.logDiagnosticData(true);
+ return;
+ }
+
+ String subCommand = args[1].toLowerCase();
+ if (subCommand.equals("center=off")) {
+ CrystalMetalDetectorSolver.setDebugDoNotUseCenter(true);
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "Center coordinates-based solutions disabled"));
+ } else if (subCommand.equals("center=on")) {
+ CrystalMetalDetectorSolver.setDebugDoNotUseCenter(false);
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "Center coordinates-based solutions enabled"));
+ } else {
+ showUsage(sender);
+ return;
+ }
+
+ break;
+ case "wishing":
+ CrystalWishingCompassSolver.getInstance().logDiagnosticData(true);
+ break;
+ case "debug":
+ if (args.length > 1) {
+ boolean enablingFlag = true;
+ String action = args[1];
+ switch (action) {
+ case "list":
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW + "Here are all flags:\n" + NEUDebugFlag.getFlagList()));
+ return;
+ case "disable":
+ enablingFlag = false;
+ // falls through
+ case "enable":
+ if (args.length != 3) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "You must specify a flag:\n" +
+ NEUDebugFlag.getFlagList()));
+ return;
+ }
+
+ String flagName = args[2].toUpperCase();
+ try {
+ NEUDebugFlag debugFlag = NEUDebugFlag.valueOf(flagName);
+ if (enablingFlag) {
+ NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.add(debugFlag);
+ } else {
+ NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.remove(debugFlag);
+ }
+ } catch (IllegalArgumentException e) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ flagName + " is invalid. Valid flags are:\n" +
+ NEUDebugFlag.getFlagList()));
+ return;
+ }
+ break;
+ default:
+ showUsage(sender);
+ return;
+ }
+ }
+
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Effective debug flags: \n" +
+ NEUDebugFlag.getEnabledFlags()));
+ break;
+ default:
+ showUsage(sender);
+ return;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java
index 223e154a..be25e697 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/DungeonWinTestCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dev;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/EnableStorageCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/EnableStorageCommand.java
new file mode 100644
index 00000000..3415b030
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/EnableStorageCommand.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.dev;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+
+public class EnableStorageCommand extends ClientCommandBase {
+
+ public EnableStorageCommand() {
+ super("neuenablestorage");
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3 = true;
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java
index 64d64545..3a9ce90f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/NullzeeSphereCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dev;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java
index e809ed72..e1504472 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/PackDevCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dev;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -5,55 +24,281 @@ import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
import io.github.moulberry.notenoughupdates.core.util.MiscUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.AbstractClientPlayer;
-import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityArmorStand;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Supplier;
+
public class PackDevCommand extends ClientCommandBase {
+ static Minecraft mc = Minecraft.getMinecraft();
public PackDevCommand() {
super("neupackdev");
}
+ private static final HashMap<String, Command<?, ?>> commands = new HashMap<String, Command<?, ?>>() {{
+ put(
+ "getnpc",
+ new Command<>(
+ "NPC",
+ () -> mc.theWorld.playerEntities,
+ true,
+ AbstractClientPlayer.class
+ )
+ );
+ put(
+ "getnpcs",
+ new Command<>(
+ "NPC",
+ () -> mc.theWorld.playerEntities,
+ false,
+ AbstractClientPlayer.class
+ )
+ );
+ put(
+ "getmob",
+ new Command<>(
+ "mob",
+ () -> mc.theWorld.loadedEntityList,
+ true,
+ EntityLiving.class
+ )
+ );
+ put(
+ "getmobs",
+ new Command<>(
+ "mob",
+ () -> mc.theWorld.loadedEntityList,
+ false,
+ EntityLiving.class
+ )
+ );
+ put(
+ "getarmorstand",
+ new Command<>(
+ "armor stand",
+ () -> mc.theWorld.loadedEntityList,
+ true,
+ EntityArmorStand.class
+ )
+ );
+ put(
+ "getarmorstands",
+ new Command<>(
+ "armor stand",
+ () -> mc.theWorld.loadedEntityList,
+ false,
+ EntityArmorStand.class
+ )
+ );
+ }};
+
+ @Override
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
+ return args.length == 1 ? getListOfStringsMatchingLastWord(args, commands.keySet()) : null;
+ }
+
+ public static void togglePackDeveloperMode(ICommandSender sender) {
+ NotEnoughUpdates.INSTANCE.packDevEnabled = !NotEnoughUpdates.INSTANCE.packDevEnabled;
+ if (NotEnoughUpdates.INSTANCE.packDevEnabled) {
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.GREEN + "Enabled pack developer mode."));
+ } else {
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Disabled pack developer mode."));
+ }
+ }
+
@Override
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- if (args.length == 1 && args[0].equalsIgnoreCase("getnpc")) {
- double distSq = 25;
- EntityPlayer closestNPC = null;
- EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
- for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
- if (player instanceof AbstractClientPlayer && p != player && player.getUniqueID().version() != 4) {
- double dSq = player.getDistanceSq(p.posX, p.posY, p.posZ);
- if (dSq < distSq) {
- distSq = dSq;
- closestNPC = player;
+ if (args.length == 0) {
+ togglePackDeveloperMode(sender);
+ return;
+ }
+
+ double dist = 5.0;
+ if (args.length >= 2) {
+ try {
+ dist = Double.parseDouble(args[1]);
+ } catch (NumberFormatException e) {
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Invalid distance! Must be a number, defaulting to a radius of 5."));
+ }
+ }
+
+ StringBuilder output;
+ String subCommand = args[0].toLowerCase();
+ if (commands.containsKey(subCommand)) {
+ Command<?, ?> command = commands.get(subCommand);
+ output = command.getData(dist);
+ } else if (subCommand.equals("getall")) {
+ output = getAll(dist);
+ } else if (subCommand.equals("getallclose")) {
+ output = getAllClose(dist);
+ } else {
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Invalid sub-command."));
+ return;
+ }
+
+ if (output.length() != 0) {
+ MiscUtils.copyToClipboard(output.toString());
+ }
+ }
+
+ private static StringBuilder getAllClose(Double dist) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(commands.get("getmob").getData(dist));
+ sb.append(commands.get("getarmorstand").getData(dist));
+ sb.append(commands.get("getnpc").getData(dist));
+ return sb;
+ }
+
+ private static StringBuilder getAll(Double dist) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(commands.get("getmobs").getData(dist));
+ sb.append(commands.get("getarmorstands").getData(dist));
+ sb.append(commands.get("getnpcs").getData(dist));
+ return sb;
+ }
+
+ public static <T extends EntityLivingBase> StringBuilder livingBaseDataBuilder(T entity, Class<T> clazz) {
+ StringBuilder entityData = new StringBuilder();
+ if (EntityPlayer.class.isAssignableFrom(entity.getClass())) {
+ EntityPlayer entityPlayer = (EntityPlayer) entity;
+
+ // NPC Information
+ String skinResourcePath = ((AbstractClientPlayer) entityPlayer).getLocationSkin().getResourcePath();
+ entityData
+ .append("Player Id: ")
+ .append(entityPlayer.getUniqueID() != null ? entityPlayer.getUniqueID().toString() : "null")
+ .append(entityPlayer.getCustomNameTag() != null ? entityPlayer.getCustomNameTag() : "null")
+ .append("\nEntity Texture Id: ")
+ .append(skinResourcePath != null ? skinResourcePath.replace("skins/", "") : "null");
+ }
+
+ if (!clazz.isAssignableFrom(entity.getClass())) {
+ return entityData;
+ }
+
+ //Entity Information
+ entityData
+ .append("Entity Id: ")
+ .append(entity.getEntityId())
+ .append("\nMob: ")
+ .append(entity.getName() != null ? entity.getName() : "null")
+ .append("\nCustom Name: ")
+ .append(entity.getCustomNameTag() != null ? entity.getCustomNameTag() : "null");
+
+ //Held Item
+ if (entity.getHeldItem() != null) {
+ entityData
+ .append("\nItem: ")
+ .append(entity.getHeldItem())
+ .append("\nItem Display Name: ")
+ .append(entity.getHeldItem().getDisplayName() != null
+ ? entity.getHeldItem().getDisplayName()
+ : "null")
+ .append("\nItem Tag Compound: ");
+ NBTTagCompound heldItemTagCompound = entity.getHeldItem().getTagCompound();
+ if (heldItemTagCompound != null) {
+ String heldItemString = heldItemTagCompound.toString();
+ NBTBase extraAttrTag = heldItemTagCompound.getTag("ExtraAttributes");
+ entityData
+ .append(heldItemString != null ? heldItemString : "null")
+ .append("\nItem Tag Compound Extra Attributes: ")
+ .append(extraAttrTag != null ? extraAttrTag : "null");
+ } else {
+ entityData.append("null");
+ }
+
+ } else {
+ entityData.append("\nItem: null");
+ }
+
+ entityData.append(armorDataBuilder(entity)).append("\n\n");
+
+ return entityData;
+ }
+
+ private static final String[] armorPieceTypes = {"Boots", "Leggings", "Chestplate", "Helmet"};
+
+ public static <T extends EntityLivingBase> StringBuilder armorDataBuilder(T entity) {
+ StringBuilder armorData = new StringBuilder();
+ for (int i = 0; i < 4; i++) {
+ ItemStack currentArmor = entity.getCurrentArmor(0);
+ armorData.append(String.format("\n%s: ", armorPieceTypes[i]));
+ if (currentArmor == null) {
+ armorData.append("null");
+ } else {
+ armorData.append(currentArmor.getTagCompound() != null ? currentArmor.getTagCompound().toString() : "null");
+ }
+ }
+ return armorData;
+ }
+
+ static class Command<T extends EntityLivingBase, U extends Entity> {
+ String typeFriendlyName;
+ Supplier<List<U>> entitySupplier;
+ Class<T> clazz;
+ boolean single;
+
+ Command(
+ String typeFriendlyName,
+ Supplier<List<U>> entitySupplier,
+ boolean single,
+ Class<T> clazz
+ ) {
+ this.typeFriendlyName = typeFriendlyName;
+ this.entitySupplier = entitySupplier;
+ this.single = single;
+ this.clazz = clazz;
+ }
+
+ @SuppressWarnings("unchecked")
+ public StringBuilder getData(double dist) {
+ StringBuilder result = new StringBuilder();
+ double distSq = dist * dist;
+ T closest = null;
+ for (Entity entity : entitySupplier.get()) {
+ if (!clazz.isAssignableFrom(entity.getClass()) || entity == mc.thePlayer) {
+ continue;
+ }
+ T entityT = (T) entity;
+ double entityDistanceSq = entity.getDistanceSq(mc.thePlayer.posX, mc.thePlayer.posY, mc.thePlayer.posZ);
+ if (entityDistanceSq < distSq) {
+ if (single) {
+ distSq = entityDistanceSq;
+ closest = entityT;
+ } else {
+ result.append(livingBaseDataBuilder(entityT, clazz));
}
}
}
- if (closestNPC == null) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.RED + "No NPCs found within 5 blocks :("));
+ if ((single && closest == null) || (!single && result.length() == 0)) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "No " + typeFriendlyName + "s found within " + dist + " blocks."));
} else {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.GREEN + "Copied entity texture id to clipboard"));
- MiscUtils.copyToClipboard(((AbstractClientPlayer) closestNPC)
- .getLocationSkin()
- .getResourcePath()
- .replace("skins/", ""));
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.GREEN + "Copied " + typeFriendlyName + " data to clipboard"));
+ return single ? livingBaseDataBuilder(closest, clazz) : result;
}
- return;
- }
- NotEnoughUpdates.INSTANCE.packDevEnabled = !NotEnoughUpdates.INSTANCE.packDevEnabled;
- if (NotEnoughUpdates.INSTANCE.packDevEnabled) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.GREEN + "Enabled pack developer mode."));
- } else {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.RED + "Disabled pack developer mode."));
+
+ return result;
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ReloadRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ReloadRepoCommand.java
new file mode 100644
index 00000000..0bf57594
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ReloadRepoCommand.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.dev;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+
+public class ReloadRepoCommand extends ClientCommandBase {
+
+ public ReloadRepoCommand() {
+ super("neureloadrepo");
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ NotEnoughUpdates.INSTANCE.manager.reloadRepository();
+ sender.addChatMessage(new ChatComponentText("§e[NEU] Reloaded repository."));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ResetRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ResetRepoCommand.java
new file mode 100644
index 00000000..3f693898
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/ResetRepoCommand.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.dev;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+
+public class ResetRepoCommand extends ClientCommandBase {
+
+ public ResetRepoCommand() {
+ super("neuresetrepo");
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ NotEnoughUpdates.INSTANCE.manager
+ .userFacingRepositoryReload()
+ .thenAccept(strings ->
+ strings.forEach(line ->
+ sender.addChatMessage(new ChatComponentText("§e[NEU] " + line))));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java
index 38eafe39..756afc88 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dev/StatsCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dev;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -146,7 +165,7 @@ public class StatsCommand extends ClientCommandBase {
builder.append("Loaded Mods", String.valueOf(activeModCount));
builder.append("Forge", ForgeVersion.getVersion());
builder.category("Neu Settings");
- builder.append("API Key", NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.isEmpty() ? "FALSE" : "TRUE");
+ builder.append("API Key", NotEnoughUpdates.INSTANCE.config.apiData.apiKey.isEmpty() ? "FALSE" : "TRUE");
builder.append("On Skyblock", NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() ? "TRUE" : "FALSE");
builder.append(
"Mod Version",
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java
index 89299a36..222862f9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DhCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dungeon;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java
index 8fbbceba..a5a7bcca 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/DnCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dungeon;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java
index 874e81db..d69f86f3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/JoinDungeonCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dungeon;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java
index ae06a346..f5381adb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/dungeon/MapCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.dungeon;
import com.google.gson.JsonElement;
@@ -31,6 +50,7 @@ public class MapCommand extends ClientCommandBase {
@Override
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+
if (NotEnoughUpdates.INSTANCE.colourMap == null) {
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java
index 593f2575..5f709c4f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/FeaturesCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.help;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java
index 9669be60..7655f561 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/HelpCommand.java
@@ -1,15 +1,32 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.help;
import com.google.common.collect.Lists;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
import net.minecraft.client.Minecraft;
-import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.util.ChatComponentText;
import java.util.ArrayList;
-import java.util.List;
public class HelpCommand extends ClientCommandBase {
@@ -33,8 +50,8 @@ public class HelpCommand extends ClientCommandBase {
"\u00a76/neulinks \u00a7r\u00a77- Shows links to neu/moulberry.",
"\u00a76/neuoverlay \u00a7r\u00a77- Opens GUI Editor for quickcommands and searchbar.",
"\u00a76/neuah \u00a7r\u00a77- Opens neu's custom ah GUI.",
- "\u00a76/neumap \u00a7r\u00a77- Opens the dungeon map GUI.",
"\u00a76/neucalendar \u00a7r\u00a77- Opens neu's custom calendar GUI.",
+ "\u00a76/neucalc \u00a7r\u00a77- Run calculations.",
"",
"\u00a76\u00a7lOld commands:",
"\u00a76/peek \u00a7b?{user} \u00a72\u2D35 \u00a7r\u00a77- Shows quickly stats for a user.",
@@ -46,7 +63,7 @@ public class HelpCommand extends ClientCommandBase {
"\u00a76/neureloadrepo \u00a7r\u00a77- Debug command with repo.",
"",
"\u00a76\u00a7lDev commands:",
- "\u00a76/neupackdev \u00a7r\u00a77- pack creator command - getnpc"
+ "\u00a76/neupackdev \u00a7r\u00a77- pack creator command - getnpc, getmob(s), getarmorstand(s), getall. Optional radius argument for all."
);
for (String neuHelpMessage : neuHelpMessages) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(neuHelpMessage));
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java
index c81f44a8..9938403c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/LinksCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.help;
import com.google.gson.JsonObject;
@@ -25,7 +44,7 @@ public class LinksCommand extends ClientCommandBase {
JsonObject update = NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(updateJson);
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- NotEnoughUpdates.INSTANCE.displayLinks(update);
+ NotEnoughUpdates.INSTANCE.displayLinks(update,0 );
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
} catch (Exception ignored) {
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java
index 08350be9..9964b739 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/SettingsCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.help;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java
index 4f85c26e..820c6f2a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/help/StorageViewerWhyCommand.java
@@ -1,8 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.help;
import com.google.common.collect.Lists;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import net.minecraft.command.ICommandSender;
public class StorageViewerWhyCommand extends ClientCommandBase {
@@ -13,7 +32,7 @@ public class StorageViewerWhyCommand extends ClientCommandBase {
@Override
public void processCommand(ICommandSender sender, String[] args) {
- NEUEventListener.displayNotification(Lists.newArrayList(
+ NotificationHandler.displayNotification(Lists.newArrayList(
"\u00a7eStorage Viewer",
"\u00a77Currently, the storage viewer requires you to click twice",
"\u00a77in order to switch between pages. This is because Hypixel",
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java
index 0b2c155e..bd8abf1d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/AhCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.misc;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -21,8 +40,8 @@ public class AhCommand extends ClientCommandBase {
if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
"You must be on Skyblock to use this feature."));
- } else if (NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null ||
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) {
+ } else if (NotEnoughUpdates.INSTANCE.config.apiData.apiKey == null ||
+ NotEnoughUpdates.INSTANCE.config.apiData.apiKey.trim().isEmpty()) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
"Can't open NeuAH, apikey is not set. Run /api new and put the result in settings."));
} else {
@@ -31,8 +50,13 @@ public class AhCommand extends ClientCommandBase {
NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.clearSearch();
NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.updateSearch();
- if (args.length > 0)
+ if (args.length > 0) {
NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(StringUtils.join(args, " "));
+ } else {
+ if (NotEnoughUpdates.INSTANCE.config.neuAuctionHouse.saveLastSearch) {
+ NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.setSearch(null);
+ }
+ }
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java
index 63d5c327..55113462 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/ButtonsCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.misc;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java
new file mode 100644
index 00000000..2ba93585
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalculatorCommand.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.misc;
+
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import io.github.moulberry.notenoughupdates.util.Calculator;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.text.DecimalFormat;
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+public class CalculatorCommand extends ClientCommandBase {
+ public CalculatorCommand() {
+ super("neucalc");
+ }
+
+ @Override
+ public List<String> getCommandAliases() {
+ return Arrays.asList("neucalculator");
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ if ((args.length == 1 && Objects.equals(args[0], "help")) || args.length == 0) {
+ sender.addChatMessage(new ChatComponentText(
+ "\n§e[NEU] §5It's a calculator.\n" +
+ "§eFor Example §b/neucalc 3m*7k§e.\n" +
+ "§eYou can also use suffixes (k, m, b, t, s)§e.\n" +
+ "§eThe \"s\" suffix acts as 64.\n" +
+ "§eTurn on Sign Calculator in /neu misc to also support this in sign popups and the neu search bar.\n"));
+ return;
+ }
+ String source = String.join(" ", args);
+ try {
+ BigDecimal calculate = Calculator.calculate(source);
+ DecimalFormat formatter = new DecimalFormat("#,##0.##");
+ String format = formatter.format(calculate);
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] " + EnumChatFormatting.WHITE + source + " " + EnumChatFormatting.YELLOW +
+ "= " + EnumChatFormatting.GREEN + format
+ ));
+ } catch (Calculator.CalculatorException e) {
+ sender.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] " + EnumChatFormatting.RED + "Error during calculation: " +
+ e.getMessage() + "\n" +
+ EnumChatFormatting.WHITE + source.substring(0, e.getOffset()) + EnumChatFormatting.DARK_RED +
+ source.substring(e.getOffset(), e.getLength() + e.getOffset()) + EnumChatFormatting.GRAY +
+ source.substring(e.getLength() + e.getOffset())
+ ));
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java
index d3c472bd..58c13474 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CalendarCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.misc;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java
deleted file mode 100644
index 1bde7631..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CollectionLogCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.github.moulberry.notenoughupdates.commands.misc;
-
-import io.github.moulberry.notenoughupdates.collectionlog.GuiCollectionLog;
-import io.github.moulberry.notenoughupdates.commands.ScreenCommand;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-public class CollectionLogCommand extends ScreenCommand {
-
- public CollectionLogCommand() {
- super("neucl", GuiCollectionLog::new);
- }
-
- @Override
- public List<String> getCommandAliases() {
- return Collections.singletonList("collectionlog");
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java
index 9ccb7cf0..f74b5813 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CosmeticsCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.misc;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -18,7 +37,7 @@ public class CosmeticsCommand extends ClientCommandBase {
@Override
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- if (!OpenGlHelper.isFramebufferEnabled()) {
+ if (!OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.notifications.doFastRenderNotif) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
"NEU cosmetics do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it."));
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java
index 6bce4f5a..cca6535e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/CustomizeCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.misc;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -9,7 +28,6 @@ import net.minecraft.command.ICommandSender;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ChatComponentText;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java
deleted file mode 100644
index d33e560a..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/GamemodesCommand.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.github.moulberry.notenoughupdates.commands.misc;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
-import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes;
-import net.minecraft.command.CommandException;
-import net.minecraft.command.ICommandSender;
-
-public class GamemodesCommand extends ClientCommandBase {
-
- public GamemodesCommand() {
- super("neugamemodes");
- }
-
- @Override
- public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- boolean upgradeOverride = args.length == 1 && args[0].equals("upgradeOverride");
- NotEnoughUpdates.INSTANCE.openGui = new GuiGamemodes(upgradeOverride);
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java
new file mode 100644
index 00000000..5a4f1400
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/PronounsCommand.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.misc;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import io.github.moulberry.notenoughupdates.util.MinecraftExecutor;
+import io.github.moulberry.notenoughupdates.util.PronounDB;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiNewChat;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+
+import java.util.Optional;
+import java.util.Random;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+
+public class PronounsCommand extends ClientCommandBase {
+ public PronounsCommand() {
+ super("neupronouns");
+ }
+
+ @Override
+ public String getCommandUsage(ICommandSender sender) {
+ return "/neupronouns <username> [platform]";
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ switch (args.length) {
+ case 1:
+ fetchPronouns("minecraft", args[0]);
+ break;
+ case 2:
+ fetchPronouns(args[1], args[0]);
+ break;
+ default:
+ sender.addChatMessage(new ChatComponentText("§4" + getCommandUsage(sender)));
+ }
+ }
+
+ private void fetchPronouns(String platform, String user) {
+ GuiNewChat nc = Minecraft.getMinecraft().ingameGUI.getChatGUI();
+ int id = new Random().nextInt();
+ nc.printChatMessageWithOptionalDeletion(new ChatComponentText("§e[NEU] Fetching Pronouns..."), id);
+
+ CompletableFuture<Optional<PronounDB.PronounChoice>> pronouns;
+ if ("minecraft".equals(platform)) {
+ CompletableFuture<UUID> c = new CompletableFuture<>();
+ NotEnoughUpdates.profileViewer.getPlayerUUID(user, uuidString -> {
+ if (uuidString == null) {
+ c.completeExceptionally(new NullPointerException());
+ } else {
+ c.complete(Utils.parseDashlessUUID(uuidString));
+ }
+ });
+ pronouns = c.thenCompose(PronounDB::getPronounsFor);
+ } else {
+ pronouns = PronounDB.getPronounsFor(platform, user);
+ }
+ pronouns.handleAsync((pronounChoice, throwable) -> {
+ if (throwable != null || !pronounChoice.isPresent()) {
+ nc.printChatMessageWithOptionalDeletion(new ChatComponentText("§e[NEU] §4Failed to fetch pronouns."), id);
+ return null;
+ }
+ PronounDB.PronounChoice betterPronounChoice = pronounChoice.get();
+ nc.printChatMessageWithOptionalDeletion(new ChatComponentText(
+ "§e[NEU] Pronouns for §b" + user + " §eon §b" + platform + "§e:"), id);
+ betterPronounChoice.render().forEach(it -> nc.printChatMessage(new ChatComponentText("§e[NEU] §a" + it)));
+ return null;
+ }, MinecraftExecutor.INSTANCE);
+
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java
new file mode 100644
index 00000000..cac93369
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/misc/UpdateCommand.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.commands.misc;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
+import net.minecraft.command.CommandException;
+import net.minecraft.command.ICommandSender;
+import net.minecraft.util.ChatComponentText;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+
+public class UpdateCommand extends ClientCommandBase {
+ NotEnoughUpdates neu;
+
+ public UpdateCommand(NotEnoughUpdates neu) {
+ super("neuupdate");
+ this.neu = neu;
+ }
+
+ @Override
+ public List<String> getCommandAliases() {
+ return Arrays.asList("neuupdates", "enoughupdates");
+ }
+
+ public void displayHelp(ICommandSender sender) {
+ sender.addChatMessage(new ChatComponentText(
+ "" +
+ "§e[NEU] §b/neuupdate help - View help.\n" +
+ "§e[NEU] §b/neuupdate check - Check for updates.\n" +
+ ""
+ ));
+
+ }
+
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) throws CommandException {
+ if ((args.length == 1 && Objects.equals(args[0], "help")) || args.length == 0) {
+ displayHelp(sender);
+ return;
+ }
+ switch (args[0].toLowerCase().intern()) {
+ case "check":
+ neu.autoUpdater.displayUpdateMessageIfOutOfDate();
+ break;
+ case "scheduledownload":
+ neu.autoUpdater.scheduleDownload();
+ break;
+ case "updatemodes":
+ sender.addChatMessage(new ChatComponentText("§e[NEU] §bTo ensure we do not accidentally corrupt your mod folder, we can only offer support for autoupdates on system with certain capabilities for file deletions (specifically unix systems). You can still manually update your files"));
+ break;
+ default:
+ displayHelp(sender);
+
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java
index 09253e50..afc47418 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/CataCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.profile;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
@@ -11,7 +30,7 @@ public class CataCommand extends ViewProfileCommand {
@Override
public void processCommand(ICommandSender sender, String[] args) {
- GuiProfileViewer.currentPage = GuiProfileViewer.ProfileViewerPage.DUNG;
+ GuiProfileViewer.currentPage = GuiProfileViewer.ProfileViewerPage.DUNGEON;
super.processCommand(sender, args);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java
index d69139aa..75e779fc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PeekCommand.java
@@ -1,10 +1,29 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.profile;
-import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.command.CommandException;
@@ -16,16 +35,19 @@ import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.lang3.text.WordUtils;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class PeekCommand extends ClientCommandBase {
private ScheduledExecutorService peekCommandExecutorService = null;
+ private ScheduledFuture<?> peekScheduledFuture = null;
public PeekCommand() {
super("peek");
@@ -50,23 +72,23 @@ public class PeekCommand extends ClientCommandBase {
} else {
profile.resetCache();
- if (peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) {
+ if (peekCommandExecutorService == null) {
peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor();
- } else {
+ }
+
+ if (peekScheduledFuture != null && !peekScheduledFuture.isDone()) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
EnumChatFormatting.RED + "[PEEK] New peek command run, cancelling old one."));
- peekCommandExecutorService.shutdownNow();
- peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor();
+ peekScheduledFuture.cancel(true);
}
Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(
EnumChatFormatting.YELLOW + "[PEEK] Getting the player's Skyblock profile(s)..."), id);
long startTime = System.currentTimeMillis();
- peekCommandExecutorService.schedule(new Runnable() {
+ peekScheduledFuture = peekCommandExecutorService.schedule(new Runnable() {
public void run() {
if (System.currentTimeMillis() - startTime > 10 * 1000) {
-
Minecraft.getMinecraft().ingameGUI
.getChatGUI()
.printChatMessageWithOptionalDeletion(new ChatComponentText(
@@ -83,7 +105,8 @@ public class PeekCommand extends ClientCommandBase {
boolean isMe = name.equalsIgnoreCase("moulberry");
PlayerStats.Stats stats = profile.getStats(null);
- JsonObject skill = profile.getSkillInfo(null);
+ if (stats == null) return;
+ Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(null);
Minecraft.getMinecraft().ingameGUI
.getChatGUI()
@@ -92,27 +115,25 @@ public class PeekCommand extends ClientCommandBase {
Utils.getElementAsString(profile.getHypixelProfile().get("displayname"), name) + "'s Info " +
EnumChatFormatting.STRIKETHROUGH + "-=-"), id);
- if (skill == null) {
+ if (skyblockInfo == null) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "Skills api disabled!"));
+ EnumChatFormatting.YELLOW + "Skills API disabled!"));
} else {
float totalSkillLVL = 0;
float totalSkillCount = 0;
- for (Map.Entry<String, JsonElement> entry : skill.entrySet()) {
- if (entry.getKey().startsWith("level_skill")) {
- if (entry.getKey().contains("runecrafting")) continue;
- if (entry.getKey().contains("carpentry")) continue;
- totalSkillLVL += entry.getValue().getAsFloat();
- totalSkillCount++;
- }
+ List<String> skills = Arrays.asList("taming", "mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy", "carpentry");
+ for (String skillName : skills) {
+ totalSkillLVL += skyblockInfo.get(skillName).level;
+ totalSkillCount++;
}
- float combat = Utils.getElementAsFloat(skill.get("level_skill_combat"), 0);
- float zombie = Utils.getElementAsFloat(skill.get("level_slayer_zombie"), 0);
- float spider = Utils.getElementAsFloat(skill.get("level_slayer_spider"), 0);
- float wolf = Utils.getElementAsFloat(skill.get("level_slayer_wolf"), 0);
- float enderman = Utils.getElementAsFloat(skill.get("level_slayer_enderman"), 0);
+ float combat = skyblockInfo.get("combat").level;
+ float zombie = skyblockInfo.get("zombie").level;
+ float spider = skyblockInfo.get("spider").level;
+ float wolf = skyblockInfo.get("wolf").level;
+ float enderman = skyblockInfo.get("enderman").level;
+ float blaze = skyblockInfo.get("blaze").level;
float avgSkillLVL = totalSkillLVL / totalSkillCount;
@@ -123,6 +144,7 @@ public class PeekCommand extends ClientCommandBase {
spider = 1;
wolf = 2;
enderman = 0;
+ blaze = 0;
}
EnumChatFormatting combatPrefix = combat > 20
@@ -141,6 +163,11 @@ public class PeekCommand extends ClientCommandBase {
? EnumChatFormatting.GREEN
: EnumChatFormatting.YELLOW)
: EnumChatFormatting.RED;
+ EnumChatFormatting blazePrefix = blaze > 3
+ ? (blaze > 6
+ ? EnumChatFormatting.GREEN
+ : EnumChatFormatting.YELLOW)
+ : EnumChatFormatting.RED;
EnumChatFormatting avgPrefix = avgSkillLVL > 20
? (avgSkillLVL > 35
? EnumChatFormatting.GREEN
@@ -151,9 +178,10 @@ public class PeekCommand extends ClientCommandBase {
overallScore += spider * spider / 81f;
overallScore += wolf * wolf / 81f;
overallScore += enderman * enderman / 81f;
+ overallScore += blaze * blaze / 81f;
overallScore += avgSkillLVL / 20f;
- int cata = (int) Utils.getElementAsFloat(skill.get("level_skill_catacombs"), 0);
+ int cata = (int) skyblockInfo.get("catacombs").level;
EnumChatFormatting cataPrefix = cata > 15
? (cata > 25 ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW)
: EnumChatFormatting.RED;
@@ -167,8 +195,9 @@ public class PeekCommand extends ClientCommandBase {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
g + "Slayer: " + zombiePrefix + (int) Math.floor(zombie) + g + "-" +
spiderPrefix + (int) Math.floor(spider) + g + "-" +
- wolfPrefix + (int) Math.floor(wolf) + "-" +
- endermanPrefix + (int) Math.floor(enderman)));
+ wolfPrefix + (int) Math.floor(wolf) + g+ "-" +
+ endermanPrefix + (int) Math.floor(enderman) + g + "-" +
+ blazePrefix + (int) Math.floor(blaze)));
}
if (stats == null) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
@@ -266,7 +295,7 @@ public class PeekCommand extends ClientCommandBase {
peekCommandExecutorService.shutdownNow();
} else {
- peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS);
+ peekScheduledFuture = peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS);
}
}
}, 200, TimeUnit.MILLISECONDS);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java
index 07394ffd..2d5c05f4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/PvCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.profile;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java
index 371db394..e4ca497c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/profile/ViewProfileCommand.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.commands.profile;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -23,8 +42,8 @@ public class ViewProfileCommand extends ClientCommandBase {
"Some parts of the profile viewer do not work with OF Fast Render. Go to ESC > Options > Video Settings > Performance > Fast Render to disable it."));
}
- if (NotEnoughUpdates.INSTANCE.config.apiKey.apiKey == null ||
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey.trim().isEmpty()) {
+ if (NotEnoughUpdates.INSTANCE.config.apiData.apiKey == null ||
+ NotEnoughUpdates.INSTANCE.config.apiData.apiKey.trim().isEmpty()) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
"Can't view profile, apikey is not set. Run /api new and put the result in settings."));
} else if (args.length == 0) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java
deleted file mode 100644
index e363b59f..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ReloadRepoCommand.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package io.github.moulberry.notenoughupdates.commands.repo;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
-import io.github.moulberry.notenoughupdates.options.NEUConfig;
-import io.github.moulberry.notenoughupdates.util.Constants;
-import net.minecraft.command.CommandException;
-import net.minecraft.command.ICommandSender;
-
-import java.io.BufferedReader;
-import java.io.FileInputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-
-public class ReloadRepoCommand extends ClientCommandBase {
-
- public ReloadRepoCommand() {
- super("neureloadrepo");
- }
-
- @Override
- public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- NotEnoughUpdates.INSTANCE.manager.reloadRepository();
- Constants.reload();
-
- NotEnoughUpdates.INSTANCE.newConfigFile();
- if (NotEnoughUpdates.INSTANCE.getConfigFile().exists()) {
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(NotEnoughUpdates.INSTANCE.getConfigFile()),
- StandardCharsets.UTF_8
- ))
- ) {
- NotEnoughUpdates.INSTANCE.config = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, NEUConfig.class);
- } catch (Exception ignored) {
- }
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java
deleted file mode 100644
index bb6e1675..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/RepoModeCommand.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package io.github.moulberry.notenoughupdates.commands.repo;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
-import net.minecraft.client.Minecraft;
-import net.minecraft.command.CommandException;
-import net.minecraft.command.ICommandSender;
-import net.minecraft.util.ChatComponentText;
-
-public class RepoModeCommand extends ClientCommandBase {
-
- public RepoModeCommand() {
- super("neurepomode");
- }
-
- @Override
- public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- NotEnoughUpdates.INSTANCE.config.hidden.dev = !NotEnoughUpdates.INSTANCE.config.hidden.dev;
- NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing =
- !NotEnoughUpdates.INSTANCE.config.hidden.enableItemEditing;
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("\u00a75Toggled NEU repo dev mode."));
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java
deleted file mode 100644
index b9a0d7cd..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/repo/ResetRepoCommand.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.moulberry.notenoughupdates.commands.repo;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.commands.ClientCommandBase;
-import net.minecraft.command.CommandException;
-import net.minecraft.command.ICommandSender;
-
-public class ResetRepoCommand extends ClientCommandBase {
-
- public ResetRepoCommand() {
- super("neuresetrepo");
- }
-
- @Override
- public void processCommand(ICommandSender sender, String[] args) throws CommandException {
- NotEnoughUpdates.INSTANCE.manager.resetRepo();
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java
index c85841b3..fc2be97b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java
index 8f4dd87d..05a9a65e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/ChromaColour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import java.awt.*;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java
index 7cc8893f..40b9fe7a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GlScissorStack.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import net.minecraft.client.Minecraft;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java
index c1c76675..2a684164 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElement.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import net.minecraft.client.gui.Gui;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
index d5cbb3ad..b0586210 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java
index 48996c8d..1f655aaf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
index 51a4654c..45dc58cc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
@@ -36,6 +55,7 @@ public class GuiElementTextField {
private int y;
private String prependText = "";
+ private String masterStarUnicode = "";
private int customTextColour = 0xffffffff;
private final GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj,
@@ -395,6 +415,55 @@ public class GuiElementTextField {
textField.setCursorPosition(pos + 1);
}
}
+ } else {
+ for (int i = 0; i < 10; i++) {
+ if (typedChar == Integer.toString(i + 1).charAt(0)) {
+ int pos = textField.getCursorPosition() - 2;
+ if (pos >= 0 && pos < textField.getText().length()) {
+ if (textField.getText().charAt(pos) == '*') {
+ switch (i) {
+ case 0:
+ masterStarUnicode = "\u278A";
+ break;
+ case 1:
+ masterStarUnicode = "\u278B";
+ break;
+ case 2:
+ masterStarUnicode = "\u278C";
+ break;
+ case 3:
+ masterStarUnicode = "\u278D";
+ break;
+ case 4:
+ masterStarUnicode = "\u278E";
+ break;
+ case 5:
+ masterStarUnicode = "\u278F";
+ break;
+ case 6:
+ masterStarUnicode = "\u2790";
+ break;
+ case 7:
+ masterStarUnicode = "\u2791";
+ break;
+ case 8:
+ masterStarUnicode = "\u2792";
+ break;
+ case 9:
+ masterStarUnicode = "\u2793";
+ break;
+ }
+ String before = textField.getText().substring(0, pos);
+ String after = "";
+ if (pos + 2 < textField.getText().length()) {
+ after = textField.getText().substring(pos + 2);
+ }
+ textField.setText(before + masterStarUnicode + after);
+ textField.setCursorPosition(pos + 1);
+ }
+ }
+ }
+ }
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java
index c7c4517b..95ed8a5f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiScreenElementWrapper.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core;
import net.minecraft.client.gui.GuiScreen;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
index 2a696a44..6bafb1fd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config;
public class Config {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java
index 9d0133cb..eac1e5cd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/GuiPositionEditor.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config;
import net.minecraft.client.Minecraft;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java
index 30226a22..d63f871c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config;
import org.lwjgl.input.Keyboard;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/MoulConfigGuiForgeInterop.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/MoulConfigGuiForgeInterop.java
new file mode 100644
index 00000000..40887e54
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/MoulConfigGuiForgeInterop.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.core.config;
+
+import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
+import io.github.moulberry.notenoughupdates.options.NEUConfigEditor;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraftforge.fml.client.IModGuiFactory;
+import org.lwjgl.input.Keyboard;
+
+import java.io.IOException;
+import java.util.Set;
+
+public class MoulConfigGuiForgeInterop implements IModGuiFactory {
+ @Override
+ public void initialize(Minecraft minecraft) {}
+
+ @Override
+ public Class<? extends GuiScreen> mainConfigGuiClass() {
+ return WrappedMoulConfig.class;
+ }
+
+ @Override
+ public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
+ return null;
+ }
+
+ @Override
+ public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement runtimeOptionCategoryElement) {
+ return null;
+ }
+
+ public static class WrappedMoulConfig extends GuiScreenElementWrapper {
+
+ private final GuiScreen parent;
+
+ public WrappedMoulConfig(GuiScreen parent) {
+ super(NEUConfigEditor.editor);
+ this.parent = parent;
+ }
+
+ @Override
+ public void handleKeyboardInput() throws IOException {
+ if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
+ Minecraft.getMinecraft().displayGuiScreen(parent);
+ return;
+ }
+ super.handleKeyboardInput();
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java
index cf946649..535c92bf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config;
import com.google.gson.annotations.Expose;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java
index 8f2b02d8..cf756c91 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/PositionNew.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config;
import com.google.gson.annotations.Expose;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java
index b67d0383..e0a9585a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/Category.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java
index 1c847851..b11f7651 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigAccordionId.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java
index 11b798f9..7491a94f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorAccordion.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java
index a0ca1f38..8e6f652c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorBoolean.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
@@ -7,4 +26,6 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
-public @interface ConfigEditorBoolean {}
+public @interface ConfigEditorBoolean {
+ int runnableId() default -1;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java
index 455df65f..a2c56dc0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java
index 6640ade9..824b2eec 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorColour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java
index e171e0ae..d9707c9b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDraggableList.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
@@ -9,4 +28,6 @@ import java.lang.annotation.Target;
@Target(ElementType.FIELD)
public @interface ConfigEditorDraggableList {
String[] exampleText();
+
+ boolean allowDeleting() default true;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java
index ac766e93..8d870643 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorDropdown.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java
index 217df0c5..ba45ae68 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorFSR.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java
index 8d8de2eb..f1a3e329 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorKeybind.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java
index abab37f9..b8db25bc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorSlider.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java
index 1ff7e39e..b6b32fb2 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorText.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java
index 2ee23dcf..d51294e7 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigOption.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.annotations;
import java.lang.annotation.ElementType;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java
index d62c7ec7..c3969e35 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditor.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java
index 8877cd03..dc1173ef 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorAccordion.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java
index 9e2c912a..d12ec8e7 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorBoolean.java
@@ -1,15 +1,43 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.GuiElementBoolean;
+import io.github.moulberry.notenoughupdates.core.config.Config;
import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
public class GuiOptionEditorBoolean extends GuiOptionEditor {
+
private final GuiElementBoolean bool;
+ private final Config config;
+ private final int runnableId;
- public GuiOptionEditorBoolean(ConfigProcessor.ProcessedOption option) {
+ public GuiOptionEditorBoolean(
+ ConfigProcessor.ProcessedOption option,
+ int runnableId,
+ Config config
+ ) {
super(option);
-
- bool = new GuiElementBoolean(0, 0, (boolean) option.get(), 10, option::set);
+ this.config = config;
+ this.runnableId = runnableId;
+ bool = new GuiElementBoolean(0, 0, (boolean) option.get(), 10, (value) -> onUpdate(option, value));
}
@Override
@@ -34,4 +62,10 @@ public class GuiOptionEditorBoolean extends GuiOptionEditor {
public boolean keyboardInput() {
return false;
}
+
+ private void onUpdate(ConfigProcessor.ProcessedOption option, boolean value) {
+ if (option.set(value)) {
+ config.executeRunnable(runnableId);
+ }
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java
index 76944efa..aef6318c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.Config;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java
index 80d2af42..ca4087b5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorColour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.ChromaColour;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java
index 08a1024f..63a932b5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDraggableList.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
@@ -24,6 +43,7 @@ public class GuiOptionEditorDraggableList extends GuiOptionEditor {
private static final ResourceLocation DELETE = new ResourceLocation("notenoughupdates:core/delete.png");
private final String[] exampleText;
+ private final boolean enableDeleting;
private final List<Integer> activeText;
private int currentDragging = -1;
private int dragStartIndex = -1;
@@ -35,9 +55,14 @@ public class GuiOptionEditorDraggableList extends GuiOptionEditor {
private boolean dropdownOpen = false;
- public GuiOptionEditorDraggableList(ConfigProcessor.ProcessedOption option, String[] exampleText) {
+ public GuiOptionEditorDraggableList(
+ ConfigProcessor.ProcessedOption option,
+ String[] exampleText,
+ boolean disableDeleting
+ ) {
super(option);
+ this.enableDeleting = disableDeleting;
this.exampleText = exampleText;
this.activeText = (List<Integer>) option.get();
}
@@ -77,8 +102,11 @@ public class GuiOptionEditorDraggableList extends GuiOptionEditor {
float greenBlue = LerpUtils.clampZeroOne((250 + trashHoverTime - currentTime) / 250f);
GlStateManager.color(1, greenBlue, greenBlue, 1);
}
- Minecraft.getMinecraft().getTextureManager().bindTexture(DELETE);
- Utils.drawTexturedRect(x + width / 6 + 27, y + 45 - 7 - 13, 11, 14, GL11.GL_NEAREST);
+
+ if (enableDeleting) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(DELETE);
+ Utils.drawTexturedRect(x + width / 6 + 27, y + 45 - 7 - 13, 11, 14, GL11.GL_NEAREST);
+ }
Gui.drawRect(x + 5, y + 45, x + width - 5, y + height - 5, 0xffdddddd);
Gui.drawRect(x + 6, y + 46, x + width - 6, y + height - 6, 0xff000000);
@@ -206,7 +234,9 @@ public class GuiOptionEditorDraggableList extends GuiOptionEditor {
dragStartIndex >= 0 && Mouse.getEventButton() == 0 &&
mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 &&
mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) {
- activeText.remove(dragStartIndex);
+ if (enableDeleting) {
+ activeText.remove(dragStartIndex);
+ }
currentDragging = -1;
dragStartIndex = -1;
return false;
@@ -215,13 +245,13 @@ public class GuiOptionEditorDraggableList extends GuiOptionEditor {
if (!Mouse.isButtonDown(0) || dropdownOpen) {
currentDragging = -1;
dragStartIndex = -1;
- if (trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis();
+ if (trashHoverTime > 0 && enableDeleting) trashHoverTime = -System.currentTimeMillis();
} else if (currentDragging >= 0 &&
mouseX >= x + width / 6 + 27 - 3 && mouseX <= x + width / 6 + 27 + 11 + 3 &&
mouseY >= y + 45 - 7 - 13 - 3 && mouseY <= y + 45 - 7 - 13 + 14 + 3) {
- if (trashHoverTime < 0) trashHoverTime = System.currentTimeMillis();
+ if (trashHoverTime < 0 && enableDeleting) trashHoverTime = System.currentTimeMillis();
} else {
- if (trashHoverTime > 0) trashHoverTime = -System.currentTimeMillis();
+ if (trashHoverTime > 0 && enableDeleting) trashHoverTime = -System.currentTimeMillis();
}
if (Mouse.getEventButtonState()) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
index a17737e3..af6af277 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java
index b443b5f6..048e261e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorFSR.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.Config;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java
index 5ff961a7..6eb71d1e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorKeybind.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java
index 45ae70d9..7fceb92d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorSlider.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java
index f98c87ee..ad2fa4db 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorText.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
@@ -68,7 +87,6 @@ public class GuiOptionEditorText extends GuiOptionEditor {
@Override
public boolean keyboardInput() {
if (Keyboard.getEventKeyState() && textField.getFocus()) {
- Keyboard.enableRepeatEvents(true);
textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
try {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java
index 651335ed..ed45bab6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.gui;
import io.github.moulberry.notenoughupdates.core.config.Position;
@@ -129,8 +148,6 @@ public class GuiPositionEditor extends GuiScreen {
@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
- Keyboard.enableRepeatEvents(true);
-
if (keyCode == Keyboard.KEY_R) {
position.set(originalPosition);
} else if (!clicked) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
index b5aa6ba8..75862069 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
@@ -1,9 +1,50 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.config.struct;
import com.google.gson.annotations.Expose;
import io.github.moulberry.notenoughupdates.core.config.Config;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-import io.github.moulberry.notenoughupdates.core.config.gui.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.Category;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorText;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditor;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiOptionEditorText;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
@@ -130,7 +171,8 @@ public class ConfigProcessor {
}
if (optionType.isAssignableFrom(boolean.class) &&
optionField.isAnnotationPresent(ConfigEditorBoolean.class)) {
- editor = new GuiOptionEditorBoolean(option);
+ ConfigEditorBoolean configEditorAnnotation = optionField.getAnnotation(ConfigEditorBoolean.class);
+ editor = new GuiOptionEditorBoolean(option, configEditorAnnotation.runnableId(), config);
}
if (optionType.isAssignableFrom(boolean.class) &&
optionField.isAnnotationPresent(ConfigEditorAccordion.class)) {
@@ -147,7 +189,11 @@ public class ConfigProcessor {
if (optionField.isAnnotationPresent(ConfigEditorDraggableList.class)) {
ConfigEditorDraggableList configEditorAnnotation =
optionField.getAnnotation(ConfigEditorDraggableList.class);
- editor = new GuiOptionEditorDraggableList(option, configEditorAnnotation.exampleText());
+ editor = new GuiOptionEditorDraggableList(
+ option,
+ configEditorAnnotation.exampleText(),
+ configEditorAnnotation.allowDeleting()
+ );
}
}
if (optionType.isAssignableFrom(String.class)) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java
index c2252a97..3e982f9d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/GuiElementSlider.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util;
import io.github.moulberry.notenoughupdates.core.GuiElement;
@@ -10,7 +29,13 @@ import org.lwjgl.opengl.GL11;
import java.util.function.Consumer;
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_button_new;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_off_cap;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_off_notch;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_off_segment;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_on_cap;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_on_notch;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_on_segment;
public class GuiElementSlider extends GuiElement {
public int x;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java
new file mode 100644
index 00000000..a5744a26
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Line.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.core.util;
+
+import net.minecraft.util.Vec3;
+
+/**
+ * Represents a line using two points along the line or a segment with endpoints.
+ */
+public class Line {
+ private static final double DOUBLE_EPSILON = 4.94065645841247E-324;
+ public Vec3 point1;
+ public Vec3 point2;
+
+ public Line(Vec3 first, Vec3 second) {
+ point1 = first;
+ point2 = second;
+ }
+
+ public Vec3 getMidpoint() {
+ return new Vec3(
+ (point1.xCoord + point2.xCoord) / 2.0,
+ (point1.yCoord + point2.yCoord) / 2.0,
+ (point1.zCoord + point2.zCoord) / 2.0
+ );
+ }
+
+ /**
+ * Calculates the intersection line segment between 2 lines
+ * Based on http://paulbourke.net/geometry/pointlineplane/calclineline.cs
+ *
+ * @return The intersection {@link Line} or {@code null} if no solution found
+ */
+ public Line getIntersectionLineSegment(Line other) {
+ Vec3 p1 = this.point1;
+ Vec3 p2 = this.point2;
+ Vec3 p3 = other.point1;
+ Vec3 p4 = other.point2;
+ Vec3 p13 = p1.subtract(p3);
+ Vec3 p43 = p4.subtract(p3);
+
+ if (lengthSquared(p43) < DOUBLE_EPSILON) {
+ return null;
+ }
+
+ Vec3 p21 = p2.subtract(p1);
+ if (lengthSquared(p21) < DOUBLE_EPSILON) {
+ return null;
+ }
+
+ double d1343 = p13.xCoord * p43.xCoord + p13.yCoord * p43.yCoord + p13.zCoord * p43.zCoord;
+ double d4321 = p43.xCoord * p21.xCoord + p43.yCoord * p21.yCoord + p43.zCoord * p21.zCoord;
+ double d1321 = p13.xCoord * p21.xCoord + p13.yCoord * p21.yCoord + p13.zCoord * p21.zCoord;
+ double d4343 = p43.xCoord * p43.xCoord + p43.yCoord * p43.yCoord + p43.zCoord * p43.zCoord;
+ double d2121 = p21.xCoord * p21.xCoord + p21.yCoord * p21.yCoord + p21.zCoord * p21.zCoord;
+
+ double denom = d2121 * d4343 - d4321 * d4321;
+ if (Math.abs(denom) < DOUBLE_EPSILON) {
+ return null;
+ }
+ double numer = d1343 * d4321 - d1321 * d4343;
+
+ double mua = numer / denom;
+ double mub = (d1343 + d4321 * (mua)) / d4343;
+
+ Line resultSegment = new Line(
+ new Vec3(
+ (float) (p1.xCoord + mua * p21.xCoord),
+ (float) (p1.yCoord + mua * p21.yCoord),
+ (float) (p1.zCoord + mua * p21.zCoord)
+ ),
+ new Vec3(
+ (float) (p3.xCoord + mub * p43.xCoord),
+ (float) (p3.yCoord + mub * p43.yCoord),
+ (float) (p3.zCoord + mub * p43.zCoord)
+ )
+ );
+
+ return resultSegment;
+ }
+
+ public Line getImmutable() {
+ return new Line(point1, point2);
+ }
+
+ private static double lengthSquared(Vec3 vec) {
+ return vec.dotProduct(vec);
+ }
+
+ public String toString() {
+ return String.format(
+ "point1 = %s, point2 = %s, midpoint = %s",
+ point1 == null ? "NULL" : point1.toString(),
+ point2 == null ? "NULL" : point2.toString(),
+ (point1 == null || point2 == null) ? "NULL" : getMidpoint()
+ );
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java
index 03a9483b..41780140 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/MiscUtils.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util;
import net.minecraft.client.Minecraft;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java
index 0bb858db..389991b4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Splitters.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util;
import com.google.common.base.Splitter;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java
index b0deadd2..a4f814d1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/StringUtils.java
@@ -1,9 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util;
import com.google.common.collect.Sets;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
import java.util.Set;
public class StringUtils {
@@ -34,4 +56,50 @@ public class StringUtils {
return trim;
}
+
+ public static String substringBetween(String str, String open, String close) {
+ return org.apache.commons.lang3.StringUtils.substringBetween(str, open, close);
+ }
+
+ public static int cleanAndParseInt(String str) {
+ str = cleanColour(str);
+ str = str.replace(",", "");
+ return Integer.parseInt(str);
+ }
+
+ public static String shortNumberFormat(double n) {
+ return shortNumberFormat(n, 0);
+ }
+
+ private static final char[] c = new char[] { 'k', 'm', 'b', 't' };
+
+ public static String shortNumberFormat(double n, int iteration) {
+ if (n < 1000) {
+ if (n % 1 == 0) {
+ return Integer.toString((int) n);
+ } else {
+ return String.format("%.2f", n);
+ }
+ }
+
+ double d = ((long) n / 100) / 10.0;
+ boolean isRound = (d * 10) % 10 == 0;
+ return d < 1000 ? (isRound || d > 9.99 ? (int) d * 10 / 10 : d + "") + "" + c[iteration] : shortNumberFormat(d, iteration + 1);
+ }
+
+ public static String urlEncode(String something) {
+ try {
+ return URLEncoder.encode(something, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e); // UTF 8 should always be present
+ }
+ }
+
+ /**
+ * taken and modified from https://stackoverflow.com/a/23326014/5507634
+ */
+ public static String replaceLast(String string, String toReplace, String replacement) {
+ int start = string.lastIndexOf(toReplace);
+ return string.substring(0, start) + replacement + string.substring(start + toReplace.length());
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/Vec3Comparable.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Vec3Comparable.java
new file mode 100644
index 00000000..c9736b77
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/Vec3Comparable.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.core.util;
+
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+import net.minecraft.util.Vec3i;
+
+public class Vec3Comparable extends Vec3 implements Comparable<Vec3Comparable> {
+ public static final Vec3Comparable NULL_VECTOR = new Vec3Comparable(0.0, 0.0, 0.0);
+
+ public Vec3Comparable(double x, double y, double z) {
+ super(x, y, z);
+ }
+
+ public Vec3Comparable(Vec3i sourceVec) {
+ super(sourceVec);
+ }
+
+ public Vec3Comparable(Vec3 source) {
+ super(source.xCoord, source.yCoord, source.zCoord);
+ }
+
+ public Vec3Comparable(BlockPos source) {
+
+ super(source.getX(), source.getY(), source.getZ());
+ }
+
+ public Vec3Comparable(Vec3Comparable source) {
+ super(source.xCoord, source.yCoord, source.zCoord);
+ }
+
+ @Override
+ public Vec3Comparable subtractReverse(Vec3 vec) {
+ return new Vec3Comparable(super.subtractReverse(vec));
+ }
+
+ @Override
+ public Vec3Comparable normalize() {
+ return new Vec3Comparable(super.normalize());
+ }
+
+ @Override
+ public Vec3Comparable crossProduct(Vec3 vec) {
+ return new Vec3Comparable(super.crossProduct(vec));
+ }
+
+ @Override
+ public Vec3Comparable subtract(Vec3 vec) {
+ return new Vec3Comparable(super.subtract(vec));
+ }
+
+ @Override
+ public Vec3Comparable subtract(double x, double y, double z) {
+ return new Vec3Comparable(super.subtract(x, y, z));
+ }
+
+ @Override
+ public Vec3Comparable add(Vec3 other) {
+ return new Vec3Comparable(super.add(other));
+ }
+
+ @Override
+ public Vec3Comparable addVector(double x, double y, double z) {
+ return new Vec3Comparable(super.addVector(x, y, z));
+ }
+
+ @Override
+ public Vec3Comparable getIntermediateWithXValue(Vec3 vec, double x) {
+ return new Vec3Comparable(super.getIntermediateWithXValue(vec, x));
+ }
+
+ @Override
+ public Vec3Comparable getIntermediateWithYValue(Vec3 vec, double y) {
+ return new Vec3Comparable(super.getIntermediateWithYValue(vec, y));
+ }
+
+ @Override
+ public Vec3Comparable getIntermediateWithZValue(Vec3 vec, double z) {
+ return new Vec3Comparable(super.getIntermediateWithZValue(vec, z));
+ }
+
+ @Override
+ public Vec3Comparable rotatePitch(float pitch) {
+ return new Vec3Comparable(super.rotatePitch(pitch));
+ }
+
+ @Override
+ public Vec3Comparable rotateYaw(float yaw) {
+ return new Vec3Comparable(super.rotateYaw(yaw));
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ } else if (!(other instanceof Vec3Comparable)) {
+ return false;
+ } else {
+ Vec3Comparable vec3c = (Vec3Comparable) other;
+ return this.xCoord == vec3c.xCoord && this.yCoord == vec3c.yCoord && this.zCoord == vec3c.zCoord;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ long bits = 1L;
+ bits = 31L * bits + doubleToLongBits(xCoord);
+ bits = 31L * bits + doubleToLongBits(yCoord);
+ bits = 31L * bits + doubleToLongBits(zCoord);
+ return (int) (bits ^ (bits >> 32));
+ }
+
+ public int compareTo(Vec3Comparable other) {
+ return this.yCoord == other.yCoord ?
+ (this.zCoord == other.zCoord ?
+ (int) (this.xCoord - other.xCoord)
+ : (int) (this.zCoord - other.zCoord))
+ : (int) (this.yCoord - other.yCoord);
+ }
+
+ public boolean signumEquals(Vec3 other) {
+ return Math.signum(xCoord) == Math.signum(other.xCoord) &&
+ Math.signum(yCoord) == Math.signum(other.yCoord) &&
+ Math.signum(zCoord) == Math.signum(other.zCoord);
+ }
+
+ private static long doubleToLongBits(double d) {
+ return d == 0.0 ? 0L : Double.doubleToLongBits(d);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java
index 7e401959..0e60ad92 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpUtils.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util.lerp;
public class LerpUtils {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java
index 3d9e7787..fb03140c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingFloat.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util.lerp;
public class LerpingFloat {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java
index 024455fd..8462200f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/lerp/LerpingInteger.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util.lerp;
public class LerpingInteger {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
index 9a4607ed..e7ce29c3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util.render;
import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
@@ -13,11 +32,20 @@ import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
-import net.minecraft.util.*;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.Vec3i;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.vector.Vector3f;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class RenderUtils {
public static void drawFloatingRectDark(int x, int y, int width, int height) {
drawFloatingRectDark(x, y, width, height, true);
@@ -228,7 +256,7 @@ public class RenderUtils {
double d11 = 0.5D + Math.sin(d2 + 5.497787143782138D) * 0.2D;
double d14 = -1.0D + d1;
double d15 = (double) (height) * 2.5D + d14;
- worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
worldrenderer.pos(x + d4, y + topOffset, z + d5).tex(1.0D, d15).color(r, g, b, 1.0F * alphaMult).endVertex();
worldrenderer.pos(x + d4, y + bottomOffset, z + d5).tex(1.0D, d14).color(r, g, b, 1.0F).endVertex();
worldrenderer.pos(x + d6, y + bottomOffset, z + d7).tex(0.0D, d14).color(r, g, b, 1.0F).endVertex();
@@ -251,7 +279,7 @@ public class RenderUtils {
double d12 = -1.0D + d1;
double d13 = height + d12;
- worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR);
worldrenderer.pos(x + 0.2D, y + topOffset, z + 0.2D).tex(1.0D, d13).color(r, g, b, 0.25F * alphaMult).endVertex();
worldrenderer.pos(x + 0.2D, y + bottomOffset, z + 0.2D).tex(1.0D, d12).color(r, g, b, 0.25F).endVertex();
worldrenderer.pos(x + 0.8D, y + bottomOffset, z + 0.2D).tex(0.0D, d12).color(r, g, b, 0.25F).endVertex();
@@ -345,11 +373,19 @@ public class RenderUtils {
}
}
- public static void renderWayPoint(String str, BlockPos loc, float partialTicks) {
+ public static void renderWayPoint(String str, Vec3i loc, float partialTicks) {
+ renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks);
+ }
+
+ public static void renderWayPoint(List<String> str, Vec3i loc, float partialTicks) {
renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks);
}
public static void renderWayPoint(String str, Vector3f loc, float partialTicks) {
+ renderWayPoint(Arrays.asList(str), loc, partialTicks);
+ }
+
+ public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks) {
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.pushMatrix();
@@ -373,15 +409,9 @@ public class RenderUtils {
GlStateManager.translate(x, y, z);
GlStateManager.translate(0, viewer.getEyeHeight(), 0);
- renderNametag(str);
-
- GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F);
- GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F);
- GlStateManager.translate(0, -0.25f, 0);
- GlStateManager.rotate(-Minecraft.getMinecraft().getRenderManager().playerViewX, 1.0F, 0.0F, 0.0F);
- GlStateManager.rotate(Minecraft.getMinecraft().getRenderManager().playerViewY, 0.0F, 1.0F, 0.0F);
-
- renderNametag(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m");
+ lines = new ArrayList<>(lines);
+ lines.add(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m");
+ renderNametag(lines);
GlStateManager.popMatrix();
@@ -389,6 +419,10 @@ public class RenderUtils {
}
public static void renderNametag(String str) {
+ renderNametag(Arrays.asList(str));
+ }
+
+ public static void renderNametag(List<String> lines) {
FontRenderer fontrenderer = Minecraft.getMinecraft().fontRendererObj;
float f = 1.6F;
float f1 = 0.016666668F * f;
@@ -406,20 +440,23 @@ public class RenderUtils {
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
int i = 0;
- int j = fontrenderer.getStringWidth(str) / 2;
- GlStateManager.disableTexture2D();
- worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
- worldrenderer.pos(-j - 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
- worldrenderer.pos(-j - 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
- worldrenderer.pos(j + 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
- worldrenderer.pos(j + 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
- tessellator.draw();
- GlStateManager.enableTexture2D();
- fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127);
- GlStateManager.depthMask(true);
-
- fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1);
-
+ for (String str : lines) {
+ int j = fontrenderer.getStringWidth(str) / 2;
+
+ GlStateManager.disableTexture2D();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+ worldrenderer.pos(-j - 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
+ worldrenderer.pos(-j - 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
+ worldrenderer.pos(j + 1, 8 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
+ worldrenderer.pos(j + 1, -1 + i, 0.0D).color(0.0F, 0.0F, 0.0F, 0.25F).endVertex();
+ tessellator.draw();
+ GlStateManager.enableTexture2D();
+ fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, 553648127);
+ GlStateManager.depthMask(true);
+
+ fontrenderer.drawString(str, -fontrenderer.getStringWidth(str) / 2, i, -1);
+ GlStateManager.translate(0, 10f, 0);
+ }
GlStateManager.enableDepth();
GlStateManager.enableBlend();
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java
index ff7ac53a..cee38cea 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/TextRenderUtils.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.core.util.render;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
index 3f7476bd..7a609a2a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.cosmetics;
import com.google.common.collect.BiMap;
@@ -67,6 +86,7 @@ public class CapeManager {
new CapeData("lava", false, false),
new CapeData("tunnel", false, false),
new CapeData("planets", false, false),
+ new CapeData("screensaver", false, false),
//Admins
new CapeData("nullzee", true, false),
@@ -125,46 +145,53 @@ public class CapeManager {
}
private void updateCapes() {
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("activecapes.json", (jsonObject) -> {
- if (jsonObject.get("success").getAsBoolean()) {
- lastJsonSync = jsonObject;
-
- lastCapeSynced = System.currentTimeMillis();
- capeMap.clear();
- for (JsonElement active : jsonObject.get("active").getAsJsonArray()) {
- if (active.isJsonObject()) {
- JsonObject activeObj = (JsonObject) active;
- setCape(activeObj.get("_id").getAsString(), activeObj.get("capeType").getAsString(), false);
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newMoulberryRequest("activecapes.json")
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (jsonObject.get("success").getAsBoolean()) {
+ lastJsonSync = jsonObject;
+
+ lastCapeSynced = System.currentTimeMillis();
+ capeMap.clear();
+ for (JsonElement active : jsonObject.get("active").getAsJsonArray()) {
+ if (active.isJsonObject()) {
+ JsonObject activeObj = (JsonObject) active;
+ setCape(activeObj.get("_id").getAsString(), activeObj.get("capeType").getAsString(), false);
+ }
}
}
- }
- }, () -> System.out.println("[MBAPI] Update capes errored"));
+ });
if (Minecraft.getMinecraft().thePlayer != null && permSyncTries > 0) {
String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
permSyncTries--;
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("permscapes.json", (jsonObject) -> {
- if (!jsonObject.get("success").getAsBoolean()) return;
-
- permSyncTries = 0;
- availableCapes.clear();
- for (JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) {
- if (!permPlayer.isJsonObject()) continue;
- String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString();
- if (!(playerUuid != null && playerUuid.equals(uuid))) continue;
- for (JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) {
- if (!perm.isJsonPrimitive()) continue;
- String cape = perm.getAsString();
- if (cape.equals("*")) {
- allAvailable = true;
- } else {
- availableCapes.add(cape);
- }
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newMoulberryRequest("permscapes.json")
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (!jsonObject.get("success").getAsBoolean()) return;
+
+ permSyncTries = 0;
+ availableCapes.clear();
+ for (JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) {
+ if (!permPlayer.isJsonObject()) continue;
+ String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString();
+ if (!(playerUuid != null && playerUuid.equals(uuid))) continue;
+ for (JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) {
+ if (!perm.isJsonPrimitive()) continue;
+ String cape = perm.getAsString();
+ if (cape.equals("*")) {
+ allAvailable = true;
+ } else {
+ availableCapes.add(cape);
+ }
+ }
+ return;
}
- return;
- }
- }, () -> System.out.println("[MBAPI] Update capes errored - perms"));
+
+ });
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
index c32cc98f..9bf0313b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.cosmetics;
import net.minecraft.client.renderer.Tessellator;
@@ -391,4 +410,4 @@ public class CapeNode {
.normal(otherSideNorm.x, otherSideNorm.y, otherSideNorm.z).endVertex();
tessellator.draw();
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
index 1b33decf..12d8c92d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.cosmetics;
import com.google.gson.Gson;
@@ -385,21 +404,14 @@ public class GuiCosmetics extends GuiScreen {
.getSession()
.getProfile(), accessToken, serverId);
- if (wantToEquipCape == null) {
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync(
- "cgi-bin/changecape.py?capeType=null&serverId=" +
- serverId + "&username=" + userName,
- System.out::println,
- () -> System.out.println("Change cape error")
- );
- } else {
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync(
- "cgi-bin/changecape.py?capeType=" + wantToEquipCape + "&serverId=" +
- serverId + "&username=" + userName,
- System.out::println,
- () -> System.out.println("Change cape error")
- );
- }
+ String toEquipName = wantToEquipCape == null ? "null" : wantToEquipCape;
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newMoulberryRequest("cgi-bin/changecape.py")
+ .queryArgument("capeType", toEquipName)
+ .queryArgument("serverId", serverId)
+ .queryArgument("username", userName)
+ .requestString()
+ .thenAccept(System.out::println);
} catch (Exception e) {
System.out.println("Exception while generating mojang shared secret");
e.printStackTrace();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
index da9d1f68..d32abf64 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.cosmetics;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -18,13 +37,22 @@ import net.minecraftforge.client.event.RenderPlayerEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.*;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.opengl.GL42;
+import org.lwjgl.opengl.GL43;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.TreeMap;
public class NEUCape {
private int currentFrame = 0;
@@ -43,6 +71,10 @@ public class NEUCape {
private final Random random = new Random();
private long eventMillis;
+ private float dvdPositionX = 100;
+ private float dvdPositionY = 100;
+ private float dvdVelocityX = -10;
+ private float dvdVelocityY = 10;
private float eventLength;
private float eventRandom;
@@ -101,6 +133,8 @@ public class NEUCape {
shaderName = "tunnel";
} else if (capeName.equalsIgnoreCase("planets")) {
shaderName = "planets";
+ } else if (capeName.equalsIgnoreCase("screensaver")) {
+ shaderName = "screensaver";
} else {
shaderName = "shiny_cape";
}
@@ -322,6 +356,9 @@ public class NEUCape {
Minecraft.getMinecraft().displayWidth,
Minecraft.getMinecraft().displayHeight
));
+ } else if (shaderName.equalsIgnoreCase("screensaver")) {
+ shaderManager.loadData(shaderId, "something", (int) ((System.currentTimeMillis() / 4) % 256));
+ shaderManager.loadData(shaderId, "dvdPosition", new Vector2f(dvdPositionX, dvdPositionY));
}
}
@@ -530,6 +567,19 @@ public class NEUCape {
private int crouchTicks = 0;
long startTime = 0;
+ public float deltaYComparedToLine(float x0, float y0, float x1, float y1) {
+ float m = (y1 - y0) / (x1 - x0);
+ float b = y0 - m * x0;
+ float lineAtX = dvdPositionX * m + b;
+ return dvdPositionY - lineAtX;
+ }
+
+ public float projectOntoLine(float x0, float y0, float x1, float y1, float x) {
+ float m = (y1 - y0) / (x1 - x0);
+ float b = y0 - m * x0;
+ return x * m + b;
+ }
+
private void updateCape(EntityPlayer player) {
Vector3f capeTranslation = updateFixedCapeNodes(player);
@@ -546,6 +596,30 @@ public class NEUCape {
eventMillis = currentTime;
eventLength = random.nextFloat() * 3000 + 3000;
}
+ } else if (shaderName.equals("screensaver")) {
+ dvdPositionX += dvdVelocityX;
+ dvdPositionY += dvdVelocityY;
+ float diskSizeX = 162 / 2F, diskSizeY = 78 / 2F;
+ // Left line
+ if (deltaYComparedToLine(0, 404, 47, 0) < 0) {
+ dvdVelocityX = 10;
+ dvdPositionX = projectOntoLine(404, 0, 0, 47, dvdPositionY);
+ }
+ // Bottom line
+ if (deltaYComparedToLine(0, 404 - diskSizeY, 292, 404 - diskSizeY) > 0) {
+ dvdVelocityY = -10;
+ dvdPositionY = 404 - diskSizeY;
+ }
+ // Top line
+ if (deltaYComparedToLine(47, 0, 246, 0) < 0) {
+ dvdVelocityY = 10;
+ dvdPositionY = 0;
+ }
+ // Right line
+ if (deltaYComparedToLine(246 - diskSizeX, 0, 293 - diskSizeX, 404) < 0) {
+ dvdVelocityX = -10;
+ dvdPositionX = projectOntoLine(0, 246 - diskSizeX, 404, 293 - diskSizeX, dvdPositionY);
+ }
}
double playerAngle = getPlayerRenderAngle(player, 0);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java
index 4e934e10..45db303b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/ShaderManager.java
@@ -1,6 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.cosmetics;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.client.resources.IResourceManagerReloadListener;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL43;
@@ -14,7 +35,7 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
-public class ShaderManager {
+public class ShaderManager implements IResourceManagerReloadListener {
private final ResourceLocation shaderLocation = new ResourceLocation("notenoughupdates:shaders");
private final HashMap<String, Shader> shaderMap = new HashMap<>();
@@ -24,6 +45,14 @@ public class ShaderManager {
return INSTANCE;
}
+ @Override
+ public void onResourceManagerReload(IResourceManager iResourceManager) {
+ shaderMap.values().forEach(it -> {
+ GL20.glDeleteProgram(it.program);
+ });
+ shaderMap.clear();
+ }
+
public static class Shader {
public final int program;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java
index 0e7c59c7..7a2eb2b0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.dungeons;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
index 592f5b19..a4c5a60a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.dungeons;
import com.google.common.collect.Iterables;
@@ -660,17 +679,6 @@ public class DungeonMap {
float deltaX = entityPos.getRenderX() - pos.getRenderX();
float deltaY = entityPos.getRenderY() - pos.getRenderY();
- /*if(deltaX > (renderRoomSize + renderConnSize)/2) {
- deltaX -= (renderRoomSize + renderConnSize);
- } else if(deltaX < -(renderRoomSize + renderConnSize)/2) {
- deltaX += (renderRoomSize + renderConnSize);
- }
- if(deltaY > (renderRoomSize + renderConnSize)/2) {
- deltaY -= (renderRoomSize + renderConnSize);
- } else if(deltaY < -(renderRoomSize + renderConnSize)/2) {
- deltaY += (renderRoomSize + renderConnSize);
- }*/
-
x += deltaX;
y += deltaY;
@@ -718,7 +726,7 @@ public class DungeonMap {
}
GlStateManager.color(1, 1, 1, 1);
if ((!NotEnoughUpdates.INSTANCE.config.dungeons.showOwnHeadAsMarker ||
- playerMarkerMapPositions.size() <= 1 || minU != 1 / 4f) &&
+ playerMarkerMapPositions.size() < 1 || minU != 1 / 4f) &&
NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPlayerHeads >= 1 &&
playerSkinMap.containsKey(entry.getKey())) {
Minecraft.getMinecraft().getTextureManager().bindTexture(playerSkinMap.get(entry.getKey()));
@@ -1153,7 +1161,7 @@ public class DungeonMap {
String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName());
line = Utils.cleanColour(line);
- if (line.contains("(F1)") || line.contains("(E0)") || line.contains("(M1)")) {
+ if (line.contains("(F1)") || line.contains("(E)") || line.contains("(M1)")) {
isFloorOne = true;
break;
}
@@ -1278,15 +1286,15 @@ public class DungeonMap {
if (entity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) entity;
- float roomX = (float) player.posX / (roomSizeBlocks + 1);
- float roomY = (float) player.posZ / (roomSizeBlocks + 1);
+ float roomX = (float) (player.posX + 200) / (roomSizeBlocks + 1);
+ float roomY = (float) (player.posZ + 200) / (roomSizeBlocks + 1);
float playerRoomOffsetX = (float) Math.floor(roomX);
float playerConnOffsetX = (float) Math.floor(roomX);
float playerRoomOffsetY = (float) Math.floor(roomY);
float playerConnOffsetY = (float) Math.floor(roomY);
- float roomXInBlocks = (float) player.posX % (roomSizeBlocks + 1);
+ float roomXInBlocks = (float) (player.posX + 200) % (roomSizeBlocks + 1);
if (roomXInBlocks < 2) { //0,1
playerConnOffsetX -= 2 / 5f - roomXInBlocks / 5f;
} else if (roomXInBlocks > roomSizeBlocks - 2) { //31,30,29
@@ -1296,7 +1304,7 @@ public class DungeonMap {
playerRoomOffsetX += (roomXInBlocks - 2) / (roomSizeBlocks - 4);
}
- float roomYInBlocks = (float) player.posZ % (roomSizeBlocks + 1);
+ float roomYInBlocks = (float) (player.posZ + 200) % (roomSizeBlocks + 1);
if (roomYInBlocks < 2) { //0,1
playerConnOffsetY -= 2 / 5f - roomYInBlocks / 5f;
} else if (roomYInBlocks > roomSizeBlocks - 2) { //31,30,29
@@ -1606,7 +1614,6 @@ public class DungeonMap {
if(player.getUniqueID().toString().charAt(14) == '4') {
actualPlayers.add(player.getName());
System.out.println(player.getName());
-
}
}*/
int players = 0;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java
index 976dfcf8..a56a5679 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.dungeons;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -14,7 +33,12 @@ import net.minecraftforge.client.event.ClientChatReceivedEvent;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -200,7 +224,17 @@ public class DungeonWin {
displayWin();
} else {
if (unformatted.trim().length() > 0) {
- text.add(e.message.getFormattedText().substring(6).trim());
+ if (unformatted.contains("The Catacombs") || unformatted.contains("Master Mode Catacombs") ||
+ unformatted.contains("Team Score") || unformatted.contains("Defeated") || unformatted.contains(
+ "Total Damage")
+ || unformatted.contains("Ally Healing") || unformatted.contains("Enemies Killed") || unformatted.contains(
+ "Deaths") || unformatted.contains("Secrets Found")) {
+ text.add(e.message.getFormattedText().substring(6).trim());
+ } else {
+ System.out.println(
+ "These messages would of showed on neu dungeon overlay but didnt, They are either bugged or i missed them: \"" +
+ e.message.getFormattedText().substring(6).trim() + "\"");
+ }
}
}
} else {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
index 41fa3663..8ce9d505 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
@@ -1,847 +1,872 @@
-package io.github.moulberry.notenoughupdates.dungeons;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.core.GuiElementColour;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
-import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
-import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
-import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
-import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig;
-import io.github.moulberry.notenoughupdates.util.SpecialColour;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.OpenGlHelper;
-import net.minecraft.client.shader.Framebuffer;
-import net.minecraft.client.shader.Shader;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.util.Matrix4f;
-import net.minecraft.util.ResourceLocation;
-import net.minecraft.util.Vec4b;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.List;
-import java.util.*;
-
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
-
-public class GuiDungeonMapEditor extends GuiScreen {
- public static final ResourceLocation BACKGROUND = new ResourceLocation(
- "notenoughupdates:dungeon_map/editor/background.png");
- public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png");
- private static final DungeonMap demoMap = new DungeonMap();
-
- private int sizeX;
- private int sizeY;
- private int guiLeft;
- private int guiTop;
-
- private final List<Button> buttons = new ArrayList<>();
-
- private final GuiElementTextField blurField = new GuiElementTextField(
- "",
- GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE
- );
- private GuiElementColour activeColourEditor = null;
-
- private Field clickedSlider;
-
- class Button {
- private final int id;
- private final int x;
- private final int y;
- private String text;
- private Color colour = new Color(-1, true);
- private final Field option;
- private String displayName;
- private String desc;
-
- public Button(int id, int x, int y, String text) {
- this(id, x, y, text, null);
- }
-
- public Button(int id, int x, int y, String text, Field option) {
- this.id = id;
- this.x = x;
- this.y = y;
- this.text = text;
- this.option = option;
-
- if (option != null) {
- ConfigOption optionAnnotation = option.getAnnotation(ConfigOption.class);
- displayName = optionAnnotation.name();
- desc = optionAnnotation.desc();
- }
- }
-
- public List<String> getTooltip() {
- if (option == null) {
- return null;
- }
-
- List<String> tooltip = new ArrayList<>();
- tooltip.add(EnumChatFormatting.YELLOW + displayName);
- for (String line : desc.split("\n")) {
- tooltip.add(EnumChatFormatting.AQUA + line);
- }
- return tooltip;
- }
-
- public void render() {
- if (text == null) return;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(BUTTON);
- if (isButtonPressed(id)) {
- GlStateManager.color(colour.getRed() * 0.85f / 255f, colour.getGreen() * 0.85f / 255f,
- colour.getBlue() * 0.85f / 255f, 1
- );
- Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, 1, 0, 1, 0, GL11.GL_NEAREST);
- } else {
- GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue() / 255f, 1);
- Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, GL11.GL_NEAREST);
- }
-
- if (text.length() > 0) {
- Utils.drawStringCenteredScaledMaxWidth(
- text,
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + x + 24,
- guiTop + y + 8,
- false,
- 39,
- 0xFF000000
- );
- }
- }
-
- }
-
- public GuiDungeonMapEditor() {
- DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
- //Map Border Size
- //buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize));
- //buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize));
- //buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize));
-
- //Map Rooms Size
- //buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize));
- //buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize));
- //buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize));
-
- //Map Border Styles
- buttons.add(new Button(6, 6, 97 + 30, "None"));
- buttons.add(new Button(7, 52, 97 + 30, "Custom"));
- buttons.add(new Button(8, 98, 97 + 30, "Stone"));
- buttons.add(new Button(9, 6, 116 + 30, "Wood"));
- buttons.add(new Button(10, 52, 116 + 30, "Rustic(S)"));
- buttons.add(new Button(11, 98, 116 + 30, "Rustic(C)"));
- buttons.add(new Button(12, 6, 135 + 30, "Fade"));
- buttons.add(new Button(13, 52, 135 + 30, "Ribbons"));
- buttons.add(new Button(14, 98, 135 + 30, "Paper"));
- buttons.add(new Button(15, 6, 154 + 30, "Crimson"));
- buttons.add(new Button(16, 52, 154 + 30, "Ornate"));
- buttons.add(new Button(17, 98, 154 + 30, "Dragon"));
-
- try {
- //Dungeon Map
- buttons.add(new Button(18, 20 + 139, 36, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmEnable")));
- //Center
- buttons.add(new Button(
- 19,
- 84 + 139,
- 36,
- "Player/Map",
- DungeonMapConfig.class.getDeclaredField("dmCenterPlayer")
- ));
- //Rotate
- buttons.add(new Button(
- 20,
- 20 + 139,
- 65,
- "Player/No Rotate",
- DungeonMapConfig.class.getDeclaredField("dmRotatePlayer")
- ));
- //Icon Style
- buttons.add(new Button(
- 21,
- 84 + 139,
- 65,
- "Default/Heads",
- DungeonMapConfig.class.getDeclaredField("dmPlayerHeads")
- ));
- //Check Orient
- buttons.add(new Button(
- 22,
- 20 + 139,
- 94,
- "Normal/Reorient",
- DungeonMapConfig.class.getDeclaredField("dmOrientCheck")
- ));
- //Check Center
- buttons.add(new Button(23, 84 + 139, 94, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmCenterCheck")));
- //Interpolation
- buttons.add(new Button(24, 20 + 139, 123, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmPlayerInterp")));
- //Compatibility
- buttons.add(new Button(
- 25,
- 84 + 139,
- 123,
- "Normal/No SHD/No FB/SHD",
- DungeonMapConfig.class.getDeclaredField("dmCompat")
- ));
-
- //Background
- buttons.add(new Button(26, 20 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBackgroundColour")));
- //Border
- buttons.add(new Button(27, 84 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBorderColour")));
-
- //Chroma Mode
- buttons.add(new Button(
- 28,
- 84 + 139,
- 181,
- "Normal/Scroll",
- DungeonMapConfig.class.getDeclaredField("dmChromaBorder")
- ));
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- //buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize));
- //buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize));
-
- {
- double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur;
- String strVal;
- if (val % 1 == 0) {
- strVal = Integer.toString((int) val);
- } else {
- strVal = Double.toString(val);
- strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1");
- strVal = strVal.replaceAll("0+$", "");
- }
- blurField.setText(strVal);
- }
- }
-
- @Override
- public void drawScreen(int mouseX, int mouseY, float partialTicks) {
- ScaledResolution scaledResolution = Utils.pushGuiScale(2);
- this.width = scaledResolution.getScaledWidth();
- this.height = scaledResolution.getScaledHeight();
-
- mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
- mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
-
- List<String> tooltipToDisplay = null;
- for (Button button : buttons) {
- if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 &&
- mouseY >= guiTop + button.y - 13 && mouseY <= guiTop + button.y + 16) {
- if (button.id >= 6 && button.id <= 17) {
- String mapDesc = null;
- String mapCredit = null;
- int id = button.id;
- switch (id) {
- case 6:
- mapDesc = "No Border";
- break;
- case 7:
- mapDesc = "Used by custom Resource Packs";
- break;
- case 8:
- mapDesc = "Simple gray border";
- mapCredit = "TomEngMaster";
- break;
- case 9:
- mapDesc = "Viney wood border";
- mapCredit = "iDevil4Hell";
- break;
- case 10:
- mapDesc = "Steampunk-inspired square border";
- mapCredit = "ThatGravyBoat";
- break;
- case 11:
- mapDesc = "Steampunk-inspired circular border";
- mapCredit = "ThatGravyBoat";
- break;
- case 12:
- mapDesc = "Light fade border";
- mapCredit = "Qwiken";
- break;
- case 13:
- mapDesc = "Simple gray border with red ribbons";
- mapCredit = "Sai";
- break;
- case 14:
- mapDesc = "Paper border";
- mapCredit = "KingJames02st";
- break;
- case 15:
- mapDesc = "Nether-inspired border";
- mapCredit = "DTRW191";
- break;
- case 16:
- mapDesc = "Golden ornate border";
- mapCredit = "iDevil4Hell";
- break;
- case 17:
- mapDesc = "Stone dragon border";
- mapCredit = "ImperiaL";
- break;
- }
-
- ArrayList<String> tooltip = new ArrayList<>();
- tooltip.add(EnumChatFormatting.YELLOW + "Border Style");
- tooltip.add(EnumChatFormatting.AQUA + "Customize the look of the dungeon border");
- tooltip.add("");
- if (mapDesc != null)
- tooltip.add(EnumChatFormatting.YELLOW + "Set to: " + EnumChatFormatting.AQUA + mapDesc);
- if (mapCredit != null)
- tooltip.add(EnumChatFormatting.YELLOW + "Artist: " + EnumChatFormatting.GOLD + mapCredit);
- tooltipToDisplay = tooltip;
- } else {
- tooltipToDisplay = button.getTooltip();
- }
- break;
- }
- }
-
- this.sizeX = 431;
- this.sizeY = 237;
- this.guiLeft = (this.width - this.sizeX) / 2;
- this.guiTop = (this.height - this.sizeY) / 2;
-
- super.drawScreen(mouseX, mouseY, partialTicks);
- drawDefaultBackground();
-
- blurBackground();
- renderBlurredBackground(width, height, guiLeft + 2, guiTop + 2, sizeX - 4, sizeY - 4);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
- GlStateManager.color(1, 1, 1, 1);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().fontRendererObj.drawString("NEU Dungeon Map Editor", guiLeft + 8, guiTop + 6, 0xFFB4B4B4);
-
- Utils.drawStringCenteredScaledMaxWidth("Border Size", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 76, guiTop + 30, false, 137, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Rooms Size", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 76, guiTop + 60, false, 137, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Icon Scale", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 76, guiTop + 90, false, 137, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Border Style", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 76, guiTop + 120, false, 137, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Dungeon Map", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 30, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Center", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 30, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Rotate", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 59, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Icon Style", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 59, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Check Orient", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 88, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Check Center", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 88, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Interpolation", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 117, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Compatibility", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 117, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Background", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 146, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Border", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 146, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("BG Blur", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 44 + 139, guiTop + 175, false, 60, 0xFFB4B4B4
- );
- Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 108 + 139, guiTop + 175, false, 60, 0xFFB4B4B4
- );
-
- Utils.drawStringCenteredScaledMaxWidth("Edit Map Position", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 76, guiTop + 209, false, 200, 0xFFB4B4B4
- );
-
- try {
- drawSlider(DungeonMapConfig.class.getDeclaredField("dmBorderSize"), guiLeft + 76, guiTop + 45);
- drawSlider(DungeonMapConfig.class.getDeclaredField("dmRoomSize"), guiLeft + 76, guiTop + 75);
- drawSlider(DungeonMapConfig.class.getDeclaredField("dmIconScale"), guiLeft + 76, guiTop + 105);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
- buttons.get(18 - 6).text = options.dmEnable ? "Enabled" : "Disabled";
- buttons.get(19 - 6).text = options.dmCenterPlayer ? "Player" : "Map";
- buttons.get(20 - 6).text = options.dmRotatePlayer ? "Player" : "Vertical";
- buttons.get(21 - 6).text =
- options.dmPlayerHeads <= 0 ? "Default" : options.dmPlayerHeads == 1 ? "Heads" : "Heads w/ Border";
- buttons.get(22 - 6).text = options.dmOrientCheck ? "Orient" : "Off";
- buttons.get(23 - 6).text = options.dmCenterCheck ? "Center" : "Off";
- buttons.get(24 - 6).text = options.dmPlayerInterp ? "Interp" : "No Interp";
- buttons.get(25 - 6).text = options.dmCompat <= 0 ? "Normal" : options.dmCompat >= 2 ? "No FB/SHD" : "No SHD";
-
- buttons.get(26 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBackgroundColour));
- buttons.get(27 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBorderColour));
-
- buttons.get(28 - 6).text = options.dmChromaBorder ? "Scroll" : "Normal";
-
- blurField.setSize(48, 16);
- blurField.render(guiLeft + 20 + 139, guiTop + 181);
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex);
- RenderUtils.drawTexturedRect(guiLeft + 52, guiTop + 215, 48, 16);
- TextRenderUtils.drawStringCenteredScaledMaxWidth("Edit", fontRendererObj, guiLeft + 76, guiTop + 223,
- false, 48, 0xFF303030
- );
-
- Map<String, Vec4b> decorations = new HashMap<>();
- Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360));
- decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
-
- HashSet<String> players = new HashSet<>();
- players.add(Minecraft.getMinecraft().thePlayer.getName());
- GlStateManager.color(1, 1, 1, 1);
-
- demoMap.renderMap(guiLeft + 357, guiTop + 125, NotEnoughUpdates.INSTANCE.colourMap, decorations, 0,
- players, false, partialTicks
- );
-
- for (Button button : buttons) {
- button.render();
- }
-
- //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font
- if (tooltipToDisplay != null) {
- Utils.drawHoveringText(
- tooltipToDisplay,
- mouseX,
- mouseY,
- width,
- height,
- 200,
- Minecraft.getMinecraft().fontRendererObj
- );
- }
-
- Utils.pushGuiScale(-1);
-
- if (activeColourEditor != null) {
- activeColourEditor.render();
- }
- }
-
- public void drawSlider(Field option, int centerX, int centerY) {
- float value;
- float minValue;
- float maxValue;
- try {
- value = ((Number) option.get(NotEnoughUpdates.INSTANCE.config.dungeonMap)).floatValue();
-
- ConfigEditorSlider sliderAnnotation = option.getAnnotation(ConfigEditorSlider.class);
- minValue = sliderAnnotation.minValue();
- maxValue = sliderAnnotation.maxValue();
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
-
- float sliderAmount = Math.max(0, Math.min(1, (value - minValue) / (maxValue - minValue)));
- int sliderAmountI = (int) (96 * sliderAmount);
-
- GlStateManager.color(1f, 1f, 1f, 1f);
- Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_large);
- Utils.drawTexturedRect(centerX - 48, centerY - 8, sliderAmountI, 16,
- 0, sliderAmount, 0, 1, GL11.GL_NEAREST
- );
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_large);
- Utils.drawTexturedRect(centerX - 48 + sliderAmountI, centerY - 8, 96 - sliderAmountI, 16,
- sliderAmount, 1, 0, 1, GL11.GL_NEAREST
- );
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button);
- Utils.drawTexturedRect(centerX - 48 + sliderAmountI - 4, centerY - 8, 8, 16,
- 0, 1, 0, 1, GL11.GL_NEAREST
- );
- }
-
- @Override
- protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
- super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
-
- if (clickedSlider != null) {
- float minValue;
- float maxValue;
- try {
- ConfigEditorSlider sliderAnnotation = clickedSlider.getAnnotation(ConfigEditorSlider.class);
- minValue = sliderAnnotation.minValue();
- maxValue = sliderAnnotation.maxValue();
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
-
- float sliderAmount = (mouseX - (guiLeft + 76 - 48)) / 96f;
- double val = minValue + (maxValue - minValue) * sliderAmount;
- if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- val = Math.round(val);
- }
- float value = (float) Math.max(minValue, Math.min(maxValue, val));
- try {
- if (clickedSlider.getType() == int.class) {
- clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, Math.round(value));
- } else {
- clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, value);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- }
-
- @Override
- protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
- for (Button button : buttons) {
- if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 &&
- mouseY >= guiTop + button.y && mouseY <= guiTop + button.y + 16) {
- buttonClicked(mouseX, mouseY, button.id);
-
- blurField.otherComponentClick();
- return;
- }
- }
-
- clickedSlider = null;
- if (mouseX >= guiLeft + 76 - 48 && mouseX <= guiLeft + 76 + 48) {
- try {
- if (mouseY > guiTop + 45 - 8 && mouseY < guiTop + 45 + 8) {
- clickedSlider = DungeonMapConfig.class.getDeclaredField("dmBorderSize");
- return;
- } else if (mouseY > guiTop + 75 - 8 && mouseY < guiTop + 75 + 8) {
- clickedSlider = DungeonMapConfig.class.getDeclaredField("dmRoomSize");
- return;
- } else if (mouseY > guiTop + 105 - 8 && mouseY < guiTop + 105 + 8) {
- clickedSlider = DungeonMapConfig.class.getDeclaredField("dmIconScale");
- return;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- if (mouseY > guiTop + 181 && mouseY < guiTop + 181 + 16) {
- if (mouseX > guiLeft + 20 + 139 && mouseX < guiLeft + 20 + 139 + 48) {
- blurField.mouseClicked(mouseX, mouseY, mouseButton);
- return;
- }
- } else if (mouseY > guiTop + 215 && mouseY < guiTop + 215 + 16) {
- if (mouseX > guiLeft + 52 && mouseX < guiLeft + 100) {
- int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize);
-
- Map<String, Vec4b> decorations = new HashMap<>();
- Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360));
- decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
-
- HashSet<String> players = new HashSet<>();
- players.add(Minecraft.getMinecraft().thePlayer.getName());
- GlStateManager.color(1, 1, 1, 1);
-
- Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition,
- size, size, () -> {
- ScaledResolution scaledResolution = Utils.pushGuiScale(2);
- demoMap.renderMap(
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsX(scaledResolution, size) + size / 2,
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsY(scaledResolution, size) + size / 2,
- NotEnoughUpdates.INSTANCE.colourMap,
- decorations,
- 0,
- players,
- false,
- 0
- );
- Utils.pushGuiScale(-1);
- }, () -> {}, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor()
- ).withScale(2));
- return;
- }
- }
-
- blurField.otherComponentClick();
- }
-
- @Override
- public void handleMouseInput() throws IOException {
- super.handleMouseInput();
-
- if (activeColourEditor != null) {
- ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
- int mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
- int mouseY =
- realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
- activeColourEditor.mouseInput(mouseX, mouseY);
- }
- }
-
- @Override
- public void handleKeyboardInput() throws IOException {
- super.handleKeyboardInput();
-
- if (activeColourEditor != null) {
- activeColourEditor.keyboardInput();
- }
- }
-
- @Override
- protected void keyTyped(char typedChar, int keyCode) throws IOException {
- super.keyTyped(typedChar, keyCode);
-
- if (blurField.getFocus()) {
- blurField.keyTyped(typedChar, keyCode);
-
- try {
- blurField.setCustomBorderColour(-1);
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur = Float.parseFloat(blurField.getText());
- } catch (Exception e) {
- blurField.setCustomBorderColour(Color.RED.getRGB());
- }
- }
- }
-
- private void buttonClicked(int mouseX, int mouseY, int id) {
- DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
- switch (id) {
- case 0:
- options.dmBorderSize = 0;
- break;
- case 1:
- options.dmBorderSize = 1;
- break;
- case 2:
- options.dmBorderSize = 2;
- break;
- case 30:
- options.dmBorderSize = 3;
- break;
- case 3:
- options.dmRoomSize = 0;
- break;
- case 4:
- options.dmRoomSize = 1;
- break;
- case 5:
- options.dmRoomSize = 2;
- break;
- case 29:
- options.dmRoomSize = 3;
- break;
- case 18:
- options.dmEnable = !options.dmEnable;
- break;
- case 19:
- options.dmCenterPlayer = !options.dmCenterPlayer;
- break;
- case 20:
- options.dmRotatePlayer = !options.dmRotatePlayer;
- break;
- case 21:
- options.dmPlayerHeads++;
- if (options.dmPlayerHeads > 2) options.dmPlayerHeads = 0;
- break;
- case 22:
- options.dmOrientCheck = !options.dmOrientCheck;
- break;
- case 23:
- options.dmCenterCheck = !options.dmCenterCheck;
- break;
- case 24:
- options.dmPlayerInterp = !options.dmPlayerInterp;
- break;
- case 25:
- options.dmCompat++;
- if (options.dmCompat > 2) options.dmCompat = 0;
- break;
- case 26: {
- ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
- mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
- mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
- activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBackgroundColour,
- (col) -> options.dmBackgroundColour = col, () -> activeColourEditor = null
- );
- }
- break;
- case 27: {
- ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
- mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
- mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
- activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBorderColour,
- (col) -> options.dmBorderColour = col, () -> activeColourEditor = null
- );
- }
- break;
- case 28:
- options.dmChromaBorder = !options.dmChromaBorder;
- break;
- default:
- if (id >= 6 && id <= 17) {
- options.dmBorderStyle = id - 6;
- break;
- }
- }
- }
-
- private boolean isButtonPressed(int id) {
- DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
-
- if (id >= 0 && id <= 2) {
- return options.dmBorderSize == id;
- } else if (id >= 3 && id <= 5) {
- return options.dmRoomSize == id - 3;
- } else if (id >= 6 && id <= 17) {
- return options.dmBorderStyle == id - 6;
- } else if (id == 29) {
- return options.dmRoomSize == 3;
- } else if (id == 30) {
- return options.dmBorderSize == 3;
- }
- return false;
- }
-
- Shader blurShaderHorz = null;
- Framebuffer blurOutputHorz = null;
- Shader blurShaderVert = null;
- Framebuffer blurOutputVert = null;
-
- /**
- * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
- * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
- * <p>
- * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to
- * apply scales and translations manually.
- */
- private Matrix4f createProjectionMatrix(int width, int height) {
- Matrix4f projMatrix = new Matrix4f();
- projMatrix.setIdentity();
- projMatrix.m00 = 2.0F / (float) width;
- projMatrix.m11 = 2.0F / (float) (-height);
- projMatrix.m22 = -0.0020001999F;
- projMatrix.m33 = 1.0F;
- projMatrix.m03 = -1.0F;
- projMatrix.m13 = 1.0F;
- projMatrix.m23 = -1.0001999F;
- return projMatrix;
- }
-
- private double lastBgBlurFactor = -1;
-
- private void blurBackground() {
- if (!OpenGlHelper.isFramebufferEnabled()) return;
-
- int width = Minecraft.getMinecraft().displayWidth;
- int height = Minecraft.getMinecraft().displayHeight;
-
- if (blurOutputHorz == null) {
- blurOutputHorz = new Framebuffer(width, height, false);
- blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
- }
- if (blurOutputVert == null) {
- blurOutputVert = new Framebuffer(width, height, false);
- blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
- }
- if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
- blurOutputHorz.createBindFramebuffer(width, height);
- blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
- if (blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
- blurOutputVert.createBindFramebuffer(width, height);
- blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
-
- if (blurShaderHorz == null) {
- try {
- blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz
- );
- blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
- blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
- } catch (Exception ignored) {
- }
- }
- if (blurShaderVert == null) {
- try {
- blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- blurOutputHorz, blurOutputVert
- );
- blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
- blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
- } catch (Exception ignored) {
- }
- }
- if (blurShaderHorz != null && blurShaderVert != null) {
- if (15 != lastBgBlurFactor) {
- blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float) 15);
- blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float) 15);
- lastBgBlurFactor = 15;
- }
- GL11.glPushMatrix();
- blurShaderHorz.loadShader(0);
- blurShaderVert.loadShader(0);
- GlStateManager.enableDepth();
- GL11.glPopMatrix();
-
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
- }
- }
-
- /**
- * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
- * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
- */
- public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
- if (!OpenGlHelper.isFramebufferEnabled()) return;
-
- float uMin = x / (float) width;
- float uMax = (x + blurWidth) / (float) width;
- float vMin = (height - y) / (float) height;
- float vMax = (height - y - blurHeight) / (float) height;
-
- blurOutputVert.bindFramebufferTexture();
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax);
- blurOutputVert.unbindFramebufferTexture();
- }
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.dungeons;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GuiElementColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.Matrix4f;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.Vec4b;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_button;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_off_large;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.slider_on_large;
+
+public class GuiDungeonMapEditor extends GuiScreen {
+ public static final ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates:dungeon_map/editor/background.png");
+ public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:dungeon_map/editor/button.png");
+ private static final DungeonMap demoMap = new DungeonMap();
+
+ private int sizeX;
+ private int sizeY;
+ private int guiLeft;
+ private int guiTop;
+
+ private final List<Button> buttons = new ArrayList<>();
+
+ private final GuiElementTextField blurField = new GuiElementTextField(
+ "",
+ GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE
+ );
+ private GuiElementColour activeColourEditor = null;
+
+ private Field clickedSlider;
+
+ class Button {
+ private final int id;
+ private final int x;
+ private final int y;
+ private String text;
+ private Color colour = new Color(-1, true);
+ private final Field option;
+ private String displayName;
+ private String desc;
+
+ public Button(int id, int x, int y, String text) {
+ this(id, x, y, text, null);
+ }
+
+ public Button(int id, int x, int y, String text, Field option) {
+ this.id = id;
+ this.x = x;
+ this.y = y;
+ this.text = text;
+ this.option = option;
+
+ if (option != null) {
+ ConfigOption optionAnnotation = option.getAnnotation(ConfigOption.class);
+ displayName = optionAnnotation.name();
+ desc = optionAnnotation.desc();
+ }
+ }
+
+ public List<String> getTooltip() {
+ if (option == null) {
+ return null;
+ }
+
+ List<String> tooltip = new ArrayList<>();
+ tooltip.add(EnumChatFormatting.YELLOW + displayName);
+ for (String line : desc.split("\n")) {
+ tooltip.add(EnumChatFormatting.AQUA + line);
+ }
+ return tooltip;
+ }
+
+ public void render() {
+ if (text == null) return;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BUTTON);
+ if (isButtonPressed(id)) {
+ GlStateManager.color(colour.getRed() * 0.85f / 255f, colour.getGreen() * 0.85f / 255f,
+ colour.getBlue() * 0.85f / 255f, 1
+ );
+ Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, 1, 0, 1, 0, GL11.GL_NEAREST);
+ } else {
+ GlStateManager.color(colour.getRed() / 255f, colour.getGreen() / 255f, colour.getBlue() / 255f, 1);
+ Utils.drawTexturedRect(guiLeft + x, guiTop + y, 48, 16, GL11.GL_NEAREST);
+ }
+
+ if (text.length() > 0) {
+ Utils.drawStringCenteredScaledMaxWidth(
+ text,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + x + 24,
+ guiTop + y + 8,
+ false,
+ 39,
+ 0xFF000000
+ );
+ }
+ }
+
+ }
+
+ public GuiDungeonMapEditor() {
+ DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
+ //Map Border Size
+ //buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize));
+ //buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize));
+ //buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize));
+
+ //Map Rooms Size
+ //buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize));
+ //buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize));
+ //buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize));
+
+ //Map Border Styles
+ buttons.add(new Button(6, 6, 97 + 30, "None"));
+ buttons.add(new Button(7, 52, 97 + 30, "Custom"));
+ buttons.add(new Button(8, 98, 97 + 30, "Stone"));
+ buttons.add(new Button(9, 6, 116 + 30, "Wood"));
+ buttons.add(new Button(10, 52, 116 + 30, "Rustic(S)"));
+ buttons.add(new Button(11, 98, 116 + 30, "Rustic(C)"));
+ buttons.add(new Button(12, 6, 135 + 30, "Fade"));
+ buttons.add(new Button(13, 52, 135 + 30, "Ribbons"));
+ buttons.add(new Button(14, 98, 135 + 30, "Paper"));
+ buttons.add(new Button(15, 6, 154 + 30, "Crimson"));
+ buttons.add(new Button(16, 52, 154 + 30, "Ornate"));
+ buttons.add(new Button(17, 98, 154 + 30, "Dragon"));
+
+ try {
+ //Dungeon Map
+ buttons.add(new Button(18, 20 + 139, 36, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmEnable")));
+ //Center
+ buttons.add(new Button(
+ 19,
+ 84 + 139,
+ 36,
+ "Player/Map",
+ DungeonMapConfig.class.getDeclaredField("dmCenterPlayer")
+ ));
+ //Rotate
+ buttons.add(new Button(
+ 20,
+ 20 + 139,
+ 65,
+ "Player/No Rotate",
+ DungeonMapConfig.class.getDeclaredField("dmRotatePlayer")
+ ));
+ //Icon Style
+ buttons.add(new Button(
+ 21,
+ 84 + 139,
+ 65,
+ "Default/Heads",
+ DungeonMapConfig.class.getDeclaredField("dmPlayerHeads")
+ ));
+ //Check Orient
+ buttons.add(new Button(
+ 22,
+ 20 + 139,
+ 94,
+ "Normal/Reorient",
+ DungeonMapConfig.class.getDeclaredField("dmOrientCheck")
+ ));
+ //Check Center
+ buttons.add(new Button(23, 84 + 139, 94, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmCenterCheck")));
+ //Interpolation
+ buttons.add(new Button(24, 20 + 139, 123, "Yes/No", DungeonMapConfig.class.getDeclaredField("dmPlayerInterp")));
+ //Compatibility
+ buttons.add(new Button(
+ 25,
+ 84 + 139,
+ 123,
+ "Normal/No SHD/No FB/SHD",
+ DungeonMapConfig.class.getDeclaredField("dmCompat")
+ ));
+
+ //Background
+ buttons.add(new Button(26, 20 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBackgroundColour")));
+ //Border
+ buttons.add(new Button(27, 84 + 139, 152, "", DungeonMapConfig.class.getDeclaredField("dmBorderColour")));
+
+ //Chroma Mode
+ buttons.add(new Button(
+ 28,
+ 84 + 139,
+ 181,
+ "Normal/Scroll",
+ DungeonMapConfig.class.getDeclaredField("dmChromaBorder")
+ ));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ //buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize));
+ //buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize));
+
+ {
+ double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur;
+ String strVal;
+ if (val % 1 == 0) {
+ strVal = Integer.toString((int) val);
+ } else {
+ strVal = Double.toString(val);
+ strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1");
+ strVal = strVal.replaceAll("0+$", "");
+ }
+ blurField.setText(strVal);
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ ScaledResolution scaledResolution = Utils.pushGuiScale(2);
+ this.width = scaledResolution.getScaledWidth();
+ this.height = scaledResolution.getScaledHeight();
+
+ mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
+ mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
+
+ List<String> tooltipToDisplay = null;
+ for (Button button : buttons) {
+ if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 &&
+ mouseY >= guiTop + button.y - 13 && mouseY <= guiTop + button.y + 16) {
+ if (button.id >= 6 && button.id <= 17) {
+ String mapDesc = null;
+ String mapCredit = null;
+ int id = button.id;
+ switch (id) {
+ case 6:
+ mapDesc = "No Border";
+ break;
+ case 7:
+ mapDesc = "Used by custom Resource Packs";
+ break;
+ case 8:
+ mapDesc = "Simple gray border";
+ mapCredit = "Lucy";
+ break;
+ case 9:
+ mapDesc = "Viney wood border";
+ mapCredit = "iDevil4Hell";
+ break;
+ case 10:
+ mapDesc = "Steampunk-inspired square border";
+ mapCredit = "ThatGravyBoat";
+ break;
+ case 11:
+ mapDesc = "Steampunk-inspired circular border";
+ mapCredit = "ThatGravyBoat";
+ break;
+ case 12:
+ mapDesc = "Light fade border";
+ mapCredit = "Qwiken";
+ break;
+ case 13:
+ mapDesc = "Simple gray border with red ribbons";
+ mapCredit = "Sai";
+ break;
+ case 14:
+ mapDesc = "Paper border";
+ mapCredit = "KingJames02st";
+ break;
+ case 15:
+ mapDesc = "Nether-inspired border";
+ mapCredit = "DTRW191";
+ break;
+ case 16:
+ mapDesc = "Golden ornate border";
+ mapCredit = "iDevil4Hell";
+ break;
+ case 17:
+ mapDesc = "Stone dragon border";
+ mapCredit = "ImperiaL";
+ break;
+ }
+
+ ArrayList<String> tooltip = new ArrayList<>();
+ tooltip.add(EnumChatFormatting.YELLOW + "Border Style");
+ tooltip.add(EnumChatFormatting.AQUA + "Customize the look of the dungeon border");
+ tooltip.add("");
+ if (mapDesc != null)
+ tooltip.add(EnumChatFormatting.YELLOW + "Set to: " + EnumChatFormatting.AQUA + mapDesc);
+ if (mapCredit != null)
+ tooltip.add(EnumChatFormatting.YELLOW + "Artist: " + EnumChatFormatting.GOLD + mapCredit);
+ tooltipToDisplay = tooltip;
+ } else {
+ tooltipToDisplay = button.getTooltip();
+ }
+ break;
+ }
+ }
+
+ this.sizeX = 431;
+ this.sizeY = 237;
+ this.guiLeft = (this.width - this.sizeX) / 2;
+ this.guiTop = (this.height - this.sizeY) / 2;
+
+ super.drawScreen(mouseX, mouseY, partialTicks);
+ drawDefaultBackground();
+
+ blurBackground();
+ renderBlurredBackground(width, height, guiLeft + 2, guiTop + 2, sizeX - 4, sizeY - 4);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("NEU Dungeon Map Editor", guiLeft + 8, guiTop + 6, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Border Size", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 76, guiTop + 30, false, 137, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Rooms Size", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 76, guiTop + 60, false, 137, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Icon Scale", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 76, guiTop + 90, false, 137, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Border Style", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 76, guiTop + 120, false, 137, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Dungeon Map", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 30, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Center", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 30, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Rotate", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 59, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Icon Style", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 59, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Check Orient", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 88, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Check Center", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 88, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Interpolation", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 117, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Compatibility", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 117, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Background", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 146, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Border", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 146, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("BG Blur", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 44 + 139, guiTop + 175, false, 60, 0xFFB4B4B4
+ );
+ Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 108 + 139, guiTop + 175, false, 60, 0xFFB4B4B4
+ );
+
+ Utils.drawStringCenteredScaledMaxWidth("Edit Map Position", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 76, guiTop + 209, false, 200, 0xFFB4B4B4
+ );
+
+ try {
+ drawSlider(DungeonMapConfig.class.getDeclaredField("dmBorderSize"), guiLeft + 76, guiTop + 45);
+ drawSlider(DungeonMapConfig.class.getDeclaredField("dmRoomSize"), guiLeft + 76, guiTop + 75);
+ drawSlider(DungeonMapConfig.class.getDeclaredField("dmIconScale"), guiLeft + 76, guiTop + 105);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
+ buttons.get(18 - 6).text = options.dmEnable ? "Enabled" : "Disabled";
+ buttons.get(19 - 6).text = options.dmCenterPlayer ? "Player" : "Map";
+ buttons.get(20 - 6).text = options.dmRotatePlayer ? "Player" : "Vertical";
+ buttons.get(21 - 6).text =
+ options.dmPlayerHeads <= 0 ? "Default" : options.dmPlayerHeads == 1 ? "Heads" : "Heads w/ Border";
+ buttons.get(22 - 6).text = options.dmOrientCheck ? "Orient" : "Off";
+ buttons.get(23 - 6).text = options.dmCenterCheck ? "Center" : "Off";
+ buttons.get(24 - 6).text = options.dmPlayerInterp ? "Interp" : "No Interp";
+ buttons.get(25 - 6).text = options.dmCompat <= 0 ? "Normal" : options.dmCompat >= 2 ? "No FB/SHD" : "No SHD";
+
+ buttons.get(26 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBackgroundColour));
+ buttons.get(27 - 6).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBorderColour));
+
+ buttons.get(28 - 6).text = options.dmChromaBorder ? "Scroll" : "Normal";
+
+ blurField.setSize(48, 16);
+ blurField.render(guiLeft + 20 + 139, guiTop + 181);
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex);
+ RenderUtils.drawTexturedRect(guiLeft + 52, guiTop + 215, 48, 16);
+ TextRenderUtils.drawStringCenteredScaledMaxWidth("Edit", fontRendererObj, guiLeft + 76, guiTop + 223,
+ false, 48, 0xFF303030
+ );
+
+ Map<String, Vec4b> decorations = new HashMap<>();
+ Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360));
+ decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
+
+ HashSet<String> players = new HashSet<>();
+ players.add(Minecraft.getMinecraft().thePlayer.getName());
+ GlStateManager.color(1, 1, 1, 1);
+
+ demoMap.renderMap(guiLeft + 357, guiTop + 125, NotEnoughUpdates.INSTANCE.colourMap, decorations, 0,
+ players, false, partialTicks
+ );
+
+ for (Button button : buttons) {
+ button.render();
+ }
+
+ //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font
+ if (tooltipToDisplay != null) {
+ Utils.drawHoveringText(
+ tooltipToDisplay,
+ mouseX,
+ mouseY,
+ width,
+ height,
+ 200,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+
+ Utils.pushGuiScale(-1);
+
+ if (activeColourEditor != null) {
+ activeColourEditor.render();
+ }
+ }
+
+ public void drawSlider(Field option, int centerX, int centerY) {
+ float value;
+ float minValue;
+ float maxValue;
+ try {
+ value = ((Number) option.get(NotEnoughUpdates.INSTANCE.config.dungeonMap)).floatValue();
+
+ ConfigEditorSlider sliderAnnotation = option.getAnnotation(ConfigEditorSlider.class);
+ minValue = sliderAnnotation.minValue();
+ maxValue = sliderAnnotation.maxValue();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ float sliderAmount = Math.max(0, Math.min(1, (value - minValue) / (maxValue - minValue)));
+ int sliderAmountI = (int) (96 * sliderAmount);
+
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(slider_on_large);
+ Utils.drawTexturedRect(centerX - 48, centerY - 8, sliderAmountI, 16,
+ 0, sliderAmount, 0, 1, GL11.GL_NEAREST
+ );
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(slider_off_large);
+ Utils.drawTexturedRect(centerX - 48 + sliderAmountI, centerY - 8, 96 - sliderAmountI, 16,
+ sliderAmount, 1, 0, 1, GL11.GL_NEAREST
+ );
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(slider_button);
+ Utils.drawTexturedRect(centerX - 48 + sliderAmountI - 4, centerY - 8, 8, 16,
+ 0, 1, 0, 1, GL11.GL_NEAREST
+ );
+ }
+
+ @Override
+ protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
+
+ if (clickedSlider != null) {
+ float minValue;
+ float maxValue;
+ try {
+ ConfigEditorSlider sliderAnnotation = clickedSlider.getAnnotation(ConfigEditorSlider.class);
+ minValue = sliderAnnotation.minValue();
+ maxValue = sliderAnnotation.maxValue();
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ float sliderAmount = (mouseX - (guiLeft + 76 - 48)) / 96f;
+ double val = minValue + (maxValue - minValue) * sliderAmount;
+ if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ val = Math.round(val);
+ }
+ float value = (float) Math.max(minValue, Math.min(maxValue, val));
+ try {
+ if (clickedSlider.getType() == int.class) {
+ clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, Math.round(value));
+ } else {
+ clickedSlider.set(NotEnoughUpdates.INSTANCE.config.dungeonMap, value);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ for (Button button : buttons) {
+ if (mouseX >= guiLeft + button.x && mouseX <= guiLeft + button.x + 48 &&
+ mouseY >= guiTop + button.y && mouseY <= guiTop + button.y + 16) {
+ buttonClicked(mouseX, mouseY, button.id);
+
+ blurField.otherComponentClick();
+ return;
+ }
+ }
+
+ clickedSlider = null;
+ if (mouseX >= guiLeft + 76 - 48 && mouseX <= guiLeft + 76 + 48) {
+ try {
+ if (mouseY > guiTop + 45 - 8 && mouseY < guiTop + 45 + 8) {
+ clickedSlider = DungeonMapConfig.class.getDeclaredField("dmBorderSize");
+ return;
+ } else if (mouseY > guiTop + 75 - 8 && mouseY < guiTop + 75 + 8) {
+ clickedSlider = DungeonMapConfig.class.getDeclaredField("dmRoomSize");
+ return;
+ } else if (mouseY > guiTop + 105 - 8 && mouseY < guiTop + 105 + 8) {
+ clickedSlider = DungeonMapConfig.class.getDeclaredField("dmIconScale");
+ return;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (mouseY > guiTop + 181 && mouseY < guiTop + 181 + 16) {
+ if (mouseX > guiLeft + 20 + 139 && mouseX < guiLeft + 20 + 139 + 48) {
+ blurField.mouseClicked(mouseX, mouseY, mouseButton);
+ return;
+ }
+ } else if (mouseY > guiTop + 215 && mouseY < guiTop + 215 + 16) {
+ if (mouseX > guiLeft + 52 && mouseX < guiLeft + 100) {
+ int size = 80 + Math.round(40 * NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize);
+
+ Map<String, Vec4b> decorations = new HashMap<>();
+ Vec4b vec4b = new Vec4b((byte) 3, (byte) (((50) - 64) * 2), (byte) (((40) - 64) * 2), (byte) ((60) * 16 / 360));
+ decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
+
+ HashSet<String> players = new HashSet<>();
+ players.add(Minecraft.getMinecraft().thePlayer.getName());
+ GlStateManager.color(1, 1, 1, 1);
+
+ Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition,
+ size, size, () -> {
+ ScaledResolution scaledResolution = Utils.pushGuiScale(2);
+ demoMap.renderMap(
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsX(scaledResolution, size) + size / 2,
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsY(scaledResolution, size) + size / 2,
+ NotEnoughUpdates.INSTANCE.colourMap,
+ decorations,
+ 0,
+ players,
+ false,
+ 0
+ );
+ Utils.pushGuiScale(-1);
+ }, () -> {}, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor()
+ ).withScale(2));
+ return;
+ }
+ }
+
+ blurField.otherComponentClick();
+ }
+
+ @Override
+ public void handleMouseInput() throws IOException {
+ super.handleMouseInput();
+
+ if (activeColourEditor != null) {
+ ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
+ int mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
+ int mouseY =
+ realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
+ activeColourEditor.mouseInput(mouseX, mouseY);
+ }
+ }
+
+ @Override
+ public void handleKeyboardInput() throws IOException {
+ super.handleKeyboardInput();
+
+ if (activeColourEditor != null) {
+ activeColourEditor.keyboardInput();
+ }
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ super.keyTyped(typedChar, keyCode);
+
+ if (blurField.getFocus()) {
+ blurField.keyTyped(typedChar, keyCode);
+
+ try {
+ blurField.setCustomBorderColour(-1);
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur = Float.parseFloat(blurField.getText());
+ } catch (Exception e) {
+ blurField.setCustomBorderColour(Color.RED.getRGB());
+ }
+ }
+ }
+
+ private void buttonClicked(int mouseX, int mouseY, int id) {
+ DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
+ switch (id) {
+ case 0:
+ options.dmBorderSize = 0;
+ break;
+ case 1:
+ options.dmBorderSize = 1;
+ break;
+ case 2:
+ options.dmBorderSize = 2;
+ break;
+ case 30:
+ options.dmBorderSize = 3;
+ break;
+ case 3:
+ options.dmRoomSize = 0;
+ break;
+ case 4:
+ options.dmRoomSize = 1;
+ break;
+ case 5:
+ options.dmRoomSize = 2;
+ break;
+ case 29:
+ options.dmRoomSize = 3;
+ break;
+ case 18:
+ options.dmEnable = !options.dmEnable;
+ break;
+ case 19:
+ options.dmCenterPlayer = !options.dmCenterPlayer;
+ break;
+ case 20:
+ options.dmRotatePlayer = !options.dmRotatePlayer;
+ break;
+ case 21:
+ options.dmPlayerHeads++;
+ if (options.dmPlayerHeads > 2) options.dmPlayerHeads = 0;
+ break;
+ case 22:
+ options.dmOrientCheck = !options.dmOrientCheck;
+ break;
+ case 23:
+ options.dmCenterCheck = !options.dmCenterCheck;
+ break;
+ case 24:
+ options.dmPlayerInterp = !options.dmPlayerInterp;
+ break;
+ case 25:
+ options.dmCompat++;
+ if (options.dmCompat > 2) options.dmCompat = 0;
+ break;
+ case 26: {
+ ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
+ mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
+ mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
+ activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBackgroundColour,
+ (col) -> options.dmBackgroundColour = col, () -> activeColourEditor = null
+ );
+ }
+ break;
+ case 27: {
+ ScaledResolution realRes = new ScaledResolution(Minecraft.getMinecraft());
+ mouseX = Mouse.getEventX() * realRes.getScaledWidth() / this.mc.displayWidth;
+ mouseY = realRes.getScaledHeight() - Mouse.getEventY() * realRes.getScaledHeight() / this.mc.displayHeight - 1;
+ activeColourEditor = new GuiElementColour(mouseX, mouseY, options.dmBorderColour,
+ (col) -> options.dmBorderColour = col, () -> activeColourEditor = null
+ );
+ }
+ break;
+ case 28:
+ options.dmChromaBorder = !options.dmChromaBorder;
+ break;
+ default:
+ if (id >= 6 && id <= 17) {
+ options.dmBorderStyle = id - 6;
+ break;
+ }
+ }
+ }
+
+ private boolean isButtonPressed(int id) {
+ DungeonMapConfig options = NotEnoughUpdates.INSTANCE.config.dungeonMap;
+
+ if (id >= 0 && id <= 2) {
+ return options.dmBorderSize == id;
+ } else if (id >= 3 && id <= 5) {
+ return options.dmRoomSize == id - 3;
+ } else if (id >= 6 && id <= 17) {
+ return options.dmBorderStyle == id - 6;
+ } else if (id == 29) {
+ return options.dmRoomSize == 3;
+ } else if (id == 30) {
+ return options.dmBorderSize == 3;
+ }
+ return false;
+ }
+
+ Shader blurShaderHorz = null;
+ Framebuffer blurOutputHorz = null;
+ Shader blurShaderVert = null;
+ Framebuffer blurOutputVert = null;
+
+ /**
+ * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
+ * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
+ * <p>
+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to
+ * apply scales and translations manually.
+ */
+ private Matrix4f createProjectionMatrix(int width, int height) {
+ Matrix4f projMatrix = new Matrix4f();
+ projMatrix.setIdentity();
+ projMatrix.m00 = 2.0F / (float) width;
+ projMatrix.m11 = 2.0F / (float) (-height);
+ projMatrix.m22 = -0.0020001999F;
+ projMatrix.m33 = 1.0F;
+ projMatrix.m03 = -1.0F;
+ projMatrix.m13 = 1.0F;
+ projMatrix.m23 = -1.0001999F;
+ return projMatrix;
+ }
+
+ private double lastBgBlurFactor = -1;
+
+ private void blurBackground() {
+ if (!OpenGlHelper.isFramebufferEnabled()) return;
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ if (blurOutputHorz == null) {
+ blurOutputHorz = new Framebuffer(width, height, false);
+ blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if (blurOutputVert == null) {
+ blurOutputVert = new Framebuffer(width, height, false);
+ blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if (blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
+ blurOutputHorz.createBindFramebuffer(width, height);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ if (blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
+ blurOutputVert.createBindFramebuffer(width, height);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+
+ if (blurShaderHorz == null) {
+ try {
+ blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz
+ );
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch (Exception ignored) {
+ }
+ }
+ if (blurShaderVert == null) {
+ try {
+ blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ blurOutputHorz, blurOutputVert
+ );
+ blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch (Exception ignored) {
+ }
+ }
+ if (blurShaderHorz != null && blurShaderVert != null) {
+ if (15 != lastBgBlurFactor) {
+ blurShaderHorz.getShaderManager().getShaderUniform("Radius").set((float) 15);
+ blurShaderVert.getShaderManager().getShaderUniform("Radius").set((float) 15);
+ lastBgBlurFactor = 15;
+ }
+ GL11.glPushMatrix();
+ blurShaderHorz.loadShader(0);
+ blurShaderVert.loadShader(0);
+ GlStateManager.enableDepth();
+ GL11.glPopMatrix();
+
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ }
+
+ /**
+ * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
+ * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
+ */
+ public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
+ if (!OpenGlHelper.isFramebufferEnabled()) return;
+
+ float uMin = x / (float) width;
+ float uMax = (x + blurWidth) / (float) width;
+ float vMin = (height - y) / (float) height;
+ float vMax = (height - y - blurHeight) / (float) height;
+
+ blurOutputVert.bindFramebufferTexture();
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax);
+ blurOutputVert.unbindFramebufferTexture();
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java
new file mode 100644
index 00000000..8e0f24b9
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java
@@ -0,0 +1,85 @@
+package io.github.moulberry.notenoughupdates.envcheck;
+
+import javax.swing.*;
+import java.lang.reflect.Field;
+import java.util.Objects;
+
+public class EnvironmentScan {
+
+ static Class<?> tryGetClass(String name) {
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ static Object tryGetField(Class<?> clazz, Object inst, String name) {
+ if (clazz == null) return null;
+ try {
+ Field declaredField = clazz.getDeclaredField(name);
+ return declaredField.get(inst);
+ } catch (NoSuchFieldException | IllegalAccessException ignored) {
+ }
+ return null;
+ }
+
+
+ static boolean isAtLeast(Object left, int right) {
+ if (left instanceof Integer) {
+ return (Integer) left >= right;
+ }
+ return false;
+ }
+
+ static boolean shouldCheckOnce = true;
+
+ static void checkEnvironmentOnce() {
+ if (shouldCheckOnce) checkEnvironment();
+ }
+
+
+ static void checkEnvironment() {
+ shouldCheckOnce = false;
+ checkForgeEnvironment();
+ }
+
+ static void checkForgeEnvironment() {
+ Class<?> forgeVersion = tryGetClass("net.minecraftforge.common.ForgeVersion");
+ if (forgeVersion == null
+ || !Objects.equals(tryGetField(forgeVersion, null, "majorVersion"), 11)
+ || !Objects.equals(tryGetField(forgeVersion, null, "minorVersion"), 15)
+ || !isAtLeast(tryGetField(forgeVersion, null, "revisionVersion"), 1)
+ || !Objects.equals(tryGetField(forgeVersion, null, "mcVersion"), "1.8.9")
+ ) {
+
+ System.out.printf("Forge Version : %s%nMajor : %s%nMinor : %s%nRevision : %s%nMinecraft : %s%n",
+ forgeVersion,
+ tryGetField(forgeVersion, null, "majorVersion"),
+ tryGetField(forgeVersion, null, "minorVersion"),
+ tryGetField(forgeVersion, null, "revisionVersion"),
+ tryGetField(forgeVersion, null, "mcVersion")
+ );
+ missingOrOutdatedForgeError();
+ }
+ }
+
+ static void missingOrOutdatedForgeError() {
+ showErrorMessage(
+ "You just launched NotEnoughUpdates with the wrong (or no) modloader installed.",
+ "",
+ "NotEnoughUpdates only works in Minecraft 1.8.9, with Forge 11.15.1+",
+ "Please relaunch NotEnoughUpdates in the correct environment.",
+ "If you are using Minecraft 1.8.9 with Forge 11.15.1+ installed, please contact support.",
+ "Click OK to launch anyways."
+ );
+ }
+
+
+ public static void showErrorMessage(String... messages) {
+ String message = String.join("\n", messages);
+ JOptionPane.showMessageDialog(
+ null, message, "NotEnoughUpdates - Problematic System Configuration", JOptionPane.ERROR_MESSAGE
+ );
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java
new file mode 100644
index 00000000..4a70fca3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/FabricEntrypoint.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.envcheck;
+
+public class FabricEntrypoint {
+ static {
+ EnvironmentScan.checkForgeEnvironment();
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java
new file mode 100644
index 00000000..44e24ff4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/NEUMixinConfigPlugin.java
@@ -0,0 +1,46 @@
+package io.github.moulberry.notenoughupdates.envcheck;
+
+import org.spongepowered.asm.lib.tree.ClassNode;
+import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
+import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
+
+import java.util.List;
+import java.util.Set;
+
+public class NEUMixinConfigPlugin implements IMixinConfigPlugin {
+
+ static {
+ EnvironmentScan.checkEnvironmentOnce();
+ }
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ return true;
+ }
+
+ @Override
+ public void acceptTargets(Set<String> myTargets, Set<String> otherTargets) {
+ }
+
+ @Override
+ public List<String> getMixins() {
+ return null;
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/GuiInventoryBackgroundDrawnEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/GuiInventoryBackgroundDrawnEvent.java
new file mode 100644
index 00000000..0b8bf126
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/GuiInventoryBackgroundDrawnEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.events;
+
+import net.minecraft.client.gui.inventory.GuiContainer;
+
+public class GuiInventoryBackgroundDrawnEvent extends NEUEvent {
+ private final GuiContainer container;
+ private final float partialTicks;
+
+ public GuiInventoryBackgroundDrawnEvent(GuiContainer container, float partialTicks) {
+ this.container = container;
+ this.partialTicks = partialTicks;
+ }
+
+ public GuiContainer getContainer() {
+ return container;
+ }
+
+ public float getPartialTicks() {
+ return partialTicks;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/NEUEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/NEUEvent.java
index a2c82070..178431d0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/events/NEUEvent.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/NEUEvent.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.events;
import net.minecraftforge.common.MinecraftForge;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/OnBlockBreakSoundEffect.java b/src/main/java/io/github/moulberry/notenoughupdates/events/OnBlockBreakSoundEffect.java
index aeffa7da..9a2516e1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/events/OnBlockBreakSoundEffect.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/OnBlockBreakSoundEffect.java
@@ -1,6 +1,24 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.events;
-import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.audio.ISound;
import net.minecraft.util.BlockPos;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java
new file mode 100644
index 00000000..ab650c54
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/RepositoryReloadEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.events;
+
+import java.io.File;
+
+public class RepositoryReloadEvent extends NEUEvent {
+ private final File baseFile;
+ private final boolean isFirstLoad;
+
+ public RepositoryReloadEvent(File baseFile, boolean isFirstLoad) {
+ this.baseFile = baseFile;
+ this.isFirstLoad = isFirstLoad;
+ }
+
+ public boolean isFirstLoad() {
+ return isFirstLoad;
+ }
+
+ public File getRepositoryRoot() {
+ return baseFile;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/SignSubmitEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/SignSubmitEvent.java
new file mode 100644
index 00000000..9bc7b8b0
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/SignSubmitEvent.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.events;
+
+import net.minecraft.client.gui.inventory.GuiEditSign;
+
+public class SignSubmitEvent extends NEUEvent {
+ public final GuiEditSign sign;
+ public final String[] lines;
+
+ public SignSubmitEvent(GuiEditSign sign, String[] hehe) {
+ this.sign = sign;
+ this.lines = hehe;
+ }
+
+ public GuiEditSign getSign() {
+ return sign;
+ }
+
+ public String[] getLines() {
+ return lines;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/events/SlotClickEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/events/SlotClickEvent.java
new file mode 100644
index 00000000..13c31b54
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/events/SlotClickEvent.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.events;
+
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.inventory.Slot;
+import net.minecraftforge.fml.common.eventhandler.Cancelable;
+
+@Cancelable
+public class SlotClickEvent extends NEUEvent {
+ public final GuiContainer guiContainer;
+ public final Slot slot;
+ public final int slotId;
+ public int clickedButton;
+ public int clickType;
+ public boolean usePickblockInstead = false;
+
+ public SlotClickEvent(GuiContainer guiContainer, Slot slot, int slotId, int clickedButton, int clickType) {
+ this.guiContainer = guiContainer;
+ this.slot = slot;
+ this.slotId = slotId;
+ this.clickedButton = clickedButton;
+ this.clickType = clickType;
+ }
+
+ public void usePickblockInstead() {
+ usePickblockInstead = true;
+ }
+
+ @Override
+ public void setCanceled(boolean cancel) {
+ super.setCanceled(cancel);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java
deleted file mode 100644
index 77305904..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java
+++ /dev/null
@@ -1,323 +0,0 @@
-package io.github.moulberry.notenoughupdates.gamemodes;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.util.ChatComponentText;
-import net.minecraft.util.EnumChatFormatting;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
-
-public class GuiGamemodes extends GuiScreen {
- private final String currentProfile;
- private SBGamemodes.Gamemode currentGamemode = null;
- private final boolean upgradeOverride;
-
- private int guiLeft = 100;
- private int guiTop = 100;
- private final int xSize = 200;
- private final int ySize = 232;
-
- public GuiGamemodes(boolean upgradeOverride) {
- this.currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
- this.upgradeOverride = upgradeOverride;
- }
-
- private boolean canChange(int from, int to) {
- if (from >= to) {
- return true;
- } else {
- return !currentGamemode.locked || upgradeOverride;
- }
- }
-
- @Override
- public void updateScreen() {
- if (this.currentProfile == null) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- Minecraft.getMinecraft().thePlayer.addChatMessage(
- new ChatComponentText(EnumChatFormatting.RED + "Couldn't detect current profile. Maybe try later?"));
- }
-
- if (currentGamemode == null) {
- currentGamemode = SBGamemodes.getGamemode();
- if (currentGamemode == null) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- Minecraft.getMinecraft().thePlayer.addChatMessage(
- new ChatComponentText(EnumChatFormatting.RED + "Couldn't automatically detect current profile." +
- "If you have only 1 profile, try using /api new so that NEU can detect your profile."));
- }
- }
-
- String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
- if (!this.currentProfile.equals(currentProfile)) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- Minecraft.getMinecraft().thePlayer.addChatMessage(
- new ChatComponentText(EnumChatFormatting.RED + "Profile change detected. Closing gamemodes menu."));
- }
- }
-
- @Override
- public void handleKeyboardInput() throws IOException {
- if (Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
- SBGamemodes.saveToFile();
- }
-
- super.handleKeyboardInput();
- }
-
- public void drawStringShadow(String str, float x, float y, int len) {
- for (int xOff = -2; xOff <= 2; xOff++) {
- for (int yOff = -2; yOff <= 2; yOff++) {
- if (Math.abs(xOff) != Math.abs(yOff)) {
- Utils.drawStringScaledMaxWidth(Utils.cleanColourNotModifiers(str),
- Minecraft.getMinecraft().fontRendererObj,
- x + xOff / 2f, y + yOff / 2f, false, len,
- new Color(20, 20, 20, 100 / Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB()
- );
- }
- }
- }
-
- Utils.drawStringScaledMaxWidth(str,
- Minecraft.getMinecraft().fontRendererObj,
- x, y, false, len,
- new Color(64, 64, 64, 255).getRGB()
- );
- }
-
- @Override
- protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
- if (mouseButton == 0) {
- SBGamemodes.HardcoreMode setHC = SBGamemodes.HardcoreMode.NORMAL;
- SBGamemodes.IronmanMode setIM = SBGamemodes.IronmanMode.NORMAL;
- int setMod = 0;
-
- if (mouseX > guiLeft + xSize - 27 && mouseX < guiLeft + xSize - 9) {
- if (mouseY > guiTop + 30 && mouseY < guiTop + 30 + 16) {
- setHC = SBGamemodes.HardcoreMode.SOFTCORE;
- } else if (mouseY > guiTop + 50 && mouseY < guiTop + 50 + 16) {
- setHC = SBGamemodes.HardcoreMode.HARDCORE;
- } else if (mouseY > guiTop + 80 && mouseY < guiTop + 80 + 16) {
- setIM = SBGamemodes.IronmanMode.IRONMAN;
- } else if (mouseY > guiTop + 100 && mouseY < guiTop + 100 + 16) {
- setIM = SBGamemodes.IronmanMode.IRONMANPLUS;
- } else if (mouseY > guiTop + 120 && mouseY < guiTop + 120 + 16) {
- setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN;
- } else if (mouseY > guiTop + 140 && mouseY < guiTop + 140 + 16) {
- setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS;
- } else if (mouseY > guiTop + 170 && mouseY < guiTop + 170 + 16) {
- setMod = SBGamemodes.MODIFIER_DEVILISH;
- } else if (mouseY > guiTop + 190 && mouseY < guiTop + 190 + 16) {
- setMod = SBGamemodes.MODIFIER_NOBANK;
- } else if (mouseY > guiTop + 210 && mouseY < guiTop + 210 + 16) {
- setMod = SBGamemodes.MODIFIER_SMALLISLAND;
- }
- }
-
- if (setHC != SBGamemodes.HardcoreMode.NORMAL) {
- if (currentGamemode.hardcoreMode == setHC) {
- currentGamemode.hardcoreMode = SBGamemodes.HardcoreMode.NORMAL;
- } else {
- if (canChange(currentGamemode.hardcoreMode.ordinal(), setHC.ordinal())) {
- currentGamemode.hardcoreMode = setHC;
- }
- }
- } else if (setIM != SBGamemodes.IronmanMode.NORMAL) {
- if (currentGamemode.ironmanMode == setIM) {
- currentGamemode.ironmanMode = SBGamemodes.IronmanMode.NORMAL;
- } else {
- if (canChange(currentGamemode.ironmanMode.ordinal(), setIM.ordinal())) {
- currentGamemode.ironmanMode = setIM;
- }
- }
- } else if (setMod != 0) {
- if (canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers ^ setMod)) {
- currentGamemode.gamemodeModifiers ^= setMod;
- }
- }
- }
- }
-
- @Override
- public void drawScreen(int mouseX, int mouseY, float partialTicks) {
- super.drawDefaultBackground();
-
- guiLeft = (width - xSize) / 2;
- guiTop = (height - ySize) / 2;
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(gamemodes);
- Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, GL11.GL_NEAREST);
-
- if (currentGamemode == null) return;
-
- Utils.drawStringCentered("NEU Skyblock Gamemodes", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + xSize / 2f, guiTop + 14, false, new Color(64, 64, 64).getRGB()
- );
-
- drawStringShadow(SBGamemodes.HardcoreMode.SOFTCORE.display, guiLeft + 10, guiTop + 30, xSize - 47);
- drawStringShadow(SBGamemodes.HardcoreMode.HARDCORE.display, guiLeft + 10, guiTop + 50, xSize - 47);
-
- drawStringShadow(SBGamemodes.IronmanMode.IRONMAN.display, guiLeft + 10, guiTop + 80, xSize - 47);
- drawStringShadow(SBGamemodes.IronmanMode.IRONMANPLUS.display, guiLeft + 10, guiTop + 100, xSize - 47);
- drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.display, guiLeft + 10, guiTop + 120, xSize - 47);
- drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.display, guiLeft + 10, guiTop + 140, xSize - 47);
-
- drawStringShadow(SBGamemodes.MODIFIER_DEVILISH_DISPLAY, guiLeft + 10, guiTop + 170, xSize - 47);
- drawStringShadow(SBGamemodes.MODIFIER_NOBANK_DISPLAY, guiLeft + 10, guiTop + 190, xSize - 47);
- drawStringShadow(SBGamemodes.MODIFIER_SMALLISLAND_DISPLAY, guiLeft + 10, guiTop + 210, xSize - 47);
-
- String tooltipToDisplay = null;
-
- GlStateManager.color(1, 1, 1, 1);
- if (canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.SOFTCORE.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.SOFTCORE ? radial_circle_on : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 30 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 30 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 30 - 4 && mouseY < guiTop + 30 + 12) {
- tooltipToDisplay = SBGamemodes.HardcoreMode.SOFTCORE.desc;
- }
- }
- }
- if (canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.HARDCORE.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.HARDCORE ? radial_circle_on : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 50 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 50 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 50 - 4 && mouseY < guiTop + 50 + 12) {
- tooltipToDisplay = SBGamemodes.HardcoreMode.HARDCORE.desc;
- }
- }
- }
-
- if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMAN.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMAN ? radial_circle_on : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 80 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 80 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 80 - 4 && mouseY < guiTop + 80 + 12) {
- tooltipToDisplay = SBGamemodes.IronmanMode.IRONMAN.desc;
- }
- }
- }
- if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMANPLUS.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMANPLUS ? radial_circle_on : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 100 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 100 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 100 - 4 && mouseY < guiTop + 100 + 12) {
- tooltipToDisplay = SBGamemodes.IronmanMode.IRONMANPLUS.desc;
- }
- }
- }
- if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMAN ? radial_circle_on : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 120 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 120 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 120 - 4 && mouseY < guiTop + 120 + 12) {
- tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.desc;
- }
- }
- }
- if (canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.ordinal())) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS
- ? radial_circle_on
- : radial_circle_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 140 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 140 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 140 - 4 && mouseY < guiTop + 140 + 12) {
- tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.desc;
- }
- }
- }
-
- if (canChange(
- currentGamemode.gamemodeModifiers,
- currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_DEVILISH
- )) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_DEVILISH) != 0
- ? radial_square_on
- : radial_square_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 170 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 170 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 170 - 4 && mouseY < guiTop + 170 + 12) {
- tooltipToDisplay = SBGamemodes.MODIFIER_DEVILISH_DESC;
- }
- }
- }
- if (canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_NOBANK)) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_NOBANK) != 0 ? radial_square_on : radial_square_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 190 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 190 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 190 - 4 && mouseY < guiTop + 190 + 12) {
- tooltipToDisplay = SBGamemodes.MODIFIER_NOBANK_DESC;
- }
- }
- }
- if (canChange(
- currentGamemode.gamemodeModifiers,
- currentGamemode.gamemodeModifiers ^ SBGamemodes.MODIFIER_SMALLISLAND
- )) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(
- (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_SMALLISLAND) != 0
- ? radial_square_on
- : radial_square_off);
- Utils.drawTexturedRect(guiLeft + xSize - 26, guiTop + 210 - 4, 16, 16, GL11.GL_NEAREST);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- Utils.drawTexturedRect(guiLeft + xSize - 47, guiTop + 210 - 4, 16, 16, GL11.GL_NEAREST);
- if (mouseX > guiLeft + xSize - 47 && mouseX < guiLeft + xSize - 31) {
- if (mouseY > guiTop + 210 - 4 && mouseY < guiTop + 210 + 12) {
- tooltipToDisplay = SBGamemodes.MODIFIER_SMALLISLAND_DESC;
- }
- }
- }
-
- if (tooltipToDisplay != null) {
- List<String> lines = new ArrayList<>();
- for (String line : tooltipToDisplay.split("\n")) {
- lines.add(EnumChatFormatting.GRAY + line);
- }
- Utils.drawHoveringText(lines, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java
deleted file mode 100644
index ddd4a4ba..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java
+++ /dev/null
@@ -1,374 +0,0 @@
-package io.github.moulberry.notenoughupdates.gamemodes;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
-import net.minecraft.client.gui.inventory.GuiChest;
-import net.minecraft.inventory.ContainerChest;
-import net.minecraft.util.ChatComponentText;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.event.entity.player.PlayerInteractEvent;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.SecretKeySpec;
-import java.io.*;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.security.Key;
-import java.util.Base64;
-import java.util.HashMap;
-
-public class SBGamemodes {
- private static final Gson gson = new Gson();
-
- public static final int MODIFIER_DEVILISH = 0b1;
- public static final int MODIFIER_NOBANK = 0b10;
- public static final int MODIFIER_SMALLISLAND = 0b100;
-
- public static final String MODIFIER_DEVILISH_DISPLAY = EnumChatFormatting.DARK_PURPLE + "Devilish";
- public static final String MODIFIER_NOBANK_DISPLAY = EnumChatFormatting.RED + "No" + EnumChatFormatting.GOLD + "Bank";
- public static final String MODIFIER_SMALLISLAND_DISPLAY = EnumChatFormatting.GREEN + "SmallIsland";
-
- public static final String MODIFIER_DEVILISH_DESC = EnumChatFormatting.DARK_PURPLE + "Devilish\n" +
- "You are NOT allowed to use fairy souls.";
- public static final String MODIFIER_NOBANK_DESC = EnumChatFormatting.RED + "No" + EnumChatFormatting.GOLD + "Bank\n" +
- "You are NOT allowed to use the bank.";
- public static final String MODIFIER_SMALLISLAND_DESC = EnumChatFormatting.GREEN + "SmallIsland\n" +
- "Your private island is 1/4 the normal size.";
-
- private static HashMap<String, Gamemode> currentGamemode = new HashMap<>();
- private static long lastDeathExemption = 0;
-
- public static class Gamemode {
- public HardcoreMode hardcoreMode = HardcoreMode.NORMAL;
- public IronmanMode ironmanMode = IronmanMode.NORMAL;
- public int gamemodeModifiers = 0;
-
- public boolean locked = true;
- }
-
- public enum HardcoreMode {
- NORMAL("Normal", "Normal"),
- SOFTCORE(EnumChatFormatting.RED + "Soft" + EnumChatFormatting.DARK_RED + "core\n" +
- "You only have 1 life.\nDying will remove your hardcore status.\nDeaths to the void or 'unknown' are exempted.",
- "You died.", "You fell into the void"
- ),
- HARDCORE(EnumChatFormatting.DARK_RED + "Hardcore\n" +
- "You only have 1 life.\nDying will remove your hardcore status.");
-
- public final String display;
- public final String desc;
- private final String[] exemptions;
-
- HardcoreMode(String display, String... exemptions) {
- this.display = display.split("\n")[0];
- this.desc = display;
- this.exemptions = exemptions;
- }
-
- public boolean isExemption(String line) {
- for (String exemption : exemptions) {
- if (line.contains(exemption)) return true;
- }
- return false;
- }
- }
-
- public enum IronmanMode {
- NORMAL("Normal"),
- IRONMAN(EnumChatFormatting.WHITE + "Ironman\n" +
- "You are NOT allowed to trade or use the auction house.",
- "You ", "Auction House", "Auctions Browser", "Auction View"
- ),
- IRONMANPLUS(EnumChatFormatting.WHITE + "Ironman" + EnumChatFormatting.GOLD + "+\n" +
- "You are NOT allowed to trade, use the auction house or bazaar.",
- "You ", "Auction House", "Auctions Browser", "Auction View", "Bazaar"
- ),
- ULTIMATE_IRONMAN(EnumChatFormatting.DARK_AQUA + "Ultimate " + EnumChatFormatting.WHITE + "Ironman\n" +
- "You are NOT allowed to trade or use the auction house.\n" +
- "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).",
- "You ", "Auction House", "Auctions Browser", "Auction View", "Chest",
- "Wardrobe", "Weapon Rack", "Shelves"
- ),
- ULTIMATE_IRONMANPLUS(
- EnumChatFormatting.DARK_AQUA + "Ultimate " + EnumChatFormatting.WHITE + "Ironman" + EnumChatFormatting.GOLD +
- "+\n" +
- "You are NOT allowed to trade, use the auction house or bazaar.\n" +
- "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).",
- "You ",
- "Auction House",
- "Auctions Browser",
- "Auction View",
- "Bazaar",
- "Chest",
- "Wardrobe",
- "Weapon Rack",
- "Shelves"
- );
-
- public final String display;
- public final String desc;
- private final String[] bannedInventories;
-
- IronmanMode(String display, String... bannedInventories) {
- this.display = display.split("\n")[0];
- this.desc = display;
- this.bannedInventories = bannedInventories;
- }
-
- public boolean isBanned(String inventoryName) {
- for (String banned : bannedInventories) {
- if (inventoryName.contains(banned + " ") || inventoryName.endsWith(banned)) return true;
- }
- return false;
- }
- }
-
- public static Gamemode getGamemode() {
- String currentProfile = SBInfo.getInstance().currentProfile;
-
- if (currentProfile == null || currentProfile.isEmpty()) return null;
-
- return currentGamemode.computeIfAbsent(currentProfile, k -> new Gamemode());
- }
-
- public static void loadFromFile() {
- File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation;
- File gamemodeFile = new File(
- configDir,
- "gamemodes/gamemodes-" + Minecraft.getMinecraft().thePlayer.getUniqueID().toString() + ".json"
- );
- gamemodeFile.getParentFile().mkdirs();
-
- if (!gamemodeFile.exists()) {
- return;
- }
-
- try (
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(gamemodeFile),
- StandardCharsets.UTF_8
- ))
- ) {
- String line = reader.readLine();
- String decoded = decrypt(line);
- currentGamemode = gson.fromJson(decoded, GamemodeWrapper.class).currentGamemode;
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static class GamemodeWrapper {
- private final HashMap<String, Gamemode> currentGamemode;
-
- public GamemodeWrapper(HashMap<String, Gamemode> currentGamemode) {
- this.currentGamemode = currentGamemode;
- }
- }
-
- public static void saveToFile() {
- File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation;
- File gamemodeFile = new File(
- configDir,
- "gamemodes/gamemodes-" + Minecraft.getMinecraft().thePlayer.getUniqueID().toString() + ".json"
- );
- gamemodeFile.getParentFile().mkdirs();
-
- try {
- gamemodeFile.createNewFile();
-
- try (
- BufferedWriter writer = new BufferedWriter(
- new OutputStreamWriter(new FileOutputStream(gamemodeFile), StandardCharsets.UTF_8))
- ) {
- JsonObject obj = new JsonObject();
- writer.write(encrypt(gson.toJson(new GamemodeWrapper(currentGamemode), GamemodeWrapper.class)));
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public static Key getKeyFromPlayerUUID() {
- byte[] bytes = ByteBuffer.allocate(2 * Long.SIZE / Byte.SIZE)
- .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getLeastSignificantBits())
- .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getMostSignificantBits())
- .array();
- SecretKeySpec key = new SecretKeySpec(bytes, "AES");
-
- return key;
- }
-
- public static String encrypt(String value) {
- try {
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.ENCRYPT_MODE, getKeyFromPlayerUUID());
- String encrypt = Base64.getEncoder().encodeToString(cipher.doFinal(value.getBytes()));
- return encrypt;
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static String decrypt(String encrypted) {
- try {
- Cipher cipher = Cipher.getInstance("AES");
- cipher.init(Cipher.DECRYPT_MODE, getKeyFromPlayerUUID());
- byte[] b64Decoded = Base64.getDecoder().decode(encrypted);
- byte[] bytes = cipher.doFinal(b64Decoded);
-
- return new String(bytes);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- public static void setGamemode(Gamemode gamemode) {
- String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
-
- if (currentProfile == null || currentProfile.isEmpty()) return;
-
- currentGamemode.put(currentProfile, gamemode);
- }
-
- @SubscribeEvent
- public void onPlayerInteract(PlayerInteractEvent event) {
- if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
-
- if (!"Your Island".equals(SBInfo.getInstance().location)) return;
-
- if ((getGamemode().gamemodeModifiers & MODIFIER_SMALLISLAND) != 0) {
- if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
- if (Math.abs(event.pos.getX()) > 40 || Math.abs(event.pos.getZ()) > 40) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NPC] Builder" +
- EnumChatFormatting.WHITE + ": Sorry, " + Minecraft.getMinecraft().thePlayer.getName() +
- ", due to budget cuts your skyblock island is now only 80 blocks wide."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" +
- EnumChatFormatting.AQUA + " if you would like to build further out)"));
-
- event.setCanceled(true);
- }
- }
- }
- }
-
- @SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent event) {
- if (event.phase != TickEvent.Phase.START) return;
-
- if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
-
- boolean inDungeons = SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals(
- "dungeon");
-
- getGamemode().locked = !(EnumChatFormatting.YELLOW + "Break a log").equals(SBInfo.getInstance().objective);
-
- IronmanMode ironmanMode = getGamemode().ironmanMode;
- GuiScreen gui = Minecraft.getMinecraft().currentScreen;
- if (gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- if (containerName.equals("Bank") && (getGamemode().gamemodeModifiers & MODIFIER_NOBANK) != 0) {
- Minecraft.getMinecraft().thePlayer.closeScreen();
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NPC] Banker" +
- EnumChatFormatting.WHITE + ": Hi, " + Minecraft.getMinecraft().thePlayer.getName() +
- ", you would like to create an account and make a deposit?"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NPC] Banker" +
- EnumChatFormatting.WHITE + ": Alright, I've invested your money into ..."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[" +
- EnumChatFormatting.WHITE + "YouTube" + EnumChatFormatting.RED + "] Nullzee" +
- EnumChatFormatting.WHITE + ": Hows it going everyone, welcome to my ultimate bazaar flipping guide ..."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NPC] Banker" +
- EnumChatFormatting.WHITE +
- ": Hmm, it seems as though the economy has crashed. All your money is gone. Poof. Vanished."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[IDIOT] You" +
- EnumChatFormatting.WHITE + ": ... never again ..."));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" +
- EnumChatFormatting.AQUA + " if you would like to use the bank)"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- } else if (containerName.equals("Fairy") && (getGamemode().gamemodeModifiers & MODIFIER_DEVILISH) != 0) {
- Minecraft.getMinecraft().thePlayer.closeScreen();
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NPC] " + EnumChatFormatting.LIGHT_PURPLE + "Tia the Fairy" +
- EnumChatFormatting.WHITE + ": Oh no, " + Minecraft.getMinecraft().thePlayer.getName() +
- ", you have sold your soul to the devil... please go away!"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" +
- EnumChatFormatting.AQUA + " if you would like to use fairy souls)"));
- } else if (!inDungeons && ironmanMode.isBanned(containerName)) {
- Minecraft.getMinecraft().thePlayer.closeScreen();
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.AQUA + "You cannot access this inventory/menu because of your"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- " " + ironmanMode.display + EnumChatFormatting.AQUA + " status!"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.AQUA + "(Use " + EnumChatFormatting.YELLOW + "/neugamemodes" +
- EnumChatFormatting.AQUA + " if you would like to downgrade the status)"));
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
- }
- }
- }
-
- @SubscribeEvent
- public void onChatMessage(ClientChatReceivedEvent event) {
- if (event.type != 0) return;
-
- /*if(Keyboard.isKeyDown(Keyboard.KEY_K)) {
- boolean has = false;
- for(char c : event.message.getFormattedText().toCharArray()) {
- if((int)c > 200) {
- if(!has) System.out.println("-----START");
- has = true;
- System.out.println((int)c);
- }
- }
- if(has) System.out.println("-----END");
- }*/
- if (getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
-
- String message = event.message.getFormattedText();
- if (message.contains("\u2620")) { //Death symbol ( ☠ )
- HardcoreMode hardcoreMode = getGamemode().hardcoreMode;
- if (hardcoreMode != HardcoreMode.NORMAL) {
- if (hardcoreMode.isExemption(message)) {
- lastDeathExemption = System.currentTimeMillis();
- }
- }
- }
-
- if (System.currentTimeMillis() - lastDeathExemption > 1000 &&
- message.contains("!") && message.startsWith(
- EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "You died")) {
- if (getGamemode().hardcoreMode != HardcoreMode.NORMAL) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.RED.toString() + EnumChatFormatting.OBFUSCATED + "AAA" +
- EnumChatFormatting.RED + " You have lost your " +
- getGamemode().hardcoreMode.display + EnumChatFormatting.RED + " status! " +
- EnumChatFormatting.RED + EnumChatFormatting.OBFUSCATED + "AAA"));
- getGamemode().hardcoreMode = HardcoreMode.NORMAL;
- }
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
deleted file mode 100644
index bbdbabd2..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
+++ /dev/null
@@ -1,534 +0,0 @@
-package io.github.moulberry.notenoughupdates.infopanes;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NEUManager;
-import io.github.moulberry.notenoughupdates.NEUOverlay;
-import io.github.moulberry.notenoughupdates.util.NEUResourceManager;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.shader.Framebuffer;
-import net.minecraft.client.shader.Shader;
-import net.minecraft.item.ItemStack;
-import net.minecraft.util.EnumChatFormatting;
-import org.lwjgl.input.Mouse;
-import org.lwjgl.opengl.GL11;
-
-import java.awt.*;
-import java.util.List;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.item_mask;
-
-public class CollectionLogInfoPane extends ScrollableInfoPane {
- private final String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$";
- private final String petRegex = ".*?;[0-4]$";
-
- TreeSet<String> items = new TreeSet<>(getItemComparator());
-
- private int buttonHover = -1;
-
- private int previousAcquiredCount = 0;
- private int previousScroll = 0;
- private int previousX = 0;
- private int previousFilter = 0;
-
- private final long lastUpdate = 0;
-
- private static final int FILTER_ALL = 0;
- private static final int FILTER_WEAPON = 1;
- private static final int FILTER_ARMOR = 2;
- private static final int FILTER_ACCESSORY = 3;
- private static final int FILTER_PET = 4;
- private static final int FILTER_DUNGEON = 5;
- private static final int FILTER_SLAYER_ZOMBIE = 6;
- private static final int FILTER_SLAYER_WOLF = 7;
- private static final int FILTER_SLAYER_SPIDER = 8;
- private int filterMode = FILTER_ALL;
- private final String[] filterPrettyNames = new String[]{
- "ALL", "WEAPON", "ARMOR",
- "ACCESSORY", "PET", "DUNGEON", "ZOMBIE SLAYER", "WOLF SLAYER", "SPIDER SLAYER"
- };
-
- private Framebuffer itemFramebuffer = null;
- private Framebuffer itemBGFramebuffer = null;
- private Framebuffer itemFramebufferGrayscale = null;
- private Shader grayscaleShader = null;
-
- private final int updateCounter = 0;
-
- public CollectionLogInfoPane(NEUOverlay overlay, NEUManager manager) {
- super(overlay, manager);
- refreshItems();
- }
-
- private boolean loreContains(JsonArray lore, String str) {
- for (int i = 0; i < lore.size(); i++) {
- String line = lore.get(i).getAsString();
- if (line.contains(str)) return true;
- }
- return false;
- }
-
- private void refreshItems() {
- items.clear();
- for (String internalname : manager.getItemInformation().keySet()) {
- if (!manager.auctionManager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) {
- JsonObject item = manager.getItemInformation().get(internalname);
- JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray();
- switch (filterMode) {
- case FILTER_WEAPON:
- if (overlay.checkItemType(lore, "SWORD", "BOW", "WAND") < 0) continue;
- break;
- case FILTER_ARMOR:
- if (overlay.checkItemType(lore, "HELMET", "CHESTPLATE", "LEGGINGS", "BOOTS") < 0) continue;
- break;
- case FILTER_ACCESSORY:
- if (overlay.checkItemType(lore, "ACCESSORY") < 0) continue;
- break;
- case FILTER_PET:
- if (!internalname.matches(petRegex) || !item.get("displayname").getAsString().contains("["))
- continue;
- break;
- case FILTER_DUNGEON:
- if (Utils.checkItemType(lore, true, "DUNGEON") < 0) continue;
- break;
- case FILTER_SLAYER_ZOMBIE:
- if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("ZOMBIE"))
- continue;
- break;
- case FILTER_SLAYER_WOLF:
- if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("WOLF"))
- continue;
- break;
- case FILTER_SLAYER_SPIDER:
- if (!item.has("slayer_req") || !item.get("slayer_req").getAsString().startsWith("SPIDER"))
- continue;
- break;
- }
- items.add(internalname);
- }
- }
- }
-
- private Map<String, ArrayList<String>> getAcquiredItems() {
- return null;//manager.config.collectionLog.value;
- }
-
- private Comparator<String> getItemComparator() {
- return (o1, o2) -> {
- float cost1 = manager.auctionManager.getLowestBin(o1);
- float cost2 = manager.auctionManager.getLowestBin(o2);
-
- if (cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1).craftCost;
- if (cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2).craftCost;
-
- if (cost1 < cost2) return 1;
- if (cost1 > cost2) return -1;
-
- return o1.compareTo(o2);
- };
- }
-
- public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) {
- super.mouseInput(width, height, mouseX, mouseY, mouseDown);
- if (mouseDown) {
- if (buttonHover == 0) {
- if (Mouse.getEventButton() == 0) {
- filterMode++;
- if (filterMode >= filterPrettyNames.length) {
- filterMode = 0;
- }
- } else if (Mouse.getEventButton() == 1) {
- filterMode--;
- if (filterMode < 0) {
- filterMode = filterPrettyNames.length - 1;
- }
- }
- }
- refreshItems();
- }
- }
-
- public void render(
- int width,
- int height,
- Color bg,
- Color fg,
- ScaledResolution scaledresolution,
- int mouseX,
- int mouseY
- ) {
- int paneWidth = (int) (width / 3 * overlay.getWidthMult());
- int rightSide = (int) (width * overlay.getInfoPaneOffsetFactor());
- int leftSide = rightSide - paneWidth;
- int padding = overlay.getBoxPadding();
-
- renderDefaultBackground(width, height, bg);
-
- renderControls(height, padding, leftSide + padding, rightSide - padding, 20, fg);
- renderCollectionLog(fg, width, height, leftSide + padding, rightSide - padding, padding + 25, height - padding);
- }
-
- private float getCompletedness() {
- int total = items.size();
- int own = 0;
- for (String item : items) {
- if (getAcquiredItems() != null &&
- getAcquiredItems().containsKey(manager.getCurrentProfile()) &&
- getAcquiredItems().get(manager.getCurrentProfile()).contains(item)) {
- own++;
- }
-
- }
- return own / (float) total;
- }
-
- private final EnumChatFormatting[] rainbow = new EnumChatFormatting[]{
- EnumChatFormatting.RED,
- EnumChatFormatting.GOLD,
- EnumChatFormatting.YELLOW,
- EnumChatFormatting.GREEN,
- EnumChatFormatting.AQUA,
- EnumChatFormatting.LIGHT_PURPLE,
- EnumChatFormatting.DARK_PURPLE
- };
-
- private String getCompletednessString() {
- float completedness = getCompletedness();
- String text = (int) (completedness * 100) + "% Complete";
- if (completedness >= 1) {
- StringBuilder rainbowText = new StringBuilder();
- for (int i = 0; i < text.length(); i++) {
- char c = text.charAt(i);
- int index = (int) (i - System.currentTimeMillis() / 100) % rainbow.length;
- if (index < 0) index += rainbow.length;
- rainbowText.append(rainbow[index]).append(c);
- }
- text = rainbowText.toString();
- }
- return text;
- }
-
- private void renderControls(int height, int top, int left, int right, int ySize, Color fg) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
-
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
-
- buttonHover = -1;
-
- int totalAvailable = right - left;
- int controlPadding = 3;
- String[] controls = new String[]{
- "Filter: " + filterPrettyNames[filterMode],
- getCompletednessString()
- };
- int numControls = controls.length;
- int available = totalAvailable - (numControls - 1) * controlPadding;
- int controlSize = available / numControls;
- int extraPadding = (available % controlSize) / 2;
-
- for (int i = 0; i < numControls; i++) {
- int width = controlSize + controlPadding;
- int x = left + extraPadding + i * width;
-
- if (mouseX > x && mouseX < x + controlSize) {
- if (mouseY > top && mouseY < top + ySize) {
- buttonHover = i;
- }
- }
-
- drawRect(x, top, x + controlSize, top + ySize,
- new Color(177, 177, 177).getRGB()
- );
- drawRect(x + 1, top + 1, x + controlSize, top + ySize,
- new Color(50, 50, 50).getRGB()
- );
- drawRect(x + 1, top + 1, x + controlSize - 1, top + ySize - 1, fg.getRGB());
- Utils.drawStringCenteredScaledMaxWidth(controls[i], Minecraft.getMinecraft().fontRendererObj,
- x + width / 2f, top + ySize / 2f, true, controlSize - 4, Color.WHITE.getRGB()
- );
- }
- }
-
- public int getCurrentAcquiredCount() {
- if (getAcquiredItems() == null) return 0;
- if (!getAcquiredItems().containsKey(manager.getCurrentProfile())) return 0;
- return getAcquiredItems().get(manager.getCurrentProfile()).size();
- }
-
- private void renderCollectionLog(Color fg, int width, int height, int left, int right, int top, int bottom) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
-
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
-
- if (itemFramebuffer != null && grayscaleShader != null &&
- (itemFramebuffer.framebufferWidth != width || itemFramebuffer.framebufferHeight != height)) {
- grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix(
- width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor()));
- }
-
- itemFramebuffer = checkFramebufferSizes(itemFramebuffer, width, height,
- scaledresolution.getScaleFactor()
- );
- itemBGFramebuffer = checkFramebufferSizes(itemBGFramebuffer, width, height,
- scaledresolution.getScaleFactor()
- );
- itemFramebufferGrayscale = checkFramebufferSizes(itemFramebufferGrayscale, width, height,
- scaledresolution.getScaleFactor()
- );
-
- /*if(!manager.config.cacheRenderedItempane.value || previousAcquiredCount != getCurrentAcquiredCount() ||
- previousScroll != scrollHeight.getValue() || previousX != left || previousFilter != filterMode ||
- System.currentTimeMillis() - lastUpdate > 5000) {
- lastUpdate = System.currentTimeMillis();
- renderItemsToImage(itemFramebuffer, fg, left+5, right, top+1, bottom);
- renderItemBGToImage(itemBGFramebuffer, fg, left+5, right, top+1, bottom);
- }*/
- previousAcquiredCount = getCurrentAcquiredCount();
- previousScroll = scrollHeight.getValue();
- previousX = left;
- previousFilter = filterMode;
-
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
- renderFromImage(itemBGFramebuffer, width, height, left, right, top, bottom);
- renderFromImage(itemFramebuffer, width, height, left, right, top, bottom);
-
- if (grayscaleShader == null) {
- try {
- grayscaleShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
- "grayscale",
- itemFramebuffer, itemFramebufferGrayscale
- );
- grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix(
- width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor()));
- } catch (Exception e) {
- return;
- }
- }
-
- GL11.glPushMatrix();
- grayscaleShader.loadShader(0);
- GlStateManager.enableDepth();
- GL11.glPopMatrix();
-
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
-
- itemFramebufferGrayscale.bindFramebufferTexture();
-
- AtomicReference<ItemStack> tooltipToDisplay = new AtomicReference<>(null);
-
- AtomicBoolean isTop = new AtomicBoolean(false);
- AtomicInteger lowestY = new AtomicInteger(-1);
-
- String[] items = getItemList();
- GlStateManager.color(1f, 1f, 1f, 1f);
- iterateItemSlots(new ItemSlotConsumer() {
- @Override
- public void consume(int x, int y, int id) {
- if (id < items.length) {
- String internalname = items[id];
- if (id == 0) isTop.set(true);
-
- int leftI = x - 1;
- int rightI = x + 17;
- int topI = y - 1;
- int bottomI = y + 17;
-
- lowestY.set(Math.max(bottomI, lowestY.get()));
-
- if (mouseX > leftI && mouseX < rightI) {
- if (mouseY > topI && mouseY < bottomI) {
- tooltipToDisplay.set(manager.jsonToStack(manager.getItemInformation().get(internalname), true));
- }
- }
-
- if (getAcquiredItems() != null &&
- getAcquiredItems().containsKey(manager.getCurrentProfile()) &&
- getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) {
- return;
- }
-
- topI = Math.max(topI, top);
- bottomI = Math.min(bottomI, bottom);
-
- Utils.drawTexturedRect(leftI, topI, rightI - leftI, bottomI - topI,
- leftI / (float) width, rightI / (float) width,
- (height - topI) / (float) height, (height - bottomI) / (float) height
- );
- }
- }
- }, left + 5, right, top + 1, bottom);
-
- if (!isTop.get()) {
- if (lowestY.get() == -1) {
- scrollHeight.setValue(0);
- } else {
- int dist = bottom - lowestY.get() - 10;
- if (dist > 0) {
- scrollHeight.setValue(scrollHeight.getValue() - dist);
- }
- }
- }
-
- itemFramebufferGrayscale.unbindFramebufferTexture();
-
- ItemStack displayStack = tooltipToDisplay.get();
- if (displayStack != null) {
- List<String> text = displayStack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
- Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
- }
- }
-
- private String[] getItemList() {
- String[] items_arr = new String[items.size()];
- int i = 0;
- for (String internalname : items) {
- items_arr[i++] = internalname;
- }
- return items_arr;
- }
-
- private int limCol(int col) {
- return Math.min(255, Math.max(0, col));
- }
-
- private void renderItems(int left, int right, int top, int bottom) {
- String[] items = getItemList();
- iterateItemSlots(new ItemSlotConsumer() {
- public void consume(int x, int y, int id) {
- if (id < items.length) {
- String internalname = items[id];
-
- ItemStack stack = manager.jsonToStack(manager.getItemInformation().get(internalname));
- Utils.drawItemStack(stack, x, y);
- }
- }
- }, left, right, top, bottom);
- }
-
- private void renderItemBackgrounds(Color fg, int left, int right, int top, int bottom) {
- Color fgCustomOpacity =
- null;//new Color(SpecialColour.specialToChromaRGB(manager.config.itemBackgroundColour.value), true);
- Color fgGold = null;//new Color(SpecialColour.specialToChromaRGB(manager.config.itemFavouriteColour.value), true);
-
- String[] items = getItemList();
- iterateItemSlots(new ItemSlotConsumer() {
- public void consume(int x, int y, int id) {
- if (id < items.length) {
- String internalname = items[id];
-
- Color color = fgCustomOpacity;
- if (getAcquiredItems() != null &&
- getAcquiredItems().containsKey(manager.getCurrentProfile()) &&
- getAcquiredItems().get(manager.getCurrentProfile()).contains(internalname)) {
- color = fgGold;
- }
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
- /*if(manager.config.itemStyle.value) {
- GlStateManager.color(color.getRed() / 255f, color.getGreen() / 255f,
- color.getBlue() / 255f, color.getAlpha() / 255f);
- Utils.drawTexturedRect(x - 1, y - 1, overlay.ITEM_SIZE + 2, overlay.ITEM_SIZE + 2, GL11.GL_NEAREST);
- } else {
- drawRect(x-1, y-1, x+overlay.ITEM_SIZE+1, y+overlay.ITEM_SIZE+1, color.getRGB());
- }*/
- GlStateManager.bindTexture(0);
- }
- }
- }, left, right, top, bottom);
- }
-
- /**
- * Checks whether the screen size has changed, if so it reconstructs the itemPane framebuffer and marks that the
- * itemPane should be redrawn.
- */
- private Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height, int scaleFactor) {
- int sw = width * scaleFactor;
- int sh = height * scaleFactor;
-
- if (framebuffer == null || framebuffer.framebufferWidth != sw || framebuffer.framebufferHeight != sh) {
- if (framebuffer == null) {
- framebuffer = new Framebuffer(sw, sh, true);
- } else {
- framebuffer.createBindFramebuffer(sw, sh);
- }
- framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
- }
- return framebuffer;
- }
-
- private void renderItemsToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) {
- GL11.glPushMatrix();
- framebuffer.framebufferClear();
- framebuffer.bindFramebuffer(false);
-
- renderItems(left, right, top, bottom);
-
- framebuffer.unbindFramebuffer();
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
- GL11.glPopMatrix();
- }
-
- private void renderItemBGToImage(Framebuffer framebuffer, Color fg, int left, int right, int top, int bottom) {
- GL11.glPushMatrix();
- framebuffer.framebufferClear();
- framebuffer.bindFramebuffer(false);
-
- renderItemBackgrounds(fg, left, right, top, bottom);
-
- framebuffer.unbindFramebuffer();
- Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
- GL11.glPopMatrix();
- }
-
- private void renderFromImage(
- Framebuffer framebuffer,
- int width,
- int height,
- int left,
- int right,
- int top,
- int bottom
- ) {
- framebuffer.bindFramebufferTexture();
- GlStateManager.color(1f, 1f, 1f, 1f);
- Utils.drawTexturedRect(left, top, right - left, bottom - top,
- left / (float) width, right / (float) width,
- (height - top) / (float) height, (height - bottom) / (float) height
- );
- framebuffer.unbindFramebufferTexture();
- }
-
- private abstract static class ItemSlotConsumer {
- public abstract void consume(int x, int y, int id);
- }
-
- public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int left, int right, int top, int bottom) {
- int scrolledTop = top - scrollHeight.getValue();
-
- int id = 0;
- int extraSize = NEUOverlay.ITEM_SIZE + NEUOverlay.ITEM_PADDING;
- for (int y = scrolledTop; y < bottom; y += extraSize) {
- for (int x = left; x < right - extraSize; x += extraSize) {
- if (y > top - extraSize) {
- itemSlotConsumer.consume(x, y, id);
- }
- if (++id >= items.size()) {
- return;
- }
- }
- }
- }
-
- public boolean keyboardInput() {
- return false;
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
index 945dd71c..0b1963d6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import com.google.gson.JsonObject;
@@ -62,6 +81,7 @@ public class DevInfoPane extends TextInfoPane {
for (String internalname : manager.auctionManager.getItemAuctionInfoKeySet()) {
if (internalname.matches("^.*-[0-9]{1,3}$")) continue;
if (!manager.getItemInformation().containsKey(internalname)) {
+ if (internalname.equals("RUNE") || internalname.contains("PARTY_HAT_CRAB")) continue;
text += internalname + "\n";
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
index 441bf735..4b6c73f4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/FlipperInfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import io.github.moulberry.notenoughupdates.NEUManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
index baf88457..de9c608f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import info.bliki.htmlcleaner.TagNode;
@@ -14,6 +33,7 @@ import io.github.moulberry.notenoughupdates.util.AllowEmptyHTMLTag;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.texture.DynamicTexture;
@@ -25,15 +45,26 @@ import org.apache.commons.lang3.SystemUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.regex.Pattern;
public class HTMLInfoPane extends TextInfoPane {
private static final WikiModel wikiModel;
@@ -47,6 +78,10 @@ public class HTMLInfoPane extends TextInfoPane {
private int imageHeight = 0;
private int imageWidth = 0;
+ private float xMin = 0;
+ private int mouseOffset = 0;
+ private boolean selected = false;
+
private static boolean hasAttemptedDownload = false;
/*
@@ -61,6 +96,16 @@ public class HTMLInfoPane extends TextInfoPane {
conf.addTokenTag("infobox", new IgnoreTag("infobox"));
conf.addTokenTag("tabber", new IgnoreTag("tabber"));
conf.addTokenTag("kbd", new HTMLTag("kbd"));
+ conf.addTokenTag("td", new AllowEmptyHTMLTag("td"));
+ conf.addTokenTag("tbody", new AllowEmptyHTMLTag("tbody"));
+ conf.addTokenTag("style", new AllowEmptyHTMLTag("style"));
+ conf.addTokenTag("article", new AllowEmptyHTMLTag("article"));
+ conf.addTokenTag("section", new AllowEmptyHTMLTag("section"));
+ conf.addTokenTag("link", new AllowEmptyHTMLTag("link"));
+ conf.addTokenTag("wbr", new AllowEmptyHTMLTag("wbr"));
+ conf.addTokenTag("dl", new AllowEmptyHTMLTag("dl"));
+ conf.addTokenTag("dd", new AllowEmptyHTMLTag("dd"));
+ conf.addTokenTag("dt", new AllowEmptyHTMLTag("dt"));
wikiModel = new WikiModel(conf, "https://hypixel-skyblock.fandom.com/wiki/Special:Filepath/${image}",
"https://hypixel-skyblock.fandom.com/wiki/${title}"
) {
@@ -101,7 +146,7 @@ public class HTMLInfoPane extends TextInfoPane {
) {
return manager.getWebFile(wikiUrl).thenApply(f -> {
if (f == null) {
- return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl);
+ return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl, false);
}
StringBuilder sb = new StringBuilder();
@@ -114,9 +159,16 @@ public class HTMLInfoPane extends TextInfoPane {
sb.append(l).append("\n");
}
} catch (IOException e) {
- return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl);
+ return new HTMLInfoPane(overlay, manager, "error", "error", "Failed to load wiki url: " + wikiUrl, false);
}
- return createFromWikiText(overlay, manager, name, f.getName(), sb.toString());
+ return createFromWikiText(
+ overlay,
+ manager,
+ name,
+ f.getName(),
+ sb.toString(),
+ wikiUrl.startsWith("https://wiki.hypixel.net/")
+ );
});
}
@@ -126,30 +178,55 @@ public class HTMLInfoPane extends TextInfoPane {
* a more permanent solution that can be abstracted to work with arbitrary wiki codes (eg. moulberry.github.io/
* files/neu_help.html).
*/
+
+ private static final Pattern replacePattern = Pattern.compile(
+ "<nav class=\"page-actions-menu\">.*</nav>|",
+ Pattern.DOTALL
+ );
+
public static HTMLInfoPane createFromWikiText(
NEUOverlay overlay, NEUManager manager, String name, String filename,
- String wiki
+ String wiki, boolean isOfficialWiki
) {
- String[] split = wiki.split("</infobox>");
- wiki = split[split.length - 1]; //Remove everything before infobox
- wiki = wiki.split("<span class=\"navbox-vde\">")[0]; //Remove navbox
- wiki = wiki.split("<table class=\"navbox mw-collapsible\"")[0];
- wiki = "__NOTOC__\n" + wiki; //Remove TOC
+ if (isOfficialWiki) {
+ wiki = wiki.split("<main id=\"content\" class=\"mw-body\">")[1].split("</main>")[0]; // hide top bar
+ wiki = wiki.split("<div class=\"container-navbox\">")[0]; // hide giant bottom list
+ wiki = wiki.split("<div class=\"categoryboxcontainer\">")[0]; // hide small bottom category thing
+ wiki = replacePattern.matcher(wiki).replaceAll("");
+ wiki = wiki.replaceAll(
+ "<div id=\"siteNotice\"></div><div id=\"mw-dismissablenotice-anonplace\"></div><script>.*</script>",
+ ""
+ ); // hide beta box
+ wiki = wiki.replaceAll("<h1 id=\"section_0\">.*</h1>", ""); // hide title
+ wiki = wiki.replace("src=\"/", "src=\"https://wiki.hypixel.net/");
+ wiki = wiki.replace("\uD83D\uDDF8", "✓"); // replace checkmark with one that renders
+ wiki = wiki.replace("\uD83E\uDC10", "\u27F5"); // replace left arrow with one that renders
+ wiki = wiki.replace("\uD83E\uDC12", "\u27F6"); // replace right arrow with one that renders
+ } else {
+ String[] split = wiki.split("</infobox>");
+ wiki = split[split.length - 1]; //Remove everything before infobox
+ wiki = wiki.split("<span class=\"navbox-vde\">")[0]; //Remove navbox
+ wiki = wiki.split("<table class=\"navbox mw-collapsible\"")[0];
+ wiki = "__NOTOC__\n" + wiki; //Remove TOC
+ }
try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/parsed.txt"))) {
out.println(wiki);
} catch (IOException ignored) {
}
String html;
try {
- html = wikiModel.render(wiki);
- } catch (IOException e) {
- return new HTMLInfoPane(overlay, manager, "error", "error", "Could not render wiki.");
+ if (isOfficialWiki)
+ html = wiki;
+ else
+ html = wikiModel.render(wiki);
+ } catch (Exception e) {
+ return new HTMLInfoPane(overlay, manager, "error", "error", "Could not render wiki.", false);
}
try (PrintWriter out = new PrintWriter(new File(manager.configLocation, "debug/html.txt"))) {
out.println(html);
} catch (IOException ignored) {
}
- return new HTMLInfoPane(overlay, manager, name, filename, html);
+ return new HTMLInfoPane(overlay, manager, name, filename, html, isOfficialWiki);
}
private String spaceEscape(String str) {
@@ -164,7 +241,14 @@ public class HTMLInfoPane extends TextInfoPane {
* generation is done asynchronously as sometimes it can take up to 10 seconds for more
* complex webpages.
*/
- public HTMLInfoPane(NEUOverlay overlay, NEUManager manager, String name, String filename, String html) {
+ public HTMLInfoPane(
+ NEUOverlay overlay,
+ NEUManager manager,
+ String name,
+ String filename,
+ String html,
+ boolean isOfficial
+ ) {
super(overlay, manager, name, "");
this.title = name;
@@ -180,7 +264,7 @@ public class HTMLInfoPane extends TextInfoPane {
return;
}
- File cssFile = new File(manager.configLocation, "wikia.css");
+ File cssFile = new File(manager.configLocation, isOfficial ? "official-wiki.css" : "wikia.css");
File wkHtmlToImage = new File(manager.configLocation, "wkhtmltox-" + osId + "/bin/wkhtmltoimage");
//Use old binary folder
@@ -235,13 +319,20 @@ public class HTMLInfoPane extends TextInfoPane {
return;
}
+ if (!cssFile.exists() && isOfficial) {
+ try {
+ Files.copy(this.getClass().getResourceAsStream("/assets/notenoughupdates/official-wiki.css"), cssFile.toPath());
+ } catch (IOException e) {
+ e.printStackTrace();
+ return;
+ }
+ }
+
File input = new File(manager.configLocation, "tmp/input.html");
String outputFileName = filename.replaceAll("(?i)\\u00A7.", "")
.replaceAll("[^a-zA-Z0-9_\\-]", "_");
File output = new File(manager.configLocation, "tmp/" +
outputFileName + ".png");
- File outputExt = new File(manager.configLocation, "tmp/" +
- outputFileName + "_ext.png");
input.deleteOnExit();
output.deleteOnExit();
@@ -412,12 +503,23 @@ public class HTMLInfoPane extends TextInfoPane {
}
int yScroll = scrollHeight.getValue();
+ float xSize = Math.min((paneWidth - overlay.getBoxPadding() * 2f) / imageWidth * scaleF, 1);
+ float xMax = xMin + xSize;
+
float vMin = yScroll / (imageHeight / scaleF);
float vMax = (yScroll + height - overlay.getBoxPadding() * 3) / (imageHeight / scaleF);
Utils.drawTexturedRect(leftSide + overlay.getBoxPadding(), overlay.getBoxPadding() * 2, imageW,
- height - overlay.getBoxPadding() * 3,
- 0, 1, vMin, vMax
+ (height - overlay.getBoxPadding() * 3),
+ xMin, xMax, vMin, vMax
);
+ if (xSize < 1) {
+ int barX = (int) (xMin * imageW) + leftSide + overlay.getBoxPadding();
+ int barY = height - overlay.getBoxPadding() - 10;
+ int barWidth = (int) (xMax * imageW) + leftSide + overlay.getBoxPadding();
+ int barHeight = height - overlay.getBoxPadding() - 5;
+ boolean isHovered = mouseX >= barX && mouseX <= barWidth && mouseY >= barY && mouseY <= barHeight || selected;
+ Gui.drawRect(barX, barY, barWidth, barHeight, new Color(255, 255, 255, isHovered ? 150 : 100).getRGB());
+ }
} else {
scrollHeight.setValue(0);
@@ -435,6 +537,27 @@ public class HTMLInfoPane extends TextInfoPane {
@Override
public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) {
+ int paneWidth = (int) (width / 3 * overlay.getWidthMult());
+ int rightSide = (int) (width * overlay.getInfoPaneOffsetFactor());
+ int leftSide = rightSide - paneWidth;
+ int imageW = paneWidth - overlay.getBoxPadding() * 2;
+ float scaleF = IMAGE_WIDTH * ZOOM_FACTOR / (float) imageW;
+ float xSize = Math.min((paneWidth - overlay.getBoxPadding() * 2f) / imageWidth * scaleF, 1);
+ float xMax = xMin + xSize;
+ int barX = (int) (xMin * imageW) + leftSide + overlay.getBoxPadding();
+ int barY = height - overlay.getBoxPadding() - 10;
+ int barWidth = (int) (xMax * imageW) + leftSide + overlay.getBoxPadding();
+ int barHeight = height - overlay.getBoxPadding() - 5;
+ if (!mouseDown)
+ selected = false;
+ if (mouseX >= barX && mouseX <= barWidth && mouseY >= barY && mouseY <= barHeight && mouseDown || selected) {
+ if (!selected)
+ mouseOffset = mouseX - barX;
+ xMin = (mouseX - leftSide - overlay.getBoxPadding() / 2f - mouseOffset) / imageWidth * scaleF;
+ xMin = Math.max(0, xMin);
+ xMin = Math.min(xMin, 1 - xSize);
+ selected = true;
+ }
super.mouseInput(width, height, mouseX, mouseY, mouseDown);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
index 70d7d65b..5f73e57a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import io.github.moulberry.notenoughupdates.NEUManager;
@@ -61,10 +80,10 @@ public abstract class InfoPane extends Gui {
return HTMLInfoPane.createFromWikiUrl(overlay, manager, name, infoText);
case "WIKI":
return CompletableFuture.completedFuture(
- HTMLInfoPane.createFromWikiText(overlay, manager, name, internalName, infoText));
+ HTMLInfoPane.createFromWikiText(overlay, manager, name, internalName, infoText, false));
case "HTML":
return CompletableFuture.completedFuture(
- new HTMLInfoPane(overlay, manager, name, internalName, infoText));
+ new HTMLInfoPane(overlay, manager, name, internalName, infoText, false));
default:
return CompletableFuture.completedFuture(
new TextInfoPane(overlay, manager, name, infoText));
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/ScrollableInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/ScrollableInfoPane.java
index 75b66770..9bc47fc5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/ScrollableInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/ScrollableInfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import io.github.moulberry.notenoughupdates.NEUManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
index 77d47a3d..90bed1fa 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/TextInfoPane.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.infopanes;
import io.github.moulberry.notenoughupdates.NEUManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElement.java
index 38ad2824..ab277078 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElement.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElement.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.itemeditor;
import net.minecraft.client.gui.Gui;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementButton.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementButton.java
index 35b31490..54cba6b8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementButton.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementButton.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.itemeditor;
import java.awt.*;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementText.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementText.java
index 1e7a8c08..9f612fcf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementText.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementText.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.itemeditor;
import net.minecraft.client.Minecraft;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
index fd78f3aa..71c4d498 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.itemeditor;
import io.github.moulberry.notenoughupdates.util.Utils;
@@ -158,7 +177,12 @@ public class GuiElementTextField extends GuiElement {
String textNC = textNoColour.substring(0, cursorIndex);
int colorCodes = StringUtils.countMatches(textNC, "\u00B6");
- String line = text.substring(cursorIndex + (((options & COLOUR) != 0) ? colorCodes * 2 : 0)).split("\n")[0];
+ String[] lines = text.substring(cursorIndex + (((options & COLOUR) != 0) ? colorCodes * 2 : 0)).split("\n");
+ if (lines.length < 1) {
+ return 0;
+ }
+ String line = lines[0];
+
int padding = Math.min(5, searchBarXSize - strLenNoColor(line)) / 2;
String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(line, xComp - padding);
int linePos = strLenNoColor(trimmed);
@@ -210,6 +234,33 @@ public class GuiElementTextField extends GuiElement {
@Override
public void keyTyped(char typedChar, int keyCode) {
if (focus) {
+ //allows for pasting formatted text that includes "§"
+ if (GuiScreen.isKeyComboCtrlV(keyCode)) {
+ textField.setEnabled(false);
+
+ int selectionEnd = textField.getSelectionEnd();
+ int cursorPosition = textField.getCursorPosition();
+
+ if (cursorPosition < selectionEnd) {
+ //swap selectionEnd and cursorPosition
+ selectionEnd = selectionEnd ^ cursorPosition;
+ cursorPosition = selectionEnd ^ cursorPosition;
+ selectionEnd = selectionEnd ^ cursorPosition;
+ }
+
+ String clipboardContent = GuiScreen.getClipboardString();
+
+ StringBuilder stringBuilder = new StringBuilder(getText())
+ .replace(selectionEnd, cursorPosition, "")
+ .insert(selectionEnd, clipboardContent);
+
+ //writeText removes unwanted chars from the String which includes "§"
+ textField.setText(stringBuilder.toString());
+ textField.setCursorPosition(selectionEnd + clipboardContent.length());
+ } else {
+ textField.setEnabled(true);
+ }
+
if ((options & MULTILINE) != 0) { //Carriage return
Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n])(?!\\u00B6)");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
index 0392c32f..e08e5369 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/NEUItemEditor.java
@@ -1,8 +1,29 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.itemeditor;
import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NEUManager;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
@@ -14,7 +35,11 @@ import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.*;
+import net.minecraft.nbt.JsonToNBT;
+import net.minecraft.nbt.NBTException;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
@@ -27,116 +52,172 @@ import java.util.Arrays;
import java.util.List;
import java.util.function.Supplier;
-import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.*;
+import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.COLOUR;
+import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.FORCE_CAPS;
+import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.MULTILINE;
+import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.NO_SPACE;
+import static io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField.NUM_ONLY;
public class NEUItemEditor extends GuiScreen {
- private final NEUManager manager;
-
private final List<GuiElement> options = new ArrayList<>();
private final List<GuiElement> rightOptions = new ArrayList<>();
- private final JsonObject item;
+ private JsonObject item;
+ private final JsonObject savedRepoItem;
private static final int PADDING = 10;
private static final int SCROLL_AMOUNT = 20;
private final LerpingInteger scrollHeight = new LerpingInteger(0);
- private final Supplier<String> internalname;
- private final Supplier<String> itemid;
- private final Supplier<String> displayname;
+ private final Supplier<String> internalName;
+ private final Supplier<String> itemId;
+ private final Supplier<String> displayName;
private final Supplier<String> lore;
- private final Supplier<String> crafttext;
+ private final Supplier<String> craftText;
private final Supplier<String> infoType;
private final Supplier<String> info;
- private final Supplier<String> clickcommand;
+ private final Supplier<String> clickCommand;
private final Supplier<String> damage;
- private NBTTagCompound nbttag;
+ private NBTTagCompound nbtTag;
+ private int saved = 0;
- public NEUItemEditor(NEUManager manager, String internalname, JsonObject item) {
- this.manager = manager;
+ public NEUItemEditor(String internalName, JsonObject item) {
this.item = item;
-
if (item.has("nbttag")) {
try {
- nbttag = JsonToNBT.getTagFromJson(item.get("nbttag").getAsString());
+ nbtTag = JsonToNBT.getTagFromJson(item.get("nbttag").getAsString());
} catch (NBTException ignored) {
}
}
+ NBTTagCompound extraAttributes = nbtTag.getCompoundTag("ExtraAttributes");
+ extraAttributes.removeTag("uuid");
+ extraAttributes.removeTag("timestamp");
+
+ if (extraAttributes.hasKey("petInfo")) {
+ String petInfo = extraAttributes.getString("petInfo");
+ JsonObject jsonObject = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(petInfo, JsonObject.class);
+
+ jsonObject.remove("heldItem");
+ jsonObject.add("exp", new JsonPrimitive(0));
+ jsonObject.add("candyUsed", new JsonPrimitive(0));
+
+ extraAttributes.setString("petInfo", jsonObject.toString());
+ }
+
+ savedRepoItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().getOrDefault(internalName, null);
- internalname = internalname == null ? "" : internalname;
+ internalName = internalName == null ? "" : internalName;
options.add(new GuiElementText("Internal Name: ", Color.WHITE.getRGB()));
- this.internalname = addTextFieldWithSupplier(internalname, NO_SPACE | FORCE_CAPS);
+ this.internalName = addTextFieldWithSupplier(internalName, NO_SPACE | FORCE_CAPS);
options.add(new GuiElementText("Item ID: ", Color.WHITE.getRGB()));
String itemid = item.has("itemid") ? item.get("itemid").getAsString() : "";
- this.itemid = addTextFieldWithSupplier(itemid, NO_SPACE);
+ this.itemId = addTextFieldWithSupplier(itemid, NO_SPACE);
options.add(new GuiElementText("Display name: ", Color.WHITE.getRGB()));
- String displayname = item.has("displayname") ? item.get("displayname").getAsString() : "";
- this.displayname = addTextFieldWithSupplier(displayname, COLOUR);
+ String displayName = item.has("displayname") ? item.get("displayname").getAsString() : "";
+ this.displayName = addTextFieldWithSupplier(displayName, COLOUR);
options.add(new GuiElementText("Lore: ", Color.WHITE.getRGB()));
- JsonArray lore = item.has("lore") ? item.get("lore").getAsJsonArray() : new JsonArray();
+ JsonElement loreElement = getItemInfo("lore");
+ JsonArray lore = loreElement != null ? loreElement.getAsJsonArray() : new JsonArray();
String[] loreA = new String[lore.size()];
for (int i = 0; i < lore.size(); i++) loreA[i] = lore.get(i).getAsString();
this.lore = addTextFieldWithSupplier(String.join("\n", loreA), COLOUR | MULTILINE);
options.add(new GuiElementText("Craft text: ", Color.WHITE.getRGB()));
- String crafttext = item.has("crafttext") ? item.get("crafttext").getAsString() : "";
- this.crafttext = addTextFieldWithSupplier(crafttext, COLOUR);
+ JsonElement craftTextElement = getItemInfo("crafttext");
+ String craftText = craftTextElement != null ? craftTextElement.getAsString() : "";
+ this.craftText = addTextFieldWithSupplier(craftText, COLOUR);
options.add(new GuiElementText("Info type: ", Color.WHITE.getRGB()));
- String infoType = item.has("infoType") ? item.get("infoType").getAsString() : "";
+ JsonElement infoTypeElement = getItemInfo("infoType");
+ String infoType = infoTypeElement != null ? infoTypeElement.getAsString() : "";
this.infoType = addTextFieldWithSupplier(infoType, NO_SPACE | FORCE_CAPS);
options.add(new GuiElementText("Additional information: ", Color.WHITE.getRGB()));
- JsonArray info = item.has("info") ? item.get("info").getAsJsonArray() : new JsonArray();
+ JsonElement infoElement = getItemInfo("info");
+ JsonArray info = infoElement != null ? infoElement.getAsJsonArray() : new JsonArray();
String[] infoA = new String[info.size()];
for (int i = 0; i < info.size(); i++) infoA[i] = info.get(i).getAsString();
this.info = addTextFieldWithSupplier(String.join("\n", infoA), COLOUR | MULTILINE);
options.add(new GuiElementText("Click-command (viewrecipe or viewpotion): ", Color.WHITE.getRGB()));
- String clickcommand = item.has("clickcommand") ? item.get("clickcommand").getAsString() : "";
- this.clickcommand = addTextFieldWithSupplier(clickcommand, NO_SPACE);
+ JsonElement clickCommandElement = getItemInfo("clickcommand");
+ String clickCommand = clickCommandElement != null ? clickCommandElement.getAsString() : "";
+ this.clickCommand = addTextFieldWithSupplier(clickCommand, NO_SPACE);
options.add(new GuiElementText("Damage: ", Color.WHITE.getRGB()));
- String damage = item.has("damage") ? item.get("damage").getAsString() : "";
+ JsonElement damageElement = getItemInfo("damage");
+ String damage = damageElement != null ? damageElement.getAsString() : "";
this.damage = addTextFieldWithSupplier(damage, NO_SPACE | NUM_ONLY);
rightOptions.add(new GuiElementButton("Close (discards changes)", Color.LIGHT_GRAY.getRGB(), () ->
Minecraft.getMinecraft().displayGuiScreen(null)));
+
+ rightOptions.add(new GuiElementText("", Color.WHITE.getRGB()));
+
GuiElementButton button = new Object() { //Used to make the compiler shut the fuck up
final GuiElementButton b = new GuiElementButton("Save to local disk", Color.GREEN.getRGB(), new Runnable() {
public void run() {
if (save()) {
- b.setText("Save to local disk (SUCCESS)");
+ b.setText(saved == 0 ? "Saved" : "Saved (" + saved + ")");
+ saved++;
} else {
- b.setText("Save to local disk (FAILED)");
+ b.setText("Saving FAILED!");
}
}
});
}.b;
rightOptions.add(button);
- rightOptions.add(new GuiElementText("", Color.WHITE.getRGB()));
-
rightOptions.add(new GuiElementButton("Remove enchants", Color.RED.getRGB(), () -> {
- nbttag.removeTag("ench");
- nbttag.getCompoundTag("ExtraAttributes").removeTag("enchantments");
+ nbtTag.removeTag("ench");
+ extraAttributes.removeTag("enchantments");
}));
rightOptions.add(new GuiElementButton(
"Add enchant glint",
Color.ORANGE.getRGB(),
- () -> nbttag.setTag("ench", new NBTTagList())
+ () -> nbtTag.setTag("ench", new NBTTagList())
));
- rightOptions.add(new GuiElementButton("Remove timestamp/uuid", Color.RED.getRGB(), () -> {
- nbttag.getCompoundTag("ExtraAttributes").removeTag("uuid");
- nbttag.getCompoundTag("ExtraAttributes").removeTag("timestamp");
- }));
-
resetScrollToTop();
+ if (savedRepoItem != null) {
+ this.item = savedRepoItem;
+ } else {
+ this.item = item;
+ }
+ }
+
+ /**
+ * Creates a new ItemEditor object and instantly saves. This will update the lore/nbt tag and other item infos in the repo without removing things like recipes and wiki URLs and without showing the GUI
+ *
+ * @param internalName the internal name for the item
+ * @param item the Item as a JsonObject
+ * @return weather the saving was successful or not
+ * @see io.github.moulberry.notenoughupdates.NEUManager#getInternalNameForItem(ItemStack)
+ * @see io.github.moulberry.notenoughupdates.NEUManager#getJsonForItem(ItemStack)
+ */
+ public static boolean saveOnly(String internalName, JsonObject item) {
+ NEUItemEditor editor = new NEUItemEditor(internalName, item);
+ return editor.save();
+ }
+
+ /**
+ * Returns the Element from the item being edited or the already existing item, prioritizing the item currently being edited
+ *
+ * @param key The JSON key
+ * @return the element found, or null
+ */
+ private JsonElement getItemInfo(String key) {
+ if (item.has(key)) {
+ return item.get(key);
+ } else if (savedRepoItem != null && savedRepoItem.has(key)) {
+ return savedRepoItem.get(key);
+ } else {
+ return null;
+ }
}
public boolean save() {
@@ -150,15 +231,21 @@ public class NEUItemEditor extends GuiScreen {
if (infoA.length == 0 || infoA[0].isEmpty()) {
infoA = new String[0];
}
- return manager.writeItemJson(item, internalname.get(), itemid.get(), displayname.get(), lore.get().split("\n"),
- crafttext.get(), infoType.get(), infoA, clickcommand.get(), damageI, nbttag
+ return NotEnoughUpdates.INSTANCE.manager.writeItemJson(
+ item,
+ internalName.get(),
+ itemId.get(),
+ displayName.get(),
+ lore.get().split("\n"),
+ craftText.get(),
+ infoType.get(),
+ infoA,
+ clickCommand.get(),
+ damageI,
+ nbtTag
);
}
- public void onGuiClosed() {
- Keyboard.enableRepeatEvents(false);
- }
-
public Supplier<String> addTextFieldWithSupplier(String initialText, int options) {
GuiElementTextField textField = new GuiElementTextField(initialText, options);
this.options.add(textField);
@@ -166,7 +253,7 @@ public class NEUItemEditor extends GuiScreen {
}
public void resyncNbttag() {
- if (nbttag == null) nbttag = new NBTTagCompound();
+ if (nbtTag == null) nbtTag = new NBTTagCompound();
//Item lore
NBTTagList list = new NBTTagList();
@@ -174,17 +261,17 @@ public class NEUItemEditor extends GuiScreen {
list.appendTag(new NBTTagString(lore));
}
- NBTTagCompound display = nbttag.getCompoundTag("display");
+ NBTTagCompound display = nbtTag.getCompoundTag("display");
display.setTag("Lore", list);
//Name
- display.setString("Name", displayname.get());
- nbttag.setTag("display", display);
+ display.setString("Name", displayName.get());
+ nbtTag.setTag("display", display);
//Internal ID
- NBTTagCompound ea = nbttag.getCompoundTag("ExtraAttributes");
- ea.setString("id", internalname.get());
- nbttag.setTag("ExtraAttributes", ea);
+ NBTTagCompound ea = nbtTag.getCompoundTag("ExtraAttributes");
+ ea.setString("id", internalName.get());
+ nbtTag.setTag("ExtraAttributes", ea);
}
public void resetScrollToTop() {
@@ -238,9 +325,6 @@ public class NEUItemEditor extends GuiScreen {
drawRect(0, 0, width, height, backgroundColour.getRGB());
int yScroll = calculateYScroll();
- if (yScroll > 0) {
- //Render scroll bar
- }
int currentY = PADDING - yScroll;
for (GuiElement gui : options) {
@@ -263,7 +347,7 @@ public class NEUItemEditor extends GuiScreen {
drawRect(itemX - 9, itemY - 9, itemX + itemSize + 9, itemY + itemSize + 9, itemBorder.getRGB());
drawRect(itemX - 6, itemY - 6, itemX + itemSize + 6, itemY + itemSize + 6, Color.DARK_GRAY.getRGB());
drawRect(itemX - 5, itemY - 5, itemX + itemSize + 5, itemY + itemSize + 5, itemBackground.getRGB());
- ItemStack stack = new ItemStack(Item.itemRegistry.getObject(new ResourceLocation(itemid.get())));
+ ItemStack stack = new ItemStack(Item.itemRegistry.getObject(new ResourceLocation(itemId.get())));
if (stack.getItem() != null) {
try {
@@ -272,18 +356,18 @@ public class NEUItemEditor extends GuiScreen {
}
resyncNbttag();
- stack.setTagCompound(nbttag);
+ stack.setTagCompound(nbtTag);
int scaleFactor = itemSize / 16;
GL11.glPushMatrix();
GlStateManager.scale(scaleFactor, scaleFactor, 1);
- drawItemStack(stack, itemX / scaleFactor, itemY / scaleFactor, null);
+ drawItemStack(stack, itemX / scaleFactor, itemY / scaleFactor);
GL11.glPopMatrix();
}
//Tooltip
List<String> text = new ArrayList<>();
- text.add(displayname.get());
+ text.add(displayName.get());
text.addAll(Arrays.asList(lore.get().split("\n")));
Utils.drawHoveringText(text, itemX - 20, itemY + itemSize + 28, width, height, -1,
@@ -295,6 +379,12 @@ public class NEUItemEditor extends GuiScreen {
@Override
protected void keyTyped(char typedChar, int keyCode) {
+ boolean hasChanges = false;
+ if (keyCode == Keyboard.KEY_ESCAPE && !hasChanges) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ return;
+ }
+
for (GuiElement gui : options) {
gui.keyTyped(typedChar, keyCode);
}
@@ -398,7 +488,7 @@ public class NEUItemEditor extends GuiScreen {
}
}
- private void drawItemStack(ItemStack stack, int x, int y, String altText) {
+ private void drawItemStack(ItemStack stack, int x, int y) {
RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
FontRenderer font = Minecraft.getMinecraft().fontRendererObj;
@@ -406,7 +496,6 @@ public class NEUItemEditor extends GuiScreen {
itemRender.renderItemAndEffectIntoGUI(stack, x, y);
RenderHelper.disableStandardItemLighting();
- itemRender.renderItemOverlayIntoGUI(font, stack, x, y, altText);
+ itemRender.renderItemOverlayIntoGUI(font, stack, x, y, null);
}
-
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java
new file mode 100644
index 00000000..3473124c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
+import io.github.moulberry.notenoughupdates.miscfeatures.CookieWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.StreamerMode;
+import io.github.moulberry.notenoughupdates.overlays.OverlayManager;
+import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay;
+import io.github.moulberry.notenoughupdates.overlays.TimersOverlay;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.client.ClientCommandHandler;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.RNGMeter;
+import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.slayerXp;
+import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.timeSinceLastBoss;
+import static io.github.moulberry.notenoughupdates.overlays.SlayerOverlay.timeSinceLastBoss2;
+
+public class ChatListener {
+ private final NotEnoughUpdates neu;
+ private static final Pattern SLAYER_XP = Pattern.compile(
+ " (Spider|Zombie|Wolf|Enderman|Blaze) Slayer LVL (\\d) - (?:Next LVL in ([\\d,]+) XP!|LVL MAXED OUT!)");
+ AtomicBoolean missingRecipe = new AtomicBoolean(false);
+
+ public ChatListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ private String processText(String text) {
+ if (SBInfo.getInstance().getLocation() == null) return text;
+ if (!SBInfo.getInstance().getLocation().startsWith("mining_") && !SBInfo.getInstance().getLocation().equals(
+ "crystal_hollows"))
+ return text;
+
+ if (Minecraft.getMinecraft().thePlayer == null) return text;
+ if (!NotEnoughUpdates.INSTANCE.config.mining.drillFuelBar) return text;
+
+ return Utils.trimIgnoreColour(text.replaceAll(EnumChatFormatting.DARK_GREEN + "\\S+ Drill Fuel", ""));
+ }
+
+ private IChatComponent processChatComponent(IChatComponent chatComponent) {
+ IChatComponent newComponent;
+ if (chatComponent instanceof ChatComponentText) {
+ ChatComponentText text = (ChatComponentText) chatComponent;
+
+ newComponent = new ChatComponentText(processText(text.getUnformattedTextForChat()));
+ newComponent.setChatStyle(text.getChatStyle().createShallowCopy());
+
+ for (IChatComponent sibling : text.getSiblings()) {
+ newComponent.appendSibling(processChatComponent(sibling));
+ }
+ } else if (chatComponent instanceof ChatComponentTranslation) {
+ ChatComponentTranslation trans = (ChatComponentTranslation) chatComponent;
+
+ Object[] args = trans.getFormatArgs();
+ Object[] newArgs = new Object[args.length];
+ for (int i = 0; i < trans.getFormatArgs().length; i++) {
+ if (args[i] instanceof IChatComponent) {
+ newArgs[i] = processChatComponent((IChatComponent) args[i]);
+ } else {
+ newArgs[i] = args[i];
+ }
+ }
+ newComponent = new ChatComponentTranslation(trans.getKey(), newArgs);
+
+ for (IChatComponent sibling : trans.getSiblings()) {
+ newComponent.appendSibling(processChatComponent(sibling));
+ }
+ } else {
+ newComponent = chatComponent.createCopy();
+ }
+
+ return newComponent;
+ }
+
+ private IChatComponent replaceSocialControlsWithPV(IChatComponent chatComponent) {
+
+ if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 > 0 && chatComponent.getChatStyle() != null &&
+ chatComponent.getChatStyle().getChatClickEvent() != null &&
+ chatComponent.getChatStyle().getChatClickEvent().getAction() == ClickEvent.Action.RUN_COMMAND &&
+ NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ if (chatComponent.getChatStyle().getChatClickEvent().getValue().startsWith("/socialoptions")) {
+ String username = chatComponent.getChatStyle().getChatClickEvent().getValue().substring(15);
+ if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 1) {
+ chatComponent.setChatStyle(Utils.createClickStyle(
+ ClickEvent.Action.RUN_COMMAND,
+ "/pv " + username,
+ "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD +
+ username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s profile in " +
+ EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD + "NEU's" + EnumChatFormatting.RESET +
+ EnumChatFormatting.YELLOW + " profile viewer."
+ ));
+ return chatComponent;
+ } else if (NotEnoughUpdates.INSTANCE.config.misc.replaceSocialOptions1 == 2) {
+ chatComponent.setChatStyle(Utils.createClickStyle(
+ ClickEvent.Action.RUN_COMMAND,
+ "/ah " + username,
+ "" + EnumChatFormatting.YELLOW + "Click to open " + EnumChatFormatting.AQUA + EnumChatFormatting.BOLD +
+ username + EnumChatFormatting.RESET + EnumChatFormatting.YELLOW + "'s /ah page"
+ ));
+ return chatComponent;
+ }
+ } // wanted to add this for guild but guild uses uuid :sad:
+ }
+ return chatComponent;
+ }
+
+ /**
+ * 1) When receiving "You are playing on profile" messages, will set the current profile.
+ * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI)
+ * 3) Replaces lobby join notifications when streamer mode is active
+ */
+ @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
+ public void onGuiChat(ClientChatReceivedEvent e) {
+ if (e.type == 2) {
+ CrystalMetalDetectorSolver.process(e.message);
+ TimersOverlay.processActionBar(e.message.getUnformattedText());
+ e.message = processChatComponent(e.message);
+ return;
+ } else if (e.type == 0) {
+ e.message = replaceSocialControlsWithPV(e.message);
+ }
+
+ DungeonWin.onChatMessage(e);
+
+ String r = null;
+ String unformatted = Utils.cleanColour(e.message.getUnformattedText());
+ Matcher matcher = SLAYER_XP.matcher(unformatted);
+ if (unformatted.startsWith("You are playing on profile: ")) {
+ neu.manager.setCurrentProfile(unformatted
+ .substring("You are playing on profile: ".length())
+ .split(" ")[0].trim());
+ } else if (unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to:
+ neu.manager.setCurrentProfile(unformatted
+ .substring("Your profile was changed to: ".length())
+ .split(" ")[0].trim());
+ } else if (unformatted.startsWith("Your new API key is ")) {
+ NotEnoughUpdates.INSTANCE.config.apiData.apiKey =
+ unformatted.substring("Your new API key is ".length()).substring(
+ 0,
+ 36
+ );
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] API Key automatically configured"));
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ } else if (unformatted.startsWith("Player List Info is now disabled!")) {
+ SBInfo.getInstance().hasNewTab = false;
+ } else if (unformatted.startsWith("Player List Info is now enabled!")) {
+ SBInfo.getInstance().hasNewTab = true;
+ }
+ if (e.message.getFormattedText().equals(
+ EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "You haven't unlocked this recipe!" +
+ EnumChatFormatting.RESET)) {
+ r = EnumChatFormatting.RED + "You haven't unlocked this recipe!";
+ } else if (e.message.getFormattedText().startsWith(
+ EnumChatFormatting.RESET.toString() + EnumChatFormatting.RED + "Invalid recipe ")) {
+ r = "";
+ } else if (unformatted.equals(" NICE! SLAYER BOSS SLAIN!")) {
+ SlayerOverlay.isSlain = true;
+ } else if (unformatted.equals(" SLAYER QUEST STARTED!")) {
+ SlayerOverlay.isSlain = false;
+ if (timeSinceLastBoss == 0) {
+ SlayerOverlay.timeSinceLastBoss = System.currentTimeMillis();
+ } else {
+ timeSinceLastBoss2 = timeSinceLastBoss;
+ timeSinceLastBoss = System.currentTimeMillis();
+ }
+ } else if (unformatted.startsWith(" RNG Meter")) {
+ RNGMeter = unformatted.substring(" RNG Meter - ".length());
+ } else if (matcher.matches()) {
+ //matcher.group(1);
+ SlayerOverlay.slayerLVL = matcher.group(2);
+ if (!SlayerOverlay.slayerLVL.equals("9")) {
+ SlayerOverlay.slayerXp = matcher.group(3);
+ } else {
+ slayerXp = "maxed";
+ }
+ } else if (unformatted.startsWith("Sending to server") || (unformatted.startsWith(
+ "Your Slayer Quest has been cancelled!"))) {
+ SlayerOverlay.slayerQuest = false;
+ SlayerOverlay.unloadOverlayTimer = System.currentTimeMillis();
+ } else if (unformatted.startsWith("You consumed a Booster Cookie!")) {
+ CookieWarning.resetNotification();
+ } else if (unformatted.startsWith("QUICK MATHS! Solve:") && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ if (Math.random() < 0.2) {
+ if (NotEnoughUpdates.INSTANCE.config.misc.calculationMode == 2) {
+ ClientCommandHandler.instance.executeCommand(
+ Minecraft.getMinecraft().thePlayer,
+ "/neucalc " + unformatted.substring("QUICK MATHS! Solve: ".length())
+ );
+ }
+ }
+ }
+ if (e.message.getFormattedText().contains(
+ EnumChatFormatting.YELLOW + "Visit the Auction House to collect your item!")) {
+ if (NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null &&
+ System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) {
+ NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " +
+ NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId(NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid));
+ }
+ }
+ if (r != null) {
+ if (neu.manager.failViewItem(r)) {
+ e.setCanceled(true);
+ }
+ missingRecipe.set(true);
+ }
+ if (unformatted.startsWith("Sending to server") &&
+ NotEnoughUpdates.INSTANCE.config.misc.streamerMode && e.message instanceof ChatComponentText) {
+ String m = e.message.getFormattedText();
+ String m2 = StreamerMode.filterChat(e.message.getFormattedText());
+ if (!m.equals(m2)) {
+ e.message = new ChatComponentText(m2);
+ }
+ }
+ if (unformatted.startsWith("You found ") && SBInfo.getInstance().getLocation() != null &&
+ SBInfo.getInstance().getLocation().equals("crystal_hollows")) {
+ CrystalMetalDetectorSolver.resetSolution(true);
+ }
+ if (unformatted.startsWith("[NPC] Keeper of ") | unformatted.startsWith("[NPC] Professor Robot: ") ||
+ unformatted.startsWith(" ") || unformatted.startsWith("✦") || unformatted.equals(
+ " You've earned a Crystal Loot Bundle!"))
+ OverlayManager.crystalHollowOverlay.message(unformatted);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java
new file mode 100644
index 00000000..4b380c2f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipEssenceShopListener.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ItemTooltipEssenceShopListener {
+ private final NotEnoughUpdates neu;
+
+ private final Pattern ESSENCE_PATTERN = Pattern.compile("§5§o§d([\\d,]+) (.+) Essence");
+
+ public ItemTooltipEssenceShopListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ @SubscribeEvent
+ public void onItemTooltip(ItemTooltipEvent event) {
+ if (!neu.isOnSkyblock()) return;
+ if (event.toolTip == null) return;
+ if (!Utils.getOpenChestName().endsWith(" Essence Shop")) return;
+ if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.essencePriceInEssenceShop) return;
+
+ List<String> newToolTip = new ArrayList<>();
+ boolean next = false;
+ for (String line : event.toolTip) {
+
+ if (next) {
+ next = false;
+ Matcher matcher = ESSENCE_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ String rawNumber = matcher.group(1).replace(",", "");
+ int amount = Integer.parseInt(rawNumber);
+ String type = matcher.group(2);
+
+ String essenceName = "ESSENCE_" + type.toUpperCase();
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(essenceName);
+
+ if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
+ float bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
+ double price = bazaarPrice * amount;
+ String format = StringUtils.shortNumberFormat(price);
+ newToolTip.add(line + " §7(§6" + format + " coins§7)");
+ continue;
+ }
+ }
+ }
+
+ if (line.contains("Cost")) {
+ next = true;
+ }
+ newToolTip.add(line);
+ }
+
+ event.toolTip.clear();
+ event.toolTip.addAll(newToolTip);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java
new file mode 100644
index 00000000..d89e886f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipListener.java
@@ -0,0 +1,887 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import io.github.moulberry.notenoughupdates.ItemPriceInformation;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.MiscUtils;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTUtil;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.input.Keyboard;
+
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ItemTooltipListener {
+ public static final String petToolTipRegex =
+ "((Farming)|(Combat)|(Fishing)|(Mining)|(Foraging)|(Enchanting)|(Alchemy)) ((Mount)|(Pet)|(Morph)).*";
+ private final NotEnoughUpdates neu;
+ private final Pattern xpLevelPattern = Pattern.compile("(.*) (\\xA7e(.*)\\xA76/\\xA7e(.*))");
+ private final HashSet<String> percentStats = new HashSet<>();
+ DecimalFormat myFormatter = new DecimalFormat("#,###,###.###");
+ private String currentRarity = "COMMON";
+ private boolean copied = false;
+ private boolean showReforgeStoneStats = true;
+ private boolean pressedArrowLast = false;
+ private boolean pressedShiftLast = false;
+ private int sbaloaded = -1;
+
+ public ItemTooltipListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ percentStats.add("bonus_attack_speed");
+ percentStats.add("crit_damage");
+ percentStats.add("crit_chance");
+ percentStats.add("sea_creature_chance");
+ percentStats.add("ability_damage");
+ }
+
+ private boolean isSkyblockAddonsLoaded() {
+ if (sbaloaded == -1) {
+ if (Loader.isModLoaded("skyblockaddons")) {
+ sbaloaded = 1;
+ } else {
+ sbaloaded = 0;
+ }
+ }
+ return sbaloaded == 1;
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onItemTooltipLow(ItemTooltipEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return;
+
+ String internalName = NotEnoughUpdates.INSTANCE.manager
+ .createItemResolutionQuery()
+ .withCurrentGuiContext()
+ .withItemStack(event.itemStack)
+ .resolveInternalName();
+
+ if (internalName == null) {
+ return;
+ }
+ petToolTipXPExtendPetMenu(event);
+
+ boolean hasEnchantments = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey(
+ "enchantments",
+ 10
+ );
+ boolean hasAttributes = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey(
+ "attributes",
+ 10
+ );
+ Set<String> enchantIds = new HashSet<>();
+ if (hasEnchantments) enchantIds = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag(
+ "enchantments").getKeySet();
+
+ JsonObject enchantsConst = Constants.ENCHANTS;
+ JsonArray allItemEnchs = null;
+ Set<String> ignoreFromPool = new HashSet<>();
+ if (enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) {
+ try {
+ JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray();
+ for (JsonElement element : enchantPools) {
+ Set<String> currentPool = new HashSet<>();
+ for (JsonElement poolElement : element.getAsJsonArray()) {
+ String poolS = poolElement.getAsString();
+ currentPool.add(poolS);
+ }
+ for (JsonElement poolElement : element.getAsJsonArray()) {
+ String poolS = poolElement.getAsString();
+ if (enchantIds.contains(poolS)) {
+ ignoreFromPool.addAll(currentPool);
+ break;
+ }
+ }
+ }
+
+ JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject();
+ NBTTagCompound tag = event.itemStack.getTagCompound();
+ if (tag != null) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ out:
+ for (int i = list.tagCount(); i >= 0; i--) {
+ String line = list.getStringTagAt(i);
+ for (int j = 0; j < Utils.rarityArrC.length; j++) {
+ for (Map.Entry<String, JsonElement> entry : enchantsObj.entrySet()) {
+ if (line.contains(Utils.rarityArrC[j] + " " + entry.getKey()) || line.contains(
+ Utils.rarityArrC[j] + " DUNGEON " + entry.getKey()) || line.contains(
+ "SHINY " + Utils.rarityArrC[j].replaceAll("§.§.", "") + " DUNGEON " + entry.getKey())) {
+ allItemEnchs = entry.getValue().getAsJsonArray();
+ break out;
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+ }
+
+ boolean gotToEnchants = false;
+ boolean passedEnchants = false;
+
+ boolean dungeonProfit = false;
+ int index = 0;
+ List<String> newTooltip = new ArrayList<>();
+
+ for (String line : event.toolTip) {
+ if (line.endsWith(EnumChatFormatting.DARK_GRAY + "Reforge Stone") &&
+ NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showReforgeStats) {
+ JsonObject reforgeStones = Constants.REFORGESTONES;
+
+ if (reforgeStones != null && reforgeStones.has(internalName)) {
+ boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+ if (!pressedShiftLast && shift) {
+ showReforgeStoneStats = !showReforgeStoneStats;
+ }
+ pressedShiftLast = shift;
+
+ newTooltip.add(line);
+ newTooltip.add("");
+ if (!showReforgeStoneStats) {
+ newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to show extra info]");
+ } else {
+ newTooltip.add(EnumChatFormatting.DARK_GRAY + "[Press SHIFT to hide extra info]");
+ }
+
+ JsonObject reforgeInfo = reforgeStones.get(internalName).getAsJsonObject();
+ JsonArray requiredRaritiesArray = reforgeInfo.get("requiredRarities").getAsJsonArray();
+
+ if (showReforgeStoneStats && requiredRaritiesArray.size() > 0) {
+ String reforgeName = Utils.getElementAsString(reforgeInfo.get("reforgeName"), "");
+
+ String[] requiredRarities = new String[requiredRaritiesArray.size()];
+ for (int i = 0; i < requiredRaritiesArray.size(); i++) {
+ requiredRarities[i] = requiredRaritiesArray.get(i).getAsString();
+ }
+
+ int rarityIndex = requiredRarities.length - 1;
+ String rarity = requiredRarities[rarityIndex];
+ for (int i = 0; i < requiredRarities.length; i++) {
+ String rar = requiredRarities[i];
+ if (rar.equalsIgnoreCase(currentRarity)) {
+ rarity = rar;
+ rarityIndex = i;
+ break;
+ }
+ }
+
+ boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT);
+ boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
+ if (!pressedArrowLast && (left || right)) {
+ if (left) {
+ rarityIndex--;
+ } else {
+ rarityIndex++;
+ }
+ if (rarityIndex < 0) rarityIndex = 0;
+ if (rarityIndex >= requiredRarities.length) rarityIndex = requiredRarities.length - 1;
+ currentRarity = requiredRarities[rarityIndex];
+ rarity = currentRarity;
+ }
+ pressedArrowLast = left || right;
+
+ JsonElement statsE = reforgeInfo.get("reforgeStats");
+
+ String rarityFormatted = Utils.rarityArrMap.getOrDefault(rarity, rarity);
+
+ JsonElement reforgeAbilityE = reforgeInfo.get("reforgeAbility");
+ String reforgeAbility = null;
+ if (reforgeAbilityE != null) {
+ if (reforgeAbilityE.isJsonPrimitive() && reforgeAbilityE.getAsJsonPrimitive().isString()) {
+ reforgeAbility = Utils.getElementAsString(reforgeInfo.get("reforgeAbility"), "");
+
+ } else if (reforgeAbilityE.isJsonObject()) {
+ if (reforgeAbilityE.getAsJsonObject().has(rarity)) {
+ reforgeAbility = reforgeAbilityE.getAsJsonObject().get(rarity).getAsString();
+ }
+ }
+ }
+
+ if (reforgeAbility != null && !reforgeAbility.isEmpty()) {
+ String text = EnumChatFormatting.BLUE + (reforgeName.isEmpty() ? "Bonus: " : reforgeName + " Bonus: ") +
+ EnumChatFormatting.GRAY + reforgeAbility;
+ boolean first = true;
+ for (String s : Minecraft.getMinecraft().fontRendererObj.listFormattedStringToWidth(text, 150)) {
+ newTooltip.add((first ? "" : " ") + s);
+ first = false;
+ }
+ newTooltip.add("");
+ }
+
+ newTooltip.add(EnumChatFormatting.BLUE + "Stats for " + rarityFormatted + "§9: [§l§m< §9Switch§l➡§9]");
+
+ if (statsE != null && statsE.isJsonObject()) {
+ JsonObject stats = statsE.getAsJsonObject();
+
+ JsonElement statsRarE = stats.get(rarity);
+ if (statsRarE != null && statsRarE.isJsonObject()) {
+
+ JsonObject statsRar = statsRarE.getAsJsonObject();
+
+ TreeSet<Map.Entry<String, JsonElement>> sorted = new TreeSet<>(Map.Entry.comparingByKey());
+ sorted.addAll(statsRar.entrySet());
+
+ for (Map.Entry<String, JsonElement> entry : sorted) {
+ if (entry.getValue().isJsonPrimitive() && ((JsonPrimitive) entry.getValue()).isNumber()) {
+ float statNumF = entry.getValue().getAsFloat();
+ String statNumS;
+ if (statNumF % 1 == 0) {
+ statNumS = String.valueOf(Math.round(statNumF));
+ } else {
+ statNumS = Utils.floatToString(statNumF, 1);
+ }
+ String reforgeNamePretty = WordUtils.capitalizeFully(entry.getKey().replace("_", " "));
+ String text =
+ EnumChatFormatting.GRAY + reforgeNamePretty + ": " + EnumChatFormatting.GREEN + "+" + statNumS;
+ if (percentStats.contains(entry.getKey())) {
+ text += "%";
+ }
+ newTooltip.add(" " + text);
+ }
+ }
+ }
+ }
+
+ JsonElement reforgeCostsE = reforgeInfo.get("reforgeCosts");
+ int reforgeCost = -1;
+ if (reforgeCostsE != null) {
+ if (reforgeCostsE.isJsonPrimitive() && reforgeCostsE.getAsJsonPrimitive().isNumber()) {
+ reforgeCost = (int) Utils.getElementAsFloat(reforgeInfo.get("reforgeAbility"), -1);
+
+ } else if (reforgeCostsE.isJsonObject()) {
+ if (reforgeCostsE.getAsJsonObject().has(rarity)) {
+ reforgeCost = (int) Utils.getElementAsFloat(reforgeCostsE.getAsJsonObject().get(rarity), -1);
+ }
+ }
+ }
+
+ if (reforgeCost >= 0) {
+ String text = EnumChatFormatting.BLUE + "Apply Cost: " + EnumChatFormatting.GOLD +
+ NumberFormat.getNumberInstance().format(reforgeCost) + " coins";
+ newTooltip.add("");
+ newTooltip.add(text);
+ }
+
+ }
+
+ continue;
+ }
+
+ } else if (line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) {
+ line = line.replace(
+ "\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune",
+ Utils.chromaString("Rainbow Rune", index, false) + EnumChatFormatting.BLUE
+ );
+ } else if (hasEnchantments) {
+ if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) &&
+ NotEnoughUpdates.INSTANCE.config.tooltipTweaks.missingEnchantList) {
+ boolean lineHasEnch = false;
+ for (String s : enchantIds) {
+ String enchantName = WordUtils.capitalizeFully(s.replace("_", " "));
+ if (line.contains(enchantName)) {
+ lineHasEnch = true;
+ break;
+ }
+ }
+ if (lineHasEnch) {
+ gotToEnchants = true;
+ } else {
+ if (gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) {
+ if (enchantsConst != null && allItemEnchs != null) {
+ List<String> missing = new ArrayList<>();
+ for (JsonElement enchIdElement : allItemEnchs) {
+ String enchId = enchIdElement.getAsString();
+ if (!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) &&
+ !enchantIds.contains(enchId)) {
+ missing.add(enchId);
+ }
+ }
+ if (!missing.isEmpty()) {
+ newTooltip.add("");
+ StringBuilder currentLine = new StringBuilder(
+ EnumChatFormatting.RED + "Missing: " + EnumChatFormatting.GRAY);
+ for (int i = 0; i < missing.size(); i++) {
+ String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " "));
+ if (currentLine.length() != 0 &&
+ (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) {
+ newTooltip.add(currentLine.toString());
+ currentLine = new StringBuilder();
+ }
+ if (currentLine.length() != 0 && i != 0) {
+ currentLine.append(", ").append(enchName);
+ } else {
+ currentLine.append(EnumChatFormatting.GRAY).append(enchName);
+ }
+ }
+ if (currentLine.length() != 0) {
+ newTooltip.add(currentLine.toString());
+ }
+ }
+ }
+ passedEnchants = true;
+ }
+ }
+ }
+ }
+ if (hasEnchantments || hasAttributes) {
+ ArrayList<String> addedEnchants = new ArrayList<>();
+ for (String op : NotEnoughUpdates.INSTANCE.config.hidden.enchantColours) {
+ List<String> colourOps = GuiEnchantColour.splitter.splitToList(op);
+ String enchantName = GuiEnchantColour.getColourOpIndex(colourOps, 0);
+ String comparator = GuiEnchantColour.getColourOpIndex(colourOps, 1);
+ String comparison = GuiEnchantColour.getColourOpIndex(colourOps, 2);
+ String colourCode = GuiEnchantColour.getColourOpIndex(colourOps, 3);
+ String modifier = GuiEnchantColour.getColourOpIndex(colourOps, 4);
+
+ int modifierI = GuiEnchantColour.getIntModifier(modifier);
+
+ assert enchantName != null;
+ if (enchantName.length() == 0) continue;
+ assert comparator != null;
+ if (comparator.length() == 0) continue;
+ assert comparison != null;
+ if (comparison.length() == 0) continue;
+ assert colourCode != null;
+ if (colourCode.length() == 0) continue;
+
+ int comparatorI = ">=<".indexOf(comparator.charAt(0));
+
+ int levelToFind;
+ try {
+ levelToFind = Integer.parseInt(comparison);
+ } catch (Exception e) {
+ continue;
+ }
+
+ if (comparatorI < 0) continue;
+ String regexText = "0123456789abcdefz";
+ if (isSkyblockAddonsLoaded()) {
+ regexText = regexText + "Z";
+ }
+
+ if (regexText.indexOf(colourCode.charAt(0)) < 0) continue;
+
+ //item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1");
+ //9([a-zA-Z ]+?) ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$)
+ Pattern pattern;
+ try {
+ pattern = Pattern.compile(
+ "(\\u00A7b|\\u00A79|\\u00A7(b|9|l)\\u00A7d\\u00A7l)(?<enchantName>" + enchantName + ") " +
+ "(?<level>[0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))((\\u00A79)?,|( \\u00A78(?:,?[0-9]+)*)?$)");
+ } catch (Exception e) {
+ continue;
+ }
+ Matcher matcher = pattern.matcher(line);
+ int matchCount = 0;
+ while (matcher.find() && matchCount < 5) {
+ if (Utils.cleanColour(matcher.group("enchantName")).startsWith(" ")) continue;
+
+ matchCount++;
+ int level = -1;
+ String levelStr = matcher.group("level");
+ if (levelStr == null || levelStr.isEmpty()) continue;
+ level = Utils.parseIntOrRomanNumeral(levelStr);
+ boolean matches = false;
+ if (level > 0) {
+ switch (comparator) {
+ case ">":
+ matches = level > levelToFind;
+ break;
+ case "=":
+ matches = level == levelToFind;
+ break;
+ case "<":
+ matches = level < levelToFind;
+ break;
+ }
+ }
+ if (matches) {
+ String enchantText = matcher.group("enchantName");
+ StringBuilder extraModifiersBuilder = new StringBuilder();
+
+ if ((modifierI & GuiEnchantColour.BOLD_MODIFIER) != 0) {
+ extraModifiersBuilder.append(EnumChatFormatting.BOLD);
+ }
+ if ((modifierI & GuiEnchantColour.ITALIC_MODIFIER) != 0) {
+ extraModifiersBuilder.append(EnumChatFormatting.ITALIC);
+ }
+ if ((modifierI & GuiEnchantColour.UNDERLINE_MODIFIER) != 0) {
+ extraModifiersBuilder.append(EnumChatFormatting.UNDERLINE);
+ }
+ if ((modifierI & GuiEnchantColour.OBFUSCATED_MODIFIER) != 0) {
+ extraModifiersBuilder.append(EnumChatFormatting.OBFUSCATED);
+ }
+ if ((modifierI & GuiEnchantColour.STRIKETHROUGH_MODIFIER) != 0) {
+ extraModifiersBuilder.append(EnumChatFormatting.STRIKETHROUGH);
+ }
+
+ String extraMods = extraModifiersBuilder.toString();
+
+ if (!colourCode.equals("z")) {
+ if (!addedEnchants.contains(enchantText)) {
+ line = line.replace("\u00A79" + enchantText, "\u00A7" + colourCode + extraMods + enchantText);
+ line = line.replace("\u00A7b" + enchantText, "\u00A7" + colourCode + extraMods + enchantText);
+ line = line.replace(
+ "\u00A79\u00A7d\u00A7l" + enchantText,
+ "\u00A7" + colourCode + extraMods + enchantText
+ );
+ line = line.replace(
+ "\u00A7b\u00A7d\u00A7l" + enchantText,
+ "\u00A7" + colourCode + extraMods + enchantText
+ );
+ line = line.replace(
+ "\u00A7l\u00A7d\u00A7l" + enchantText,
+ "\u00A7" + colourCode + extraMods + enchantText
+ );
+ }
+ } else {
+ int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
+ "\\u00A79" + enchantText + ".*",
+ ""
+ ));
+ line = line.replace(
+ "\u00A79" + enchantText,
+ Utils.chromaString(enchantText, offset / 12f + index, false)
+ );
+
+ offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
+ "\\u00A79\\u00A7d\\u00A7l" + enchantText + ".*",
+ ""
+ ));
+ line = line.replace(
+ "\u00A79\u00A7d\u00A7l" + enchantText,
+ Utils.chromaString(enchantText, offset / 12f + index, true)
+ );
+ offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
+ "\\u00A7l\\u00A7d\\u00A7l" + enchantText + ".*",
+ ""
+ ));
+ line = line.replace(
+ "\u00A7l\u00A7d\u00A7l" + enchantText,
+ Utils.chromaString(enchantText, offset / 12f + index, true)
+ );
+ }
+ addedEnchants.add(enchantText);
+ }
+ }
+ }
+ }
+
+ newTooltip.add(line);
+
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoAucItem) {
+ if (line.contains(EnumChatFormatting.GRAY + "Buy it now: ") || line.contains(
+ EnumChatFormatting.GRAY + "Bidder: ") || line.contains(EnumChatFormatting.GRAY + "Starting bid: ")) {
+
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ newTooltip.add("");
+ newTooltip.add(EnumChatFormatting.GRAY + "[SHIFT for Price Info]");
+ } else {
+ ItemPriceInformation.addToTooltip(newTooltip, internalName, event.itemStack);
+ }
+ }
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 2 &&
+ Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ if (line.contains(EnumChatFormatting.GREEN + "Open Reward Chest")) {
+ dungeonProfit = true;
+ } else if (index == 7 && dungeonProfit) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ int chestCost = 0;
+ try {
+ String line6 = Utils.cleanColour(line);
+ StringBuilder cost = new StringBuilder();
+ for (int i = 0; i < line6.length(); i++) {
+ char c = line6.charAt(i);
+ if ("0123456789".indexOf(c) >= 0) {
+ cost.append(c);
+ }
+ }
+ if (cost.length() > 0) {
+ chestCost = Integer.parseInt(cost.toString());
+ }
+ } catch (Exception ignored) {
+ }
+
+ String missingItem = null;
+ int totalValue = 0;
+ HashMap<String, Double> itemValues = new HashMap<>();
+ for (int i = 0; i < 5; i++) {
+ ItemStack item = lower.getStackInSlot(11 + i);
+ String internal = neu.manager.getInternalNameForItem(item);
+ if (internal != null) {
+ internal = internal.replace("\u00CD", "I").replace("\u0130", "I");
+ float bazaarPrice = -1;
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
+ if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
+ bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
+ }
+ if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000;
+
+ double worth = -1;
+ if (bazaarPrice > 0) {
+ worth = bazaarPrice;
+ } else {
+ switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) {
+ case 1:
+ worth = neu.manager.auctionManager.getItemAvgBin(internal);
+ break;
+ case 2:
+ JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if (auctionInfo != null) {
+ if (auctionInfo.has("clean_price")) {
+ worth = (long) auctionInfo.get("clean_price").getAsDouble();
+ } else {
+ worth =
+ (long) (auctionInfo.get("price").getAsDouble() / auctionInfo.get("count").getAsDouble());
+ }
+ }
+ break;
+ default:
+ worth = neu.manager.auctionManager.getLowestBin(internal);
+ }
+ if (worth <= 0) {
+ worth = neu.manager.auctionManager.getLowestBin(internal);
+ if (worth <= 0) {
+ worth = neu.manager.auctionManager.getItemAvgBin(internal);
+ if (worth <= 0) {
+ JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if (auctionInfo != null) {
+ if (auctionInfo.has("clean_price")) {
+ worth = (int) auctionInfo.get("clean_price").getAsFloat();
+ } else {
+ worth = (int) (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (worth > 0 && totalValue >= 0) {
+ totalValue += worth;
+
+ String display = item.getDisplayName();
+
+ if (display.contains("Enchanted Book")) {
+ NBTTagCompound tag = item.getTagCompound();
+ if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ NBTTagCompound enchants = ea.getCompoundTag("enchantments");
+
+ int highestLevel = -1;
+ for (String enchname : enchants.getKeySet()) {
+ int level = enchants.getInteger(enchname);
+ if (level > highestLevel) {
+ display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(enchname
+ .replace("_", " ")
+ .replace("Ultimate", "")
+ .trim()) + " " + level;
+ }
+ }
+ }
+ }
+
+ itemValues.put(display, worth);
+ } else {
+ if (totalValue != -1) {
+ missingItem = internal;
+ }
+ totalValue = -1;
+ }
+ }
+ }
+
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+ String valueStringBIN1;
+ String valueStringBIN2;
+ if (totalValue >= 0) {
+ valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): ";
+ valueStringBIN2 = EnumChatFormatting.GOLD + format.format(totalValue) + " coins";
+ } else {
+ valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: ";
+ valueStringBIN2 = missingItem;
+ }
+
+ int profitLossBIN = totalValue - chestCost;
+ String profitPrefix = EnumChatFormatting.DARK_GREEN.toString();
+ String lossPrefix = EnumChatFormatting.RED.toString();
+ String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix;
+
+ String plStringBIN;
+ if (profitLossBIN >= 0) {
+ plStringBIN = prefix + "+" + format.format(profitLossBIN) + " coins";
+ } else {
+ plStringBIN = prefix + "-" + format.format(-profitLossBIN) + " coins";
+ }
+
+ String neu = EnumChatFormatting.YELLOW + "[NEU] ";
+
+ newTooltip.add(neu + valueStringBIN1 + " " + valueStringBIN2);
+ if (totalValue >= 0) {
+ newTooltip.add(neu + EnumChatFormatting.YELLOW + "Profit/Loss: " + plStringBIN);
+ }
+
+ for (Map.Entry<String, Double> entry : itemValues.entrySet()) {
+ newTooltip.add(neu + entry.getKey() + prefix + "+" + format.format(entry.getValue().intValue()));
+ }
+ }
+ }
+
+ index++;
+ }
+
+
+ pressedShiftLast = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+ pressedArrowLast = Keyboard.isKeyDown(Keyboard.KEY_LEFT) || Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
+
+ event.toolTip.clear();
+ event.toolTip.addAll(newTooltip);
+
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.showPriceInfoInvItem) {
+ ItemPriceInformation.addToTooltip(event.toolTip, internalName, event.itemStack);
+ }
+
+ if (event.itemStack.getTagCompound() != null && event.itemStack.getTagCompound().getBoolean("NEUHIDEPETTOOLTIP") &&
+ NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip) {
+ event.toolTip.clear();
+ }
+ }
+
+ private void petToolTipXPExtendPetMenu(ItemTooltipEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.petExtendExp) return;
+ //7 is just a random number i chose, prob no pets with less lines than 7
+ if (event.toolTip.size() < 7) return;
+ if (event.itemStack.getTagCompound().hasKey("NEUHIDEPETTOOLTIP")) return;
+ if (Utils.cleanColour(event.toolTip.get(1)).matches(petToolTipRegex)) {
+ GuiProfileViewer.PetLevel petLevel;
+
+ int xpLine = -1;
+ for (int i = event.toolTip.size() - 1; i >= 0; i--) {
+ Matcher matcher = xpLevelPattern.matcher(event.toolTip.get(i));
+ if (matcher.matches()) {
+ xpLine = i;
+ event.toolTip.set(xpLine, matcher.group(1));
+ break;
+ } else if (event.toolTip.get(i).matches("MAX LEVEL")) {
+ return;
+ }
+ }
+
+ PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack(
+ event.itemStack.getTagCompound()
+ );
+ if (pet == null) {
+ return;
+ }
+ petLevel = pet.petLevel;
+
+ if (petLevel == null || xpLine == -1) {
+ return;
+ }
+
+ event.toolTip.add(
+ xpLine + 1,
+ EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW + myFormatter.format(petLevel.levelXp) +
+ EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW +
+ myFormatter.format(petLevel.currentLevelRequirement)
+ );
+
+ }
+ }
+
+ /**
+ * This method does the following:
+ * Remove reforge stats for Legendary items from Hypixel if enabled
+ * Show NBT data when holding LCONTROL
+ */
+ @SubscribeEvent
+ public void onItemTooltip(ItemTooltipEvent event) {
+ if (!neu.isOnSkyblock()) return;
+ if (event.toolTip == null) return;
+
+ if (event.toolTip.size() > 2 && NotEnoughUpdates.INSTANCE.config.tooltipTweaks.hideDefaultReforgeStats) {
+ String secondLine = StringUtils.cleanColour(event.toolTip.get(1));
+ if (secondLine.equals("Reforge Stone")) {
+ Integer startIndex = null;
+ Integer cutoffIndex = null;
+ //loop from the back of the List to find the wanted index sooner
+ for (int i = event.toolTip.size() - 1; i >= 0; i--) {
+ //rarity or mining level requirement
+ String line = StringUtils.cleanColour(event.toolTip.get(i));
+ if (line.contains("REFORGE STONE") || line.contains("Requires Mining Skill Level")) {
+ cutoffIndex = i;
+ }
+
+ //The line where the Hypixel stats start
+ if (line.contains("(Legendary):")) {
+ startIndex = i;
+ break;
+ }
+ }
+ if (startIndex != null && cutoffIndex != null && startIndex < cutoffIndex) {
+ event.toolTip.subList(startIndex, cutoffIndex).clear();
+ }
+ }
+ }
+
+ if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) && NotEnoughUpdates.INSTANCE.config.hidden.dev &&
+ event.toolTip.size() > 0 && event.toolTip.get(event.toolTip.size() - 1).startsWith(
+ EnumChatFormatting.DARK_GRAY + "NBT: ")) {
+ event.toolTip.remove(event.toolTip.size() - 1);
+
+ StringBuilder sb = new StringBuilder();
+ String nbt = event.itemStack.getTagCompound().toString();
+ int indent = 0;
+ for (char c : nbt.toCharArray()) {
+ boolean newline = false;
+ if (c == '{' || c == '[') {
+ indent++;
+ newline = true;
+ } else if (c == '}' || c == ']') {
+ indent--;
+ sb.append("\n");
+ for (int i = 0; i < indent; i++) sb.append(" ");
+ } else if (c == ',') {
+ newline = true;
+ } else if (c == '\"') {
+ sb.append(EnumChatFormatting.RESET).append(EnumChatFormatting.GRAY);
+ }
+
+ sb.append(c);
+ if (newline) {
+ sb.append("\n");
+ for (int i = 0; i < indent; i++) sb.append(" ");
+ }
+ }
+ event.toolTip.add(sb.toString());
+ if (Keyboard.isKeyDown(Keyboard.KEY_H)) {
+ if (!copied) {
+ copied = true;
+ StringSelection selection = new StringSelection(sb.toString());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ }
+ } else {
+ copied = false;
+ }
+ } else if (NotEnoughUpdates.INSTANCE.packDevEnabled) {
+ event.toolTip.add("");
+ event.toolTip.add(EnumChatFormatting.AQUA + "NEU Pack Dev Info:");
+ event.toolTip.add(
+ EnumChatFormatting.GRAY + "Press " + EnumChatFormatting.GOLD + "[KEY]" + EnumChatFormatting.GRAY +
+ " to copy line");
+
+ String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
+
+ boolean k = Keyboard.isKeyDown(Keyboard.KEY_K);
+ boolean m = Keyboard.isKeyDown(Keyboard.KEY_M);
+ boolean n = Keyboard.isKeyDown(Keyboard.KEY_N);
+ boolean f = Keyboard.isKeyDown(Keyboard.KEY_F);
+
+ if (!copied && f && NotEnoughUpdates.INSTANCE.config.hidden.dev) {
+ MiscUtils.copyToClipboard(NotEnoughUpdates.INSTANCE.manager.getSkullValueForItem(event.itemStack));
+ }
+
+
+ event.toolTip.add(
+ EnumChatFormatting.AQUA + "Internal Name: " + EnumChatFormatting.GRAY + internal + EnumChatFormatting.GOLD +
+ " [K]");
+ if (!copied && k) {
+ MiscUtils.copyToClipboard(internal);
+ }
+
+ if (event.itemStack.getTagCompound() != null) {
+ NBTTagCompound tag = event.itemStack.getTagCompound();
+
+ if (tag.hasKey("SkullOwner", 10)) {
+ GameProfile gameprofile = NBTUtil.readGameProfileFromNBT(tag.getCompoundTag("SkullOwner"));
+
+ if (gameprofile != null) {
+ event.toolTip.add(EnumChatFormatting.AQUA + "Skull UUID: " + EnumChatFormatting.GRAY + gameprofile.getId() +
+ EnumChatFormatting.GOLD + " [M]");
+ if (!copied && m) {
+ MiscUtils.copyToClipboard(gameprofile.getId().toString());
+ }
+
+ Map<MinecraftProfileTexture.Type, MinecraftProfileTexture> map =
+ Minecraft.getMinecraft().getSkinManager().loadSkinFromCache(gameprofile);
+
+ if (map.containsKey(MinecraftProfileTexture.Type.SKIN)) {
+ MinecraftProfileTexture profTex = map.get(MinecraftProfileTexture.Type.SKIN);
+ event.toolTip.add(
+ EnumChatFormatting.AQUA + "Skull Texture Link: " + EnumChatFormatting.GRAY + profTex.getUrl() +
+ EnumChatFormatting.GOLD + " [N]");
+
+ if (!copied && n) {
+ MiscUtils.copyToClipboard(profTex.getUrl());
+ }
+ }
+ }
+ }
+ }
+
+ copied = k || m || n || f;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java
new file mode 100644
index 00000000..fdae53ea
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.util.Calculator;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.ItemResolutionQuery;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.input.Keyboard;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ItemTooltipRngListener {
+ private final NotEnoughUpdates neu;
+ private boolean showSlayerRngFractions = false;
+ private boolean pressedShiftLast = false;
+ private int currentSelected = 0;
+ private boolean pressedArrowLast = false;
+ private boolean repoReloadNeeded = true;
+
+ private final Pattern ODDS_PATTERN = Pattern.compile("§5§o§7Odds: (.+) §7\\(§7(.*)%\\)");
+ private final Pattern ODDS_SELECTED_PATTERN = Pattern.compile("§5§o§7Odds: (.+) §7\\(§8§m(.*)%§r §7(.+)%\\)");
+
+ private final Pattern RUNS_PATTERN = Pattern.compile("§5§o§7(Dungeon Score|Slayer XP): §d(.*)§5/§d(.+)");
+ private final Pattern RUNS_SELECTED_PATTERN = Pattern.compile("§5§o§d-(.+)- §d(.*)§5/§d(.+)");
+
+ private final Pattern SLAYER_INVENTORY_TITLE_PATTERN = Pattern.compile("(.+) RNG Meter");
+
+ private final Map<String, Integer> dungeonData = new LinkedHashMap<>();
+ private final Map<String, LinkedHashMap<String, Integer>> slayerData = new LinkedHashMap<>();
+
+ public ItemTooltipRngListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ @SubscribeEvent
+ public void onItemTooltip(ItemTooltipEvent event) {
+ if (!neu.isOnSkyblock()) return;
+ if (event.toolTip == null) return;
+ if (!Utils.getOpenChestName().endsWith(" RNG Meter") && !slayerData.containsKey(Utils.getOpenChestName())) return;
+
+ List<String> newToolTip = new ArrayList<>();
+
+ boolean nextLineProgress = false;
+ for (String line : event.toolTip) {
+
+ if (line.contains("Odds:")) {
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterFractionDisplay) {
+ fractionDisplay(newToolTip, line);
+ continue;
+ }
+ }
+
+ if (nextLineProgress || line.contains("Dungeon Score:") || line.contains("Slayer XP:")) {
+ Matcher matcher = RUNS_PATTERN.matcher(line);
+ Matcher matcherSelected = RUNS_SELECTED_PATTERN.matcher(line);
+ Matcher m = null;
+ if (matcher.matches()) {
+ m = matcher;
+ } else if (matcherSelected.matches()) {
+ m = matcherSelected;
+ }
+
+ if (m != null) {
+ int having;
+ try {
+ having = Calculator.calculate(m.group(2).replace(",", "")).intValue();
+ } catch (Calculator.CalculatorException e) {
+ having = -1;
+ }
+
+ int needed;
+ try {
+ needed = Calculator.calculate(m.group(3).replace(",", "")).intValue();
+ } catch (Calculator.CalculatorException e) {
+ needed = -1;
+ }
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterRunsNeeded) {
+ runsRequired(newToolTip, having, needed, nextLineProgress, event.itemStack);
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterProfitPerUnit) {
+ if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterRunsNeeded) {
+ String name = Utils.getOpenChestName().contains("Catacombs") ? "Score" : "XP";
+ String formatCoinsPer = getFormatCoinsPer(event.itemStack, needed, 1, name);
+ if (formatCoinsPer != null) {
+ newToolTip.add(line);
+ newToolTip.add(formatCoinsPer);
+ continue;
+ }
+ }
+ }
+ }
+ nextLineProgress = false;
+ }
+
+ if (line.contains("Progress:")) {
+ nextLineProgress = true;
+ }
+ newToolTip.add(line);
+ }
+
+ event.toolTip.clear();
+ event.toolTip.addAll(newToolTip);
+ }
+
+ private String getFormatCoinsPer(ItemStack stack, int needed, int multiplier, String label) {
+ String internalName = neu.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName();
+ double profit = neu.manager.auctionManager.getBazaarOrBin(internalName);
+ if (profit <= 0) return null;
+
+ //ask hypixel nicely to release a 'chest price api' with 4 dimensions for us. the 4 dimensions needed are: item name, floor, normal/mm, s/s+
+// double chestPrice = grabChestPrice(stack, internalName);
+// profit -= chestPrice;
+
+ double coinsPer = (profit / needed) * multiplier;
+ String format = StringUtils.shortNumberFormat(coinsPer);
+ return "§7Coins per " + label + ": §6" + format + " coins";
+ }
+
+ private void fractionDisplay(List<String> newToolTip, String line) {
+ boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT);
+ if (!pressedShiftLast && shift) {
+ showSlayerRngFractions = !showSlayerRngFractions;
+ }
+ pressedShiftLast = shift;
+
+ String result;
+ Matcher matcher = ODDS_PATTERN.matcher(line);
+ Matcher matcherSelected = ODDS_SELECTED_PATTERN.matcher(line);
+ if (matcher.matches()) {
+ String odds = matcher.group(1);
+ int baseChance = calculateChance(matcher.group(2));
+ String baseFormat = GuiProfileViewer.numberFormat.format(baseChance);
+
+ String fractionFormat = "§7(1/" + baseFormat + ")";
+ result = odds + " " + fractionFormat;
+ } else if (matcherSelected.matches()) {
+ String odds = matcherSelected.group(1);
+ int baseChance = calculateChance(matcherSelected.group(2));
+ String baseFormat = GuiProfileViewer.numberFormat.format(baseChance);
+
+ int increasedChance = calculateChance(matcherSelected.group(3));
+ String increased = GuiProfileViewer.numberFormat.format(increasedChance);
+ String fractionFormat = "§7(§8§m1/" + baseFormat + "§r §71/" + increased + ")";
+
+ result = odds + " " + fractionFormat;
+ } else {
+ return;
+ }
+
+ if (showSlayerRngFractions) {
+ newToolTip.add("§7Odds: " + result);
+ newToolTip.add("§8[Press SHIFT to show odds as percentages]");
+ } else {
+ newToolTip.add(line);
+ newToolTip.add("§8[Press SHIFT to show odds as fractions]");
+ }
+ }
+
+ /**
+ * This adds support for the /neureloadrepo command
+ */
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onRepoReload(RepositoryReloadEvent event) {
+ repoReloadNeeded = true;
+ }
+
+ public void checkUpdateData() {
+ if (repoReloadNeeded) {
+ updateRepoData();
+ }
+ }
+
+ private void updateRepoData() {
+ slayerData.clear();
+ dungeonData.clear();
+
+ JsonObject leveling = Constants.LEVELING;
+ if (!leveling.has("slayer_boss_xp") ||
+ !leveling.has("slayer_highest_tier") ||
+ !leveling.has("slayer_tier_colors") ||
+ !leveling.has("rng_meter_dungeon_score")) {
+ Utils.showOutdatedRepoNotification();
+ return;
+ }
+
+ List<Integer> slayerExp = new ArrayList<>();
+ for (JsonElement element : leveling.get("slayer_boss_xp").getAsJsonArray()) {
+ slayerExp.add(element.getAsInt());
+ }
+
+ List<String> slayerColors = new ArrayList<>();
+ for (JsonElement element : leveling.get("slayer_tier_colors").getAsJsonArray()) {
+ slayerColors.add(element.getAsString());
+ }
+
+ for (Map.Entry<String, JsonElement> entry : leveling.get("slayer_highest_tier").getAsJsonObject().entrySet()) {
+ String slayerName = entry.getKey();
+ int maxTier = entry.getValue().getAsInt();
+ LinkedHashMap<String, Integer> singleSlayerData = new LinkedHashMap<>();
+ for (int i = 0; i < maxTier; i++) {
+ String name = slayerColors.get(i) + "Tier " + (i + 1);
+ singleSlayerData.put(name, slayerExp.get(i));
+ }
+ slayerData.put(slayerName, singleSlayerData);
+ }
+
+ for (Map.Entry<String, JsonElement> entry : leveling.get("rng_meter_dungeon_score").getAsJsonObject().entrySet()) {
+ String dungeonScore = entry.getKey();
+ int score = entry.getValue().getAsInt();
+ dungeonData.put(dungeonScore, score);
+ }
+
+ repoReloadNeeded = false;
+ }
+
+ private void runsRequired(
+ List<String> toolTip,
+ int having,
+ int needed,
+ boolean nextLineProgress,
+ ItemStack stack
+ ) {
+ checkUpdateData();
+ if (repoReloadNeeded) return;
+
+ String openChestName = Utils.getOpenChestName();
+ Map<String, Integer> runsData;
+ String labelPlural;
+ String labelSingular;
+ String repoCategory;
+ if (openChestName.contains("Catacombs")) {
+ runsData = dungeonData;
+ labelPlural = "Runs";
+ labelSingular = "Run";
+ repoCategory = "catacombs";
+ } else { // Slayer
+ Matcher matcher = SLAYER_INVENTORY_TITLE_PATTERN.matcher(openChestName);
+ if (!matcher.matches()) {
+ //Happens for the first 4-5 ticks after inventory opens. Thanks hypixel
+ return;
+ }
+
+ String slayerName = matcher.group(1);
+ runsData = slayerData.get(slayerName);
+ labelPlural = "Bosses";
+ labelSingular = "Boss";
+ repoCategory = "slayer";
+ }
+
+ int repoScore = getRepoScore(stack, repoCategory);
+ if (repoScore != -1) {
+ needed = repoScore;
+ }
+
+ handleArrowKeys(runsData);
+
+ if (currentSelected >= runsData.keySet().size()) {
+ currentSelected = 0;
+ }
+
+ String name = (String) runsData.keySet().toArray()[currentSelected];
+ int gainPerRun = runsData.get(name);
+
+ int runsNeeded = (int) Math.floor((double) needed / (double) gainPerRun);
+ int runsHaving = having / gainPerRun;
+ String runsNeededFormat = GuiProfileViewer.numberFormat.format(runsNeeded);
+ String runsHavingFormat = GuiProfileViewer.numberFormat.format(runsHaving);
+
+ String progressString = null;
+ if (nextLineProgress) {
+ progressString = toolTip.remove(toolTip.size() - 1);
+ }
+
+ toolTip.add("§9Stats for " + name + "§9: [§l§m< §9Switch§l➡§9]");
+ toolTip.add(
+ " §7" + labelPlural + " completed: §e" + runsHavingFormat + " §7(of §e" + runsNeededFormat + " §7needed)");
+
+ if (NotEnoughUpdates.INSTANCE.config.tooltipTweaks.rngMeterProfitPerUnit) {
+ String formatCoinsPer = getFormatCoinsPer(stack, needed, gainPerRun, labelSingular);
+ if (formatCoinsPer != null) {
+ toolTip.add(" " + formatCoinsPer);
+ }
+ }
+
+ toolTip.add(" ");
+ if (progressString != null) {
+ toolTip.add(progressString);
+ }
+ }
+
+ private int getRepoScore(ItemStack stack, String repoCategory) {
+ ItemResolutionQuery query =
+ NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withItemStack(stack).withCurrentGuiContext();
+ String internalName = query.resolveInternalName();
+
+ JsonObject jsonObject = Constants.RNGSCORE;
+ if (jsonObject == null) {
+ Utils.showOutdatedRepoNotification();
+ return -1;
+ }
+
+ String repoType = grabRepoType(stack);
+ if (!jsonObject.has(repoCategory)) return -1;
+
+ JsonObject category = jsonObject.get(repoCategory).getAsJsonObject();
+ if (!category.has(repoType)) return -1;
+
+ JsonObject typeObject = category.get(repoType).getAsJsonObject();
+ if (!typeObject.has(internalName)) return -1;
+
+ return typeObject.get(internalName).getAsInt();
+ }
+
+ // Determines the floor or the slayer type from where the item can be obtained. E.g. F7, M3, Revenant Horror or Sven Packmaster
+ private String grabRepoType(ItemStack stack) {
+ String openChestName = Utils.getOpenChestName();
+ if (openChestName.contains("Catacombs")) {
+ if (openChestName.equals("Catacombs RNG Meter")) {
+ List<String> list = ItemUtils.getLore(stack);
+ String line = list.get(4);
+ return line.substring(26, 28);
+ } else {
+ // supporting more pages (f7/m7)
+ if (openChestName.contains("(")) {
+ return openChestName.substring(17, 19);
+ }
+ return openChestName.substring(11, 13);
+ }
+ } else {
+ return openChestName.substring(0, openChestName.length() - 9);
+ }
+ }
+
+ private void handleArrowKeys(Map<String, Integer> runsData) {
+ boolean left = Keyboard.isKeyDown(Keyboard.KEY_LEFT);
+ boolean right = Keyboard.isKeyDown(Keyboard.KEY_RIGHT);
+ if (!pressedArrowLast && (left || right)) {
+ if (Utils.getOpenChestName().contains("Catacombs") ? right : left) {
+ currentSelected--;
+ } else {
+ currentSelected++;
+ }
+ if (currentSelected < 0) currentSelected = 0;
+ if (currentSelected >= runsData.size()) currentSelected = runsData.size() - 1;
+ }
+ pressedArrowLast = left || right;
+ }
+
+ private int calculateChance(String string) {
+ return (int) (100.0 / Double.parseDouble(string));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java
new file mode 100644
index 00000000..e202b828
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
+import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
+import io.github.moulberry.notenoughupdates.miscfeatures.CookieWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay;
+import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
+import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing;
+import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant;
+import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex;
+import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay;
+import io.github.moulberry.notenoughupdates.overlays.OverlayManager;
+import io.github.moulberry.notenoughupdates.overlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.overlays.TextTabOverlay;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import io.github.moulberry.notenoughupdates.util.ProfileApiSyncer;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import io.github.moulberry.notenoughupdates.util.XPInformation;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.input.Keyboard;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class NEUEventListener {
+
+ private final NotEnoughUpdates neu;
+ private final ExecutorService itemPreloader = Executors.newFixedThreadPool(10);
+ private final List<ItemStack> toPreload = new ArrayList<>();
+ private boolean joinedSB = false;
+
+ private boolean preloadedItems = false;
+ private long lastLongUpdate = 0;
+ private long lastSkyblockScoreboard = 0;
+
+ public NEUEventListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Unload event) {
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ CrystalMetalDetectorSolver.initWorld();
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (event.phase != TickEvent.Phase.START) return;
+ if (Minecraft.getMinecraft().theWorld == null) return;
+ if (Minecraft.getMinecraft().thePlayer == null) return;
+
+ if ((Keyboard.isKeyDown(Keyboard.KEY_NUMPAD1) && Keyboard.isKeyDown(Keyboard.KEY_NUMPAD4) && Keyboard.isKeyDown(
+ Keyboard.KEY_NUMPAD9))) {
+ ChatComponentText component = new ChatComponentText("\u00a7cYou are permanently banned from this server!");
+ component.appendText("\n");
+ component.appendText("\n\u00a77Reason: \u00a7rSuspicious account activity/Other");
+ component.appendText("\n\u00a77Find out more: \u00a7b\u00a7nhttps://www.hypixel.net/appeal");
+ component.appendText("\n");
+ component.appendText("\n\u00a77Ban ID: \u00a7r#49871982");
+ component.appendText("\n\u00a77Sharing your Ban ID may affect the processing of your appeal!");
+ Minecraft.getMinecraft().getNetHandler().getNetworkManager().closeChannel(component);
+ return;
+ }
+
+ if (neu.hasSkyblockScoreboard()) {
+ if (!preloadedItems) {
+ preloadedItems = true;
+ List<JsonObject> list = new ArrayList<>(neu.manager.getItemInformation().values());
+ for (JsonObject json : list) {
+ itemPreloader.submit(() -> {
+ ItemStack stack = neu.manager.jsonToStack(json, true, true);
+ if (stack.getItem() == Items.skull) toPreload.add(stack);
+ });
+ }
+ } else if (!toPreload.isEmpty()) {
+ Utils.drawItemStack(toPreload.get(0), -100, -100);
+ toPreload.remove(0);
+ } else {
+ itemPreloader.shutdown();
+ }
+
+ for (TextOverlay overlay : OverlayManager.textOverlays) {
+ overlay.shouldUpdateFrequent = true;
+ }
+ }
+
+ boolean longUpdate = false;
+ long currentTime = System.currentTimeMillis();
+ if (currentTime - lastLongUpdate > 1000) {
+ longUpdate = true;
+ lastLongUpdate = currentTime;
+ }
+ if (!NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) {
+ DungeonBlocks.tick();
+ }
+ DungeonWin.tick();
+
+ String containerName = null;
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) {
+ GuiCustomEnchant.getInstance().tick();
+ }
+ if (GuiCustomHex.getInstance().shouldOverride(containerName)) {
+ GuiCustomHex.getInstance().tick(containerName);
+ }
+ }
+
+ //MiningOverlay and TimersOverlay need real tick speed
+ if (neu.hasSkyblockScoreboard()) {
+ for (TextOverlay overlay : OverlayManager.textOverlays) {
+ if (overlay instanceof TextTabOverlay) {
+ TextTabOverlay skillOverlay = (TextTabOverlay) overlay;
+ skillOverlay.realTick();
+ }
+ }
+ }
+
+
+ if (longUpdate) {
+ CrystalOverlay.tick();
+ FairySouls.getInstance().tick();
+ XPInformation.getInstance().tick();
+ ProfileApiSyncer.getInstance().tick();
+ ItemCustomizeManager.tick();
+ BackgroundBlur.markDirty();
+ NPCRetexturing.getInstance().tick();
+ StorageOverlay.getInstance().markDirty();
+ CookieWarning.checkCookie();
+
+ if (neu.hasSkyblockScoreboard()) {
+ for (TextOverlay overlay : OverlayManager.textOverlays) {
+ overlay.tick();
+ }
+ }
+
+ NotEnoughUpdates.INSTANCE.overlay.redrawItems();
+ CapeManager.onTickSlow();
+
+ NotEnoughUpdates.profileViewer.putNameUuid(
+ Minecraft.getMinecraft().thePlayer.getName(),
+ Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")
+ );
+
+ if (NotEnoughUpdates.INSTANCE.config.dungeons.slowDungeonBlocks) {
+ DungeonBlocks.tick();
+ }
+
+ if (System.currentTimeMillis() - SBInfo.getInstance().joinedWorld > 500 &&
+ System.currentTimeMillis() - SBInfo.getInstance().unloadedWorld > 500) {
+ neu.updateSkyblockScoreboard();
+ }
+ CapeManager.getInstance().tick();
+
+ if (containerName != null) {
+ if (!containerName.trim().startsWith("Accessory Bag")) {
+ AccessoryBagOverlay.resetCache();
+ }
+ } else {
+ AccessoryBagOverlay.resetCache();
+ }
+
+ if (neu.hasSkyblockScoreboard()) {
+ SBInfo.getInstance().tick();
+ lastSkyblockScoreboard = currentTime;
+ if (!joinedSB) {
+ joinedSB = true;
+
+ if (NotEnoughUpdates.INSTANCE.config.notifications.updateChannel != 0) {
+ NotEnoughUpdates.INSTANCE.autoUpdater.displayUpdateMessageIfOutOfDate();
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.notifications.doRamNotif) {
+ long maxMemoryMB = Runtime.getRuntime().maxMemory() / 1024L / 1024L;
+ if (maxMemoryMB > 4100) {
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ EnumChatFormatting.GRAY + "Too much memory allocated!",
+ String.format(
+ EnumChatFormatting.DARK_GRAY + "NEU has detected %03dMB of memory allocated to Minecraft!",
+ maxMemoryMB
+ ),
+ EnumChatFormatting.GRAY + "It is recommended to allocated between 2-4GB of memory",
+ EnumChatFormatting.GRAY + "More than 4GB MAY cause FPS issues, EVEN if you have 16GB+ available",
+ EnumChatFormatting.GRAY + "For more information, visit #ram-info in discord.gg/moulberry",
+ "",
+ EnumChatFormatting.GRAY + "Press X on your keyboard to close this notification"
+ ), false);
+ }
+ }
+
+ if (!NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore) {
+ NotEnoughUpdates.INSTANCE.config.hidden.loadedModBefore = true;
+ if (Constants.MISC == null || !Constants.MISC.has("featureslist")) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "" + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "WARNING: " + EnumChatFormatting.RESET +
+ EnumChatFormatting.RED + "Could not load Feature List URL from repo."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "" + EnumChatFormatting.RED + "Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" +
+ EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD +
+ "restart your game" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " +
+ EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + "If that doesn't fix it" +
+ EnumChatFormatting.RESET + EnumChatFormatting.RED +
+ ", please join discord.gg/moulberry and post in #neu-support"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "" + EnumChatFormatting.GOLD + "To view the feature list after restarting type /neufeatures"));
+ } else {
+ String url = Constants.MISC.get("featureslist").getAsString();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.BLUE + "It seems this is your first time using NotEnoughUpdates."));
+ ChatComponentText clickTextFeatures = new ChatComponentText(EnumChatFormatting.YELLOW +
+ "Click this message if you would like to view a list of NotEnoughUpdate's Features.");
+ clickTextFeatures.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, url));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextFeatures);
+ }
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ ChatComponentText clickTextHelp = new ChatComponentText(EnumChatFormatting.YELLOW +
+ "Click this message if you would like to view a list of NotEnoughUpdate's commands.");
+ clickTextHelp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuhelp"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(clickTextHelp);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ }
+ }
+ }
+ if (currentTime - lastSkyblockScoreboard < 5 * 60 * 1000) { //5 minutes
+ neu.manager.auctionManager.tick();
+ } else {
+ neu.manager.auctionManager.markNeedsUpdate();
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java
new file mode 100644
index 00000000..7858918b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/OldAnimationChecker.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.common.collect.Lists;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class OldAnimationChecker {
+
+ private void unregister() {
+ MinecraftForge.EVENT_BUS.unregister(this);
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ if (!NotEnoughUpdates.INSTANCE.config.notifications.doOamNotif) {
+ unregister();
+ return;
+ }
+ boolean oldAnimations = false;
+ if (Loader.isModLoaded("animations")) {
+ oldAnimations = true;
+ } else {
+ try {
+ Class.forName("com.spiderfrog.oldanimations.OldAnimationsMod");
+ //previous statement would throw if not present
+ oldAnimations = true;
+ } catch (ClassNotFoundException ignored) {
+ }
+ }
+
+ if (oldAnimations) {
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ "\u00a74Old animations warning",
+ "\u00a77You use a old animations mod from Orange or spiderfrog",
+ "\u00a77These mods break features in NEU and other mods",
+ "\u00a77Please remove them and optionally replace them with the OldAnimations mod from Sk1er",
+ "\u00a77It can be found at the following website: \u00a79sk1er.club/beta",
+ "\u00a77For more information join the discord at \u00a79discord.gg/moulberry\u00a77 and message in \u00a79#neu-support",
+ "\u00a77",
+ "\u00a77Press X on your keyboard to close this notification or turn it off in the config"
+ ), true, true);
+ unregister();
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java
new file mode 100644
index 00000000..6460e1ed
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java
@@ -0,0 +1,1718 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUApi;
+import io.github.moulberry.notenoughupdates.NEUOverlay;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
+import io.github.moulberry.notenoughupdates.commands.profile.ViewProfileCommand;
+import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
+import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor;
+import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionProfit;
+import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
+import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager;
+import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant;
+import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor;
+import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.TradeWindow;
+import io.github.moulberry.notenoughupdates.miscgui.TrophyRewardOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.overlays.AuctionSearchOverlay;
+import io.github.moulberry.notenoughupdates.overlays.BazaarSearchOverlay;
+import io.github.moulberry.notenoughupdates.overlays.EquipmentOverlay;
+import io.github.moulberry.notenoughupdates.overlays.OverlayManager;
+import io.github.moulberry.notenoughupdates.overlays.RancherBootOverlay;
+import io.github.moulberry.notenoughupdates.overlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import io.github.moulberry.notenoughupdates.util.RequestFocusListener;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.client.gui.inventory.GuiInventory;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.StringUtils;
+import net.minecraftforge.client.ClientCommandHandler;
+import net.minecraftforge.client.event.GuiOpenEvent;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderLivingEvent;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import javax.swing.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_chest_worth;
+
+public class RenderListener {
+ private static final ResourceLocation EDITOR = new ResourceLocation("notenoughupdates:invbuttons/editor.png");
+ public static boolean disableCraftingText = false;
+ public static boolean drawingGuiScreen = false;
+ public static long lastGuiClosed = 0;
+ public static boolean inventoryLoaded = false;
+ private final NotEnoughUpdates neu;
+ ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+ JsonObject essenceJson = new JsonObject();
+ private boolean hoverInv = false;
+ private boolean focusInv = false;
+ private boolean doInventoryButtons = false;
+ private NEUConfig.InventoryButton buttonHovered = null;
+ private long buttonHoveredMillis = 0;
+ private int inventoryLoadedTicks = 0;
+ private String loadedInvName = "";
+ //NPC parsing
+ private String correctingItem;
+ private boolean typing;
+ private HashMap<String, String> cachedDefinitions;
+ private boolean inDungeonPage = false;
+ private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US));
+
+ private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)");
+
+ public RenderListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ @SubscribeEvent(priority = EventPriority.HIGHEST)
+ public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre<EntityPlayer> event) {
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) {
+ if (((GuiProfileViewer) Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) {
+ event.setCanceled(true);
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event) {
+ if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) &&
+ Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) {
+ event.setCanceled(true);
+ }
+ if (event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.PLAYER_LIST)) {
+ GlStateManager.enableDepth();
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderGameOverlayPost(RenderGameOverlayEvent.Post event) {
+ if (neu.hasSkyblockScoreboard() && event.type.equals(RenderGameOverlayEvent.ElementType.ALL)) {
+ DungeonWin.render(event.partialTicks);
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, -200);
+ for (TextOverlay overlay : OverlayManager.textOverlays) {
+ if (OverlayManager.dontRenderOverlay != null &&
+ OverlayManager.dontRenderOverlay.isAssignableFrom(overlay.getClass())) {
+ continue;
+ }
+ GlStateManager.translate(0, 0, -1);
+ GlStateManager.enableDepth();
+ overlay.render();
+ }
+ GlStateManager.popMatrix();
+ OverlayManager.dontRenderOverlay = null;
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_X)) {
+ NotificationHandler.notificationDisplayMillis = 0;
+ }
+
+ if (event.type == RenderGameOverlayEvent.ElementType.ALL) {
+ NotificationHandler.renderNotification();
+ }
+
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (event.phase != TickEvent.Phase.START) return;
+ if (Minecraft.getMinecraft().theWorld == null) return;
+ if (Minecraft.getMinecraft().thePlayer == null) return;
+
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ if (!loadedInvName.equals(cc.getLowerChestInventory().getDisplayName().getUnformattedText())) {
+ loadedInvName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ inventoryLoaded = false;
+ inventoryLoadedTicks = 3;
+ }
+
+ if (!inventoryLoaded) {
+ if (cc.getLowerChestInventory().getStackInSlot(cc.getLowerChestInventory().getSizeInventory() - 1) != null) {
+ inventoryLoaded = true;
+ } else {
+ for (ItemStack stack : chest.inventorySlots.getInventory()) {
+ if (stack != null) {
+ if (--inventoryLoadedTicks <= 0) {
+ inventoryLoaded = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ inventoryLoaded = false;
+ inventoryLoadedTicks = 3;
+ }
+
+ }
+
+ @SubscribeEvent
+ public void onGuiOpen(GuiOpenEvent event) {
+ NEUApi.disableInventoryButtons = false;
+
+ if ((Minecraft.getMinecraft().currentScreen instanceof GuiScreenElementWrapper ||
+ Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe) && event.gui == null &&
+ !(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) &&
+ System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.lastOpenedGui < 500) {
+ NotEnoughUpdates.INSTANCE.lastOpenedGui = 0;
+ event.setCanceled(true);
+ return;
+ }
+
+ if (!(event.gui instanceof GuiContainer) && Minecraft.getMinecraft().currentScreen != null) {
+ CalendarOverlay.setEnabled(false);
+ }
+
+ if (Minecraft.getMinecraft().currentScreen != null) {
+ lastGuiClosed = System.currentTimeMillis();
+ }
+
+ neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis();
+ BetterContainers.reset();
+ inventoryLoaded = false;
+ inventoryLoadedTicks = 3;
+
+ if (event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() &&
+ !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
+ event.gui = new CustomAHGui();
+ }
+
+ if (!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) {
+ neu.manager.auctionManager.customAH.setRenderOverAuctionView(false);
+ } else if (event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() ||
+ Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
+ GuiChest chest = (GuiChest) event.gui;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ neu.manager.auctionManager.customAH.setRenderOverAuctionView(
+ containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View") ||
+ containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase"));
+ }
+
+ //OPEN
+ if (Minecraft.getMinecraft().currentScreen == null && event.gui instanceof GuiContainer) {
+ neu.overlay.reset();
+ }
+ if (event.gui != null && NotEnoughUpdates.INSTANCE.config.hidden.dev) {
+ if (event.gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+ ses.schedule(() -> {
+ if (Minecraft.getMinecraft().currentScreen != event.gui) {
+ return;
+ }
+ if (lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ try {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = neu.manager.getInternalNameForItem(res);
+
+ if (lower.getStackInSlot(48) != null) {
+ String backName = null;
+ NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound();
+ if (tag.hasKey("display", 10)) {
+ NBTTagCompound nbttagcompound = tag.getCompoundTag("display");
+ if (nbttagcompound.getTagId("Lore") == 9) {
+ NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8);
+ backName = nbttaglist1.getStringTagAt(0);
+ }
+ }
+
+ if (backName != null) {
+ String[] split = backName.split(" ");
+ if (split[split.length - 1].contains("Rewards")) {
+ String col = backName.substring(
+ split[0].length() + 1,
+ backName.length() - split[split.length - 1].length() - 1
+ );
+
+ JsonObject json = neu.manager.getItemInformation().get(resInternalname);
+ json.addProperty("crafttext", "Requires: " + col);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "Added: " + resInternalname));
+ neu.manager.writeJsonDefaultDir(json, resInternalname + ".json");
+ neu.manager.loadItem(resInternalname);
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }, 200, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+
+ /**
+ * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
+ * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
+ * <p>
+ * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI)
+ * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv)
+ * <p>
+ * All of this only matters if players are using gui scale auto which may result in the inventory being drawn
+ * over the various panes.
+ */
+ @SubscribeEvent
+ public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
+ if (NotificationHandler.showNotificationOverInv) {
+
+ NotificationHandler.renderNotification();
+
+ }
+ inDungeonPage = false;
+ if ((NotificationHandler.shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) &&
+ neu.isOnSkyblock()) {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledresolution.getScaledWidth();
+
+ boolean hoverPane = event.getMouseX() < width * neu.overlay.getInfoPaneOffsetFactor() ||
+ event.getMouseX() > width * neu.overlay.getItemPaneOffsetFactor();
+
+ if (event.gui instanceof GuiContainer) {
+ try {
+ int xSize = ((AccessorGuiContainer) event.gui).getXSize();
+ int ySize = ((AccessorGuiContainer) event.gui).getYSize();
+ int guiLeft = ((AccessorGuiContainer) event.gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) event.gui).getGuiTop();
+
+ hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize && event.getMouseY() > guiTop &&
+ event.getMouseY() < guiTop + ySize;
+
+ if (hoverPane) {
+ if (!hoverInv) focusInv = false;
+ } else {
+ focusInv = true;
+ }
+ } catch (NullPointerException npe) {
+ focusInv = !hoverPane;
+ }
+ }
+ if (event.gui instanceof GuiItemRecipe) {
+ GuiItemRecipe guiItemRecipe = ((GuiItemRecipe) event.gui);
+ hoverInv = event.getMouseX() > guiItemRecipe.guiLeft &&
+ event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize && event.getMouseY() > guiItemRecipe.guiTop &&
+ event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize;
+
+ if (hoverPane) {
+ if (!hoverInv) focusInv = false;
+ } else {
+ focusInv = true;
+ }
+ }
+ if (focusInv) {
+ try {
+ neu.overlay.render(hoverInv);
+ } catch (ConcurrentModificationException e) {
+ e.printStackTrace();
+ }
+ GL11.glTranslatef(0, 0, 10);
+ }
+ if (hoverInv) {
+ renderDungKuudraChestOverlay(event.gui);
+ if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) {
+ AccessoryBagOverlay.renderOverlay();
+ }
+ }
+ }
+
+ drawingGuiScreen = true;
+ }
+
+ @SubscribeEvent
+ public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
+ doInventoryButtons = false;
+
+ if (AuctionSearchOverlay.shouldReplace()) {
+ AuctionSearchOverlay.render();
+ event.setCanceled(true);
+ return;
+ }
+ if (BazaarSearchOverlay.shouldReplace()) {
+ BazaarSearchOverlay.render();
+ event.setCanceled(true);
+ return;
+ }
+ if (RancherBootOverlay.shouldReplace()) {
+ RancherBootOverlay.render();
+ event.setCanceled(true);
+ return;
+ }
+
+ String containerName = null;
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if (guiScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) guiScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ }
+
+ if (GuiCustomHex.getInstance().shouldOverride(containerName)) {
+ GuiCustomHex.getInstance().render(event.renderPartialTicks, containerName);
+ event.setCanceled(true);
+ return;
+ }
+
+ if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) {
+ GuiCustomEnchant.getInstance().render(event.renderPartialTicks);
+ event.setCanceled(true);
+ return;
+ }
+
+
+ boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
+ boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
+ boolean customAhActive =
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
+
+ if (storageOverlayActive) {
+ StorageOverlay.getInstance().render();
+ event.setCanceled(true);
+ return;
+ }
+
+ if (tradeWindowActive || customAhActive) {
+ event.setCanceled(true);
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ //Dark background
+ Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
+
+ if (event.mouseX < width * neu.overlay.getWidthMult() / 3 ||
+ event.mouseX > width - width * neu.overlay.getWidthMult() / 3) {
+ if (customAhActive) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
+ neu.overlay.render(false);
+ } else {
+ neu.overlay.render(false);
+ if (customAhActive) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
+ }
+ }
+
+ if (CalendarOverlay.isEnabled() || event.isCanceled()) return;
+ if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) &&
+ event.gui instanceof GuiContainer) {
+ doInventoryButtons = true;
+
+ int zOffset = 50;
+
+ GlStateManager.translate(0, 0, zOffset);
+
+ int xSize = ((AccessorGuiContainer) event.gui).getXSize();
+ int ySize = ((AccessorGuiContainer) event.gui).getYSize();
+ int guiLeft = ((AccessorGuiContainer) event.gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) event.gui).getGuiTop();
+
+ if (!NEUApi.disableInventoryButtons) {
+ if (!EnchantingSolvers.disableButtons()) {
+ for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if (!button.isActive()) continue;
+ if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft + button.x;
+ int y = guiTop + button.y;
+ if (button.anchorRight) {
+ x += xSize;
+ }
+ if (button.anchorBottom) {
+ y += ySize;
+ }
+ if (AccessoryBagOverlay.isInAccessoryBag()) {
+ if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
+ x += 80 + 28;
+ }
+ }
+ if (TrophyRewardOverlay.inTrophyFishingInventory()) {
+ int diffX = 162;
+ if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 120) {
+ x += diffX;
+ }
+ }
+ if (AuctionProfit.inAuctionPage()) {
+ if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 56) {
+ x -= 68 - 200;
+ }
+ }
+ if (EquipmentOverlay.isRenderingArmorHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (EquipmentOverlay.isRenderingPetHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+ if (inDungeonPage) {
+ if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 100) {
+ x += 185;
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1f);
+
+ GlStateManager.enableDepth();
+ GlStateManager.enableAlpha();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(EDITOR);
+ Utils.drawTexturedRect(
+ x,
+ y,
+ 18,
+ 18,
+ button.backgroundIndex * 18 / 256f,
+ (button.backgroundIndex * 18 + 18) / 256f,
+ 18 / 256f,
+ 36 / 256f,
+ GL11.GL_NEAREST
+ );
+
+ if (button.icon != null && !button.icon.trim().isEmpty()) {
+ GuiInvButtonEditor.renderIcon(button.icon, x + 1, y + 1);
+ }
+ }
+ }
+ }
+ GlStateManager.translate(0, 0, -zOffset);
+ }
+ }
+
+ /**
+ * Will draw the NEUOverlay over the inventory if focusInv == false. (z-translation of 300 is so that NEUOverlay
+ * will draw over Items in the inventory (which render at a z value of about 250))
+ */
+ @SubscribeEvent
+ public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
+ drawingGuiScreen = false;
+ disableCraftingText = false;
+
+ String containerName = null;
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if (guiScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) guiScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ if (GuiCustomHex.getInstance().shouldOverride(containerName)) return;
+ if (GuiCustomEnchant.getInstance().shouldOverride(containerName)) return;
+ }
+
+ boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
+ boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
+ boolean customAhActive =
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
+
+ if (!(tradeWindowActive || storageOverlayActive || customAhActive)) {
+ if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ GlStateManager.pushMatrix();
+ if (!focusInv) {
+ GL11.glTranslatef(0, 0, 300);
+ neu.overlay.render(hoverInv && focusInv);
+ GL11.glTranslatef(0, 0, -300);
+ }
+ GlStateManager.popMatrix();
+ }
+ }
+
+ if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock() && !hoverInv) {
+ renderDungKuudraChestOverlay(event.gui);
+ if (NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay) {
+ AccessoryBagOverlay.renderOverlay();
+ }
+ }
+
+ boolean hoveringButton = false;
+ if (!doInventoryButtons) return;
+ if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) &&
+ event.gui instanceof GuiContainer) {
+ int xSize = ((AccessorGuiContainer) event.gui).getXSize();
+ int ySize = ((AccessorGuiContainer) event.gui).getYSize();
+ int guiLeft = ((AccessorGuiContainer) event.gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) event.gui).getGuiTop();
+
+ if (!NEUApi.disableInventoryButtons) {
+ if (!EnchantingSolvers.disableButtons()) {
+ for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if (!button.isActive()) continue;
+ if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft + button.x;
+ int y = guiTop + button.y;
+ if (button.anchorRight) {
+ x += xSize;
+ }
+ if (button.anchorBottom) {
+ y += ySize;
+ }
+ if (AccessoryBagOverlay.isInAccessoryBag()) {
+ if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
+ x += 80 + 28;
+ }
+ }
+ if (TrophyRewardOverlay.inTrophyFishingInventory()) {
+ int diffX = 162;
+ if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 120) {
+ x += diffX;
+ }
+ }
+ if (AuctionProfit.inAuctionPage()) {
+ if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 56) {
+ x -= 68 - 200;
+ }
+ }
+ if (EquipmentOverlay.isRenderingArmorHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (EquipmentOverlay.isRenderingPetHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+
+ if (inDungeonPage) {
+ if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 100) {
+ x += 185;
+ }
+ }
+
+ if (x - guiLeft >= 85 && x - guiLeft <= 115 && y - guiTop >= 4 && y - guiTop <= 25) {
+ disableCraftingText = true;
+ }
+
+ if (event.mouseX >= x && event.mouseX <= x + 18 && event.mouseY >= y && event.mouseY <= y + 18) {
+ hoveringButton = true;
+ long currentTime = System.currentTimeMillis();
+
+ if (buttonHovered != button) {
+ buttonHoveredMillis = currentTime;
+ buttonHovered = button;
+ }
+
+ if (currentTime - buttonHoveredMillis > 600) {
+ String command = button.command.trim();
+ if (!command.startsWith("/")) {
+ command = "/" + command;
+ }
+
+ Utils.drawHoveringText(
+ Lists.newArrayList("\u00a77" + command),
+ event.mouseX,
+ event.mouseY,
+ event.gui.width,
+ event.gui.height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+ }
+ }
+ }
+ }
+ if (!hoveringButton) buttonHovered = null;
+
+ if (AuctionBINWarning.getInstance().shouldShow()) {
+ AuctionBINWarning.getInstance().render();
+ }
+
+ if (AbiphoneWarning.getInstance().shouldShow()) {
+ AbiphoneWarning.getInstance().render();
+ }
+ }
+
+ private void renderDungKuudraChestOverlay(GuiScreen gui) {
+ if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 3) return;
+ if (gui instanceof GuiChest && NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc != 2) {
+ try {
+ int xSize = ((AccessorGuiContainer) gui).getXSize();
+ int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) gui).getGuiTop();
+
+ GuiChest eventGui = (GuiChest) gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ ItemStack rewardChest = lower.getStackInSlot(31);
+ this.inDungeonPage = rewardChest != null && rewardChest.getDisplayName().endsWith(
+ EnumChatFormatting.GREEN + "Open Reward Chest");
+ if (inDungeonPage) {
+ int chestCost = 0;
+ try {
+ String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]);
+ StringBuilder cost = new StringBuilder();
+ for (int i = 0; i < line6.length(); i++) {
+ char c = line6.charAt(i);
+ if (Character.isDigit(c)) {
+ cost.append(c);
+ }
+ }
+ if (cost.length() > 0) {
+ chestCost = Integer.parseInt(cost.toString());
+ }
+ } catch (Exception ignored) {
+ }
+
+ String missingItem = null;
+ double totalValue = 0;
+ HashMap<String, Double> itemValues = new HashMap<>();
+ for (int i = 0; i < 5; i++) {
+ ItemStack item = lower.getStackInSlot(11 + i);
+ if (ItemUtils.isSoulbound(item)) continue;
+
+ String internal = neu.manager.createItemResolutionQuery().withItemStack(item).resolveInternalName();
+ String displayName = item.getDisplayName();
+ Matcher matcher = ESSENCE_PATTERN.matcher(displayName);
+ if (neu.config.dungeons.useEssenceCostFromBazaar && matcher.matches()) {
+ String type = matcher.group(1).toUpperCase();
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo("ESSENCE_" + type);
+ if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
+ float bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
+ int amount = Integer.parseInt(matcher.group(2));
+ double price = bazaarPrice * amount;
+ itemValues.put(displayName, price);
+ totalValue += price;
+ }
+ continue;
+ }
+ if (internal != null) {
+ internal = internal.replace("\u00CD", "I").replace("\u0130", "I");
+ float bazaarPrice = -1;
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
+ if (bazaarInfo != null && bazaarInfo.has("curr_sell")) {
+ bazaarPrice = bazaarInfo.get("curr_sell").getAsFloat();
+ } else if (bazaarInfo != null) {
+ bazaarPrice = 0;
+ }
+ if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000;
+
+ double worth = -1;
+ boolean isOnBz = false;
+ if (bazaarPrice >= 0) {
+ worth = bazaarPrice;
+ isOnBz = true;
+ } else {
+ switch (NotEnoughUpdates.INSTANCE.config.dungeons.profitType) {
+ case 1:
+ worth = neu.manager.auctionManager.getItemAvgBin(internal);
+ break;
+ case 2:
+ JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if (auctionInfo != null) {
+ if (auctionInfo.has("clean_price")) {
+ worth = (long) auctionInfo.get("clean_price").getAsDouble();
+ } else {
+ worth =
+ (long) (auctionInfo.get("price").getAsDouble() / auctionInfo.get("count").getAsDouble());
+ }
+ }
+ break;
+ default:
+ worth = neu.manager.auctionManager.getLowestBin(internal);
+ }
+ if (worth <= 0) {
+ worth = neu.manager.auctionManager.getLowestBin(internal);
+ if (worth <= 0) {
+ worth = neu.manager.auctionManager.getItemAvgBin(internal);
+ if (worth <= 0) {
+ JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if (auctionInfo != null) {
+ if (auctionInfo.has("clean_price")) {
+ worth = auctionInfo.get("clean_price").getAsFloat();
+ } else {
+ worth = (auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ((worth >= 0 || isOnBz) && totalValue >= 0) {
+ totalValue += worth;
+ String display = item.getDisplayName();
+
+ if (display.contains("Enchanted Book")) {
+ NBTTagCompound tag = item.getTagCompound();
+ if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ NBTTagCompound enchants = ea.getCompoundTag("enchantments");
+
+ int highestLevel = -1;
+ for (String enchname : enchants.getKeySet()) {
+ int level = enchants.getInteger(enchname);
+ if (level > highestLevel) {
+ display = EnumChatFormatting.BLUE + WordUtils.capitalizeFully(enchname
+ .replace("_", " ")
+ .replace("Ultimate", "")
+ .trim()) + " " + level;
+ }
+ }
+ }
+ }
+
+ itemValues.put(display, worth);
+ } else {
+ if (totalValue != -1) {
+ missingItem = internal;
+ }
+ totalValue = -1;
+ }
+ }
+ }
+
+ String valueStringBIN1;
+ String valueStringBIN2;
+ if (totalValue >= 0) {
+ valueStringBIN1 = EnumChatFormatting.YELLOW + "Value (BIN): ";
+ valueStringBIN2 = EnumChatFormatting.GOLD + formatCoins(totalValue) + " coins";
+ } else {
+ valueStringBIN1 = EnumChatFormatting.YELLOW + "Can't find BIN: ";
+ valueStringBIN2 = missingItem;
+ }
+
+ double profitLossBIN = totalValue - chestCost;
+
+ boolean kismetUsed = false;
+ // checking for kismet
+ Slot slot = (eventGui.inventorySlots.getSlot(50));
+ if (slot.getHasStack()) {
+ String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(slot.getStack().getTagCompound());
+ for (String line : lore) {
+ if (line.contains("You already rerolled a chest!")) {
+ kismetUsed = true;
+ break;
+ }
+ }
+ }
+ double kismetPrice = neu.manager.auctionManager.getLowestBin("KISMET_FEATHER");
+ String kismetStr = EnumChatFormatting.RED + formatCoins(kismetPrice) + " coins";
+ if (neu.config.dungeons.useKismetOnDungeonProfit)
+ profitLossBIN = kismetUsed ? profitLossBIN - kismetPrice : profitLossBIN;
+
+ String profitPrefix = EnumChatFormatting.DARK_GREEN.toString();
+ String lossPrefix = EnumChatFormatting.RED.toString();
+ String prefix = profitLossBIN >= 0 ? profitPrefix : lossPrefix;
+
+ String plStringBIN;
+ if (profitLossBIN >= 0) {
+ plStringBIN = prefix + "+" + formatCoins(profitLossBIN) + " coins";
+ } else {
+ plStringBIN = prefix + "-" + formatCoins(-profitLossBIN) + " coins";
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.dungeons.profitDisplayLoc == 1 && !valueStringBIN2.equals(missingItem)) {
+ int w = Minecraft.getMinecraft().fontRendererObj.getStringWidth(plStringBIN);
+ GlStateManager.disableLighting();
+ GlStateManager.translate(0, 0, 200);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ plStringBIN,
+ guiLeft + xSize - 5 - w,
+ guiTop + 5,
+ 0xffffffff,
+ true
+ );
+ GlStateManager.translate(0, 0, -200);
+ return;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth);
+ GL11.glColor4f(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+ Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST);
+
+ Utils.renderAlignedString(valueStringBIN1, valueStringBIN2, guiLeft + xSize + 4 + 10, guiTop + 14, 160);
+ if (neu.config.dungeons.useKismetOnDungeonProfit && kismetUsed) {
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Kismet Feather: ",
+ kismetStr,
+ guiLeft + xSize + 4 + 10,
+ guiTop + 24,
+ 160
+ );
+ }
+ if (totalValue >= 0) {
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Profit/Loss: ",
+ plStringBIN,
+ guiLeft + xSize + 4 + 10,
+ guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 34 : 24) : 24),
+ 160
+ );
+ }
+
+ int index = 0;
+ for (Map.Entry<String, Double> entry : itemValues.entrySet()) {
+ Utils.renderAlignedString(
+ entry.getKey(),
+ prefix + formatCoins(entry.getValue().doubleValue()),
+ guiLeft + xSize + 4 + 10,
+ guiTop + (neu.config.dungeons.useKismetOnDungeonProfit ? (kismetUsed ? 39 : 29) : 29) + (++index) * 10,
+ 160
+ );
+ }
+ JsonObject mayorJson = SBInfo.getInstance().getMayorJson();
+ JsonElement mayor = mayorJson.get("mayor");
+ if (mayorJson.has("mayor") && mayor != null && mayor.getAsJsonObject().has("name") &&
+ mayor.getAsJsonObject().get("name").getAsString().equals("Derpy")
+ && NotEnoughUpdates.INSTANCE.config.dungeons.shouldWarningDerpy) {
+ Utils.drawStringScaled(
+ EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "shMayor Derpy active!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + xSize + 4 + 10,
+ guiTop + 85,
+ true,
+ 0,
+ 1.3f
+ );
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private String formatCoins(double price) {
+ return format.format(price < 5 ? price : (long) price);
+ }
+
+ /**
+ * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused.
+ * Will also cancel the event if if NEUOverlay#mouseInput returns true.
+ */
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
+ if (Mouse.getEventButtonState() && StorageManager.getInstance().onAnyClick()) {
+ event.setCanceled(true);
+ return;
+ }
+
+ final ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ final int scaledWidth = scaledresolution.getScaledWidth();
+ final int scaledHeight = scaledresolution.getScaledHeight();
+ int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
+ int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
+
+ if (AuctionBINWarning.getInstance().shouldShow()) {
+ AuctionBINWarning.getInstance().mouseInput(mouseX, mouseY);
+ event.setCanceled(true);
+ return;
+ }
+ if (AbiphoneWarning.getInstance().shouldShow()) {
+ AbiphoneWarning.getInstance().mouseInput(mouseX, mouseY);
+ event.setCanceled(true);
+ return;
+ }
+
+ if (!event.isCanceled()) {
+ Utils.scrollTooltip(Mouse.getEventDWheel());
+ }
+ if (AuctionSearchOverlay.shouldReplace()) {
+ AuctionSearchOverlay.mouseEvent();
+ event.setCanceled(true);
+ return;
+ }
+ if (BazaarSearchOverlay.shouldReplace()) {
+ BazaarSearchOverlay.mouseEvent();
+ event.setCanceled(true);
+ return;
+ }
+ if (RancherBootOverlay.shouldReplace()) {
+ RancherBootOverlay.mouseEvent();
+ event.setCanceled(true);
+ return;
+ }
+
+ String containerName = null;
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if (guiScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) guiScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if (containerName.contains(" Profile") && BetterContainers.profileViewerStackIndex != -1 &&
+ ((AccessorGuiContainer) eventGui).doIsMouseOverSlot(
+ cc.inventorySlots.get(BetterContainers.profileViewerStackIndex),
+ mouseX,
+ mouseY
+ ) &&
+ Mouse.getEventButton() >= 0) {
+ event.setCanceled(true);
+ if (Mouse.getEventButtonState() && eventGui.inventorySlots.inventorySlots.get(22).getStack() != null &&
+ eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound() != null) {
+ NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound();
+ if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) {
+ String username = tag.getCompoundTag("SkullOwner").getString("Name");
+ Utils.playPressSound();
+ ViewProfileCommand.RUNNABLE.accept(new String[]{username});
+ }
+ }
+ }
+ }
+
+ if (GuiCustomHex.getInstance().shouldOverride(containerName) &&
+ GuiCustomHex.getInstance().mouseInput(mouseX, mouseY)) {
+ event.setCanceled(true);
+ return;
+ }
+ if (GuiCustomEnchant.getInstance().shouldOverride(containerName) &&
+ GuiCustomEnchant.getInstance().mouseInput(mouseX, mouseY)) {
+ event.setCanceled(true);
+ return;
+ }
+
+
+ boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
+ boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
+ boolean customAhActive =
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
+
+ if (storageOverlayActive) {
+ if (StorageOverlay.getInstance().mouseInput(mouseX, mouseY)) {
+ event.setCanceled(true);
+ }
+ return;
+ }
+
+ if (tradeWindowActive || customAhActive) {
+ event.setCanceled(true);
+ if (customAhActive) {
+ neu.manager.auctionManager.customAH.handleMouseInput();
+ } else {
+ TradeWindow.handleMouseInput();
+ }
+ neu.overlay.mouseInput();
+ return;
+ }
+
+ if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ if (!NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay || !AccessoryBagOverlay.mouseClick()) {
+ if (!(hoverInv && focusInv)) {
+ if (neu.overlay.mouseInput()) {
+ event.setCanceled(true);
+ }
+ } else {
+ neu.overlay.mouseInputInv();
+ }
+ }
+ }
+ if (event.isCanceled()) return;
+ if (!doInventoryButtons) return;
+ if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() && NotificationHandler.shouldRenderOverlay(event.gui) &&
+ Mouse.getEventButton() >= 0 && event.gui instanceof GuiContainer) {
+ int xSize = ((AccessorGuiContainer) event.gui).getXSize();
+ int ySize = ((AccessorGuiContainer) event.gui).getYSize();
+ int guiLeft = ((AccessorGuiContainer) event.gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) event.gui).getGuiTop();
+ if (!NEUApi.disableInventoryButtons) {
+ if (!EnchantingSolvers.disableButtons()) {
+ for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
+ if (!button.isActive()) continue;
+ if (button.playerInvOnly && !(event.gui instanceof GuiInventory)) continue;
+
+ int x = guiLeft + button.x;
+ int y = guiTop + button.y;
+ if (button.anchorRight) {
+ x += xSize;
+ }
+ if (button.anchorBottom) {
+ y += ySize;
+ }
+ if (AccessoryBagOverlay.isInAccessoryBag()) {
+ if (x > guiLeft + xSize && x < guiLeft + xSize + 80 + 28 + 5 && y > guiTop - 18 && y < guiTop + 150) {
+ x += 80 + 28;
+ }
+ }
+ if (TrophyRewardOverlay.inTrophyFishingInventory()) {
+ int diffX = 162;
+ if (x > guiLeft + xSize && x < guiLeft + xSize + diffX + 5 && y > guiTop - 18 && y < guiTop + 120) {
+ x += diffX;
+ }
+ }
+ if (AuctionProfit.inAuctionPage()) {
+ if (x + 18 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 56) {
+ x -= 68 - 200;
+ }
+ }
+ if (EquipmentOverlay.isRenderingArmorHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (EquipmentOverlay.isRenderingPetHud()) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+ if (inDungeonPage) {
+ if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 &&
+ y < guiTop + 100) {
+ x += 185;
+ }
+ }
+
+ if (mouseX >= x && mouseX <= x + 18 && mouseY >= y && mouseY <= y + 18) {
+ if (Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
+ int clickType = NotEnoughUpdates.INSTANCE.config.inventoryButtons.clickType;
+ if ((clickType == 0 && Mouse.getEventButtonState()) ||
+ (clickType == 1 && !Mouse.getEventButtonState())) {
+ String command = button.command.trim();
+ if (!command.startsWith("/")) {
+ command = "/" + command;
+ }
+ if (ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command) == 0) {
+ NotEnoughUpdates.INSTANCE.sendChatMessage(command);
+ }
+ }
+ } else {
+ event.setCanceled(true);
+ }
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true.
+ * Also includes a dev function used for creating custom named json files with recipes.
+ */
+ @SubscribeEvent
+ public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
+ Keyboard.enableRepeatEvents(true);
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiInventory &&
+ !NEUOverlay.searchBarHasFocus &&
+ Keyboard.isRepeatEvent()) {
+ event.setCanceled(true);
+ return;
+ }
+ if (typing) {
+ event.setCanceled(true);
+ }
+ if (NotEnoughUpdates.INSTANCE.config.hidden.dev && Keyboard.isKeyDown(Keyboard.KEY_B) &&
+ Minecraft.getMinecraft().currentScreen instanceof GuiChest
+ ) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ ItemStack backArrow = lower.getStackInSlot(48);
+ List<String> tooltip = backArrow != null ? backArrow.getTooltip(Minecraft.getMinecraft().thePlayer, false) : null;
+ if (tooltip != null && tooltip.size() >= 2 && tooltip.get(1).endsWith("Essence")) {
+
+ try {
+ File file = new File(
+ Minecraft.getMinecraft().mcDataDir.getAbsolutePath(),
+ "config/notenoughupdates/repo/constants/essencecosts.json"
+ );
+ String fileContent;
+ fileContent = new BufferedReader(new InputStreamReader(
+ Files.newInputStream(file.toPath()),
+ StandardCharsets.UTF_8
+ ))
+ .lines()
+ .collect(Collectors.joining(System.lineSeparator()));
+ String id = null;
+ JsonObject jsonObject = new JsonParser().parse(fileContent).getAsJsonObject();
+ JsonObject newEntry = new JsonObject();
+ for (int i = 0; i < 54; i++) {
+ ItemStack stack = lower.getStackInSlot(i);
+ if (!stack.getDisplayName().isEmpty() && stack.getItem() != Item.getItemFromBlock(Blocks.barrier) &&
+ stack.getItem() != Items.arrow) {
+ if (stack.getTagCompound().getCompoundTag("display").hasKey("Lore", 9)) {
+ int stars = Utils.getNumberOfStars(stack);
+ if (stars == 0) continue;
+
+ NBTTagList lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+ int costIndex = 10000;
+ id = NotEnoughUpdates.INSTANCE.manager.getInternalnameFromNBT(stack.getTagCompound());
+ if (jsonObject.has(id)) {
+ jsonObject.remove(id);
+ }
+ for (int j = 0; j < lore.tagCount(); j++) {
+ String entry = lore.getStringTagAt(j);
+ if (entry.equals("§7Cost")) {
+ costIndex = j;
+ }
+ if (j > costIndex) {
+ entry = entry.trim();
+ int index = entry.lastIndexOf('x');
+ String item, amountString;
+ if (index < 0) {
+ item = entry.trim() + " x1";
+ amountString = "x1";
+ } else {
+ amountString = entry.substring(index);
+ item = entry.substring(0, index).trim();
+ }
+ item = item.substring(0, item.length() - 3);
+ int amount = Integer.parseInt(amountString.trim().replace("x", "").replace(",", ""));
+ if (item.endsWith("Essence")) {
+ int index2 = entry.indexOf("Essence");
+ String type = item.substring(0, index2).trim().substring(2);
+ newEntry.add("type", new JsonPrimitive(type));
+ newEntry.add(String.valueOf(stars), new JsonPrimitive(amount));
+ } else {
+ String itemString = item + " §8x" + amount;
+ if (!newEntry.has("items")) {
+ newEntry.add("items", new JsonObject());
+ }
+ if (!newEntry.get("items").getAsJsonObject().has(String.valueOf(stars))) {
+ newEntry.get("items").getAsJsonObject().add(String.valueOf(stars), new JsonArray());
+ }
+ newEntry
+ .get("items")
+ .getAsJsonObject()
+ .get(String.valueOf(stars))
+ .getAsJsonArray()
+ .add(new JsonPrimitive(itemString));
+ }
+ }
+ }
+ jsonObject.add(id, newEntry);
+ }
+ }
+ }
+ if (jsonObject.get(id).getAsJsonObject().has("items")) {
+ JsonObject itemsObj = jsonObject.get(id).getAsJsonObject().get("items").getAsJsonObject();
+ jsonObject.get(id).getAsJsonObject().remove("items");
+ jsonObject.get(id).getAsJsonObject().add("items", itemsObj);
+ }
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ try {
+ try (
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
+ Files.newOutputStream(file.toPath()),
+ StandardCharsets.UTF_8
+ ))
+ ) {
+ writer.write(gson.toJson(jsonObject));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + id));
+ }
+ } catch (IOException ignored) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Error while writing file."));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details."));
+ }
+ }
+ } else if (Keyboard.isKeyDown(Keyboard.KEY_RETURN) && NotEnoughUpdates.INSTANCE.config.hidden.dev) {
+ Minecraft mc = Minecraft.getMinecraft();
+
+ if (typing) {
+ typing = false;
+ cachedDefinitions.put(correctingItem, NEUOverlay.getTextField().getText());
+ NEUOverlay.getTextField().setText("");
+ }
+
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ try {
+ JsonObject newNPC = new JsonObject();
+ String displayName = lower.getDisplayName().getUnformattedText();
+ File file = new File(
+ Minecraft.getMinecraft().mcDataDir.getAbsolutePath(),
+ "config" + File.separator + "notenoughupdates" +
+ File.separator + "repo" + File.separator + "npc" + File.separator +
+ displayName.toUpperCase().replace(" ", "_") + ".json"
+ );
+ newNPC.add("itemid", new JsonPrimitive("minecraft:skull"));
+ newNPC.add("displayname", new JsonPrimitive("§9" + displayName + " (NPC)"));
+ newNPC.add("nbttag", new JsonPrimitive("TODO"));
+ newNPC.add("damage", new JsonPrimitive(3));
+
+ JsonArray newArray = new JsonArray();
+ newArray.add(new JsonPrimitive(""));
+ newNPC.add("lore", newArray);
+ newNPC.add("internalname", new JsonPrimitive(displayName.toUpperCase().replace(" ", "_") + "_NPC"));
+ newNPC.add("clickcommand", new JsonPrimitive("viewrecipe"));
+ newNPC.add("modver", new JsonPrimitive(NotEnoughUpdates.VERSION));
+ newNPC.add("infoType", new JsonPrimitive("WIKI_URL"));
+ JsonArray emptyInfoArray = new JsonArray();
+ emptyInfoArray.add(new JsonPrimitive("TODO"));
+ newNPC.add("info", emptyInfoArray);
+ newNPC.add("x", new JsonPrimitive((int) mc.thePlayer.posX));
+ newNPC.add("y", new JsonPrimitive((int) mc.thePlayer.posY + 2));
+ newNPC.add("z", new JsonPrimitive((int) mc.thePlayer.posZ));
+ newNPC.add("island", new JsonPrimitive(SBInfo.getInstance().getLocation()));
+
+ JsonArray recipesArray = new JsonArray();
+
+ TreeMap<String, JsonObject> itemInformation = NotEnoughUpdates.INSTANCE.manager.getItemInformation();
+ for (int i = 0; i < 45; i++) {
+ ItemStack stack = lower.getStackInSlot(i);
+ if (stack == null) continue;
+ if (stack.getDisplayName().isEmpty() || stack.getDisplayName().equals(" ")) continue;
+
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalnameFromNBT(stack.getTagCompound());
+ if (internalname == null) continue;
+ JsonObject currentRecipe = new JsonObject();
+ currentRecipe.add("type", new JsonPrimitive("npc_shop"));
+ JsonArray costArray = new JsonArray();
+ boolean inCost = false;
+ for (String s : NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound())) {
+ if (s.equals("§7Cost")) {
+ inCost = true;
+ continue;
+ } else if (s.equals("§eClick to trade!")) {
+ inCost = false;
+ }
+ if (!inCost) continue;
+ String entry = StringUtils.stripControlCodes(s);
+ if (entry.isEmpty()) continue;
+ int coinIndex = entry.indexOf(" Coins");
+ if (coinIndex != -1) {
+ String amountString = entry.substring(0, coinIndex).replace(",", "");
+ costArray.add(new JsonPrimitive("SKYBLOCK_COIN:" + amountString));
+ } else {
+ if (cachedDefinitions == null) {
+ cachedDefinitions = new HashMap<>();
+ }
+
+ String item;
+ int amountIndex = entry.lastIndexOf(" x");
+ String amountString;
+ if (amountIndex == -1) {
+ amountString = "1";
+ item = entry.replace(" ", "_").toUpperCase();
+ } else {
+ amountString = entry.substring(amountIndex);
+ item = entry.substring(0, amountIndex).replace(" ", "_").toUpperCase();
+ }
+ amountString = amountString.replace(",", "").replace("x", "").trim();
+ if (itemInformation.containsKey(item)) {
+ costArray.add(new JsonPrimitive(item + ":" + amountString));
+ } else if (cachedDefinitions.containsKey(item)) {
+ costArray.add(new JsonPrimitive(cachedDefinitions.get(item) + ":" + amountString));
+ } else {
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ "Change the item ID of " + item + " to the correct one and press Enter."));
+ NEUOverlay.getTextField().setText(item);
+ event.setCanceled(true);
+ typing = true;
+ correctingItem = item;
+ if (cachedDefinitions == null) {
+ cachedDefinitions = new HashMap<>();
+ }
+ return;
+ }
+ }
+ }
+ currentRecipe.add("cost", costArray);
+ currentRecipe.add("result", new JsonPrimitive(internalname));
+ recipesArray.add(currentRecipe);
+ newNPC.add("recipes", recipesArray);
+ }
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ System.out.println(gson.toJson(newNPC));
+ try {
+ //noinspection ResultOfMethodCallIgnored
+ file.createNewFile();
+ try (
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
+ Files.newOutputStream(file.toPath()),
+ StandardCharsets.UTF_8
+ ))
+ ) {
+ writer.write(gson.toJson(newNPC));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA + "Parsed and saved: " + EnumChatFormatting.WHITE + displayName));
+ }
+ } catch (IOException ignored) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Error while writing file."));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "Error while parsing inventory. Try again or check logs for details"));
+ }
+ }
+ } else if (NotEnoughUpdates.INSTANCE.config.hidden.dev && Keyboard.isKeyDown(Keyboard.KEY_B) &&
+ Minecraft.getMinecraft().currentScreen instanceof GuiChest &&
+ ((((ContainerChest) ((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots)
+ .getLowerChestInventory()
+ .getDisplayName()
+ .getUnformattedText()
+ .endsWith("Essence")))) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ for (int i = 9; i < 45; i++) {
+ ItemStack stack = lower.getStackInSlot(i);
+ if (stack == null) continue;
+ if (stack.getDisplayName().isEmpty() || stack.getDisplayName().equals(" ")) continue;
+ String internalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if (internalName == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "ERROR: Could not get internal name for: " + EnumChatFormatting.AQUA +
+ stack.getDisplayName()));
+ continue;
+ }
+ JsonObject itemObject = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(stack);
+ JsonArray lore = itemObject.get("lore").getAsJsonArray();
+ List<String> loreList = new ArrayList<>();
+ for (int j = 0; j < lore.size(); j++) loreList.add(lore.get(j).getAsString());
+ if (loreList.get(loreList.size() - 1).equals("§7§eClick to view upgrades!")) {
+ loreList.remove(loreList.size() - 1);
+ loreList.remove(loreList.size() - 1);
+ }
+
+ JsonArray newLore = new JsonArray();
+ for (String s : loreList) {
+ newLore.add(new JsonPrimitive(s));
+ }
+ itemObject.remove("lore");
+ itemObject.add("lore", newLore);
+
+ if (!NEUItemEditor.saveOnly(internalName, itemObject)) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "ERROR: Failed to save item: " + EnumChatFormatting.AQUA +
+ stack.getDisplayName()));
+ }
+ }
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA + "Parsed page: " + lower.getDisplayName().getUnformattedText()));
+ event.setCanceled(true);
+ return;
+ }
+
+ if (AuctionBINWarning.getInstance().shouldShow()) {
+ AuctionBINWarning.getInstance().keyboardInput();
+ event.setCanceled(true);
+ return;
+ }
+ if (AbiphoneWarning.getInstance().shouldShow()) {
+ AbiphoneWarning.getInstance().keyboardInput();
+ event.setCanceled(true);
+ return;
+ }
+
+ if (AuctionSearchOverlay.shouldReplace()) {
+ AuctionSearchOverlay.keyEvent();
+ event.setCanceled(true);
+ return;
+ }
+ if (BazaarSearchOverlay.shouldReplace()) {
+ BazaarSearchOverlay.keyEvent();
+ event.setCanceled(true);
+ return;
+ }
+ if (RancherBootOverlay.shouldReplace()) {
+ RancherBootOverlay.keyEvent();
+ event.setCanceled(true);
+ return;
+ }
+
+ String containerName = null;
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+
+ if (guiScreen instanceof GuiChest) {
+ containerName = ((ContainerChest) ((GuiChest) guiScreen).inventorySlots)
+ .getLowerChestInventory()
+ .getDisplayName()
+ .getUnformattedText();
+ }
+
+ if (GuiCustomHex.getInstance().shouldOverride(containerName) &&
+ GuiCustomHex.getInstance().keyboardInput()) {
+ event.setCanceled(true);
+ return;
+ }
+
+ if (GuiCustomEnchant.getInstance().shouldOverride(containerName) &&
+ GuiCustomEnchant.getInstance().keyboardInput()) {
+ event.setCanceled(true);
+ return;
+ }
+
+
+ boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName);
+ boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName);
+ boolean customAhActive =
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView();
+
+ if (storageOverlayActive) {
+ if (StorageOverlay.getInstance().keyboardInput()) {
+ event.setCanceled(true);
+ return;
+ }
+ }
+
+ if (tradeWindowActive || customAhActive) {
+ if (customAhActive) {
+ if (neu.manager.auctionManager.customAH.keyboardInput()) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ } else if (neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ } else {
+ TradeWindow.keyboardInput();
+ if (Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ neu.overlay.keyboardInput(focusInv);
+ }
+ }
+ return;
+ }
+
+ if (NotificationHandler.shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ if (neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ }
+ if (NotEnoughUpdates.INSTANCE.config.apiData.repositoryEditing &&
+ Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_N &&
+ Keyboard.getEventKeyState()) {
+ GuiScreen gui = Minecraft.getMinecraft().currentScreen;
+ if (gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ if (!lower.getDisplayName().getUnformattedText().endsWith("Essence")) return;
+
+ for (int i = 0; i < lower.getSizeInventory(); i++) {
+ ItemStack stack = lower.getStackInSlot(i);
+
+ String internalname = neu.manager.getInternalNameForItem(stack);
+ if (internalname != null) {
+ String[] lore = neu.manager.getLoreFromNBT(stack.getTagCompound());
+
+ for (String line : lore) {
+ if (line.contains(":") && (line.startsWith("\u00A77Upgrade to") || line.startsWith(
+ "\u00A77Convert to Dungeon Item"))) {
+ String[] split = line.split(":");
+ String after = Utils.cleanColour(split[1]);
+ StringBuilder costS = new StringBuilder();
+ for (char c : after.toCharArray()) {
+ if (c >= '0' && c <= '9') {
+ costS.append(c);
+ }
+ }
+ int cost = Integer.parseInt(costS.toString());
+ String[] afterSplit = after.split(" ");
+ String type = afterSplit[afterSplit.length - 2];
+
+ if (!essenceJson.has(internalname)) {
+ essenceJson.add(internalname, new JsonObject());
+ }
+ JsonObject obj = essenceJson.get(internalname).getAsJsonObject();
+ obj.addProperty("type", type);
+
+ if (line.startsWith("\u00A77Convert to Dungeon Item")) {
+ obj.addProperty("dungeonize", cost);
+ } else if (line.startsWith("\u00A77Upgrade to")) {
+ int stars = 0;
+ for (char c : line.toCharArray()) {
+ if (c == '\u272A') stars++;
+ }
+ if (stars > 0) {
+ obj.addProperty(stars + "", cost);
+ }
+ }
+ }
+ }
+ }
+ }
+ System.out.println(essenceJson);
+ }
+ }
+ if (NotEnoughUpdates.INSTANCE.config.apiData.repositoryEditing &&
+ Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_O &&
+ Keyboard.getEventKeyState()) {
+ GuiScreen gui = Minecraft.getMinecraft().currentScreen;
+ if (gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ if (lower.getStackInSlot(23) != null && lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = neu.manager.getInternalNameForItem(res);
+ JTextField tf = new JTextField();
+ tf.setText(resInternalname);
+ tf.addAncestorListener(new RequestFocusListener());
+ JOptionPane.showOptionDialog(
+ null,
+ tf,
+ "Enter Name:",
+ JOptionPane.NO_OPTION,
+ JOptionPane.PLAIN_MESSAGE,
+ null,
+ new String[]{"Enter"},
+ "Enter"
+ );
+ resInternalname = tf.getText();
+ if (resInternalname.trim().length() == 0) {
+ return;
+ }
+
+ JsonObject recipe = new JsonObject();
+
+ String[] x = {"1", "2", "3"};
+ String[] y = {"A", "B", "C"};
+
+ for (int i = 0; i <= 18; i += 9) {
+ for (int j = 0; j < 3; j++) {
+ ItemStack stack = lower.getStackInSlot(10 + i + j);
+ String internalname = "";
+ if (stack != null) {
+ internalname = neu.manager.getInternalNameForItem(stack);
+ if (!neu.manager.getItemInformation().containsKey(internalname)) {
+ neu.manager.writeItemToFile(stack);
+ }
+ internalname += ":" + stack.stackSize;
+ }
+ recipe.addProperty(y[i / 9] + x[j], internalname);
+ }
+ }
+
+ JsonObject json = neu.manager.getJsonForItem(res);
+ json.add("recipe", recipe);
+ json.addProperty("internalname", resInternalname);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ neu.manager.writeJsonDefaultDir(json, resInternalname + ".json");
+ neu.manager.loadItem(resInternalname);
+ } catch (IOException ignored) {
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ CrystalMetalDetectorSolver.render(event.partialTicks);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java
new file mode 100644
index 00000000..622b2088
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ScoreboardLocationChangeListener.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.listener;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.overlays.TimersOverlay;
+
+public class ScoreboardLocationChangeListener {
+
+ public ScoreboardLocationChangeListener(String oldLocation, String newLocation) {
+ if (oldLocation.equals("Belly of the Beast") && newLocation.equals("Matriarchs Lair")) {
+ //Check inventory pearl count for AFTER they complete to see if it is the same as before + (amount available on actionbar)
+ Thread thread = new Thread(() -> {
+ try {
+ Thread.sleep(3000);
+ TimersOverlay.afterPearls = TimersOverlay.heavyPearlCount();
+ //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"You exited the beast with ["+EnumChatFormatting.AQUA+(TimersOverlay.afterPearls-TimersOverlay.beforePearls)+EnumChatFormatting.YELLOW+"/"+EnumChatFormatting.AQUA+TimersOverlay.availablePearls+EnumChatFormatting.YELLOW+"] Heavy Pearls!"));
+ if (TimersOverlay.afterPearls - TimersOverlay.beforePearls == TimersOverlay.availablePearls) {
+ NotEnoughUpdates.INSTANCE.config.getProfileSpecific().dailyHeavyPearlCompleted = System.currentTimeMillis();
+ //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Daily "+EnumChatFormatting.DARK_AQUA+"Heavy Pearls"+EnumChatFormatting.GREEN+" Complete!"));
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ });
+ thread.start();
+ } else if (oldLocation.equals("Matriarchs Lair") && newLocation.equals("Belly of the Beast")) {
+ //Check inventory pearl count BEFORE they complete so we can later check if it is complete.
+ TimersOverlay.beforePearls = TimersOverlay.heavyPearlCount();
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
index eaf41ba6..7193b47f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
import org.lwjgl.util.vector.Vector2f;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java
index b9e858ef..5f530c00 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
import com.google.gson.JsonObject;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
index ad836097..3e3ab1e3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
public abstract class MBGuiElement {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
index 4540b146..b183bd1e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
import org.lwjgl.util.vector.Vector2f;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java
index eef4b5e5..5c0cd37e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
import org.lwjgl.util.vector.Vector2f;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
index 24697cc6..c57f0b74 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mbgui;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -10,7 +29,11 @@ import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import org.lwjgl.util.vector.Vector2f;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
public class MBGuiGroupFloating extends MBGuiGroup {
private GuiScreen lastScreen = null;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java
new file mode 100644
index 00000000..67ac4f4c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AbiphoneWarning.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GuiElement;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.util.List;
+
+public class AbiphoneWarning extends GuiElement {
+ private static final AbiphoneWarning INSTANCE = new AbiphoneWarning();
+
+ private boolean showWarning = false;
+ private String contactName = null;
+ private int contactSlot = -1;
+
+ public static AbiphoneWarning getInstance() {
+ return INSTANCE;
+ }
+
+ private boolean shouldPerformCheck() {
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ showWarning = false;
+ return false;
+ }
+
+ if (Utils.getOpenChestName().startsWith("Abiphone ")) {
+ return true;
+ } else {
+ showWarning = false;
+ return false;
+ }
+ }
+
+ public boolean shouldShow() {
+ return shouldPerformCheck() && showWarning;
+ }
+
+ @SubscribeEvent
+ public void onMouseClick(SlotClickEvent event) {
+ if (!shouldPerformCheck()) return;
+ if (!NotEnoughUpdates.INSTANCE.config.misc.abiphoneWarning) return;
+ if (event.slotId == -999) return;
+ if (event.clickedButton == 0) return;
+
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+
+ ItemStack clickedContact = chest.inventorySlots.getSlot(event.slotId).getStack();
+ if (clickedContact == null) return;
+
+ List<String> list = ItemUtils.getLore(clickedContact);
+ if (list.isEmpty()) return;
+
+ String last = list.get(list.size() - 1);
+ if (last.contains("Right-click to remove contact!")) {
+ showWarning = true;
+ contactName = clickedContact.getDisplayName();
+ contactSlot = event.slotId;
+ event.setCanceled(true);
+ }
+ }
+
+ public void overrideIsMouseOverSlot(Slot slot, int mouseX, int mouseY, CallbackInfoReturnable<Boolean> cir) {
+ if (shouldShow()) {
+ cir.setReturnValue(false);
+ }
+ }
+
+ @Override
+ public void render() {
+ final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ final int width = scaledResolution.getScaledWidth();
+ final int height = scaledResolution.getScaledHeight();
+
+ GlStateManager.disableLighting();
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 500);
+
+ Gui.drawRect(0, 0, width, height, 0x80000000);
+
+ RenderUtils.drawFloatingRectDark(width / 2 - 90, height / 2 - 45, 180, 90);
+
+ int neuLength = Minecraft.getMinecraft().fontRendererObj.getStringWidth("\u00a7lNEU");
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ "\u00a7lNEU",
+ width / 2 + 90 - neuLength - 3,
+ height / 2 - 45 + 4,
+ 0xff000000
+ );
+
+ TextRenderUtils.drawStringCenteredScaledMaxWidth("Are you SURE?", Minecraft.getMinecraft().fontRendererObj,
+ width / 2, height / 2 - 45 + 10, false, 170, 0xffff4040
+ );
+
+ String sellLine = "\u00a77[ \u00a7r" + contactName + "\u00a77 ]";
+
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(sellLine, Minecraft.getMinecraft().fontRendererObj,
+ width / 2, height / 2 - 45 + 25, false, 170, 0xffffffff
+ );
+
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(
+ "Continue removing this contact?",
+ Minecraft.getMinecraft().fontRendererObj,
+ width / 2,
+ height / 2 - 45 + 50,
+ false,
+ 170,
+ 0xffa0a0a0
+ );
+
+ RenderUtils.drawFloatingRectDark(width / 2 - 43, height / 2 + 23, 40, 16, false);
+ RenderUtils.drawFloatingRectDark(width / 2 + 3, height / 2 + 23, 40, 16, false);
+
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(
+ EnumChatFormatting.GREEN + "[Y]es",
+ Minecraft.getMinecraft().fontRendererObj,
+ width / 2 - 23,
+ height / 2 + 31,
+ true,
+ 36,
+ 0xff00ff00
+ );
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(
+ EnumChatFormatting.RED + "[N]o",
+ Minecraft.getMinecraft().fontRendererObj,
+ width / 2 + 23,
+ height / 2 + 31,
+ true,
+ 36,
+ 0xffff0000
+ );
+
+ GlStateManager.popMatrix();
+ }
+
+ @Override
+ public boolean mouseInput(int mouseX, int mouseY) {
+ final ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ final int width = scaledResolution.getScaledWidth();
+ final int height = scaledResolution.getScaledHeight();
+
+ if (Mouse.getEventButtonState()) {
+ if (mouseY >= height / 2 + 23 && mouseY <= height / 2 + 23 + 16) {
+ if (mouseX >= width / 2 - 43 && mouseX <= width / 2 - 3) {
+ makeClick();
+ }
+ showWarning = false;
+ }
+
+ if (mouseX < width / 2 - 90 || mouseX > width / 2 + 90 ||
+ mouseY < height / 2 - 45 || mouseY > height / 2 + 45) {
+ showWarning = false;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean keyboardInput() {
+ if (!Keyboard.getEventKeyState()) {
+ if (Keyboard.getEventKey() == Keyboard.KEY_Y || Keyboard.getEventKey() == Keyboard.KEY_RETURN) {
+ makeClick();
+ }
+ showWarning = false;
+ }
+
+ return false;
+ }
+
+ private void makeClick() {
+ if (contactSlot != -1) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ Minecraft.getMinecraft().playerController.windowClick(chest.inventorySlots.windowId,
+ contactSlot, 1, 0, Minecraft.getMinecraft().thePlayer
+ );
+ contactSlot = -1;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java
new file mode 100644
index 00000000..70ac4489
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AntiCoopAdd.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+public class AntiCoopAdd {
+
+ @SubscribeEvent
+ public void onMouseClick(SlotClickEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.config.misc.coopWarning) return;
+ if (event.slotId == -999) return;
+ if (!Utils.getOpenChestName().contains("Profile")) return;
+
+ ItemStack stack = event.slot.getStack();
+ if (stack == null) return;
+ if (stack.getItem() == Items.diamond && stack.getDisplayName() != null && stack.getDisplayName().contains(
+ "Co-op Request")) {
+ String ign = Utils.getOpenChestName().split("'s Profile")[0];
+ ChatComponentText storageMessage = new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] " + EnumChatFormatting.YELLOW +
+ "You just clicked on the Co-op add button. If you want to coop add this person, click this chat message");
+ storageMessage.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/coopadd " + ign));
+ storageMessage.setChatStyle(storageMessage.getChatStyle().setChatHoverEvent(
+ new HoverEvent(
+ HoverEvent.Action.SHOW_TEXT,
+ new ChatComponentText(EnumChatFormatting.YELLOW + "Click to add " + ign + " to your coop")
+ )));
+ ChatComponentText storageChatMessage = new ChatComponentText("");
+ storageChatMessage.appendSibling(storageMessage);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(storageChatMessage);
+ event.setCanceled(true);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java
index c76a22b4..ad9df7af 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionBINWarning.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.gson.JsonObject;
@@ -5,7 +24,7 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.GuiElement;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
@@ -15,6 +34,7 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -35,19 +55,20 @@ public class AuctionBINWarning extends GuiElement {
private boolean showWarning = false;
private List<String> sellingTooltip;
private String sellingName;
- private int sellingPrice;
- private int lowestPrice;
+ private long sellingPrice;
+ private long lowestPrice;
+ private long buyPercentage;
+ private int sellStackAmount;
+ private boolean isALoss = true;
private boolean shouldPerformCheck() {
- if (!NotEnoughUpdates.INSTANCE.config.ahTweaks.enableBINWarning ||
- !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
sellingTooltip = null;
showWarning = false;
return false;
}
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest &&
- SBInfo.getInstance().lastOpenContainerName.startsWith("Create BIN Auction")) {
+ if (Utils.getOpenChestName().startsWith("Create BIN Auction")) {
return true;
} else {
sellingTooltip = null;
@@ -60,65 +81,73 @@ public class AuctionBINWarning extends GuiElement {
return shouldPerformCheck() && showWarning;
}
- public boolean onMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType) {
- if (!shouldPerformCheck()) return false;
+ @SubscribeEvent
+ public void onMouseClick(SlotClickEvent event) {
+ if (!shouldPerformCheck()) return;
- if (slotId == 29) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ if (event.slotId != 29) {
+ return;
+ }
- sellingPrice = -1;
+ sellingPrice = -1;
- ItemStack priceStack = chest.inventorySlots.getSlot(31).getStack();
- if (priceStack != null) {
- String displayName = priceStack.getDisplayName();
- Matcher priceMatcher = ITEM_PRICE_REGEX.matcher(displayName);
+ ItemStack priceStack = event.guiContainer.inventorySlots.getSlot(31).getStack();
+ if (priceStack != null) {
+ String displayName = priceStack.getDisplayName();
+ Matcher priceMatcher = ITEM_PRICE_REGEX.matcher(displayName);
- if (priceMatcher.matches()) {
- try {
- sellingPrice = Integer.parseInt(priceMatcher.group(1).replace(",", ""));
- } catch (NumberFormatException ignored) {
- }
+ if (priceMatcher.matches()) {
+ try {
+ sellingPrice = Long.parseLong(priceMatcher.group(1).replace(",", ""));
+ } catch (NumberFormatException ignored) {
}
}
+ }
- ItemStack sellStack = chest.inventorySlots.getSlot(13).getStack();
- String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(sellStack);
-
- if (internalname == null) {
- return false;
- }
+ ItemStack sellStack = event.guiContainer.inventorySlots.getSlot(13).getStack();
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(sellStack);
+ sellStackAmount = sellStack.stackSize;
- JsonObject itemInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(internalname);
- if (itemInfo == null || !itemInfo.has("displayname")) {
- sellingName = internalname;
- } else {
- sellingName = itemInfo.get("displayname").getAsString();
- }
+ if (internalname == null) {
+ return;
+ }
- sellingTooltip = sellStack.getTooltip(
- Minecraft.getMinecraft().thePlayer,
- Minecraft.getMinecraft().gameSettings.advancedItemTooltips
- );
+ JsonObject itemInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(internalname);
+ if (itemInfo == null || !itemInfo.has("displayname")) {
+ sellingName = internalname;
+ } else {
+ sellingName = itemInfo.get("displayname").getAsString();
+ }
- lowestPrice = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
- if (lowestPrice <= 0) {
- lowestPrice = (int) NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname);
- }
+ sellingTooltip = sellStack.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
- //TODO: Add option for warning if lowest price does not exist
+ lowestPrice = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
+ if (lowestPrice <= 0) {
+ lowestPrice = (int) NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAvgBin(internalname);
+ }
- float factor = 1 - NotEnoughUpdates.INSTANCE.config.ahTweaks.warningThreshold / 100;
- if (factor < 0) factor = 0;
- if (factor > 1) factor = 1;
+ float undercutFactor = 1 - NotEnoughUpdates.INSTANCE.config.ahTweaks.warningThreshold / 100;
+ if (undercutFactor < 0) undercutFactor = 0;
+ if (undercutFactor > 1) undercutFactor = 1;
+ float overcutFactor = 1 - NotEnoughUpdates.INSTANCE.config.ahTweaks.overcutWarningThreshold / 100;
+ if (overcutFactor < 0) overcutFactor = 0;
+ if (overcutFactor > 1) overcutFactor = 1;
- if (sellingPrice > 0 && lowestPrice > 0 && sellingPrice < lowestPrice * factor) {
- showWarning = true;
- return true;
- } else {
- return false;
- }
+ if (lowestPrice == -1) {
+ return;
+ }
+ if (NotEnoughUpdates.INSTANCE.config.ahTweaks.underCutWarning &&
+ (sellingPrice > 0 && lowestPrice > 0 && sellingPrice < sellStackAmount * lowestPrice * undercutFactor)) {
+ showWarning = true;
+ event.setCanceled(true);
+ } else if (NotEnoughUpdates.INSTANCE.config.ahTweaks.overCutWarning &&
+ (sellingPrice > 0 && lowestPrice > 0 && sellingPrice > sellStackAmount * lowestPrice * (overcutFactor + 1))) {
+ showWarning = true;
+ event.setCanceled(true);
}
- return false;
}
public void overrideIsMouseOverSlot(Slot slot, int mouseX, int mouseY, CallbackInfoReturnable<Boolean> cir) {
@@ -155,10 +184,10 @@ public class AuctionBINWarning extends GuiElement {
);
String lowestPriceStr;
- if (lowestPrice > 999) {
- lowestPriceStr = Utils.shortNumberFormat(lowestPrice, 0);
+ if (lowestPrice * sellStackAmount > 999) {
+ lowestPriceStr = Utils.shortNumberFormat(lowestPrice * sellStackAmount, 0);
} else {
- lowestPriceStr = "" + lowestPrice;
+ lowestPriceStr = "" + lowestPrice * sellStackAmount;
}
String sellingPriceStr;
@@ -174,7 +203,9 @@ public class AuctionBINWarning extends GuiElement {
width / 2, height / 2 - 45 + 25, false, 170, 0xffffffff
);
TextRenderUtils.drawStringCenteredScaledMaxWidth(
- "has a lowest BIN of \u00a76" + lowestPriceStr + "\u00a7r coins",
+ (lowestPrice > 0
+ ? "has a lowest BIN of \u00a76" + lowestPriceStr + "\u00a7r coins"
+ : "\u00a7cWarning: No lowest BIN found!"),
Minecraft.getMinecraft().fontRendererObj,
width / 2,
height / 2 - 45 + 34,
@@ -183,8 +214,14 @@ public class AuctionBINWarning extends GuiElement {
0xffa0a0a0
);
- int buyPercentage = 100 - sellingPrice * 100 / lowestPrice;
- if (buyPercentage <= 0) buyPercentage = 1;
+ if (sellingPrice > lowestPrice * sellStackAmount) {
+ buyPercentage = sellingPrice * 100 / (lowestPrice * sellStackAmount);
+ isALoss = false;
+ } else if (sellingPrice < lowestPrice * sellStackAmount) {
+ buyPercentage = 100 - sellingPrice * 100 / (lowestPrice * sellStackAmount);
+ if (buyPercentage <= 0) buyPercentage = 1;
+ isALoss = true;
+ }
TextRenderUtils.drawStringCenteredScaledMaxWidth(
"Continue selling it for",
@@ -196,7 +233,8 @@ public class AuctionBINWarning extends GuiElement {
0xffa0a0a0
);
TextRenderUtils.drawStringCenteredScaledMaxWidth(
- "\u00a76" + sellingPriceStr + "\u00a7r coins? (\u00a7c-" + buyPercentage + "%\u00a7r)",
+ "\u00a76" + sellingPriceStr + "\u00a7r coins?" +
+ (lowestPrice > 0 ? "(\u00a7" + (isALoss ? "c-" : "a+") + buyPercentage + "%\u00a7r)" : ""),
Minecraft.getMinecraft().fontRendererObj,
width / 2,
height / 2 - 45 + 59,
@@ -218,7 +256,7 @@ public class AuctionBINWarning extends GuiElement {
0xff00ff00
);
TextRenderUtils.drawStringCenteredScaledMaxWidth(
- EnumChatFormatting.RED + "[n]o",
+ EnumChatFormatting.RED + "[N]o",
Minecraft.getMinecraft().fontRendererObj,
width / 2 + 23,
height / 2 + 31,
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java
new file mode 100644
index 00000000..88ca0cc8
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionProfit.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.opengl.GL11;
+
+public class AuctionProfit {
+
+ public static final ResourceLocation auctionProfitImage =
+ new ResourceLocation("notenoughupdates:auction_profit.png");
+
+ @SubscribeEvent
+ public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) {
+ if (!inAuctionPage()) return;
+
+ Minecraft minecraft = Minecraft.getMinecraft();
+ Container inventoryContainer = minecraft.thePlayer.openContainer;
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return;
+ Gui gui = event.gui;
+ int xSize = ((AccessorGuiContainer) gui).getXSize();
+ int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) gui).getGuiTop();
+ minecraft.getTextureManager().bindTexture(auctionProfitImage);
+ GL11.glColor4f(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+ Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST);
+
+ double coinsToCollect = 0;
+ double coinsIfAllSold = 0;
+ int expiredAuctions = 0;
+ int unclaimedAuctions = 0;
+ for (ItemStack itemStack : inventoryContainer.getInventory()) {
+ boolean isBin = false;
+ if (itemStack == null || !itemStack.hasTagCompound()) continue;
+
+ NBTTagCompound tag = itemStack.getTagCompound();
+ if (tag == null) continue;
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (!display.hasKey("Lore", 9)) continue;
+ NBTTagList lore = itemStack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+
+ int coinsToCheck = 0;
+ for (int i = 0; i < lore.tagCount(); i++) {
+ String line = lore.getStringTagAt(i);
+ if (line.contains("§7Buy it now")) {
+ isBin = true;
+ String s = line.split("§7Buy it now: ")[1];
+ String coinsString = s.split("coins")[0];
+ int coins = tryParse(EnumChatFormatting.getTextWithoutFormattingCodes(coinsString.trim()));
+ if (coins != 0) {
+ coinsToCheck += coins;
+ }
+ }
+
+ if (line.contains("§7Top bid: ")) {
+ String s = line.split("§7Top bid: ")[1];
+ String coinsString = s.split("coins")[0];
+ String textWithoutFormattingCodes = EnumChatFormatting.getTextWithoutFormattingCodes(coinsString.trim());
+ int coins = tryParse(textWithoutFormattingCodes);
+ if (coins != 0) {
+ coinsToCheck += coins;
+ }
+ }
+
+ if (line.contains("§7Sold for: ")) {
+ String s = line.split("§7Sold for: ")[1];
+ String coinsString = s.split("coins")[0];
+ int coins = tryParse(EnumChatFormatting.getTextWithoutFormattingCodes(coinsString.trim()));
+ if (coins != 0) {
+ if (coins > 1000000) {
+ coins /= 1.1;
+ }
+ coinsToCollect += coins;
+ }
+ }
+
+ if (line.contains("§7Status: §aSold!") || line.contains("§7Status: §aEnded!")) {
+ if (coinsToCheck != 0) {
+ if (coinsToCheck > 1000000) {
+ coinsToCheck /= 1.1;
+ }
+ coinsToCollect += coinsToCheck;
+ coinsToCheck = 0;
+ }
+ unclaimedAuctions++;
+ } else if (line.contains("§7Status: §cExpired!")) {
+ expiredAuctions++;
+ }
+
+ if (isBin && line.contains("§7Ends in") && coinsToCheck != 0) {
+ coinsIfAllSold += coinsToCheck;
+ coinsToCheck = 0;
+ }
+
+ }
+
+ }
+ int a = guiLeft + xSize + 4;
+ String unclaimedAuctionsStr = EnumChatFormatting.DARK_GREEN.toString()
+ + unclaimedAuctions + EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY + " Unclaimed auctions";
+ String expiredAuctionsStr =
+ EnumChatFormatting.RED.toString() + expiredAuctions + EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY +
+ " Expired auctions";
+
+ FontRenderer fontRendererObj = minecraft.fontRendererObj;
+ fontRendererObj.drawString(unclaimedAuctionsStr, a + 6, guiTop + 6, -1, false);
+ fontRendererObj.drawString(expiredAuctionsStr, a + 6, guiTop + 16, -1, false);
+
+ String coinsToCollectStr =
+ EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY.toString() + "Coins to collect: " +
+ EnumChatFormatting.RESET + EnumChatFormatting.DARK_GREEN + "" +
+ StringUtils.shortNumberFormat(coinsToCollect);
+ String valueIfSoldStr = EnumChatFormatting.BOLD + EnumChatFormatting.DARK_GRAY.toString() + "Value if all sold: " +
+ EnumChatFormatting.RESET + EnumChatFormatting.DARK_GREEN + "" +
+ StringUtils.shortNumberFormat(coinsIfAllSold);
+
+ fontRendererObj.drawString(coinsToCollectStr, a + 6, guiTop + 32, -1, false);
+ fontRendererObj.drawString(valueIfSoldStr, a + 6, guiTop + 42, -1, false);
+ }
+
+ public static Integer tryParse(String s) {
+ try {
+ return Integer.parseInt(s.replace(",", ""));
+ } catch (NumberFormatException exception) {
+ return 0;
+ }
+ }
+
+ public static boolean inAuctionPage() {
+ if (!NotEnoughUpdates.INSTANCE.config.ahTweaks.enableAhSellValue
+ || !NotEnoughUpdates.INSTANCE.isOnSkyblock()) return false;
+
+ Minecraft minecraft = Minecraft.getMinecraft();
+ if (minecraft == null || minecraft.thePlayer == null) return false;
+
+ Container inventoryContainer = minecraft.thePlayer.openContainer;
+ if (!(inventoryContainer instanceof ContainerChest)) return false;
+ ContainerChest containerChest = (ContainerChest) inventoryContainer;
+ return containerChest.getLowerChestInventory().getDisplayName()
+ .getUnformattedText().equalsIgnoreCase("Manage Auctions");
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java
index 4b526185..ed05ee79 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/AuctionSortModeWarning.java
@@ -1,9 +1,28 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiChest;
@@ -21,55 +40,51 @@ public class AuctionSortModeWarning {
private boolean isAuctionBrowser() {
return NotEnoughUpdates.INSTANCE.config.ahTweaks.enableSortWarning &&
- Minecraft.getMinecraft().currentScreen instanceof GuiChest &&
- (SBInfo.getInstance().lastOpenContainerName.startsWith("Auctions Browser") ||
- SBInfo.getInstance().lastOpenContainerName.startsWith("Auctions: \""));
+ (Utils.getOpenChestName().startsWith("Auctions Browser") ||
+ Utils.getOpenChestName().startsWith("Auctions: \""));
}
public void onPostGuiRender() {
- if (isAuctionBrowser()) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
-
- ItemStack stack = chest.inventorySlots.getSlot(50).getStack();
-
- if (stack != null) {
- List<String> tooltip = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
-
- String selectedSort = null;
- for (String line : tooltip) {
- if (line.startsWith("\u00a75\u00a7o\u00a7b\u25B6 ")) {
- selectedSort = Utils.cleanColour(line.substring("\u00a75\u00a7o\u00a7b\u25B6 ".length()));
- }
- }
-
- if (selectedSort != null) {
- if (!selectedSort.trim().equals("Lowest Price")) {
- GlStateManager.disableLighting();
- GlStateManager.pushMatrix();
- GlStateManager.translate(0, 0, 500);
-
- String selectedColour = "\u00a7e";
-
- if (selectedSort.trim().equals("Highest Price")) {
- selectedColour = "\u00a7c";
- }
-
- String warningText = "\u00a7aSort: " + selectedColour + selectedSort;
- int warningLength = Minecraft.getMinecraft().fontRendererObj.getStringWidth(warningText);
-
- int centerX = chest.guiLeft + chest.xSize / 2 + 9;
- int centerY = chest.guiTop + 26;
-
- RenderUtils.drawFloatingRectDark(centerX - warningLength / 2 - 4, centerY - 6,
- warningLength + 8, 12, false
- );
- TextRenderUtils.drawStringCenteredScaledMaxWidth(warningText, Minecraft.getMinecraft().fontRendererObj,
- centerX, centerY, true, chest.width / 2, 0xffffffff
- );
- GlStateManager.popMatrix();
- }
- }
+ if (!isAuctionBrowser()) return;
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+
+ ItemStack stack = chest.inventorySlots.getSlot(50).getStack();
+
+ if (stack == null) return;
+ List<String> tooltip = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+
+ String selectedSort = null;
+ for (String line : tooltip) {
+ if (line.startsWith("\u00a75\u00a7o\u00a7b\u25B6 ")) {
+ selectedSort = Utils.cleanColour(line.substring("\u00a75\u00a7o\u00a7b\u25B6 ".length()));
}
}
+
+ if (selectedSort == null) return;
+ if (selectedSort.trim().equals("Lowest Price")) return;
+ GlStateManager.disableLighting();
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(0, 0, 500);
+
+ String selectedColour = "\u00a7e";
+
+ if (selectedSort.trim().equals("Highest Price")) {
+ selectedColour = "\u00a7c";
+ }
+
+ String warningText = "\u00a7aSort: " + selectedColour + selectedSort;
+ int warningLength = Minecraft.getMinecraft().fontRendererObj.getStringWidth(warningText);
+
+ int centerX =
+ ((AccessorGuiContainer) chest).getGuiLeft() + ((AccessorGuiContainer) chest).getXSize() / 2 + 9;
+ int centerY = ((AccessorGuiContainer) chest).getGuiTop() + 26;
+
+ RenderUtils.drawFloatingRectDark(centerX - warningLength / 2 - 4, centerY - 6,
+ warningLength + 8, 12, false
+ );
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(warningText, Minecraft.getMinecraft().fontRendererObj,
+ centerX, centerY, true, chest.width / 2, 0xffffffff
+ );
+ GlStateManager.popMatrix();
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java
index c1ce229c..ad0b238a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/BetterContainers.java
@@ -1,8 +1,28 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.renderer.GlStateManager;
@@ -18,6 +38,7 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import javax.imageio.ImageIO;
import java.awt.*;
@@ -69,7 +90,7 @@ public class BetterContainers {
public static void bindHook(TextureManager textureManager, ResourceLocation location) {
long currentMillis = System.currentTimeMillis();
- if (isChestOpen() && NEUEventListener.inventoryLoaded) {
+ if (isChestOpen() && RenderListener.inventoryLoaded) {
int invHashcode = lastInvHashcode;
if (currentMillis - lastHashcodeCheck > 50) {
@@ -544,4 +565,17 @@ public class BetterContainers {
return 0;
}
}
+
+ @SubscribeEvent
+ public void onMouseClick(SlotClickEvent event) {
+ if (!isOverriding()) return;
+ boolean isBlankStack = BetterContainers.isBlankStack(event.slot.slotNumber, event.slot.getStack());
+ if (!(isBlankStack ||
+ BetterContainers.isButtonStack(event.slot.slotNumber, event.slot.getStack()))) return;
+ clickSlot(event.slotId);
+ if (isBlankStack) {
+ event.usePickblockInstead();
+ }
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java
deleted file mode 100644
index c550ce53..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CollectionLogManager.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package io.github.moulberry.notenoughupdates.miscfeatures;
-
-import io.github.moulberry.notenoughupdates.collectionlog.CollectionConstant;
-import io.github.moulberry.notenoughupdates.util.Constants;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.multiplayer.WorldClient;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.item.EntityArmorStand;
-
-import java.util.regex.Matcher;
-
-public class CollectionLogManager {
- private static final CollectionLogManager INSTANCE = new CollectionLogManager();
-
- public static CollectionLogManager getInstance() {
- return INSTANCE;
- }
-
- public void onEntityMetadataUpdated(int entityId) {
- System.out.println("entity created:" + entityId);
- WorldClient world = Minecraft.getMinecraft().theWorld;
- if (world != null) {
- Entity entity = world.getEntityByID(entityId);
-
- if (entity instanceof EntityArmorStand && entity.hasCustomName()) {
- String customName = entity.getName();
- System.out.println("got name:" + customName);
- for (CollectionConstant.DropEntry entry : Constants.COLLECTIONLOG.dropdata) {
- System.out.println("iter entry");
- if (entry.type.equalsIgnoreCase("itemdrop")) {
- Matcher matcher = entry.regex.matcher(customName);
- if (matcher.matches()) {
- System.out.println("Match found!");
- System.out.println("Count: " + matcher.group("count"));
- System.out.println("Name: " + matcher.group("itemname"));
- } else {
- System.out.println("Doesn't match: " + customName);
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java
new file mode 100644
index 00000000..f21d0c50
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CookieWarning.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import com.google.common.collect.Lists;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiPlayerTabOverlay;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+
+public class CookieWarning {
+
+ private static boolean hasNotified;
+
+ public static void resetNotification() {
+ hasNotified = false;
+ NotificationHandler.cancelNotification();
+ }
+
+ /**
+ * Checks the tab list for a cookie timer, and sends a notification if the timer is within the tolerance
+ */
+ public static void checkCookie() {
+ if (NotEnoughUpdates.INSTANCE.config.notifications.doBoosterNotif &&
+ NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ String[] lines;
+ try {
+ lines = ((AccessorGuiPlayerTabOverlay) Minecraft.getMinecraft().ingameGUI.getTabList())
+ .getFooter()
+ .getUnformattedText()
+ .split("\n");
+ } catch (NullPointerException e) {
+ return; // if the footer is null or somehow doesn't exist, stop
+ }
+ boolean hasCookie = true;
+ String timeLine = null; // the line that contains the cookie timer
+ for (int i = 0; i < lines.length; i++) {
+ if (lines[i].startsWith("Cookie Buff")) {
+ timeLine = lines[i + 1]; // the line after the "Cookie Buff" line
+ }
+ if (lines[i].startsWith("Not active! Obtain booster cookies from the")) {
+ hasCookie = false;
+ }
+ }
+ if (!hasCookie) {
+ if (!hasNotified) {
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ "\u00a7cBooster Cookie Ran Out!",
+ "\u00a77Your Booster Cookie expired!",
+ "\u00a77",
+ "\u00a77Press X on your keyboard to close this notification"
+ ), true, true);
+ hasNotified = true;
+ }
+ return;
+ }
+ if (timeLine != null) {
+ String[] digits = timeLine.split(" ");
+ int minutes = 0;
+ try {
+ for (String digit : digits) {
+ if (digit.endsWith("y")) {
+ digit = digit.substring(0, digit.length() - 1);
+ minutes += Integer.parseInt(digit) * 525600;
+ } else if (digit.endsWith("d")) {
+ digit = digit.substring(0, digit.length() - 1);
+ minutes += Integer.parseInt(digit) * 1440;
+ } else if (digit.endsWith("h")) {
+ digit = digit.substring(0, digit.length() - 1);
+ minutes += Integer.parseInt(digit) * 60;
+ } else if (digit.endsWith("m")) {
+ digit = digit.substring(0, digit.length() - 1);
+ minutes += Integer.parseInt(digit);
+ } // ignore seconds
+ }
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED +
+ "NEU ran into an issue when retrieving the Booster Cookie Timer. Check the logs for details."));
+ hasNotified = true;
+ }
+ if (minutes < NotEnoughUpdates.INSTANCE.config.notifications.boosterCookieWarningMins && !hasNotified) {
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ "\u00a7cBooster Cookie Running Low!",
+ "\u00a77Your Booster Cookie will expire in " + timeLine,
+ "\u00a77",
+ "\u00a77Press X on your keyboard to close this notification"
+ ), true, true);
+ hasNotified = true;
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java
index 4586d190..ab9345cb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalMetalDetectorSolver.java
@@ -1,32 +1,157 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.Vec3Comparable;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
+import io.github.moulberry.notenoughupdates.util.NEUDebugLogger;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.Minecraft;
-import net.minecraft.util.*;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.util.Vec3i;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
+import java.util.stream.Collectors;
public class CrystalMetalDetectorSolver {
+ enum SolutionState {
+ NOT_STARTED,
+ MULTIPLE,
+ MULTIPLE_KNOWN,
+ FOUND,
+ FOUND_KNOWN,
+ FAILED,
+ INVALID,
+ }
+
private static final Minecraft mc = Minecraft.getMinecraft();
- private static BlockPos prevPlayerPos;
- private static double prevDistToTreasure = 0;
- private static List<BlockPos> possibleBlocks = new ArrayList<>();
- private static final List<BlockPos> locations = new ArrayList<>();
- private static Boolean chestRecentlyFound = false;
- private static long chestLastFoundMillis = 0;
+ private static Vec3Comparable prevPlayerPos;
+ private static double prevDistToTreasure;
+ private static HashSet<BlockPos> possibleBlocks = new HashSet<>();
+ private static final HashMap<Vec3Comparable, Double> evaluatedPlayerPositions = new HashMap<>();
+ private static boolean chestRecentlyFound;
+ private static long chestLastFoundMillis;
+ private static final HashSet<BlockPos> openedChestPositions = new HashSet<>();
+
+ // Keeper and Mines of Divan center location info
+ private static Vec3i minesCenter;
+ private static boolean debugDoNotUseCenter = false;
+ private static boolean visitKeeperMessagePrinted;
+ private static final String KEEPER_OF_STRING = "Keeper of ";
+ private static final String DIAMOND_STRING = "diamond";
+ private static final String LAPIS_STRING = "lapis";
+ private static final String EMERALD_STRING = "emerald";
+ private static final String GOLD_STRING = "gold";
+ private static final HashMap<String, Vec3i> keeperOffsets = new HashMap<String, Vec3i>() {{
+ put(DIAMOND_STRING, new Vec3i(33, 0, 3));
+ put(LAPIS_STRING, new Vec3i(-33, 0, -3));
+ put(EMERALD_STRING, new Vec3i(-3, 0, 33));
+ put(GOLD_STRING, new Vec3i(3, 0, -33));
+ }};
+
+ // Chest offsets from center
+ private static final HashSet<Long> knownChestOffsets = new HashSet<>(Arrays.asList(
+ -10171958951910L, // x=-38, y=-22, z=26
+ 10718829084646L, // x=38, y=-22, z=-26
+ -10721714765806L, // x=-40, y=-22, z=18
+ -10996458455018L, // x=-41, y=-20, z=22
+ -1100920913904L, // x=-5, y=-21, z=16
+ 11268584898530L, // x=40, y=-22, z=-30
+ -11271269253148L, // x=-42, y=-20, z=-28
+ -11546281377832L, // x=-43, y=-22, z=-40
+ 11818542038999L, // x=42, y=-19, z=-41
+ 12093285728240L, // x=43, y=-21, z=-16
+ -1409286164L, // x=-1, y=-22, z=-20
+ 1922736062492L, // x=6, y=-21, z=28
+ 2197613969419L, // x=7, y=-21, z=11
+ 2197613969430L, // x=7, y=-21, z=22
+ -3024999153708L, // x=-12, y=-21, z=-44
+ 3571936395295L, // x=12, y=-22, z=31
+ 3572003504106L, // x=12, y=-22, z=-22
+ 3572003504135L, // x=12, y=-21, z=7
+ 3572070612949L, // x=12, y=-21, z=-43
+ -3574822076373L, // x=-14, y=-21, z=43
+ -3574822076394L, // x=-14, y=-21, z=22
+ -4399455797228L, // x=-17, y=-21, z=20
+ -5224156626944L, // x=-20, y=-22, z=0
+ 548346527764L, // x=1, y=-21, z=20
+ 5496081743901L, // x=19, y=-22, z=29
+ 5770959650816L, // x=20, y=-22, z=0
+ 5771093868518L, // x=20, y=-21, z=-26
+ -6048790347736L, // x=-23, y=-22, z=40
+ 6320849682418L, // x=22, y=-21, z=-14
+ -6323668254708L, // x=-24, y=-22, z=12
+ 6595593371674L, // x=23, y=-22, z=26
+ 6595660480473L, // x=23, y=-22, z=-39
+ 6870471278619L, // x=24, y=-22, z=27
+ 7145349185553L, // x=25, y=-22, z=17
+ 8244995030996L, // x=29, y=-21, z=-44
+ -8247679385612L, // x=-31, y=-21, z=-12
+ -8247679385640L, // x=-31, y=-21, z=-40
+ 8519872937959L, // x=30, y=-21, z=-25
+ -8522557292584L, // x=-32, y=-21, z=-40
+ -9622068920278L, // x=-36, y=-20, z=42
+ -9896946827278L, // x=-37, y=-21, z=-14
+ -9896946827286L // x=-37, y=-21, z=-22
+ ));
+
+ static Predicate<BlockPos> treasureAllowedPredicate = CrystalMetalDetectorSolver::treasureAllowed;
+ static SolutionState currentState = SolutionState.NOT_STARTED;
+ static SolutionState previousState = SolutionState.NOT_STARTED;
+
+ public interface Predicate<BlockPos> {
+ boolean check(BlockPos blockPos);
+ }
public static void process(IChatComponent message) {
+ if (SBInfo.getInstance().getLocation() == null ||
+ !NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled ||
+ !SBInfo.getInstance().getLocation().equals("crystal_hollows") ||
+ !message.getUnformattedText().contains("TREASURE: ")) {
+ return;
+ }
+
+ boolean centerNewlyDiscovered = locateMinesCenterIfNeeded();
+
+ double distToTreasure = Double.parseDouble(message
+ .getUnformattedText()
+ .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", ""));
+
// Delay to keep old chest location from being treated as the new chest location
if (chestRecentlyFound) {
long currentTimeMillis = System.currentTimeMillis();
if (chestLastFoundMillis == 0) {
chestLastFoundMillis = currentTimeMillis;
return;
- } else if (currentTimeMillis - chestLastFoundMillis < 1000) {
+ } else if (currentTimeMillis - chestLastFoundMillis < 1000 && distToTreasure < 5.0) {
return;
}
@@ -34,80 +159,185 @@ public class CrystalMetalDetectorSolver {
chestRecentlyFound = false;
}
- if (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("crystal_hollows")
- && message.getUnformattedText().contains("TREASURE: ")) {
- double distToTreasure = Double.parseDouble(message
- .getUnformattedText()
- .split("TREASURE: ")[1].split("m")[0].replaceAll("(?!\\.)\\D", ""));
- if (NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled && prevDistToTreasure == distToTreasure &&
- prevPlayerPos.getX() == mc.thePlayer.getPosition().getX() &&
- prevPlayerPos.getY() == mc.thePlayer.getPosition().getY() &&
- prevPlayerPos.getZ() == mc.thePlayer.getPosition().getZ() && !locations.contains(mc.thePlayer.getPosition())) {
- if (possibleBlocks.size() == 0) {
- locations.add(mc.thePlayer.getPosition());
- for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) {
- for (int y = 65; y <= 75; y++) {
- double calculatedDist = 0;
- int xOffset = 0;
- while (calculatedDist < distToTreasure) {
- BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) + xOffset,
- y, Math.floor(mc.thePlayer.posZ) + zOffset
- );
- calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D));
- if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) &&
- treasureAllowed(pos) && mc.theWorld.
- getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) {
- possibleBlocks.add(pos);
- }
- xOffset++;
- }
- xOffset = 0;
- calculatedDist = 0;
- while (calculatedDist < distToTreasure) {
- BlockPos pos = new BlockPos(Math.floor(mc.thePlayer.posX) - xOffset,
- y, Math.floor(mc.thePlayer.posZ) + zOffset
- );
- calculatedDist = getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D));
- if (round(calculatedDist, 1) == distToTreasure && !possibleBlocks.contains(pos) &&
- treasureAllowed(pos) && mc.theWorld.
- getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air")) {
- possibleBlocks.add(pos);
- }
- xOffset++;
+ SolutionState originalState = currentState;
+ int originalCount = possibleBlocks.size();
+ Vec3Comparable adjustedPlayerPos = getPlayerPosAdjustedForEyeHeight();
+ findPossibleSolutions(distToTreasure, adjustedPlayerPos, centerNewlyDiscovered);
+ if (currentState != originalState || originalCount != possibleBlocks.size()) {
+ switch (currentState) {
+ case FOUND_KNOWN:
+ NEUDebugLogger.log(NEUDebugFlag.METAL, "Known location identified.");
+ // falls through
+ case FOUND:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Found solution."));
+ if (NEUDebugFlag.METAL.isSet() &&
+ (previousState == SolutionState.INVALID || previousState == SolutionState.FAILED)) {
+ NEUDebugLogger.log(
+ NEUDebugFlag.METAL,
+ EnumChatFormatting.AQUA + "Solution coordinates: " +
+ EnumChatFormatting.WHITE + possibleBlocks.iterator().next().toString()
+ );
+ }
+ break;
+ case INVALID:
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "[NEU] Previous solution is invalid."));
+ logDiagnosticData(false);
+ resetSolution(false);
+ break;
+ case FAILED:
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "[NEU] Failed to find a solution."));
+ logDiagnosticData(false);
+ resetSolution(false);
+ break;
+ case MULTIPLE_KNOWN:
+ NEUDebugLogger.log(NEUDebugFlag.METAL, "Multiple known locations identified:");
+ // falls through
+ case MULTIPLE:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Need another position to find solution. Possible blocks: " + possibleBlocks.size()));
+ break;
+ default:
+ throw new IllegalStateException("Metal detector is in invalid state");
+ }
+ }
+ }
+
+ static void findPossibleSolutions(double distToTreasure, Vec3Comparable playerPos, boolean centerNewlyDiscovered) {
+ if (prevDistToTreasure == distToTreasure && prevPlayerPos.equals(playerPos) &&
+ !evaluatedPlayerPositions.containsKey(playerPos)) {
+ evaluatedPlayerPositions.put(playerPos, distToTreasure);
+ if (possibleBlocks.size() == 0) {
+ for (int zOffset = (int) Math.floor(-distToTreasure); zOffset <= Math.ceil(distToTreasure); zOffset++) {
+ for (int y = 65; y <= 75; y++) {
+ double calculatedDist = 0;
+ int xOffset = 0;
+ while (calculatedDist < distToTreasure) {
+ BlockPos pos = new BlockPos(Math.floor(playerPos.xCoord) + xOffset,
+ y, Math.floor(playerPos.zCoord) + zOffset
+ );
+ calculatedDist = playerPos.distanceTo(new Vec3Comparable(pos).addVector(0D, 1D, 0D));
+ if (round(calculatedDist, 1) == distToTreasure && treasureAllowedPredicate.check(pos)) {
+ possibleBlocks.add(pos);
}
+ xOffset++;
}
- }
- sendMessage();
- } else if (possibleBlocks.size() != 1) {
- locations.add(mc.thePlayer.getPosition());
- List<BlockPos> temp = new ArrayList<>();
- for (BlockPos pos : possibleBlocks) {
- if (round(getPlayerPos().distanceTo(new Vec3(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) {
- temp.add(pos);
+ xOffset = 0;
+ calculatedDist = 0;
+ while (calculatedDist < distToTreasure) {
+ BlockPos pos = new BlockPos(Math.floor(playerPos.xCoord) - xOffset,
+ y, Math.floor(playerPos.zCoord) + zOffset
+ );
+ calculatedDist = playerPos.distanceTo(new Vec3Comparable(pos).addVector(0D, 1D, 0D));
+ if (round(calculatedDist, 1) == distToTreasure && treasureAllowedPredicate.check(pos)) {
+ possibleBlocks.add(pos);
+ }
+ xOffset++;
}
}
- possibleBlocks = temp;
- sendMessage();
- } else {
- BlockPos pos = possibleBlocks.get(0);
- if (Math.abs(distToTreasure - (getPlayerPos().distanceTo(new Vec3(pos)))) > 5) {
- mc.thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.RED + "[NEU] Previous solution is invalid."));
- reset(false);
+ }
+
+ updateSolutionState();
+ } else if (possibleBlocks.size() != 1) {
+ HashSet<BlockPos> temp = new HashSet<>();
+ for (BlockPos pos : possibleBlocks) {
+ if (round(playerPos.distanceTo(new Vec3Comparable(pos).addVector(0D, 1D, 0D)), 1) == distToTreasure) {
+ temp.add(pos);
}
}
+ possibleBlocks = temp;
+ updateSolutionState();
+ } else {
+ BlockPos pos = possibleBlocks.iterator().next();
+ if (Math.abs(distToTreasure - (playerPos.distanceTo(new Vec3Comparable(pos)))) > 5) {
+ currentState = SolutionState.INVALID;
+ }
+ }
+ } else if (centerNewlyDiscovered && possibleBlocks.size() > 1) {
+ updateSolutionState();
+ }
+
+ prevPlayerPos = playerPos;
+ prevDistToTreasure = distToTreasure;
+ }
+
+ public static void setDebugDoNotUseCenter(boolean val) {
+ debugDoNotUseCenter = val;
+ }
+
+ private static String getFriendlyBlockPositions(Collection<BlockPos> positions) {
+ if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || positions.size() == 0) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ for (BlockPos blockPos : positions) {
+ sb.append("Absolute: ");
+ sb.append(blockPos.toString());
+ if (minesCenter != Vec3i.NULL_VECTOR) {
+ BlockPos relativeOffset = blockPos.subtract(minesCenter);
+ sb.append(", Relative: ");
+ sb.append(relativeOffset.toString());
+ sb.append(" (" + relativeOffset.toLong() + ")");
+ }
+ sb.append("\n");
+ }
+
+ return sb.toString();
+ }
+
+ private static String getFriendlyEvaluatedPositions() {
+ if (!NEUDebugLogger.isFlagEnabled(NEUDebugFlag.METAL) || evaluatedPlayerPositions.size() == 0) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append("\n");
+ for (Vec3Comparable vec : evaluatedPlayerPositions.keySet()) {
+ sb.append("Absolute: " + vec.toString());
+ if (minesCenter != Vec3i.NULL_VECTOR) {
+ BlockPos positionBlockPos = new BlockPos(vec);
+ BlockPos relativeOffset = positionBlockPos.subtract(minesCenter);
+ sb.append(", Relative: " + relativeOffset.toString() + " (" + relativeOffset.toLong() + ")");
}
- prevPlayerPos = mc.thePlayer.getPosition();
- prevDistToTreasure = distToTreasure;
+ sb.append(" Distance: ");
+ sb.append(evaluatedPlayerPositions.get(vec));
+
+ sb.append("\n");
}
+
+ return sb.toString();
}
- public static void reset(Boolean chestFound) {
+ public static void resetSolution(Boolean chestFound) {
+ if (chestFound) {
+ prevPlayerPos = null;
+ prevDistToTreasure = 0;
+ if (possibleBlocks.size() == 1) {
+ openedChestPositions.add(possibleBlocks.iterator().next().getImmutable());
+ }
+ }
+
chestRecentlyFound = chestFound;
possibleBlocks.clear();
- locations.clear();
+ evaluatedPlayerPositions.clear();
+ previousState = currentState;
+ currentState = SolutionState.NOT_STARTED;
+ }
+
+ public static void initWorld() {
+ minesCenter = Vec3i.NULL_VECTOR;
+ visitKeeperMessagePrinted = false;
+ openedChestPositions.clear();
+ chestLastFoundMillis = 0;
+ prevDistToTreasure = 0;
+ prevPlayerPos = null;
+ currentState = SolutionState.NOT_STARTED;
+ resetSolution(false);
}
public static void render(float partialTicks) {
@@ -117,10 +347,10 @@ public class CrystalMetalDetectorSolver {
SBInfo.getInstance().location.equals("Mines of Divan")) {
if (possibleBlocks.size() == 1) {
- BlockPos block = possibleBlocks.get(0);
+ BlockPos block = possibleBlocks.iterator().next();
RenderUtils.renderBeaconBeam(block.add(0, 1, 0), beaconRGB, 1.0f, partialTicks);
- RenderUtils.renderWayPoint("Treasure", possibleBlocks.get(0).add(0, 2.5, 0), partialTicks);
+ RenderUtils.renderWayPoint("Treasure", possibleBlocks.iterator().next().add(0, 2.5, 0), partialTicks);
} else if (possibleBlocks.size() > 1 && NotEnoughUpdates.INSTANCE.config.mining.metalDetectorShowPossible) {
for (BlockPos block : possibleBlocks) {
RenderUtils.renderBeaconBeam(block.add(0, 1, 0), beaconRGB, 1.0f, partialTicks);
@@ -130,33 +360,106 @@ public class CrystalMetalDetectorSolver {
}
}
+ private static boolean locateMinesCenterIfNeeded() {
+ if (minesCenter != Vec3i.NULL_VECTOR) {
+ return false;
+ }
+
+ List<EntityArmorStand> keeperEntities = mc.theWorld.getEntities(EntityArmorStand.class, (entity) -> {
+ if (!entity.hasCustomName()) return false;
+ return entity.getCustomNameTag().contains(KEEPER_OF_STRING);
+ });
+
+ if (keeperEntities.size() == 0) {
+ if (!visitKeeperMessagePrinted) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Approach a Keeper while holding the metal detector to enable faster treasure hunting."));
+ visitKeeperMessagePrinted = true;
+ }
+ return false;
+ }
+
+ EntityArmorStand keeperEntity = keeperEntities.get(0);
+ String keeperName = keeperEntity.getCustomNameTag();
+ NEUDebugLogger.log(NEUDebugFlag.METAL, "Locating center using Keeper: " +
+ EnumChatFormatting.WHITE + keeperEntity);
+ String keeperType = keeperName.substring(keeperName.indexOf(KEEPER_OF_STRING) + KEEPER_OF_STRING.length());
+ minesCenter = keeperEntity.getPosition().add(keeperOffsets.get(keeperType.toLowerCase()));
+ NEUDebugLogger.log(NEUDebugFlag.METAL, "Mines center: " +
+ EnumChatFormatting.WHITE + minesCenter.toString());
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] Faster treasure hunting is now enabled based on Keeper location."));
+ return true;
+ }
+
+ public static void setMinesCenter(BlockPos center) {
+ minesCenter = center;
+ }
+
private static double round(double value, int precision) {
int scale = (int) Math.pow(10, precision);
return (double) Math.round(value * scale) / scale;
}
- private static void sendMessage() {
- if (possibleBlocks.size() > 1) {
- mc.thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.YELLOW + "[NEU] Need another position to find solution. Possible blocks: "
- + possibleBlocks.size()));
- } else if (possibleBlocks.size() == 0) {
- mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Failed to find solution."));
- reset(false);
- } else {
- mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Found solution."));
+ private static void updateSolutionState() {
+ previousState = currentState;
+
+ if (possibleBlocks.size() == 0) {
+ currentState = SolutionState.FAILED;
+ return;
+ }
+
+ if (possibleBlocks.size() == 1) {
+ currentState = SolutionState.FOUND;
+ return;
+ }
+
+ // Narrow solutions using known locations if the mines center is known
+ if (minesCenter.equals(BlockPos.NULL_VECTOR) || debugDoNotUseCenter) {
+ currentState = SolutionState.MULTIPLE;
+ return;
+ }
+
+ HashSet<BlockPos> temp =
+ possibleBlocks.stream()
+ .filter(block -> knownChestOffsets.contains(block.subtract(minesCenter).toLong()))
+ .collect(Collectors.toCollection(HashSet::new));
+ if (temp.size() == 0) {
+ currentState = SolutionState.MULTIPLE;
+ return;
}
+
+ if (temp.size() == 1) {
+ possibleBlocks = temp;
+ currentState = SolutionState.FOUND_KNOWN;
+ return;
+
+ }
+
+ currentState = SolutionState.MULTIPLE_KNOWN;
}
- private static Vec3 getPlayerPos() {
- return new Vec3(
+ public static BlockPos getSolution() {
+ if (CrystalMetalDetectorSolver.possibleBlocks.size() != 1) {
+ return BlockPos.ORIGIN;
+ }
+
+ return CrystalMetalDetectorSolver.possibleBlocks.stream().iterator().next();
+ }
+
+ private static Vec3Comparable getPlayerPosAdjustedForEyeHeight() {
+ return new Vec3Comparable(
mc.thePlayer.posX,
mc.thePlayer.posY + (mc.thePlayer.getEyeHeight() - mc.thePlayer.getDefaultEyeHeight()),
mc.thePlayer.posZ
);
}
- private static boolean treasureAllowed(BlockPos pos) {
+ static boolean isKnownOffset(BlockPos pos) {
+ return knownChestOffsets.contains(pos.subtract(minesCenter).toLong());
+ }
+
+ static boolean isAllowedBlockType(BlockPos pos) {
return mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:gold_block") ||
mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:prismarine") ||
mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:chest") ||
@@ -165,4 +468,106 @@ public class CrystalMetalDetectorSolver {
mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:wool") ||
mc.theWorld.getBlockState(pos).getBlock().getRegistryName().equals("minecraft:stained_hardened_clay");
}
+
+ static boolean isAirAbove(BlockPos pos) {
+ return mc.theWorld.
+ getBlockState(pos.add(0, 1, 0)).getBlock().getRegistryName().equals("minecraft:air");
+ }
+
+ private static boolean treasureAllowed(BlockPos pos) {
+ boolean airAbove = isAirAbove(pos);
+ boolean allowedBlockType = isAllowedBlockType(pos);
+ return isKnownOffset(pos) || (airAbove && allowedBlockType);
+ }
+
+ static private String getDiagnosticMessage() {
+ StringBuilder diagsMessage = new StringBuilder();
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Mines Center: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((minesCenter.equals(Vec3i.NULL_VECTOR)) ? "<NOT DISCOVERED>" : minesCenter.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Current Solution State: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(currentState.name());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Previous Solution State: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(previousState.name());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Previous Player Position: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((prevPlayerPos == null) ? "<NONE>" : prevPlayerPos.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Previous Distance To Treasure: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((prevDistToTreasure == 0) ? "<NONE>" : prevDistToTreasure);
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Current Possible Blocks: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(possibleBlocks.size());
+ diagsMessage.append(getFriendlyBlockPositions(possibleBlocks));
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Evaluated player positions: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(evaluatedPlayerPositions.size());
+ diagsMessage.append(getFriendlyEvaluatedPositions());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Chest locations not on known list:\n");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ if (minesCenter != Vec3i.NULL_VECTOR) {
+ HashSet<BlockPos> locationsNotOnKnownList = openedChestPositions
+ .stream()
+ .filter(block -> !knownChestOffsets.contains(block.subtract(minesCenter).toLong()))
+ .map(block -> block.subtract(minesCenter))
+ .collect(Collectors.toCollection(HashSet::new));
+ if (locationsNotOnKnownList.size() > 0) {
+ for (BlockPos blockPos : locationsNotOnKnownList) {
+ diagsMessage.append(String.format(
+ "%dL,\t\t// x=%d, y=%d, z=%d",
+ blockPos.toLong(),
+ blockPos.getX(),
+ blockPos.getY(),
+ blockPos.getZ()
+ ));
+ }
+ }
+ } else {
+ diagsMessage.append("<REQUIRES MINES CENTER>");
+ }
+
+ return diagsMessage.toString();
+ }
+
+ public static void logDiagnosticData(boolean outputAlways) {
+ if (!SBInfo.getInstance().checkForSkyblockLocation()) {
+ return;
+ }
+
+ if (!NotEnoughUpdates.INSTANCE.config.mining.metalDetectorEnabled) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Metal Detector Solver is not enabled."));
+ return;
+ }
+
+ boolean metalDebugFlagSet = NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(NEUDebugFlag.METAL);
+ if (outputAlways || metalDebugFlagSet) {
+ NEUDebugLogger.logAlways(getDiagnosticMessage());
+ }
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java
index 2b095c42..c0653742 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java
new file mode 100644
index 00000000..0ee29b4f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalWishingCompassSolver.java
@@ -0,0 +1,1108 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.Line;
+import io.github.moulberry.notenoughupdates.core.util.Vec3Comparable;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
+import io.github.moulberry.notenoughupdates.util.NEUDebugLogger;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.EnumParticleTypes;
+import net.minecraft.util.Vec3i;
+import net.minecraftforge.client.ClientCommandHandler;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.function.BooleanSupplier;
+import java.util.function.LongSupplier;
+
+public class CrystalWishingCompassSolver {
+ enum SolverState {
+ NOT_STARTED,
+ PROCESSING_FIRST_USE,
+ NEED_SECOND_COMPASS,
+ PROCESSING_SECOND_USE,
+ SOLVED,
+ FAILED_EXCEPTION,
+ FAILED_TIMEOUT_NO_REPEATING,
+ FAILED_TIMEOUT_NO_PARTICLES,
+ FAILED_INTERSECTION_CALCULATION,
+ FAILED_INVALID_SOLUTION,
+ }
+
+ enum CompassTarget {
+ GOBLIN_QUEEN,
+ GOBLIN_KING,
+ BAL,
+ JUNGLE_TEMPLE,
+ ODAWA,
+ PRECURSOR_CITY,
+ MINES_OF_DIVAN,
+ CRYSTAL_NUCLEUS,
+ }
+
+ enum Crystal {
+ AMBER,
+ AMETHYST,
+ JADE,
+ SAPPHIRE,
+ TOPAZ,
+ }
+
+ enum HollowsZone {
+ CRYSTAL_NUCLEUS,
+ JUNGLE,
+ MITHRIL_DEPOSITS,
+ GOBLIN_HOLDOUT,
+ PRECURSOR_REMNANTS,
+ MAGMA_FIELDS,
+ }
+
+ private static final CrystalWishingCompassSolver INSTANCE = new CrystalWishingCompassSolver();
+
+ public static CrystalWishingCompassSolver getInstance() {
+ return INSTANCE;
+ }
+
+ private static final Minecraft mc = Minecraft.getMinecraft();
+ private static boolean isSkytilsPresent = false;
+ private static final ArrayDeque<ParticleData> seenParticles = new ArrayDeque<>();
+
+ // There is a small set of breakable blocks above the nucleus at Y > 181. While this zone is reported
+ // as the Crystal Nucleus by Hypixel, for wishing compass purposes it is in the appropriate quadrant.
+ private static final AxisAlignedBB NUCLEUS_BB = new AxisAlignedBB(462, 63, 461, 564, 181, 565);
+ // Bounding box around all breakable blocks in the crystal hollows, appears as bedrock in-game
+ private static final AxisAlignedBB HOLLOWS_BB = new AxisAlignedBB(201, 30, 201, 824, 189, 824);
+
+ // Zone bounding boxes
+ private static final AxisAlignedBB PRECURSOR_REMNANTS_BB = new AxisAlignedBB(512, 63, 512, 824, 189, 824);
+ private static final AxisAlignedBB MITHRIL_DEPOSITS_BB = new AxisAlignedBB(512, 63, 201, 824, 189, 513);
+ private static final AxisAlignedBB GOBLIN_HOLDOUT_BB = new AxisAlignedBB(201, 63, 512, 513, 189, 824);
+ private static final AxisAlignedBB JUNGLE_BB = new AxisAlignedBB(201, 63, 201, 513, 189, 513);
+ private static final AxisAlignedBB MAGMA_FIELDS_BB = new AxisAlignedBB(201, 30, 201, 824, 64, 824);
+
+ // Structure bounding boxes (size + 2 in each dimension to make it an actual bounding box)
+ private static final AxisAlignedBB PRECURSOR_CITY_BB = new AxisAlignedBB(0, 0, 0, 107, 122, 107);
+ private static final AxisAlignedBB GOBLIN_KING_BB = new AxisAlignedBB(0, 0, 0, 59, 53, 56);
+ private static final AxisAlignedBB GOBLIN_QUEEN_BB = new AxisAlignedBB(0, 0, 0, 108, 114, 108);
+ private static final AxisAlignedBB JUNGLE_TEMPLE_BB = new AxisAlignedBB(0, 0, 0, 108, 120, 108);
+ private static final AxisAlignedBB ODAWA_BB = new AxisAlignedBB(0, 0, 0, 53, 46, 54);
+ private static final AxisAlignedBB MINES_OF_DIVAN_BB = new AxisAlignedBB(0, 0, 0, 108, 125, 108);
+ private static final AxisAlignedBB KHAZAD_DUM_BB = new AxisAlignedBB(0, 0, 0, 110, 46, 108);
+
+ private static final Vec3Comparable JUNGLE_DOOR_OFFSET_FROM_CRYSTAL = new Vec3Comparable(-57, 36, -21);
+
+ private static final double MAX_DISTANCE_BETWEEN_PARTICLES = 0.6;
+ private static final double MAX_DISTANCE_FROM_USE_TO_FIRST_PARTICLE = 9.0;
+
+ // 64.0 is an arbitrary value but seems to work well
+ private static final double MINIMUM_DISTANCE_SQ_BETWEEN_COMPASSES = 64.0;
+
+ // All particles typically arrive in < 3500, so 5000 should be enough buffer
+ public static final long ALL_PARTICLES_MAX_MILLIS = 5000L;
+
+ public LongSupplier currentTimeMillis = System::currentTimeMillis;
+ public BooleanSupplier kingsScentPresent = this::isKingsScentPresent;
+ public BooleanSupplier keyInInventory = this::isKeyInInventory;
+
+ public interface CrystalEnumSetSupplier {
+ EnumSet<Crystal> getAsCrystalEnumSet();
+ }
+
+ public CrystalEnumSetSupplier foundCrystals = this::getFoundCrystals;
+
+ private SolverState solverState;
+ private Compass firstCompass;
+ private Compass secondCompass;
+ private Line solutionIntersectionLine;
+ private EnumSet<CompassTarget> possibleTargets;
+ private Vec3Comparable solution;
+ private Vec3Comparable originalSolution;
+ private EnumSet<CompassTarget> solutionPossibleTargets;
+
+ public SolverState getSolverState() {
+ return solverState;
+ }
+
+ public Vec3i getSolutionCoords() {
+ return new Vec3i(solution.xCoord, solution.yCoord, solution.zCoord);
+ }
+
+ public EnumSet<CompassTarget> getPossibleTargets() {
+ return possibleTargets;
+ }
+
+ public static HollowsZone getZoneForCoords(BlockPos blockPos) {
+ return getZoneForCoords(new Vec3Comparable(blockPos));
+ }
+
+ public static HollowsZone getZoneForCoords(Vec3Comparable coords) {
+ if (NUCLEUS_BB.isVecInside(coords)) return HollowsZone.CRYSTAL_NUCLEUS;
+ if (JUNGLE_BB.isVecInside(coords)) return HollowsZone.JUNGLE;
+ if (MITHRIL_DEPOSITS_BB.isVecInside(coords)) return HollowsZone.MITHRIL_DEPOSITS;
+ if (GOBLIN_HOLDOUT_BB.isVecInside(coords)) return HollowsZone.GOBLIN_HOLDOUT;
+ if (PRECURSOR_REMNANTS_BB.isVecInside(coords)) return HollowsZone.PRECURSOR_REMNANTS;
+ if (MAGMA_FIELDS_BB.isVecInside(coords)) return HollowsZone.MAGMA_FIELDS;
+ throw new IllegalArgumentException("Coordinates do not fall in known zone: " + coords.toString());
+ }
+
+ private void resetForNewTarget() {
+ NEUDebugLogger.log(NEUDebugFlag.WISHING, "Resetting for new target");
+ solverState = SolverState.NOT_STARTED;
+ firstCompass = null;
+ secondCompass = null;
+ solutionIntersectionLine = null;
+ possibleTargets = null;
+ solution = null;
+ originalSolution = null;
+ solutionPossibleTargets = null;
+ }
+
+ public void initWorld() {
+ resetForNewTarget();
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Unload event) {
+ initWorld();
+ isSkytilsPresent = Loader.isModLoaded("skytils");
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver ||
+ SBInfo.getInstance().getLocation() == null ||
+ !SBInfo.getInstance().getLocation().equals("crystal_hollows") ||
+ event.entityPlayer != mc.thePlayer ||
+ (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_AIR &&
+ event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK)
+ ) {
+ return;
+ }
+
+ ItemStack heldItem = event.entityPlayer.getHeldItem();
+ if (heldItem == null || heldItem.getItem() != Items.skull) {
+ return;
+ }
+
+ String heldInternalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(heldItem);
+ if (heldInternalName == null || !heldInternalName.equals("WISHING_COMPASS")) {
+ return;
+ }
+
+ BlockPos playerPos = mc.thePlayer.getPosition().getImmutable();
+
+ try {
+ HandleCompassResult result = handleCompassUse(playerPos);
+ switch (result) {
+ case SUCCESS:
+ return;
+ case STILL_PROCESSING_PRIOR_USE:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Wait a little longer before using the wishing compass again."));
+ event.setCanceled(true);
+ break;
+ case LOCATION_TOO_CLOSE:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Move a little further before using the wishing compass again."));
+ event.setCanceled(true);
+ break;
+ case POSSIBLE_TARGETS_CHANGED:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Possible wishing compass targets have changed. Solver has been reset."));
+ event.setCanceled(true);
+ break;
+ case NO_PARTICLES_FOR_PREVIOUS_COMPASS:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] No particles detected for prior compass use. Need another position to solve."));
+ break;
+ case PLAYER_IN_NUCLEUS:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Wishing compass must be used outside the nucleus for accurate results."));
+ event.setCanceled(true);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected wishing compass solver state: \n" + getDiagnosticMessage());
+ }
+ } catch (Exception e) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Error processing wishing compass action - see log for details"));
+ e.printStackTrace();
+ event.setCanceled(true);
+ solverState = SolverState.FAILED_EXCEPTION;
+ }
+ }
+
+ public HandleCompassResult handleCompassUse(BlockPos playerPos) {
+ long lastCompassUsedMillis = 0;
+ switch (solverState) {
+ case PROCESSING_SECOND_USE:
+ if (secondCompass != null) {
+ lastCompassUsedMillis = secondCompass.whenUsedMillis;
+ }
+ case PROCESSING_FIRST_USE:
+ if (lastCompassUsedMillis == 0 && firstCompass != null) {
+ lastCompassUsedMillis = firstCompass.whenUsedMillis;
+ }
+ if (lastCompassUsedMillis != 0 &&
+ (currentTimeMillis.getAsLong() > lastCompassUsedMillis + ALL_PARTICLES_MAX_MILLIS)) {
+ return HandleCompassResult.NO_PARTICLES_FOR_PREVIOUS_COMPASS;
+ }
+
+ return HandleCompassResult.STILL_PROCESSING_PRIOR_USE;
+ case SOLVED:
+ case FAILED_EXCEPTION:
+ case FAILED_TIMEOUT_NO_REPEATING:
+ case FAILED_TIMEOUT_NO_PARTICLES:
+ case FAILED_INTERSECTION_CALCULATION:
+ case FAILED_INVALID_SOLUTION:
+ resetForNewTarget();
+ // falls through, NOT_STARTED is the state when resetForNewTarget returns
+ case NOT_STARTED:
+ if (NUCLEUS_BB.isVecInside(new Vec3Comparable(playerPos.getX(), playerPos.getY(), playerPos.getZ()))) {
+ return HandleCompassResult.PLAYER_IN_NUCLEUS;
+ }
+
+ firstCompass = new Compass(playerPos, currentTimeMillis.getAsLong());
+ seenParticles.clear();
+ solverState = SolverState.PROCESSING_FIRST_USE;
+ possibleTargets = calculatePossibleTargets(playerPos);
+ return HandleCompassResult.SUCCESS;
+ case NEED_SECOND_COMPASS:
+ if (firstCompass.whereUsed.distanceSq(playerPos) < MINIMUM_DISTANCE_SQ_BETWEEN_COMPASSES) {
+ return HandleCompassResult.LOCATION_TOO_CLOSE;
+ }
+
+ HollowsZone firstCompassZone = getZoneForCoords(firstCompass.whereUsed);
+ HollowsZone playerZone = getZoneForCoords(playerPos);
+ if (!possibleTargets.equals(calculatePossibleTargets(playerPos)) ||
+ firstCompassZone != playerZone) {
+ resetForNewTarget();
+ return HandleCompassResult.POSSIBLE_TARGETS_CHANGED;
+ }
+
+ secondCompass = new Compass(playerPos, currentTimeMillis.getAsLong());
+ solverState = SolverState.PROCESSING_SECOND_USE;
+ return HandleCompassResult.SUCCESS;
+ }
+
+ throw new IllegalStateException("Unexpected compass state");
+ }
+
+ /*
+ * Processes particles if the wishing compass was used within the last 5 seconds.
+ *
+ * The first and the last particles are used to create a line for each wishing compass
+ * use that is then used to calculate the target.
+ *
+ * Once two lines have been calculated, the shortest line between the two is calculated
+ * with the midpoint on that line being the wishing compass target. The accuracy of this
+ * seems to be very high.
+ *
+ * The target location varies based on various criteria, including, but not limited to:
+ * Topaz Crystal (Khazad-dûm) Magma Fields
+ * Odawa (Jungle Village) Jungle w/no Jungle Key in inventory
+ * Amethyst Crystal (Jungle Temple) Jungle w/Jungle Key in inventory
+ * Sapphire Crystal (Lost Precursor City) Precursor Remnants
+ * Jade Crystal (Mines of Divan) Mithril Deposits
+ * King Yolkar Goblin Holdout without "King's Scent I" effect
+ * Goblin Queen Goblin Holdout with "King's Scent I" effect
+ * Crystal Nucleus All Crystals found and none placed
+ * per-area structure missing, or because Hypixel.
+ * Always within 1 block of X=513 Y=106 Z=551.
+ */
+ public void onSpawnParticle(
+ EnumParticleTypes particleType,
+ double x,
+ double y,
+ double z
+ ) {
+ if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver ||
+ particleType != EnumParticleTypes.VILLAGER_HAPPY ||
+ !SBInfo.getInstance().getLocation().equals("crystal_hollows")) {
+ return;
+ }
+
+ // Capture particle troubleshooting info for two minutes starting when the first compass is used.
+ // This list is reset each time the first compass is used from a NOT_STARTED state.
+ if (firstCompass != null && !solverState.equals(SolverState.SOLVED) &&
+ System.currentTimeMillis() < firstCompass.whenUsedMillis + 2 * 60 * 1000) {
+ seenParticles.add(new ParticleData(new Vec3Comparable(x, y, z), System.currentTimeMillis()));
+ }
+
+ try {
+ SolverState originalSolverState = solverState;
+ solveUsingParticle(x, y, z, currentTimeMillis.getAsLong());
+ if (solverState != originalSolverState) {
+ switch (solverState) {
+ case SOLVED:
+ showSolution();
+ break;
+ case FAILED_EXCEPTION:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Unable to determine wishing compass target."));
+ logDiagnosticData(false);
+ break;
+ case FAILED_TIMEOUT_NO_REPEATING:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Timed out waiting for repeat set of compass particles."));
+ logDiagnosticData(false);
+ break;
+ case FAILED_TIMEOUT_NO_PARTICLES:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Timed out waiting for compass particles."));
+ logDiagnosticData(false);
+ break;
+ case FAILED_INTERSECTION_CALCULATION:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Unable to determine intersection of wishing compasses."));
+ logDiagnosticData(false);
+ break;
+ case FAILED_INVALID_SOLUTION:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Failed to find solution."));
+ logDiagnosticData(false);
+ break;
+ case NEED_SECOND_COMPASS:
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW +
+ "[NEU] Need another position to determine wishing compass target."));
+ break;
+ }
+ }
+ } catch (Exception e) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Exception while calculating wishing compass solution - see log for details"));
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @param x Particle x coordinate
+ * @param y Particle y coordinate
+ * @param z Particle z coordinate
+ */
+ public void solveUsingParticle(double x, double y, double z, long currentTimeMillis) {
+ Compass currentCompass;
+ switch (solverState) {
+ case PROCESSING_FIRST_USE:
+ currentCompass = firstCompass;
+ break;
+ case PROCESSING_SECOND_USE:
+ currentCompass = secondCompass;
+ break;
+ default:
+ return;
+ }
+
+ currentCompass.processParticle(x, y, z, currentTimeMillis);
+ switch (currentCompass.compassState) {
+ case FAILED_TIMEOUT_NO_PARTICLES:
+ solverState = SolverState.FAILED_TIMEOUT_NO_PARTICLES;
+ return;
+ case FAILED_TIMEOUT_NO_REPEATING:
+ solverState = SolverState.FAILED_TIMEOUT_NO_REPEATING;
+ return;
+ case WAITING_FOR_FIRST_PARTICLE:
+ case COMPUTING_LAST_PARTICLE:
+ return;
+ case COMPLETED:
+ if (solverState == SolverState.NEED_SECOND_COMPASS) {
+ return;
+ }
+ if (solverState == SolverState.PROCESSING_FIRST_USE) {
+ solverState = SolverState.NEED_SECOND_COMPASS;
+ return;
+ }
+ break;
+ }
+
+ // First and Second compasses have completed
+ solutionIntersectionLine = firstCompass.line.getIntersectionLineSegment(secondCompass.line);
+
+ if (solutionIntersectionLine == null) {
+ solverState = SolverState.FAILED_INTERSECTION_CALCULATION;
+ return;
+ }
+
+ solution = new Vec3Comparable(solutionIntersectionLine.getMidpoint());
+
+ Vec3Comparable firstDirection = firstCompass.getDirection();
+ Vec3Comparable firstSolutionDirection = firstCompass.getDirectionTo(solution);
+ Vec3Comparable secondDirection = secondCompass.getDirection();
+ Vec3Comparable secondSolutionDirection = secondCompass.getDirectionTo(solution);
+ if (!firstDirection.signumEquals(firstSolutionDirection) ||
+ !secondDirection.signumEquals(secondSolutionDirection) ||
+ !HOLLOWS_BB.isVecInside(solution)) {
+ solverState = SolverState.FAILED_INVALID_SOLUTION;
+ return;
+ }
+
+ solutionPossibleTargets = getSolutionTargets(
+ getZoneForCoords(firstCompass.whereUsed),
+ foundCrystals.getAsCrystalEnumSet(),
+ possibleTargets,
+ solution
+ );
+
+ // Adjust the Jungle Temple solution coordinates
+ if (solutionPossibleTargets.size() == 1 &&
+ solutionPossibleTargets.contains(CompassTarget.JUNGLE_TEMPLE)) {
+ originalSolution = solution;
+ solution = solution.add(JUNGLE_DOOR_OFFSET_FROM_CRYSTAL);
+ }
+
+ solverState = SolverState.SOLVED;
+ }
+
+ private boolean isKeyInInventory() {
+ for (ItemStack item : mc.thePlayer.inventory.mainInventory) {
+ if (item != null && item.getDisplayName().contains("Jungle Key")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isKingsScentPresent() {
+ return SBInfo.getInstance().footer.getUnformattedText().contains("King's Scent I");
+ }
+
+ private EnumSet<Crystal> getFoundCrystals() {
+ EnumSet<Crystal> foundCrystals = EnumSet.noneOf(Crystal.class);
+ NEUConfig.HiddenProfileSpecific perProfileConfig = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
+ if (perProfileConfig == null) return foundCrystals;
+ HashMap<String, Integer> crystals = perProfileConfig.crystals;
+ for (String crystalName : crystals.keySet()) {
+ Integer crystalState = crystals.get(crystalName);
+ if (crystalState != null && crystalState > 0) {
+ foundCrystals.add(Crystal.valueOf(crystalName.toUpperCase(Locale.US).replace("İ", "I")));
+ }
+ }
+
+ return foundCrystals;
+ }
+
+ // Returns candidates based on:
+ // - Structure Y levels observed in various lobbies. It is assumed
+ // that structures other than Khazad Dum cannot have any portion
+ // in the Magma Fields.
+ //
+ // - Structure sizes & offsets into other zones that assume at least
+ // one block must be in the correct zone.
+ //
+ // - An assumption that any structure could be missing with a
+ // special exception for the Jungle Temple since it often conflicts
+ // with Bal and a lobby with a missing Jungle Temple has not been
+ // observed. This exception will remove Bal as a target if:
+ // - Target candidates include both Bal & the Jungle Temple.
+ // - The Amethyst crystal has not been acquired.
+ // - The zone that the compass was used in is the Jungle.
+ //
+ // - If the solution is the Crystal Nucleus then a copy of the
+ // passed in possible targets is returned.
+ //
+ // |----------|------------|
+ // | Jungle | Mithril |
+ // | | Deposits |
+ // |----------|----------- |
+ // | Goblin | Precursor |
+ // | Holdout | Deposits |
+ // |----------|------------|
+ static public EnumSet<CompassTarget> getSolutionTargets(
+ HollowsZone compassUsedZone,
+ EnumSet<Crystal> foundCrystals,
+ EnumSet<CompassTarget> possibleTargets,
+ Vec3Comparable solution
+ ) {
+ EnumSet<CompassTarget> solutionPossibleTargets;
+ solutionPossibleTargets = possibleTargets.clone();
+
+ HollowsZone solutionZone = getZoneForCoords(solution);
+ if (solutionZone == HollowsZone.CRYSTAL_NUCLEUS) {
+ return solutionPossibleTargets;
+ }
+
+ solutionPossibleTargets.remove(CompassTarget.CRYSTAL_NUCLEUS);
+
+ // Y coordinates are 43-71 from 13 samples
+ // Y=41/74 is the absolute min/max based on structure size if
+ // the center of the topaz crystal has to be in magma fields.
+ if (solutionPossibleTargets.contains(CompassTarget.BAL) &&
+ solution.yCoord > 75) {
+ solutionPossibleTargets.remove(CompassTarget.BAL);
+ }
+
+ // Y coordinates are 93-157 from 15 samples.
+ // Y=83/167 is the absolute min/max based on structure size
+ if (solutionPossibleTargets.contains(CompassTarget.GOBLIN_KING) &&
+ solution.yCoord < 82 || solution.yCoord > 168) {
+ solutionPossibleTargets.remove(CompassTarget.GOBLIN_KING);
+ }
+
+ // Y coordinates are 129-139 from 10 samples
+ // Y=126/139 is the absolute min/max based on structure size
+ if (solutionPossibleTargets.contains(CompassTarget.GOBLIN_QUEEN) &&
+ (solution.yCoord < 125 || solution.yCoord > 140)) {
+ solutionPossibleTargets.remove(CompassTarget.GOBLIN_QUEEN);
+ }
+
+ // Y coordinates are 72-80 from 10 samples
+ // Y=73/80 is the absolute min/max based on structure size
+ if (solutionPossibleTargets.contains(CompassTarget.JUNGLE_TEMPLE) &&
+ (solution.yCoord < 72 || solution.yCoord > 81)) {
+ solutionPossibleTargets.remove(CompassTarget.JUNGLE_TEMPLE);
+ }
+
+ // Y coordinates are 87-155 from 7 samples
+ // Y=74/155 is the absolute min/max solution based on structure size
+ if (solutionPossibleTargets.contains(CompassTarget.ODAWA) &&
+ (solution.yCoord < 73 || solution.yCoord > 155)) {
+ solutionPossibleTargets.remove(CompassTarget.ODAWA);
+ }
+
+ // Y coordinates are 122-129 from 8 samples
+ // Y=122/129 is the absolute min/max based on structure size
+ if (solutionPossibleTargets.contains(CompassTarget.PRECURSOR_CITY) &&
+ (solution.yCoord < 121 || solution.yCoord > 130)) {
+ solutionPossibleTargets.remove(CompassTarget.PRECURSOR_CITY);
+ }
+
+ // Y coordinates are 98-102 from 15 samples
+ // Y=98/100 is the absolute min/max based on structure size,
+ // but 102 has been seen - possibly with earlier code that rounded up
+ if (solutionPossibleTargets.contains(CompassTarget.MINES_OF_DIVAN) &&
+ (solution.yCoord < 97 || solution.yCoord > 102)) {
+ solutionPossibleTargets.remove(CompassTarget.MINES_OF_DIVAN);
+ }
+
+ // Now filter by structure offset
+ if (solutionPossibleTargets.contains(CompassTarget.GOBLIN_KING) &&
+ (solution.xCoord > GOBLIN_HOLDOUT_BB.maxX + GOBLIN_KING_BB.maxX ||
+ solution.zCoord < GOBLIN_HOLDOUT_BB.minZ - GOBLIN_KING_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.GOBLIN_KING);
+ }
+
+ if (solutionPossibleTargets.contains(CompassTarget.GOBLIN_QUEEN) &&
+ (solution.xCoord > GOBLIN_HOLDOUT_BB.maxX + GOBLIN_QUEEN_BB.maxX ||
+ solution.zCoord < GOBLIN_HOLDOUT_BB.minZ - GOBLIN_QUEEN_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.GOBLIN_QUEEN);
+ }
+
+ if (solutionPossibleTargets.contains(CompassTarget.JUNGLE_TEMPLE) &&
+ (solution.xCoord > JUNGLE_BB.maxX + JUNGLE_TEMPLE_BB.maxX ||
+ solution.zCoord > JUNGLE_BB.maxZ + JUNGLE_TEMPLE_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.JUNGLE_TEMPLE);
+ }
+
+ if (solutionPossibleTargets.contains(CompassTarget.ODAWA) &&
+ (solution.xCoord > JUNGLE_BB.maxX + ODAWA_BB.maxX ||
+ solution.zCoord > JUNGLE_BB.maxZ + ODAWA_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.ODAWA);
+ }
+
+ if (solutionPossibleTargets.contains(CompassTarget.PRECURSOR_CITY) &&
+ (solution.xCoord < PRECURSOR_REMNANTS_BB.minX - PRECURSOR_CITY_BB.maxX ||
+ solution.zCoord < PRECURSOR_REMNANTS_BB.minZ - PRECURSOR_CITY_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.PRECURSOR_CITY);
+ }
+
+ if (solutionPossibleTargets.contains(CompassTarget.MINES_OF_DIVAN) &&
+ (solution.xCoord < MITHRIL_DEPOSITS_BB.minX - MINES_OF_DIVAN_BB.maxX ||
+ solution.zCoord > MITHRIL_DEPOSITS_BB.maxZ + MINES_OF_DIVAN_BB.maxZ)) {
+ solutionPossibleTargets.remove(CompassTarget.MINES_OF_DIVAN);
+ }
+
+ // Special case the Jungle Temple
+ if (solutionPossibleTargets.contains(CompassTarget.JUNGLE_TEMPLE) &&
+ solutionPossibleTargets.contains(CompassTarget.BAL) &&
+ !foundCrystals.contains(Crystal.AMETHYST) &&
+ compassUsedZone == HollowsZone.JUNGLE) {
+ solutionPossibleTargets.remove(CompassTarget.BAL);
+ }
+
+ return solutionPossibleTargets;
+ }
+
+ private EnumSet<CompassTarget> calculatePossibleTargets(BlockPos playerPos) {
+ EnumSet<CompassTarget> candidateTargets = EnumSet.of(CompassTarget.CRYSTAL_NUCLEUS);
+ EnumSet<Crystal> foundCrystals = this.foundCrystals.getAsCrystalEnumSet();
+
+ // Add targets based on missing crystals.
+ // NOTE:
+ // We used to assume that only the adjacent zone's targets could be returned. That turned
+ // out to be incorrect (e.g. a compass in the jungle pointed to the Precursor City when
+ // the king would have been a valid target). Now we assume that any structure could be
+ // missing (because Hypixel) and depend on the solution coordinates to filter the list.
+ for (Crystal crystal : Crystal.values()) {
+ if (foundCrystals.contains(crystal)) {
+ continue;
+ }
+
+ switch (crystal) {
+ case JADE:
+ candidateTargets.add(CompassTarget.MINES_OF_DIVAN);
+ break;
+ case AMBER:
+ candidateTargets.add(
+ kingsScentPresent.getAsBoolean() ? CompassTarget.GOBLIN_QUEEN : CompassTarget.GOBLIN_KING);
+ break;
+ case TOPAZ:
+ candidateTargets.add(CompassTarget.BAL);
+ break;
+ case AMETHYST:
+ candidateTargets.add(
+ keyInInventory.getAsBoolean() ? CompassTarget.JUNGLE_TEMPLE : CompassTarget.ODAWA);
+ break;
+ case SAPPHIRE:
+ candidateTargets.add(CompassTarget.PRECURSOR_CITY);
+ break;
+ }
+ }
+
+ return candidateTargets;
+ }
+
+ private String getFriendlyNameForCompassTarget(CompassTarget compassTarget) {
+ switch (compassTarget) {
+ case BAL:
+ return EnumChatFormatting.RED + "Bal";
+ case ODAWA:
+ return EnumChatFormatting.GREEN + "Odawa";
+ case JUNGLE_TEMPLE:
+ return EnumChatFormatting.AQUA + "the " +
+ EnumChatFormatting.GREEN + "Jungle Temple";
+ case GOBLIN_KING:
+ return EnumChatFormatting.GOLD + "King Yolkar";
+ case GOBLIN_QUEEN:
+ return EnumChatFormatting.AQUA + "the " +
+ EnumChatFormatting.YELLOW + "Goblin Queen";
+ case PRECURSOR_CITY:
+ return EnumChatFormatting.AQUA + "the " +
+ EnumChatFormatting.WHITE + "Precursor City";
+ case MINES_OF_DIVAN:
+ return EnumChatFormatting.AQUA + "the " +
+ EnumChatFormatting.BLUE + "Mines of Divan";
+ default:
+ return EnumChatFormatting.WHITE + "an undetermined location";
+ }
+ }
+
+ private String getNameForCompassTarget(CompassTarget compassTarget) {
+ boolean useSkytilsNames = (NotEnoughUpdates.INSTANCE.config.mining.wishingCompassWaypointNames == 1);
+ switch (compassTarget) {
+ case BAL:
+ return useSkytilsNames ? "internal_bal" : "Bal";
+ case ODAWA:
+ return "Odawa";
+ case JUNGLE_TEMPLE:
+ return useSkytilsNames ? "internal_temple" : "Temple";
+ case GOBLIN_KING:
+ return useSkytilsNames ? "internal_king" : "King";
+ case GOBLIN_QUEEN:
+ return useSkytilsNames ? "internal_den" : "Queen";
+ case PRECURSOR_CITY:
+ return useSkytilsNames ? "internal_city" : "City";
+ case MINES_OF_DIVAN:
+ return useSkytilsNames ? "internal_mines" : "Mines";
+ default:
+ return "WishingTarget";
+ }
+ }
+
+ private String getSolutionCoordsText() {
+ return solution == null ? "" :
+ String.format("%.0f %.0f %.0f", solution.xCoord, solution.yCoord, solution.zCoord);
+ }
+
+ private String getWishingCompassDestinationsMessage() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(EnumChatFormatting.YELLOW);
+ sb.append("[NEU] ");
+ sb.append(EnumChatFormatting.AQUA);
+ sb.append("Wishing compass points to ");
+ int index = 1;
+ for (CompassTarget target : solutionPossibleTargets) {
+ if (index > 1) {
+ sb.append(EnumChatFormatting.AQUA);
+ if (index == solutionPossibleTargets.size()) {
+ sb.append(" or ");
+ } else {
+ sb.append(", ");
+ }
+ }
+ sb.append(getFriendlyNameForCompassTarget(target));
+ index++;
+ }
+
+ sb.append(EnumChatFormatting.AQUA);
+ sb.append(" (");
+ sb.append(getSolutionCoordsText());
+ sb.append(")");
+ return sb.toString();
+ }
+
+ private void showSolution() {
+ if (solution == null) return;
+
+ if (NUCLEUS_BB.isVecInside(solution)) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] " +
+ EnumChatFormatting.AQUA + "Wishing compass target is the Crystal Nucleus"));
+ return;
+ }
+
+ String destinationMessage = getWishingCompassDestinationsMessage();
+
+ if (!isSkytilsPresent) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(destinationMessage));
+ return;
+ }
+
+ String targetNameForSkytils = solutionPossibleTargets.size() == 1 ?
+ getNameForCompassTarget(solutionPossibleTargets.iterator().next()) :
+ "WishingTarget";
+ String skytilsCommand = String.format("/sthw add %s %s", getSolutionCoordsText(), targetNameForSkytils);
+ if (NotEnoughUpdates.INSTANCE.config.mining.wishingCompassAutocreateKnownWaypoints &&
+ solutionPossibleTargets.size() == 1) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(destinationMessage));
+ int commandResult = ClientCommandHandler.instance.executeCommand(mc.thePlayer, skytilsCommand);
+ if (commandResult == 1) {
+ return;
+ }
+ mc.thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "[NEU] Failed to automatically run /sthw"));
+ }
+
+ destinationMessage += EnumChatFormatting.YELLOW + " [Add Skytils Waypoint]";
+ ChatComponentText chatMessage = new ChatComponentText(destinationMessage);
+ chatMessage.setChatStyle(Utils.createClickStyle(
+ ClickEvent.Action.RUN_COMMAND,
+ skytilsCommand,
+ EnumChatFormatting.YELLOW + "Set waypoint for wishing target"
+ ));
+ mc.thePlayer.addChatMessage(chatMessage);
+ }
+
+ private String getDiagnosticMessage() {
+ StringBuilder diagsMessage = new StringBuilder();
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Solver State: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(solverState.name());
+ diagsMessage.append("\n");
+
+ if (firstCompass == null) {
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("First Compass: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append("<NONE>");
+ diagsMessage.append("\n");
+ } else {
+ firstCompass.appendCompassDiagnostics(diagsMessage, "First Compass");
+ }
+
+ if (secondCompass == null) {
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Second Compass: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append("<NONE>");
+ diagsMessage.append("\n");
+ } else {
+ secondCompass.appendCompassDiagnostics(diagsMessage, "Second Compass");
+ }
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Intersection Line: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((solutionIntersectionLine == null) ? "<NONE>" : solutionIntersectionLine);
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Jungle Key in Inventory: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(isKeyInInventory());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("King's Scent Present: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(isKingsScentPresent());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("First Compass Targets: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(possibleTargets == null ? "<NONE>" : possibleTargets.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Current Calculated Targets: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(calculatePossibleTargets(mc.thePlayer.getPosition()));
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Found Crystals: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(getFoundCrystals());
+ diagsMessage.append("\n");
+
+ if (originalSolution != null) {
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Original Solution: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(originalSolution);
+ diagsMessage.append("\n");
+ }
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Solution: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((solution == null) ? "<NONE>" : solution.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Solution Targets: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((solutionPossibleTargets == null) ? "<NONE>" : solutionPossibleTargets.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Seen particles:\n");
+ for (ParticleData particleData : seenParticles) {
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(particleData);
+ diagsMessage.append("\n");
+ }
+
+ return diagsMessage.toString();
+ }
+
+ public void logDiagnosticData(boolean outputAlways) {
+ if (!SBInfo.getInstance().checkForSkyblockLocation()) {
+ return;
+ }
+
+ if (!NotEnoughUpdates.INSTANCE.config.mining.wishingCompassSolver) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] Wishing Compass Solver is not enabled."));
+ return;
+ }
+
+ boolean wishingDebugFlagSet = NEUDebugFlag.WISHING.isSet();
+ if (outputAlways || wishingDebugFlagSet) {
+ NEUDebugLogger.logAlways(getDiagnosticMessage());
+ }
+ }
+
+ enum CompassState {
+ WAITING_FOR_FIRST_PARTICLE,
+ COMPUTING_LAST_PARTICLE,
+ COMPLETED,
+ FAILED_TIMEOUT_NO_REPEATING,
+ FAILED_TIMEOUT_NO_PARTICLES,
+ }
+
+ enum HandleCompassResult {
+ SUCCESS,
+ LOCATION_TOO_CLOSE,
+ STILL_PROCESSING_PRIOR_USE,
+ POSSIBLE_TARGETS_CHANGED,
+ NO_PARTICLES_FOR_PREVIOUS_COMPASS,
+ PLAYER_IN_NUCLEUS
+ }
+
+ static class Compass {
+ public CompassState compassState;
+ public Line line = null;
+
+ private final BlockPos whereUsed;
+ private final long whenUsedMillis;
+ private Vec3Comparable firstParticle = null;
+ private Vec3Comparable previousParticle = null;
+ private Vec3Comparable lastParticle = null;
+ private final ArrayList<ProcessedParticle> processedParticles;
+
+ Compass(BlockPos whereUsed, long whenUsedMillis) {
+ this.whereUsed = whereUsed;
+ this.whenUsedMillis = whenUsedMillis;
+ compassState = CompassState.WAITING_FOR_FIRST_PARTICLE;
+ processedParticles = new ArrayList<>();
+ }
+
+ public Vec3Comparable getDirection() {
+ if (firstParticle == null || lastParticle == null) {
+ return null;
+ }
+
+ return new Vec3Comparable(firstParticle.subtractReverse(lastParticle).normalize());
+ }
+
+ public Vec3Comparable getDirectionTo(Vec3Comparable target) {
+ if (firstParticle == null || target == null) {
+ return null;
+ }
+
+ return new Vec3Comparable(firstParticle.subtractReverse(target).normalize());
+ }
+
+ public double particleSpread() {
+ if (firstParticle == null || lastParticle == null) {
+ return 0.0;
+ }
+ return firstParticle.distanceTo(lastParticle);
+ }
+
+ public void processParticle(double x, double y, double z, long particleTimeMillis) {
+ if (compassState == CompassState.FAILED_TIMEOUT_NO_REPEATING ||
+ compassState == CompassState.FAILED_TIMEOUT_NO_PARTICLES ||
+ compassState == CompassState.COMPLETED) {
+ throw new UnsupportedOperationException("processParticle should not be called in a failed or completed state");
+ }
+
+ if (particleTimeMillis - this.whenUsedMillis > ALL_PARTICLES_MAX_MILLIS) {
+ // Assume we have failed if we're still trying to process particles
+ compassState = CompassState.FAILED_TIMEOUT_NO_REPEATING;
+ return;
+ }
+
+ Vec3Comparable currentParticle = new Vec3Comparable(x, y, z);
+ if (compassState == CompassState.WAITING_FOR_FIRST_PARTICLE) {
+ if (currentParticle.distanceTo(new Vec3Comparable(whereUsed)) < MAX_DISTANCE_FROM_USE_TO_FIRST_PARTICLE) {
+ processedParticles.add(new ProcessedParticle(currentParticle, particleTimeMillis));
+ firstParticle = currentParticle;
+ previousParticle = currentParticle;
+ compassState = CompassState.COMPUTING_LAST_PARTICLE;
+ }
+ return;
+ }
+
+ // State is COMPUTING_LAST_PARTICLE, keep updating the previousParticle until
+ // the first particle in the second sequence is seen.
+ if (currentParticle.distanceTo(previousParticle) <= MAX_DISTANCE_BETWEEN_PARTICLES) {
+ processedParticles.add(new ProcessedParticle(currentParticle, particleTimeMillis));
+ previousParticle = currentParticle;
+ return;
+ }
+
+ if (currentParticle.distanceTo(firstParticle) > MAX_DISTANCE_BETWEEN_PARTICLES) {
+ return;
+ }
+
+ // It's a repeating particle
+ processedParticles.add(new ProcessedParticle(currentParticle, particleTimeMillis));
+ lastParticle = previousParticle;
+ line = new Line(firstParticle, lastParticle);
+ compassState = CompassState.COMPLETED;
+ }
+
+ public void appendCompassDiagnostics(StringBuilder diagsMessage, String compassName) {
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append("Compass State: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(compassState.name());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append(compassName);
+ diagsMessage.append(" Used Millis: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(whenUsedMillis);
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append(compassName);
+ diagsMessage.append(" Used Position: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((whereUsed == null) ? "<NONE>" : whereUsed.toString());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append(compassName);
+ diagsMessage.append(" All Seen Particles: \n");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ for (ProcessedParticle particle : processedParticles) {
+ diagsMessage.append(particle.toString());
+ diagsMessage.append("\n");
+ }
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append(compassName);
+ diagsMessage.append(" Particle Spread: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append(particleSpread());
+ diagsMessage.append("\n");
+
+ diagsMessage.append(EnumChatFormatting.AQUA);
+ diagsMessage.append(compassName);
+ diagsMessage.append(" Compass Line: ");
+ diagsMessage.append(EnumChatFormatting.WHITE);
+ diagsMessage.append((line == null) ? "<NONE>" : line.toString());
+ diagsMessage.append("\n");
+ }
+
+ static class ProcessedParticle {
+ Vec3Comparable coords;
+ long particleTimeMillis;
+
+ ProcessedParticle(Vec3Comparable coords, long particleTimeMillis) {
+ this.coords = coords;
+ this.particleTimeMillis = particleTimeMillis;
+ }
+
+ @Override
+ public String toString() {
+ return coords.toString() + " " + particleTimeMillis;
+ }
+ }
+ }
+
+ private static class ParticleData {
+ Vec3Comparable particleLocation;
+ long systemTime;
+
+ public ParticleData(Vec3Comparable particleLocation, long systemTime) {
+ this.particleLocation = particleLocation;
+ this.systemTime = systemTime;
+ }
+
+ public String toString() {
+ return "Location: " + particleLocation.toString() + ", systemTime: " + systemTime;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
index e621cf78..452f8a9b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -11,7 +30,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.multiplayer.WorldClient;
-import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.BlockRendererDispatcher;
+import net.minecraft.client.renderer.EntityRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
@@ -24,7 +47,13 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
-import net.minecraft.util.*;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.MovingObjectPosition;
+import net.minecraft.util.Vec3;
+import net.minecraft.util.Vec3i;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
@@ -36,8 +65,14 @@ import org.lwjgl.util.vector.Vector3f;
import java.awt.*;
import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
-import java.util.*;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -178,12 +213,14 @@ public class CustomItemEffects {
@SubscribeEvent
public void onGameTick(TickEvent.ClientTickEvent event) {
if (event.phase != TickEvent.Phase.END) return;
+ EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
+ if (player == null) return;
if (!usingEtherwarp && wasUsingEtherwarp) {
- if (Minecraft.getMinecraft().thePlayer.rotationYaw > 0) {
- Minecraft.getMinecraft().thePlayer.rotationYaw -= 0.000001;
+ if (player.rotationYaw > 0) {
+ player.rotationYaw -= 0.000001;
} else {
- Minecraft.getMinecraft().thePlayer.rotationYaw += 0.000001;
+ player.rotationYaw += 0.000001;
}
}
wasUsingEtherwarp = usingEtherwarp;
@@ -238,6 +275,7 @@ public class CustomItemEffects {
private boolean usingEtherwarp = false;
private RaycastResult etherwarpRaycast = null;
private int lastEtherwarpUse = 0;
+ private String denyTpReason = null;
@SubscribeEvent
public void onOverlayDrawn(RenderGameOverlayEvent.Post event) {
@@ -246,40 +284,50 @@ public class CustomItemEffects {
ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
- if (usingEtherwarp && NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpHelperOverlay) {
- String denyTpReason = null;
+ WorldClient world = Minecraft.getMinecraft().theWorld;
+ if (usingEtherwarp) {
+ denyTpReason = null;
if (etherwarpRaycast == null) {
denyTpReason = "Too far!";
} else {
BlockPos pos = etherwarpRaycast.pos;
- if (!etherwarpRaycast.state.getBlock().isCollidable() ||
- etherwarpRaycast.state.getBlock().getCollisionBoundingBox(
- Minecraft.getMinecraft().theWorld,
- etherwarpRaycast.pos,
- etherwarpRaycast.state
- ) == null) {
+ Block block = etherwarpRaycast.state.getBlock();
+ if (!block.isCollidable() ||
+ //Don't allow teleport at this block
+ block == Blocks.carpet || block == Blocks.skull ||
+ block.getCollisionBoundingBox(world, etherwarpRaycast.pos, etherwarpRaycast.state) == null &&
+ //Allow teleport at this block
+ block != Blocks.wall_sign && block != Blocks.standing_sign) {
denyTpReason = "Not solid!";
} else {
- WorldClient world = Minecraft.getMinecraft().theWorld;
- Block above = world.getBlockState(pos.add(0, 1, 0)).getBlock();
- if (above != Blocks.air && above.isCollidable() &&
- above.getCollisionBoundingBox(Minecraft.getMinecraft().theWorld, pos.add(0, 1, 0),
- world.getBlockState(pos.add(0, 1, 0))
- ) != null ||
- world.getBlockState(pos.add(0, 2, 0)).getBlock() != Blocks.air) {
+ BlockPos blockPosAbove = pos.add(0, 1, 0);
+ Block blockAbove = world.getBlockState(blockPosAbove).getBlock();
+
+ Block twoBlockAbove = world.getBlockState(pos.add(0, 2, 0)).getBlock();
+ if (blockAbove != Blocks.air &&
+ //Allow teleport to the block below this block
+ blockAbove != Blocks.carpet && blockAbove != Blocks.skull && blockAbove.isCollidable() &&
+ blockAbove.getCollisionBoundingBox(world, blockPosAbove, world.getBlockState(blockPosAbove)) != null ||
+ //Don't allow teleport to the block below this block
+ blockAbove == Blocks.wall_sign || block == Blocks.standing_sign ||
+ //Allow teleport to the block 2 blocks below this block
+ twoBlockAbove != Blocks.air && twoBlockAbove != Blocks.double_plant && twoBlockAbove != Blocks.carpet &&
+ blockAbove != Blocks.skull) {
denyTpReason = "No air above!";
}
}
}
- if (denyTpReason != null) {
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- Utils.drawStringCentered(EnumChatFormatting.RED + "Can't TP: " + denyTpReason,
- Minecraft.getMinecraft().fontRendererObj,
- scaledResolution.getScaledWidth() / 2f, scaledResolution.getScaledHeight() / 2f + 10, true, 0
- );
- GlStateManager.color(1, 1, 1, 1);
+ if (NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpHelperOverlay) {
+ if (denyTpReason != null) {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ Utils.drawStringCentered(EnumChatFormatting.RED + "Can't TP: " + denyTpReason,
+ Minecraft.getMinecraft().fontRendererObj,
+ scaledResolution.getScaledWidth() / 2f, scaledResolution.getScaledHeight() / 2f + 10, true, 0
+ );
+ GlStateManager.color(1, 1, 1, 1);
+ }
}
}
@@ -291,7 +339,7 @@ public class CustomItemEffects {
Minecraft.getMinecraft().objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK &&
onPrivateIsland) {
- IBlockState hover = Minecraft.getMinecraft().theWorld.getBlockState(
+ IBlockState hover = world.getBlockState(
Minecraft.getMinecraft().objectMouseOver.getBlockPos().offset(
Minecraft.getMinecraft().objectMouseOver.sideHit, 1));
if (hover.getBlock() == Blocks.air) {
@@ -303,14 +351,14 @@ public class CustomItemEffects {
TreeMap<Float, Set<BlockPos>> candidatesOldSorted = new TreeMap<>();
IBlockState match =
- Minecraft.getMinecraft().theWorld.getBlockState(Minecraft.getMinecraft().objectMouseOver.getBlockPos());
+ world.getBlockState(Minecraft.getMinecraft().objectMouseOver.getBlockPos());
Item matchItem = Item.getItemFromBlock(match.getBlock());
if (matchItem != null) {
ItemStack matchStack = new ItemStack(matchItem, 1,
match
.getBlock()
.getDamageValue(
- Minecraft.getMinecraft().theWorld,
+ world,
Minecraft.getMinecraft().objectMouseOver.getBlockPos()
)
);
@@ -568,7 +616,8 @@ public class CustomItemEffects {
double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) event.partialTicks;
double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) event.partialTicks;
- if (tick - lastEtherwarpUse > 10) {
+ //Don't need to wait 10 ticks when zoom is disabled
+ if (tick - lastEtherwarpUse > 10 || !NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpZoom) {
boolean aotv = Minecraft.getMinecraft().thePlayer.isSneaking() &&
(heldInternal.equals("ASPECT_OF_THE_VOID") || heldInternal.equals("ASPECT_OF_THE_END"));
if (aotv || heldInternal.equals("ETHERWARP_CONDUIT")) {
@@ -597,20 +646,30 @@ public class CustomItemEffects {
if (etherwarpRaycast != null &&
NotEnoughUpdates.INSTANCE.config.itemOverlays.enableEtherwarpBlockOverlay) {
- AxisAlignedBB bb = etherwarpRaycast.state.getBlock().getSelectedBoundingBox(
- Minecraft.getMinecraft().theWorld,
- etherwarpRaycast.pos
- )
- .expand(0.01D, 0.01D, 0.01D).offset(-d0, -d1, -d2);
- drawFilledBoundingBox(bb, 1f, NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour);
+ if (denyTpReason == null || !NotEnoughUpdates.INSTANCE.config.itemOverlays.disableOverlayWhenFailed) {
+ AxisAlignedBB box = etherwarpRaycast.state.getBlock().getSelectedBoundingBox(
+ Minecraft.getMinecraft().theWorld,
+ etherwarpRaycast.pos
+ );
+ AxisAlignedBB bb = box.expand(0.01D, 0.01D, 0.01D).offset(-d0, -d1, -d2);
+ drawFilledBoundingBox(
+ bb,
+ 1f,
+ NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour
+ );
- GlStateManager.disableDepth();
- drawOutlineBoundingBox(bb, 2f, NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour);
- GlStateManager.enableDepth();
+ GlStateManager.disableDepth();
+ drawOutlineBoundingBox(
+ bb,
+ 2f,
+ NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpHighlightColour
+ );
+ GlStateManager.enableDepth();
- GlStateManager.depthMask(true);
- GlStateManager.enableTexture2D();
- GlStateManager.disableBlend();
+ GlStateManager.depthMask(true);
+ GlStateManager.enableTexture2D();
+ GlStateManager.disableBlend();
+ }
if (NotEnoughUpdates.INSTANCE.config.itemOverlays.etherwarpZoom) {
float distFactor = 1 -
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomSkulls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomSkulls.java
index 1157e73a..95ec0f7a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomSkulls.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomSkulls.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.common.collect.Maps;
@@ -14,8 +33,17 @@ import net.minecraft.client.model.ModelSkeletonHead;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.WorldRenderer;
-import net.minecraft.client.renderer.block.model.*;
-import net.minecraft.client.renderer.texture.*;
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import net.minecraft.client.renderer.block.model.BlockPart;
+import net.minecraft.client.renderer.block.model.BlockPartFace;
+import net.minecraft.client.renderer.block.model.FaceBakery;
+import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
+import net.minecraft.client.renderer.block.model.ModelBlock;
+import net.minecraft.client.renderer.texture.AbstractTexture;
+import net.minecraft.client.renderer.texture.IIconCreator;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.resources.IResourceManagerReloadListener;
@@ -31,7 +59,11 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class CustomSkulls implements IResourceManagerReloadListener {
private static final CustomSkulls INSTANCE = new CustomSkulls();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
index 9c93b9c5..b1ab11c1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -26,15 +45,18 @@ public class DamageCommas {
};
private static final char STAR = '\u2727';
+ private static final char OVERLOAD_STAR = '\u272F';
private static final Pattern PATTERN_CRIT = Pattern.compile(
- "\u00a7f" + STAR + "((?:\u00a7.\\d)+)\u00a7." + STAR + "(.*)");
- private static final Pattern PATTERN_NO_CRIT = Pattern.compile("\u00a77(\\d+)(.*)");
+ "\u00a7f" + STAR + "((?:\u00a7.\\d(?:§.,)?)+)\u00a7." + STAR + "(.*)");
+ private static final Pattern PATTERN_NO_CRIT = Pattern.compile("(\u00a7.)([\\d+,]*)(.*)");
+ private static final Pattern OVERLOAD_PATTERN = Pattern.compile("(\u00a7.)" + OVERLOAD_STAR + "((?:\u00a7.[\\d,])+)(\u00a7.)" + OVERLOAD_STAR + "\u00a7r");
public static IChatComponent replaceName(EntityLivingBase entity) {
if (!entity.hasCustomName()) return entity.getDisplayName();
IChatComponent name = entity.getDisplayName();
- if (NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle == 0) return name;
+ if (!NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle2) return name;
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return name;
if (replacementMap.containsKey(entity)) {
ChatComponentText component = replacementMap.get(entity);
@@ -50,17 +72,23 @@ public class DamageCommas {
String suffix;
Matcher matcherCrit = PATTERN_CRIT.matcher(formatted);
+ Matcher matcherOverload = OVERLOAD_PATTERN.matcher(formatted);
if (matcherCrit.matches()) {
crit = true;
- numbers = StringUtils.cleanColour(matcherCrit.group(1));
+ numbers = StringUtils.cleanColour(matcherCrit.group(1)).replace(",", "");
prefix = "\u00a7f" + STAR;
suffix = "\u00a7f" + STAR + matcherCrit.group(2);
- } else {
+ } else if (matcherOverload.matches()) {
+ crit = true;
+ numbers = StringUtils.cleanColour(matcherOverload.group(2)).replace(",", "");
+ prefix = matcherOverload.group(1) + OVERLOAD_STAR;
+ suffix = matcherOverload.group(3) + OVERLOAD_STAR + "\u00a7r";
+ } else {
Matcher matcherNoCrit = PATTERN_NO_CRIT.matcher(formatted);
if (matcherNoCrit.matches()) {
- numbers = matcherNoCrit.group(1);
- prefix = "\u00A77";
- suffix = "\u00A7r" + matcherNoCrit.group(2);
+ numbers = matcherNoCrit.group(2).replace(",", "");
+ prefix = matcherNoCrit.group(1);
+ suffix = "\u00A7r" + matcherNoCrit.group(3);
} else {
replacementMap.put(entity, null);
return name;
@@ -72,10 +100,10 @@ public class DamageCommas {
try {
int number = Integer.parseInt(numbers);
- if (number > 999 && NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle == 2) {
+ if (number > 999) {
newFormatted.append(Utils.shortNumberFormat(number, 0));
} else {
- newFormatted.append(NumberFormat.getIntegerInstance().format(number));
+ return name;
}
} catch (NumberFormatException e) {
replacementMap.put(entity, null);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java
index f7f9003c..c1c7dca1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesWaypoints.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
index 16b59b05..d5cbfdde 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/EnchantingSolvers.java
@@ -1,6 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiChest;
@@ -17,13 +37,18 @@ import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.input.Keyboard;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
public class EnchantingSolvers {
- private static SolverType currentSolver = SolverType.NONE;
+ public static SolverType currentSolver = SolverType.NONE;
- private enum SolverType {
+ public enum SolverType {
NONE,
CHRONOMATRON,
ULTRASEQUENCER,
@@ -72,20 +97,14 @@ public class EnchantingSolvers {
return;
}
- if (event.gui instanceof GuiChest) {
- GuiChest chest = (GuiChest) event.gui;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
- String lower = containerName.toLowerCase();
-
- if (!lower.contains("stakes")) {
- if (lower.startsWith("chronomatron")) {
- currentSolver = SolverType.CHRONOMATRON;
- } else if (lower.startsWith("ultrasequencer")) {
- currentSolver = SolverType.ULTRASEQUENCER;
- } else if (lower.startsWith("superpairs")) {
- currentSolver = SolverType.SUPERPAIRS;
- }
+ String openChestName = Utils.getOpenChestName();
+ if (!openChestName.contains("Stakes")) {
+ if (openChestName.startsWith("Chronomatron")) {
+ currentSolver = SolverType.CHRONOMATRON;
+ } else if (openChestName.startsWith("Ultrasequencer")) {
+ currentSolver = SolverType.ULTRASEQUENCER;
+ } else if (openChestName.startsWith("Superpairs")) {
+ currentSolver = SolverType.SUPERPAIRS;
}
}
}
@@ -290,97 +309,88 @@ public class EnchantingSolvers {
return false;
}
- public static boolean onStackClick(ItemStack stack, int windowId, int slotId, int mouseButtonClicked, int mode) {
- if (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableEnchantingSolvers) {
- return false;
+ @SubscribeEvent
+ public void onStackClick(SlotClickEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableEnchantingSolvers
+ || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ return;
}
- if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
- return false;
+ ItemStack stack = event.slot.getStack();
+ if (stack == null || stack.getDisplayName() == null) {
+ return;
}
+ String displayName = stack.getDisplayName();
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) {
+ return;
+ }
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ IInventory lower = container.getLowerChestInventory();
+
+ if (currentSolver == SolverType.CHRONOMATRON) {
+ ItemStack timerStack = lower.getStackInSlot(lower.getSizeInventory() - 5);
+ if (timerStack == null) {
+ return;
+ }
- if (stack != null && stack.getDisplayName() != null) {
- String displayName = stack.getDisplayName();
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- IInventory lower = container.getLowerChestInventory();
-
- if (currentSolver == SolverType.CHRONOMATRON) {
- ItemStack timerStack = lower.getStackInSlot(lower.getSizeInventory() - 5);
- if (timerStack == null) {
- return false;
- }
-
- boolean yepClock = timerStack.getItem() == Items.clock;
- if (timerStack.getItem() == Item.getItemFromBlock(Blocks.glowstone) ||
- (yepClock && (!addToChronomatron || chronomatronOrder.size() < lastChronomatronSize + 1))) {
- return true;
- } else if (yepClock) {
- long currentTime = System.currentTimeMillis();
- if (currentTime - millisLastClick < 150) {
- return true;
- }
+ boolean yepClock = timerStack.getItem() == Items.clock;
+ if (timerStack.getItem() == Item.getItemFromBlock(Blocks.glowstone) ||
+ (yepClock && (!addToChronomatron || chronomatronOrder.size() < lastChronomatronSize + 1))) {
+ event.setCanceled(true);
+ return;
+ }
+ if (yepClock) {
+ long currentTime = System.currentTimeMillis();
+ if (currentTime - millisLastClick < 150) {
+ event.setCanceled(true);
+ return;
+ }
- if (chronomatronReplayIndex < chronomatronOrder.size()) {
- String chronomatronCurrent = chronomatronOrder.get(chronomatronReplayIndex);
- if (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks1 ||
- chronomatronCurrent.equals(displayName)) {
- chronomatronReplayIndex++;
- Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
- 2, mode, Minecraft.getMinecraft().thePlayer
- );
- millisLastClick = currentTime;
- }
- /*if (chronomatronCurrent.equals(displayName)) {
- chronomatronReplayIndex++;
- }
- Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
- 2, mode, Minecraft.getMinecraft().thePlayer);
- millisLastClick = currentTime;*/
- }
- return true;
- }
- } else if (currentSolver == SolverType.ULTRASEQUENCER) {
- ItemStack timerStack = lower.getStackInSlot(lower.getSizeInventory() - 5);
- if (timerStack == null) {
- return false;
+ if (chronomatronReplayIndex < chronomatronOrder.size()) {
+ String chronomatronCurrent = chronomatronOrder.get(chronomatronReplayIndex);
+ if ((!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks1 ||
+ chronomatronCurrent.equals(displayName) || Keyboard.getEventKey() == Keyboard.KEY_LSHIFT) &&
+ stack.getItem() != Item.getItemFromBlock(Blocks.stained_glass_pane) && event.slotId != 4 &&
+ event.slotId != 49) {
+ chronomatronReplayIndex++;
+ millisLastClick = currentTime;
+ event.usePickblockInstead();
+ return;
}
+ }
+ event.setCanceled(true);
+ return;
+ }
+ }
+ if (currentSolver == SolverType.ULTRASEQUENCER) {
+ ItemStack timerStack = lower.getStackInSlot(lower.getSizeInventory() - 5);
+ if (timerStack == null) {
+ return;
+ }
- boolean yepClock = timerStack.getItem() == Items.clock;
- if (yepClock) {
- UltrasequencerItem current = ultraSequencerOrder.get(ultrasequencerReplayIndex);
- if (current == null) {
- return true;
- }
- long currentTime = System.currentTimeMillis();
- if (currentTime - millisLastClick > 150 &&
- (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks1 ||
- current.containerIndex == slotId)) {
- ultrasequencerReplayIndex++;
- Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
- 2, mode, Minecraft.getMinecraft().thePlayer
- );
- millisLastClick = currentTime;
- }
- /*if (currentTime - millisLastClick > 150) {
- if (current.containerIndex == slotId) {
- ultrasequencerReplayIndex++;
- }
- Minecraft.getMinecraft().playerController.windowClick(windowId, slotId,
- 2, mode, Minecraft.getMinecraft().thePlayer);
- millisLastClick = currentTime;
- }*/
- return true;
- } else {
- return true;
- }
- } else if (currentSolver == SolverType.SUPERPAIRS) {
- lastSlotClicked = slotId;
+ boolean yepClock = timerStack.getItem() == Items.clock;
+ if (yepClock) {
+ UltrasequencerItem current = ultraSequencerOrder.get(ultrasequencerReplayIndex);
+ long currentTime = System.currentTimeMillis();
+ if (current == null) {
+ event.setCanceled(true);
+ return;
+ }
+ if (currentTime - millisLastClick > 150 &&
+ (!NotEnoughUpdates.INSTANCE.config.enchantingSolvers.preventMisclicks1 ||
+ current.containerIndex == event.slotId || Keyboard.getEventKey() == Keyboard.KEY_LSHIFT) &&
+ (event.slotId < 45 && event.slotId > 8)) {
+ ultrasequencerReplayIndex++;
+ millisLastClick = currentTime;
+ event.usePickblockInstead();
+ return;
}
}
+ event.setCanceled(true);
+ } else if (currentSolver == SolverType.SUPERPAIRS) {
+ lastSlotClicked = event.slotId;
}
- return false;
}
public static void processInventoryContents(boolean fromTick) {
@@ -573,4 +583,8 @@ public class EnchantingSolvers {
processInventoryContents(true);
}
+
+ public static boolean disableButtons() {
+ return currentSolver != SolverType.NONE && NotEnoughUpdates.INSTANCE.config.enchantingSolvers.hideButtons;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
index 725d4b9d..75f1b427 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.common.reflect.TypeToken;
@@ -21,70 +40,305 @@ import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.stream.Collectors;
public class FairySouls {
+ private static FairySouls instance = null;
private static final String unknownProfile = "unknown";
- private static List<BlockPos> currentSoulList = null;
- private static List<BlockPos> currentSoulListClose = null;
- private static HashMap<String, HashMap<String, Set<Integer>>> loadedFoundSouls = new HashMap<>();
- private static HashMap<String, Set<Integer>> getFoundSoulsForProfile() {
+ private boolean trackSouls;
+ private boolean showSouls;
+ private HashMap<String, HashMap<String, Set<Integer>>> allProfilesFoundSouls = new HashMap<>();
+ private List<BlockPos> allSoulsInCurrentLocation;
+ private Set<Integer> foundSoulsInLocation;
+ private TreeMap<Double, BlockPos> missingSoulsDistanceSqMap;
+ private List<BlockPos> closestMissingSouls;
+ private String currentLocation;
+ private BlockPos lastPlayerPos;
+
+ public static FairySouls getInstance() {
+ if (instance == null) {
+ instance = new FairySouls();
+ }
+ return instance;
+ }
+
+ @SubscribeEvent
+ public void onWorldLoad(WorldEvent.Load event) {
+ currentLocation = null;
+ trackSouls = NotEnoughUpdates.INSTANCE.config.misc.trackFairySouls;
+ showSouls = NotEnoughUpdates.INSTANCE.config.misc.fariySoul;
+ }
+
+ public void initializeLocation() {
+ if (!trackSouls || currentLocation == null) {
+ return;
+ }
+
+ foundSoulsInLocation = null;
+ closestMissingSouls = new ArrayList<>();
+ missingSoulsDistanceSqMap = new TreeMap<>();
+ lastPlayerPos = BlockPos.ORIGIN;
+
+ allSoulsInCurrentLocation = loadLocationFairySoulsFromConfig(currentLocation);
+ if (allSoulsInCurrentLocation == null) {
+ return;
+ }
+
+ foundSoulsInLocation = getFoundSoulsForProfile()
+ .computeIfAbsent(currentLocation, k -> new HashSet<>());
+ refreshMissingSoulInfo(true);
+ }
+
+ private void refreshMissingSoulInfo(boolean force) {
+ if (allSoulsInCurrentLocation == null) return;
+
+ BlockPos currentPlayerPos = Minecraft.getMinecraft().thePlayer.getPosition();
+ if (lastPlayerPos.equals(currentPlayerPos) && !force) {
+ return;
+ }
+ lastPlayerPos = currentPlayerPos;
+
+ missingSoulsDistanceSqMap.clear();
+ for (int i = 0; i < allSoulsInCurrentLocation.size(); i++) {
+ if (foundSoulsInLocation.contains(i)) {
+ continue;
+ }
+ BlockPos pos = allSoulsInCurrentLocation.get(i);
+ double distSq = pos.distanceSq(lastPlayerPos);
+ missingSoulsDistanceSqMap.put(distSq, pos);
+ }
+ closestMissingSouls.clear();
+ if (missingSoulsDistanceSqMap.isEmpty()) {
+ return;
+ }
+
+ // rebuild the list of the closest ones
+ int maxSouls = 15;
+ int souls = 0;
+ for (BlockPos pos : missingSoulsDistanceSqMap.values()) {
+ closestMissingSouls.add(pos);
+ if (++souls >= maxSouls) break;
+ }
+ }
+
+ private int interpolateColors(int color1, int color2, double factor) {
+ int r1 = ((color1 >> 16) & 0xff);
+ int g1 = ((color1 >> 8) & 0xff);
+ int b1 = (color1 & 0xff);
+
+ int r2 = (color2 >> 16) & 0xff;
+ int g2 = (color2 >> 8) & 0xff;
+ int b2 = color2 & 0xff;
+
+ int r3 = r1 + (int) Math.round(factor * (r2 - r1));
+ int g3 = g1 + (int) Math.round(factor * (g2 - g1));
+ int b3 = b1 + (int) Math.round(factor * (b2 - b1));
+
+ return (r3 & 0xff) << 16 |
+ (g3 & 0xff) << 8 |
+ (b3 & 0xff);
+ }
+
+ private double normalize(double value, double min, double max) {
+ return ((value - min) / (max - min));
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ if (!showSouls || !trackSouls || currentLocation == null || closestMissingSouls.isEmpty()) {
+ return;
+ }
+
+ int closeColor = 0x772991; // 0xa839ce
+ int farColor = 0xCEB4D1;
+ double farSoulDistSq = lastPlayerPos.distanceSq(closestMissingSouls.get(closestMissingSouls.size() - 1));
+ for (BlockPos currentSoul : closestMissingSouls) {
+ double currentDistSq = lastPlayerPos.distanceSq(currentSoul);
+ double factor = normalize(currentDistSq, 0.0, farSoulDistSq);
+ int rgb = interpolateColors(closeColor, farColor, Math.min(0.40, factor));
+ RenderUtils.renderBeaconBeamOrBoundingBox(currentSoul, rgb, 1.0f, event.partialTicks);
+ }
+ }
+
+ public void setShowFairySouls(boolean enabled) {
+ NotEnoughUpdates.INSTANCE.config.misc.fariySoul = enabled;
+ showSouls = enabled;
+ }
+
+ public void setTrackFairySouls(boolean enabled) {
+ NotEnoughUpdates.INSTANCE.config.misc.trackFairySouls = enabled;
+ trackSouls = enabled;
+ }
+
+ public void markClosestSoulFound() {
+ if (!trackSouls) return;
+ int closestIndex = -1;
+ double closestDistSq = 10 * 10;
+ for (int i = 0; i < allSoulsInCurrentLocation.size(); i++) {
+ BlockPos pos = allSoulsInCurrentLocation.get(i);
+
+ double distSq = pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition());
+
+ if (distSq < closestDistSq) {
+ closestDistSq = distSq;
+ closestIndex = i;
+ }
+ }
+ if (closestIndex != -1) {
+ foundSoulsInLocation.add(closestIndex);
+ refreshMissingSoulInfo(true);
+ }
+ }
+
+ public void markAllAsFound() {
+ if (!trackSouls) {
+ print(EnumChatFormatting.RED + "Fairy soul tracking is turned off, turn it on using /neu");
+ return;
+ }
+ if (allSoulsInCurrentLocation == null) {
+ print(EnumChatFormatting.RED + "No fairy souls found in your current world");
+ return;
+ }
+ for (int i = 0; i < allSoulsInCurrentLocation.size(); i++) {
+ foundSoulsInLocation.add(i);
+ }
+ refreshMissingSoulInfo(true);
+
+ print(EnumChatFormatting.DARK_PURPLE + "Marked all fairy souls as found");
+ }
+
+ public void markAllAsMissing() {
+ if (!trackSouls) {
+ print(EnumChatFormatting.RED + "Fairy soul tracking is turned off, turn it on using /neu");
+ return;
+ }
+ if (allSoulsInCurrentLocation == null) {
+ print(EnumChatFormatting.RED + "No fairy souls found in your current world");
+ return;
+ }
+ foundSoulsInLocation.clear();
+ refreshMissingSoulInfo(true);
+
+ print(EnumChatFormatting.DARK_PURPLE + "Marked all fairy souls as not found");
+ }
+
+ private HashMap<String, Set<Integer>> getFoundSoulsForProfile() {
String profile = SBInfo.getInstance().currentProfile;
if (profile == null) {
- if (loadedFoundSouls.containsKey(unknownProfile))
- return loadedFoundSouls.get(unknownProfile);
+ if (allProfilesFoundSouls.containsKey(unknownProfile))
+ return allProfilesFoundSouls.get(unknownProfile);
} else {
profile = profile.toLowerCase(Locale.getDefault());
- if (loadedFoundSouls.containsKey(unknownProfile)) {
- HashMap<String, Set<Integer>> unknownProfileData = loadedFoundSouls.remove(unknownProfile);
- loadedFoundSouls.put(profile, unknownProfileData);
+ if (allProfilesFoundSouls.containsKey(unknownProfile)) {
+ HashMap<String, Set<Integer>> unknownProfileData = allProfilesFoundSouls.remove(unknownProfile);
+ allProfilesFoundSouls.put(profile, unknownProfileData);
return unknownProfileData;
}
- if (loadedFoundSouls.containsKey(profile)) {
- return loadedFoundSouls.get(profile);
+ if (allProfilesFoundSouls.containsKey(profile)) {
+ return allProfilesFoundSouls.get(profile);
} else {
- //create a new entry for this profile
+ // Create a new entry for this profile
HashMap<String, Set<Integer>> profileData = new HashMap<>();
- loadedFoundSouls.put(profile, profileData);
+ allProfilesFoundSouls.put(profile, profileData);
return profileData;
}
}
return new HashMap<>();
}
- public static void load(File file, Gson gson) {
- loadedFoundSouls = new HashMap<>();
+ private static List<BlockPos> loadLocationFairySoulsFromConfig(String currentLocation) {
+ JsonObject fairySoulList = Constants.FAIRYSOULS;
+ if (fairySoulList == null) {
+ return null;
+ }
+
+ if (!fairySoulList.has(currentLocation) || !fairySoulList.get(currentLocation).isJsonArray()) {
+ return null;
+ }
+
+ JsonArray locations = fairySoulList.get(currentLocation).getAsJsonArray();
+ List<BlockPos> locationSouls = new ArrayList<>();
+ for (int i = 0; i < locations.size(); i++) {
+ try {
+ String coord = locations.get(i).getAsString();
+
+ String[] split = coord.split(",");
+ if (split.length == 3) {
+ String xS = split[0];
+ String yS = split[1];
+ String zS = split[2];
+
+ int x = Integer.parseInt(xS);
+ int y = Integer.parseInt(yS);
+ int z = Integer.parseInt(zS);
+
+ locationSouls.add(new BlockPos(x, y, z));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ if (locationSouls.size() == 0) {
+ return null;
+ }
+
+ return locationSouls;
+ }
+
+ public void loadFoundSoulsForAllProfiles(File file, Gson gson) {
+ allProfilesFoundSouls = new HashMap<>();
String fileContent;
try {
fileContent = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))
.lines()
.collect(Collectors.joining(System.lineSeparator()));
} catch (FileNotFoundException e) {
+ // it is possible that the collected_fairy_souls.json won't exist
return;
}
try {
//noinspection UnstableApiUsage
Type multiProfileSoulsType = new TypeToken<HashMap<String, HashMap<String, Set<Integer>>>>() {}.getType();
- loadedFoundSouls = gson.fromJson(fileContent, multiProfileSoulsType);
+ allProfilesFoundSouls = gson.fromJson(fileContent, multiProfileSoulsType);
+ if (allProfilesFoundSouls == null){
+ allProfilesFoundSouls = new HashMap<>();
+ }
} catch (JsonSyntaxException e) {
//The file is in the old format, convert it to the new one and set the profile to unknown
try {
//noinspection UnstableApiUsage
Type singleProfileSoulsType = new TypeToken<HashMap<String, Set<Integer>>>() {}.getType();
- loadedFoundSouls.put(unknownProfile, gson.fromJson(fileContent, singleProfileSoulsType));
+ allProfilesFoundSouls.put(unknownProfile, gson.fromJson(fileContent, singleProfileSoulsType));
} catch (JsonSyntaxException e2) {
System.err.println("Can't read file containing collected fairy souls, resetting.");
}
}
}
- public static void save(File file, Gson gson) {
+ public void saveFoundSoulsForAllProfiles(File file, Gson gson) {
try {
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
@@ -95,78 +349,24 @@ public class FairySouls {
StandardCharsets.UTF_8
))
) {
- writer.write(gson.toJson(loadedFoundSouls));
+ writer.write(gson.toJson(allProfilesFoundSouls));
}
- } catch (IOException ignored) {
+ } catch (IOException e) {
+ e.printStackTrace();
}
}
- public static void tick() {
- if (!NotEnoughUpdates.INSTANCE.config.misc.fariySoul) return;
-
- if (Minecraft.getMinecraft().theWorld == null) {
- currentSoulList = null;
- return;
- }
-
- JsonObject fairySouls = Constants.FAIRYSOULS;
- if (fairySouls == null) return;
-
+ public void tick() {
+ if (!trackSouls) return;
String location = SBInfo.getInstance().getLocation();
- if (location == null) {
- currentSoulList = null;
- return;
- }
+ if (location == null || location.isEmpty()) return;
- if (currentSoulList == null) {
- if (fairySouls.has(location) && fairySouls.get(location).isJsonArray()) {
- JsonArray locations = fairySouls.get(location).getAsJsonArray();
- currentSoulList = new ArrayList<>();
- for (int i = 0; i < locations.size(); i++) {
- try {
- String coord = locations.get(i).getAsString();
-
- String[] split = coord.split(",");
- if (split.length == 3) {
- String xS = split[0];
- String yS = split[1];
- String zS = split[2];
-
- int x = Integer.parseInt(xS);
- int y = Integer.parseInt(yS);
- int z = Integer.parseInt(zS);
-
- currentSoulList.add(new BlockPos(x, y, z));
- }
- } catch (Exception ignored) {
- }
- }
- }
+ if (!location.equals(currentLocation)) {
+ currentLocation = location;
+ initializeLocation();
}
- if (currentSoulList != null && !currentSoulList.isEmpty()) {
- TreeMap<Double, BlockPos> distanceSqMap = new TreeMap<>();
-
- HashMap<String, Set<Integer>> foundSouls = getFoundSoulsForProfile();
-
- Set<Integer> found = foundSouls.computeIfAbsent(location, k -> new HashSet<>());
-
- for (int i = 0; i < currentSoulList.size(); i++) {
- if (found.contains(i)) continue;
-
- BlockPos pos = currentSoulList.get(i);
- double distSq = pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition());
- distanceSqMap.put(distSq, pos);
- }
-
- int maxSouls = 15;
- int souls = 0;
- currentSoulListClose = new ArrayList<>();
- for (BlockPos pos : distanceSqMap.values()) {
- currentSoulListClose.add(pos);
- if (++souls >= maxSouls) break;
- }
- }
+ refreshMissingSoulInfo(false);
}
private static void print(String s) {
@@ -186,63 +386,24 @@ public class FairySouls {
}
print(EnumChatFormatting.GOLD.toString() + EnumChatFormatting.BOLD + " Commands:");
print(EnumChatFormatting.YELLOW + "/neusouls help - Display this message");
- print(EnumChatFormatting.YELLOW + "/neusouls on/off - Enable/disable the waypoint markers");
+ print(EnumChatFormatting.YELLOW + "/neusouls on/off - Enable/disable showing waypoint markers");
print(EnumChatFormatting.YELLOW +
"/neusouls clear/unclear - Marks every waypoint in your current world as completed/uncompleted");
print("");
}
@SubscribeEvent
- public void onWorldUnload(WorldEvent.Unload event) {
- currentSoulList = null;
- }
-
- @SubscribeEvent
public void onChatReceived(ClientChatReceivedEvent event) {
- if (currentSoulList == null) return;
+ if (!trackSouls || event.type == 2) return;
- if (event.message.getFormattedText().equals("\u00A7r\u00A7dYou have already found that Fairy Soul!\u00A7r") ||
- event.message.getFormattedText().equals(
- "\u00A7d\u00A7lSOUL! \u00A7fYou found a \u00A7r\u00A7dFairy Soul\u00A7r\u00A7f!\u00A7r")) {
- String location = SBInfo.getInstance().getLocation();
- if (location == null) return;
-
- int closestIndex = -1;
- double closestDistSq = 10 * 10;
- for (int i = 0; i < currentSoulList.size(); i++) {
- BlockPos pos = currentSoulList.get(i);
-
- double distSq = pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition());
-
- if (distSq < closestDistSq) {
- closestDistSq = distSq;
- closestIndex = i;
- }
- }
- if (closestIndex != -1) {
- HashMap<String, Set<Integer>> foundSouls = getFoundSoulsForProfile();
- Set<Integer> found = foundSouls.computeIfAbsent(location, k -> new HashSet<>());
- found.add(closestIndex);
- }
- }
- }
-
- @SubscribeEvent
- public void onRenderLast(RenderWorldLastEvent event) {
- if (!NotEnoughUpdates.INSTANCE.config.misc.fariySoul) return;
-
- String location = SBInfo.getInstance().getLocation();
- if (location == null) return;
- if (currentSoulList == null || currentSoulList.isEmpty()) return;
-
- int rgb = 0xa839ce;
- for (BlockPos currentSoul : currentSoulListClose) {
- RenderUtils.renderBeaconBeamOrBoundingBox(currentSoul, rgb, 1.0f, event.partialTicks);
+ if (event.message.getUnformattedText().equals("You have already found that Fairy Soul!") ||
+ event.message.getUnformattedText().equals(
+ "SOUL! You found a Fairy Soul!")) {
+ markClosestSoulFound();
}
}
public static class FairySoulsCommand extends ClientCommandBase {
-
public FairySoulsCommand() {
super("neusouls");
}
@@ -258,73 +419,36 @@ public class FairySouls {
printHelp();
return;
}
- String subcommand = args[0].toLowerCase();
+ String subcommand = args[0].toLowerCase();
switch (subcommand) {
case "help":
printHelp();
- return;
+ break;
case "on":
case "enable":
+ if (!FairySouls.instance.trackSouls) {
+ print(
+ EnumChatFormatting.RED + "Fairy soul tracking is off, enable it using /neu before using this command");
+ return;
+ }
print(EnumChatFormatting.DARK_PURPLE + "Enabled fairy soul waypoints");
- NotEnoughUpdates.INSTANCE.config.misc.fariySoul = true;
- return;
+ FairySouls.getInstance().setShowFairySouls(true);
+ break;
case "off":
case "disable":
+ FairySouls.getInstance().setShowFairySouls(false);
print(EnumChatFormatting.DARK_PURPLE + "Disabled fairy soul waypoints");
- NotEnoughUpdates.INSTANCE.config.misc.fariySoul = false;
- return;
- case "clear": {
- String location = SBInfo.getInstance().getLocation();
- if (currentSoulList == null || location == null) {
- print(EnumChatFormatting.RED + "No fairy souls found in your current world");
- } else {
- HashMap<String, Set<Integer>> foundSouls = getFoundSoulsForProfile();
- Set<Integer> found = foundSouls.computeIfAbsent(location, k -> new HashSet<>());
- for (int i = 0; i < currentSoulList.size(); i++) {
- found.add(i);
- }
- String profileName = SBInfo.getInstance().currentProfile;
- if (profileName == null) {
- if (loadedFoundSouls.containsKey(unknownProfile)) {
- loadedFoundSouls.get(unknownProfile).put(location, found);
- }
- } else {
- profileName = profileName.toLowerCase();
- if (!loadedFoundSouls.containsKey(profileName)) {
- HashMap<String, Set<Integer>> profileData = new HashMap<>();
- loadedFoundSouls.put(profileName, profileData);
- }
- loadedFoundSouls.get(profileName).put(location, found);
- }
- print(EnumChatFormatting.DARK_PURPLE + "Marked all fairy souls as found");
- }
- }
- return;
+ break;
+ case "clear":
+ FairySouls.getInstance().markAllAsFound();
+ break;
case "unclear":
- String location = SBInfo.getInstance().getLocation();
- if (location == null) {
- print(EnumChatFormatting.RED + "No fairy souls found in your current world");
- } else {
- String profileName = SBInfo.getInstance().currentProfile;
- if (profileName == null) {
- if (loadedFoundSouls.containsKey(unknownProfile)) {
- loadedFoundSouls.get(unknownProfile).remove(location);
- }
- } else {
- profileName = profileName.toLowerCase();
- if (!loadedFoundSouls.containsKey(profileName)) {
- HashMap<String, Set<Integer>> profileData = new HashMap<>();
- loadedFoundSouls.put(profileName, profileData);
- }
- loadedFoundSouls.get(profileName).remove(location);
- }
- print(EnumChatFormatting.DARK_PURPLE + "Marked all fairy souls as not found");
- }
- return;
+ FairySouls.getInstance().markAllAsMissing();
+ break;
+ default:
+ print(EnumChatFormatting.RED + "Unknown subcommand: " + subcommand);
}
-
- print(EnumChatFormatting.RED + "Unknown subcommand: " + subcommand);
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java
deleted file mode 100644
index 12e65e65..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java
+++ /dev/null
@@ -1,293 +0,0 @@
-package io.github.moulberry.notenoughupdates.miscfeatures;
-
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.Gui;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.RenderGlobal;
-import net.minecraft.client.renderer.WorldRenderer;
-import net.minecraft.client.renderer.chunk.CompiledChunk;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.client.renderer.vertex.VertexFormat;
-import net.minecraft.client.renderer.vertex.VertexFormatElement;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.EntityLivingBase;
-import net.minecraft.network.play.server.S07PacketRespawn;
-import net.minecraft.util.MathHelper;
-import net.minecraft.util.ResourceLocation;
-import net.minecraftforge.client.event.RenderLivingEvent;
-import net.minecraftforge.client.event.RenderWorldLastEvent;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import org.lwjgl.input.Keyboard;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.util.glu.Project;
-
-import java.nio.ByteBuffer;
-import java.util.List;
-
-public class FancyPortals {
- private static final ResourceLocation[] RENDERS = new ResourceLocation[6];
-
- static {
- for (int i = 0; i < 6; i++) {
- RENDERS[i] = new ResourceLocation("notenoughupdates:portal_panoramas/nether/pansc-" + (i + 1) + ".png");
- }
- }
-
- public static int perspectiveId = -1;
-
- public static boolean overridePerspective() {
- if (perspectiveId >= 0 && !Keyboard.isKeyDown(Keyboard.KEY_K)) {
- if (perspectiveId == 0) {
- GlStateManager.matrixMode(5889);
- GlStateManager.loadIdentity();
- GlStateManager.ortho(0.0D, 7, 7, 0.0D, -100D, 100D);
- GlStateManager.scale(1, 1, -1);
- GlStateManager.matrixMode(5888);
- GlStateManager.loadIdentity();
- GlStateManager.translate(3.5F, 3.5F, -1.0F);
- GlStateManager.rotate(-90, 1, 0, 0);
- } else if (perspectiveId <= 4) {
- GlStateManager.matrixMode(5889);
- GlStateManager.loadIdentity();
- Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2);
- GlStateManager.matrixMode(5888);
- GlStateManager.loadIdentity();
- GlStateManager.rotate(perspectiveId * 90, 0, 1, 0);
- GlStateManager.translate(0, -3.5f, 0);
- } else {
- GlStateManager.matrixMode(5889);
- GlStateManager.loadIdentity();
- Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2);
- GlStateManager.matrixMode(5888);
- GlStateManager.loadIdentity();
- GlStateManager.rotate(-90, 1, 0, 0);
- GlStateManager.translate(0, -3.5f, 0);
- }
-
- return true;
- }
- return false;
- }
-
- private static WorldRenderer surfaceWorldRenderer = null;
-
- private static WorldRenderer getSurfaceWorldRenderer() {
- if (surfaceWorldRenderer != null && !Keyboard.isKeyDown(Keyboard.KEY_O)) {
- return surfaceWorldRenderer;
- }
-
- surfaceWorldRenderer = createSurfaceWorldRenderer();
-
- return surfaceWorldRenderer;
- }
-
- private static void drawPoint(WorldRenderer worldRenderer, int x, int y) {
- float xDist = 1 - Math.abs(x - 50) / 50f;
- float yDist = 1 - Math.abs(y - 50) / 50f;
- float distToEdge = Math.min(xDist, yDist);
-
- float z = 0.4142f;
- if (distToEdge < 1 / 3.5f) {
- if (y > 50 && yDist < xDist) {
- float circleH = 1.414f - distToEdge * 3.5f * 1.414f;
- z = (float) Math.sqrt(2f - circleH * circleH);
- z *= 0.4142f / 1.4142f;
- } else {
- float circleH = 1 - distToEdge * 3.5f;
- z = (float) Math.sqrt(2f - circleH * circleH) - 1;
- }
- }
-
- worldRenderer.pos(x * 7 / 100f, y * 7 / 100f, z).tex(x / 100f, y / 100f).endVertex();
- }
-
- private static WorldRenderer createSurfaceWorldRenderer() {
- WorldRenderer worldRenderer = new WorldRenderer(20 * 100 * 100);
- worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
-
- for (int x = 0; x < 100; x++) {
- for (int y = 0; y < 100; y++) {
- drawPoint(worldRenderer, x, y);
- drawPoint(worldRenderer, x, y + 1);
- drawPoint(worldRenderer, x + 1, y + 1);
- drawPoint(worldRenderer, x + 1, y);
- }
- }
-
- return worldRenderer;
- }
-
- private static long overridingRenderMillis = -1;
-
- public static void onRespawnPacket(S07PacketRespawn packet) {
- if (true) return;
- if (packet.getDimensionID() != Minecraft.getMinecraft().thePlayer.dimension) {
- overridingRenderMillis = System.currentTimeMillis();
- }
- }
-
- public static boolean shouldRenderLoadingScreen() {
- return false;
- }
-
- public static boolean shouldRenderWorldOverlay() {
- if (overridingRenderMillis > 0) {
- if (Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) {
- RenderGlobal renderGlobal = Minecraft.getMinecraft().renderGlobal;
- int loaded = 0;
- for (RenderGlobal.ContainerLocalRenderInformation info : renderGlobal.renderInfos) {
- CompiledChunk compiledchunk = info.renderChunk.compiledChunk;
-
- if (compiledchunk != CompiledChunk.DUMMY && !compiledchunk.isEmpty()) {
- if (++loaded >= 5) {
- overridingRenderMillis = -1;
- return false;
- }
- }
- }
- }
- if (System.currentTimeMillis() - overridingRenderMillis > 1000) {
- overridingRenderMillis = -1;
- return false;
- }
- return true;
- }
- return false;
- }
-
- public static void onUpdateCameraAndRender(float partialTicks, long nanoTime) {
- if (overridingRenderMillis > 0) {
- if (Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) {
- Minecraft.getMinecraft().thePlayer.timeInPortal = 0.3f;
- Minecraft.getMinecraft().thePlayer.prevTimeInPortal = 0.3f;
- }
-
- GlStateManager.rotate(90, 0, 1, 0);
- renderWorld();
-
- Minecraft.getMinecraft().ingameGUI.renderGameOverlay(partialTicks);
- }
- }
-
- @SubscribeEvent
- public void onRenderEntityYeeter(RenderLivingEvent.Pre<EntityLivingBase> event) {
- /*if(!Keyboard.isKeyDown(Keyboard.KEY_G)) return;
- event.setCanceled(true);
- if(event.entity instanceof EntityPlayer) {
- EntityPlayer player = (EntityPlayer) event.entity;
- if(player.getUniqueID().version() == 4) {
- event.setCanceled(true);
- }
- }*/
- }
-
- private static void renderWorld() {
- for (int i = 5; i >= 0; i--) {
- GlStateManager.pushMatrix();
-
- GlStateManager.disableDepth();
- GlStateManager.disableLighting();
-
- GlStateManager.rotate(180, 0, 0, 1);
- GlStateManager.rotate(-90, 0, 1, 0);
-
- if (i != 0) GlStateManager.translate(0, -3.49, 0);
-
- switch (i) {
- case 1:
- GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F);
- break;
- case 2:
- GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F);
- break;
- case 3:
- GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F);
- break;
- case 5:
- GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F);
- break;
- case 0:
- GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F);
- break;
- }
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(RENDERS[i]);
- GlStateManager.color(1, 1, 1, 1);
- if (i != 0) GlStateManager.translate(0, 0, 3.49);
-
- if (i != 0) {
- GlStateManager.translate(-3.5f, -3.5f, 0);
- WorldRenderer worldRenderer = getSurfaceWorldRenderer();
- VertexFormat vertexformat = worldRenderer.getVertexFormat();
- int stride = vertexformat.getNextOffset();
- ByteBuffer bytebuffer = worldRenderer.getByteBuffer();
- List<VertexFormatElement> list = vertexformat.getElements();
-
- for (int index = 0; index < list.size(); index++) {
- VertexFormatElement vertexformatelement = list.get(index);
- vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer);
- }
-
- GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount());
-
- for (int index = 0; index < list.size(); index++) {
- VertexFormatElement vertexformatelement = list.get(index);
- vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer);
- }
- } else {
- Utils.drawTexturedRect(-3.5f, -3.5f, 7, 7, i == 0 ? GL11.GL_NEAREST : GL11.GL_LINEAR);
- }
-
- GlStateManager.enableDepth();
-
- GlStateManager.popMatrix();
- }
- }
-
- @SubscribeEvent
- public void onRenderLast(RenderWorldLastEvent event) {
- if (true) return;
- if (!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled())
- Minecraft.getMinecraft().getFramebuffer().enableStencil();
-
- GL11.glEnable(GL11.GL_STENCIL_TEST);
- GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
- GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE);
- GL11.glStencilMask(0xFF);
- GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
- GlStateManager.enableDepth();
- GlStateManager.enableCull();
- GlStateManager.cullFace(GL11.GL_BACK);
-
- GL11.glColorMask(false, false, false, false);
-
- Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
- double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * event.partialTicks;
- double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * event.partialTicks;
- double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * event.partialTicks;
- GlStateManager.pushMatrix();
-
- GlStateManager.translate(-viewerX + 12 + 5 / 16f, -viewerY + 100, -viewerZ + 39);
- GlStateManager.rotate(90, 0, 1, 0);
- Gui.drawRect(0, 5, 3, 0, 0xffffffff);
- GlStateManager.rotate(180, 0, 1, 0);
- GlStateManager.translate(-3, 0, -6 / 16f);
- Gui.drawRect(0, 5, 3, 0, 0xffffffff);
-
- GlStateManager.popMatrix();
-
- GL11.glColorMask(true, true, true, true);
-
- // Only pass stencil test if equal to 1
- GL11.glStencilMask(0x00);
- GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
-
- GlStateManager.translate(-viewerX + 12, -viewerY + 100, -viewerZ + 37.5f);
-
- renderWorld();
-
- GL11.glDisable(GL11.GL_STENCIL_TEST);
- GlStateManager.enableCull();
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java
index 34e849d0..13a078a2 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java
@@ -1,8 +1,29 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.ChromaColour;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.PositionedSound;
@@ -11,8 +32,10 @@ import net.minecraft.client.particle.EntityFX;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.projectile.EntityFishHook;
+import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
@@ -21,7 +44,13 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.opengl.GL11;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class FishingHelper {
private static final FishingHelper INSTANCE = new FishingHelper();
@@ -63,46 +92,92 @@ public class FishingHelper {
private int pingDelayTicks = 0;
private final List<Integer> pingDelayList = new ArrayList<>();
private int buildupSoundDelay = 0;
+ private boolean playedSound = false;
private static final ResourceLocation FISHING_WARNING_EXCLAM = new ResourceLocation(
"notenoughupdates:fishing_warning_exclam.png");
+ public boolean renderWarning() {
+ if (warningState == PlayerWarningState.NOTHING) return false;
+
+ if (!NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarning &&
+ warningState == PlayerWarningState.FISH_INCOMING)
+ return false;
+ if (!NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarningR &&
+ warningState == PlayerWarningState.FISH_HOOKED)
+ return false;
+
+ float offset = warningState == PlayerWarningState.FISH_HOOKED ? 0.5f : 0f;
+
+ float centerOffset = 0.5f / 8f;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(FISHING_WARNING_EXCLAM);
+ Utils.drawTexturedRect(
+ centerOffset - 4f / 8f,
+ -20 / 8f,
+ 1f,
+ 2f,
+ 0 + offset,
+ 0.5f + offset,
+ 0,
+ 1,
+ GL11.GL_NEAREST
+ );
+ return true;
+ }
+
public void onRenderBobber(EntityFishHook hook) {
- if (Minecraft.getMinecraft().thePlayer.fishEntity == hook && warningState != PlayerWarningState.NOTHING) {
-
- if (!NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarning &&
- warningState == PlayerWarningState.FISH_INCOMING)
- return;
- if (!NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarningR &&
- warningState == PlayerWarningState.FISH_HOOKED)
- return;
-
- GlStateManager.disableCull();
- GlStateManager.disableLighting();
- GL11.glDepthFunc(GL11.GL_ALWAYS);
- GlStateManager.scale(1, -1, 1);
-
- float offset = warningState == PlayerWarningState.FISH_HOOKED ? 0.5f : 0f;
-
- float centerOffset = 0.5f / 8f;
- Minecraft.getMinecraft().getTextureManager().bindTexture(FISHING_WARNING_EXCLAM);
- Utils.drawTexturedRect(
- centerOffset - 4f / 8f,
- -20 / 8f,
- 1f,
- 2f,
- 0 + offset,
- 0.5f + offset,
- 0,
- 1,
- GL11.GL_NEAREST
- );
-
- GlStateManager.scale(1, -1, 1);
- GL11.glDepthFunc(GL11.GL_LEQUAL);
- GlStateManager.enableLighting();
- GlStateManager.enableCull();
+ if (Minecraft.getMinecraft().thePlayer.fishEntity != hook) return;
+ GlStateManager.pushMatrix();
+ GlStateManager.disableCull();
+ GlStateManager.disableLighting();
+ GL11.glDepthFunc(GL11.GL_ALWAYS);
+ GlStateManager.scale(1, -1, 1);
+ boolean isExclamationMarkPresent = renderWarning();
+ GlStateManager.scale(0.1, 0.1, 1);
+ drawFishingTimer(hook, isExclamationMarkPresent);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ GlStateManager.enableLighting();
+ GlStateManager.enableCull();
+ GlStateManager.popMatrix();
+ }
+
+ private void drawFishingTimer(EntityFishHook hook, boolean isExclamationMarkPresent) {
+ if (!NotEnoughUpdates.INSTANCE.config.fishing.fishingTimer) return;
+ float baseHeight = isExclamationMarkPresent ? 20 : 0;
+ int ticksExisted = hook.ticksExisted;
+ float seconds = ticksExisted / 20F;
+ int color;
+ if (seconds >= 30) {
+ color = ChromaColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.fishing.fishingTimerColor30SecPlus);
+ if (NotEnoughUpdates.INSTANCE.config.fishing.fishingSound30Sec && !playedSound) {
+ ISound sound = new PositionedSound(new ResourceLocation("random.orb")) {{
+ volume = 50;
+ pitch = 2f;
+ repeat = false;
+ repeatDelay = 0;
+ attenuationType = ISound.AttenuationType.NONE;
+ }};
+
+ float oldLevel = Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.RECORDS);
+ Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.RECORDS, 1);
+ Minecraft.getMinecraft().getSoundHandler().playSound(sound);
+ Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.RECORDS, oldLevel);
+ playedSound = true;
+ }
+ } else {
+ color = ChromaColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.fishing.fishingTimerColor);
+ playedSound = false;
}
+
+ Utils.drawStringCentered(
+ String.format("%.02fs", seconds),
+ Minecraft.getMinecraft().fontRendererObj,
+ 0,
+ -baseHeight - Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT,
+ false,
+ color
+ );
+
}
public void addEntity(int entityId, Entity entity) {
@@ -257,7 +332,17 @@ public class FishingHelper {
double angle2
) {
double dY = particleY - hook.posY;
- if (Math.abs(dY) > 0.5f) {
+ double tolerance = 0.5F;
+ if (hook.worldObj != null) {
+ for (int i = -2; i < 2; i++) {
+ IBlockState state = hook.worldObj.getBlockState(new BlockPos(particleX, particleY + i, particleZ));
+ if (state != null && (state.getBlock() == Blocks.flowing_lava
+ || state.getBlock() == Blocks.flowing_water
+ || state.getBlock() == Blocks.lava))
+ tolerance = 2.0F;
+ }
+ }
+ if (Math.abs(dY) > tolerance) {
return HookPossibleRet.NOT_POSSIBLE;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java
index 96522d34..f2b13abc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
index 655364ef..e1b9d567 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.gson.Gson;
@@ -18,7 +37,13 @@ import org.lwjgl.opengl.GL14;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.function.Consumer;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemRarityHalo.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemRarityHalo.java
index 88c7261c..79dd18f1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemRarityHalo.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemRarityHalo.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -5,7 +24,11 @@ import io.github.moulberry.notenoughupdates.util.NEUResourceManager;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
-import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
index b56737e7..12e0301b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java
index 05d75c26..ad0dd66d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.gson.Gson;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java
new file mode 100644
index 00000000..6244c32c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/Navigation.java
@@ -0,0 +1,418 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
+import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
+import io.github.moulberry.notenoughupdates.miscgui.GuiNavigation;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.Vec3i;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.event.entity.EntityJoinWorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.InputEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.input.Keyboard;
+
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class Navigation {
+
+ private List<Teleporter> teleporters = new ArrayList<>();
+ private Map<String, String> areaNames = new HashMap<>();
+ private Map<String, WarpPoint> warps = new HashMap<>();
+ private Map<String, JsonObject> waypoints = new HashMap<>();
+
+ public Map<String, JsonObject> getWaypoints() {
+ return waypoints;
+ }
+
+ public static class WarpPoint {
+ public final BlockPos blockPos;
+ public final String warpName, modeName;
+
+ public WarpPoint(double x, double y, double z, String warpName, String modeName) {
+ this.blockPos = new BlockPos(x, y, z);
+ this.warpName = warpName;
+ this.modeName = modeName;
+ }
+ }
+
+ public static class Teleporter {
+ public final double x, y, z;
+ public final String from, to;
+
+ public Teleporter(double x, double y, double z, String from, String to) {
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.from = from;
+ this.to = to;
+ }
+ }
+
+ private NotEnoughUpdates neu;
+
+ public Navigation(NotEnoughUpdates notEnoughUpdates) {
+ neu = notEnoughUpdates;
+ }
+
+ /* JsonObject (x,y,z,island,displayname) */
+ private JsonObject currentlyTrackedWaypoint = null;
+ private BlockPos position = null;
+ private String island = null;
+ private String displayName = null;
+ private String internalname = null;
+ private String warpAgainTo = null;
+ private int lastInvHashcode = 0;
+ private Instant warpAgainTiming = null;
+
+ private Teleporter nextTeleporter = null;
+
+ public boolean isValidWaypoint(JsonObject object) {
+ return object.has("x")
+ && object.has("y")
+ && object.has("z")
+ && object.has("island")
+ && object.has("displayname")
+ && object.has("internalname");
+ }
+
+ public void trackWaypoint(String trackNow) {
+ if (trackNow == null) {
+ trackWaypoint((JsonObject) null);
+ } else {
+ JsonObject jsonObject = waypoints.get(trackNow);
+ if (jsonObject == null) {
+ showError(
+ "Could not track waypoint " + trackNow + ". This is likely due to an outdated or broken repository.",
+ true
+ );
+ return;
+ }
+ trackWaypoint(jsonObject);
+ }
+ }
+
+ public void trackWaypoint(JsonObject trackNow) {
+ if (trackNow != null && !isValidWaypoint(trackNow)) {
+ showError("Could not track waypoint. This is likely due to an outdated or broken repository.", true);
+ return;
+ }
+ if (!neu.config.hidden.hasOpenedWaypointMenu)
+ NotificationHandler.displayNotification(Arrays.asList(
+ "You just tracked a waypoint.",
+ "Press [N] to open the waypoint menu to untrack it",
+ "or to find other waypoints to track.",
+ "Press [X] to close this message."
+ ), true, false);
+ currentlyTrackedWaypoint = trackNow;
+ updateData();
+ }
+
+ @SubscribeEvent
+ public void onRepositoryReload(RepositoryReloadEvent event) {
+ JsonObject obj = Utils.getConstant("islands", neu.manager.gson);
+ List<Teleporter> teleporters = JsonUtils.getJsonArrayOrEmpty(obj, "teleporters", jsonElement -> {
+ JsonObject teleporterObj = jsonElement.getAsJsonObject();
+ return new Teleporter(
+ teleporterObj.get("x").getAsDouble(),
+ teleporterObj.get("y").getAsDouble(),
+ teleporterObj.get("z").getAsDouble(),
+ teleporterObj.get("from").getAsString(),
+ teleporterObj.get("to").getAsString()
+ );
+ });
+ for (Teleporter teleporter : teleporters) {
+ if (teleporter.from.equals(teleporter.to)) {
+ showError("Found self referencing teleporter: " + teleporter.from, true);
+ }
+ }
+ this.teleporters = teleporters;
+ this.waypoints = NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation().values().stream()
+ .filter(this::isValidWaypoint)
+ .collect(Collectors.toMap(it -> it.get("internalname").getAsString(), it -> it));
+ this.areaNames = JsonUtils.transformJsonObjectToMap(obj.getAsJsonObject("area_names"), JsonElement::getAsString);
+ this.warps = JsonUtils.getJsonArrayOrEmpty(obj, "island_warps", jsonElement -> {
+ JsonObject warpObject = jsonElement.getAsJsonObject();
+ return new WarpPoint(
+ warpObject.get("x").getAsDouble(),
+ warpObject.get("y").getAsDouble(),
+ warpObject.get("z").getAsDouble(),
+ warpObject.get("warp").getAsString(),
+ warpObject.get("mode").getAsString()
+ );
+ }).stream().collect(Collectors.toMap(it -> it.warpName, it -> it));
+ }
+
+ @SubscribeEvent
+ public void onKeybindPressed(InputEvent.KeyInputEvent event) {
+ if (!Keyboard.getEventKeyState()) return;
+ int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
+ if (neu.config.misc.keybindWaypoint == key) {
+ if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ if (currentlyTrackedWaypoint != null) {
+ useWarpCommand();
+ }
+ } else {
+ Minecraft.getMinecraft().displayGuiScreen(new GuiNavigation());
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onGuiTick(TickEvent.ClientTickEvent event) {
+ if (event.phase != TickEvent.Phase.START) return;
+ if (Minecraft.getMinecraft().theWorld == null) return;
+ if (Minecraft.getMinecraft().thePlayer == null) return;
+ if (neu.config.getProfileSpecific() == null) return;
+
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) {
+ GuiChest currentScreen = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest container = (ContainerChest) currentScreen.inventorySlots;
+ if (container.getLowerChestInventory().getDisplayName().getUnformattedText().equals("Fast Travel")) {
+ int hashCode = container.getInventory().hashCode();
+ if (hashCode == lastInvHashcode) return;
+ lastInvHashcode = hashCode;
+ for (ItemStack stackInSlot : container.getInventory()) {
+ if (stackInSlot == null) continue;
+ List<String> lore = ItemUtils.getLore(stackInSlot);
+ if (lore.isEmpty())
+ continue;
+ String warpLine = Utils.cleanColour(lore.get(0));
+ if (!warpLine.startsWith("/warp ")) continue;
+ String warpName = warpLine.substring(6);
+ boolean isUnlocked = !lore.contains("§cWarp not unlocked!");
+ neu.config.getProfileSpecific().unlockedWarpScrolls.put(warpName, isUnlocked);
+ }
+ }
+ }
+ }
+
+ public Map<String, WarpPoint> getWarps() {
+ return warps;
+ }
+
+ public WarpPoint getClosestWarp(String mode, Vec3i position, boolean checkAvailable) {
+ double minDistance = -1;
+ HashMap<String, Boolean> unlockedWarpScrolls = neu.config.getProfileSpecific().unlockedWarpScrolls;
+ WarpPoint minWarp = null;
+ for (WarpPoint value : warps.values()) {
+ if (value.modeName.equals(mode)) {
+ if (checkAvailable && !unlockedWarpScrolls.getOrDefault(value.warpName, false))
+ continue;
+ double distance = value.blockPos.distanceSq(position);
+ if (distance < minDistance || minWarp == null) {
+ minDistance = distance;
+ minWarp = value;
+ }
+ }
+ }
+ return minWarp;
+ }
+
+ public void useWarpCommand() {
+ EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer;
+ if (currentlyTrackedWaypoint == null || thePlayer == null) return;
+ WarpPoint closestWarp = getClosestWarp(island, position, true);
+ if (closestWarp == null) {
+ showError("Could not find an unlocked warp that could be used.", false);
+ return;
+ }
+
+ if (!island.equals(SBInfo.getInstance().mode)) {
+ warpAgainTiming = Instant.now();
+ warpAgainTo = closestWarp.warpName;
+ } else if (thePlayer.getDistanceSq(position) < closestWarp.blockPos.distanceSq(position)) {
+ showError("You are already on the same island and nearer than the closest unlocked warp scroll.", false);
+ return;
+ }
+ thePlayer.sendChatMessage("/warp " + closestWarp.warpName);
+ }
+
+ @SubscribeEvent
+ public void onTeleportDone(EntityJoinWorldEvent event) {
+ if (neu.config.misc.warpTwice
+ && event.entity == Minecraft.getMinecraft().thePlayer
+ && warpAgainTo != null
+ && warpAgainTiming != null
+ && warpAgainTiming.plusSeconds(1).isAfter(Instant.now())) {
+ warpAgainTiming = null;
+ String savedWarpAgain = warpAgainTo;
+ warpAgainTo = null;
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/warp " + savedWarpAgain);
+ }
+ }
+
+ public String getNameForAreaMode(String mode) {
+ return areaNames.get(mode);
+ }
+
+ public String getNameForAreaModeOrUnknown(String mode) {
+ return areaNames.getOrDefault(mode, "Unknown");
+ }
+
+ public void untrackWaypoint() {
+ trackWaypoint((JsonObject) null);
+ }
+
+ public JsonObject getTrackedWaypoint() {
+ return currentlyTrackedWaypoint;
+ }
+
+ public String getIsland() {
+ return island;
+ }
+
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public BlockPos getPosition() {
+ return position;
+ }
+
+ public String getInternalname() {
+ return internalname;
+ }
+
+ private void updateData() {
+ if (currentlyTrackedWaypoint == null) {
+ position = null;
+ island = null;
+ displayName = null;
+ nextTeleporter = null;
+ internalname = null;
+ return;
+ }
+ position = new BlockPos(
+ currentlyTrackedWaypoint.get("x").getAsDouble(),
+ currentlyTrackedWaypoint.get("y").getAsDouble(),
+ currentlyTrackedWaypoint.get("z").getAsDouble()
+ );
+ internalname = currentlyTrackedWaypoint.get("internalname").getAsString();
+ island = currentlyTrackedWaypoint.get("island").getAsString();
+ displayName = currentlyTrackedWaypoint.get("displayname").getAsString();
+ recalculateNextTeleporter(SBInfo.getInstance().mode);
+ }
+
+ @SubscribeEvent
+ public void onLocationChange(LocationChangeEvent event) {
+ recalculateNextTeleporter(event.newLocation);
+ }
+
+ public Teleporter recalculateNextTeleporter(String from) {
+ String to = island;
+ if (from == null || to == null) return null;
+ List<Teleporter> nextTeleporter = findNextTeleporter0(from, to, new HashSet<>());
+ if (nextTeleporter == null || nextTeleporter.isEmpty()) {
+ this.nextTeleporter = null;
+ } else {
+ this.nextTeleporter = nextTeleporter.get(0);
+ }
+ return this.nextTeleporter;
+ }
+
+ private List<Teleporter> findNextTeleporter0(String from, String to, Set<String> visited) {
+ if (from.equals(to)) return new ArrayList<>();
+ if (visited.contains(from)) return null;
+ visited.add(from);
+ int minPathLength = 0;
+ List<Teleporter> minPath = null;
+ for (Teleporter teleporter : teleporters) {
+ if (!teleporter.from.equals(from)) continue;
+ List<Teleporter> nextTeleporter0 = findNextTeleporter0(teleporter.to, to, visited);
+ if (nextTeleporter0 == null) continue;
+ if (minPath == null || nextTeleporter0.size() < minPathLength) {
+ minPathLength = nextTeleporter0.size();
+ nextTeleporter0.add(0, teleporter);
+ minPath = nextTeleporter0;
+ }
+ }
+ visited.remove(from);
+ return minPath;
+ }
+
+ private void showError(String message, boolean log) {
+ EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
+ if (player != null)
+ player.addChatMessage(new ChatComponentText(EnumChatFormatting.DARK_RED +
+ "[NEU-Waypoint] " + message));
+ if (log)
+ new RuntimeException("[NEU-Waypoint] " + message).printStackTrace();
+ }
+
+ @SubscribeEvent
+ public void onEvent(TickEvent.ClientTickEvent event) {
+ if (event.phase == TickEvent.Phase.END && currentlyTrackedWaypoint != null
+ && NotEnoughUpdates.INSTANCE.config.misc.untrackCloseWaypoints
+ && island.equals(SBInfo.getInstance().mode)) {
+ EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer;
+ if (thePlayer != null && thePlayer.getDistanceSq(position) < 16)
+ untrackWaypoint();
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ if (currentlyTrackedWaypoint != null) {
+ if (island.equals(SBInfo.getInstance().mode)) {
+ RenderUtils.renderWayPoint(displayName, position, event.partialTicks);
+ } else if (nextTeleporter != null) {
+ String to = nextTeleporter.to;
+ String toName = getNameForAreaModeOrUnknown(to);
+ RenderUtils.renderWayPoint(
+ Arrays.asList("Teleporter to " + toName, "(towards " + displayName + "§r)"),
+ new BlockPos(
+ nextTeleporter.x,
+ nextTeleporter.y,
+ nextTeleporter.z
+ ), event.partialTicks
+ );
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java
new file mode 100644
index 00000000..6036d93b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NewApiKeyHelper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.network.play.client.C01PacketChatMessage;
+import net.minecraft.util.ChatComponentText;
+
+public class NewApiKeyHelper {
+ private static final NewApiKeyHelper INSTANCE = new NewApiKeyHelper();
+
+ public static NewApiKeyHelper getInstance() {
+ return INSTANCE;
+ }
+
+ public void hookPacketChatMessage(C01PacketChatMessage packet) {
+ String message = packet.getMessage().toLowerCase();
+ if (message.equals("/api new")) return;
+
+ if (message.replace(" ", "").startsWith("/apinew")) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "§e[NotEnoughUpdates] §7You just executed §c" + packet.getMessage() +
+ "§7. Did you mean to execute §e/api new§7?"));
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java
index 927111b3..6302343e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NullzeeSphere.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
index cb2b7031..776e3647 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PetInfoOverlay.java
@@ -1,12 +1,37 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.common.collect.Lists;
-import com.google.gson.*;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
-import io.github.moulberry.notenoughupdates.NEUOverlay;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonNull;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.overlays.TextOverlay;
import io.github.moulberry.notenoughupdates.overlays.TextOverlayStyle;
@@ -23,10 +48,10 @@ import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -34,23 +59,34 @@ import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.util.vector.Vector2f;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class PetInfoOverlay extends TextOverlay {
private static final Pattern XP_BOOST_PATTERN = Pattern.compile(
"PET_ITEM_(COMBAT|FISHING|MINING|FORAGING|ALL|FARMING)_(SKILL|SKILLS)_BOOST_(COMMON|UNCOMMON|RARE|EPIC)");
private static final Pattern PET_CONTAINER_PAGE = Pattern.compile("\\((\\d)/(\\d)\\) Pets");
- private static final Pattern PET_NAME_PATTERN = Pattern.compile("\u00a77\\[Lvl \\d+] \u00a7(.+)");
- private static final Pattern XP_LINE_PATTERN = Pattern.compile(
- "-------------------- (\\d+(?:,\\d+)*(?:\\.\\d+)?)/(\\d+(?:\\.\\d+)?[B|M|k]?)");
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
@@ -70,10 +106,10 @@ public class PetInfoOverlay extends TextOverlay {
LEGENDARY(20, 4, 5, EnumChatFormatting.GOLD),
MYTHIC(20, 5, 5, EnumChatFormatting.LIGHT_PURPLE);
- public int petOffset;
- public EnumChatFormatting chatFormatting;
- public int petId;
- public int beastcreatMultiplyer;
+ public final int petOffset;
+ public final EnumChatFormatting chatFormatting;
+ public final int petId;
+ public final int beastcreatMultiplyer;
Rarity(int petOffset, int petId, int beastcreatMultiplyer, EnumChatFormatting chatFormatting) {
this.chatFormatting = chatFormatting;
@@ -97,9 +133,15 @@ public class PetInfoOverlay extends TextOverlay {
public GuiProfileViewer.PetLevel petLevel;
public String petXpType;
public String petItem;
- }
+ public String skin;
+ public int candyUsed;
- private static long lastXpGain = 0;
+ public String getPetId(boolean withoutBoost) {
+ boolean shouldDecreaseRarity = withoutBoost && "PET_ITEM_TIER_BOOST".equals(petItem);
+ return petType + ";" + (shouldDecreaseRarity ? rarity.petId - 1 : rarity.petId);
+ }
+
+ }
public static class PetConfig {
public HashMap<Integer, Pet> petMap = new HashMap<>();
@@ -129,7 +171,7 @@ public class PetInfoOverlay extends TextOverlay {
public static void loadConfig(File file) {
try (
BufferedReader reader = new BufferedReader(new InputStreamReader(
- new FileInputStream(file),
+ Files.newInputStream(file.toPath()),
StandardCharsets.UTF_8
))
) {
@@ -146,7 +188,7 @@ public class PetInfoOverlay extends TextOverlay {
file.createNewFile();
try (
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(file),
+ Files.newOutputStream(file.toPath()),
StandardCharsets.UTF_8
))
) {
@@ -208,15 +250,11 @@ public class PetInfoOverlay extends TextOverlay {
}
private static Pet getClosestPet(String petType, int petId, String petItem, float petLevel) {
- Set<Pet> pets = new HashSet<Pet>() {{
- for (Pet pet : config.petMap.values()) {
- if (pet.petType.equals(petType) && pet.rarity.petId == petId) {
- add(pet);
- }
- }
- }};
+ Set<Pet> pets = config.petMap.values().stream().filter(pet -> pet.petType.equals(petType) &&
+ pet.rarity.petId == petId).collect(
+ Collectors.toSet());
- if (pets == null || pets.isEmpty()) {
+ if (pets.isEmpty()) {
return null;
}
@@ -224,15 +262,10 @@ public class PetInfoOverlay extends TextOverlay {
return pets.iterator().next();
}
- String searchItem = petItem;
-
- Set<Pet> itemMatches = new HashSet<>();
- for (Pet pet : pets) {
- if ((searchItem == null && pet.petItem == null) ||
- (searchItem != null && searchItem.equals(pet.petItem))) {
- itemMatches.add(pet);
- }
- }
+ Set<Pet> itemMatches = pets
+ .stream()
+ .filter(pet -> Objects.equals(petItem, pet.petItem))
+ .collect(Collectors.toSet());
if (itemMatches.size() == 1) {
return itemMatches.iterator().next();
@@ -253,15 +286,11 @@ public class PetInfoOverlay extends TextOverlay {
}
}
- if (closestPet != null) {
- return closestPet;
- } else {
- return pets.iterator().next();
- }
+ return closestPet;
}
private static void getAndSetPet(ProfileViewer.Profile profile) {
- JsonObject skillInfo = profile.getSkillInfo(profile.getLatestProfile());
+ Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profile.getLatestProfile());
JsonObject invInfo = profile.getInventoryInfo(profile.getLatestProfile());
JsonObject profileInfo = profile.getProfileInformation(profile.getLatestProfile());
if (invInfo != null && profileInfo != null) {
@@ -300,7 +329,8 @@ public class PetInfoOverlay extends TextOverlay {
}
}
}
- if (skillInfo != null) config.tamingLevel = skillInfo.get("level_skill_taming").getAsInt();
+ if (skyblockInfo != null) config.tamingLevel = (int) skyblockInfo.get("taming").level;
+
//JsonObject petObject = profile.getPetsInfo(profile.getLatestProfile());
/*JsonObject petsJson = Constants.PETS;
if(petsJson != null) {
@@ -421,7 +451,7 @@ public class PetInfoOverlay extends TextOverlay {
String etaStr = null;
String etaMaxStr = null;
- if (currentPet.petLevel.level < 100) {
+ if (currentPet.petLevel.level < currentPet.petLevel.maxLevel) {
float remaining = currentPet.petLevel.currentLevelRequirement - currentPet.petLevel.levelXp;
if (remaining > 0) {
if (xpGain < 1000) {
@@ -433,14 +463,15 @@ public class PetInfoOverlay extends TextOverlay {
}
}
- if (currentPet.petLevel.level < 99 || !NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.contains(6)) {
+ if (currentPet.petLevel.level < (currentPet.petLevel.maxLevel - 1) ||
+ !NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayText.contains(6)) {
float remainingMax = currentPet.petLevel.maxXP - currentPet.petLevel.totalXp;
if (remaining > 0) {
if (xpGain < 1000) {
- etaMaxStr = EnumChatFormatting.AQUA + "Until L100: " +
+ etaMaxStr = EnumChatFormatting.AQUA + "Until L" + (int) currentPet.petLevel.maxLevel + ": " +
EnumChatFormatting.YELLOW + "N/A";
} else {
- etaMaxStr = EnumChatFormatting.AQUA + "Until L100: " +
+ etaMaxStr = EnumChatFormatting.AQUA + "Until L" + (int) currentPet.petLevel.maxLevel + ": " +
EnumChatFormatting.YELLOW + Utils.prettyTime((long) (remainingMax) * 1000 * 60 * 60 / (long) xpGain);
}
}
@@ -525,86 +556,10 @@ public class PetInfoOverlay extends TextOverlay {
}
}
- private static GuiProfileViewer.PetLevel getMaxLevel(JsonArray levels, int offset) {
- float xpTotal = 0;
- float level = 1;
- float currentLevelRequirement = 0;
-
- for (int i = offset; i < offset + 99; i++) {
- currentLevelRequirement = levels.get(i).getAsFloat();
- xpTotal += currentLevelRequirement;
- level += 1;
- }
-
- if (level <= 0) {
- level = 1;
- } else if (level > 100) {
- level = 100;
- }
- GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel();
- levelObj.level = level;
- levelObj.currentLevelRequirement = currentLevelRequirement;
- levelObj.maxXP = xpTotal;
- levelObj.levelPercentage = 1;
- levelObj.levelXp = currentLevelRequirement - 5;
- levelObj.totalXp = xpTotal - 5;
- return levelObj;
- }
-
- private static GuiProfileViewer.PetLevel getLevel(
- JsonArray levels,
- int offset,
- float xpThisLevel,
- int xpMaxThisLevel
- ) {
- float xpTotal = 0;
- float level = 1;
- float currentLevelRequirement = 0;
- float exp = xpThisLevel;
-
- boolean addLevel = true;
-
- for (int i = offset; i < offset + 99; i++) {
- if (addLevel) {
- currentLevelRequirement = levels.get(i).getAsFloat();
- xpTotal += currentLevelRequirement;
-
- if (currentLevelRequirement >= xpMaxThisLevel) {
- addLevel = false;
- } else {
- exp += currentLevelRequirement;
- level += 1;
- }
- } else {
- xpTotal += levels.get(i).getAsFloat();
- }
- }
-
- level += xpThisLevel / currentLevelRequirement;
- if (level <= 0) {
- level = 1;
- } else if (level > 100) {
- level = 100;
- }
- GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel();
- levelObj.level = level;
- levelObj.currentLevelRequirement = currentLevelRequirement;
- levelObj.maxXP = xpTotal;
- levelObj.levelPercentage = xpThisLevel / currentLevelRequirement;
- levelObj.levelXp = xpThisLevel;
- levelObj.totalXp = exp;
- return levelObj;
- }
-
- public static Pet getPetFromStack(String name, String[] lore) {
+ public static Pet getPetFromStack(NBTTagCompound tag) {
if (Constants.PETS == null || Constants.PETS.get("pet_levels") == null ||
Constants.PETS.get("pet_levels") instanceof JsonNull) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- "\u00a7cInvalid PET constants. Please run " + EnumChatFormatting.BOLD + "/neuresetrepo" +
- EnumChatFormatting.RESET + EnumChatFormatting.RED + " and " + EnumChatFormatting.BOLD + "restart your game" +
- EnumChatFormatting.RESET + EnumChatFormatting.RED + " in order to fix. " + EnumChatFormatting.DARK_RED +
- EnumChatFormatting.BOLD + "If that doesn't fix it" + EnumChatFormatting.RESET + EnumChatFormatting.RED +
- ", please join discord.gg/moulberry and post in #neu-support"));
+ Utils.showOutdatedRepoNotification();
return null;
}
@@ -612,132 +567,50 @@ public class PetInfoOverlay extends TextOverlay {
Rarity rarity = null;
String heldItem = null;
GuiProfileViewer.PetLevel level = null;
-
- Matcher petNameMatcher = PET_NAME_PATTERN.matcher(name);
- if (petNameMatcher.matches()) {
- String petStringMatch = petNameMatcher.group(1);
-
- char colChar = petStringMatch.charAt(0);
- EnumChatFormatting col = EnumChatFormatting.RESET;
- for (EnumChatFormatting formatting : EnumChatFormatting.values()) {
- if (formatting.toString().equals("\u00a7" + colChar)) {
- col = formatting;
- break;
- }
- }
-
- rarity = Rarity.COMMON;
- if (col != EnumChatFormatting.RESET) {
- rarity = Rarity.getRarityFromColor(col);
- }
-
- petType = Utils.cleanColour(petStringMatch.substring(1))
- .replaceAll("[^\\w ]", "").trim()
- .replace(" ", "_").toUpperCase();
- }
- if (petType == null || rarity == null) {
- return null;
- }
-
- for (String line : lore) {
- Matcher xpLineMatcher = XP_LINE_PATTERN.matcher(Utils.cleanColour(line));
- if (line.startsWith("\u00a76Held Item: ")) {
- String after = line.substring("\u00a76Held Item: ".length());
-
- if (itemMap == null) {
- itemMap = new HashMap<>();
-
- for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .entrySet()) {
- boolean petItem = false;
-
- if (entry.getKey().startsWith("PET_ITEM_")) {
- petItem = true;
- } else {
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue());
- if (stack.hasTagCompound()) {
- String[] itemLore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
-
- for (String itemLoreLine : itemLore) {
- if (itemLoreLine.contains("PET ITEM")) {
- petItem = true;
- break;
- }
- }
- }
- }
-
- if (petItem) {
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue());
- itemMap.put(stack.getDisplayName().replace("\u00a7f\u00a7f", ""), entry.getKey());
- }
- }
+ String skin = null;
+
+ if (tag != null && tag.hasKey("ExtraAttributes")) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if (ea.hasKey("petInfo")) {
+ JsonObject petInfo = new JsonParser().parse(ea.getString("petInfo")).getAsJsonObject();
+ petType = petInfo.get("type").getAsString();
+ rarity = Rarity.valueOf(petInfo.get("tier").getAsString());
+ level = GuiProfileViewer.getPetLevel(
+ petType,
+ rarity.name(),
+ Utils.getElementAsFloat(petInfo.get("exp"), 0) // Should only default if from item list and repo missing exp:0
+ );
+ if (petInfo.has("heldItem")) {
+ heldItem = petInfo.get("heldItem").getAsString();
}
-
- if (itemMap.containsKey(after)) {
- heldItem = itemMap.get(after);
- }
- } else if (xpLineMatcher.matches()) {
- String xpThisLevelS = xpLineMatcher.group(1);
- String xpMaxThisLevelS = xpLineMatcher.group(2).toLowerCase();
-
- try {
- float xpThisLevel = Float.parseFloat(xpThisLevelS.replace(",", ""));
-
- int mutiplier = 1;
- char end = xpMaxThisLevelS.charAt(xpMaxThisLevelS.length() - 1);
- if (end < '0' || end > '9') {
- xpMaxThisLevelS = xpMaxThisLevelS.substring(0, xpMaxThisLevelS.length() - 1);
-
- switch (end) {
- case 'k':
- mutiplier = 1000;
- break;
- case 'm':
- mutiplier = 1000000;
- break;
- case 'b':
- mutiplier = 1000000000;
- break;
- }
- }
- int xpMaxThisLevel = (int) (Float.parseFloat(xpMaxThisLevelS) * mutiplier);
-
- level = getLevel(
- Constants.PETS.get("pet_levels").getAsJsonArray(),
- rarity.petOffset,
- xpThisLevel,
- xpMaxThisLevel
- );
- } catch (NumberFormatException ignored) {
+ if (petInfo.has("skin")) {
+ skin = "PET_SKIN_" + petInfo.get("skin").getAsString();
}
- } else if (line.equals("\u00a7b\u00a7lMAX LEVEL")) {
- level = getMaxLevel(Constants.PETS.get("pet_levels").getAsJsonArray(), rarity.petOffset);
}
}
- if (level != null) {
- Pet pet = new Pet();
- pet.petItem = heldItem;
- pet.petLevel = level;
- pet.rarity = rarity;
- pet.petType = petType;
- JsonObject petTypes = Constants.PETS.get("pet_types").getAsJsonObject();
- pet.petXpType =
- petTypes.has(pet.petType) ? petTypes.get(pet.petType.toUpperCase()).getAsString().toLowerCase() : "unknown";
-
- return pet;
+ if (petType == null) {
+ return null;
}
- return null;
+ Pet pet = new Pet();
+ pet.petItem = heldItem;
+ pet.petLevel = level;
+ pet.rarity = rarity;
+ pet.petType = petType;
+ JsonObject petTypes = Constants.PETS.get("pet_types").getAsJsonObject();
+ pet.petXpType =
+ petTypes.has(pet.petType) ? petTypes.get(pet.petType.toUpperCase()).getAsString().toLowerCase() : "unknown";
+ pet.skin = skin;
+
+ return pet;
}
private static final HashMap<Integer, Integer> removeMap = new HashMap<>();
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && NEUEventListener.inventoryLoaded) {
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) {
GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest container = (ContainerChest) chest.inventorySlots;
IInventory lower = container.getLowerChestInventory();
@@ -761,7 +634,6 @@ public class PetInfoOverlay extends TextOverlay {
}
}
}
-
if (isPets) {
boolean hasItem = false;
for (int i = 0; i < lower.getSizeInventory(); i++) {
@@ -805,14 +677,14 @@ public class PetInfoOverlay extends TextOverlay {
}
} else {
String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
- Pet pet = getPetFromStack(stack.getDisplayName(), lore);
+ Pet pet = getPetFromStack(stack.getTagCompound());
if (pet != null) {
config.petMap.put(petIndex, pet);
if (currentTime - lastPetSelect > 500) {
boolean foundDespawn = false;
for (String line : lore) {
- if (line.equals("\u00a77\u00a7cClick to despawn.")) {
+ if (line.startsWith("\u00a77\u00a7cClick to despawn")) {
config.selectedPet = petIndex;
foundDespawn = true;
break;
@@ -829,6 +701,40 @@ public class PetInfoOverlay extends TextOverlay {
}
}
removeMap.keySet().retainAll(removeSet);
+ } else if (containerName.equals("Your Equipment")) {
+ ItemStack petStack = lower.getStackInSlot(47);
+ if (petStack != null && petStack.getItem() == Items.skull) {
+ NBTTagCompound tag = petStack.getTagCompound();
+
+ if (tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if (ea.hasKey("petInfo")) {
+ JsonParser jsonParser = new JsonParser();
+
+ JsonObject petInfoObject = jsonParser.parse(ea.getString("petInfo")).getAsJsonObject();
+
+ JsonObject jsonStack = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(petStack);
+ if (jsonStack == null || !jsonStack.has("lore") || !petInfoObject.has("exp")) {
+ return;
+ }
+
+ int rarity = Utils.getRarityFromLore(jsonStack.get("lore").getAsJsonArray());
+ String rarityString = Utils.getRarityFromInt(rarity);
+
+ String name = StringUtils.cleanColour(petStack.getDisplayName());
+ name = name.substring(name.indexOf(']') + 1).trim().replace(' ', '_').toUpperCase();
+
+ float petXp = petInfoObject.get("exp").getAsFloat();
+
+ double petLevel = GuiProfileViewer.getPetLevel(name, rarityString, petXp).level;
+ int index = getClosestPetIndex(name, rarity, "", (float) petLevel);
+ if (index != config.selectedPet) {
+ clearPet();
+ setCurrentPet(index);
+ }
+ }
+ }
+ }
}
}
}
@@ -885,11 +791,14 @@ public class PetInfoOverlay extends TextOverlay {
if (!NotEnoughUpdates.INSTANCE.config.petOverlay.petOverlayIcon) return;
int mythicRarity = currentPet.rarity.petId;
- if (currentPet.rarity.petId == 5) {
- mythicRarity = 4;
- }
JsonObject petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
- currentPet.petType + ";" + mythicRarity);
+ currentPet.skin != null ? currentPet.skin : (currentPet.petType + ";" + mythicRarity));
+
+ if (petItem == null && currentPet.rarity.petId == 5) {
+ petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
+ currentPet.skin != null ? currentPet.skin : (currentPet.petType + ";" + 4));
+ }
+
if (petItem != null) {
Vector2f position = getPosition(overlayWidth, overlayHeight);
int x = (int) position.x;
@@ -907,7 +816,7 @@ public class PetInfoOverlay extends TextOverlay {
Pet currentPet2 = getCurrentPet2();
if (currentPet2 != null) {
JsonObject petItem2 = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
- currentPet2.petType + ";" + currentPet2.rarity.petId);
+ currentPet2.skin != null ? currentPet2.skin : (currentPet2.petType + ";" + currentPet2.rarity.petId));
if (petItem2 != null) {
Vector2f position = getPosition(overlayWidth, overlayHeight);
int x = (int) position.x;
@@ -954,19 +863,19 @@ public class PetInfoOverlay extends TextOverlay {
"alchemy"
);
- public static void onStackClick(ItemStack stack, int windowId, int slotId, int mouseButtonClicked, int mode) {
- if (mode != 0) return;
- if (mouseButtonClicked != 0 && mouseButtonClicked != 1) return;
+ @SubscribeEvent
+ public void onStackClick(SlotClickEvent event) {
+ if (event.clickedButton != 0 && event.clickedButton != 1 && event.clickedButton != 2) return;
- int slotIdMod = (slotId - 10) % 9;
- if (slotId >= 10 && slotId <= 43 && slotIdMod >= 0 && slotIdMod <= 6 &&
+ int slotIdMod = (event.slotId - 10) % 9;
+ if (event.slotId >= 10 && event.slotId <= 43 && slotIdMod >= 0 && slotIdMod <= 6 &&
Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest container = (ContainerChest) chest.inventorySlots;
IInventory lower = container.getLowerChestInventory();
String containerName = lower.getDisplayName().getUnformattedText();
- if (lower.getSizeInventory() >= 54 && windowId == container.windowId) {
+ if (lower.getSizeInventory() >= 54 && event.guiContainer.inventorySlots.windowId == container.windowId) {
int page = 0;
boolean isPets = false;
@@ -988,7 +897,7 @@ public class PetInfoOverlay extends TextOverlay {
boolean isRemoving =
removingStack != null && removingStack.getItem() == Items.dye && removingStack.getItemDamage() == 10;
- int newSelected = (slotId - 10) - (slotId - 10) / 9 * 2 + page * 28;
+ int newSelected = (event.slotId - 10) - (event.slotId - 10) / 9 * 2 + page * 28;
lastPetSelect = System.currentTimeMillis();
@@ -1001,10 +910,11 @@ public class PetInfoOverlay extends TextOverlay {
} else {
setCurrentPet(newSelected);
- String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
- Pet pet = getPetFromStack(stack.getDisplayName(), lore);
- if (pet != null) {
- config.petMap.put(config.selectedPet, pet);
+ if (event.slot.getStack() != null && event.slot.getStack().getTagCompound() != null) {
+ Pet pet = getPetFromStack(event.slot.getStack().getTagCompound());
+ if (pet != null) {
+ config.petMap.put(config.selectedPet, pet);
+ }
}
}
}
@@ -1013,7 +923,7 @@ public class PetInfoOverlay extends TextOverlay {
}
public static float getXpGain(Pet pet, float xp, String xpType) {
- if (pet.petLevel.level >= 100) return 0;
+ if (pet.petLevel.level >= pet.petLevel.maxLevel) return 0;
if (validXpTypes == null)
validXpTypes = Lists.newArrayList("mining", "foraging", "enchanting", "farming", "combat", "fishing", "alchemy");
@@ -1047,8 +957,6 @@ public class PetInfoOverlay extends TextOverlay {
public void updatePetLevels() {
HashMap<String, XPInformation.SkillInfo> skillInfoMap = XPInformation.getInstance().getSkillInfoMap();
- long currentTime = System.currentTimeMillis();
-
float totalGain = 0;
Pet currentPet = getCurrentPet();
@@ -1062,7 +970,6 @@ public class PetInfoOverlay extends TextOverlay {
if (skillXpLast <= 0) {
skillInfoMapLast.put(entry.getKey(), skillXp);
} else if (skillXp > skillXpLast) {
- lastXpGain = currentTime;
float deltaXp = skillXp - skillXpLast;
@@ -1106,7 +1013,7 @@ public class PetInfoOverlay extends TextOverlay {
JsonObject petsJson = Constants.PETS;
if (currentPet != null && petsJson != null) {
currentPet.petLevel = GuiProfileViewer.getPetLevel(
- currentPet.petItem,
+ currentPet.petType,
currentPet.rarity.name(),
currentPet.petLevel.totalXp
);
@@ -1136,48 +1043,6 @@ public class PetInfoOverlay extends TextOverlay {
}
private int lastLevelHovered = 0;
- private String lastItemHovered = null;
-
- private static HashMap<String, String> itemMap = null;
-
- @SubscribeEvent(priority = EventPriority.HIGHEST, receiveCanceled = true)
- public void onTooltip(ItemTooltipEvent event) {
- for (String line : event.toolTip) {
- if (line.startsWith("\u00a7o\u00a77[Lvl ")) {
- lastItemHovered = null;
-
- String after = line.substring("\u00a7o\u00a77[Lvl ".length());
- if (after.contains("]")) {
- String levelStr = after.split("]")[0];
-
- try {
- lastLevelHovered = Integer.parseInt(levelStr.trim());
- } catch (Exception ignored) {
- }
- }
- } else if (line.startsWith("\u00a75\u00a7o\u00a76Held Item: ")) {
- String after = line.substring("\u00a75\u00a7o\u00a76Held Item: ".length());
-
- if (itemMap == null) {
- itemMap = new HashMap<>();
-
- for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .entrySet()) {
- if (entry.getKey().equals("ALL_SKILLS_SUPER_BOOST") ||
- XP_BOOST_PATTERN.matcher(entry.getKey()).matches()) {
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(entry.getValue());
- itemMap.put(stack.getDisplayName(), entry.getKey());
- }
- }
- }
-
- if (itemMap.containsKey(after)) {
- lastItemHovered = itemMap.get(after);
- }
- }
- }
- }
private static final Pattern AUTOPET_EQUIP = Pattern.compile(
"\u00a7cAutopet \u00a7eequipped your \u00a77\\[Lvl (\\d+)] \u00a7(.{2,})\u00a7e! \u00a7a\u00a7lVIEW RULE\u00a7r");
@@ -1185,18 +1050,12 @@ public class PetInfoOverlay extends TextOverlay {
@SubscribeEvent(priority = EventPriority.HIGHEST)
public void onChatReceived(ClientChatReceivedEvent event) {
NEUConfig config = NotEnoughUpdates.INSTANCE.config;
- if (NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() &&
- (config.petOverlay.enablePetInfo || config.itemOverlays.enableMonkeyCheck || config.petOverlay.petInvDisplay)) {
+ if (config.petOverlay.enablePetInfo || config.itemOverlays.enableMonkeyCheck || config.petOverlay.petInvDisplay) {
if (event.type == 0) {
String chatMessage = Utils.cleanColour(event.message.getUnformattedText());
Matcher autopetMatcher = AUTOPET_EQUIP.matcher(event.message.getFormattedText());
- if (event.message.getUnformattedText().startsWith("You summoned your") ||
- System.currentTimeMillis() - NEUOverlay.cachedPetTimer < 500) {
- NEUOverlay.cachedPetTimer = System.currentTimeMillis();
- NEUOverlay.shouldUseCachedPet = false;
- } else if (autopetMatcher.matches()) {
- NEUOverlay.shouldUseCachedPet = false;
+ if (autopetMatcher.matches()) {
try {
lastLevelHovered = Integer.parseInt(autopetMatcher.group(1));
} catch (NumberFormatException ignored) {
@@ -1223,9 +1082,13 @@ public class PetInfoOverlay extends TextOverlay {
setCurrentPet(getClosestPetIndex(pet, rarity.petId, "", lastLevelHovered));
if (PetInfoOverlay.config.selectedPet == -1) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
- EnumChatFormatting.RED + "[NEU] Can't find pet \u00a7" + petStringMatch +
- EnumChatFormatting.RED + " try revisiting all pages of /pets."));
+ setCurrentPet(getClosestPetIndex(pet, rarity.petId - 1, "", lastLevelHovered));
+ if (!"PET_ITEM_TIER_BOOST".equals(getCurrentPet().petItem)) {
+ PetInfoOverlay.config.selectedPet = -1;
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED + "[NEU] Can't find pet \u00a7" + petStringMatch +
+ EnumChatFormatting.RED + " try revisiting all pages of /pets."));
+ }
}
} else if ((chatMessage.toLowerCase().startsWith("you despawned your")) || (chatMessage.toLowerCase().contains(
"switching to profile"))
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java
new file mode 100644
index 00000000..975bbe6e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/PowerStoneStatsDisplay.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.client.event.GuiOpenEvent;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+import java.text.NumberFormat;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+
+public class PowerStoneStatsDisplay {
+ private static PowerStoneStatsDisplay instance = null;
+ private final NumberFormat format = NumberFormat.getInstance(Locale.US);
+ private boolean dirty = true;
+
+ public static PowerStoneStatsDisplay getInstance() {
+ if (instance == null) {
+ instance = new PowerStoneStatsDisplay();
+ }
+ return instance;
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent event) {
+ if (!dirty) return;
+
+ if (!Utils.getOpenChestName().equals("SkyBlock Menu")) {
+ dirty = false;
+ return;
+ }
+
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ Container openContainer = p.openContainer;
+ for (Slot slot : openContainer.inventorySlots) {
+ ItemStack stack = slot.getStack();
+ if (stack == null) continue;
+
+ String displayName = stack.getDisplayName();
+ if (!"§aAccessory Bag".equals(displayName)) continue;
+
+ for (String line : ItemUtils.getLore(stack)) {
+ if (line.startsWith("§7Magical Power: ")) {
+ String rawNumber = line.split("§6")[1].replace(",", "");
+ NEUConfig.HiddenProfileSpecific configProfileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
+ if (configProfileSpecific == null) return;
+ configProfileSpecific.magicalPower = Integer.parseInt(rawNumber);
+ dirty = false;
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onGuiOpen(GuiOpenEvent event) {
+ if (event.gui != null) {
+ dirty = true;
+ }
+ }
+
+ @SubscribeEvent
+ public void onItemTooltipLow(ItemTooltipEvent event) {
+ if (!NotEnoughUpdates.INSTANCE.config.tooltipTweaks.powerStoneStats) return;
+
+ ItemStack itemStack = event.itemStack;
+ if (itemStack == null) return;
+ List<String> lore = ItemUtils.getLore(itemStack);
+
+ boolean isPowerStone = false;
+ for (String line : lore) {
+ if (line.equals("§8Power Stone")) {
+ isPowerStone = true;
+ break;
+ }
+ }
+
+ if (!isPowerStone) return;
+
+ NEUConfig.HiddenProfileSpecific configProfileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
+ if (configProfileSpecific == null) return;
+
+ int magicalPower = configProfileSpecific.magicalPower;
+ if (magicalPower < 1) return;
+
+ double scaledMagicalPower = scalePower(magicalPower);
+ double scaledCurrentPower = 0.0;
+
+ int index = 0;
+ boolean foundMagicalPower = false;
+ for (String line : new LinkedList<>(lore)) {
+ index++;
+ line = line.replace("§k", "");
+
+ if (line.startsWith("§7At ")) {
+
+ String rawNumber = StringUtils.substringBetween(StringUtils.cleanColour(line), "At ", " Magical");
+ if (rawNumber == null) return;
+
+ //This ignores old repo entries in the item browser from neu
+ if (rawNumber.equals("mmm")) return;
+
+ try {
+ scaledCurrentPower = scalePower(StringUtils.cleanAndParseInt(rawNumber));
+ } catch (NumberFormatException ignored) {
+ return;
+ }
+
+ event.toolTip.set(index, "§7At §6" + format.format((double) magicalPower) + " Magical Power§7:");
+ foundMagicalPower = true;
+ continue;
+ }
+
+ if (!foundMagicalPower) continue;
+
+ String cleanLine = StringUtils.cleanColour(line);
+ if (cleanLine.equals("")) {
+ break;
+ }
+
+ for (String operator : new String[]{"+", "-"}) {
+ if (!cleanLine.startsWith(operator)) continue;
+ String rawStat = StringUtils.cleanColour(StringUtils.substringBetween(line, operator, " "));
+
+ double currentStat;
+ try {
+ currentStat = 0.0 + StringUtils.cleanAndParseInt(rawStat.substring(0, rawStat.length() - 1));
+ } catch (NumberFormatException ignored) {
+ continue;
+ }
+ double realStat = (currentStat / scaledCurrentPower) * scaledMagicalPower;
+
+ String format = this.format.format((double) Math.round(realStat));
+ format += rawStat.substring(rawStat.length() - 1);
+
+ event.toolTip.set(index, line.replace(rawStat, format));
+ }
+ }
+ }
+
+ private double scalePower(int magicalPower) {
+ return Math.pow(29.97 * (Math.log(0.0019 * magicalPower + 1)), 1.2);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
index 743625f5..8a487739 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import com.google.gson.Gson;
@@ -5,6 +24,8 @@ import com.google.gson.GsonBuilder;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.ISound;
@@ -23,16 +44,20 @@ import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.GuiScreenEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import org.apache.commons.lang3.tuple.Triple;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Vector2f;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
-import java.util.function.Consumer;
public class SlotLocking {
private static final SlotLocking INSTANCE = new SlotLocking();
@@ -200,7 +225,7 @@ public class SlotLocking {
int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
- Slot slot = container.getSlotAtPosition(mouseX, mouseY);
+ Slot slot = ((AccessorGuiContainer) container).doGetSlotAtPosition(mouseX, mouseY);
if (slot != null && slot.getSlotIndex() != 8 && slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) {
int slotNum = slot.getSlotIndex();
if (slotNum >= 0 && slotNum <= 39) {
@@ -280,7 +305,7 @@ public class SlotLocking {
int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
- Slot slot = container.getSlotAtPosition(mouseX, mouseY);
+ Slot slot = ((AccessorGuiContainer) container).doGetSlotAtPosition(mouseX, mouseY);
if (slot != null && slot.getSlotIndex() != 8 && slot.inventory == Minecraft.getMinecraft().thePlayer.inventory) {
int slotNum = slot.getSlotIndex();
if (slotNum >= 0 && slotNum <= 39) {
@@ -378,10 +403,10 @@ public class SlotLocking {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {
return;
}
- GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen;
+ AccessorGuiContainer container = (AccessorGuiContainer) Minecraft.getMinecraft().currentScreen;
- int x1 = container.guiLeft + pairingSlot.xDisplayPosition + 8;
- int y1 = container.guiTop + pairingSlot.yDisplayPosition + 8;
+ int x1 = container.getGuiLeft() + pairingSlot.xDisplayPosition + 8;
+ int y1 = container.getGuiTop() + pairingSlot.yDisplayPosition + 8;
int x2 = event.mouseX;
int y2 = event.mouseY;
@@ -429,22 +454,21 @@ public class SlotLocking {
}
}
- public void onWindowClick(
- Slot slotIn,
- int slotId,
- int clickedButton,
- int clickType,
- Consumer<Triple<Integer, Integer, Integer>> consumer
- ) {
- LockedSlot locked = getLockedSlot(slotIn);
+ @SubscribeEvent
+ public void onWindowClick(SlotClickEvent slotClickEvent) {
+ LockedSlot locked = getLockedSlot(slotClickEvent.slot);
if (locked == null) {
return;
- } else if (locked.locked || (clickType == 2 && SlotLocking.getInstance().isSlotIndexLocked(clickedButton))) {
- consumer.accept(null);
- } else if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && clickType == 1 &&
+ }
+ if (locked.locked ||
+ (slotClickEvent.clickType == 2 && SlotLocking.getInstance().isSlotIndexLocked(slotClickEvent.clickedButton))) {
+ slotClickEvent.setCanceled(true);
+ return;
+ }
+ if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding
+ && slotClickEvent.clickType == 1 &&
locked.boundTo != -1) {
- GuiContainer container = (GuiContainer) Minecraft.getMinecraft().currentScreen;
- Slot boundSlot = container.inventorySlots.getSlotFromInventory(
+ Slot boundSlot = slotClickEvent.guiContainer.inventorySlots.getSlotFromInventory(
Minecraft.getMinecraft().thePlayer.inventory,
locked.boundTo
);
@@ -455,29 +479,41 @@ public class SlotLocking {
LockedSlot boundLocked = getLockedSlot(boundSlot);
- int id = slotIn.getSlotIndex();
- if (id >= 9 && locked.boundTo >= 0 && locked.boundTo < 8) {
- if (!boundLocked.locked) {
- consumer.accept(Triple.of(slotId, locked.boundTo, 2));
- if (boundLocked == DEFAULT_LOCKED_SLOT) {
- LockedSlot[] lockedSlots = getDataForProfile();
- lockedSlots[locked.boundTo] = new LockedSlot();
- lockedSlots[locked.boundTo].boundTo = id;
- } else {
- boundLocked.boundTo = id;
- }
+ int from, to;
+ int id = slotClickEvent.slot.getSlotIndex();
+ if (id >= 9 && 0 <= locked.boundTo && locked.boundTo < 8 && !boundLocked.locked) {
+ from = id;
+ to = locked.boundTo;
+ if (boundLocked == DEFAULT_LOCKED_SLOT) {
+ LockedSlot[] lockedSlots = getDataForProfile();
+ lockedSlots[locked.boundTo] = new LockedSlot();
+ lockedSlots[locked.boundTo].boundTo = id;
+ } else {
+ boundLocked.boundTo = id;
}
- } else if (id >= 0 && id < 8 && locked.boundTo >= 9 && locked.boundTo <= 39) {
+ } else if (0 <= id && id < 8 && locked.boundTo >= 9 && locked.boundTo <= 39) {
if (boundLocked.locked || boundLocked.boundTo != id) {
locked.boundTo = -1;
+ return;
} else {
- int boundTo = boundSlot.slotNumber;
- consumer.accept(Triple.of(boundTo, id, 2));
+ from = boundSlot.slotNumber;
+ to = id;
}
+ } else {
+ return;
}
+ if (from == 39) from = 5;
+ if (from == 38) from = 6;
+ if (from == 37) from = 7;
+ if (from == 36) from = 8;
+ Minecraft.getMinecraft().playerController.windowClick(
+ slotClickEvent.guiContainer.inventorySlots.windowId,
+ from, to, 2, Minecraft.getMinecraft().thePlayer
+ );
+ slotClickEvent.setCanceled(true);
} else if (NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotBinding && locked.boundTo != -1 &&
NotEnoughUpdates.INSTANCE.config.slotLocking.bindingAlsoLocks) {
- consumer.accept(null);
+ slotClickEvent.setCanceled(true);
}
}
@@ -514,7 +550,7 @@ public class SlotLocking {
return;
}
- boolean hoverOverSlot = container.isMouseOverSlot(slot, mouseX, mouseY);
+ boolean hoverOverSlot = ((AccessorGuiContainer) container).doIsMouseOverSlot(slot, mouseX, mouseY);
if (hoverOverSlot || slot.getSlotIndex() >= 9) {
Minecraft.getMinecraft().getTextureManager().bindTexture(BOUND);
@@ -545,8 +581,8 @@ public class SlotLocking {
);
}
} else if (pairingSlot != null && lockKeyHeld && slot.getSlotIndex() < 8) {
- int x1 = container.guiLeft + pairingSlot.xDisplayPosition;
- int y1 = container.guiTop + pairingSlot.yDisplayPosition;
+ int x1 = ((AccessorGuiContainer) container).getGuiLeft() + pairingSlot.xDisplayPosition;
+ int y1 = ((AccessorGuiContainer) container).getGuiTop() + pairingSlot.yDisplayPosition;
if (mouseX <= x1 || mouseX >= x1 + 16 ||
mouseY <= y1 || mouseY >= y1 + 16) {
@@ -634,8 +670,8 @@ public class SlotLocking {
int mouseX = Mouse.getX() * scaledWidth / Minecraft.getMinecraft().displayWidth;
int mouseY = scaledHeight - Mouse.getY() * scaledHeight / Minecraft.getMinecraft().displayHeight - 1;
- int x1 = container.guiLeft + pairingSlot.xDisplayPosition;
- int y1 = container.guiTop + pairingSlot.yDisplayPosition;
+ int x1 = ((AccessorGuiContainer) container).getGuiLeft() + pairingSlot.xDisplayPosition;
+ int y1 = ((AccessorGuiContainer) container).getGuiTop() + pairingSlot.yDisplayPosition;
if (mouseX <= x1 || mouseX >= x1 + 16 ||
mouseY <= y1 || mouseY >= y1 + 16) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
index 94aee789..bef07399 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java
@@ -1,6 +1,35 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
-import com.google.gson.*;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay;
import io.github.moulberry.notenoughupdates.util.SBInfo;
@@ -9,18 +38,38 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.*;
+import net.minecraft.nbt.JsonToNBT;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTException;
+import net.minecraft.nbt.NBTTagByte;
+import net.minecraft.nbt.NBTTagByteArray;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagDouble;
+import net.minecraft.nbt.NBTTagFloat;
+import net.minecraft.nbt.NBTTagInt;
+import net.minecraft.nbt.NBTTagIntArray;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagLong;
+import net.minecraft.nbt.NBTTagShort;
+import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.play.client.C0EPacketClickWindow;
import net.minecraft.network.play.server.S2DPacketOpenWindow;
import net.minecraft.network.play.server.S2EPacketCloseWindow;
import net.minecraft.network.play.server.S2FPacketSetSlot;
import net.minecraft.network.play.server.S30PacketWindowItems;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
@@ -35,11 +84,12 @@ public class StorageManager {
private static final StorageManager INSTANCE = new StorageManager();
private static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(ItemStack.class, new ItemStackSerializer())
- .registerTypeAdapter(ItemStack.class, new ItemStackDeserilizer()).create();
+ .registerTypeAdapter(ItemStack.class, new ItemStackDeserializer()).create();
public static class ItemStackSerializer implements JsonSerializer<ItemStack> {
@Override
public JsonElement serialize(ItemStack src, Type typeOfSrc, JsonSerializationContext context) {
+ fixPetInfo(src);
NBTTagCompound tag = src.serializeNBT();
return nbtToJson(tag);
}
@@ -47,7 +97,7 @@ public class StorageManager {
private static final Pattern JSON_FIX_REGEX = Pattern.compile("\"([^,:]+)\":");
- public static class ItemStackDeserilizer implements JsonDeserializer<ItemStack> {
+ public static class ItemStackDeserializer implements JsonDeserializer<ItemStack> {
@Override
public ItemStack deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
@@ -87,6 +137,63 @@ public class StorageManager {
return (JsonObject) loadJson(NBTTagCompound);
}
+ private static class PetInfo {
+ String type;
+ Boolean active;
+ Double exp;
+ String tier;
+ Boolean hideInfo;
+ Integer candyUsed;
+ String uuid;
+ Boolean hideRightClick;
+ String heldItem;
+ String skin;
+
+ private <T> void appendIfNotNull(StringBuilder builder, String key, T value) {
+ if (value != null) {
+ if (builder.indexOf("{") != builder.length()-1) {
+ builder.append(",");
+ }
+ builder.append(key).append(":");
+ if (value instanceof String) {
+ builder.append("\"").append(value).append("\"");
+ } else {
+ builder.append(value);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder object = new StringBuilder();
+ object.append("{");
+ appendIfNotNull(object, "type", type);
+ appendIfNotNull(object, "active", active);
+ appendIfNotNull(object, "exp", exp);
+ appendIfNotNull(object, "tier", tier);
+ appendIfNotNull(object, "hideInfo", hideInfo);
+ appendIfNotNull(object, "candyUsed", candyUsed);
+ appendIfNotNull(object, "uuid", uuid);
+ appendIfNotNull(object, "hideRightClick", hideRightClick);
+ appendIfNotNull(object, "heldItem", heldItem);
+ appendIfNotNull(object, "skin", skin);
+ object.append("}");
+ return object.toString();
+ }
+ }
+
+ private static void fixPetInfo(ItemStack src) {
+ if (src.getTagCompound() == null || !src.getTagCompound().hasKey("ExtraAttributes") || !src.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("petInfo")) return;
+ PetInfo oldPetInfo = GSON.fromJson(src.getTagCompound().getCompoundTag("ExtraAttributes").getString("petInfo"), PetInfo.class);
+ src.getTagCompound().getCompoundTag("ExtraAttributes").removeTag("petInfo");
+ try {
+ src.getTagCompound().getCompoundTag("ExtraAttributes").setTag(
+ "petInfo",
+ JsonToNBT.getTagFromJson(oldPetInfo.toString())
+ );
+ } catch (NBTException | NullPointerException ignored) {}
+ }
+
private static JsonElement loadJson(NBTBase tag) {
if (tag instanceof NBTTagCompound) {
NBTTagCompound compoundTag = (NBTTagCompound) tag;
@@ -187,7 +294,7 @@ public class StorageManager {
private boolean shouldRenderStorageOverlayCached = false;
- private static final Pattern WINDOW_REGEX = Pattern.compile(".+ Backpack (?:\u2726 )?\\((\\d+)/(\\d+)\\)");
+ private static final Pattern WINDOW_REGEX = Pattern.compile(".+ Backpack (?:✦ )?\\(Slot #(\\d+)\\)");
private static final Pattern ECHEST_WINDOW_REGEX = Pattern.compile("Ender Chest \\((\\d+)/(\\d+)\\)");
public void loadConfig(File file) {
@@ -508,8 +615,8 @@ public class StorageManager {
int index = slot - 9;
boolean changed = false;
- if (stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) &&
- stack.getMetadata() == 14) {
+ if ((stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) &&
+ stack.getMetadata() == 14) || (stack.getItem() == Items.dye && stack.getMetadata() == 8)) {
if (storagePresent[index]) changed = true;
storagePresent[index] = false;
removePage(index);
@@ -549,7 +656,8 @@ public class StorageManager {
boolean changed = false;
- if (stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ if (stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)
+ || (stack.getItem() == Items.dye && stack.getMetadata() == 8)) {
if (storagePresent[index]) changed = true;
storagePresent[index] = false;
removePage(index);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StreamerMode.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StreamerMode.java
index 064f41ca..a2951e56 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StreamerMode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StreamerMode.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.util.Utils;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java
index 27cf42ac..7fc8beba 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SunTzu.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.util.Utils;
@@ -37,7 +56,8 @@ public class SunTzu {
"The wise warrior avoids the battle.",
"Great results, can be achieved with small forces.",
"Attack is the secret of defense; defense is the planning of an attack.",
- "Subscribe to Moulberry on YouTube."
+ "Subscribe to Moulberry on YouTube.",
+ "Technoblade never dies!"
};
public static void setEnabled(boolean enabled) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CrystalHollowsTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CrystalHollowsTextures.java
index 36858276..7d23d922 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CrystalHollowsTextures.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CrystalHollowsTextures.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import net.minecraft.util.BlockPos;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java
index 9a6f9cac..48a01187 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBiomes.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBlockSounds.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBlockSounds.java
index dec011d3..2a3e9ec4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBlockSounds.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/CustomBlockSounds.java
@@ -1,8 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.PositionedSoundRecord;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java
index faf7eabe..1c6acc1d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/DwarvenMinesTextures.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import com.google.gson.JsonArray;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/IslandZoneSubdivider.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/IslandZoneSubdivider.java
index 8b00bc85..75ff566f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/IslandZoneSubdivider.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/IslandZoneSubdivider.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import net.minecraft.util.BlockPos;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/LocationChangeEvent.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/LocationChangeEvent.java
index c6f5e9c0..5a87af11 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/LocationChangeEvent.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/LocationChangeEvent.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import net.minecraftforge.fml.common.eventhandler.Event;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/SpecialBlockZone.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/SpecialBlockZone.java
index f4e8f1fc..e88e2c25 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/SpecialBlockZone.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/customblockzones/SpecialBlockZone.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscfeatures.customblockzones;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java
new file mode 100644
index 00000000..963fa793
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/AgeModifier.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.mixins.AccessorEntityAgeable;
+import io.github.moulberry.notenoughupdates.mixins.AccessorEntityArmorStand;
+import net.minecraft.entity.EntityAgeable;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.entity.monster.EntityZombie;
+
+public class AgeModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ boolean baby = info.has("baby") && info.get("baby").getAsBoolean();
+ if (base instanceof EntityAgeable) {
+ ((AccessorEntityAgeable) base).setGrowingAgeDirect(baby ? -1 : 1);
+ return base;
+ }
+ if (base instanceof EntityZombie) {
+ ((EntityZombie) base).setChild(baby);
+ return base;
+ }
+ if (base instanceof EntityArmorStand) {
+ ((AccessorEntityArmorStand) base).setSmallDirect(baby);
+ return base;
+ }
+ System.out.println("Cannot apply age to a non ageable entity: " + base);
+ return null;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java
new file mode 100644
index 00000000..5f452132
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/ChargedModifier.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.monster.EntityCreeper;
+
+public class ChargedModifier extends EntityViewerModifier {
+
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (base instanceof EntityCreeper) {
+ base.getDataWatcher().updateObject(17, (byte) 1);
+ return base;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java
new file mode 100644
index 00000000..367d62d3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewer.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiInventory;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.boss.EntityDragon;
+import net.minecraft.entity.boss.EntityWither;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.entity.monster.EntityBlaze;
+import net.minecraft.entity.monster.EntityCaveSpider;
+import net.minecraft.entity.monster.EntityCreeper;
+import net.minecraft.entity.monster.EntityEnderman;
+import net.minecraft.entity.monster.EntityEndermite;
+import net.minecraft.entity.monster.EntityGhast;
+import net.minecraft.entity.monster.EntityGuardian;
+import net.minecraft.entity.monster.EntityIronGolem;
+import net.minecraft.entity.monster.EntityMagmaCube;
+import net.minecraft.entity.monster.EntityPigZombie;
+import net.minecraft.entity.monster.EntitySilverfish;
+import net.minecraft.entity.monster.EntitySkeleton;
+import net.minecraft.entity.monster.EntitySlime;
+import net.minecraft.entity.monster.EntitySnowman;
+import net.minecraft.entity.monster.EntitySpider;
+import net.minecraft.entity.monster.EntityWitch;
+import net.minecraft.entity.monster.EntityZombie;
+import net.minecraft.entity.passive.EntityBat;
+import net.minecraft.entity.passive.EntityChicken;
+import net.minecraft.entity.passive.EntityCow;
+import net.minecraft.entity.passive.EntityHorse;
+import net.minecraft.entity.passive.EntityMooshroom;
+import net.minecraft.entity.passive.EntityOcelot;
+import net.minecraft.entity.passive.EntityPig;
+import net.minecraft.entity.passive.EntityRabbit;
+import net.minecraft.entity.passive.EntitySheep;
+import net.minecraft.entity.passive.EntitySquid;
+import net.minecraft.entity.passive.EntityVillager;
+import net.minecraft.entity.passive.EntityWolf;
+import net.minecraft.util.ResourceLocation;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Supplier;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+
+public class EntityViewer extends GuiScreen {
+
+ public static Map<String, Supplier<? extends EntityLivingBase>> validEntities =
+ new HashMap<String, Supplier<? extends EntityLivingBase>>() {{
+ put("Zombie", () -> new EntityZombie(null));
+ put("Chicken", () -> new EntityChicken(null));
+ put("Slime", () -> new EntitySlime(null));
+ put("Wolf", () -> new EntityWolf(null));
+ put("Skeleton", () -> new EntitySkeleton(null));
+ put("Creeper", () -> new EntityCreeper(null));
+ put("Ocelot", () -> new EntityOcelot(null));
+ put("Blaze", () -> new EntityBlaze(null));
+ put("Rabbit", () -> new EntityRabbit(null));
+ put("Sheep", () -> new EntitySheep(null));
+ put("Horse", () -> new EntityHorse(null));
+ put("Eisengolem", () -> new EntityIronGolem(null));
+ put("Silverfish", () -> new EntitySilverfish(null));
+ put("Witch", () -> new EntityWitch(null));
+ put("Endermite", () -> new EntityEndermite(null));
+ put("Snowman", () -> new EntitySnowman(null));
+ put("Villager", () -> new EntityVillager(null));
+ put("Guardian", () -> new EntityGuardian(null));
+ put("ArmorStand", () -> new EntityArmorStand(null));
+ put("Squid", () -> new EntitySquid(null));
+ put("Bat", () -> new EntityBat(null));
+ put("Spider", () -> new EntitySpider(null));
+ put("CaveSpider", () -> new EntityCaveSpider(null));
+ put("Pigman", () -> new EntityPigZombie(null));
+ put("Ghast", () -> new EntityGhast(null));
+ put("MagmaCube", () -> new EntityMagmaCube(null));
+ put("Wither", () -> new EntityWither(null));
+ put("Enderman", () -> new EntityEnderman(null));
+ put("Mooshroom", () -> new EntityMooshroom(null));
+ put("WitherSkeleton", () -> {
+ EntitySkeleton skeleton = new EntitySkeleton(null);
+ skeleton.setSkeletonType(1);
+ return skeleton;
+ });
+ put("Cow", () -> new EntityCow(null));
+ put("Dragon", () -> new EntityDragon(null));
+ put("Player", () -> new GUIClientPlayer());
+ put("Pig", () -> new EntityPig(null));
+ }};
+
+ public static Map<String, EntityViewerModifier> validModifiers = new HashMap<String, EntityViewerModifier>() {{
+ put("playerdata", new SkinModifier());
+ put("equipment", new EquipmentModifier());
+ put("riding", new RidingModifier());
+ put("charged", new ChargedModifier());
+ put("witherdata", new WitherModifier());
+ put("invisible", new InvisibleModifier());
+ put("age", new AgeModifier());
+ put("horse", new HorseModifier());
+ put("name", new NameModifier());
+ }};
+
+ public int guiLeft = 0;
+ public int guiTop = 0;
+ public int xSize = 176;
+ public int ySize = 166;
+
+ private final String label;
+ private final EntityLivingBase entity;
+ private static final ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/entity_viewer.png"
+ );
+
+ public EntityViewer(String label, EntityLivingBase entity) {
+ this.label = label;
+ this.entity = entity;
+ }
+
+ public static EntityLivingBase constructEntity(ResourceLocation resourceLocation) {
+ Gson gson = NotEnoughUpdates.INSTANCE.manager.gson;
+ try (
+ Reader is = new InputStreamReader(
+ Minecraft.getMinecraft().getResourceManager().getResource(resourceLocation).getInputStream(),
+ StandardCharsets.UTF_8
+ )
+ ) {
+ return constructEntity(gson.fromJson(is, JsonObject.class));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static EntityLivingBase constructEntity(JsonObject info) {
+ List<JsonObject> modifiers = info.has("modifiers") ?
+ StreamSupport.stream(info.get("modifiers").getAsJsonArray().spliterator(), false)
+ .map(JsonElement::getAsJsonObject).collect(Collectors.toList())
+ : Collections.emptyList();
+ return EntityViewer.constructEntity(info.get("entity").getAsString(), modifiers);
+ }
+
+ public static EntityLivingBase constructEntity(String string, String[] modifiers) {
+ Gson gson = NotEnoughUpdates.INSTANCE.manager.gson;
+ return constructEntity(
+ string,
+ Arrays.stream(modifiers).map(it -> gson.fromJson(it, JsonObject.class)).collect(Collectors.toList())
+ );
+ }
+
+ public static EntityLivingBase constructEntity(String string, List<JsonObject> modifiers) {
+ Supplier<? extends EntityLivingBase> aClass = validEntities.get(string);
+ if (aClass == null) {
+ System.err.println("Could not find entity of type: " + string);
+ return null;
+ }
+ try {
+ EntityLivingBase entity = aClass.get();
+ for (JsonObject modifier : modifiers) {
+ String type = modifier.get("type").getAsString();
+ EntityViewerModifier entityViewerModifier = validModifiers.get(type);
+ entity = entityViewerModifier.applyModifier(entity, modifier);
+ if (entity == null) break;
+ }
+ return entity;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ drawDefaultBackground();
+ FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
+
+ this.guiLeft = (width - this.xSize) / 2;
+ this.guiTop = (height - this.ySize) / 2;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
+
+ Utils.drawStringScaledMaxWidth(label, fontRenderer, guiLeft + 10, guiTop + 10, false, 100, 0xFF00FF);
+ renderEntity(entity, guiLeft + 90, guiTop + 75, mouseX, mouseY);
+ }
+
+ public static void renderEntity(EntityLivingBase entity, int posX, int posY, int mouseX, int mouseY) {
+ GlStateManager.color(1F, 1F, 1F, 1F);
+
+ int scale = 30;
+ float bottomOffset = 0F;
+ EntityLivingBase stack = entity;
+ while (true) {
+
+ stack.ticksExisted = Minecraft.getMinecraft().thePlayer.ticksExisted;
+ GuiInventory.drawEntityOnScreen(
+ posX,
+ (int) (posY - bottomOffset * scale),
+ scale,
+ posX - mouseX,
+ (int) (posY - stack.getEyeHeight() * scale - mouseY),
+ stack
+ );
+ bottomOffset += stack.getMountedYOffset();
+ if (!(stack.riddenByEntity instanceof EntityLivingBase)) {
+ break;
+ }
+ stack = (EntityLivingBase) stack.riddenByEntity;
+ }
+
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java
new file mode 100644
index 00000000..aa6d22c9
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EntityViewerModifier.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+
+public abstract class EntityViewerModifier {
+ public abstract EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info);
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java
new file mode 100644
index 00000000..685e161a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/EquipmentModifier.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemArmor;
+import net.minecraft.item.ItemStack;
+
+public class EquipmentModifier extends EntityViewerModifier {
+
+ private ItemStack createItem(String item) {
+ NEUManager manager = NotEnoughUpdates.INSTANCE.manager;
+ String[] split = item.split("#");
+ if (split.length == 2) {
+ switch (split[0].intern()) {
+ case "LEATHER_LEGGINGS":
+ return coloredLeatherArmor(Items.leather_leggings, split[1]);
+ case "LEATHER_HELMET":
+ return coloredLeatherArmor(Items.leather_helmet, split[1]);
+ case "LEATHER_CHESTPLATE":
+ return coloredLeatherArmor(Items.leather_chestplate, split[1]);
+ case "LEATHER_BOOTS":
+ return coloredLeatherArmor(Items.leather_boots, split[1]);
+ default:
+ throw new RuntimeException("Unknown leather piece: " + item);
+ }
+ }
+ return manager.createItem(item);
+ }
+
+ private ItemStack coloredLeatherArmor(ItemArmor item, String colorHex) {
+ ItemStack is = new ItemStack(item);
+ item.setColor(is, Integer.parseInt(colorHex, 16));
+ return is;
+ }
+
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (info.has("hand"))
+ setCurrentItemOrArmor(base, 0, createItem(info.get("hand").getAsString()));
+ if (info.has("helmet"))
+ setCurrentItemOrArmor(base, 4, createItem(info.get("helmet").getAsString()));
+ if (info.has("chestplate"))
+ setCurrentItemOrArmor(base, 3, createItem(info.get("chestplate").getAsString()));
+ if (info.has("leggings"))
+ setCurrentItemOrArmor(base, 2, createItem(info.get("leggings").getAsString()));
+ if (info.has("feet"))
+ setCurrentItemOrArmor(base, 1, createItem(info.get("feet").getAsString()));
+ return base;
+ }
+
+ public void setCurrentItemOrArmor(EntityLivingBase entity, int slot, ItemStack itemStack) {
+ if (entity instanceof EntityPlayer) {
+ setPlayerCurrentItemOrArmor((EntityPlayer) entity, slot, itemStack);
+ } else {
+ entity.setCurrentItemOrArmor(slot, itemStack);
+ }
+ }
+
+ // Biscuit person needs to learn how to code and not fuck up valid vanilla behaviour
+ public static void setPlayerCurrentItemOrArmor(EntityPlayer player, int slot, ItemStack itemStack) {
+ if (slot == 0) {
+ player.inventory.mainInventory[player.inventory.currentItem] = itemStack;
+ } else {
+ player.inventory.armorInventory[slot - 1] = itemStack;
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java
new file mode 100644
index 00000000..8cdf2ef0
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/GUIClientPlayer.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.mojang.authlib.GameProfile;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.UUID;
+
+public class GUIClientPlayer extends AbstractClientPlayer {
+ public GUIClientPlayer() {
+ super(null, new GameProfile(UUID.randomUUID(), "GuiPlayer"));
+ }
+
+ ResourceLocation overrideSkin = DefaultPlayerSkin.getDefaultSkinLegacy();
+ ResourceLocation overrideCape = null;
+ boolean overrideIsSlim = false;
+ NetworkPlayerInfo playerInfo = new NetworkPlayerInfo(this.getGameProfile()) {
+ @Override
+ public String getSkinType() {
+ return overrideIsSlim ? "slim" : "default";
+ }
+
+ @Override
+ public ResourceLocation getLocationSkin() {
+ return overrideSkin;
+ }
+
+ @Override
+ public ResourceLocation getLocationCape() {
+ return overrideCape;
+ }
+ };
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public String name;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ protected NetworkPlayerInfo getPlayerInfo() {
+ return playerInfo;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java
new file mode 100644
index 00000000..b29152bf
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/HorseModifier.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.passive.EntityHorse;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+
+public class HorseModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (!(base instanceof EntityHorse))
+ return null;
+ EntityHorse horse = (EntityHorse) base;
+ if (info.has("kind")) {
+ String type = info.get("kind").getAsString().intern();
+ switch (type) {
+ case "skeleton":
+ horse.setHorseType(4);
+ break;
+ case "zombie":
+ horse.setHorseType(3);
+ break;
+ case "mule":
+ horse.setHorseType(2);
+ break;
+ case "donkey":
+ horse.setHorseType(1);
+ break;
+ case "horse":
+ horse.setHorseType(0);
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown horse type: " + type);
+ }
+ }
+ if (info.has("armor")) {
+ JsonElement el = info.get("armor");
+ if (el.isJsonNull()) {
+ horse.setHorseArmorStack(null);
+ } else {
+ Item item;
+ switch (el.getAsString().intern()) {
+ case "iron":
+ item = Items.iron_horse_armor;
+ break;
+ case "golden":
+ item = Items.golden_horse_armor;
+ break;
+ case "diamond":
+ item = Items.diamond_horse_armor;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown horse armor: " + el.getAsString());
+ }
+ horse.setHorseArmorStack(new ItemStack(item));
+ }
+ }
+ if (info.has("saddled")) {
+ horse.setHorseSaddled(info.get("saddled").getAsBoolean());
+ }
+ return horse;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java
new file mode 100644
index 00000000..74535ce9
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/InvisibleModifier.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+
+public class InvisibleModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ base.setInvisible(!info.has("invisible") || info.get("invisible").getAsBoolean());
+ return base;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/NameModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/NameModifier.java
new file mode 100644
index 00000000..c0fd23bd
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/NameModifier.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+
+public class NameModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (base instanceof GUIClientPlayer) {
+ ((GUIClientPlayer) base).setName(info.get("name").getAsString());
+ }
+ base.setCustomNameTag(info.get("name").getAsString());
+ return base;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java
new file mode 100644
index 00000000..72dd8b73
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/RidingModifier.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+
+public class RidingModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ EntityLivingBase newEntity = EntityViewer.constructEntity(info);
+ if (newEntity == null) return null;
+ newEntity.mountEntity(base);
+ return base;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java
new file mode 100644
index 00000000..076e8417
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/SkinModifier.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EnumPlayerModelParts;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.Map;
+
+public class SkinModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (base instanceof GUIClientPlayer) {
+ GUIClientPlayer player = (GUIClientPlayer) base;
+ if (info.has("cape")) {
+ player.overrideCape = new ResourceLocation(info.get("cape").getAsString());
+ }
+ if (info.has("skin")) {
+ player.overrideSkin = new ResourceLocation(info.get("skin").getAsString());
+ }
+ if (info.has("slim")) {
+ player.overrideIsSlim = info.get("slim").getAsBoolean();
+ }
+ if (info.has("parts")) {
+ JsonElement parts = info.get("parts");
+ byte partBitField = player.getDataWatcher().getWatchableObjectByte(10);
+ if (parts.isJsonPrimitive() && parts.getAsJsonPrimitive().isBoolean()) {
+ partBitField = parts.getAsBoolean() ? (byte) -1 : 0;
+ } else {
+ JsonObject obj = parts.getAsJsonObject();
+ for (Map.Entry<String, JsonElement> part : obj.entrySet()) {
+ EnumPlayerModelParts modelPart = EnumPlayerModelParts.valueOf(part.getKey());
+ if (part.getValue().getAsBoolean()) {
+ partBitField |= modelPart.getPartMask();
+ } else {
+ partBitField &= ~modelPart.getPartMask();
+ }
+ }
+ }
+ player.getDataWatcher().updateObject(10, partBitField);
+ }
+ }
+ return base;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java
new file mode 100644
index 00000000..3b73c26f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/entityviewer/WitherModifier.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.entityviewer;
+
+import com.google.gson.JsonObject;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.boss.EntityWither;
+
+public class WitherModifier extends EntityViewerModifier {
+ @Override
+ public EntityLivingBase applyModifier(EntityLivingBase base, JsonObject info) {
+ if (!(base instanceof EntityWither))
+ return null;
+ EntityWither wither = (EntityWither) base;
+ if (info.has("tiny")) {
+ if (info.get("tiny").getAsBoolean()) {
+ wither.setInvulTime(800);
+ } else {
+ wither.setInvulTime(0);
+ }
+ }
+ if (info.has("armored")) {
+ if (info.get("armored").getAsBoolean()) {
+ wither.setHealth(1);
+ } else {
+ wither.setHealth(wither.getMaxHealth());
+ }
+ }
+ return base;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java
new file mode 100644
index 00000000..54fcc204
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/AutoUpdater.java
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.updater;
+
+import com.google.common.collect.Iterables;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSyntaxException;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.MoulSigner;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraftforge.fml.common.Loader;
+import org.apache.commons.lang3.SystemUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+public class AutoUpdater {
+
+ NotEnoughUpdates neu;
+
+ public AutoUpdater(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ public void logProgress(String str) {
+ logProgress(new ChatComponentText(str));
+ }
+
+ public void logProgress(IChatComponent chatComponent) {
+ Minecraft.getMinecraft().addScheduledTask(() -> {
+ IChatComponent chatComponent1 = new ChatComponentText("");
+ chatComponent1.setChatStyle(new ChatStyle().setColor(EnumChatFormatting.AQUA));
+ chatComponent1.appendSibling(chatComponent);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§e[NEU-AutoUpdater] ").appendSibling(
+ chatComponent1));
+ });
+ }
+
+ public UpdateLoader getUpdateLoader(URL url) {
+ if (SystemUtils.IS_OS_UNIX) {
+ return new LinuxBasedUpdater(this, url);
+ }
+ if (Loader.isModLoaded("skyblockclientupdater") && SCUCompatUpdater.IS_ENABLED) {
+ return SCUCompatUpdater.tryCreate(this, url);
+ }
+ return null;
+ }
+
+ UpdateLoader updateLoader;
+
+ public void updateFromURL(URL url) {
+ if (updateLoader != null) {
+ logProgress(
+ "There is already an update in progress, so the auto updater cannot process this update (as it might already be installed or is currently being downloaded). Please restart your client to install another update");
+ return;
+ }
+ if (!"https".equals(url.getProtocol())) {
+ logProgress("§cInvalid protocol in url: " + url + ". Only https is a valid protocol.");
+ return;
+ }
+ updateLoader = getUpdateLoader(url);
+ if (updateLoader == null) {
+ return;
+ }
+ updateLoader.greet();
+ logProgress(new ChatComponentText("[Start download now]")
+ .setChatStyle(new ChatStyle()
+ .setColor(EnumChatFormatting.GREEN)
+ .setChatHoverEvent(new HoverEvent(
+ HoverEvent.Action.SHOW_TEXT,
+ new ChatComponentText("Click to start download.")
+ ))
+ .setChatClickEvent(new ClickEvent(
+ ClickEvent.Action.RUN_COMMAND,
+ "/neuupdate scheduleDownload"
+ ))));
+ }
+
+ public void scheduleDownload() {
+ if (updateLoader == null) {
+ logProgress("§cNo update found. Try running /neuupdate check first");
+ return;
+ }
+ if (updateLoader.getState() != UpdateLoader.State.NOTHING) {
+ logProgress("§cUpdate download already started. No need to start the download again.");
+ return;
+ }
+ logProgress("Download started.");
+ updateLoader.scheduleDownload();
+ }
+
+ private void displayUpdateMessage(
+ JsonObject updateJson,
+ String updateMessage,
+ String downloadLink,
+ String directDownload
+ ) {
+ int firstWidth = -1;
+
+ for (String line : Iterables.concat(Arrays.asList(updateMessage.split("\n")), Arrays.asList("Download here"))) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ boolean isDownloadLink = line.equals("Download here");
+ int width = fr.getStringWidth(line);
+ if (firstWidth == -1) {
+ firstWidth = width;
+ }
+ int missingLen = firstWidth - width;
+ if (missingLen > 0) {
+ StringBuilder sb = new StringBuilder(missingLen / 4 / 2 + line.length());
+ for (int i = 0; i < missingLen / 4 / 2; i++) { /* fr.getCharWidth(' ') == 4 */
+ sb.append(" ");
+ }
+ sb.append(line);
+ line = sb.toString();
+ }
+ ChatComponentText cp = new ChatComponentText(line);
+ if (isDownloadLink)
+ cp.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, downloadLink));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(cp);
+ }
+ neu.displayLinks(updateJson, firstWidth);
+ NotificationHandler.displayNotification(Arrays.asList(
+ "",
+ "§eThere is a new version of NotEnoughUpdates available.",
+ "§eCheck the chat for more information"
+ ), true);
+ try {
+ if (directDownload != null)
+ updateFromURL(new URL(directDownload));
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void displayUpdateMessageIfOutOfDate() {
+ File repo = neu.manager.repoLocation;
+ File updateJson = new File(repo, "update.json");
+ if (updateJson.exists()) {
+ if (!MoulSigner.verifySignature(updateJson)) {
+ NotEnoughUpdates.LOGGER.error("update.json found without signature");
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "§e[NEU] §cThere has been an error checking for updates. Check the log or join the discord for more information.").setChatStyle(
+ Utils.createClickStyle(
+ ClickEvent.Action.OPEN_URL, "https://discord.gg/moulberry")));
+ return;
+ }
+ try {
+ JsonObject o = neu.manager.getJsonFromFile(updateJson);
+
+ int fullReleaseVersion =
+ o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1;
+ int preReleaseVersion =
+ o.has("version_id") && o.get("version_id").isJsonPrimitive() ? o.get("version_id").getAsInt() : -1;
+ int hotfixVersion =
+ o.has("hotfix_id") && o.get("hotfix_id").isJsonPrimitive() ? o.get("hotfix_id").getAsInt() : -1;
+
+ boolean hasFullReleaseAvailableForUpgrade = fullReleaseVersion > NotEnoughUpdates.VERSION_ID;
+ boolean hasHotfixAvailableForUpgrade =
+ fullReleaseVersion == NotEnoughUpdates.VERSION_ID && hotfixVersion > NotEnoughUpdates.HOTFIX_VERSION_ID;
+ boolean hasPreReleaseAvailableForUpdate =
+ fullReleaseVersion == NotEnoughUpdates.VERSION_ID && preReleaseVersion > NotEnoughUpdates.PRE_VERSION_ID;
+
+ int updateChannel = NotEnoughUpdates.INSTANCE.config.notifications.updateChannel; /* 1 = Full, 2 = Pre */
+ if (hasFullReleaseAvailableForUpgrade || (hasHotfixAvailableForUpgrade && updateChannel == 1)) {
+ displayUpdateMessage(
+ o,
+ o.get("update_msg").getAsString(),
+ o.get("update_link").getAsString(),
+ o.has("update_direct") ? o.get("update_direct").getAsString() : null
+ );
+ } else if (hasPreReleaseAvailableForUpdate && updateChannel == 2) {
+ displayUpdateMessage(
+ o,
+ o.get("pre_update_msg").getAsString(),
+ o.get("pre_update_link").getAsString(),
+ o.has("pre_update_direct") ? o.get("pre_update_direct").getAsString() : null
+ );
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "§e[NEU] §cThere has been an error checking for updates. Check the log or join the discord for more information.").setChatStyle(
+ Utils.createClickStyle(
+ ClickEvent.Action.OPEN_URL, "https://discord.gg/moulberry")));
+ }
+ }
+ }
+
+ private boolean validateMcModInfo(JsonArray array) {
+ if (array.size() != 1) return false;
+ JsonElement jsonElement = array.get(0);
+ if (!jsonElement.isJsonObject()) return false;
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ if (!jsonObject.has("modid")) return false;
+ JsonElement modid = jsonObject.get("modid");
+ if (!modid.isJsonPrimitive()) return false;
+ JsonPrimitive primitive = modid.getAsJsonPrimitive();
+ if (!primitive.isString()) return false;
+ return "notenoughupdates".equals(primitive.getAsString());
+ }
+
+ public boolean isNeuJar(File sus) {
+ try (ZipFile zipFile = new ZipFile(sus)) {
+ ZipEntry entry = zipFile.getEntry("mcmod.info");
+ if (entry == null) {
+ return false;
+ }
+ try (InputStream inputStream = zipFile.getInputStream(entry)) {
+ JsonArray jsonArray = neu.manager.gson.fromJson(
+ new InputStreamReader(inputStream),
+ JsonArray.class
+ );
+ return validateMcModInfo(jsonArray);
+ }
+ } catch (IOException | JsonSyntaxException e) {
+ e.printStackTrace();
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java
new file mode 100644
index 00000000..3118b135
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/LinuxBasedUpdater.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.updater;
+
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+
+class LinuxBasedUpdater /* Based on what? */ extends UpdateLoader {
+
+ LinuxBasedUpdater(AutoUpdater updater, URL url) {
+ super(updater, url);
+ }
+
+ @Override
+ public void greet() {
+ updater.logProgress(
+ "Welcome Aristocrat! Your superior linux system configuration is supported for NEU auto updates.");
+ }
+
+ @Override
+ public void deleteFiles(List<File> toDelete) {
+ for (File toDel : toDelete) {
+ if (!toDel.delete()) {
+ updater.logProgress("§cCould not delete old version of NEU: " + toDel + ". Please manually delete file.");
+ state = State.FAILED;
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java
new file mode 100644
index 00000000..3cb600cb
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/SCUCompatUpdater.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.updater;
+
+import java.io.File;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.List;
+
+/*
+ * Legal considerations: Skyblock Client Updater is licensed under the GNU AGPL v3.0 or later (with modifications).
+ * https://github.com/My-Name-Is-Jeff/SkyblockClient-Updater/blob/main/LICENSE
+ *
+ * However, even tho the AGPL License does not allow conveying covered work in combination with LGPL licensed code
+ * (such as our own), we do not perceive ourselves as conveying neither an unmodified version of Skyblock Client Updater
+ * nor a work based on Skyblock Client Updater (modified work) since our work is usable and functional in its entirety
+ * without presence of Skyblock Client Updater and is not to be distributed along a copy of Skyblock Client Updater
+ * unless that combined work is licensed with respect of both the LGPL and the AGPL, therefore is not adapting any part
+ * of Skyblock Client Updater unless already part of a whole distribution.
+ *
+ * In case the Copyright owner (Lily aka My-Name-Is-Jeff on Github) disagrees, we are willing to take down this module
+ * (or only convey this component of our work under a pure GPL license) with or without them providing legal grounds
+ * for this request. However, due to them not being able to be reached for comment, we will include this
+ * component for the time being.
+ * */
+public class SCUCompatUpdater extends UpdateLoader {
+
+ public static final boolean IS_ENABLED = false;
+
+ private SCUCompatUpdater(AutoUpdater updater, URL url) {
+ super(updater, url);
+ }
+
+ @Override
+ public void greet() {
+ updater.logProgress("Skyblock Client Updater compatibility layer loaded.");
+ }
+
+ @Override
+ public void deleteFiles(List<File> toDelete) {
+ try {
+ for (File f : toDelete)
+ ReflectionHolder.deleteFileOnShutdownHandle.invoke(ReflectionHolder.updateCheckerInstance, f, "");
+ } catch (Throwable e) {
+ e.printStackTrace();
+ updater.logProgress("Invoking SCU failed. Check the log for more info.");
+ state = State.FAILED;
+ }
+ }
+
+ static class ReflectionHolder {
+ static boolean isSCUFullyPresent = false;
+ static Class<?> updateChecker;
+ static Object updateCheckerInstance;
+ static Method deleteFileOnShutdown;
+ static MethodHandle deleteFileOnShutdownHandle;
+
+ static {
+ try {
+ updateChecker = Class.forName("mynameisjeff.skyblockclientupdater.utils.UpdateChecker");
+ Field instanceField = updateChecker.getDeclaredField("INSTANCE");
+ instanceField.setAccessible(true);
+ updateCheckerInstance = instanceField.get(null);
+ deleteFileOnShutdown = updateChecker.getDeclaredMethod("deleteFileOnShutdown", File.class, String.class);
+ deleteFileOnShutdownHandle = MethodHandles.publicLookup().unreflect(deleteFileOnShutdown);
+ isSCUFullyPresent = true;
+ } catch (NoSuchFieldException | ClassNotFoundException | IllegalAccessException | NoSuchMethodException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static UpdateLoader tryCreate(AutoUpdater updater, URL url) {
+ if (!ReflectionHolder.isSCUFullyPresent) {
+ updater.logProgress("§cFound Skyclient Updater Mod, however our hooks did not function properly.");
+ return null;
+ }
+ return new SCUCompatUpdater(updater, url);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java
new file mode 100644
index 00000000..1a1a8504
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/updater/UpdateLoader.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscfeatures.updater;
+
+import io.github.moulberry.notenoughupdates.util.NetUtils;
+import net.minecraft.client.Minecraft;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class UpdateLoader {
+
+ enum State {
+ NOTHING, DOWNLOAD_STARTED, DOWNLOAD_FINISHED, INSTALLED, FAILED
+ }
+
+ URL url;
+ AutoUpdater updater;
+
+ State state = State.NOTHING;
+
+ UpdateLoader(AutoUpdater updater, URL url) {
+ this.url = url;
+ this.updater = updater;
+ }
+
+ public State getState() {
+ return state;
+ }
+
+ public void setState(State state) {
+ this.state = state;
+ }
+
+ public URL getUrl() {
+ return url;
+ }
+
+ public void scheduleDownload() {
+ state = State.DOWNLOAD_STARTED;
+ try {
+ NetUtils.downloadAsync(url, File.createTempFile("NotEnoughUpdates-update", ".jar"))
+ .handle(
+ (f, exc) -> {
+ if (exc != null) {
+ state = State.FAILED;
+ updater.logProgress("§cError while downloading. Check your logs for more info.");
+ exc.printStackTrace();
+ return null;
+ }
+ state = State.DOWNLOAD_FINISHED;
+
+ updater.logProgress("Download completed. Trying to install");
+ launchUpdate(f);
+ return null;
+ });
+ } catch (IOException e) {
+ state = State.FAILED;
+ updater.logProgress("§cError while creating download. Check your logs for more info.");
+ e.printStackTrace();
+ }
+ }
+
+ public abstract void greet();
+
+ public void launchUpdate(File file) {
+
+ if (state != State.DOWNLOAD_FINISHED) {
+ updater.logProgress("§cUpdate is invalid state " + state + " to start update.");
+ state = State.FAILED;
+ return;
+ }
+ File mcDataDir = new File(Minecraft.getMinecraft().mcDataDir, "mods");
+ if (!mcDataDir.exists() || !mcDataDir.isDirectory() || !mcDataDir.canRead()) {
+ updater.logProgress("§cCould not find mods folder. Searched: " + mcDataDir);
+ state = State.FAILED;
+ return;
+ }
+ ArrayList<File> toDelete = new ArrayList<>();
+ File[] modFiles = mcDataDir.listFiles();
+ if (modFiles == null) {
+ updater.logProgress("§cCould not list minecraft mod folder (" + mcDataDir + ")");
+ state = State.FAILED;
+ return;
+ }
+ for (File sus : modFiles) {
+ if (sus.getName().endsWith(".jar")) {
+ if (updater.isNeuJar(sus)) {
+ updater.logProgress("Found old NEU file: " + sus + ". Deleting later.");
+ toDelete.add(sus);
+ }
+ }
+ }
+ File dest = new File(mcDataDir, file.getName());
+ try (
+ InputStream i = Files.newInputStream(file.toPath());
+ OutputStream o = Files.newOutputStream(dest.toPath());
+ ) {
+ IOUtils.copyLarge(i, o);
+ } catch (IOException e) {
+ e.printStackTrace();
+ updater.logProgress(
+ "§cFailed to copy release JAR. Not making any changes to your mod folder. Consult your logs for more info.");
+ state = State.FAILED;
+ }
+ deleteFiles(toDelete);
+ if (state != State.FAILED) {
+ state = State.INSTALLED;
+ updater.logProgress("Update successful. Thank you for your time.");
+ return;
+ }
+ updater.logProgress("§cFailure to delete some files. Please delte the old NEU version manually from your mods folder.");
+ }
+
+ public abstract void deleteFiles(List<File> toDelete);
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
index 8996dc7a..530dcfd1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
@@ -1,12 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats;
import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
@@ -33,8 +52,14 @@ import org.lwjgl.opengl.GL14;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.*;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -95,14 +120,30 @@ public class AccessoryBagOverlay {
int mouseX = Mouse.getX() / scaledResolution.getScaleFactor();
int mouseY = height - Mouse.getY() / scaledResolution.getScaleFactor();
- int xSize =
- (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "xSize", "field_146999_f");
- int ySize =
- (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "ySize", "field_147000_g");
- int guiLeft =
- (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiLeft", "field_147003_i");
- int guiTop =
- (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiTop", "field_147009_r");
+ int xSize = (int) Utils.getField(
+ GuiContainer.class,
+ Minecraft.getMinecraft().currentScreen,
+ "xSize",
+ "field_146999_f"
+ );
+ int ySize = (int) Utils.getField(
+ GuiContainer.class,
+ Minecraft.getMinecraft().currentScreen,
+ "ySize",
+ "field_147000_g"
+ );
+ int guiLeft = (int) Utils.getField(
+ GuiContainer.class,
+ Minecraft.getMinecraft().currentScreen,
+ "guiLeft",
+ "field_147003_i"
+ );
+ int guiTop = (int) Utils.getField(
+ GuiContainer.class,
+ Minecraft.getMinecraft().currentScreen,
+ "guiTop",
+ "field_147009_r"
+ );
if (mouseX < guiLeft + xSize + 3 || mouseX > guiLeft + xSize + 80 + 28) return false;
if (mouseY < guiTop || mouseY > guiTop + 166) return false;
@@ -797,7 +838,7 @@ public class AccessoryBagOverlay {
private static Comparator<String> getItemComparator() {
return (o1, o2) -> {
- float cost1;
+ double cost1;
JsonObject o1Auc = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(o1);
if (o1Auc != null && o1Auc.has("price")) {
cost1 = o1Auc.get("price").getAsFloat();
@@ -806,9 +847,9 @@ public class AccessoryBagOverlay {
if (info != null)
cost1 = info.craftCost;
else
- cost1 = 0;
+ cost1 = -1;
}
- float cost2;
+ double cost2;
JsonObject o2Auc = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(o2);
if (o2Auc != null && o2Auc.has("price")) {
cost2 = o2Auc.get("price").getAsFloat();
@@ -817,7 +858,7 @@ public class AccessoryBagOverlay {
if (info != null)
cost2 = info.craftCost;
else
- cost2 = 0;
+ cost2 = -1;
}
if (cost1 == -1 && cost2 == -1) return o1.compareTo(o2);
@@ -834,16 +875,17 @@ public class AccessoryBagOverlay {
private static boolean inAccessoryBag = false;
public static boolean isInAccessoryBag() {
- return inAccessoryBag;
+ return inAccessoryBag && NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay;
}
public static void renderOverlay() {
inAccessoryBag = false;
- if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && NEUEventListener.inventoryLoaded) {
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest && RenderListener.inventoryLoaded) {
GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
- if (containerName.trim().startsWith("Accessory Bag")) {
+ if (containerName.trim().startsWith("Accessory Bag") && !containerName.contains("Thaumaturgy") &&
+ !containerName.contains("Upgrades")) {
inAccessoryBag = true;
try {
int xSize = (int) Utils.getField(GuiContainer.class, eventGui, "xSize", "field_146999_f");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
index 98d8f11d..b1a3dca9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.gson.JsonArray;
@@ -36,7 +55,12 @@ import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import java.io.File;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -51,6 +75,8 @@ public class CalendarOverlay {
private static boolean enabled = false;
+ public static boolean ableToClickCalendar = true;
+
public static void setEnabled(boolean enabled) {
CalendarOverlay.enabled = enabled;
}
@@ -455,8 +481,7 @@ public class CalendarOverlay {
guiLeft = (width - xSize) / 2;
guiTop = 5;
-
- if (mouseX >= guiLeft && mouseX <= guiLeft + xSize) {
+ if (mouseX >= guiLeft && mouseX <= guiLeft + xSize && ableToClickCalendar) {
if (mouseY >= guiTop && mouseY <= guiTop + ySize) {
ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neucalendar");
}
@@ -659,6 +684,8 @@ public class CalendarOverlay {
}
}
}
+ } else {
+ Minecraft.getMinecraft().dispatchKeypresses();
}
}
}
@@ -839,8 +866,8 @@ public class CalendarOverlay {
SBEvent firstEvent = null;
List<SBEvent> nextFavourites = new ArrayList<>();
List<Long> nextFavouritesTime = new ArrayList<>();
- long timeUntilMajor = 0;
- SBEvent nextMajorEvent = null;
+ long timeUntilMayor = 0;
+ SBEvent nextMayorEvent = null;
List<String> eventFavourites = NotEnoughUpdates.INSTANCE.config.hidden.eventFavourites;
@@ -863,10 +890,10 @@ public class CalendarOverlay {
}
}
- if (nextMajorEvent == null && !sbEvent.id.split(":")[0].equals("jacob_farming") &&
+ if (nextMayorEvent == null && !sbEvent.id.split(":")[0].equals("jacob_farming") &&
!sbEvent.id.equals("dark_auction")) {
- nextMajorEvent = sbEvent;
- timeUntilMajor = timeUntilMillis;
+ nextMayorEvent = sbEvent;
+ timeUntilMayor = timeUntilMillis;
}
if (firstEvent == null) {
@@ -893,7 +920,7 @@ public class CalendarOverlay {
}
}
- if (nextFavourites.size() >= 3 && nextMajorEvent != null) {
+ if (nextFavourites.size() >= 3 && nextMayorEvent != null) {
break out;
}
}
@@ -974,18 +1001,18 @@ public class CalendarOverlay {
if (sbEvent.id.split(":")[0].equals("jacob_farming") && sbEvent.desc != null) {
tooltipToDisplay.addAll(sbEvent.desc);
}
- if (nextMajorEvent != null || i < nextFavourites.size() - 1) {
+ if (nextMayorEvent != null || i < nextFavourites.size() - 1) {
tooltipToDisplay.add("");
}
}
- if (nextMajorEvent != null) {
- tooltipToDisplay.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Next Major:");
- tooltipToDisplay.add(nextMajorEvent.display);
+ if (nextMayorEvent != null) {
+ tooltipToDisplay.add(EnumChatFormatting.YELLOW.toString() + EnumChatFormatting.BOLD + "Next Mayor:");
+ tooltipToDisplay.add(nextMayorEvent.display);
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW +
- prettyTime(timeUntilMajor, false));
- if (nextMajorEvent.lastsFor >= 0) {
+ prettyTime(timeUntilMayor, false));
+ if (nextMayorEvent.lastsFor >= 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Lasts for: " + EnumChatFormatting.YELLOW +
- prettyTime(nextMajorEvent.lastsFor, true));
+ prettyTime(nextMayorEvent.lastsFor, true));
}
}
@@ -1000,6 +1027,21 @@ public class CalendarOverlay {
GlStateManager.translate(0, 0, -100);
}
}
+ } else if (!enabled && NotEnoughUpdates.INSTANCE.config.calendar.showEventTimerInInventory) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.disableFog();
+ GlStateManager.disableLighting();
+ GlStateManager.disableColorMaterial();
+
+ renderBlurredBackground(10, width, height, guiLeft + 3, guiTop + 3, xSize - 6, ySize - 6);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(DISPLAYBAR);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, 20, GL11.GL_NEAREST);
+
+ String nextS = EnumChatFormatting.RED + "Open calendar to see events";
+ fr.drawString(nextS, guiLeft + 8, guiTop + 6, -1, false);
}
}
GlStateManager.translate(0, 0, -10);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiCustomEnchant.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiCustomEnchant.java
index f5838052..6f190ada 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiCustomEnchant.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiCustomEnchant.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.collect.Lists;
@@ -9,8 +28,11 @@ import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingFloat;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
+import io.github.moulberry.notenoughupdates.miscgui.util.OrbDisplay;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
@@ -38,7 +60,12 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Project;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -49,9 +76,9 @@ public class GuiCustomEnchant extends Gui {
"textures/entity/enchanting_table_book.png");
private static final ModelBook MODEL_BOOK = new ModelBook();
- private static final int EXPERIENCE_ORB_COUNT = 30;
-
private static final Pattern XP_COST_PATTERN = Pattern.compile("\\u00a73(\\d+) Exp Levels");
+ private static final Pattern ENCHANT_LEVEL_PATTERN = Pattern.compile("(.*)_(.*)");
+ private static final Pattern ENCHANT_NAME_PATTERN = Pattern.compile("([^IVX]*) ([IVX]*)");
private enum EnchantState {
NO_ITEM,
@@ -80,6 +107,7 @@ public class GuiCustomEnchant extends Gui {
this.enchId = enchId;
this.displayLore = displayLore;
this.level = level;
+ this.enchId = ItemUtils.fixEnchantId(enchId, true);
if (Constants.ENCHANTS != null) {
if (checkConflicts && Constants.ENCHANTS.has("enchant_pools")) {
@@ -108,12 +136,18 @@ public class GuiCustomEnchant extends Gui {
if (level >= 1 && Constants.ENCHANTS.has("enchants_xp_cost")) {
JsonObject allCosts = Constants.ENCHANTS.getAsJsonObject("enchants_xp_cost");
- if (allCosts.has(enchId)) {
- JsonArray costs = allCosts.getAsJsonArray(enchId);
+ JsonObject maxLevel = null;
+ if (Constants.ENCHANTS.has("max_xp_table_levels")) {
+ maxLevel = Constants.ENCHANTS.getAsJsonObject("max_xp_table_levels");
+ }
+
+ if (allCosts.has(this.enchId)) {
+ JsonArray costs = allCosts.getAsJsonArray(this.enchId);
if (costs.size() >= 1) {
if (useMaxLevelForCost) {
- this.xpCost = costs.get(costs.size() - 1).getAsInt();
+ int cost = (maxLevel != null && maxLevel.has(this.enchId) ? maxLevel.get(this.enchId).getAsInt() : costs.size());
+ this.xpCost = costs.get(cost - 1).getAsInt();
} else if (level - 1 < costs.size()) {
this.xpCost = costs.get(level - 1).getAsInt();
} else {
@@ -127,21 +161,7 @@ public class GuiCustomEnchant extends Gui {
}
}
- public static class ExperienceOrb {
- public float x;
- public float y;
- public float xLast;
- public float yLast;
- public float xVel;
- public float yVel;
-
- public int type;
- public int rotationDeg;
- }
-
- private final List<ExperienceOrb> orbs = new ArrayList<>();
- private int orbTargetX = 0;
- private int orbTargetY = 0;
+ public OrbDisplay orbDisplay = new OrbDisplay();
private int guiLeft;
private int guiTop;
@@ -201,8 +221,15 @@ public class GuiCustomEnchant extends Gui {
}
public boolean shouldOverride(String containerName) {
+ if (containerName == null) {
+ shouldOverrideFast = false;
+ return false;
+ }
shouldOverrideFast = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableTableGUI &&
- Objects.equals("Enchant Item", containerName) &&
+ (containerName.length() >= 12 && Objects.equals(
+ "Enchant Item",
+ containerName.substring(0, "Enchant Item".length())
+ )) &&
NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard();
if (!shouldOverrideFast) {
currentState = EnchantState.NO_ITEM;
@@ -210,6 +237,13 @@ public class GuiCustomEnchant extends Gui {
removable.clear();
expectedMaxPage = 1;
}
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+ ItemStack hexStack = cc.getLowerChestInventory().getStackInSlot(50);
+ if (hexStack != null && hexStack.getItem() == Items.experience_bottle) {
+ shouldOverrideFast = false;
+ return false;
+ }
return shouldOverrideFast;
}
@@ -220,13 +254,15 @@ public class GuiCustomEnchant extends Gui {
ContainerChest cc = (ContainerChest) chest.inventorySlots;
ItemStack stack = cc.getLowerChestInventory().getStackInSlot(23);
- ItemStack enchantGuideStack = cc.getLowerChestInventory().getStackInSlot(50);
+ ItemStack arrowStack = cc.getLowerChestInventory().getStackInSlot(45);
ItemStack enchantingItemStack = cc.getLowerChestInventory().getStackInSlot(19);
+ ItemStack hexStack = cc.getLowerChestInventory().getStackInSlot(50);
int lastPage = currentPage;
this.lastState = currentState;
- if (enchantGuideStack != null && enchantGuideStack.getItem() != Items.book && enchantingItem != null) {
+ if (hexStack != null && hexStack.getItem() == Items.experience_bottle) return;
+ if (arrowStack != null && arrowStack.getItem() == Items.arrow && enchantingItem != null) {
currentState = EnchantState.ADDING_ENCHANT;
} else if (stack == null || enchantingItemStack == null) {
if (currentState == EnchantState.SWITCHING_DONT_UPDATE || currentState == EnchantState.NO_ITEM) {
@@ -280,30 +316,7 @@ public class GuiCustomEnchant extends Gui {
}
}
- List<ExperienceOrb> toRemove = new ArrayList<>();
- for (ExperienceOrb orb : orbs) {
- float targetDeltaX = guiLeft + orbTargetX - orb.x;
- float targetDeltaY = guiTop + orbTargetY - orb.y;
-
- float length = (float) Math.sqrt(targetDeltaX * targetDeltaX + targetDeltaY * targetDeltaY);
-
- if (length < 8 && orb.xVel * orb.xVel + orb.yVel * orb.yVel < 20) {
- toRemove.add(orb);
- continue;
- }
-
- orb.xVel += targetDeltaX * 2 / length;
- orb.yVel += targetDeltaY * 2 / length;
-
- orb.xVel *= 0.90;
- orb.yVel *= 0.90;
-
- orb.xLast = orb.x;
- orb.yLast = orb.y;
- orb.x += orb.xVel;
- orb.y += orb.yVel;
- }
- orbs.removeAll(toRemove);
+ orbDisplay.physicsTickOrbs();
if (++tickCounter >= 20) {
tickCounter = 0;
@@ -364,40 +377,50 @@ public class GuiCustomEnchant extends Gui {
if (ea != null) {
NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
if (enchantments != null) {
- for (String enchId : enchantments.getKeySet()) {
- String name = Utils.cleanColour(book.getDisplayName());
- if (name.equalsIgnoreCase("Bane of Arthropods")) {
- name = "Bane of Arth.";
- } else if (name.equalsIgnoreCase("Projectile Protection")) {
- name = "Projectile Prot";
- } else if (name.equalsIgnoreCase("Blast Protection")) {
- name = "Blast Prot";
- }
- Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
- Utils.getRawTooltip(book), enchantments.getInteger(enchId), false, true
- );
- enchantment.displayLore.remove(0);
+ String enchId = Utils
+ .cleanColour(book.getDisplayName())
+ .toLowerCase()
+ .replace(" ", "_")
+ .replace("-", "_")
+ .replaceAll("[^a-z_]", "");
+ String name = Utils.cleanColour(book.getDisplayName());
+ int enchLevel = -1;
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ }
+ Matcher levelMatcher = ENCHANT_LEVEL_PATTERN.matcher(enchId);
+ if (levelMatcher.matches()) {
+ enchLevel = Utils.parseRomanNumeral(levelMatcher.group(2).toUpperCase());
+ enchId = levelMatcher.group(1);
+ }
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), enchLevel, false, true
+ );
+ enchantment.displayLore.remove(0);
- if (removingEnchantPlayerLevel == -1 && playerEnchantIds.containsKey(enchId)) {
- removingEnchantPlayerLevel = playerEnchantIds.get(enchId);
- }
+ if (removingEnchantPlayerLevel == -1 && playerEnchantIds.containsKey(enchId)) {
+ removingEnchantPlayerLevel = playerEnchantIds.get(enchId);
+ }
- if (removingEnchantPlayerLevel >= 0 && enchantment.level < removingEnchantPlayerLevel) {
- continue;
- }
+ if (removingEnchantPlayerLevel >= 0 && enchantment.level < removingEnchantPlayerLevel) {
+ continue;
+ }
- if (enchanterCurrentEnch == null) {
+ if (enchanterCurrentEnch == null) {
+ enchanterCurrentEnch = enchantment;
+ } else if (updateLevel) {
+ if (removingEnchantPlayerLevel < 0 && enchantment.level > enchanterCurrentEnch.level) {
+ enchanterCurrentEnch = enchantment;
+ } else if (removingEnchantPlayerLevel >= 0 && enchantment.level < enchanterCurrentEnch.level) {
enchanterCurrentEnch = enchantment;
- } else if (updateLevel) {
- if (removingEnchantPlayerLevel < 0 && enchantment.level > enchanterCurrentEnch.level) {
- enchanterCurrentEnch = enchantment;
- } else if (removingEnchantPlayerLevel >= 0 && enchantment.level < enchanterCurrentEnch.level) {
- enchanterCurrentEnch = enchantment;
- }
}
-
- enchanterEnchLevels.put(enchantment.level, enchantment);
}
+
+ enchanterEnchLevels.put(enchantment.level, enchantment);
}
}
}
@@ -430,43 +453,53 @@ public class GuiCustomEnchant extends Gui {
if (ea != null) {
NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
if (enchantments != null) {
- for (String enchId : enchantments.getKeySet()) {
- String name = Utils.cleanColour(book.getDisplayName());
-
- if (searchField.getText().trim().isEmpty() ||
- name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
- if (name.equalsIgnoreCase("Bane of Arthropods")) {
- name = "Bane of Arth.";
- } else if (name.equalsIgnoreCase("Projectile Protection")) {
- name = "Projectile Prot";
- } else if (name.equalsIgnoreCase("Blast Protection")) {
- name = "Blast Prot";
- } else if (name.equalsIgnoreCase("Luck of the Sea")) {
- name = "Luck of Sea";
- }
+ String enchId = Utils
+ .cleanColour(book.getDisplayName())
+ .toLowerCase()
+ .replace(" ", "_")
+ .replace("-", "_")
+ .replaceAll("[^a-z_]", "");
+ if (enchId.equalsIgnoreCase("_")) continue;
+ enchId = ItemUtils.fixEnchantId(enchId, true);
+ String name = Utils.cleanColour(book.getDisplayName());
+
+ if (searchField.getText().trim().isEmpty() ||
+ name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ } else if (name.equalsIgnoreCase("Luck of the Sea")) {
+ name = "Luck of Sea";
+ }
+ Matcher nameMatcher = ENCHANT_NAME_PATTERN.matcher(name);
+ if (nameMatcher.matches()) {
+ name = nameMatcher.group(1);
+ }
- if (playerEnchantIds.containsKey(enchId)) {
- Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
- Utils.getRawTooltip(book), playerEnchantIds.get(enchId), false, false
- );
- if (!enchantment.overMaxLevel) {
- removable.add(enchantment);
- }
- } else {
- Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
- Utils.getRawTooltip(book), enchantments.getInteger(enchId), true, true
- );
- applicable.add(enchantment);
+ if (playerEnchantIds.containsKey(enchId)) {
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), playerEnchantIds.get(enchId), false, false
+ );
+ if (!enchantment.overMaxLevel) {
+ removable.add(enchantment);
}
} else {
- if (playerEnchantIds.containsKey(enchId)) {
- searchRemovedFromRemovable = true;
- } else {
- searchRemovedFromApplicable = true;
- }
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), 1, true, true
+ );
+ applicable.add(enchantment);
+ }
+ } else {
+ if (playerEnchantIds.containsKey(enchId)) {
+ searchRemovedFromRemovable = true;
+ } else {
+ searchRemovedFromApplicable = true;
}
-
}
+
}
}
}
@@ -945,7 +978,7 @@ public class GuiCustomEnchant extends Gui {
GlStateManager.pushMatrix();
GlStateManager.translate(guiLeft + 102 - 8, guiTop + 191 - (inventoryStartIndex / 9 * 18 + 89), 0);
Slot slot = cc.getSlot(inventoryStartIndex + i);
- chest.drawSlot(slot);
+ ((AccessorGuiContainer) chest).doDrawSlot(slot);
GlStateManager.popMatrix();
if (mouseX >= itemX && mouseX < itemX + 18 &&
@@ -1040,7 +1073,9 @@ public class GuiCustomEnchant extends Gui {
Minecraft.getMinecraft().fontRendererObj.drawString(levelStr, left + 8 - levelWidth / 2, top + 4, colour, false);
//Enchant name
- String name = WordUtils.capitalizeFully(enchanterCurrentEnch.enchId.replace("_", " "));
+ String name = WordUtils.capitalizeFully(ItemUtils
+ .fixEnchantId(enchanterCurrentEnch.enchId, false)
+ .replace("_", " "));
if (name.equalsIgnoreCase("Bane of Arthropods")) {
name = "Bane of Arth.";
} else if (name.equalsIgnoreCase("Projectile Protection")) {
@@ -1331,37 +1366,11 @@ public class GuiCustomEnchant extends Gui {
//Orb animation
Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
- GlStateManager.color(1, 1, 1, 1);
GlStateManager.disableDepth();
- for (ExperienceOrb orb : orbs) {
- int orbX = Math.round(orb.xLast + (orb.x - orb.xLast) * partialTicks);
- int orbY = Math.round(orb.yLast + (orb.y - orb.yLast) * partialTicks);
- GlStateManager.pushMatrix();
- GlStateManager.translate(orbX, orbY, 0);
- GlStateManager.rotate(orb.rotationDeg, 0, 0, 1);
-
- float targetDeltaX = guiLeft + orbTargetX - orb.x;
- float targetDeltaY = guiTop + orbTargetY - orb.y;
- float length = (float) Math.sqrt(targetDeltaX * targetDeltaX + targetDeltaY * targetDeltaY);
- float velSq = orb.xVel * orb.xVel + orb.yVel * orb.yVel;
- float opacity = Math.min(2, Math.max(0.5f, length / 16)) * Math.min(2, Math.max(0.5f, velSq / 40));
- if (opacity > 1) opacity = 1;
- opacity = (float) Math.sqrt(opacity);
- GlStateManager.color(1, 1, 1, opacity);
-
- Utils.drawTexturedRect(
- -8,
- -8,
- 16,
- 16,
- ((orb.type % 3) * 16) / 512f,
- (16 + (orb.type % 3) * 16) / 512f,
- (217 + orb.type / 3 * 16) / 512f,
- (217 + 16 + orb.type / 3 * 16) / 512f,
- GL11.GL_NEAREST
- );
- GlStateManager.popMatrix();
- }
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft, guiTop, 0);
+ orbDisplay.renderOrbs(partialTicks);
+ GlStateManager.popMatrix();
GlStateManager.enableDepth();
if (stackOnMouse != null) {
@@ -1378,37 +1387,6 @@ public class GuiCustomEnchant extends Gui {
GlStateManager.translate(0, 0, -300);
}
- private void spawnExperienceOrbs(int startX, int startY, int targetX, int targetY, int baseType) {
- orbs.clear();
-
- this.orbTargetX = targetX;
- this.orbTargetY = targetY;
-
- Random rand = new Random();
- for (int i = 0; i < EXPERIENCE_ORB_COUNT; i++) {
- ExperienceOrb orb = new ExperienceOrb();
- orb.x = startX;
- orb.y = startY;
- orb.xLast = startX;
- orb.yLast = startY;
- orb.xVel = rand.nextFloat() * 20 - 10;
- orb.yVel = rand.nextFloat() * 20 - 10;
- orb.type = baseType;
-
- float typeRand = rand.nextFloat();
- if (typeRand < 0.6) {
- orb.type += 0;
- } else if (typeRand < 0.9) {
- orb.type += 1;
- } else {
- orb.type += 2;
- }
- orb.rotationDeg = rand.nextInt(4) * 90;
-
- orbs.add(orb);
- }
- }
-
private void renderEnchantBook(ScaledResolution scaledresolution, float partialTicks) {
GlStateManager.enableDepth();
@@ -1515,9 +1493,9 @@ public class GuiCustomEnchant extends Gui {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
}
@@ -1567,9 +1545,9 @@ public class GuiCustomEnchant extends Gui {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
} else if (!isChangingEnchLevel && enchanterCurrentEnch != null &&
@@ -1592,9 +1570,9 @@ public class GuiCustomEnchant extends Gui {
int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
if (playerXpLevel >= enchanterCurrentEnch.xpCost) {
if (removingEnchantPlayerLevel >= 0 && enchanterCurrentEnch.level == removingEnchantPlayerLevel) {
- spawnExperienceOrbs(guiLeft + X_SIZE / 2, guiTop + 66, X_SIZE / 2, 36, 3);
+ orbDisplay.spawnExperienceOrbs(X_SIZE / 2, 66, X_SIZE / 2, 36, 3);
} else {
- spawnExperienceOrbs(mouseX, mouseY, X_SIZE / 2, 66, 0);
+ orbDisplay.spawnExperienceOrbs(mouseX - guiLeft, mouseY - guiTop, X_SIZE / 2, 66, 0);
}
}
@@ -1765,9 +1743,9 @@ public class GuiCustomEnchant extends Gui {
} else if (currentState == EnchantState.ADDING_ENCHANT) {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
}
@@ -1805,9 +1783,9 @@ public class GuiCustomEnchant extends Gui {
} else if (currentState == EnchantState.ADDING_ENCHANT) {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
}
@@ -1852,9 +1830,9 @@ public class GuiCustomEnchant extends Gui {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
}
@@ -1873,9 +1851,9 @@ public class GuiCustomEnchant extends Gui {
EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
- ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(48);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
- chest.inventorySlots.windowId, 48, 0, 0, stack, transactionID));
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
cancelButtonAnimTime = System.currentTimeMillis();
}
@@ -1899,6 +1877,7 @@ public class GuiCustomEnchant extends Gui {
}
return Keyboard.getEventKey() != Keyboard.KEY_ESCAPE &&
+ Keyboard.getEventKey() != Minecraft.getMinecraft().gameSettings.keyBindInventory.getKeyCode() &&
(!NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking ||
Keyboard.getEventKey() != NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockKey);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiEnchantColour.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiEnchantColour.java
index bd4bd680..b90b1356 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiEnchantColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiEnchantColour.java
@@ -1,13 +1,34 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
-import com.google.gson.*;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
-import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
@@ -66,7 +87,9 @@ public class GuiEnchantColour extends GuiScreen {
private static final Pattern settingPattern = Pattern.compile(".*:[>=<]:[0-9]+:[a-zA-Z0-9]+(:[a-zA-Z0-9]+)?");
private ItemStack maxedBook;
+ private ItemStack maxedAttBook;
private int maxedBookFound = 0;
+ private int maxedAttBookFound = 0;
private List<String> getEnchantColours() {
return NotEnoughUpdates.INSTANCE.config.hidden.enchantColours;
@@ -227,14 +250,42 @@ public class GuiEnchantColour extends GuiScreen {
if (maxedBookFound == 1) {
Utils.drawItemStack(maxedBook, guiLeft + xSize + 3, guiTopSidebar - 34);
}
+ if (maxedAttBookFound == 0) {
+ try {
+ if (NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("MAXED_ATTRIBUTE_SHARD")).hasDisplayName()) {
+ maxedAttBook = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("MAXED_ATTRIBUTE_SHARD"));
+ maxedAttBookFound = 1;
+ } else {
+ maxedAttBookFound = 2;
+ }
+
+ } catch (Exception ignored) {
+ maxedAttBookFound = 2;
+ }
+ }
+ if (maxedAttBookFound == 1) {
+ Utils.drawItemStack(maxedAttBook, guiLeft + xSize + 3, guiTopSidebar - 52);
+ }
+
+ if (mouseX >= guiLeft + xSize + 3 && mouseX < guiLeft + xSize + 39) {
+ boolean renderingTooltip = false;
- if (mouseX >= guiLeft + xSize + 3 && mouseX < guiLeft + xSize + 19) {
if (mouseY >= guiTopSidebar - 34 && mouseY <= guiTopSidebar - 18 && maxedBookFound == 1) {
tooltipToDisplay = maxedBook.getTooltip(Minecraft.getMinecraft().thePlayer, false);
Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
tooltipToDisplay = null;
+ renderingTooltip = true;
+ }
+ if (mouseY >= guiTopSidebar - 52 && mouseY <= guiTopSidebar - 34 && maxedAttBookFound == 1 && !renderingTooltip) {
+ tooltipToDisplay = maxedAttBook.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1, fr);
+ tooltipToDisplay = null;
+ renderingTooltip = true;
}
- if (mouseY >= guiTopSidebar - 18 && mouseY <= guiTopSidebar - 2) {
+ if (mouseY >= guiTopSidebar - 18 && mouseY <= guiTopSidebar - 2 && !renderingTooltip) {
tooltipToDisplay = Lists.newArrayList(
EnumChatFormatting.AQUA + "NEUEC Colouring Guide",
EnumChatFormatting.GREEN + "",
@@ -395,6 +446,11 @@ public class GuiEnchantColour extends GuiScreen {
}
@Override
+ public void onGuiClosed() {
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ }
+
+ @Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
for (int yIndex = 0; yIndex < guiElementTextFields.size(); yIndex++) {
@@ -573,10 +629,12 @@ public class GuiEnchantColour extends GuiScreen {
getEnchantOpString(guiElementTextFields.get(yIndex), comparators.get(yIndex), modifiers.get(yIndex))
);
} else if (mouseX > guiLeft + 160 && mouseX < guiLeft + 160 + 20) {
- NotEnoughUpdates.INSTANCE.config.hidden.enchantColours.remove(yIndex);
- guiElementTextFields.remove(yIndex);
- comparators.remove(yIndex);
- modifiers.remove(yIndex);
+ if (NotEnoughUpdates.INSTANCE.config.hidden.enchantColours.size() > 0) {
+ NotEnoughUpdates.INSTANCE.config.hidden.enchantColours.remove(yIndex);
+ guiElementTextFields.remove(yIndex);
+ comparators.remove(yIndex);
+ modifiers.remove(yIndex);
+ }
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java
index 7c74c6e2..7aa0d2ec 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiInvButtonEditor.java
@@ -1,11 +1,37 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
-import com.google.gson.*;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonParser;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.GlScissorStack;
import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.overlays.EquipmentOverlay;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
@@ -17,7 +43,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ResourceLocation;
-import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
@@ -29,8 +54,15 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.*;
+import java.util.Map;
+import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -53,6 +85,15 @@ public class GuiInvButtonEditor extends GuiScreen {
private int guiLeft;
private int guiTop;
+ //region getGuiCoordinates
+ public int getGuiLeft() {
+ return this.guiLeft;
+ }
+ public int getGuiTop() {
+ return this.guiTop;
+ }
+ //endregion
+
private static final int BACKGROUND_TYPES = 5;
private static final int ICON_TYPES = 3;
private int iconTypeIndex = 0;
@@ -107,8 +148,6 @@ public class GuiInvButtonEditor extends GuiScreen {
put("crypts", "skull:25d2f31ba162fe6272e831aed17f53213db6fa1c4cbe4fc827f3963cc98b9");
put("spiders den", "skull:c754318a3376f470e481dfcd6c83a59aa690ad4b4dd7577fdad1c2ef08d8aee6");
put("top of the nest", "skull:9d7e3b19ac4f3dee9c5677c135333b9d35a7f568b63d1ef4ada4b068b5a25");
- put("blazing fortress", "skull:c3687e25c632bce8aa61e0d64c24e694c3eea629ea944f4cf30dcfb4fbce071");
- put("blazing fortress magma boss", "skull:38957d5023c937c4c41aa2412d43410bda23cf79a9f6ab36b76fef2d7c429");
put("the end", "skull:7840b87d52271d2a755dedc82877e0ed3df67dcc42ea479ec146176b02779a5");
put("the end dragons nest", "skull:a1cd6d2d03f135e7c6b5d6cdae1b3a68743db4eb749faf7341e9fb347aa283b");
put("the park", "skull:a221f813dacee0fef8c59f76894dbb26415478d9ddfc44c2e708a6d3b7549b");
@@ -117,11 +156,18 @@ public class GuiInvButtonEditor extends GuiScreen {
put("gold mines", "skull:73bc965d579c3c6039f0a17eb7c2e6faf538c7a5de8e60ec7a719360d0a857a9");
put("deep caverns", "skull:569a1f114151b4521373f34bc14c2963a5011cdc25a6554c48c708cd96ebfc");
put("the barn", "skull:4d3a6bd98ac1833c664c4909ff8d2dc62ce887bdcf3cc5b3848651ae5af6b");
- put("mushroom desert", "skull:2116b9d8df346a25edd05f842e7a9345beaf16dca4118abf5a68c75bcaae10");
+ put("mushroom desert", "skull:6b20b23c1aa2be0270f016b4c90d6ee6b8330a17cfef87869d6ad60b2ffbf3b5");
put("dungeon hub", "skull:9b56895b9659896ad647f58599238af532d46db9c1b0389b8bbeb70999dab33d");
- put("dwarven mines", "skull:569a1f114151b4521373f34bc14c2963a5011cdc25a6554c48c708cd96ebfc");
+ put("dwarven mines", "skull:51539dddf9ed255ece6348193cd75012c82c93aec381f05572cecf7379711b3b");
put("hotm heart of the mountain", "skull:86f06eaa3004aeed09b3d5b45d976de584e691c0e9cade133635de93d23b9edb");
put("bazaar dude", "skull:c232e3820897429157619b0ee099fec0628f602fff12b695de54aef11d923ad7");
+ put("museum", "skull:438cf3f8e54afc3b3f91d20a49f324dca1486007fe545399055524c17941f4dc");
+ put("crystal hollows", "skull:21dbe30b027acbceb612563bd877cd7ebb719ea6ed1399027dcee58bb9049d4a");
+ put("dwarven forge", "skull:5cbd9f5ec1ed007259996491e69ff649a3106cf920227b1bb3a71ee7a89863f");
+ put("forgotton skull", "skull:6becc645f129c8bc2faa4d8145481fab11ad2ee75749d628dcd999aa94e7");
+ put("crystal nucleus", "skull:34d42f9c461cee1997b67bf3610c6411bf852b9e5db607bbf626527cfb42912c");
+ put("void sepulture", "skull:eb07594e2df273921a77c101d0bfdfa1115abed5b9b2029eb496ceba9bdbb4b3");
+ put("crimson isle", "skull:c3687e25c632bce8aa61e0d64c24e694c3eea629ea944f4cf30dcfb4fbce071");
}};
private static LinkedHashMap<String, List<NEUConfig.InventoryButton>> presets = null;
@@ -130,7 +176,6 @@ public class GuiInvButtonEditor extends GuiScreen {
super();
reloadExtraIcons();
reloadPresets();
- Keyboard.enableRepeatEvents(true);
}
private static void reloadExtraIcons() {
@@ -282,6 +327,13 @@ public class GuiInvButtonEditor extends GuiScreen {
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, 0, xSize / 256f, 0, ySize / 256f, GL11.GL_NEAREST);
+ if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud) {
+ EquipmentOverlay.INSTANCE.renderPreviewArmorHud();
+ }
+ if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay) {
+ EquipmentOverlay.INSTANCE.renderPreviewPetInvHud();
+ }
+
for (NEUConfig.InventoryButton button : NotEnoughUpdates.INSTANCE.config.hidden.inventoryButtons) {
int x = guiLeft + button.x;
int y = guiTop + button.y;
@@ -292,6 +344,17 @@ public class GuiInvButtonEditor extends GuiScreen {
y += ySize;
}
+ if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+
if (button.isActive()) {
GlStateManager.color(1, 1, 1, 1f);
} else {
@@ -324,7 +387,7 @@ public class GuiInvButtonEditor extends GuiScreen {
Minecraft.getMinecraft().getTextureManager().bindTexture(custom_ench_colour);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(
- guiLeft - 88 - 2 - 22,
+ guiLeft - 88 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 2,
88,
20,
@@ -335,7 +398,7 @@ public class GuiInvButtonEditor extends GuiScreen {
GL11.GL_NEAREST
);
Utils.drawTexturedRect(
- guiLeft - 88 - 2 - 22,
+ guiLeft - 88 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 2 + 24,
88,
20,
@@ -348,7 +411,7 @@ public class GuiInvButtonEditor extends GuiScreen {
Utils.drawStringCenteredScaledMaxWidth(
"Load preset",
fontRendererObj,
- guiLeft - 44 - 2 - 22,
+ guiLeft - 44 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 8,
false,
86,
@@ -357,7 +420,7 @@ public class GuiInvButtonEditor extends GuiScreen {
Utils.drawStringCenteredScaledMaxWidth(
"from Clipboard",
fontRendererObj,
- guiLeft - 44 - 2 - 22,
+ guiLeft - 44 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 16,
false,
86,
@@ -366,7 +429,7 @@ public class GuiInvButtonEditor extends GuiScreen {
Utils.drawStringCenteredScaledMaxWidth(
"Save preset",
fontRendererObj,
- guiLeft - 44 - 2 - 22,
+ guiLeft - 44 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 8 + 24,
false,
86,
@@ -375,7 +438,7 @@ public class GuiInvButtonEditor extends GuiScreen {
Utils.drawStringCenteredScaledMaxWidth(
"to Clipboard",
fontRendererObj,
- guiLeft - 44 - 2 - 22,
+ guiLeft - 44 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0),
guiTop + 16 + 24,
false,
86,
@@ -383,7 +446,7 @@ public class GuiInvButtonEditor extends GuiScreen {
);
if (!validShareContents()) {
- Gui.drawRect(guiLeft - 88 - 2 - 22, guiTop + 2, guiLeft - 2 - 22, guiTop + 2 + 20, 0x80000000);
+ Gui.drawRect(guiLeft - 88 - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0), guiTop + 2, guiLeft - 2 - 22 - (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud ? 25 : 0), guiTop + 2 + 20, 0x80000000);
}
GlStateManager.color(1, 1, 1, 1);
@@ -427,6 +490,17 @@ public class GuiInvButtonEditor extends GuiScreen {
y += ySize;
}
+ if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+
GlStateManager.translate(0, 0, 300);
editorLeft = x + 8 - editorXSize / 2;
editorTop = y + 18 + 2;
@@ -707,6 +781,17 @@ public class GuiInvButtonEditor extends GuiScreen {
y += ySize;
}
+ if (NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop && y < guiTop + 84) {
+ x -= 25;
+ }
+ }
+ if (NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay) {
+ if (x < guiLeft + xSize - 150 && x > guiLeft + xSize - 200 && y > guiTop + 60 && y < guiTop + 120) {
+ x -= 25;
+ }
+ }
+
if (mouseX >= x && mouseY >= y &&
mouseX <= x + 18 && mouseY <= y + 18) {
if (editingButton == button) {
@@ -826,6 +911,11 @@ public class GuiInvButtonEditor extends GuiScreen {
private final ExecutorService searchES = Executors.newSingleThreadExecutor();
private final AtomicInteger searchId = new AtomicInteger(0);
+ @Override
+ public void onGuiClosed() {
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ }
+
public void search() {
final int thisSearchId = searchId.incrementAndGet();
final String searchString = iconTextField.getText();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemCustomize.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemCustomize.java
index 222a0f88..7d541296 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemCustomize.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemCustomize.java
@@ -1,7 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.collect.Lists;
-import io.github.moulberry.notenoughupdates.core.*;
+import io.github.moulberry.notenoughupdates.core.ChromaColour;
+import io.github.moulberry.notenoughupdates.core.GlScissorStack;
+import io.github.moulberry.notenoughupdates.core.GuiElement;
+import io.github.moulberry.notenoughupdates.core.GuiElementBoolean;
+import io.github.moulberry.notenoughupdates.core.GuiElementColour;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingFloat;
import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
@@ -199,6 +223,7 @@ public class GuiItemCustomize extends GuiScreen {
EnumChatFormatting.GREEN + "",
EnumChatFormatting.GREEN + "Type \"&&\" to use colour codes",
EnumChatFormatting.GREEN + "Type \"**\" for \u272A",
+ EnumChatFormatting.GREEN + "Type \"*1-9\" for \u278A-\u2792",
EnumChatFormatting.GREEN + "",
EnumChatFormatting.GREEN + "Available colour codes:",
Utils.chromaString("\u00B6z = Chroma"),
@@ -355,8 +380,6 @@ public class GuiItemCustomize extends GuiScreen {
@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
- Keyboard.enableRepeatEvents(true);
-
if (textFieldRename.getFocus()) {
if (keyCode == Keyboard.KEY_ESCAPE) {
textFieldRename.setFocus(false);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
index 63a4d6d8..e06c271f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
@@ -1,17 +1,39 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.collect.ImmutableList;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.recipes.NeuRecipe;
import io.github.moulberry.notenoughupdates.recipes.RecipeSlot;
+import io.github.moulberry.notenoughupdates.recipes.RecipeType;
import io.github.moulberry.notenoughupdates.util.Utils;
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.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
@@ -21,52 +43,79 @@ import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
public class GuiItemRecipe extends GuiScreen {
public static final ResourceLocation resourcePacksTexture = new ResourceLocation("textures/gui/resource_packs.png");
+ public static final ResourceLocation tabsTexture = new ResourceLocation("notenoughupdates", "textures/gui/tab.png");
public static final int SLOT_SIZE = 16;
public static final int SLOT_SPACING = SLOT_SIZE + 2;
public static final int BUTTON_WIDTH = 7;
public static final int BUTTON_HEIGHT = 11;
- public static final int BUTTON_POSITION_Y = 63;
- public static final int BUTTON_POSITION_LEFT_X = 110;
- public static final int BUTTON_POSITION_RIGHT_X = 147;
- public static final int PAGE_STRING_X = 132;
- public static final int PAGE_STRING_Y = 69;
public static final int TITLE_X = 28;
public static final int TITLE_Y = 6;
public static final int HOTBAR_SLOT_X = 8;
- public static final int HOTBAR_SLOT_Y = 142;
+ public static final int HOTBAR_SLOT_Y = 197;
public static final int PLAYER_INVENTORY_X = 8;
- public static final int PLAYER_INVENTORY_Y = 84;
+ public static final int PLAYER_INVENTORY_Y = 140;
+ public static final int TAB_POS_X = -26;
+ public static final int TAB_POS_Y = 8;
+ public static final int TAB_OFFSET_Y = 30;
+ public static final int TAB_SIZE_X = 26;
+ public static final int TAB_SIZE_Y = 30;
+ public static final int TAB_TEXTURE_SIZE_X = 29;
private int currentIndex = 0;
+ private int currentTab = 0;
- private final String title;
- private final List<NeuRecipe> craftingRecipes;
+ private final Map<RecipeType, List<NeuRecipe>> craftingRecipes = new HashMap<>();
+ private final List<RecipeType> tabs = new ArrayList<>();
private final NEUManager manager;
public int guiLeft = 0;
public int guiTop = 0;
public int xSize = 176;
- public int ySize = 166;
+ public int ySize = 222;
- public GuiItemRecipe(String title, List<NeuRecipe> craftingRecipes, NEUManager manager) {
- this.craftingRecipes = craftingRecipes;
+ public GuiItemRecipe(List<NeuRecipe> unsortedRecipes, NEUManager manager) {
this.manager = manager;
- this.title = title;
+
+ for (NeuRecipe recipe : unsortedRecipes) {
+ craftingRecipes.computeIfAbsent(recipe.getType(), ignored -> new ArrayList<>()).add(recipe);
+ if (!tabs.contains(recipe.getType()))
+ tabs.add(recipe.getType());
+ }
+ changeRecipe(0, 0);
+ }
+
+ @Override
+ public void initGui() {
+ this.guiLeft = (width - this.xSize) / 2;
+ this.guiTop = (height - this.ySize) / 2;
}
public NeuRecipe getCurrentRecipe() {
- currentIndex = MathHelper.clamp_int(currentIndex, 0, craftingRecipes.size());
- return craftingRecipes.get(currentIndex);
+ List<NeuRecipe> currentRecipes = getCurrentRecipeList();
+ currentIndex = MathHelper.clamp_int(currentIndex, 0, currentRecipes.size() - 1);
+ return currentRecipes.get(currentIndex);
+ }
+
+ public List<NeuRecipe> getCurrentRecipeList() {
+ return craftingRecipes.get(getCurrentTab());
+ }
+
+ public RecipeType getCurrentTab() {
+ currentTab = MathHelper.clamp_int(currentTab, 0, tabs.size() - 1);
+ return tabs.get(currentTab);
}
public boolean isWithinRect(int x, int y, int topLeftX, int topLeftY, int width, int height) {
- return topLeftX <= x && x <= topLeftX + width
- && topLeftY <= y && y <= topLeftY + height;
+ return topLeftX <= x && x < topLeftX + width
+ && topLeftY <= y && y < topLeftY + height;
}
private ImmutableList<RecipeSlot> getAllRenderedSlots() {
@@ -80,9 +129,6 @@ public class GuiItemRecipe extends GuiScreen {
drawDefaultBackground();
FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
- this.guiLeft = (width - this.xSize) / 2;
- this.guiTop = (height - this.ySize) / 2;
-
GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
NeuRecipe currentRecipe = getCurrentRecipe();
@@ -90,17 +136,19 @@ public class GuiItemRecipe extends GuiScreen {
Minecraft.getMinecraft().getTextureManager().bindTexture(currentRecipe.getBackground());
this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
+ drawTabs();
+
currentRecipe.drawExtraBackground(this, mouseX, mouseY);
List<RecipeSlot> slots = getAllRenderedSlots();
for (RecipeSlot slot : slots) {
- Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this));
+ Utils.drawItemStack(slot.getItemStack(), slot.getX(this), slot.getY(this), true);
}
- if (craftingRecipes.size() > 1) drawArrows(mouseX, mouseY);
+ drawArrows(currentRecipe, mouseX, mouseY);
Utils.drawStringScaledMaxWidth(
- title,
+ currentRecipe.getTitle(),
fontRendererObj,
guiLeft + TITLE_X,
guiTop + TITLE_Y,
@@ -110,7 +158,7 @@ public class GuiItemRecipe extends GuiScreen {
);
currentRecipe.drawExtraInfo(this, mouseX, mouseY);
-
+ super.drawScreen(mouseX, mouseY, partialTicks);
for (RecipeSlot slot : slots) {
if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
if (slot.getItemStack() == null) continue;
@@ -126,42 +174,104 @@ public class GuiItemRecipe extends GuiScreen {
}
}
currentRecipe.drawHoverInformation(this, mouseX, mouseY);
+ drawTabHoverInformation(mouseX, mouseY);
+ }
+
+ private void drawTabHoverInformation(int mouseX, int mouseY) {
+ if (tabs.size() < 2) return;
+ for (int i = 0; i < tabs.size(); i++) {
+ if (isWithinRect(
+ mouseX - guiLeft,
+ mouseY - guiTop,
+ TAB_POS_X,
+ TAB_POS_Y + TAB_OFFSET_Y * i,
+ TAB_SIZE_X,
+ TAB_SIZE_Y
+ )) {
+ RecipeType type = tabs.get(i);
+ Utils.drawHoveringText(
+ Arrays.asList(
+ "" + EnumChatFormatting.RESET + EnumChatFormatting.GREEN + type.getLabel(),
+ "" + EnumChatFormatting.RESET + EnumChatFormatting.GRAY + craftingRecipes.get(type).size() + " Recipes"
+ ),
+ mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj
+ );
+ return;
+ }
+ }
+ }
+
+ private void drawTabs() {
+ if (tabs.size() < 2) return;
+ for (int i = 0; i < tabs.size(); i++) {
+ RecipeType recipeType = tabs.get(i);
+ int tabPosX = guiLeft + TAB_POS_X, tabPosY = guiTop + TAB_OFFSET_Y * i + TAB_POS_Y;
+ int textureOffset = 0;
+ if (currentTab == i) {
+ textureOffset = 30;
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(tabsTexture);
+ drawTexturedModalRect(
+ tabPosX, tabPosY,
+ 0, textureOffset,
+ TAB_TEXTURE_SIZE_X, TAB_SIZE_Y
+ );
+ Utils.drawItemStack(recipeType.getIcon(), tabPosX + 7, tabPosY + 7);
+ }
}
- private void drawArrows(int mouseX, int mouseY) {
+ public static final int BUTTON_POSITION_RIGHT_OFFSET_X = 37;
+ public static final int PAGE_STRING_OFFSET_X = 22;
+ public static final int PAGE_STRING_OFFSET_Y = 6;
+
+ private void drawArrows(
+ NeuRecipe currentRecipe,
+ int mouseX,
+ int mouseY
+ ) {
+ int recipeCount = getCurrentRecipeList().size();
+ if (recipeCount < 2) return;
+ int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner();
+ int buttonPositionLeftX = topLeft[0];
+ int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X;
+ int pageStringX = buttonPositionLeftX + PAGE_STRING_OFFSET_X;
+ int buttonPositionY = topLeft[1];
+ int pageStringY = buttonPositionY + PAGE_STRING_OFFSET_Y;
+
boolean leftSelected = isWithinRect(
mouseX - guiLeft,
mouseY - guiTop,
- BUTTON_POSITION_LEFT_X,
- BUTTON_POSITION_Y,
+ buttonPositionLeftX,
+ buttonPositionY,
BUTTON_WIDTH,
BUTTON_HEIGHT
);
boolean rightSelected = isWithinRect(
mouseX - guiLeft,
mouseY - guiTop,
- BUTTON_POSITION_RIGHT_X,
- BUTTON_POSITION_Y,
+ buttonPositionRightX,
+ buttonPositionY,
BUTTON_WIDTH,
BUTTON_HEIGHT
);
-
Minecraft.getMinecraft().getTextureManager().bindTexture(resourcePacksTexture);
- Utils.drawTexturedRect(guiLeft + BUTTON_POSITION_LEFT_X, guiTop + BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT,
- 34 / 256f, 48 / 256f,
- leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f
- );
- Utils.drawTexturedRect(guiLeft + BUTTON_POSITION_RIGHT_X, guiTop + BUTTON_POSITION_Y, BUTTON_WIDTH, BUTTON_HEIGHT,
- 10 / 256f, 24 / 256f,
- rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f
- );
+ if (currentIndex != 0)
+ Utils.drawTexturedRect(guiLeft + buttonPositionLeftX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT,
+ 34 / 256f, 48 / 256f,
+ leftSelected ? 37 / 256f : 5 / 256f, leftSelected ? 59 / 256f : 27 / 256f
+ );
+ if (currentIndex != recipeCount - 1)
+ Utils.drawTexturedRect(guiLeft + buttonPositionRightX, guiTop + buttonPositionY, BUTTON_WIDTH, BUTTON_HEIGHT,
+ 10 / 256f, 24 / 256f,
+ rightSelected ? 37 / 256f : 5 / 256f, rightSelected ? 59 / 256f : 27 / 256f
+ );
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
- String selectedPage = (currentIndex + 1) + "/" + craftingRecipes.size();
+ String selectedPage = (currentIndex + 1) + "/" + recipeCount;
Utils.drawStringCenteredScaledMaxWidth(selectedPage, fontRendererObj,
- guiLeft + PAGE_STRING_X, guiTop + PAGE_STRING_Y, false, 24, Color.BLACK.getRGB()
+ guiLeft + pageStringX, guiTop + pageStringY, false, 24, Color.BLACK.getRGB()
);
}
@@ -196,12 +306,12 @@ public class GuiItemRecipe extends GuiScreen {
int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
int keyPressed = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
-
+ if (Keyboard.getEventKeyState()) return;
for (RecipeSlot slot : getAllRenderedSlots()) {
if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
ItemStack itemStack = slot.getItemStack();
- if (keyPressed == manager.keybindViewRecipe.getKeyCode()) { // TODO: rework this so it doesnt skip recipe chains
- manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), "");
+ if (keyPressed == manager.keybindViewRecipe.getKeyCode()) {
+ manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack));
} else if (keyPressed == manager.keybindViewUsages.getKeyCode()) {
manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
}
@@ -209,19 +319,37 @@ public class GuiItemRecipe extends GuiScreen {
}
}
+ public void changeRecipe(int tabIndex, int recipeIndex) {
+ buttonList.removeAll(getCurrentRecipe().getExtraButtons(this));
+ currentTab = tabIndex;
+ currentIndex = recipeIndex;
+ buttonList.addAll(getCurrentRecipe().getExtraButtons(this));
+ }
+
+ @Override
+ protected void actionPerformed(GuiButton p_actionPerformed_1_) throws IOException {
+ getCurrentRecipe().actionPerformed(p_actionPerformed_1_);
+ }
+
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
+ NeuRecipe currentRecipe = getCurrentRecipe();
+ int[] topLeft = currentRecipe.getPageFlipPositionLeftTopCorner();
+ int buttonPositionLeftX = topLeft[0];
+ int buttonPositionRightX = buttonPositionLeftX + BUTTON_POSITION_RIGHT_OFFSET_X;
+ int buttonPositionY = topLeft[1];
if (isWithinRect(
mouseX - guiLeft,
mouseY - guiTop,
- BUTTON_POSITION_LEFT_X,
- BUTTON_POSITION_Y,
+ buttonPositionLeftX,
+ buttonPositionY,
BUTTON_WIDTH,
BUTTON_HEIGHT
- )) {
- currentIndex = currentIndex == 0 ? 0 : currentIndex - 1;
+ ) &&
+ currentIndex > 0) {
+ changeRecipe(currentTab, currentIndex - 1);
Utils.playPressSound();
return;
}
@@ -229,25 +357,45 @@ public class GuiItemRecipe extends GuiScreen {
if (isWithinRect(
mouseX - guiLeft,
mouseY - guiTop,
- BUTTON_POSITION_RIGHT_X,
- BUTTON_POSITION_Y,
+ buttonPositionRightX,
+ buttonPositionY,
BUTTON_WIDTH,
BUTTON_HEIGHT
- )) {
- currentIndex = currentIndex == craftingRecipes.size() - 1 ? currentIndex : currentIndex + 1;
+ ) &&
+ currentIndex < getCurrentRecipeList().size()) {
+ changeRecipe(currentTab, currentIndex + 1);
Utils.playPressSound();
return;
}
+ for (int i = 0; i < tabs.size(); i++) {
+ if (isWithinRect(
+ mouseX - guiLeft,
+ mouseY - guiTop,
+ TAB_POS_X,
+ TAB_POS_Y + TAB_OFFSET_Y * i,
+ TAB_SIZE_X,
+ TAB_SIZE_Y
+ )) {
+ changeRecipe(i, currentIndex);
+ Utils.playPressSound();
+ return;
+ }
+ }
+
for (RecipeSlot slot : getAllRenderedSlots()) {
if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
ItemStack itemStack = slot.getItemStack();
if (mouseButton == 0) {
- manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack), "");
+ manager.displayGuiItemRecipe(manager.getInternalNameForItem(itemStack));
+ return;
} else if (mouseButton == 1) {
manager.displayGuiItemUsages(manager.getInternalNameForItem(itemStack));
+ return;
}
}
}
+
+ currentRecipe.mouseClicked(this, mouseX, mouseY, mouseButton);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java
new file mode 100644
index 00000000..dcb1344c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiNavigation.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class GuiNavigation extends GuiScreen {
+
+ public static ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/navigation.png"
+ );
+
+ public static final int PIN_POSITION_U = 182;
+ public static final int PIN_POSITION_V = 3;
+ public static final int TICK_POSITION_U = 182;
+ public static final int TICK_POSITION_V = 34;
+ public static final int ICON_SIZE = 26;
+
+ public static final int SEARCH_BAR_X = 14;
+ public static final int SEARCH_BAR_Y = 11;
+ public static final int SEARCH_BAR_WIDTH = 151;
+ public static final int SEARCH_BAR_HEIGHT = 24;
+
+ public static final int LIST_START_X = 14;
+ public static final int LIST_START_Y = 43;
+ public static final int LIST_OFFSET_Y = 28;
+ public static final int TEXT_OFFSET_X = 28;
+ public static final int LIST_COUNT = 6;
+
+ List<String> searchResults = new ArrayList<>();
+
+ public int xSize = 176;
+ public int ySize = 222;
+ public int guiLeft, guiTop;
+
+ public GuiElementTextField textField = new GuiElementTextField("", SEARCH_BAR_WIDTH, SEARCH_BAR_HEIGHT, 0);
+
+ @Override
+ public void initGui() {
+ super.initGui();
+ NotEnoughUpdates.INSTANCE.config.hidden.hasOpenedWaypointMenu = true;
+ guiLeft = (width - xSize) / 2;
+ guiTop = (height - ySize) / 2;
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ drawDefaultBackground();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, xSize, ySize);
+ textField.render(guiLeft + SEARCH_BAR_X, guiTop + SEARCH_BAR_Y);
+
+ refreshResults();
+ for (int i = 0; i < LIST_COUNT; i++) {
+ if (i < searchResults.size()) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ String name = searchResults.get(i);
+ JsonObject json = NotEnoughUpdates.INSTANCE.navigation.getWaypoints().get(name);
+ boolean selected = name.equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname());
+ int baseX = guiLeft + LIST_START_X;
+ int baseY = guiTop + LIST_START_Y + LIST_OFFSET_Y * i;
+
+ GlStateManager.color(1F, 1F, 1F);
+ drawTexturedModalRect(
+ baseX,
+ baseY,
+ selected ? TICK_POSITION_U : PIN_POSITION_U, selected ? TICK_POSITION_V : PIN_POSITION_V,
+ ICON_SIZE, ICON_SIZE
+ );
+ Utils.drawStringF(
+ json.get("displayname").getAsString(),
+ Minecraft.getMinecraft().fontRendererObj,
+ baseX + TEXT_OFFSET_X,
+ baseY + LIST_OFFSET_Y / 2F - Minecraft.getMinecraft().fontRendererObj.FONT_HEIGHT / 2F,
+ false,
+ 0x000000
+ );
+ }
+ }
+ }
+
+ private void refreshResults() {
+ String text = textField.getText().toLowerCase();
+ List<String> results = NotEnoughUpdates.INSTANCE.navigation
+ .getWaypoints()
+ .values()
+ .stream()
+ .filter(it ->
+ it.get("internalname").getAsString().toLowerCase().contains(text)
+ || it.get("displayname").getAsString().toLowerCase().contains(text))
+ .map(it -> it.get("internalname").getAsString())
+ .sorted(Comparator.comparing(String::length)
+ .thenComparing(String.CASE_INSENSITIVE_ORDER))
+ .collect(Collectors.toList());
+
+ String internalname = NotEnoughUpdates.INSTANCE.navigation.getInternalname();
+ if (internalname != null) {
+ results.remove(internalname);
+ results.add(0, internalname);
+ }
+ searchResults = results;
+ }
+
+ @Override
+ protected void keyTyped(char p_keyTyped_1_, int p_keyTyped_2_) throws IOException {
+ super.keyTyped(p_keyTyped_1_, p_keyTyped_2_);
+ textField.keyTyped(p_keyTyped_1_, p_keyTyped_2_);
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+ if (Utils.isWithinRect(
+ mouseX,
+ mouseY,
+ guiLeft + SEARCH_BAR_X,
+ guiTop + SEARCH_BAR_Y,
+ SEARCH_BAR_WIDTH,
+ SEARCH_BAR_HEIGHT
+ )) {
+ textField.mouseClicked(mouseX, mouseY, mouseButton);
+ } else {
+ textField.setFocus(false);
+ }
+ for (int i = 0; i < LIST_COUNT; i++) {
+ if (i < searchResults.size()) {
+ int baseX = guiLeft + LIST_START_X;
+ int baseY = guiTop + LIST_START_Y + LIST_OFFSET_Y * i;
+ if (Utils.isWithinRect(mouseX, mouseY, baseX, baseY, ICON_SIZE, ICON_SIZE)) {
+ String thing = searchResults.get(i);
+ boolean selected = thing.equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname());
+ if (selected) {
+ NotEnoughUpdates.INSTANCE.navigation.untrackWaypoint();
+ } else {
+ NotEnoughUpdates.INSTANCE.navigation.trackWaypoint(thing);
+ }
+ Utils.playPressSound();
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiPriceGraph.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiPriceGraph.java
index 3955b35f..71a23ffb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiPriceGraph.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiPriceGraph.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.reflect.TypeToken;
@@ -17,14 +36,26 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@@ -36,11 +67,11 @@ public class GuiPriceGraph extends GuiScreen {
private final ResourceLocation TEXTURE;
private static final int X_SIZE = 364;
private static final int Y_SIZE = 215;
- private Data dataPoints;
- private float highestValue;
+ private ItemData itemData;
+ private double highestValue;
private long firstTime;
private long lastTime;
- private Float lowestValue = null;
+ private Double lowestValue = null;
private String itemName;
private final String itemId;
private int guiLeft;
@@ -117,27 +148,27 @@ public class GuiPriceGraph extends GuiScreen {
Utils.drawStringCentered("Loading...", Minecraft.getMinecraft().fontRendererObj,
guiLeft + 166, guiTop + 116, false, 0xffffff00
);
- else if (dataPoints == null || dataPoints.get() == null || dataPoints.get().size() <= 1)
+ else if (
+ itemData == null || itemData.get() == null || itemData.get().size() <= 1 || lowestValue == null)
Utils.drawStringCentered("No data found.", Minecraft.getMinecraft().fontRendererObj,
guiLeft + 166, guiTop + 116, false, 0xffff0000
);
else {
-
int graphColor = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.ahGraph.graphColor);
int graphColor2 = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.config.ahGraph.graphColor2);
Integer lowestDist = null;
Long lowestDistTime = null;
HashMap<Integer, Integer> secondLineData = new HashMap<>();
- for (int i = (dataPoints.isBz() ? 1 : 0); i >= 0; i--) {
+ for (int i = (itemData.isBz() ? 1 : 0); i >= 0; i--) {
Utils.drawGradientRect(0, guiLeft + 17, guiTop + 35, guiLeft + 315, guiTop + 198,
changeAlpha(i == 0 ? graphColor : graphColor2, 120), changeAlpha(i == 0 ? graphColor : graphColor2, 10)
);
Integer prevX = null;
Integer prevY = null;
- for (Long time : dataPoints.get().keySet()) {
- float price = dataPoints.isBz()
- ? i == 0 ? dataPoints.bz.get(time).b : dataPoints.bz.get(time).s
- : dataPoints.ah.get(time);
+ for (Long time : itemData.get().keySet()) {
+ double price = itemData.isBz()
+ ? i == 0 ? itemData.bz.get(time).b : itemData.bz.get(time).s
+ : itemData.ah.get(time);
int xPos = (int) map(time, firstTime, lastTime, guiLeft + 17, guiLeft + 315);
int yPos = (int) map(price, highestValue + 10d, lowestValue - 10d, guiTop + 35, guiTop + 198);
if (prevX != null) {
@@ -160,7 +191,7 @@ public class GuiPriceGraph extends GuiScreen {
);
if (i == 0) {
Utils.drawLine(prevX, prevY + 0.5f, xPos, yPos + 0.5f, 2, graphColor);
- if (dataPoints.isBz())
+ if (itemData.isBz())
Utils.drawLine(
prevX,
secondLineData.get(prevX) + 0.5f,
@@ -219,8 +250,8 @@ public class GuiPriceGraph extends GuiScreen {
Utils.drawDottedLine(customStart, guiTop + 197, customEnd, guiTop + 197, 2, 10, 0xFFc6c6c6);
}
if (lowestDist != null && !customSelecting) {
- float price = dataPoints.isBz() ? dataPoints.bz.get(lowestDistTime).b : dataPoints.ah.get(lowestDistTime);
- Float price2 = dataPoints.isBz() ? dataPoints.bz.get(lowestDistTime).s : null;
+ double price = itemData.isBz() ? itemData.bz.get(lowestDistTime).b : itemData.ah.get(lowestDistTime);
+ Float price2 = itemData.isBz() ? itemData.bz.get(lowestDistTime).s : null;
int xPos = (int) map(lowestDistTime, firstTime, lastTime, guiLeft + 17, guiLeft + 315);
int yPos = (int) map(price, highestValue + 10d, lowestValue - 10d, guiTop + 35, guiTop + 198);
int yPos2 = price2 != null
@@ -244,7 +275,7 @@ public class GuiPriceGraph extends GuiScreen {
NumberFormat nf = NumberFormat.getInstance();
ArrayList<String> text = new ArrayList<>();
text.add(displayFormat.format(date));
- if (dataPoints.isBz()) {
+ if (itemData.isBz()) {
text.add(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "Bazaar Insta-Buy: " +
EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + nf.format(price));
text.add(EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "Bazaar Insta-Sell: " +
@@ -321,7 +352,7 @@ public class GuiPriceGraph extends GuiScreen {
}
private void loadData() {
- dataPoints = null;
+ itemData = null;
loaded = false;
new Thread(() -> {
File dir = new File("config/notenoughupdates/prices");
@@ -330,46 +361,46 @@ public class GuiPriceGraph extends GuiScreen {
return;
}
File[] files = dir.listFiles();
- Data data = new Data();
+ ItemData itemData = new ItemData();
if (files == null) return;
for (File file : files) {
if (!file.getName().endsWith(".gz")) continue;
- HashMap<String, Data> data2 = load(file);
+ HashMap<String, ItemData> data2 = load(file);
if (data2 == null || !data2.containsKey(itemId)) continue;
if (data2.get(itemId).isBz()) {
- if (data.bz == null) data.bz = data2.get(itemId).bz;
- else data.bz.putAll(data2.get(itemId).bz);
- } else if (data.ah == null) data.ah = data2.get(itemId).ah;
- else data.ah.putAll(data2.get(itemId).ah);
+ if (itemData.bz == null) itemData.bz = data2.get(itemId).bz;
+ else itemData.bz.putAll(data2.get(itemId).bz);
+ } else if (itemData.ah == null) itemData.ah = data2.get(itemId).ah;
+ else itemData.ah.putAll(data2.get(itemId).ah);
}
- if (data.get() != null && !data.get().isEmpty()) {
+ if (itemData.get() != null && !itemData.get().isEmpty()) {
if (mode < 3)
- data = new Data(
- new TreeMap<>(data.get().entrySet().stream()
- .filter(e -> e.getKey() > System.currentTimeMillis() / 1000 -
- (mode == 0 ? 3600 : mode == 1 ? 86400 : 604800))
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))),
- data.isBz()
+ itemData = new ItemData(
+ new TreeMap<>(itemData.get().entrySet().stream()
+ .filter(e -> e.getKey() > System.currentTimeMillis() / 1000 -
+ (mode == 0 ? 3600 : mode == 1 ? 86400 : 604800))
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))),
+ itemData.isBz()
);
else if (mode == 4)
- data = new Data(
- new TreeMap<>(data.get().entrySet().stream()
- .filter(e -> e.getKey() >= customStart && e.getKey() <= customEnd)
- .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))),
- data.isBz()
+ itemData = new ItemData(
+ new TreeMap<>(itemData.get().entrySet().stream()
+ .filter(e -> e.getKey() >= customStart && e.getKey() <= customEnd)
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))),
+ itemData.isBz()
);
- if (data.get() == null || data.get().isEmpty()) {
+ if (itemData.get() == null || itemData.get().isEmpty()) {
loaded = true;
return;
}
- dataPoints = trimData(data);
- firstTime = dataPoints.get().firstKey();
- lastTime = dataPoints.get().lastKey();
+ this.itemData = trimData(itemData);
+ firstTime = this.itemData.get().firstKey();
+ lastTime = this.itemData.get().lastKey();
highestValue = 0;
lowestValue = null;
- for (long key : dataPoints.get().keySet()) {
- float value1 = dataPoints.isBz() ? dataPoints.bz.get(key).b : dataPoints.ah.get(key);
- Float value2 = dataPoints.isBz() ? dataPoints.bz.get(key).s : null;
+ for (long key : this.itemData.get().keySet()) {
+ double value1 = this.itemData.isBz() ? this.itemData.bz.get(key).b : this.itemData.ah.get(key);
+ Float value2 = this.itemData.isBz() ? this.itemData.bz.get(key).s : null;
if (value1 > highestValue) {
highestValue = value1;
}
@@ -380,7 +411,7 @@ public class GuiPriceGraph extends GuiScreen {
lowestValue = value1;
}
if (value2 != null && value2 < lowestValue) {
- lowestValue = value2;
+ lowestValue = Double.valueOf(value2);
}
}
}
@@ -399,37 +430,19 @@ public class GuiPriceGraph extends GuiScreen {
if (!file.getName().endsWith(".gz")) continue;
if (file.lastModified() <
System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.config.ahGraph.dataRetention * 86400000L)
+ //noinspection ResultOfMethodCallIgnored
file.delete();
}
Date date = new Date();
Long epochSecond = date.toInstant().getEpochSecond();
File file = new File(dir, "prices_" + format.format(date) + ".gz");
- HashMap<String, Data> prices = new HashMap<>();
- if (file.exists())
- prices = load(file);
- if (prices == null) return;
+ HashMap<String, ItemData> prices = new HashMap<>();
+ if (file.exists()) {
+ HashMap<String, ItemData> tempPrices = load(file);
+ if (tempPrices != null) prices = tempPrices;
+ }
for (Map.Entry<String, JsonElement> item : items.entrySet()) {
- if (prices.containsKey(item.getKey())) {
- if (bazaar && item.getValue().getAsJsonObject().has("curr_buy") && item.getValue().getAsJsonObject().has(
- "curr_sell"))
- prices.get(item.getKey()).bz.put(epochSecond, new BzData(
- item.getValue().getAsJsonObject().get("curr_buy").getAsFloat(),
- item.getValue().getAsJsonObject().get("curr_sell").getAsFloat()
- ));
- else if (!bazaar)
- prices.get(item.getKey()).ah.put(epochSecond, item.getValue().getAsInt());
- } else {
- TreeMap<Long, Object> mapData = new TreeMap<>();
- if (bazaar && item.getValue().getAsJsonObject().has("curr_buy") && item.getValue().getAsJsonObject().has(
- "curr_sell"))
- mapData.put(epochSecond, new BzData(
- item.getValue().getAsJsonObject().get("curr_buy").getAsFloat(),
- item.getValue().getAsJsonObject().get("curr_sell").getAsFloat()
- ));
- else if (!bazaar)
- mapData.put(epochSecond, item.getValue().getAsLong());
- prices.put(item.getKey(), new Data(mapData, bazaar));
- }
+ addOrUpdateItemPriceInfo(item, prices, epochSecond, bazaar);
}
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
@@ -446,16 +459,71 @@ public class GuiPriceGraph extends GuiScreen {
}
}
- private Data trimData(Data data) {
- long first = data.get().firstKey();
- long last = data.get().lastKey();
- Data trimmed = new Data();
- if (data.isBz())
+ private static void addOrUpdateItemPriceInfo(
+ Map.Entry<String, JsonElement> item,
+ HashMap<String, ItemData> prices,
+ long timestamp,
+ boolean bazaar
+ ) {
+ String itemName = item.getKey();
+ ItemData existingItemData = null;
+ if (prices.containsKey(itemName)) {
+ existingItemData = prices.get(itemName);
+ }
+
+ // Handle transitions from ah to bz (the other direction typically doesn't happen)
+ if (existingItemData != null) {
+ if (existingItemData.isBz() && !bazaar) {
+ return;
+ }
+
+ if (!existingItemData.isBz() && bazaar) {
+ prices.remove(itemName);
+ existingItemData = null;
+ }
+ }
+
+ if (bazaar) {
+ if (!item.getValue().getAsJsonObject().has("curr_buy") ||
+ !item.getValue().getAsJsonObject().has("curr_sell")
+ ) {
+ return;
+ }
+
+ BzData bzData = new BzData(
+ item.getValue().getAsJsonObject().get("curr_buy").getAsFloat(),
+ item.getValue().getAsJsonObject().get("curr_sell").getAsFloat()
+ );
+
+ if (existingItemData != null) {
+ existingItemData.bz.put(timestamp, bzData);
+ } else {
+ TreeMap<Long, Object> mapData = new TreeMap<>();
+ mapData.put(timestamp, bzData);
+ prices.put(item.getKey(), new ItemData(mapData, true));
+ }
+ } else {
+ if (existingItemData != null) {
+ prices.get(item.getKey()).ah.put(timestamp, item.getValue().getAsBigDecimal().longValue());
+ } else {
+ TreeMap<Long, Object> mapData = new TreeMap<>();
+ mapData.put(timestamp, item.getValue().getAsLong());
+ prices.put(item.getKey(), new ItemData(mapData, false));
+ }
+ }
+ }
+
+ private ItemData trimData(ItemData itemData) {
+ long first = itemData.get().firstKey();
+ long last = itemData.get().lastKey();
+ ItemData trimmed = new ItemData();
+ if (itemData.isBz())
trimmed.bz = new TreeMap<>();
else
trimmed.ah = new TreeMap<>();
int zones = NotEnoughUpdates.INSTANCE.config.ahGraph.graphZones;
- Long[] dataArray = !data.isBz() ? data.ah.keySet().toArray(new Long[0]) : data.bz.keySet().toArray(new Long[0]);
+ Long[] dataArray =
+ !itemData.isBz() ? itemData.ah.keySet().toArray(new Long[0]) : itemData.bz.keySet().toArray(new Long[0]);
int prev = 0;
for (int i = 0; i < zones; i++) {
long lowest = (long) map(i, 0, zones, first, last);
@@ -466,24 +534,24 @@ public class GuiPriceGraph extends GuiScreen {
for (int l = prev; l < dataArray.length; l++) {
if (dataArray[l] >= lowest && dataArray[l] <= highest) {
amount++;
- sumBuy += data.isBz() ? data.bz.get(dataArray[l]).b : data.ah.get(dataArray[l]);
- if (data.isBz()) sumSell += data.bz.get(dataArray[l]).s;
+ sumBuy += itemData.isBz() ? itemData.bz.get(dataArray[l]).b : itemData.ah.get(dataArray[l]);
+ if (itemData.isBz()) sumSell += itemData.bz.get(dataArray[l]).s;
prev = l + 1;
} else if (dataArray[l] > highest)
break;
}
if (amount > 0) {
- if (data.isBz())
+ if (itemData.isBz())
trimmed.bz.put(lowest, new BzData((float) (sumBuy / amount), (float) (sumSell / amount)));
else
- trimmed.ah.put(lowest, (int) (sumBuy / amount));
+ trimmed.ah.put(lowest, (long) (sumBuy / amount));
}
}
return trimmed;
}
- private static HashMap<String, Data> load(File file) {
- Type type = new TypeToken<HashMap<String, Data>>() {
+ private static HashMap<String, ItemData> load(File file) {
+ Type type = new TypeToken<HashMap<String, ItemData>>() {
}.getType();
if (file.exists()) {
try (
@@ -493,7 +561,10 @@ public class GuiPriceGraph extends GuiScreen {
))
) {
return GSON.fromJson(reader, type);
- } catch (Exception ignored) {
+ } catch (Exception e) {
+ System.out.println("Deleting " + file.getName() + " because it is probably corrupted.");
+ //noinspection ResultOfMethodCallIgnored
+ file.delete();
}
}
return null;
@@ -521,18 +592,18 @@ public class GuiPriceGraph extends GuiScreen {
}
}
-class Data {
- public TreeMap<Long, Integer> ah = null;
+class ItemData {
+ public TreeMap<Long, Long> ah = null;
public TreeMap<Long, BzData> bz = null;
- public Data() {
+ public ItemData() {
}
- public Data(TreeMap<Long, ?> map, boolean bz) {
+ public ItemData(TreeMap<Long, ?> map, boolean bz) {
if (bz)
this.bz = (TreeMap<Long, BzData>) map;
else
- this.ah = (TreeMap<Long, Integer>) map;
+ this.ah = (TreeMap<Long, Long>) map;
}
public TreeMap<Long, ?> get() {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java
index 3932c9d5..0abf3f11 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/InventoryStorageSelector.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java
index 107d4db2..62aba35b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/KatSitterOverlay.java
@@ -1,9 +1,29 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
import io.github.moulberry.notenoughupdates.util.Utils;
-import io.github.moulberry.notenoughupdates.util.XPInformation;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.inventory.GuiChest;
@@ -49,8 +69,8 @@ public class KatSitterOverlay {
boolean nextRarityPresent = katSlot.getStack() != null && katSlot.getStack().getItem() != Item.getItemFromBlock(
Blocks.barrier) && upgradedRarity != null;
renderPetInformation(
- (int) XPInformation.getInstance().getPetLevel(petId, xp, rarity),
- nextRarityPresent ? (int) XPInformation.getInstance().getPetLevel(petId, xp, upgradedRarity) : null,
+ (int) GuiProfileViewer.getPetLevel(petId, rarity, (float) xp).level,
+ nextRarityPresent ? (int) GuiProfileViewer.getPetLevel(petId, upgradedRarity, (float) xp).level : null,
gui
);
}
@@ -61,12 +81,23 @@ public class KatSitterOverlay {
int currentWidth = font.getStringWidth(currentText);
String upgradedText = "Upgraded pet level: " + upgradedLevel;
int upgradedWidth = font.getStringWidth(upgradedText);
- int left = gui.guiLeft - 30 - (upgradedLevel == null ? Math.max(upgradedWidth, currentWidth) : currentWidth);
+ int left = ((AccessorGuiContainer) gui).getGuiLeft() - 30 - (upgradedLevel == null ? Math.max(
+ upgradedWidth,
+ currentWidth
+ ) : currentWidth);
GlStateManager.disableLighting();
GlStateManager.color(1F, 1F, 1F, 1F);
- Utils.drawStringScaled(currentText, font, left, gui.guiTop + 25, false, 0xFFD700, 1F);
+ Utils.drawStringScaled(currentText, font, left, ((AccessorGuiContainer) gui).getGuiTop() + 25, false, 0xFFD700, 1F);
if (upgradedLevel != null)
- Utils.drawStringScaled(upgradedText, font, left, gui.guiTop + 45, false, 0xFFD700, 1F);
+ Utils.drawStringScaled(
+ upgradedText,
+ font,
+ left,
+ ((AccessorGuiContainer) gui).getGuiTop() + 45,
+ false,
+ 0xFFD700,
+ 1F
+ );
}
public String nextRarity(String currentRarity) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NEUOverlayPlacements.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NEUOverlayPlacements.java
index f95302ef..ac96f527 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NEUOverlayPlacements.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NEUOverlayPlacements.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NeuSearchCalculator.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NeuSearchCalculator.java
new file mode 100644
index 00000000..f7306f2a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/NeuSearchCalculator.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Calculator;
+
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+
+public class NeuSearchCalculator {
+
+ static String lastInput = "";
+ static String lastResult = null;
+
+ public static String format(String text) {
+ String calculate = calculateInSearchBar(text);
+ return text + (calculate != null ? " §e= §a" + calculate : "");
+ }
+
+ private static String calculateInSearchBar(String input) {
+ int calculationMode = NotEnoughUpdates.INSTANCE.config.misc.calculationMode;
+ if (input.isEmpty() || calculationMode == 0 || (calculationMode == 1 && !input.startsWith("!"))) return null;
+ input = calculationMode == 1 ? input.substring(1) : input;
+
+ if (!lastInput.equals(input)) {
+ lastInput = input;
+ try {
+ BigDecimal calculate = Calculator.calculate(input);
+ lastResult = new DecimalFormat("#,##0.##").format(calculate);
+ } catch (Calculator.CalculatorException ignored) {
+ lastResult = null;
+ }
+ }
+
+ return lastResult;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java
new file mode 100644
index 00000000..ac676a98
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/SignCalculator.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.SignSubmitEvent;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign;
+import io.github.moulberry.notenoughupdates.util.Calculator;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.tileentity.TileEntitySign;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+import java.text.DecimalFormat;
+import java.math.BigDecimal;
+import java.util.Objects;
+
+public class SignCalculator {
+
+ String lastSource = null;
+ BigDecimal lastResult = null;
+ Calculator.CalculatorException lastException = null;
+
+ private boolean isEnabled() {
+ return NotEnoughUpdates.INSTANCE.config.misc.calculationMode != 0;
+ }
+
+ @SubscribeEvent
+ public void onSignDrawn(GuiScreenEvent.DrawScreenEvent.Post event) {
+ if (!(event.gui instanceof GuiEditSign))
+ return;
+ if (!isEnabled()) return;
+ GuiEditSign guiEditSign = (GuiEditSign) event.gui;
+ TileEntitySign tileSign = ((AccessorGuiEditSign) guiEditSign).getTileSign();
+ if (!tileSign.signText[1].getUnformattedText().equals("^^^^^^^^^^^^^^^") &&
+ !tileSign.signText[1].getUnformattedText().equals("^^^^^^")) return;
+ String source = tileSign.signText[0].getUnformattedText();
+ refresh(source);
+
+ int calculationMode = NotEnoughUpdates.INSTANCE.config.misc.calculationMode;
+ if ((calculationMode == 1 && !source.startsWith("!"))) return;
+
+ Utils.drawStringCentered(
+ getRenderedString(),
+ Minecraft.getMinecraft().fontRendererObj,
+ guiEditSign.width / 2F,
+ 58,
+ false,
+ 0x808080FF
+ );
+ }
+
+ @SubscribeEvent
+ public void onSignSubmitted(SignSubmitEvent event) {
+ if (!isEnabled()) return;
+ if (Objects.equals(event.lines[1], "^^^^^^^^^^^^^^^") || Objects.equals(event.lines[1], "^^^^^^")) {
+ refresh(event.lines[0]);
+ if (lastResult != null) {
+ event.lines[0] = lastResult.toPlainString();
+ }
+ }
+ }
+
+ public String getRenderedString() {
+ if (lastResult != null) {
+ DecimalFormat formatter = new DecimalFormat("#,##0.##");
+ String lr = formatter.format(lastResult);
+ if (Minecraft.getMinecraft().fontRendererObj.getStringWidth(lr) > 90) {
+ return EnumChatFormatting.WHITE + lastSource + " " + EnumChatFormatting.YELLOW + "= " + EnumChatFormatting.RED +
+ "Result too long";
+ }
+ return EnumChatFormatting.WHITE + lastSource + " " + EnumChatFormatting.YELLOW + "= " + EnumChatFormatting.GREEN +
+ lr;
+ } else if (lastException != null) {
+ return EnumChatFormatting.RED + lastException.getMessage();
+ }
+ return EnumChatFormatting.RED + "No calculation has been done.";
+ }
+
+ private void refresh(String source) {
+ if (Objects.equals(source, lastSource)) return;
+ lastSource = source;
+ int calculationMode = NotEnoughUpdates.INSTANCE.config.misc.calculationMode;
+ if (source.isEmpty() || calculationMode == 0 || (calculationMode == 1 && !source.startsWith("!"))) {
+ lastResult = null;
+ lastException = null;
+ return;
+ }
+ try {
+ lastResult = Calculator.calculate(calculationMode == 1 ? source.substring(1) : source);
+ lastException = null;
+ } catch (Calculator.CalculatorException ex) {
+ lastException = ex;
+ lastResult = null;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
index bce5bfbd..8878c284 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/StorageOverlay.java
@@ -1,14 +1,38 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.common.collect.Lists;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.core.*;
+import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
+import io.github.moulberry.notenoughupdates.core.ChromaColour;
+import io.github.moulberry.notenoughupdates.core.GlScissorStack;
+import io.github.moulberry.notenoughupdates.core.GuiElement;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
@@ -21,13 +45,17 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.event.HoverEvent;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.Slot;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
+import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.ClientCommandHandler;
import org.lwjgl.input.Keyboard;
@@ -38,19 +66,17 @@ import org.lwjgl.util.vector.Vector2f;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
-import java.util.*;
+import java.util.Map;
+import java.util.Set;
public class StorageOverlay extends GuiElement {
+ public static final ResourceLocation[] STORAGE_PREVIEW_TEXTURES = new ResourceLocation[4];
private static final int CHEST_TOP_OFFSET = 17;
private static final int CHEST_SLOT_SIZE = 18;
private static final int CHEST_BOTTOM_OFFSET = 215;
-
- private Framebuffer framebuffer = null;
-
- private final Set<Vector2f> enchantGlintRenderLocations = new HashSet<>();
-
- public static final ResourceLocation[] STORAGE_PREVIEW_TEXTURES = new ResourceLocation[4];
private static final ResourceLocation[] STORAGE_TEXTURES = new ResourceLocation[4];
private static final ResourceLocation STORAGE_ICONS_TEXTURE = new ResourceLocation(
"notenoughupdates:storage_gui/storage_icons.png");
@@ -58,6 +84,9 @@ public class StorageOverlay extends GuiElement {
"notenoughupdates:storage_gui/storage_gui_pane_ctm.png");
private static final ResourceLocation[] LOAD_CIRCLE_SEQ = new ResourceLocation[11];
private static final ResourceLocation[] NOT_RICKROLL_SEQ = new ResourceLocation[19];
+ private static final StorageOverlay INSTANCE = new StorageOverlay();
+ private static final String CHROMA_STR = "230:255:255:0:0";
+ private static final ResourceLocation RES_ITEM_GLINT = new ResourceLocation("textures/misc/enchanted_item_glint.png");
static {
for (int i = 0; i < STORAGE_TEXTURES.length; i++) {
@@ -81,52 +110,193 @@ public class StorageOverlay extends GuiElement {
LOAD_CIRCLE_SEQ[10] = new ResourceLocation("notenoughupdates:loading_circle_seq/1.png");
}
- private static final StorageOverlay INSTANCE = new StorageOverlay();
-
- public static StorageOverlay getInstance() {
- return INSTANCE;
- }
-
+ private final Set<Vector2f> enchantGlintRenderLocations = new HashSet<>();
private final GuiElementTextField searchBar = new GuiElementTextField("", 88, 10,
GuiElementTextField.SCALE_TEXT | GuiElementTextField.DISABLE_BG
);
private final GuiElementTextField renameStorageField = new GuiElementTextField("", 100, 13,
GuiElementTextField.COLOUR
);
-
+ private final int[][] isPaneCaches = new int[40][];
+ private final int[][] ctmIndexCaches = new int[40][];
+ private final LerpingInteger scroll = new LerpingInteger(0, 200);
+ private Framebuffer framebuffer = null;
private int editingNameId = -1;
-
private int guiLeft;
private int guiTop;
-
private boolean fastRender = false;
-
private int loadCircleIndex = 0;
private int rollIndex = 0;
private int loadCircleRotation = 0;
-
private long millisAccumIndex = 0;
private long millisAccumRoll = 0;
private long millisAccumRotation = 0;
-
private long lastMillis = 0;
-
private int scrollVelocity = 0;
private long lastScroll = 0;
-
- private final int[][] isPaneCaches = new int[40][];
- private final int[][] ctmIndexCaches = new int[40][];
-
private int desiredHeightSwitch = -1;
private int desiredHeightMX = -1;
private int desiredHeightMY = -1;
-
private boolean dirty = false;
private boolean allowTypingInSearchBar = true;
-
private int scrollGrabOffset = -1;
- private final LerpingInteger scroll = new LerpingInteger(0, 200);
+ public static StorageOverlay getInstance() {
+ return INSTANCE;
+ }
+
+ private static boolean shouldConnect(int paneIndex1, int paneIndex2) {
+ if (paneIndex1 == 16 || paneIndex2 == 16) return false;
+ if (paneIndex1 < 1 || paneIndex2 < 1) return false;
+ return paneIndex1 == paneIndex2;
+
+ }
+
+ public static int getCTMIndex(StorageManager.StoragePage page, int index, int[] isPaneCache, int[] ctmIndexCache) {
+ if (page.items[index] == null) {
+ ctmIndexCache[index] = -1;
+ return -1;
+ }
+
+ int paneType = getPaneType(page.items[index], index, isPaneCache);
+
+ int upIndex = index - 9;
+ int leftIndex = index % 9 > 0 ? index - 1 : -1;
+ int rightIndex = index % 9 < 8 ? index + 1 : -1;
+ int downIndex = index + 9;
+ int upleftIndex = index % 9 > 0 ? index - 10 : -1;
+ int uprightIndex = index % 9 < 8 ? index - 8 : -1;
+ int downleftIndex = index % 9 > 0 ? index + 8 : -1;
+ int downrightIndex = index % 9 < 8 ? index + 10 : -1;
+
+ boolean up = upIndex >= 0 && upIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[upIndex],
+ upIndex,
+ isPaneCache
+ ), paneType);
+ boolean left = leftIndex >= 0 && leftIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[leftIndex],
+ leftIndex,
+ isPaneCache
+ ), paneType);
+ boolean down = downIndex >= 0 && downIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[downIndex],
+ downIndex,
+ isPaneCache
+ ), paneType);
+ boolean right = rightIndex >= 0 && rightIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[rightIndex],
+ rightIndex,
+ isPaneCache
+ ), paneType);
+ boolean upleft = upleftIndex >= 0 && upleftIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[upleftIndex],
+ upleftIndex,
+ isPaneCache
+ ), paneType);
+ boolean upright = uprightIndex >= 0 && uprightIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[uprightIndex],
+ uprightIndex,
+ isPaneCache
+ ), paneType);
+ boolean downleft = downleftIndex >= 0 && downleftIndex < isPaneCache.length && shouldConnect(getPaneType(
+ page.items[downleftIndex],
+ downleftIndex,
+ isPaneCache
+ ), paneType);
+ boolean downright = downrightIndex >= 0 && downrightIndex < isPaneCache.length &&
+ shouldConnect(getPaneType(page.items[downrightIndex], downrightIndex, isPaneCache), paneType);
+
+ int ctmIndex = BetterContainers.getCTMIndex(up, right, down, left, upleft, upright, downright, downleft);
+ ctmIndexCache[index] = ctmIndex;
+ return ctmIndex;
+ }
+
+ public static int getRGBFromPane(int paneType) {
+ int rgb = -1;
+ EnumChatFormatting formatting = EnumChatFormatting.WHITE;
+ switch (paneType) {
+ case 0:
+ formatting = EnumChatFormatting.WHITE;
+ break;
+ case 1:
+ formatting = EnumChatFormatting.GOLD;
+ break;
+ case 2:
+ formatting = EnumChatFormatting.LIGHT_PURPLE;
+ break;
+ case 3:
+ formatting = EnumChatFormatting.BLUE;
+ break;
+ case 4:
+ formatting = EnumChatFormatting.YELLOW;
+ break;
+ case 5:
+ formatting = EnumChatFormatting.GREEN;
+ break;
+ case 6:
+ rgb = 0xfff03c96;
+ break;
+ case 7:
+ formatting = EnumChatFormatting.DARK_GRAY;
+ break;
+ case 8:
+ formatting = EnumChatFormatting.GRAY;
+ break;
+ case 9:
+ formatting = EnumChatFormatting.DARK_AQUA;
+ break;
+ case 10:
+ formatting = EnumChatFormatting.DARK_PURPLE;
+ break;
+ case 11:
+ formatting = EnumChatFormatting.DARK_BLUE;
+ break;
+ case 12:
+ rgb = 0xffA0522D;
+ break;
+ case 13:
+ formatting = EnumChatFormatting.DARK_GREEN;
+ break;
+ case 14:
+ formatting = EnumChatFormatting.DARK_RED;
+ break;
+ case 15:
+ rgb = 0x00000000;
+ break;
+ case 16:
+ rgb = SpecialColour.specialToChromaRGB(CHROMA_STR);
+ break;
+ }
+ if (rgb != -1) return rgb;
+ return 0xff000000 | Minecraft.getMinecraft().fontRendererObj.getColorCode(formatting.toString().charAt(1));
+ }
+
+ public static int getPaneType(ItemStack stack, int index, int[] cache) {
+ if (cache != null && cache[index] != 0) return cache[index];
+
+ if (NotEnoughUpdates.INSTANCE.config.storageGUI.fancyPanes == 2) {
+ if (cache != null) cache[index] = -1;
+ return -1;
+ }
+
+ if (stack != null &&
+ (stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) || stack.getItem() == Item.getItemFromBlock(
+ Blocks.glass_pane))) {
+ String internalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if (internalName != null) {
+ if (internalName.startsWith("STAINED_GLASS_PANE")) {
+ if (cache != null) cache[index] = stack.getItemDamage() + 1;
+ return stack.getItemDamage() + 1;
+ } else if (internalName.startsWith("THIN_GLASS")) {
+ if (cache != null) cache[index] = 17;
+ return 17;
+ }
+ }
+ }
+ if (cache != null) cache[index] = -1;
+ return -1;
+ }
private int getMaximumScroll() {
synchronized (StorageManager.getInstance().storageConfig.displayToStorageIdMapRender) {
@@ -194,6 +364,7 @@ public class StorageOverlay extends GuiElement {
@Override
public void render() {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiChest)) return;
+
GuiChest guiChest = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest containerChest = (ContainerChest) guiChest.inventorySlots;
@@ -247,7 +418,7 @@ public class StorageOverlay extends GuiElement {
if (stackOnMouse != null) {
String stackDisplay = Utils.cleanColour(stackOnMouse.getDisplayName());
if (stackDisplay.startsWith("Backpack Slot ") || stackDisplay.startsWith("Empty Backpack Slot ") ||
- stackDisplay.startsWith("Ender Chest Page ")) {
+ stackDisplay.startsWith("Ender Chest Page ") || stackDisplay.startsWith("Locked Backpack Slot ")) {
stackOnMouse = null;
}
}
@@ -590,7 +761,7 @@ public class StorageOverlay extends GuiElement {
if (storageId == currentPage) {
Utils.hasEffectOverride = true;
GlStateManager.translate(storageX - 7, storageY - 17 - 18, 0);
- guiChest.drawSlot(containerChest.getSlot(k + 9));
+ ((AccessorGuiContainer) guiChest).doDrawSlot(containerChest.getSlot(k + 9));
GlStateManager.translate(-storageX + 7, -storageY + 17 + 18, 0);
Utils.hasEffectOverride = false;
} else {
@@ -605,7 +776,7 @@ public class StorageOverlay extends GuiElement {
} else if (storageId == currentPage) {
Utils.hasEffectOverride = true;
GlStateManager.translate(storageX - 7, storageY - 17 - 18, 0);
- guiChest.drawSlot(containerChest.getSlot(k + 9));
+ ((AccessorGuiContainer) guiChest).doDrawSlot(containerChest.getSlot(k + 9));
GlStateManager.translate(-storageX + 7, -storageY + 17 + 18, 0);
Utils.hasEffectOverride = false;
} else {
@@ -1099,8 +1270,8 @@ public class StorageOverlay extends GuiElement {
if (fastRender) {
fontRendererObj.drawString(
- "Fast render does not work with Storage overlay.",
- sizeX / 2 - fontRendererObj.getStringWidth("Fast render does not work with Storage overlay.") / 2,
+ "Fast render and antialiasing do not work with Storage overlay.",
+ sizeX / 2 - fontRendererObj.getStringWidth("Fast render and antialiasing do not work with Storage overlay.") / 2,
-10,
0xFFFF0000
);
@@ -1121,7 +1292,7 @@ public class StorageOverlay extends GuiElement {
GlStateManager.pushMatrix();
GlStateManager.translate(181 - 8, storageViewSize + 18 - (inventoryStartIndex / 9 * 18 + 31), 0);
- guiChest.drawSlot(containerChest.inventorySlots.get(inventoryStartIndex + i));
+ ((AccessorGuiContainer) guiChest).doDrawSlot(containerChest.inventorySlots.get(inventoryStartIndex + i));
GlStateManager.popMatrix();
if (!searchBar.getText().isEmpty()) {
@@ -1155,7 +1326,7 @@ public class StorageOverlay extends GuiElement {
//Utils.drawItemStack(playerItems[i+9], itemX, itemY);
GlStateManager.pushMatrix();
GlStateManager.translate(181 - 8, storageViewSize + 18 - (inventoryStartIndex / 9 * 18 + 31), 0);
- guiChest.drawSlot(containerChest.inventorySlots.get(inventoryStartIndex + 9 + i));
+ ((AccessorGuiContainer) guiChest).doDrawSlot(containerChest.inventorySlots.get(inventoryStartIndex + 9 + i));
GlStateManager.popMatrix();
if (!searchBar.getText().isEmpty()) {
@@ -1537,161 +1708,6 @@ public class StorageOverlay extends GuiElement {
GlStateManager.translate(0, 0, -300);
}
- private static boolean shouldConnect(int paneIndex1, int paneIndex2) {
- if (paneIndex1 == 16 || paneIndex2 == 16) return false;
- if (paneIndex1 < 1 || paneIndex2 < 1) return false;
- return paneIndex1 == paneIndex2;
-
- }
-
- public static int getCTMIndex(StorageManager.StoragePage page, int index, int[] isPaneCache, int[] ctmIndexCache) {
- if (page.items[index] == null) {
- ctmIndexCache[index] = -1;
- return -1;
- }
-
- int paneType = getPaneType(page.items[index], index, isPaneCache);
-
- int upIndex = index - 9;
- int leftIndex = index % 9 > 0 ? index - 1 : -1;
- int rightIndex = index % 9 < 8 ? index + 1 : -1;
- int downIndex = index + 9;
- int upleftIndex = index % 9 > 0 ? index - 10 : -1;
- int uprightIndex = index % 9 < 8 ? index - 8 : -1;
- int downleftIndex = index % 9 > 0 ? index + 8 : -1;
- int downrightIndex = index % 9 < 8 ? index + 10 : -1;
-
- boolean up = upIndex >= 0 && upIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[upIndex],
- upIndex,
- isPaneCache
- ), paneType);
- boolean left = leftIndex >= 0 && leftIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[leftIndex],
- leftIndex,
- isPaneCache
- ), paneType);
- boolean down = downIndex >= 0 && downIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[downIndex],
- downIndex,
- isPaneCache
- ), paneType);
- boolean right = rightIndex >= 0 && rightIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[rightIndex],
- rightIndex,
- isPaneCache
- ), paneType);
- boolean upleft = upleftIndex >= 0 && upleftIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[upleftIndex],
- upleftIndex,
- isPaneCache
- ), paneType);
- boolean upright = uprightIndex >= 0 && uprightIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[uprightIndex],
- uprightIndex,
- isPaneCache
- ), paneType);
- boolean downleft = downleftIndex >= 0 && downleftIndex < isPaneCache.length && shouldConnect(getPaneType(
- page.items[downleftIndex],
- downleftIndex,
- isPaneCache
- ), paneType);
- boolean downright = downrightIndex >= 0 && downrightIndex < isPaneCache.length &&
- shouldConnect(getPaneType(page.items[downrightIndex], downrightIndex, isPaneCache), paneType);
-
- int ctmIndex = BetterContainers.getCTMIndex(up, right, down, left, upleft, upright, downright, downleft);
- ctmIndexCache[index] = ctmIndex;
- return ctmIndex;
- }
-
- private static final String CHROMA_STR = "230:255:255:0:0";
-
- public static int getRGBFromPane(int paneType) {
- int rgb = -1;
- EnumChatFormatting formatting = EnumChatFormatting.WHITE;
- switch (paneType) {
- case 0:
- formatting = EnumChatFormatting.WHITE;
- break;
- case 1:
- formatting = EnumChatFormatting.GOLD;
- break;
- case 2:
- formatting = EnumChatFormatting.LIGHT_PURPLE;
- break;
- case 3:
- formatting = EnumChatFormatting.BLUE;
- break;
- case 4:
- formatting = EnumChatFormatting.YELLOW;
- break;
- case 5:
- formatting = EnumChatFormatting.GREEN;
- break;
- case 6:
- rgb = 0xfff03c96;
- break;
- case 7:
- formatting = EnumChatFormatting.DARK_GRAY;
- break;
- case 8:
- formatting = EnumChatFormatting.GRAY;
- break;
- case 9:
- formatting = EnumChatFormatting.DARK_AQUA;
- break;
- case 10:
- formatting = EnumChatFormatting.DARK_PURPLE;
- break;
- case 11:
- formatting = EnumChatFormatting.DARK_BLUE;
- break;
- case 12:
- rgb = 0xffA0522D;
- break;
- case 13:
- formatting = EnumChatFormatting.DARK_GREEN;
- break;
- case 14:
- formatting = EnumChatFormatting.DARK_RED;
- break;
- case 15:
- rgb = 0x00000000;
- break;
- case 16:
- rgb = SpecialColour.specialToChromaRGB(CHROMA_STR);
- break;
- }
- if (rgb != -1) return rgb;
- return 0xff000000 | Minecraft.getMinecraft().fontRendererObj.getColorCode(formatting.toString().charAt(1));
- }
-
- public static int getPaneType(ItemStack stack, int index, int[] cache) {
- if (cache != null && cache[index] != 0) return cache[index];
-
- if (NotEnoughUpdates.INSTANCE.config.storageGUI.fancyPanes == 2) {
- if (cache != null) cache[index] = -1;
- return -1;
- }
-
- if (stack != null &&
- (stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) || stack.getItem() == Item.getItemFromBlock(
- Blocks.glass_pane))) {
- String internalName = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
- if (internalName != null) {
- if (internalName.startsWith("STAINED_GLASS_PANE")) {
- if (cache != null) cache[index] = stack.getItemDamage() + 1;
- return stack.getItemDamage() + 1;
- } else if (internalName.startsWith("THIN_GLASS")) {
- if (cache != null) cache[index] = 17;
- return 17;
- }
- }
- }
- if (cache != null) cache[index] = -1;
- return -1;
- }
-
private List<String> createTooltip(String title, int selectedOption, String... options) {
String selPrefix = EnumChatFormatting.DARK_AQUA + " \u25b6 ";
String unselPrefix = EnumChatFormatting.GRAY.toString();
@@ -1710,16 +1726,6 @@ public class StorageOverlay extends GuiElement {
return list;
}
- private static class IntPair {
- int x;
- int y;
-
- public IntPair(int x, int y) {
- this.x = x;
- this.y = y;
- }
- }
-
public IntPair getPageCoords(int displayId) {
if (displayId < 0) displayId = 0;
@@ -1964,6 +1970,16 @@ public class StorageOverlay extends GuiElement {
switch (buttonIndex) {
case 0:
NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3 = false;
+ ChatComponentText storageMessage = new ChatComponentText(
+ EnumChatFormatting.YELLOW + "[NEU] " + EnumChatFormatting.YELLOW +
+ "You just disabled the custom storage gui, did you mean to do that? If not click this message to turn it back on.");
+ storageMessage.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neuenablestorage"));
+ storageMessage.setChatStyle(storageMessage.getChatStyle().setChatHoverEvent(
+ new HoverEvent(HoverEvent.Action.SHOW_TEXT,
+ new ChatComponentText(EnumChatFormatting.YELLOW + "Click to enable the custom storage gui."))));
+ ChatComponentText storageChatMessage = new ChatComponentText("");
+ storageChatMessage.appendSibling(storageMessage);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(storageChatMessage);
break;
case 1:
int size =
@@ -2202,7 +2218,7 @@ public class StorageOverlay extends GuiElement {
for (Slot slot : container.inventorySlots.inventorySlots) {
if (slot != null &&
slot.inventory == Minecraft.getMinecraft().thePlayer.inventory &&
- container.isMouseOverSlot(slot, mouseX, mouseY)) {
+ ((AccessorGuiContainer) container).doIsMouseOverSlot(slot, mouseX, mouseY)) {
SlotLocking.getInstance().toggleLock(slot.getSlotIndex());
return true;
}
@@ -2246,8 +2262,6 @@ public class StorageOverlay extends GuiElement {
return true;
}
- private static final ResourceLocation RES_ITEM_GLINT = new ResourceLocation("textures/misc/enchanted_item_glint.png");
-
private void renderEnchOverlay(Set<Vector2f> locations) {
float f = (float) (Minecraft.getSystemTime() % 3000L) / 3000.0F / 8.0F;
float f1 = (float) (Minecraft.getSystemTime() % 4873L) / 4873.0F / 8.0F;
@@ -2304,16 +2318,18 @@ public class StorageOverlay extends GuiElement {
}
public void fastRenderCheck() {
- if (!OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3) {
+ if (!OpenGlHelper.isFramebufferEnabled() && NotEnoughUpdates.INSTANCE.config.notifications.doFastRenderNotif &&
+ NotEnoughUpdates.INSTANCE.config.storageGUI.enableStorageGUI3) {
this.fastRender = true;
- NEUEventListener.displayNotification(Lists.newArrayList(
- "\u00a74Fast Render Warning",
- "\u00a77Due to the way fast render works, it's not compatible with NEU.",
- "\u00a77Please disable fast render in your options under",
- "\u00a77ESC > Options > Video Settings > Performance > Fast Render",
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ "\u00a74Warning",
+ "\u00a77Due to the way fast render and antialiasing work, they're not compatible with NEU.",
+ "\u00a77Please disable fast render and antialiasing in your options under",
+ "\u00a77ESC > Options > Video Settings > Performance > \u00A7cFast Render",
+ "\u00a77ESC > Options > Video Settings > Quality > \u00A7cAntialiasing",
"\u00a77This can't be fixed.",
"\u00a77",
- "\u00a77Press X on your keyboard to close this notifcation"
+ "\u00a77Press X on your keyboard to close this notification"
), true, true);
return;
}
@@ -2321,4 +2337,14 @@ public class StorageOverlay extends GuiElement {
this.fastRender = false;
}
+ private static class IntPair {
+ int x;
+ int y;
+
+ public IntPair(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TradeWindow.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TradeWindow.java
index 1ba155d5..16b5015b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TradeWindow.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TradeWindow.java
@@ -1,9 +1,30 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.core.config.KeybindHelper;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
@@ -26,8 +47,14 @@ import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.io.ByteArrayInputStream;
import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.*;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -95,28 +122,34 @@ public class TradeWindow {
);
}
- private static int getPrice(String internalname) {
- int pricePer = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
+ private static long getPrice(String internalName) {
+ long pricePer = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalName);
if (pricePer == -1) {
- JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalName);
if (bazaarInfo != null && bazaarInfo.has("avg_buy")) {
- pricePer = (int) bazaarInfo.get("avg_buy").getAsFloat();
+ pricePer = (long) bazaarInfo.get("avg_buy").getAsDouble();
}
}
if (pricePer == -1) {
- JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
- if (info != null && !NotEnoughUpdates.INSTANCE.manager.auctionManager.isVanillaItem(internalname) &&
+ JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalName);
+ if (info != null && !NotEnoughUpdates.INSTANCE.manager.auctionManager.isVanillaItem(internalName) &&
info.has("price") && info.has("count")) {
- int auctionPricePer = (int) (info.get("price").getAsFloat() / info.get("count").getAsFloat());
+ long auctionPricePer = (long) (info.get("price").getAsDouble() / info.get("count").getAsDouble());
pricePer = auctionPricePer;
}
}
+ if (pricePer == -1) {
+ APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalName);
+ if (craftCost != null) {
+ pricePer = (int) craftCost.craftCost;
+ }
+ }
return pricePer;
}
- private static int processTopItems(
- ItemStack stack, Map<Integer, Set<String>> topItems,
+ private static long processTopItems(
+ ItemStack stack, Map<Long, Set<String>> topItems,
Map<String, ItemStack> topItemsStack, Map<String, Integer> topItemsCount
) {
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
@@ -155,9 +188,9 @@ public class TradeWindow {
topItemsStack.putIfAbsent("TRADE_COINS", stack);
- int existingPrice = coins;
- Set<Integer> toRemove = new HashSet<>();
- for (Map.Entry<Integer, Set<String>> entry : topItems.entrySet()) {
+ long existingPrice = coins;
+ Set<Long> toRemove = new HashSet<>();
+ for (Map.Entry<Long, Set<String>> entry : topItems.entrySet()) {
if (entry.getValue().contains("TRADE_COINS")) {
entry.getValue().remove("TRADE_COINS");
existingPrice += entry.getKey();
@@ -175,12 +208,12 @@ public class TradeWindow {
}
}
} else {
- int pricePer = getPrice(internalname);
+ long pricePer = getPrice(internalname);
if (pricePer > 0) {
topItemsStack.putIfAbsent(internalname, stack);
- int price = pricePer * stack.stackSize;
- int priceInclBackpack = price;
+ long price = pricePer * stack.stackSize;
+ long priceInclBackpack = price;
NBTTagCompound tag = stack.getTagCompound();
if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
@@ -221,9 +254,9 @@ public class TradeWindow {
}
}
- int existingPrice = price;
- Set<Integer> toRemove = new HashSet<>();
- for (Map.Entry<Integer, Set<String>> entry : topItems.entrySet()) {
+ long existingPrice = price;
+ Set<Long> toRemove = new HashSet<>();
+ for (Map.Entry<Long, Set<String>> entry : topItems.entrySet()) {
if (entry.getValue().contains(internalname)) {
entry.getValue().remove(internalname);
existingPrice += entry.getKey();
@@ -267,7 +300,7 @@ public class TradeWindow {
NBTTagCompound nbt = items.getCompoundTagAt(k).getCompoundTag("tag");
String internalname2 = NotEnoughUpdates.INSTANCE.manager.getInternalnameFromNBT(nbt);
if (internalname2 != null) {
- int pricePer2 = getPrice(internalname2);
+ long pricePer2 = getPrice(internalname2);
if (pricePer2 > 0) {
int count2 = items.getCompoundTagAt(k).getByte("Count");
price += pricePer2 * count2;
@@ -300,7 +333,7 @@ public class TradeWindow {
//Set index mappings
//Our slots
- TreeMap<Integer, List<Integer>> ourTradeMap = new TreeMap<>();
+ TreeMap<Long, List<Integer>> ourTradeMap = new TreeMap<>();
for (int i = 0; i < 16; i++) {
ourTradeIndexes[i] = -1;
@@ -345,19 +378,19 @@ public class TradeWindow {
try {
int coins = (int) (Float.parseFloat(sb.toString()) * mult);
- List<Integer> list = ourTradeMap.computeIfAbsent(coins, k -> new ArrayList<>());
+ List<Integer> list = ourTradeMap.computeIfAbsent((long) coins, k -> new ArrayList<>());
list.add(containerIndex);
} catch (Exception ignored) {
- List<Integer> list = ourTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ List<Integer> list = ourTradeMap.computeIfAbsent(-1L, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
- List<Integer> list = ourTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ List<Integer> list = ourTradeMap.computeIfAbsent(-1L, k -> new ArrayList<>());
list.add(containerIndex);
}
} else {
- int price = getPrice(internalname);
+ long price = getPrice(internalname);
if (price == -1) price = 0;
price += getBackpackValue(stack);
@@ -468,7 +501,7 @@ public class TradeWindow {
}
}
int ourTradeIndex = 0;
- for (Map.Entry<Integer, List<Integer>> entry : ourTradeMap.descendingMap().entrySet()) {
+ for (Map.Entry<Long, List<Integer>> entry : ourTradeMap.descendingMap().entrySet()) {
for (Integer index : entry.getValue()) {
ourTradeIndexes[ourTradeIndex++] = index;
}
@@ -553,8 +586,12 @@ public class TradeWindow {
int y = 104 + 18 * (index / 9);
if (index < 9) y = 180;
- chest.drawSlot(new Slot(Minecraft.getMinecraft().thePlayer.inventory, index, guiLeft + x, guiTop + y));
- //Utils.drawItemStack(stack, guiLeft+x, guiTop+y);
+ ((AccessorGuiContainer) chest).doDrawSlot(new Slot(
+ Minecraft.getMinecraft().thePlayer.inventory,
+ index,
+ guiLeft + x,
+ guiTop + y
+ ));
int col = 0x80ffffff;
if (SlotLocking.getInstance().isSlotIndexLocked(index)) {
@@ -796,10 +833,10 @@ public class TradeWindow {
}
if (NotEnoughUpdates.INSTANCE.config.tradeMenu.customTradePrices) {
- TreeMap<Integer, Set<String>> ourTopItems = new TreeMap<>();
+ TreeMap<Long, Set<String>> ourTopItems = new TreeMap<>();
TreeMap<String, ItemStack> ourTopItemsStack = new TreeMap<>();
TreeMap<String, Integer> ourTopItemsCount = new TreeMap<>();
- int ourPrice = 0;
+ double ourPrice = 0;
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
@@ -810,10 +847,10 @@ public class TradeWindow {
ourPrice += processTopItems(stack, ourTopItems, ourTopItemsStack, ourTopItemsCount);
}
- TreeMap<Integer, Set<String>> theirTopItems = new TreeMap<>();
+ TreeMap<Long, Set<String>> theirTopItems = new TreeMap<>();
TreeMap<String, ItemStack> theirTopItemsStack = new TreeMap<>();
TreeMap<String, Integer> theirTopItemsCount = new TreeMap<>();
- int theirPrice = 0;
+ double theirPrice = 0;
for (int i = 0; i < 16; i++) {
int x = i % 4;
int y = i / 4;
@@ -842,7 +879,7 @@ public class TradeWindow {
int ourTopIndex = Math.max(0, 3 - ourTopItemsStack.size());
out:
- for (Map.Entry<Integer, Set<String>> entry : ourTopItems.descendingMap().entrySet()) {
+ for (Map.Entry<Long, Set<String>> entry : ourTopItems.descendingMap().entrySet()) {
for (String ourTopItemInternal : entry.getValue()) {
ItemStack stack = ourTopItemsStack.get(ourTopItemInternal);
if (stack == null) continue;
@@ -905,7 +942,7 @@ public class TradeWindow {
int theirTopIndex = Math.max(0, 3 - theirTopItemsStack.size());
out:
- for (Map.Entry<Integer, Set<String>> entry : theirTopItems.descendingMap().entrySet()) {
+ for (Map.Entry<Long, Set<String>> entry : theirTopItems.descendingMap().entrySet()) {
for (String theirTopItemInternal : entry.getValue()) {
ItemStack stack = theirTopItemsStack.get(theirTopItemInternal);
if (stack == null) continue;
@@ -1041,7 +1078,7 @@ public class TradeWindow {
!SlotLocking.getInstance().isSlotLocked(slot)) {
Minecraft.getMinecraft().playerController.windowClick(
chest.inventorySlots.windowId,
- slot.slotNumber, 2, 3, Minecraft.getMinecraft().thePlayer
+ slot.slotNumber, 0, 0, Minecraft.getMinecraft().thePlayer
);
}
return;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java
new file mode 100644
index 00000000..e6c4dc74
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/TrophyRewardOverlay.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class TrophyRewardOverlay {
+ private static TrophyRewardOverlay instance = null;
+
+ private final Map<String, Integer> data = new HashMap<>();
+ private boolean reloadNeeded = true;
+
+ public static final ResourceLocation trophyProfitImage =
+ new ResourceLocation("notenoughupdates:trophy_profit.png");
+
+ public static TrophyRewardOverlay getInstance() {
+ if (instance == null) {
+ instance = new TrophyRewardOverlay();
+ }
+ return instance;
+ }
+
+ /**
+ * This adds support for the /neureloadrepo command
+ */
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onRepoReload(RepositoryReloadEvent event) {
+ reloadNeeded = true;
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onItemTooltipLow(ItemTooltipEvent event) {
+ if (!inTrophyFishingInventory()) return;
+
+ ItemStack itemStack = event.itemStack;
+ if (itemStack == null) return;
+ if (!"§aFillet Trophy Fish".equals(itemStack.getDisplayName())) return;
+
+ event.toolTip.add(4, getToolTip());
+ event.toolTip.add(4, "");
+ }
+
+ private String getToolTip() {
+ List<String> line = createText();
+ if (line.size() == 1) {
+ return line.get(0);
+ }
+
+ return line.get(1);
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOWEST)
+ public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) {
+ if (!inTrophyFishingInventory()) return;
+
+ GuiScreen screen = Minecraft.getMinecraft().currentScreen;
+ if (!(screen instanceof GuiChest)) return;
+ Gui gui = event.gui;
+ int xSize = ((AccessorGuiContainer) gui).getXSize();
+ int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) gui).getGuiTop();
+
+ List<String> list = createText();
+ int removed = 0;
+ if (list.size() > 11) {
+ while (list.size() > 10) {
+ removed++;
+ list.remove(9);
+ }
+ list.add("§8And " + removed + " more..");
+ }
+ renderBasicOverlay(event, guiLeft + xSize + 3, guiTop, list);
+ }
+
+ private void load() {
+ data.clear();
+
+ JsonObject jsonObject = Constants.TROPHYFISH;
+ if (jsonObject == null) {
+ return;
+ }
+
+ String[] tiers = new String[]{"_BRONZE", "_SILVER", "_GOLD", "_DIAMOND"};
+
+ for (Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+ String name = entry.getKey();
+
+ int i = 0;
+ for (JsonElement element : entry.getValue().getAsJsonArray()) {
+ int price = element.getAsInt();
+ data.put(name + tiers[i], price);
+ i++;
+ }
+ }
+ }
+
+ private List<String> createText() {
+ if (reloadNeeded) {
+ load();
+ reloadNeeded = false;
+ }
+
+ List<String> texts = new ArrayList<>();
+ if (data.isEmpty()) {
+ texts.add("§cNo data in Repo found!");
+ return texts;
+ }
+
+ Map<String, Integer> totalAmount = new HashMap<>();
+ Map<String, Integer> totalExchange = new HashMap<>();
+ readInventory(totalAmount, totalExchange);
+
+ int total = totalExchange.values().stream().mapToInt(value -> value).sum();
+ texts.add("Trophy Fish Exchange");
+ texts.add("Magma Fish: §e" + total);
+
+ for (Map.Entry<String, Integer> entry : sortByValue(totalExchange).entrySet()) {
+ String name = entry.getKey();
+ int amount = totalAmount.get(name);
+ String[] split = name.split(" ");
+ String rarity = split[split.length - 1];
+ name = name.substring(0, name.length() - rarity.length() - 1);
+
+ if (name.length() > 20) {
+ name = name.substring(0, 18) + "..";
+ }
+
+ String rarityColor = rarity.replace("§l", "").substring(0, 2);
+ texts.add(String.format("%s%dx §r%s§f: §e%d", rarityColor, amount, name, entry.getValue()));
+ }
+
+ return texts;
+ }
+
+ private void readInventory(Map<String, Integer> totalAmount, Map<String, Integer> totalExchange) {
+ if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
+
+ for (Slot slot : Minecraft.getMinecraft().thePlayer.openContainer.inventorySlots) {
+ if (!slot.getHasStack()) continue;
+ ItemStack stack = slot.getStack();
+ if (stack != null) {
+ String internalId = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if (data.containsKey(internalId)) {
+ String displayName = stack.getDisplayName();
+ int stackSize = stack.stackSize;
+
+ int amount = totalAmount.getOrDefault(displayName, 0) + stackSize;
+ totalAmount.put(displayName, amount);
+
+ int exchangeRate = data.get(internalId);
+ int exchangeValue = totalExchange.getOrDefault(displayName, 0) + exchangeRate * stackSize;
+ totalExchange.put(displayName, exchangeValue);
+ }
+ }
+ }
+ }
+ }
+
+ //TODO move into utils class maybe?
+ public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map) {
+ List<Map.Entry<K, V>> list = new ArrayList<>(map.entrySet());
+ list.sort(Map.Entry.comparingByValue());
+ Collections.reverse(list);
+
+ Map<K, V> result = new LinkedHashMap<>();
+ for (Map.Entry<K, V> entry : list) {
+ result.put(entry.getKey(), entry.getValue());
+ }
+
+ return result;
+ }
+
+ private void renderBasicOverlay(
+ GuiScreenEvent.BackgroundDrawnEvent event,
+ int x,
+ int y,
+ List<String> texts
+ ) {
+
+ Gui gui = event.gui;
+ int xSize = ((AccessorGuiContainer) gui).getXSize();
+ int guiLeft = ((AccessorGuiContainer) gui).getGuiLeft();
+ int guiTop = ((AccessorGuiContainer) gui).getGuiTop();
+ Minecraft minecraft = Minecraft.getMinecraft();
+ minecraft.getTextureManager().bindTexture(trophyProfitImage);
+ GL11.glColor4f(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+
+ Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 158, 128, 0, 1, 0, 1, GL11.GL_NEAREST);
+
+ int a = guiLeft + xSize + 4;
+ FontRenderer fontRendererObj = minecraft.fontRendererObj;
+
+ //Render first two header lines
+ int i = 0;
+ for (String text : texts) {
+ fontRendererObj.drawString("§8" + text, a + 10, guiTop + 6 + i, -1, false);
+ i += 10;
+ if (i == 20) break;
+ }
+
+ //Render all other lines
+ i = 25;
+ int index = 0;
+ for (String text : texts) {
+ if (index > 1) {
+ fontRendererObj.drawString(text, a + 10, guiTop + 6 + i, -1, false);
+ i += 10;
+ } else {
+ index++;
+ }
+ }
+ }
+
+ public static boolean inTrophyFishingInventory() {
+ if (!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return false;
+ if (!NotEnoughUpdates.INSTANCE.config.fishing.trophyRewardOverlay) return false;
+
+ Minecraft minecraft = Minecraft.getMinecraft();
+ if (minecraft == null || minecraft.thePlayer == null) return false;
+
+ Container inventoryContainer = minecraft.thePlayer.openContainer;
+ if (!(inventoryContainer instanceof ContainerChest)) return false;
+ ContainerChest containerChest = (ContainerChest) inventoryContainer;
+ return containerChest.getLowerChestInventory().getDisplayName()
+ .getUnformattedText().equalsIgnoreCase("Trophy Fishing");
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/EnchantState.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/EnchantState.java
new file mode 100644
index 00000000..08e720a2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/EnchantState.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.hex;
+
+enum EnchantState {
+ NO_ITEM,
+ ADDING_ENCHANT,
+ SWITCHING_DONT_UPDATE,
+ INVALID_ITEM,
+ HAS_ITEM,
+ HAS_ITEM_IN_HEX,
+ HAS_ITEM_IN_BOOKS,
+ ADDING_BOOK,
+ NO_ITEM_IN_HEX,
+ INVALID_ITEM_HEX,
+ HAS_ITEM_IN_GEMSTONE,
+ ADDING_GEMSTONE,
+ APPLYING_GEMSTONE
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/GuiCustomHex.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/GuiCustomHex.java
new file mode 100644
index 00000000..5361ae89
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/GuiCustomHex.java
@@ -0,0 +1,4885 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.hex;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GlScissorStack;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingFloat;
+import io.github.moulberry.notenoughupdates.core.util.lerp.LerpingInteger;
+import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
+import io.github.moulberry.notenoughupdates.miscgui.CalendarOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.util.OrbDisplay;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.model.ModelBook;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.network.play.client.C0EPacketClickWindow;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.Project;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.Random;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class GuiCustomHex extends Gui {
+ private static final GuiCustomHex INSTANCE = new GuiCustomHex();
+ private static final ResourceLocation TEXTURE = new ResourceLocation("notenoughupdates:custom_enchant_gui.png");
+ private static final ResourceLocation ENCHANTMENT_TABLE_BOOK_TEXTURE = new ResourceLocation(
+ "textures/entity/enchanting_table_book.png");
+ private static final ModelBook MODEL_BOOK = new ModelBook();
+
+ private static final int EXPERIENCE_ORB_COUNT = 30;
+
+ private static final Pattern XP_COST_PATTERN = Pattern.compile("\\u00a73(\\d+) Exp Levels");
+ private static final Pattern ENCHANT_LEVEL_PATTERN = Pattern.compile("(.*)_(.*)");
+ private static final Pattern ENCHANT_NAME_PATTERN = Pattern.compile("([^IVX]*) ([IVX]*)");
+
+ public static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
+
+ public class Enchantment {
+ public int slotIndex;
+ public String enchantName;
+ public String enchId;
+ public List<String> displayLore;
+ public int level;
+ public int xpCost = -1;
+ public boolean overMaxLevel = false;
+ public boolean conflicts = false;
+ public int price = -1;
+
+ public Enchantment(
+ int slotIndex, String enchantName, String enchId, List<String> displayLore, int level,
+ boolean useMaxLevelForCost, boolean checkConflicts
+ ) {
+ this.slotIndex = slotIndex;
+ this.enchantName = enchantName;
+ this.enchId = enchId;
+ this.displayLore = displayLore;
+ this.level = level;
+ boolean isUlt = false;
+ for (String lore : displayLore) {
+ if (lore.contains("§l")) isUlt = true;
+ break;
+ }
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(
+ (isUlt ? "ULTIMATE_" : "") + enchId.toUpperCase() + ";" + level);
+ if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
+ this.price = bazaarInfo.get("curr_buy").getAsInt();
+ }
+ this.enchId = ItemUtils.fixEnchantId(this.enchId, true);
+
+ if (Constants.ENCHANTS != null) {
+ if (checkConflicts && Constants.ENCHANTS.has("enchant_pools")) {
+ JsonArray pools = Constants.ENCHANTS.getAsJsonArray("enchant_pools");
+ out:
+ for (int i = 0; i < pools.size(); i++) {
+ JsonArray pool = pools.get(i).getAsJsonArray();
+
+ boolean hasThis = false;
+ boolean hasApplied = false;
+
+ for (int j = 0; j < pool.size(); j++) {
+ String enchIdPoolElement = pool.get(j).getAsString();
+ if (this.enchId.equalsIgnoreCase(enchIdPoolElement)) {
+ hasThis = true;
+ } else if (playerEnchantIds.containsKey(enchIdPoolElement)) {
+ hasApplied = true;
+ }
+ if (hasThis && hasApplied) {
+ this.conflicts = true;
+ break out;
+ }
+ }
+ }
+ }
+
+ if (level >= 1 && Constants.ENCHANTS.has("enchants_xp_cost")) {
+ JsonObject allCosts = Constants.ENCHANTS.getAsJsonObject("enchants_xp_cost");
+ JsonObject maxLevel = null;
+ if (NotEnoughUpdates.INSTANCE.config.enchantingSolvers.maxEnchLevel && Constants.ENCHANTS.has(
+ "max_xp_table_levels")) {
+ maxLevel = Constants.ENCHANTS.getAsJsonObject("max_xp_table_levels");
+ }
+
+ if (allCosts.has(this.enchId)) {
+ JsonArray costs = allCosts.getAsJsonArray(this.enchId);
+
+ if (costs.size() >= 1) {
+ if (useMaxLevelForCost) {
+ int cost =
+ (maxLevel != null && maxLevel.has(this.enchId) ? maxLevel.get(this.enchId).getAsInt() : costs.size());
+ this.xpCost = costs.get(cost - 1).getAsInt();
+ } else if (level - 1 < costs.size()) {
+ this.xpCost = costs.get(level - 1).getAsInt();
+ } else {
+ overMaxLevel = true;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+
+ public OrbDisplay orbDisplay = new OrbDisplay();
+
+ private int guiLeft;
+ private int guiTop;
+ private boolean shouldOverrideFast = false;
+ private boolean shouldOverrideET = false;
+ private boolean shouldOverrideGemstones = false;
+ private boolean shouldOverrideXp = false;
+ public float pageOpen;
+ public float pageOpenLast;
+ public float pageOpenRandom;
+ public float pageOpenVelocity;
+ public float bookOpen;
+ public float bookOpenLast;
+
+ private int currentPage;
+ private int expectedMaxPage;
+
+ private boolean isScrollingLeft = true;
+
+ private ItemStack enchantingItem = null;
+
+ private int removingEnchantPlayerLevel = -1;
+
+ private final GuiElementTextField searchField = new GuiElementTextField("", GuiElementTextField.SCISSOR_TEXT);
+
+ private final HashMap<String, Integer> playerEnchantIds = new HashMap<>();
+
+ private boolean searchRemovedFromApplicable = false;
+ private boolean searchRemovedFromRemovable = false;
+ private final List<Enchantment> applicable = new ArrayList<>();
+ private final List<Enchantment> removable = new ArrayList<>();
+
+ private final List<HexItem> applicableItem = new ArrayList<>();
+ private final List<HexItem> removableItem = new ArrayList<>();
+ private final HashMap<Integer, Enchantment> enchanterEnchLevels = new HashMap<>();
+ private final HashMap<Integer, HexItem> enchanterItemLevels = new HashMap<>();
+ private Enchantment enchanterCurrentEnch = null;
+ private HexItem enchanterCurrentItem = null;
+
+ public Random random = new Random();
+
+ private EnchantState currentState = EnchantState.NO_ITEM;
+ private EnchantState lastState = EnchantState.NO_ITEM;
+
+ private final LerpingInteger leftScroll = new LerpingInteger(0, 150);
+ private final LerpingInteger rightScroll = new LerpingInteger(0, 150);
+
+ private final LerpingFloat arrowAmount = new LerpingFloat(0, 100);
+
+ private static final int X_SIZE = 364;
+ private static final int Y_SIZE = 215;
+
+ private int clickedScrollOffset = -1;
+ private boolean isClickedScrollLeft = true;
+
+ private boolean isChangingEnchLevel = false;
+
+ private long cancelButtonAnimTime = 0;
+ private long confirmButtonAnimTime = 0;
+
+ public static GuiCustomHex getInstance() {
+ return INSTANCE;
+ }
+
+ public boolean shouldOverride(String containerName) {
+ CalendarOverlay.ableToClickCalendar = true;
+ if (containerName == null) {
+ shouldOverrideET = false;
+ shouldOverrideFast = false;
+ shouldOverrideGemstones = false;
+ shouldOverrideXp = false;
+ searchField.setText("");
+ return false;
+ }
+ boolean config = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableHexGUI;
+ final List<String> gemList = new ArrayList<>(Arrays.asList(
+ "\u2764",
+ "\u2748",
+ "\u270e",
+ "\u2618",
+ "\u2e15",
+ "\u2727",
+ "\u2741",
+ "\u2742"
+ ));
+ shouldOverrideFast = config &&
+ (containerName.length() >= 7 && Objects.equals("The Hex", containerName.substring(0, "The Hex".length()))) &&
+ NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard();
+
+ shouldOverrideET = config &&
+ (containerName.length() >= 12 && Objects.equals(
+ "Enchant Item",
+ containerName.substring(0, "Enchant Item".length())
+ )) && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard();
+
+ shouldOverrideGemstones = config &&
+ (containerName.length() >= 12 && Objects.equals(
+ "Gemstones ➜",
+ containerName.substring(0, "Gemstones ➜".length())
+ )) && NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard();
+ if (shouldOverrideGemstones) {
+ for (String string : gemList) {
+ if (containerName.contains(string)) {
+ shouldOverrideGemstones = false;
+ break;
+ }
+ }
+ }
+
+ shouldOverrideXp = config &&
+ (containerName.length() >= 21 && Objects.equals(
+ "Bottles of Enchanting",
+ containerName.substring(0, "Bottles of Enchanting".length())
+ )) &&
+ NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard();
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+ ItemStack hexStack = cc.getLowerChestInventory().getStackInSlot(50);
+ CalendarOverlay.ableToClickCalendar =
+ !(shouldOverrideET || shouldOverrideFast || shouldOverrideGemstones || shouldOverrideXp);
+ if (hexStack != null && hexStack.getItem() == Items.experience_bottle)
+ return (shouldOverrideET || shouldOverrideFast);
+ if (!shouldOverrideFast && !shouldOverrideET && !shouldOverrideGemstones && !shouldOverrideXp) {
+ currentState = EnchantState.NO_ITEM;
+ applicable.clear();
+ removable.clear();
+ applicableItem.clear();
+ removableItem.clear();
+ expectedMaxPage = 1;
+ enchanterCurrentItem = null;
+ searchField.setText("");
+ }
+ return (shouldOverrideFast || shouldOverrideGemstones || shouldOverrideXp);
+ }
+
+ private int tickCounter = 0;
+
+ public void tick(String containerName) {
+ if (containerName.equals("The Hex")) {
+ currentState = EnchantState.HAS_ITEM_IN_HEX;
+ tickHex();
+ } else if (containerName.contains("Enchant Item")) {
+ tickEnchants();
+ } else if (containerName.contains("Books") || containerName.contains("Modifiers") || containerName.contains(
+ "Reforges") || containerName.contains("Item Upgrades") || containerName.equals("Bottles of Enchanting")) {
+ tickBooks();
+ } else if (containerName.contains("Gemstones")) {
+ tickGemstones();
+ } else {
+ tickBooks();
+ }
+ }
+
+ private void tickEnchants() {
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ //ItemStack hexStack = cc.getLowerChestInventory().getStackInSlot(12);
+ ItemStack enchantingItemStack = cc.getLowerChestInventory().getStackInSlot(19);
+ //ItemStack stack = cc.getLowerChestInventory().getStackInSlot(23);
+ ItemStack hopperStack = cc.getLowerChestInventory().getStackInSlot(51);
+
+ int lastPage = currentPage;
+
+ this.lastState = currentState;
+
+ if (hopperStack != null && hopperStack.getItem() != Item.getItemFromBlock(Blocks.hopper) &&
+ enchantingItem != null) {
+ currentState = EnchantState.ADDING_ENCHANT;
+ } else if (enchantingItemStack == null) {
+ if (currentState == EnchantState.SWITCHING_DONT_UPDATE || currentState == EnchantState.NO_ITEM) {
+ currentState = EnchantState.NO_ITEM;
+ } else {
+ currentState = EnchantState.SWITCHING_DONT_UPDATE;
+ }
+ } else {
+ ItemStack sanityCheckStack = cc.getLowerChestInventory().getStackInSlot(12);
+ if (sanityCheckStack == null || sanityCheckStack.getItem() == Items.enchanted_book) {
+ currentState = EnchantState.HAS_ITEM;
+ enchantingItem = enchantingItemStack;
+ } else {
+ currentState = EnchantState.SWITCHING_DONT_UPDATE;
+ }
+ }
+
+ if (currentState == EnchantState.HAS_ITEM) {
+ ItemStack pageUpStack = cc.getLowerChestInventory().getStackInSlot(17);
+ ItemStack pageDownStack = cc.getLowerChestInventory().getStackInSlot(35);
+ if (pageUpStack != null && pageDownStack != null) {
+ currentPage = 0;
+ boolean upIsGlass = pageUpStack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane);
+ boolean downIsGlass = pageDownStack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane);
+ int page = -1;
+
+ expectedMaxPage = 1;
+ if (!downIsGlass) {
+ try {
+ page = Integer.parseInt(Utils.getRawTooltip(pageDownStack).get(1).substring(11)) - 1;
+ expectedMaxPage = page + 1;
+ } catch (Exception ignored) {
+ }
+ }
+ if (page == -1 && !upIsGlass) {
+ try {
+ page = Integer.parseInt(Utils.getRawTooltip(pageUpStack).get(1).substring(11)) + 1;
+ expectedMaxPage = page;
+ } catch (Exception ignored) {
+ }
+ }
+ if (page == -1) {
+ currentPage = 1;
+ } else {
+ currentPage = page;
+ }
+ }
+ }
+
+ orbDisplay.physicsTickOrbs();
+
+ if (++tickCounter >= 20) {
+ tickCounter = 0;
+ }
+
+ boolean updateItems = tickCounter == 0;
+
+ if (currentState == EnchantState.ADDING_ENCHANT) {
+ if (arrowAmount.getTarget() != 1) {
+ arrowAmount.setTarget(1);
+ arrowAmount.resetTimer();
+ }
+ } else {
+ if (arrowAmount.getTarget() != 0) {
+ arrowAmount.setTarget(0);
+ arrowAmount.resetTimer();
+ }
+ }
+
+ // Set<EnchantState> allowedSwitchStates = Sets.newHashSet(EnchantState.ADDING_ENCHANT, EnchantState.HAS_ITEM, EnchantState.SWITCHING_DONT_UPDATE);
+ if (lastState != currentState || lastPage != currentPage) {
+ // if (!allowedSwitchStates.contains(lastState) || !allowedSwitchStates.contains(currentState)) {
+ leftScroll.setValue(0);
+ rightScroll.setValue(0);
+ // }
+ updateItems = true;
+ }
+
+ if (updateItems && currentState != EnchantState.SWITCHING_DONT_UPDATE) {
+ enchanterEnchLevels.clear();
+
+ if (enchantingItem != null) {
+ playerEnchantIds.clear();
+ NBTTagCompound tag = enchantingItem.getTagCompound();
+ if (tag != null) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ for (String enchId : enchantments.getKeySet()) {
+ playerEnchantIds.put(enchId, enchantments.getInteger(enchId));
+ }
+ }
+ }
+ }
+ }
+
+ if (currentState == EnchantState.ADDING_ENCHANT) {
+ removingEnchantPlayerLevel = -1;
+ boolean updateLevel = enchanterCurrentEnch == null;
+ boolean hasXpBottle = false;
+ for (int i = 0; i < 27; i++) {
+ int slotIndex = 9 + i;
+ ItemStack book = cc.getLowerChestInventory().getStackInSlot(slotIndex);
+ ItemStack xpBottle = cc.getLowerChestInventory().getStackInSlot(50);
+ if (!hasXpBottle && xpBottle != null &&
+ xpBottle.getItem() == Items.experience_bottle) {
+ String name = "Buy Xp Bottles";
+ String id = "XP_BOTTLE";
+ Enchantment xpBottleEnch = new Enchantment(50, name, id,
+ Utils.getRawTooltip(xpBottle), 1, true, false
+ );
+ boolean hasHasXpBottle = false;
+ for (Enchantment ench : applicable) {
+ if (ench.enchId.equals("XP_BOTTLE")) {
+ hasHasXpBottle = true;
+ break;
+ }
+ }
+ if (!hasHasXpBottle) applicable.add(xpBottleEnch);
+ hasXpBottle = true;
+ }
+ if (book != null && book.getItem() == Items.enchanted_book) {
+ NBTTagCompound tagBook = book.getTagCompound();
+ if (tagBook != null) {
+ NBTTagCompound ea = tagBook.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ String enchId = Utils
+ .cleanColour(book.getDisplayName())
+ .toLowerCase()
+ .replace(" ", "_")
+ .replace("-", "_")
+ .replaceAll("[^a-z_]", "");
+ String name = Utils.cleanColour(book.getDisplayName());
+ int enchLevel = -1;
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ } else if (name.equalsIgnoreCase("Turbo-Mushrooms")) {
+ name = "Turbo-Mush";
+ }
+ Matcher levelMatcher = ENCHANT_LEVEL_PATTERN.matcher(enchId);
+ if (levelMatcher.matches()) {
+ enchLevel = Utils.parseRomanNumeral(levelMatcher.group(2).toUpperCase());
+ enchId = levelMatcher.group(1);
+ }
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), enchLevel, false, true
+ );
+ int index = 0;
+ for (String lore : enchantment.displayLore) {
+ if (lore.contains("N/A") && enchantment.price > 0) {
+ String price = numberFormat.format(enchantment.price);
+ enchantment.displayLore.set(index, "\u00a76" + price + ".0 Coins");
+ }
+ if (lore.contains("Loading...")) {
+ if (enchantment.price > 0) {
+ enchantment.displayLore.set(index, "\u00a7eClick to buy on the Bazaar!");
+ } else {
+ enchantment.displayLore.set(index, "\u00a7cNot enough supply on the Bazaar!");
+ }
+ }
+ index++;
+ }
+ enchantment.displayLore.remove(0);
+
+ if (removingEnchantPlayerLevel == -1 && playerEnchantIds.containsKey(enchId)) {
+ removingEnchantPlayerLevel = playerEnchantIds.get(enchId);
+ }
+
+ if (removingEnchantPlayerLevel >= 0 && enchantment.level < removingEnchantPlayerLevel) {
+ continue;
+ }
+
+ boolean aboveMaxLevelFromEt = false;
+ if (NotEnoughUpdates.INSTANCE.config.enchantingSolvers.maxEnchLevel && Constants.ENCHANTS != null) {
+ JsonObject maxLevel = null;
+ if (Constants.ENCHANTS.has("max_xp_table_levels")) {
+ maxLevel = Constants.ENCHANTS.getAsJsonObject("max_xp_table_levels");
+ }
+ if (maxLevel != null && maxLevel.has(enchId)) {
+ if (enchantment.level > maxLevel.get(enchId).getAsInt()) {
+ aboveMaxLevelFromEt = true;
+ }
+ }
+ }
+
+ if (enchanterCurrentEnch == null) {
+ enchanterCurrentEnch = enchantment;
+ } else if (updateLevel) {
+ if (removingEnchantPlayerLevel < 0 && enchantment.level > enchanterCurrentEnch.level && !aboveMaxLevelFromEt) {
+ enchanterCurrentEnch = enchantment;
+ } else if (removingEnchantPlayerLevel >= 0 && enchantment.level < enchanterCurrentEnch.level) {
+ enchanterCurrentEnch = enchantment;
+ }
+ }
+
+ enchanterEnchLevels.put(enchantment.level, enchantment);
+ }
+ }
+ }
+ }
+ }
+ if (enchanterCurrentEnch != null && removingEnchantPlayerLevel >= 0) {
+ for (String line : enchanterCurrentEnch.displayLore) {
+ Matcher matcher = XP_COST_PATTERN.matcher(line);
+ if (matcher.find()) {
+ enchanterCurrentEnch.xpCost = Integer.parseInt(matcher.group(1));
+ }
+ }
+ }
+ } else {
+ isChangingEnchLevel = false;
+ enchanterCurrentEnch = null;
+
+ searchRemovedFromRemovable = false;
+ searchRemovedFromApplicable = false;
+ applicable.clear();
+ removable.clear();
+ boolean hasXpBottle = false;
+ if (currentState == EnchantState.HAS_ITEM) {
+ for (int i = 0; i < 15; i++) {
+ int slotIndex = 12 + (i % 5) + (i / 5) * 9;
+ ItemStack book = cc.getLowerChestInventory().getStackInSlot(slotIndex);
+ ItemStack xpBottle = cc.getLowerChestInventory().getStackInSlot(50);
+ if (!hasXpBottle && xpBottle != null &&
+ xpBottle.getItem() == Items.experience_bottle) {
+ String name = "Buy Xp Bottles";
+ String id = "XP_BOTTLE";
+ Enchantment xpBottleEnch = new Enchantment(50, name, id,
+ Utils.getRawTooltip(xpBottle), 1, true, false
+ );
+ applicable.add(xpBottleEnch);
+ hasXpBottle = true;
+ }
+ if (book != null) {
+ NBTTagCompound tagBook = book.getTagCompound();
+ if (tagBook != null) {
+ NBTTagCompound ea = tagBook.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ String enchId = Utils
+ .cleanColour(book.getDisplayName())
+ .toLowerCase()
+ .replace(" ", "_")
+ .replace("-", "_")
+ .replaceAll("[^a-z_]", "");
+ if (enchId.equalsIgnoreCase("_")) continue;
+ enchId = ItemUtils.fixEnchantId(enchId, true);
+ String name = Utils.cleanColour(book.getDisplayName());
+
+ if (searchField.getText().trim().isEmpty() ||
+ name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ } else if (name.equalsIgnoreCase("Turbo-Mushrooms")) {
+ name = "Turbo-Mush";
+ }
+ Matcher nameMatcher = ENCHANT_NAME_PATTERN.matcher(name);
+ if (nameMatcher.matches()) {
+ name = nameMatcher.group(1);
+ }
+
+ if (playerEnchantIds.containsKey(enchId)) {
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), playerEnchantIds.get(enchId), false, false
+ );
+ if (!enchantment.overMaxLevel) {
+ removable.add(enchantment);
+ }
+ } else {
+ Enchantment enchantment = new Enchantment(slotIndex, name, enchId,
+ Utils.getRawTooltip(book), 1, true, true
+ );
+ applicable.add(enchantment);
+ }
+ } else {
+ if (playerEnchantIds.containsKey(enchId)) {
+ searchRemovedFromRemovable = true;
+ } else {
+ searchRemovedFromApplicable = true;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ NEUConfig cfg = NotEnoughUpdates.INSTANCE.config;
+ int mult = cfg.enchantingSolvers.enchantOrdering == 0 ? 1 : -1;
+ Comparator<Enchantment> comparator = cfg.enchantingSolvers.enchantSorting == 0 ?
+ Comparator.comparingInt(e -> mult * e.xpCost) :
+ (c1, c2) -> mult *
+ c1.enchId.toLowerCase().compareTo(c2.enchId.toLowerCase());
+ removable.sort(comparator);
+ applicable.sort(comparator);
+ }
+ }
+ }
+
+ //Update book model state
+ if (lastState != currentState) {
+ do {
+ this.pageOpenRandom += (float) (this.random.nextInt(4) - this.random.nextInt(4));
+
+ } while (!(this.pageOpen > this.pageOpenRandom + 1.0F) && !(this.pageOpen < this.pageOpenRandom - 1.0F));
+ }
+
+ this.pageOpenLast = this.pageOpen;
+ this.bookOpenLast = this.bookOpen;
+
+ if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT) {
+ this.bookOpen += 0.2F;
+ } else {
+ this.bookOpen -= 0.2F;
+ }
+
+ this.bookOpen = MathHelper.clamp_float(this.bookOpen, 0.0F, 1.0F);
+ float f1 = (this.pageOpenRandom - this.pageOpen) * 0.4F;
+ f1 = MathHelper.clamp_float(f1, -0.2F, 0.2F);
+ this.pageOpenVelocity += (f1 - this.pageOpenVelocity) * 0.9F;
+ this.pageOpen += this.pageOpenVelocity;
+ }
+
+ private void tickBooks() {
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ ItemStack enchantingItemStack = cc.getLowerChestInventory().getStackInSlot(19);
+ ItemStack anvilStack = cc.getLowerChestInventory().getStackInSlot(28);
+
+ this.lastState = currentState;
+
+ if (anvilStack != null && anvilStack.getItem() == Item.getItemFromBlock(Blocks.anvil) &&
+ currentState != EnchantState.ADDING_BOOK) {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchantingItem = enchantingItemStack;
+ } else if (currentState == EnchantState.HAS_ITEM_IN_BOOKS && enchantingItem == null &&
+ enchantingItemStack != null) {
+ enchantingItem = enchantingItemStack;
+ } else if (anvilStack != null && anvilStack.getItem() == Item.getItemFromBlock(Blocks.enchanting_table) &&
+ currentState != EnchantState.ADDING_BOOK) {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchantingItem = enchantingItemStack;
+ }
+
+ orbDisplay.physicsTickOrbs();
+
+ if (++tickCounter >= 20) {
+ tickCounter = 0;
+ }
+
+ if (currentState == EnchantState.ADDING_BOOK) {
+ if (arrowAmount.getTarget() != 1) {
+ arrowAmount.setTarget(1);
+ arrowAmount.resetTimer();
+ }
+ } else {
+ if (arrowAmount.getTarget() != 0) {
+ arrowAmount.setTarget(0);
+ arrowAmount.resetTimer();
+ }
+ }
+
+ isChangingEnchLevel = false;
+
+ searchRemovedFromRemovable = false;
+ searchRemovedFromApplicable = false;
+ if (applicableItem.size() < 6) leftScroll.setValue(0);
+ applicableItem.clear();
+ removableItem.clear();
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.ADDING_BOOK) {
+ boolean hasRandomReforge = false;
+ for (int i = 0; i < 15; i++) {
+ int slotIndex = 12 + (i % 5) + (i / 5) * 9;
+ ItemStack book = cc.getLowerChestInventory().getStackInSlot(slotIndex);
+ ItemStack randomReforge = cc.getLowerChestInventory().getStackInSlot(48);
+ if (!hasRandomReforge && randomReforge != null &&
+ randomReforge.getItem() == Item.getItemFromBlock(Blocks.anvil)) {
+ String name = Utils.cleanColour(randomReforge.getDisplayName());
+ String id = Utils.cleanColour(randomReforge.getDisplayName());
+ if (name.equals("Convert to Dungeon Item")) {
+ name = "Dungeonize Item";
+ id = "CONVERT_TO_DUNGEON";
+ } else if (name.equals("Random Basic Reforge")) {
+ name = "Basic Reforge";
+ id = "RANDOM_REFORGE";
+ }
+ HexItem reforgeItem = new HexItem(48, name, id,
+ Utils.getRawTooltip(randomReforge), true, true
+ );
+ boolean hasAdded = false;
+ for (String lore : reforgeItem.displayLore) {
+ if (lore.contains("This item is already a Dungeon")) {
+ removableItem.add(reforgeItem);
+ hasAdded = true;
+ break;
+ }
+ }
+ if (!hasAdded) applicableItem.add(reforgeItem);
+ hasRandomReforge = true;
+ }
+ if (book != null) {
+ NBTTagCompound tagBook = book.getTagCompound();
+ if (tagBook != null) {
+ NBTTagCompound ea = tagBook.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ String itemId = Utils.cleanColour(book.getDisplayName()).toUpperCase().replace(" ", "_").replace(
+ "-",
+ "_"
+ );
+ String name = Utils.cleanColour(book.getDisplayName());
+ if (itemId.equalsIgnoreCase("_")) continue;
+ if (itemId.equalsIgnoreCase("Item_Maxed_Out")) continue;
+ if (searchField.getText().trim().isEmpty() ||
+ name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
+ if (name.equalsIgnoreCase("Hot Potato Book")) {
+ name = "Hot Potato";
+ } else if (name.equalsIgnoreCase("Fuming Potato Book")) {
+ name = "Fuming Potato";
+ } else if (name.equalsIgnoreCase("Recombobulator 3000")) {
+ name = "Recombobulator";
+ } else if (name.contains("Power Scroll")) {
+ name = name.replace("Power ", "");
+ } else if (name.contains("\u272a")) {
+ name = name.replaceAll("[^✪]*", "");
+ } else if (name.equalsIgnoreCase("First Master Star")) {
+ name = "Master Star \u00a7c➊";
+ } else if (name.equalsIgnoreCase("Second Master Star")) {
+ name = "Master Star \u00a7c➋";
+ } else if (name.equalsIgnoreCase("Third Master Star")) {
+ name = "Master Star \u00a7c➌";
+ } else if (name.equalsIgnoreCase("Fourth Master Star")) {
+ name = "Master Star \u00a7c➍";
+ } else if (name.equalsIgnoreCase("Fifth Master Star")) {
+ name = "Master Star \u00a7c➎";
+ } else if (name.equalsIgnoreCase("The Art Of Peace")) {
+ name = "Art Of Peace";
+ } else if (name.equalsIgnoreCase("Mana Disintegrator")) {
+ name = "M Disintegrator";
+ }
+ /*if (playerEnchantIds.containsKey(itemId)) {
+ HexItem item = new HexItem(slotIndex, name, itemId,
+ Utils.getRawTooltip(book), false, false
+ );
+ if (!item.overMaxLevel) {
+ removableItem.add(item);
+ }
+ enchanterItemLevels.put(item.level, item);
+ } else */
+ {
+ HexItem item = new HexItem(slotIndex, name, itemId,
+ Utils.getRawTooltip(book), true, true
+ );
+ enchanterItemLevels.put(item.level, item);
+ if (item.itemType != ItemType.UNKNOWN) {
+ int potatoCount = 0;
+ int killCount = 0;
+ int warCount = 0;
+ int ffdCount = 0;
+ int recombCount = 0;
+ int effLevel = 0;
+ int starCount = 0;
+ int singularityCount = 0;
+ int tunerCount = 0;
+ int peaceCount = 0;
+ int manaDisintegratorCount = 0;
+ boolean shadowWarp = false;
+ boolean witherShield = false;
+ boolean implosion = false;
+ String reforge = "";
+ if (enchantingItem != null) {
+ NBTTagCompound tagItem = enchantingItem.getTagCompound();
+ if (tagItem != null) {
+ NBTTagCompound extra = tagItem.getCompoundTag("ExtraAttributes");
+ if (extra != null) {
+ potatoCount = extra.getInteger("hot_potato_count");
+ killCount = extra.getInteger("stats_book");
+ warCount = extra.getInteger("art_of_war_count");
+ ffdCount = extra.getInteger("farming_for_dummies_count");
+ recombCount = extra.getInteger("rarity_upgrades");
+ starCount = extra.getInteger("upgrade_level");
+ singularityCount = extra.getInteger("wood_singularity_count");
+ tunerCount = extra.getInteger("tuned_transmission");
+ peaceCount = extra.getInteger("art_of_peace_count");
+ manaDisintegratorCount = extra.getInteger("mana_disintegrator_count");
+ reforge = extra.getString("modifier");
+ NBTTagCompound enchs = extra.getCompoundTag("enchantments");
+ NBTTagList scrolls = extra.getTagList("ability_scroll", 8);
+ if (enchs != null) {
+ effLevel = enchs.getInteger("efficiency");
+ }
+ if (scrolls != null) {
+ for (int index = 0; index < scrolls.tagCount(); index++) {
+ if (scrolls.getStringTagAt(index).equals("IMPLOSION_SCROLL")) {
+ implosion = true;
+ } else if (scrolls.getStringTagAt(index).equals("SHADOW_WARP_SCROLL")) {
+ shadowWarp = true;
+ } else if (scrolls.getStringTagAt(index).equals("WITHER_SHIELD_SCROLL")) {
+ witherShield = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (item.itemName.length() > 14) item.itemName = item.itemName.substring(0, 14);
+
+ if (item.itemType == ItemType.HOT_POTATO) {
+ if (potatoCount < 10) applicableItem.add(item);
+ else removableItem.add(item);
+
+ } else if (item.itemType == ItemType.FUMING_POTATO) {
+ if (potatoCount >= 10 && potatoCount < 15) applicableItem.add(item);
+ else if (potatoCount >= 15) removableItem.add(item);
+
+ } else if (item.itemType == ItemType.BOOK_OF_STATS) {
+ if (killCount > 0) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.ART_OF_WAR) {
+ if (warCount > 0) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.FARMING_DUMMY) {
+ if (ffdCount < 5) applicableItem.add(item);
+ else removableItem.add(item);
+
+ } else if (item.itemType == ItemType.RECOMB) {
+ if (recombCount > 0) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.SILEX) {
+ if (effLevel >= 5 && effLevel < 10) applicableItem.add(item);
+ else if (effLevel == 10) removableItem.add(item);
+
+ } else if (item.isPowerScroll()) {
+ applicableItem.add(item);
+
+ } else if (item.isMasterStar()) {
+ applicableItem.add(item);
+
+ } else if (item.isDungeonStar()) {
+ if (starCount >= item.itemType.getStarLevel()) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.WOOD_SINGULARITY) {
+ if (singularityCount > 0) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.isHypeScroll()) {
+ if (shadowWarp) removableItem.add(item);
+ else if (implosion) removableItem.add(item);
+ else if (witherShield) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.TUNER) {
+ if (tunerCount >= 4) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.REFORGE) {
+ if (item.getReforge().equalsIgnoreCase(reforge) && !reforge.equals("")) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.ART_OF_PEACE) {
+ if (peaceCount > 0) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else if (item.itemType == ItemType.MANA_DISINTEGRATOR) {
+ if (manaDisintegratorCount >= 10) removableItem.add(item);
+ else applicableItem.add(item);
+
+ } else {
+ applicableItem.add(item);
+ }
+ } else {
+ applicableItem.add(item);
+ }
+ }
+ } else {
+ if (playerEnchantIds.containsKey(itemId)) {
+ searchRemovedFromRemovable = true;
+ } else {
+ searchRemovedFromApplicable = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ NEUConfig cfg = NotEnoughUpdates.INSTANCE.config;
+ int mult = cfg.enchantingSolvers.enchantOrdering == 0 ? 1 : -1;
+ Comparator<HexItem> comparator = cfg.enchantingSolvers.enchantSorting == 0 ?
+ Comparator.comparingInt(e -> (int) (mult * e.price)) :
+ (c1, c2) -> mult *
+ c1.itemId.toLowerCase().compareTo(c2.itemId.toLowerCase());
+ removableItem.sort(comparator);
+ applicableItem.sort(comparator);
+ }
+ }
+
+ private void tickHex() {
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ ItemStack enchantingItemStack = cc.getLowerChestInventory().getStackInSlot(22);
+ ItemStack glassStack = cc.getLowerChestInventory().getStackInSlot(12);
+ //ItemStack anvilStack = cc.getLowerChestInventory().getStackInSlot(28);
+
+ this.lastState = currentState;
+
+ if (enchantingItemStack != null) {
+ if (glassStack.getItem() != null && glassStack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ if (glassStack.getItemDamage() == 14) {
+ currentState = EnchantState.INVALID_ITEM_HEX;
+ } else if (glassStack.getItemDamage() == 10) {
+ currentState = EnchantState.HAS_ITEM_IN_HEX;
+ } else {
+ currentState = EnchantState.NO_ITEM_IN_HEX;
+ }
+ enchantingItem = enchantingItemStack;
+ }
+ } else {
+ currentState = EnchantState.NO_ITEM_IN_HEX;
+ }
+
+ orbDisplay.physicsTickOrbs();
+
+ if (++tickCounter >= 20) {
+ tickCounter = 0;
+ }
+
+ if (currentState == EnchantState.ADDING_BOOK) {
+ if (arrowAmount.getTarget() != 1) {
+ arrowAmount.setTarget(1);
+ arrowAmount.resetTimer();
+ }
+ } else {
+ if (arrowAmount.getTarget() != 0) {
+ arrowAmount.setTarget(0);
+ arrowAmount.resetTimer();
+ }
+ }
+
+ isChangingEnchLevel = false;
+
+ searchRemovedFromRemovable = false;
+ searchRemovedFromApplicable = false;
+ applicableItem.clear();
+ removableItem.clear();
+ boolean hasHexItem = false;
+ if (currentState == EnchantState.HAS_ITEM_IN_HEX) {
+ for (int i = 0; i < 9; i++) {
+ int slotIndex = 15 + (i % 3) + (i / 3) * 9;
+ ItemStack book = cc.getLowerChestInventory().getStackInSlot(slotIndex);
+ if (!hasHexItem && glassStack != null) {
+ HexItem item = new HexItem(slotIndex, "Total Upgrades", "TOTAL_UPGRADES",
+ Utils.getRawTooltip(glassStack), true, true
+ );
+ removableItem.add(item);
+ hasHexItem = true;
+ }
+ if (book != null) {
+ NBTTagCompound tagBook = book.getTagCompound();
+ if (tagBook != null) {
+ NBTTagCompound ea = tagBook.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ String itemId = Utils.cleanColour(book.getDisplayName()).toUpperCase().replace(" ", "_").replace(
+ "-",
+ "_"
+ );
+ String name = Utils.cleanColour(book.getDisplayName());
+ if (itemId.equalsIgnoreCase("_")) continue;
+ if (itemId.equalsIgnoreCase("Item_Maxed_Out")) continue;
+ if (searchField.getText().trim().isEmpty() ||
+ name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
+ if (name.equalsIgnoreCase("Ultimate Enchantments")) {
+ name = "Ult Enchants";
+ }
+ /*if (playerEnchantIds.containsKey(itemId)) {
+ HexItem item = new HexItem(slotIndex, name, itemId,
+ Utils.getRawTooltip(book), false, false
+ );
+ if (!item.overMaxLevel) {
+ removableItem.add(item);
+ }
+ enchanterItemLevels.put(item.level, item);
+ } else */
+ {
+ HexItem item = new HexItem(slotIndex, name, "HEX_ITEM" + i,
+ Utils.getRawTooltip(book), true, true
+ );
+ enchanterItemLevels.put(item.level, item);
+ applicableItem.add(item);
+ }
+ } else {
+ if (playerEnchantIds.containsKey(itemId)) {
+ searchRemovedFromRemovable = true;
+ } else {
+ searchRemovedFromApplicable = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ NEUConfig cfg = NotEnoughUpdates.INSTANCE.config;
+ int mult = cfg.enchantingSolvers.enchantOrdering == 0 ? 1 : -1;
+ Comparator<HexItem> comparator = cfg.enchantingSolvers.enchantSorting == 0 ?
+ Comparator.comparingInt(e -> (int) (mult * e.price)) :
+ (c1, c2) -> mult *
+ c1.itemId.toLowerCase().compareTo(c2.itemId.toLowerCase());
+ removableItem.sort(comparator);
+ applicableItem.sort(comparator);
+ }
+ }
+
+ private void tickGemstones() {
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ ItemStack enchantingItemStack = cc.getLowerChestInventory().getStackInSlot(19);
+ ItemStack portalStack = cc.getLowerChestInventory().getStackInSlot(28);
+
+ int lastPage = currentPage;
+ this.lastState = currentState;
+ if (portalStack != null && portalStack.getItem() == Item.getItemFromBlock(Blocks.end_portal_frame) &&
+ currentState != EnchantState.ADDING_GEMSTONE && !shouldOverrideGemstones &&
+ currentState != EnchantState.APPLYING_GEMSTONE) {
+ currentState = EnchantState.HAS_ITEM_IN_GEMSTONE;
+ enchantingItem = enchantingItemStack;
+ } else if (portalStack != null && portalStack.getItem() == Item.getItemFromBlock(Blocks.end_portal_frame) &&
+ shouldOverrideGemstones && currentState != EnchantState.APPLYING_GEMSTONE) {
+ currentState = EnchantState.ADDING_GEMSTONE;
+ } else if (currentState == EnchantState.HAS_ITEM_IN_GEMSTONE && enchantingItem == null &&
+ enchantingItemStack != null) {
+ enchantingItem = enchantingItemStack;
+ } else if (currentState != EnchantState.APPLYING_GEMSTONE) {
+ currentState = EnchantState.HAS_ITEM_IN_GEMSTONE;
+ }
+
+ if (currentState == EnchantState.APPLYING_GEMSTONE || currentState == EnchantState.ADDING_GEMSTONE) {
+ ItemStack pageUpStack = cc.getLowerChestInventory().getStackInSlot(17);
+ ItemStack pageDownStack = cc.getLowerChestInventory().getStackInSlot(35);
+ if (pageUpStack != null && pageDownStack != null) {
+ currentPage = 0;
+ boolean upIsGlass = pageUpStack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane);
+ boolean downIsGlass = pageDownStack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane);
+ int page = -1;
+
+ expectedMaxPage = 1;
+ if (!downIsGlass) {
+ try {
+ page = Integer.parseInt(Utils.getRawTooltip(pageDownStack).get(1).substring(11)) - 1;
+ expectedMaxPage = page + 1;
+ } catch (Exception ignored) {
+ }
+ }
+ if (page == -1 && !upIsGlass) {
+ try {
+ page = Integer.parseInt(Utils.getRawTooltip(pageUpStack).get(1).substring(11)) + 1;
+ expectedMaxPage = page;
+ } catch (Exception ignored) {
+ }
+ }
+ if (page == -1) {
+ currentPage = 1;
+ } else {
+ currentPage = page;
+ }
+ }
+ }
+
+ orbDisplay.physicsTickOrbs();
+
+ if (++tickCounter >= 20) {
+ tickCounter = 0;
+ }
+
+ if (lastState != currentState || lastPage != currentPage) {
+ leftScroll.setValue(0);
+ rightScroll.setValue(0);
+ }
+
+ if (currentState == EnchantState.APPLYING_GEMSTONE) {
+ if (arrowAmount.getTarget() != 1) {
+ arrowAmount.setTarget(1);
+ arrowAmount.resetTimer();
+ }
+ } else {
+ if (arrowAmount.getTarget() != 0) {
+ arrowAmount.setTarget(0);
+ arrowAmount.resetTimer();
+ }
+ }
+
+ isChangingEnchLevel = false;
+
+ searchRemovedFromRemovable = false;
+ searchRemovedFromApplicable = false;
+ applicableItem.clear();
+ removableItem.clear();
+ if (isInGemstones()) {
+ for (int i = 0; i < 15; i++) {
+ int slotIndex = 12 + (i % 5) + (i / 5) * 9;
+ ItemStack book = cc.getLowerChestInventory().getStackInSlot(slotIndex);
+ if (book != null) {
+ NBTTagCompound tagBook = book.getTagCompound();
+ if (tagBook != null) {
+ NBTTagCompound ea = tagBook.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ if (enchantments != null) {
+ String itemId = Utils.cleanColour(book.getDisplayName()).toUpperCase().replace(" ", "_").replace(
+ "-",
+ "_"
+ );
+ String name = Utils.cleanColour(book.getDisplayName());
+ if (itemId.equalsIgnoreCase("_")) continue;
+ if (itemId.equalsIgnoreCase("Item_Maxed_Out")) continue;
+ if (searchField.getText().trim().isEmpty() ||
+ name.toLowerCase().contains(searchField.getText().trim().toLowerCase())) {
+ /*if (playerEnchantIds.containsKey(itemId)) {
+ HexItem item = new HexItem(slotIndex, name, itemId,
+ Utils.getRawTooltip(book), false, false
+ );
+ if (!item.overMaxLevel) {
+ removableItem.add(item);
+ }
+ enchanterItemLevels.put(item.level, item);
+ } else */
+ {
+ HexItem item = new HexItem(slotIndex, name, itemId,
+ Utils.getRawTooltip(book), true, true
+ );
+ enchanterItemLevels.put(item.level, item);
+ if (item.isGemstone()) {
+ if (book.getItem() == Items.dye) {
+ item.conflicts = true;
+ }
+ boolean removed = false;
+ for (String lore : item.displayLore) {
+ if (lore.contains("Click to remove!")) {
+ removableItem.add(item);
+ removed = true;
+ break;
+ }
+ }
+ if (!removed) {
+ applicableItem.add(item);
+ }
+ if (item.itemName.length() > 14) item.itemName = item.itemName.substring(0, 14);
+ } else {
+ applicableItem.add(item);
+ }
+ }
+ } else {
+ if (playerEnchantIds.containsKey(itemId)) {
+ searchRemovedFromRemovable = true;
+ } else {
+ searchRemovedFromApplicable = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ NEUConfig cfg = NotEnoughUpdates.INSTANCE.config;
+ int mult = cfg.enchantingSolvers.enchantOrdering == 0 ? 1 : -1;
+ Comparator<HexItem> comparator = cfg.enchantingSolvers.enchantSorting == 0 ?
+ Comparator.comparingInt(e -> (int) (mult * e.price)) :
+ (c1, c2) -> mult *
+ c1.itemId.toLowerCase().compareTo(c2.itemId.toLowerCase());
+ removableItem.sort(comparator);
+ applicableItem.sort(comparator);
+ }
+ this.pageOpenLast = this.pageOpen;
+ }
+
+ private List<String> createTooltip(String title, int selectedOption, String... options) {
+ String selPrefix = EnumChatFormatting.DARK_AQUA + " \u25b6 ";
+ String unselPrefix = EnumChatFormatting.GRAY.toString();
+
+ for (int i = 0; i < options.length; i++) {
+ if (i == selectedOption) {
+ options[i] = selPrefix + options[i];
+ } else {
+ options[i] = unselPrefix + options[i];
+ }
+ }
+
+ List<String> list = Lists.newArrayList(options);
+ list.add(0, "");
+ list.add(0, EnumChatFormatting.GREEN + title);
+ return list;
+ }
+
+ public void render(float partialTicks, String containerName) {
+ if (containerName == null) return;
+ if (containerName.equals("The Hex")) {
+ renderHex(partialTicks);
+ } else if (containerName.contains("Enchant Item")) {
+ renderEnchantment(partialTicks);
+ } else if (containerName.contains("Books") || containerName.contains("Modifiers") || containerName.contains(
+ "Bottles of Enchanting")) {
+ renderBooks(partialTicks);
+ } else if (containerName.contains("Gemstones")) {
+ renderGemstones(partialTicks);
+ } else {
+ renderBooks(partialTicks);
+ }
+ }
+
+ private void renderEnchantment(float partialTicks) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
+
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ leftScroll.tick();
+ rightScroll.tick();
+ arrowAmount.tick();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ guiLeft = (width - X_SIZE) / 2;
+ guiTop = (height - Y_SIZE) / 2;
+
+ List<String> tooltipToDisplay = null;
+ boolean disallowClick = false;
+ ItemStack stackOnMouse = Minecraft.getMinecraft().thePlayer.inventory.getItemStack();
+ int itemHoverX = -1;
+ int itemHoverY = -1;
+ boolean hoverLocked = false;
+
+ drawGradientRect(0, 0, width, height, 0xc0101010, 0xd0101010);
+
+ renderBaseTexture();
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("Applicable", guiLeft + 7, guiTop + 7, 0x404040, false);
+ Minecraft.getMinecraft().fontRendererObj.drawString("Removable", guiLeft + 247, guiTop + 7, 0x404040, false);
+
+ //Page Text
+ if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT) {
+ String pageStr = "Page: " + currentPage + "/" + expectedMaxPage;
+ int pageStrLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(pageStr);
+ Utils.drawStringCentered(pageStr, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 14, false, 0x404040
+ );
+
+ //Page Arrows
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - pageStrLen / 2 - 2 - 15, guiTop + 6, 15, 15,
+ 0, 15 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + pageStrLen / 2 + 2, guiTop + 6, 15, 15,
+ 15 / 512f, 30 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ }
+
+ tooltipToDisplay = renderSettings(mouseX, mouseY, tooltipToDisplay);
+
+ renderScrollBars(applicable, removable, mouseY);
+
+ //Enchant book model
+ renderEnchantBook(scaledResolution, partialTicks);
+
+ //Can't be enchanted text
+ if (currentState == EnchantState.INVALID_ITEM) {
+ GlStateManager.disableDepth();
+ Utils.drawStringCentered("This item can't", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 88, true, 0xffff5555
+ );
+ Utils.drawStringCentered("be enchanted", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 98, true, 0xffff5555
+ );
+ GlStateManager.enableDepth();
+ }
+
+ renderArrow();
+
+ //Text if no enchants appear
+ if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT) {
+ if (applicable.isEmpty() && removable.isEmpty() && searchRemovedFromApplicable) {
+ Utils.drawStringCentered("Can't find that", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchant, perhaps", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("it is on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 48, true, 0xffff5555
+ );
+ Utils.drawStringCentered("another page?", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 58, true, 0xffff5555
+ );
+ } else if (applicable.isEmpty() && !searchRemovedFromApplicable) {
+ Utils.drawStringCentered("No applicable", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchants on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("this page...", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 48, true, 0xffff5555
+ );
+ }
+ if (applicable.isEmpty() && removable.isEmpty() && searchRemovedFromRemovable) {
+ Utils.drawStringCentered("Can't find that", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchant, perhaps", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("it is on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 48, true, 0xffff5555
+ );
+ Utils.drawStringCentered("another page?", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 58, true, 0xffff5555
+ );
+ } else if (removable.isEmpty() && !searchRemovedFromRemovable) {
+ Utils.drawStringCentered("No removable", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchants on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("this page...", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 48, true, 0xffff5555
+ );
+ }
+ }
+ //Available enchants (left)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+
+ if (applicable.size() <= index) break;
+ Enchantment ench = applicable.get(index);
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentEnch != null && enchanterCurrentEnch.enchId.equals(ench.enchId) ? 16 : 0;
+ int uOffset = ench.conflicts ? 112 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 8, top, 96, 16,
+ uOffset / 512f, (96 + uOffset) / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (ench.displayLore != null) {
+ tooltipToDisplay = ench.displayLore;
+ }
+ }
+
+ String levelStr = "" + ench.xpCost;
+ int colour = 0xc8ff8f;
+ if (ench.xpCost > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ ench.enchantName,
+ guiLeft + 8 + 16 + 2 + textOffset,
+ top + 4 + textOffset,
+ 0xffffffdd,
+ true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Removable enchants (right)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+
+ if (removable.size() <= index) break;
+ Enchantment ench = removable.get(index);
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentEnch != null && enchanterCurrentEnch.enchId.equals(ench.enchId) ? 16 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 248, top, 96, 16,
+ 0, 96 / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (ench.displayLore != null) {
+ tooltipToDisplay = ench.displayLore;
+ }
+ }
+
+ String levelStr = "" + ench.xpCost;
+ if (ench.xpCost < 0) levelStr = "?";
+ int colour = 0xc8ff8f;
+ if (ench.xpCost > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(ench.enchantName,
+ guiLeft + 248 + 16 + 2 + textOffset, top + 4 + textOffset, 0xffffffdd, true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Player Inventory Items
+ Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().thePlayer.inventory
+ .getDisplayName()
+ .getUnformattedText(),
+ guiLeft + 102, guiTop + Y_SIZE - 96 + 2, 0x404040
+ );
+ int inventoryStartIndex = cc.getLowerChestInventory().getSizeInventory();
+ GlStateManager.enableDepth();
+ for (int i = 0; i < 36; i++) {
+ int itemX = guiLeft + 102 + 18 * (i % 9);
+ int itemY = guiTop + 133 + 18 * (i / 9);
+
+ if (i >= 27) {
+ itemY += 4;
+ }
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft + 102 - 8, guiTop + 191 - (inventoryStartIndex / 9 * 18 + 89), 0);
+ Slot slot = cc.getSlot(inventoryStartIndex + i);
+ ((AccessorGuiContainer) chest).doDrawSlot(slot);
+ GlStateManager.popMatrix();
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+ hoverLocked = SlotLocking.getInstance().isSlotLocked(slot);
+
+ if (slot.getHasStack()) {
+ tooltipToDisplay = slot.getStack().getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ //Search bar
+ if (currentState == EnchantState.HAS_ITEM) {
+ if (searchField.getText().isEmpty() && !searchField.getFocus()) {
+ searchField.setSize(90, 14);
+ searchField.setPrependText("\u00a77Search...");
+ } else {
+ if (searchField.getFocus()) {
+ int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(searchField.getTextDisplay()) + 10;
+ searchField.setSize(Math.max(90, len), 14);
+ } else {
+ searchField.setSize(90, 14);
+ }
+ searchField.setPrependText("");
+ }
+ searchField.render(guiLeft + X_SIZE / 2 - searchField.getWidth() / 2, guiTop + 83);
+ } else if (currentState == EnchantState.ADDING_ENCHANT &&
+ enchanterCurrentEnch != null && !enchanterEnchLevels.isEmpty()) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ int uOffset = enchanterCurrentEnch.conflicts ? 112 : 0;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left, top, 112, 16,
+ uOffset / 512f, (112 + uOffset) / 512f, 249 / 512f, (249 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (enchanterCurrentEnch.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentEnch.displayLore;
+ }
+ }
+
+ //Enchant cost
+ String levelStr = "" + enchanterCurrentEnch.xpCost;
+ if (enchanterCurrentEnch.xpCost < 0) levelStr = "?";
+
+ int colour = 0xc8ff8f;
+ if (enchanterCurrentEnch.xpCost > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(levelStr, left + 8 - levelWidth / 2, top + 4, colour, false);
+
+ String priceStr = "" + numberFormat.format(enchanterCurrentEnch.price) + " Coins";
+ if (enchanterCurrentEnch.price < 0) priceStr = "";
+ int priceWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(priceStr);
+ int priceTop = guiTop + 16;
+ int x = 180;
+ int color = 0x2d2102;
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2 - 1,
+ priceTop + 4,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2 + 1,
+ priceTop + 4,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4 - 1,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4 + 1,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4,
+ 0xfcba03,
+ false
+ );
+
+ //Enchant name
+ String name = WordUtils.capitalizeFully(ItemUtils
+ .fixEnchantId(enchanterCurrentEnch.enchId, false)
+ .replace("_", " "));
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ } else if (name.equalsIgnoreCase("Luck of the Sea")) {
+ name = "Luck of Sea";
+ } else if (name.equalsIgnoreCase("Turbo Mushrooms")) {
+ name = "Turbo-Mush";
+ }
+ Utils.drawStringCentered(
+ name,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2,
+ top + 8,
+ true,
+ 0xffffffdd
+ );
+
+ if (isChangingEnchLevel) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left + 96, top, 16, 16,
+ 96 / 512f, 112 / 512f, 265 / 512f, (265 + 16) / 512f, GL11.GL_NEAREST
+ );
+ }
+
+ //Enchant level
+ levelStr = "" + enchanterCurrentEnch.level;
+ if (enchanterCurrentEnch.xpCost < 0) levelStr = "?";
+ levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4,
+ 0xea82ff,
+ false
+ );
+
+ //Confirm button
+
+ String confirmText = "Apply";
+ if (removingEnchantPlayerLevel >= 0) {
+ if (removingEnchantPlayerLevel == enchanterCurrentEnch.level) {
+ confirmText = "Remove";
+ } else if (enchanterCurrentEnch.level > removingEnchantPlayerLevel) {
+ confirmText = "Upgrade";
+ } else {
+ confirmText = "Bad Level";
+ }
+ }
+ if (System.currentTimeMillis() - confirmButtonAnimTime < 500 && !(playerXpLevel < enchanterCurrentEnch.xpCost)) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 23, top + 18 + 9, false, 0x408040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 24, top + 18 + 8, false, 0x408040
+ );
+
+ if (playerXpLevel < enchanterCurrentEnch.xpCost) {
+ Gui.drawRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, guiLeft + X_SIZE / 2 - 1, top + 18 + 14, 0x80000000);
+ }
+ }
+
+ //Cancel button
+ if (System.currentTimeMillis() - cancelButtonAnimTime < 500) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 25, top + 18 + 9, false, 0xa04040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 24, top + 18 + 8, false, 0xa04040
+ );
+ }
+
+ if (mouseY > top + 18 && mouseY <= top + 18 + 16) {
+ if (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1) {
+ disallowClick = true;
+ if (enchanterCurrentEnch.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentEnch.displayLore;
+ }
+ } else if (mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48) {
+ disallowClick = true;
+ tooltipToDisplay = Lists.newArrayList("\u00a7cCancel");
+ }
+ }
+
+ //Enchant level switcher
+ if (isChangingEnchLevel) {
+ tooltipToDisplay = null;
+
+ List<Enchantment> before = new ArrayList<>();
+ List<Enchantment> after = new ArrayList<>();
+
+ for (Enchantment ench : enchanterEnchLevels.values()) {
+ if (ench.level < enchanterCurrentEnch.level) {
+ before.add(ench);
+ } else if (ench.level > enchanterCurrentEnch.level) {
+ after.add(ench);
+ }
+ }
+
+ before.sort(Comparator.comparingInt(o -> -o.level));
+ after.sort(Comparator.comparingInt(o -> o.level));
+
+ int bSize = before.size();
+ int aSize = after.size();
+ GlStateManager.disableDepth();
+ for (int i = 0; i < bSize + aSize; i++) {
+ Enchantment ench;
+ int yIndex;
+ if (i < bSize) {
+ ench = before.get(i);
+ yIndex = -i - 1;
+ } else {
+ ench = after.get(i - bSize);
+ yIndex = i - bSize + 1;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+
+ int type = 0;
+ if (i == bSize) {
+ type = 2;
+ } else if (i == 0) {
+ type = 1;
+ }
+
+ if (mouseX > left + 96 && mouseX <= left + 96 + 16 &&
+ mouseY > top + 16 * yIndex && mouseY <= top + 16 * yIndex + 16) {
+ tooltipToDisplay = new ArrayList<>(ench.displayLore);
+ if (tooltipToDisplay.size() > 2) {
+ tooltipToDisplay.remove(tooltipToDisplay.size() - 1);
+ tooltipToDisplay.remove(tooltipToDisplay.size() - 1);
+ }
+ itemHoverX = -1;
+ itemHoverY = -1;
+ }
+
+ Utils.drawTexturedRect(left + 96, top + 16 * yIndex, 16, 16,
+ 16 * type / 512f, (16 + 16 * type) / 512f, 356 / 512f, (356 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ levelStr = "" + ench.level;
+ levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 - 1,
+ top + 16 * yIndex + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 + 1,
+ top + 16 * yIndex + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 16 * yIndex + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 16 * yIndex + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 16 * yIndex + 4,
+ 0xea82ff,
+ false
+ );
+ }
+ GlStateManager.enableDepth();
+ }
+
+ if (mouseX > left + 96 && mouseX <= left + 96 + 16 &&
+ mouseY > top && mouseY <= top + 16) {
+ if (isChangingEnchLevel) {
+ tooltipToDisplay = Lists.newArrayList("\u00a7cCancel level change");
+ } else {
+ tooltipToDisplay = Lists.newArrayList("\u00a7aChange enchant level");
+ }
+ }
+ }
+
+ if (currentState == EnchantState.HAS_ITEM) {
+ renderCancel();
+ }
+
+ //Item enchant input
+ ItemStack itemEnchantInput;
+ if (currentState == EnchantState.HAS_ITEM_IN_HEX) {
+ itemEnchantInput = cc.getSlot(22).getStack();
+ } else {
+ itemEnchantInput = cc.getSlot(19).getStack();
+ }
+ if (itemEnchantInput != null && itemEnchantInput.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ itemEnchantInput = enchantingItem;
+ }
+ {
+ int itemX = guiLeft + 174;
+ int itemY = guiTop + 58;
+
+ if (itemEnchantInput == null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(itemX, itemY, 16, 16,
+ 0, 16 / 512f, 281 / 512f, (281 + 16) / 512f, GL11.GL_NEAREST
+ );
+ } else {
+ Utils.drawItemStack(itemEnchantInput, itemX, itemY);
+ }
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+
+ if (itemEnchantInput != null) {
+ tooltipToDisplay = itemEnchantInput.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (!isChangingEnchLevel && itemHoverX >= 0 && itemHoverY >= 0) {
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Gui.drawRect(itemHoverX, itemHoverY, itemHoverX + 16, itemHoverY + 16,
+ hoverLocked ? 0x80ff8080 : 0x80ffffff
+ );
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableDepth();
+ }
+
+ GlStateManager.translate(0, 0, 300);
+
+ renderOrbAnim(partialTicks);
+
+ renderMouseStack(stackOnMouse, disallowClick, mouseX, mouseY,
+ width, height, tooltipToDisplay
+ );
+ GlStateManager.translate(0, 0, -300);
+ }
+
+ private void renderBooks(float partialTicks) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
+
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ leftScroll.tick();
+ rightScroll.tick();
+ arrowAmount.tick();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ guiLeft = (width - X_SIZE) / 2;
+ guiTop = (height - Y_SIZE) / 2;
+
+ List<String> tooltipToDisplay = null;
+ boolean disallowClick = false;
+ ItemStack stackOnMouse = Minecraft.getMinecraft().thePlayer.inventory.getItemStack();
+ int itemHoverX = -1;
+ int itemHoverY = -1;
+ boolean hoverLocked = false;
+
+ drawGradientRect(0, 0, width, height, 0xc0101010, 0xd0101010);
+
+ renderBaseTexture();
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("Applicable", guiLeft + 7, guiTop + 7, 0x404040, false);
+ Minecraft.getMinecraft().fontRendererObj.drawString("Applied", guiLeft + 247, guiTop + 7, 0x404040, false);
+
+ //Page Text
+ /*if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT) {
+ String pageStr = "Page: " + currentPage + "/" + expectedMaxPage;
+ int pageStrLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(pageStr);
+ Utils.drawStringCentered(pageStr, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 14, false, 0x404040
+ );
+
+ //Page Arrows
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - pageStrLen / 2 - 2 - 15, guiTop + 6, 15, 15,
+ 0, 15 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + pageStrLen / 2 + 2, guiTop + 6, 15, 15,
+ 15 / 512f, 30 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ }*/
+
+ tooltipToDisplay = renderSettings(mouseX, mouseY, tooltipToDisplay);
+
+ renderScrollBars(applicableItem, applicableItem, mouseY);
+
+ //Enchant book model
+ renderEnchantBook(scaledResolution, partialTicks);
+
+ //Can't be enchanted text
+ /*if (currentState == EnchantState.INVALID_ITEM) {
+ GlStateManager.disableDepth();
+ Utils.drawStringCentered("This item can't", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 88, true, 0xffff5555
+ );
+ Utils.drawStringCentered("be enchanted", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 98, true, 0xffff5555
+ );
+ GlStateManager.enableDepth();
+ }*/
+
+ renderArrow();
+
+ //Text if no enchants appear
+ if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT ||
+ currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.ADDING_BOOK) {
+ if (applicableItem.isEmpty() && removableItem.isEmpty() && searchRemovedFromApplicable) {
+ Utils.drawStringCentered("Can't find that", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchant, perhaps", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("it is on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 48, true, 0xffff5555
+ );
+ Utils.drawStringCentered("another page?", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 58, true, 0xffff5555
+ );
+ } else if (applicableItem.isEmpty() && !searchRemovedFromApplicable) {
+ Utils.drawStringCentered("No applicable", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchants on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("this page...", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 8 + 48, guiTop + 48, true, 0xffff5555
+ );
+ }
+ if (applicableItem.isEmpty() && removableItem.isEmpty() && searchRemovedFromRemovable) {
+ Utils.drawStringCentered("Can't find that", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchant, perhaps", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("it is on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 48, true, 0xffff5555
+ );
+ Utils.drawStringCentered("another page?", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 58, true, 0xffff5555
+ );
+ } else if (removableItem.isEmpty() && !searchRemovedFromRemovable) {
+ Utils.drawStringCentered("No removable", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 28, true, 0xffff5555
+ );
+ Utils.drawStringCentered("enchants on", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 38, true, 0xffff5555
+ );
+ Utils.drawStringCentered("this page...", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 248 + 48, guiTop + 48, true, 0xffff5555
+ );
+ }
+ }
+ //Available enchants (left)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+
+ if (applicableItem.size() <= index) break;
+ HexItem item = applicableItem.get(index);
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int uOffset = item.conflicts ? 112 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 8, top, 96, 16,
+ uOffset / 512f, (96 + uOffset) / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ item.itemName,
+ guiLeft + 8 + 16 + 2 + textOffset,
+ top + 4 + textOffset,
+ 0xffffffdd,
+ true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Removable enchants (right)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+
+ if (removableItem.size() <= index) break;
+ HexItem item = removableItem.get(index);
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 248, top, 96, 16,
+ 0, 96 / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ /*if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }*/
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(item.itemName,
+ guiLeft + 248 + 16 + 2 + textOffset, top + 4 + textOffset, 0xffffffdd, true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Player Inventory Items
+ Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().thePlayer.inventory
+ .getDisplayName()
+ .getUnformattedText(),
+ guiLeft + 102, guiTop + Y_SIZE - 96 + 2, 0x404040
+ );
+ int inventoryStartIndex = cc.getLowerChestInventory().getSizeInventory();
+ GlStateManager.enableDepth();
+ for (int i = 0; i < 36; i++) {
+ int itemX = guiLeft + 102 + 18 * (i % 9);
+ int itemY = guiTop + 133 + 18 * (i / 9);
+
+ if (i >= 27) {
+ itemY += 4;
+ }
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft + 102 - 8, guiTop + 191 - (inventoryStartIndex / 9 * 18 + 89), 0);
+ Slot slot = cc.getSlot(inventoryStartIndex + i);
+ ((AccessorGuiContainer) chest).doDrawSlot(slot);
+ GlStateManager.popMatrix();
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+ hoverLocked = SlotLocking.getInstance().isSlotLocked(slot);
+
+ if (slot.getHasStack()) {
+ tooltipToDisplay = slot.getStack().getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ //Search bar
+ if (currentState == EnchantState.HAS_ITEM) {
+ if (searchField.getText().isEmpty() && !searchField.getFocus()) {
+ searchField.setSize(90, 14);
+ searchField.setPrependText("\u00a77Search...");
+ } else {
+ if (searchField.getFocus()) {
+ int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(searchField.getTextDisplay()) + 10;
+ searchField.setSize(Math.max(90, len), 14);
+ } else {
+ searchField.setSize(90, 14);
+ }
+ searchField.setPrependText("");
+ }
+ searchField.render(guiLeft + X_SIZE / 2 - searchField.getWidth() / 2, guiTop + 83);
+ } else if (currentState == EnchantState.ADDING_BOOK &&
+ enchanterCurrentItem != null /*&& !enchanterItemLevels.isEmpty()*/) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ int uOffset = enchanterCurrentItem.conflicts ? 112 : 0;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left, top, 112, 16,
+ uOffset / 512f, (112 + uOffset) / 512f, 249 / 512f, (249 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ }
+
+ String priceStr = "" + numberFormat.format(enchanterCurrentItem.getPrice()) + " Coins";
+ if (enchanterCurrentItem.price < 0) priceStr = "";
+ int priceWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(priceStr);
+ int priceTop = guiTop + 10;
+ int x = 180;
+ int color = 0x2d2102;
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2 - 1,
+ priceTop + 4,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2 + 1,
+ priceTop + 4,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4 - 1,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4 + 1,
+ color,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ priceStr,
+ guiLeft + x - priceWidth / 2,
+ priceTop + 4,
+ 0xfcba03,
+ false
+ );
+
+ //Enchant name
+ String name = WordUtils.capitalizeFully(enchanterCurrentItem.itemId.replace("_", " "));
+ if (name.equalsIgnoreCase("Hot Potato Book")) {
+ name = "Hot Potato";
+ } else if (name.equalsIgnoreCase("Fuming Potato Book")) {
+ name = "Fuming Potato";
+ } else if (name.equalsIgnoreCase("Recombobulator 3000")) {
+ name = "Recombobulator";
+ } else if (name.contains("Power Scroll")) {
+ name = name.replace("Power ", "");
+ } else if (name.contains("\u272a")) {
+ name = name.replaceAll("[^✪]*", "");
+ } else if (name.equalsIgnoreCase("First Master Star")) {
+ name = "Master Star \u00a7c➊";
+ } else if (name.equalsIgnoreCase("Second Master Star")) {
+ name = "Master Star \u00a7c➋";
+ } else if (name.equalsIgnoreCase("Third Master Star")) {
+ name = "Master Star \u00a7c➌";
+ } else if (name.equalsIgnoreCase("Fourth Master Star")) {
+ name = "Master Star \u00a7c➍";
+ } else if (name.equalsIgnoreCase("Fifth Master Star")) {
+ name = "Master Star \u00a7c➎";
+ } else if (name.equalsIgnoreCase("The Art Of Peace")) {
+ name = "Art Of Peace";
+ } else if (name.equalsIgnoreCase("Mana Disintegrator")) {
+ name = "M Disintegrator";
+ }
+ Utils.drawStringCentered(
+ name,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2,
+ top + 8,
+ true,
+ 0xffffffdd
+ );
+
+ //Confirm button
+ String confirmText = "Apply";
+ if (removingEnchantPlayerLevel >= 0) {
+ if (removingEnchantPlayerLevel == enchanterCurrentItem.level) {
+ confirmText = "Remove";
+ } else if (enchanterCurrentItem.level > removingEnchantPlayerLevel) {
+ confirmText = "Upgrade";
+ } else {
+ confirmText = "Bad Level";
+ }
+ }
+ if (System.currentTimeMillis() - confirmButtonAnimTime < 500 && !(playerXpLevel < enchanterCurrentItem.price)) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 23, top + 18 + 9, false, 0x408040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 24, top + 18 + 8, false, 0x408040
+ );
+
+ /*if (playerXpLevel < enchanterCurrentItem.price) {
+ Gui.drawRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, guiLeft + X_SIZE / 2 - 1, top + 18 + 14, 0x80000000);
+ }*/
+ }
+
+ //Cancel button
+ if (System.currentTimeMillis() - cancelButtonAnimTime < 500) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 25, top + 18 + 9, false, 0xa04040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 24, top + 18 + 8, false, 0xa04040
+ );
+ }
+
+ if (mouseY > top + 18 && mouseY <= top + 18 + 16) {
+ if (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ } else if (mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48) {
+ disallowClick = true;
+ tooltipToDisplay = Lists.newArrayList("\u00a7cCancel");
+ }
+ }
+ }
+
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.ADDING_BOOK) {
+ renderCancel();
+ }
+
+ //Item enchant input
+ ItemStack itemEnchantInput;
+ if (currentState == EnchantState.HAS_ITEM_IN_HEX) {
+ itemEnchantInput = cc.getSlot(22).getStack();
+ } else {
+ itemEnchantInput = cc.getSlot(19).getStack();
+ }
+ if (itemEnchantInput != null && itemEnchantInput.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ itemEnchantInput = enchantingItem;
+ }
+ {
+ int itemX = guiLeft + 174;
+ int itemY = guiTop + 58;
+
+ if (itemEnchantInput == null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(itemX, itemY, 16, 16,
+ 0, 16 / 512f, 281 / 512f, (281 + 16) / 512f, GL11.GL_NEAREST
+ );
+ } else {
+ Utils.drawItemStack(itemEnchantInput, itemX, itemY);
+ }
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+
+ if (itemEnchantInput != null) {
+ tooltipToDisplay = itemEnchantInput.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (!isChangingEnchLevel && itemHoverX >= 0 && itemHoverY >= 0) {
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Gui.drawRect(itemHoverX, itemHoverY, itemHoverX + 16, itemHoverY + 16,
+ hoverLocked ? 0x80ff8080 : 0x80ffffff
+ );
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableDepth();
+ }
+
+ GlStateManager.translate(0, 0, 300);
+
+ renderOrbAnim(partialTicks);
+
+ renderMouseStack(stackOnMouse, disallowClick, mouseX, mouseY,
+ width, height, tooltipToDisplay
+ );
+ GlStateManager.translate(0, 0, -300);
+ }
+
+ private void renderHex(float partialTicks) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
+
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ leftScroll.tick();
+ //rightScroll.tick();
+ //arrowAmount.tick();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ guiLeft = (width - X_SIZE) / 2;
+ guiTop = (height - Y_SIZE) / 2;
+
+ List<String> tooltipToDisplay = null;
+ boolean disallowClick = false;
+ ItemStack stackOnMouse = Minecraft.getMinecraft().thePlayer.inventory.getItemStack();
+ int itemHoverX = -1;
+ int itemHoverY = -1;
+ boolean hoverLocked = false;
+
+ drawGradientRect(0, 0, width, height, 0xc0101010, 0xd0101010);
+
+ renderBaseTexture();
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("The Hex", guiLeft + 7, guiTop + 7, 0x404040, false);
+ //Minecraft.getMinecraft().fontRendererObj.drawString("Applied", guiLeft + 247, guiTop + 7, 0x404040, false);
+
+ tooltipToDisplay = renderSettings(mouseX, mouseY, tooltipToDisplay);
+
+ renderScrollBars(applicableItem, applicableItem, mouseY);
+
+ //Enchant book model
+ renderEnchantBook(scaledResolution, partialTicks);
+
+ //Can't be enchanted text
+ if (currentState == EnchantState.INVALID_ITEM_HEX) {
+ GlStateManager.disableDepth();
+ Utils.drawStringCentered("This item can't", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 88, true, 0xffff5555
+ );
+ Utils.drawStringCentered("be enchanted", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 98, true, 0xffff5555
+ );
+ GlStateManager.enableDepth();
+ }
+
+ renderArrow();
+
+ //Available enchants (left)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+
+ if (applicableItem.size() <= index) break;
+ HexItem item = applicableItem.get(index);
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int uOffset = item.conflicts ? 112 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 8, top, 96, 16,
+ uOffset / 512f, (96 + uOffset) / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ item.itemName,
+ guiLeft + 8 + 16 + 2 + textOffset,
+ top + 4 + textOffset,
+ 0xffffffdd,
+ true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Removable enchants (right)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+
+ if (removableItem.size() <= index) break;
+ HexItem item = removableItem.get(index);
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 248, top, 96, 16,
+ 0, 96 / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(item.itemName,
+ guiLeft + 248 + 16 + 2 + textOffset, top + 4 + textOffset, 0xffffffdd, true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Player Inventory Items
+ Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().thePlayer.inventory
+ .getDisplayName()
+ .getUnformattedText(),
+ guiLeft + 102, guiTop + Y_SIZE - 96 + 2, 0x404040
+ );
+ int inventoryStartIndex = cc.getLowerChestInventory().getSizeInventory();
+ GlStateManager.enableDepth();
+ for (int i = 0; i < 36; i++) {
+ int itemX = guiLeft + 102 + 18 * (i % 9);
+ int itemY = guiTop + 133 + 18 * (i / 9);
+
+ if (i >= 27) {
+ itemY += 4;
+ }
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft + 102 - 8, guiTop + 191 - (inventoryStartIndex / 9 * 18 + 89), 0);
+ Slot slot = cc.getSlot(inventoryStartIndex + i);
+ ((AccessorGuiContainer) chest).doDrawSlot(slot);
+ GlStateManager.popMatrix();
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+ hoverLocked = SlotLocking.getInstance().isSlotLocked(slot);
+
+ if (slot.getHasStack()) {
+ tooltipToDisplay = slot.getStack().getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (currentState == EnchantState.ADDING_BOOK &&
+ enchanterCurrentItem != null /*&& !enchanterItemLevels.isEmpty()*/) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ int uOffset = enchanterCurrentItem.conflicts ? 112 : 0;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left, top, 112, 16,
+ uOffset / 512f, (112 + uOffset) / 512f, 249 / 512f, (249 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ }
+
+ if (mouseY > top + 18 && mouseY <= top + 18 + 16) {
+ if (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ } else if (mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48) {
+ disallowClick = true;
+ tooltipToDisplay = Lists.newArrayList("\u00a7cCancel");
+ }
+ }
+ }
+
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.ADDING_BOOK) {
+ renderCancel();
+ }
+
+ //Item enchant input
+ ItemStack itemEnchantInput;
+ if (isInHex()) {
+ itemEnchantInput = cc.getSlot(22).getStack();
+ } else {
+ itemEnchantInput = cc.getSlot(19).getStack();
+ }
+ if (itemEnchantInput != null && itemEnchantInput.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ itemEnchantInput = enchantingItem;
+ }
+ {
+ int itemX = guiLeft + 174;
+ int itemY = guiTop + 58;
+
+ if (itemEnchantInput == null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(itemX, itemY, 16, 16,
+ 0, 16 / 512f, 281 / 512f, (281 + 16) / 512f, GL11.GL_NEAREST
+ );
+ } else {
+ Utils.drawItemStack(itemEnchantInput, itemX, itemY);
+ }
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+
+ if (itemEnchantInput != null) {
+ tooltipToDisplay = itemEnchantInput.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (!isChangingEnchLevel && itemHoverX >= 0 && itemHoverY >= 0) {
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Gui.drawRect(itemHoverX, itemHoverY, itemHoverX + 16, itemHoverY + 16,
+ hoverLocked ? 0x80ff8080 : 0x80ffffff
+ );
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableDepth();
+ }
+
+ GlStateManager.translate(0, 0, 300);
+
+ renderOrbAnim(partialTicks);
+
+ renderMouseStack(stackOnMouse, disallowClick, mouseX, mouseY,
+ width, height, tooltipToDisplay
+ );
+ GlStateManager.translate(0, 0, -300);
+ }
+
+ private void renderGemstones(float partialTicks) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
+
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+
+ leftScroll.tick();
+ rightScroll.tick();
+ arrowAmount.tick();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ guiLeft = (width - X_SIZE) / 2;
+ guiTop = (height - Y_SIZE) / 2;
+
+ List<String> tooltipToDisplay = null;
+ boolean disallowClick = false;
+ ItemStack stackOnMouse = Minecraft.getMinecraft().thePlayer.inventory.getItemStack();
+ int itemHoverX = -1;
+ int itemHoverY = -1;
+ boolean hoverLocked = false;
+
+ drawGradientRect(0, 0, width, height, 0xc0101010, 0xd0101010);
+
+ renderBaseTexture();
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("Applicable", guiLeft + 7, guiTop + 7, 0x404040, false);
+ Minecraft.getMinecraft().fontRendererObj.drawString("Applied", guiLeft + 247, guiTop + 7, 0x404040, false);
+
+ //Page Text
+ if (currentState == EnchantState.ADDING_GEMSTONE || currentState == EnchantState.APPLYING_GEMSTONE) {
+ String pageStr = "Page: " + currentPage + "/" + expectedMaxPage;
+ int pageStrLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(pageStr);
+ Utils.drawStringCentered(pageStr, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2, guiTop + 14, false, 0x404040
+ );
+
+ //Page Arrows
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - pageStrLen / 2 - 2 - 15, guiTop + 6, 15, 15,
+ 0, 15 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + pageStrLen / 2 + 2, guiTop + 6, 15, 15,
+ 15 / 512f, 30 / 512f, 372 / 512f, 387 / 512f, GL11.GL_NEAREST
+ );
+ }
+
+ //Confirm button
+ {
+ int top = guiTop + 83;
+ if (currentState == EnchantState.APPLYING_GEMSTONE) {
+ String confirmText = "Apply";
+ if (removingEnchantPlayerLevel >= 0) {
+ if (removingEnchantPlayerLevel == enchanterCurrentItem.level) {
+ confirmText = "Remove";
+ } else if (enchanterCurrentItem.level > removingEnchantPlayerLevel) {
+ confirmText = "Upgrade";
+ } else {
+ confirmText = "Bad Level";
+ }
+ }
+ if (System.currentTimeMillis() - confirmButtonAnimTime < 500) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 23, top + 18 + 9, false, 0x408040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered(confirmText, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 - 1 - 24, top + 18 + 8, false, 0x408040
+ );
+ }
+ }
+
+ //Cancel button
+
+ if (System.currentTimeMillis() - cancelButtonAnimTime < 500) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 25, top + 18 + 9, false, 0xa04040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 24, top + 18 + 8, false, 0xa04040
+ );
+ }
+ }
+
+ tooltipToDisplay = renderSettings(mouseX, mouseY, tooltipToDisplay);
+
+ renderScrollBars(applicableItem, applicableItem, mouseY);
+
+ //Enchant book model
+ renderEnchantBook(scaledResolution, partialTicks);
+
+ renderArrow();
+
+ //Available enchants (left)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+
+ if (applicableItem.size() <= index) break;
+ HexItem item = applicableItem.get(index);
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int uOffset = item.conflicts ? 112 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 8, top, 96, 16,
+ uOffset / 512f, (96 + uOffset) / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 16 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ item.itemName,
+ guiLeft + 8 + 16 + 2 + textOffset,
+ top + 4 + textOffset,
+ 0xffffffdd,
+ true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Removable enchants (right)
+ GlScissorStack.push(0, guiTop + 18, width, guiTop + 18 + 96, scaledResolution);
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+
+ if (removableItem.size() <= index) break;
+ HexItem item = removableItem.get(index);
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ int vOffset = enchanterCurrentItem != null && enchanterCurrentItem.itemId.equals(item.itemId) ? 16 : 0;
+ int textOffset = vOffset / 16;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 248, top, 96, 16,
+ 0, 96 / 512f, (249 + vOffset) / 512f, (249 + 16 + vOffset) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (item.displayLore != null) {
+ tooltipToDisplay = item.displayLore;
+ }
+ }
+
+ String levelStr = getIconStr(item);
+ int colour = 0xc8ff8f;
+ if (item.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ guiLeft + 256 - levelWidth / 2,
+ top + 4,
+ colour,
+ false
+ );
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(item.itemName,
+ guiLeft + 248 + 16 + 2 + textOffset, top + 4 + textOffset, 0xffffffdd, true
+ );
+ }
+ GlScissorStack.pop(scaledResolution);
+
+ //Player Inventory Items
+ Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().thePlayer.inventory
+ .getDisplayName()
+ .getUnformattedText(),
+ guiLeft + 102, guiTop + Y_SIZE - 96 + 2, 0x404040
+ );
+ int inventoryStartIndex = cc.getLowerChestInventory().getSizeInventory();
+ GlStateManager.enableDepth();
+ for (int i = 0; i < 36; i++) {
+ int itemX = guiLeft + 102 + 18 * (i % 9);
+ int itemY = guiTop + 133 + 18 * (i / 9);
+
+ if (i >= 27) {
+ itemY += 4;
+ }
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft + 102 - 8, guiTop + 191 - (inventoryStartIndex / 9 * 18 + 89), 0);
+ Slot slot = cc.getSlot(inventoryStartIndex + i);
+ ((AccessorGuiContainer) chest).doDrawSlot(slot);
+ GlStateManager.popMatrix();
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+ hoverLocked = SlotLocking.getInstance().isSlotLocked(slot);
+
+ if (slot.getHasStack()) {
+ tooltipToDisplay = slot.getStack().getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (currentState == EnchantState.APPLYING_GEMSTONE &&
+ enchanterCurrentItem != null /*&& !enchanterItemLevels.isEmpty()*/) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ int uOffset = enchanterCurrentItem.conflicts ? 112 : 0;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left, top, 112, 16,
+ uOffset / 512f, (112 + uOffset) / 512f, 249 / 512f, (249 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ }
+
+ if (mouseY > top + 18 && mouseY <= top + 18 + 16) {
+ if (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1) {
+ disallowClick = true;
+ if (enchanterCurrentItem.displayLore != null) {
+ tooltipToDisplay = enchanterCurrentItem.displayLore;
+ }
+ } else if (mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48) {
+ disallowClick = true;
+ tooltipToDisplay = Lists.newArrayList("\u00a7cCancel");
+ }
+ }
+ }
+
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.ADDING_BOOK) {
+ renderCancel();
+ }
+
+ //Item enchant input
+ ItemStack itemEnchantInput;
+ if (isInHex()) {
+ itemEnchantInput = cc.getSlot(22).getStack();
+ } else {
+ itemEnchantInput = cc.getSlot(19).getStack();
+ }
+ if (itemEnchantInput != null && itemEnchantInput.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane)) {
+ itemEnchantInput = enchantingItem;
+ }
+ {
+ int itemX = guiLeft + 174;
+ int itemY = guiTop + 58;
+
+ if (itemEnchantInput == null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(itemX, itemY, 16, 16,
+ 0, 16 / 512f, 281 / 512f, (281 + 16) / 512f, GL11.GL_NEAREST
+ );
+ } else {
+ Utils.drawItemStack(itemEnchantInput, itemX, itemY);
+ }
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ itemHoverX = itemX;
+ itemHoverY = itemY;
+
+ if (itemEnchantInput != null) {
+ tooltipToDisplay = itemEnchantInput.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+
+ if (currentState == EnchantState.APPLYING_GEMSTONE) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+ //Enchant cost
+ String levelStr = getIconStr(enchanterCurrentItem);
+
+ int colour = 0xc8ff8f;
+ if (enchanterCurrentItem.price > playerXpLevel) {
+ colour = 0xff5555;
+ }
+
+ int levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 8 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(levelStr, left + 8 - levelWidth / 2, top + 4, colour, false);
+
+ //Enchant name
+ String name = WordUtils.capitalizeFully(enchanterCurrentItem.itemName);
+ if (name.equalsIgnoreCase("Bane of Arthropods")) {
+ name = "Bane of Arth.";
+ } else if (name.equalsIgnoreCase("Projectile Protection")) {
+ name = "Projectile Prot";
+ } else if (name.equalsIgnoreCase("Blast Protection")) {
+ name = "Blast Prot";
+ } else if (name.equalsIgnoreCase("Luck of the Sea")) {
+ name = "Luck of Sea";
+ } else if (name.equalsIgnoreCase("Turbo Mushrooms")) {
+ name = "Turbo-Mush";
+ }
+ Utils.drawStringCentered(
+ name,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2,
+ top + 8,
+ true,
+ 0xffffffdd
+ );
+
+ if (isChangingEnchLevel) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(left + 96, top, 16, 16,
+ 96 / 512f, 112 / 512f, 265 / 512f, (265 + 16) / 512f, GL11.GL_NEAREST
+ );
+ }
+
+ //Enchant level
+ levelStr = "";
+ levelWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(levelStr);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 - 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2 + 1,
+ top + 4,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4 - 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4 + 1,
+ 0x2d2102,
+ false
+ );
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ levelStr,
+ left + 96 + 8 - levelWidth / 2,
+ top + 4,
+ 0xea82ff,
+ false
+ );
+ }
+
+ if (!isChangingEnchLevel && itemHoverX >= 0 && itemHoverY >= 0) {
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Gui.drawRect(itemHoverX, itemHoverY, itemHoverX + 16, itemHoverY + 16,
+ hoverLocked ? 0x80ff8080 : 0x80ffffff
+ );
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableDepth();
+ }
+
+ GlStateManager.translate(0, 0, 300);
+
+ renderOrbAnim(partialTicks);
+
+ renderMouseStack(stackOnMouse, disallowClick, mouseX, mouseY,
+ width, height, tooltipToDisplay
+ );
+ GlStateManager.translate(0, 0, -300);
+ }
+
+ private String getIconStr(HexItem item) {
+ String levelStr = "";
+ if (item.itemType != ItemType.UNKNOWN) {
+ int potatoCount = 0;
+ int killCount = 0;
+ int warCount = 0;
+ int ffdCount = 0;
+ int recombCount = 0;
+ int effLevel = 0;
+ int starCount = 0;
+ int singularityCount = 0;
+ int tunerCount = 0;
+ int manaDisintegratorCount = 0;
+ int peaceCount = 0;
+ int dungeonItem = 0;
+ boolean shadowWarp = false;
+ boolean witherShield = false;
+ boolean implosion = false;
+ String reforge = "";
+ if (enchantingItem != null) {
+ NBTTagCompound tagItem = enchantingItem.getTagCompound();
+ if (tagItem != null) {
+ NBTTagCompound ea = tagItem.getCompoundTag("ExtraAttributes");
+ if (ea != null) {
+ potatoCount = ea.getInteger("hot_potato_count");
+ killCount = ea.getInteger("stats_book");
+ warCount = ea.getInteger("art_of_war_count");
+ ffdCount = ea.getInteger("farming_for_dummies_count");
+ recombCount = ea.getInteger("rarity_upgrades");
+ starCount = ea.getInteger("upgrade_level");
+ singularityCount = ea.getInteger("wood_singularity_count");
+ tunerCount = ea.getInteger("tuned_transmission");
+ peaceCount = ea.getInteger("art_of_peace_count");
+ manaDisintegratorCount = ea.getInteger("mana_disintegrator_count");
+ dungeonItem = ea.getInteger("dungeon_item");
+ reforge = ea.getString("modifier");
+ NBTTagCompound enchs = ea.getCompoundTag("enchantments");
+ NBTTagList scrolls = ea.getTagList("ability_scroll", 8);
+ if (enchs != null) {
+ effLevel = enchs.getInteger("efficiency");
+ }
+ if (scrolls != null) {
+ for (int index = 0; index < scrolls.tagCount(); index++) {
+ if (scrolls.getStringTagAt(index).equals("IMPLOSION_SCROLL")) {
+ implosion = true;
+ } else if (scrolls.getStringTagAt(index).equals("SHADOW_WARP_SCROLL")) {
+ shadowWarp = true;
+ } else if (scrolls.getStringTagAt(index).equals("WITHER_SHIELD_SCROLL")) {
+ witherShield = true;
+ }
+ }
+ }
+ }
+ }
+ }
+ if (item.itemType == ItemType.HOT_POTATO) {
+ if (potatoCount < 10) levelStr = "" + potatoCount;
+ else levelStr = "✔";
+
+ } else if (item.itemType == ItemType.FUMING_POTATO) {
+ if (potatoCount <= 10) levelStr = "" + 0;
+ else if (potatoCount < 15) levelStr = "" + (potatoCount - 10);
+ else levelStr = "✔";
+
+ } else if (item.itemType == ItemType.BOOK_OF_STATS) {
+ if (killCount > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.ART_OF_WAR) {
+ if (warCount > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.FARMING_DUMMY) {
+ if (ffdCount < 5) levelStr = "" + ffdCount;
+ else levelStr = "✔";
+
+ } else if (item.itemType == ItemType.RECOMB) {
+ if (recombCount > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.SILEX) {
+ if (effLevel < 10) levelStr = "✖";
+ else levelStr = "✔";
+
+ } else if (item.isPowerScroll()) {
+ levelStr = "✖";
+
+ } else if (item.isMasterStar()) {
+ levelStr = "✖";
+
+ } else if (item.isDungeonStar()) {
+ if (starCount >= item.itemType.getStarLevel()) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.WOOD_SINGULARITY) {
+ if (singularityCount > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.isHypeScroll()) {
+ if (shadowWarp) levelStr = "✔";
+ else if (implosion) levelStr = "✔";
+ else if (witherShield) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.TUNER) {
+ if (tunerCount >= 4) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.REFORGE) {
+ if (item.getReforge().equalsIgnoreCase(reforge)) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.RANDOM_REFORGE) {
+ levelStr = "?";
+
+ } else if (item.itemType == ItemType.ART_OF_PEACE) {
+ if (peaceCount > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.MANA_DISINTEGRATOR) {
+ if (manaDisintegratorCount >= 10) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.CONVERT_TO_DUNGEON) {
+ if (dungeonItem > 0) levelStr = "✔";
+ else levelStr = "✖";
+
+ } else if (item.itemType == ItemType.RUBY_GEMSTONE) {
+ levelStr = "❤";
+
+ } else if (item.itemType == ItemType.AMETHYST_GEMSTONE) {
+ levelStr = "❈";
+
+ } else if (item.itemType == ItemType.SAPPHIRE_GEMSTONE) {
+ levelStr = "✎";
+
+ } else if (item.itemType == ItemType.JADE_GEMSTONE) {
+ levelStr = "☘";
+
+ } else if (item.itemType == ItemType.AMBER_GEMSTONE) {
+ levelStr = "⸕";
+
+ } else if (item.itemType == ItemType.TOPAZ_GEMSTONE) {
+ levelStr = "✧";
+
+ } else if (item.itemType == ItemType.JASPER_GEMSTONE) {
+ levelStr = "❁";
+
+ } else if (item.itemType == ItemType.OPAL_GEMSTONE) {
+ levelStr = "❂";
+ }
+ } else {
+ levelStr = "?";
+ }
+ return levelStr;
+ }
+
+ private void renderBaseTexture() {
+ //Base Texture
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft, guiTop, X_SIZE, Y_SIZE,
+ 0, X_SIZE / 512f, 0, Y_SIZE / 512f, GL11.GL_NEAREST
+ );
+ }
+
+ private List<String> renderSettings(int mouseX, int mouseY, List<String> tooltipToDisplay) {
+ //Settings Buttons
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ //On Settings Button
+ Utils.drawTexturedRect(guiLeft + 295, guiTop + 147, 16, 16,
+ 0, 16 / 512f, 387 / 512f, (387 + 16) / 512f, GL11.GL_NEAREST
+ );
+ //Sorting Settings Button
+ float sortingMinU = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantSorting * 16 / 512f;
+ Utils.drawTexturedRect(guiLeft + 295, guiTop + 147 + 18, 16, 16,
+ sortingMinU, sortingMinU + 16 / 512f, 419 / 512f, (419 + 16) / 512f, GL11.GL_NEAREST
+ );
+ //Ordering Settings Button
+ float orderingMinU = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantOrdering * 16 / 512f;
+ Utils.drawTexturedRect(guiLeft + 295 + 18, guiTop + 147 + 18, 16, 16,
+ orderingMinU, orderingMinU + 16 / 512f, 435 / 512f, (435 + 16) / 512f, GL11.GL_NEAREST
+ );
+
+ if (mouseX >= guiLeft + 294 && mouseX < guiLeft + 294 + 36 &&
+ mouseY >= guiTop + 146 && mouseY < guiTop + 146 + 36) {
+ int index = (mouseX - (guiLeft + 295)) / 18 + (mouseY - (guiTop + 147)) / 18 * 2;
+ switch (index) {
+ case 0:
+ Gui.drawRect(guiLeft + 295, guiTop + 147, guiLeft + 295 + 16, guiTop + 147 + 16, 0x80ffffff);
+ tooltipToDisplay = createTooltip("Enable GUI", 0, "On", "Off");
+ break;
+ case 1:
+ Gui.drawRect(guiLeft + 295 + 18, guiTop + 147, guiLeft + 295 + 16 + 18, guiTop + 147 + 16, 0x80ffffff);
+ tooltipToDisplay = createTooltip("Max Level",
+ (NotEnoughUpdates.INSTANCE.config.enchantingSolvers.maxEnchLevel ? 0 : 1),
+ "Enabled", "Disabled");
+ tooltipToDisplay.add(1, EnumChatFormatting.GRAY + "Show max level of enchant");
+ tooltipToDisplay.add(2, EnumChatFormatting.GRAY + "from either hex or enchantment table");
+ tooltipToDisplay.add(3, EnumChatFormatting.GRAY + "max level");
+ break;
+ case 2:
+ Gui.drawRect(guiLeft + 295, guiTop + 147 + 18, guiLeft + 295 + 16, guiTop + 147 + 16 + 18, 0x80ffffff);
+ tooltipToDisplay = createTooltip("Sort enchants...",
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantSorting,
+ "By Cost", "Alphabetically"
+ );
+ break;
+ case 3:
+ Gui.drawRect(
+ guiLeft + 295 + 18,
+ guiTop + 147 + 18,
+ guiLeft + 295 + 16 + 18,
+ guiTop + 147 + 16 + 18,
+ 0x80ffffff
+ );
+ tooltipToDisplay = createTooltip("Order enchants...",
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantOrdering,
+ "Ascending", "Descending"
+ );
+ break;
+ }
+ }
+ return tooltipToDisplay;
+ }
+
+ private void renderScrollBars(List applicable, List removable, int mouseY) {
+ //Left scroll bar
+ {
+ int offset;
+ if (applicable.size() <= 6) {
+ offset = 0;
+ } else if (isScrollingLeft && clickedScrollOffset >= 0) {
+ offset = mouseY - clickedScrollOffset;
+ if (offset < 0) offset = 0;
+ if (offset > 96 - 15) offset = 96 - 15;
+ } else {
+ offset = Math.round((96 - 15) * (leftScroll.getValue() / (float) ((applicable.size() - 6) * 16)));
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 104, guiTop + 18 + offset, 12, 15,
+ 0, 12 / 512f, 313 / 512f, (313 + 15) / 512f, GL11.GL_NEAREST
+ );
+ }
+ //Right scroll bar
+ {
+ int offset;
+ if (removable.size() <= 6) {
+ offset = 0;
+ } else if (!isScrollingLeft && clickedScrollOffset >= 0) {
+ offset = mouseY - clickedScrollOffset;
+ if (offset < 0) offset = 0;
+ if (offset > 96 - 15) offset = 96 - 15;
+ } else {
+ offset = Math.round((96 - 15) * (rightScroll.getValue() / (float) ((removable.size() - 6) * 16)));
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 344, guiTop + 18 + offset, 12, 15,
+ 0, 12 / 512f, 313 / 512f, (313 + 15) / 512f, GL11.GL_NEAREST
+ );
+ }
+ }
+
+ private void renderArrow() {
+ //Enchant arrow
+ if (arrowAmount.getValue() > 0) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ float w = 22 * arrowAmount.getValue();
+ if (removingEnchantPlayerLevel < 0) {
+ Utils.drawTexturedRect(guiLeft + 134, guiTop + 58, w, 16,
+ 0, w / 512f, 297 / 512f, (297 + 16) / 512f, GL11.GL_NEAREST
+ );
+ } else {
+ Utils.drawTexturedRect(guiLeft + 230 - w, guiTop + 58, w, 16,
+ (44 - w) / 512f, 44 / 512f, 297 / 512f, (297 + 16) / 512f, GL11.GL_NEAREST
+ );
+ }
+ }
+ }
+
+ private void renderCancel() {
+ int top = guiTop + 83;
+ //Cancel button
+ if (System.currentTimeMillis() - cancelButtonAnimTime < 500) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 342 / 512f, (342 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 25, top + 18 + 9, false, 0xa04040
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawStringCentered("Cancel", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + X_SIZE / 2 + 1 + 24, top + 18 + 8, false, 0xa04040
+ );
+ }
+ }
+
+ private void renderOrbAnim(float partialTicks) {
+ //Orb animation
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(guiLeft, guiTop, 0);
+ orbDisplay.renderOrbs(partialTicks);
+ GlStateManager.popMatrix();
+ }
+
+ private void renderMouseStack(
+ ItemStack stackOnMouse, boolean disallowClick,
+ int mouseX, int mouseY, int width, int height,
+ List<String> tooltipToDisplay
+ ) {
+ if (stackOnMouse != null) {
+ if (disallowClick) {
+ Utils.drawItemStack(new ItemStack(Item.getItemFromBlock(Blocks.barrier)), mouseX - 8, mouseY - 8);
+ } else {
+ Utils.drawItemStack(stackOnMouse, mouseX - 8, mouseY - 8);
+ }
+ } else if (tooltipToDisplay != null) {
+ Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+
+ private void renderEnchantBook(ScaledResolution scaledresolution, float partialTicks) {
+ GlStateManager.enableDepth();
+
+ GlStateManager.pushMatrix();
+ GlStateManager.matrixMode(5889);
+ GlStateManager.pushMatrix();
+ GlStateManager.loadIdentity();
+ GlStateManager.viewport((scaledresolution.getScaledWidth() - 320) / 2 * scaledresolution.getScaleFactor(),
+ (scaledresolution.getScaledHeight() - 240) / 2 * scaledresolution.getScaleFactor(),
+ 320 * scaledresolution.getScaleFactor(), 240 * scaledresolution.getScaleFactor()
+ );
+ GlStateManager.translate(0.0F, 0.33F, 0.0F);
+ Project.gluPerspective(90.0F, 1.3333334F, 9.0F, 80.0F);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ RenderHelper.enableStandardItemLighting();
+ GlStateManager.translate(0.0F, 3.3F, -16.0F);
+ GlStateManager.scale(5, 5, 5);
+ GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(ENCHANTMENT_TABLE_BOOK_TEXTURE);
+ GlStateManager.rotate(20.0F, 1.0F, 0.0F, 0.0F);
+ float bookOpenAngle = this.bookOpenLast + (this.bookOpen - this.bookOpenLast) * partialTicks;
+ GlStateManager.translate(
+ (1.0F - bookOpenAngle) * 0.2F,
+ (1.0F - bookOpenAngle) * 0.1F,
+ (1.0F - bookOpenAngle) * 0.25F
+ );
+ GlStateManager.rotate(-(1.0F - bookOpenAngle) * 90.0F - 90.0F, 0.0F, 1.0F, 0.0F);
+ GlStateManager.rotate(180.0F, 1.0F, 0.0F, 0.0F);
+ float pageAngle1 = this.pageOpenLast + (this.pageOpen - this.pageOpenLast) * partialTicks + 0.25F;
+ float pageAngle2 = this.pageOpenLast + (this.pageOpen - this.pageOpenLast) * partialTicks + 0.75F;
+ pageAngle1 = (pageAngle1 - (float) MathHelper.truncateDoubleToInt(pageAngle1)) * 1.6F - 0.3F;
+ pageAngle2 = (pageAngle2 - (float) MathHelper.truncateDoubleToInt(pageAngle2)) * 1.6F - 0.3F;
+
+ if (pageAngle1 < 0.0F) pageAngle1 = 0.0F;
+ if (pageAngle1 > 1.0F) pageAngle1 = 1.0F;
+ if (pageAngle2 < 0.0F) pageAngle2 = 0.0F;
+ if (pageAngle2 > 1.0F) pageAngle2 = 1.0F;
+
+ GlStateManager.enableRescaleNormal();
+ MODEL_BOOK.render(null, 0.0F, pageAngle1, pageAngle2, bookOpenAngle, 0.0F, 0.0625F);
+ GlStateManager.disableRescaleNormal();
+ RenderHelper.disableStandardItemLighting();
+ GlStateManager.matrixMode(5889);
+ GlStateManager.viewport(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
+ GlStateManager.popMatrix();
+ GlStateManager.matrixMode(5888);
+ GlStateManager.popMatrix();
+ RenderHelper.disableStandardItemLighting();
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+
+ GlStateManager.enableDepth();
+ }
+
+ private boolean isInEnchanting() {
+ return currentState == EnchantState.ADDING_ENCHANT || currentState == EnchantState.HAS_ITEM ||
+ currentState == EnchantState.SWITCHING_DONT_UPDATE;
+ }
+
+ private boolean isInHex() {
+ return currentState == EnchantState.HAS_ITEM_IN_HEX || currentState == EnchantState.INVALID_ITEM_HEX ||
+ currentState == EnchantState.NO_ITEM_IN_HEX;
+ }
+
+ private boolean isInGemstones() {
+ return currentState == EnchantState.HAS_ITEM_IN_GEMSTONE || currentState == EnchantState.ADDING_GEMSTONE ||
+ currentState == EnchantState.APPLYING_GEMSTONE;
+ }
+
+ public void overrideIsMouseOverSlot(Slot slot, int mouseX, int mouseY, CallbackInfoReturnable<Boolean> cir) {
+ if ((shouldOverrideFast || shouldOverrideGemstones || shouldOverrideXp) &&
+ currentState != EnchantState.ADDING_ENCHANT) {
+ boolean playerInv = slot.inventory == Minecraft.getMinecraft().thePlayer.inventory;
+ int slotId = slot.getSlotIndex();
+ if (playerInv && slotId < 36) {
+ slotId -= 9;
+ if (slotId < 0) slotId += 36;
+
+ int itemX = guiLeft + 102 + 18 * (slotId % 9);
+ int itemY = guiTop + 133 + 18 * (slotId / 9);
+
+ if (slotId >= 27) {
+ itemY += 4;
+ }
+
+ if (mouseX >= itemX && mouseX < itemX + 18 &&
+ mouseY >= itemY && mouseY < itemY + 18) {
+ cir.setReturnValue(true);
+ } else {
+ cir.setReturnValue(false);
+ }
+ } else if ((slotId == 19 && !isInHex()) || (slotId == 22 && isInHex())) {
+ cir.setReturnValue(mouseX >= guiLeft + 173 && mouseX < guiLeft + 173 + 18 &&
+ mouseY >= guiTop + 57 && mouseY < guiTop + 57 + 18);
+ }
+ }
+ }
+
+ public boolean mouseInput(int mouseX, int mouseY) {
+ if (Mouse.getEventButtonState() &&
+ (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.ADDING_ENCHANT ||
+ currentState == EnchantState.HAS_ITEM_IN_HEX || currentState == EnchantState.ADDING_BOOK ||
+ currentState == EnchantState.ADDING_GEMSTONE || currentState == EnchantState.APPLYING_GEMSTONE)) {
+ if (mouseY > guiTop + 6 && mouseY < guiTop + 6 + 15) {
+ String pageStr = "Page: " + currentPage + "/" + expectedMaxPage;
+ int pageStrLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(pageStr);
+
+ int click = -1;
+ if (mouseX > guiLeft + X_SIZE / 2 - pageStrLen / 2 - 2 - 15 &&
+ mouseX <= guiLeft + X_SIZE / 2 - pageStrLen / 2 - 2) {
+ click = 17;
+ } else if (mouseX > guiLeft + X_SIZE / 2 + pageStrLen / 2 + 2 &&
+ mouseX <= guiLeft + X_SIZE / 2 + pageStrLen / 2 + 2 + 15) {
+ click = 35;
+ }
+
+ if (click >= 0) {
+ if (currentState == EnchantState.ADDING_ENCHANT || currentState == EnchantState.ADDING_BOOK) {
+ if (Mouse.getEventButtonState()) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ }
+ } else {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(click);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, click, 0, 0, stack, transactionID));
+ }
+ return true;
+ }
+ }
+ }
+
+ // Cancel button
+ if (currentState == EnchantState.HAS_ITEM ||
+ currentState == EnchantState.HAS_ITEM_IN_BOOKS || currentState == EnchantState.HAS_ITEM_IN_GEMSTONE) {
+ if (Mouse.getEventButtonState()) {
+ int top = guiTop + 83;
+
+ if (!isChangingEnchLevel && mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ leftScroll.setValue(0);
+ rightScroll.setValue(0);
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState != EnchantState.ADDING_BOOK) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+ if (isInGemstones()) {
+ currentState = EnchantState.HAS_ITEM_IN_GEMSTONE;
+ }
+ } else {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ }
+ searchField.setText("");
+ cancelButtonAnimTime = System.currentTimeMillis();
+ enchanterCurrentItem = null;
+ }
+
+ if (mouseX > guiLeft + X_SIZE / 2 - searchField.getWidth() / 2 &&
+ mouseX < guiLeft + X_SIZE / 2 + searchField.getWidth() / 2 &&
+ mouseY > guiTop + 80 && mouseY < guiTop + 96) {
+ searchField.mouseClicked(mouseX, mouseY, Mouse.getEventButton());
+ } else {
+ searchField.setFocus(false);
+ }
+ } else if (Mouse.getEventButton() < 0 && searchField.getFocus() && Mouse.isButtonDown(0)) {
+ searchField.mouseClickMove(mouseX, mouseY, 0, 0);
+ }
+ } else if (currentState == EnchantState.ADDING_ENCHANT && !enchanterEnchLevels.isEmpty()) {
+ if (Mouse.getEventButtonState()) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+
+ if (!isChangingEnchLevel && mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ } else if (!isChangingEnchLevel && enchanterCurrentEnch != null &&
+ (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) ||
+ (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14)) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(
+ enchanterCurrentEnch.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ enchanterCurrentEnch.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ int playerXpLevel = Minecraft.getMinecraft().thePlayer.experienceLevel;
+ if (playerXpLevel >= enchanterCurrentEnch.xpCost) {
+ if (removingEnchantPlayerLevel >= 0 && enchanterCurrentEnch.level == removingEnchantPlayerLevel) {
+ orbDisplay.spawnExperienceOrbs(X_SIZE / 2, 66, X_SIZE / 2, 36, 3);
+ } else {
+ orbDisplay.spawnExperienceOrbs(mouseX - guiLeft, mouseY - guiTop, X_SIZE / 2, 66, 0);
+ }
+ }
+
+ confirmButtonAnimTime = System.currentTimeMillis();
+ } else if (mouseX > left + 96 && mouseX <= left + 96 + 16) {
+ if (!isChangingEnchLevel) {
+ if (mouseY > top && mouseY < top + 16) {
+ isChangingEnchLevel = true;
+ return true;
+ }
+ } else {
+ List<Enchantment> before = new ArrayList<>();
+ List<Enchantment> after = new ArrayList<>();
+
+ for (Enchantment ench : enchanterEnchLevels.values()) {
+ if (ench.level < enchanterCurrentEnch.level) {
+ before.add(ench);
+ } else if (ench.level > enchanterCurrentEnch.level) {
+ after.add(ench);
+ }
+ }
+
+ before.sort(Comparator.comparingInt(o -> -o.level));
+ after.sort(Comparator.comparingInt(o -> o.level));
+
+ int bSize = before.size();
+ int aSize = after.size();
+ for (int i = 0; i < bSize + aSize; i++) {
+ Enchantment ench;
+ int yIndex;
+ if (i < bSize) {
+ yIndex = -i - 1;
+ ench = before.get(i);
+ } else {
+ yIndex = i - bSize + 1;
+ ench = after.get(i - bSize);
+ }
+
+ if (mouseY > top + 16 * yIndex && mouseY <= top + 16 * yIndex + 16) {
+ enchanterCurrentEnch = ench;
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ }
+ }
+
+ if (isChangingEnchLevel) {
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.ADDING_BOOK) {
+ if (Mouse.getEventButtonState()) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+
+ if (!isChangingEnchLevel && mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ /*GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));*/
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchanterCurrentItem = null;
+ } else if (!isChangingEnchLevel && enchanterCurrentItem != null &&
+ (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) ||
+ (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14)) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(
+ enchanterCurrentItem.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ enchanterCurrentItem.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ if (removingEnchantPlayerLevel >= 0 && enchanterCurrentItem.level == removingEnchantPlayerLevel) {
+ orbDisplay.spawnExperienceOrbs(X_SIZE / 2, 66, X_SIZE / 2, 36, 3);
+ } else {
+ orbDisplay.spawnExperienceOrbs(mouseX - guiLeft, mouseY - guiTop, X_SIZE / 2, 66, 0);
+ }
+
+ confirmButtonAnimTime = System.currentTimeMillis();
+ enchanterCurrentItem = null;
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ } else if (mouseX > left + 96 && mouseX <= left + 96 + 16) {
+ if (!isChangingEnchLevel) {
+ if (mouseY > top && mouseY < top + 16) {
+ isChangingEnchLevel = true;
+ return true;
+ }
+ } else {
+ List<HexItem> before = new ArrayList<>();
+ List<HexItem> after = new ArrayList<>();
+
+ for (HexItem item : enchanterItemLevels.values()) {
+ if (item.level < enchanterCurrentItem.level) {
+ before.add(item);
+ } else if (item.level > enchanterCurrentItem.level) {
+ after.add(item);
+ }
+ }
+
+ before.sort(Comparator.comparingInt(o -> -o.level));
+ after.sort(Comparator.comparingInt(o -> o.level));
+
+ int bSize = before.size();
+ int aSize = after.size();
+ for (int i = 0; i < bSize + aSize; i++) {
+ HexItem item;
+ int yIndex;
+ if (i < bSize) {
+ yIndex = -i - 1;
+ item = before.get(i);
+ } else {
+ yIndex = i - bSize + 1;
+ item = after.get(i - bSize);
+ }
+
+ if (mouseY > top + 16 * yIndex && mouseY <= top + 16 * yIndex + 16) {
+ enchanterCurrentItem = item;
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ }
+ }
+
+ if (isChangingEnchLevel) {
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.HAS_ITEM_IN_HEX) {
+ if (Mouse.getEventButtonState()) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+
+ if (!isChangingEnchLevel && mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) {
+ /*if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchanterCurrentItem = null;*/
+ } else if (!isChangingEnchLevel && enchanterCurrentItem != null &&
+ (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) ||
+ (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14)) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(
+ enchanterCurrentItem.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ enchanterCurrentItem.slotIndex, 0, 0, stack, transactionID
+ ));
+ enchantingItem = null;
+ if (removingEnchantPlayerLevel >= 0 && enchanterCurrentItem.level == removingEnchantPlayerLevel) {
+ orbDisplay.spawnExperienceOrbs(X_SIZE / 2, 66, X_SIZE / 2, 36, 3);
+ } else {
+ orbDisplay.spawnExperienceOrbs(mouseX - guiLeft, mouseY - guiTop, X_SIZE / 2, 66, 0);
+ }
+
+ confirmButtonAnimTime = System.currentTimeMillis();
+ //enchanterCurrentItem = null;
+ //currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ } else if (mouseX > left + 96 && mouseX <= left + 96 + 16) {
+ if (!isChangingEnchLevel) {
+ if (mouseY > top && mouseY < top + 16) {
+ isChangingEnchLevel = true;
+ return true;
+ }
+ } else {
+ List<HexItem> before = new ArrayList<>();
+ List<HexItem> after = new ArrayList<>();
+
+ for (HexItem item : enchanterItemLevels.values()) {
+ if (item.level < enchanterCurrentItem.level) {
+ before.add(item);
+ } else if (item.level > enchanterCurrentItem.level) {
+ after.add(item);
+ }
+ }
+
+ before.sort(Comparator.comparingInt(o -> -o.level));
+ after.sort(Comparator.comparingInt(o -> o.level));
+
+ int bSize = before.size();
+ int aSize = after.size();
+ for (int i = 0; i < bSize + aSize; i++) {
+ HexItem item;
+ int yIndex;
+ if (i < bSize) {
+ yIndex = -i - 1;
+ item = before.get(i);
+ } else {
+ yIndex = i - bSize + 1;
+ item = after.get(i - bSize);
+ }
+
+ if (mouseY > top + 16 * yIndex && mouseY <= top + 16 * yIndex + 16) {
+ enchanterCurrentItem = item;
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ }
+ }
+
+ if (isChangingEnchLevel) {
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.ADDING_GEMSTONE || currentState == EnchantState.APPLYING_GEMSTONE) {
+ if (Mouse.getEventButtonState()) {
+ int left = guiLeft + X_SIZE / 2 - 56;
+ int top = guiTop + 83;
+
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 - 1 - 48, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+ Utils.drawTexturedRect(guiLeft + X_SIZE / 2 + 1, top + 18, 48, 14,
+ 0, 48 / 512f, 328 / 512f, (328 + 14) / 512f, GL11.GL_NEAREST
+ );
+
+ if (!isChangingEnchLevel && mouseX > guiLeft + X_SIZE / 2 + 1 && mouseX <= guiLeft + X_SIZE / 2 + 1 + 48 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState != EnchantState.APPLYING_GEMSTONE) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ currentState = EnchantState.HAS_ITEM_IN_GEMSTONE;
+ enchanterCurrentItem = null;
+ } else {
+ currentState = EnchantState.ADDING_ENCHANT;
+ enchanterCurrentItem = null;
+ }
+ } else if (!isChangingEnchLevel && enchanterCurrentItem != null &&
+ (mouseX > left + 16 && mouseX <= left + 96 &&
+ mouseY > top && mouseY <= top + 16) ||
+ (mouseX > guiLeft + X_SIZE / 2 - 1 - 48 && mouseX <= guiLeft + X_SIZE / 2 - 1 &&
+ mouseY > top + 18 && mouseY <= top + 18 + 14) && currentState == EnchantState.APPLYING_GEMSTONE) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(
+ enchanterCurrentItem.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ enchanterCurrentItem.slotIndex, 0, 0, stack, transactionID
+ ));
+ enchantingItem = null;
+ if (removingEnchantPlayerLevel >= 0 && enchanterCurrentItem.level == removingEnchantPlayerLevel) {
+ orbDisplay.spawnExperienceOrbs(X_SIZE / 2, 66, X_SIZE / 2, 36, 3);
+ } else {
+ orbDisplay.spawnExperienceOrbs(mouseX - guiLeft, mouseY - guiTop, X_SIZE / 2, 66, 0);
+ }
+
+ confirmButtonAnimTime = System.currentTimeMillis();
+ enchanterCurrentItem = null;
+ currentState = EnchantState.ADDING_GEMSTONE;
+ } else if (mouseX > left + 96 && mouseX <= left + 96 + 16) {
+ if (!isChangingEnchLevel) {
+ if (mouseY > top && mouseY < top + 16) {
+ isChangingEnchLevel = true;
+ return true;
+ }
+ } else {
+ List<HexItem> before = new ArrayList<>();
+ List<HexItem> after = new ArrayList<>();
+
+ for (HexItem item : enchanterItemLevels.values()) {
+ if (item.level < enchanterCurrentItem.level) {
+ before.add(item);
+ } else if (item.level > enchanterCurrentItem.level) {
+ after.add(item);
+ }
+ }
+
+ before.sort(Comparator.comparingInt(o -> -o.level));
+ after.sort(Comparator.comparingInt(o -> o.level));
+
+ int bSize = before.size();
+ int aSize = after.size();
+ for (int i = 0; i < bSize + aSize; i++) {
+ HexItem item;
+ int yIndex;
+ if (i < bSize) {
+ yIndex = -i - 1;
+ item = before.get(i);
+ } else {
+ yIndex = i - bSize + 1;
+ item = after.get(i - bSize);
+ }
+
+ if (mouseY > top + 16 * yIndex && mouseY <= top + 16 * yIndex + 16) {
+ enchanterCurrentItem = item;
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ }
+ }
+
+ if (isChangingEnchLevel) {
+ isChangingEnchLevel = false;
+ return true;
+ }
+ }
+ }
+
+ if (!Mouse.getEventButtonState() && Mouse.getEventButton() < 0 && clickedScrollOffset != -1) {
+ if (isInEnchanting()) {
+ LerpingInteger lerpingInteger = isClickedScrollLeft ? leftScroll : rightScroll;
+ List<Enchantment> enchantsList = isClickedScrollLeft ? applicable : removable;
+
+ if (enchantsList.size() > 6) {
+ int newOffset = mouseY - clickedScrollOffset;
+
+ int newScroll = Math.round(newOffset * (float) ((enchantsList.size() - 6) * 16) / (96 - 15));
+ int max = (enchantsList.size() - 6) * 16;
+
+ if (newScroll > max) newScroll = max;
+ if (newScroll < 0) newScroll = 0;
+
+ lerpingInteger.setValue(newScroll);
+ }
+ } else {
+ LerpingInteger lerpingInteger = isClickedScrollLeft ? leftScroll : rightScroll;
+ List<HexItem> itemsList = isClickedScrollLeft ? applicableItem : removableItem;
+
+ if (itemsList.size() > 6) {
+ int newOffset = mouseY - clickedScrollOffset;
+
+ int newScroll = Math.round(newOffset * (float) ((itemsList.size() - 6) * 16) / (96 - 15));
+ int max = (itemsList.size() - 6) * 16;
+
+ if (newScroll > max) newScroll = max;
+ if (newScroll < 0) newScroll = 0;
+
+ lerpingInteger.setValue(newScroll);
+ }
+ }
+ }
+
+ //Config options
+ if (Mouse.getEventButtonState()) {
+ if (mouseX >= guiLeft + 294 && mouseX < guiLeft + 294 + 36 &&
+ mouseY >= guiTop + 146 && mouseY < guiTop + 146 + 36) {
+ int index = (mouseX - (guiLeft + 295)) / 18 + (mouseY - (guiTop + 147)) / 18 * 2;
+
+ int direction = Mouse.getEventButton() == 0 ? 1 : -1;
+
+ switch (index) {
+ case 0: {
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enableHexGUI = false;
+ break;
+ }
+ case 1: {
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.maxEnchLevel = !NotEnoughUpdates.INSTANCE.config.enchantingSolvers.maxEnchLevel;
+ break;
+ }
+ case 2: {
+ int val = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantSorting;
+ val += direction;
+ if (val < 0) val = 1;
+ if (val > 1) val = 0;
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantSorting = val;
+ break;
+ }
+ case 3: {
+ int val = NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantOrdering;
+ val += direction;
+ if (val < 0) val = 1;
+ if (val > 1) val = 0;
+ NotEnoughUpdates.INSTANCE.config.enchantingSolvers.enchantOrdering = val;
+ break;
+ }
+ }
+ }
+ }
+
+ if (Mouse.getEventButton() == 0) {
+ if (Mouse.getEventButtonState()) {
+ if (isInEnchanting()) {
+ if (mouseX > guiLeft + 104 && mouseX < guiLeft + 104 + 12) {
+ int offset;
+ if (applicable.size() <= 6) {
+ offset = 0;
+ } else {
+ offset = Math.round((96 - 15) * (leftScroll.getValue() / (float) ((applicable.size() - 6) * 16)));
+ }
+ if (mouseY >= guiTop + 18 + offset && mouseY < guiTop + 18 + offset + 15) {
+ isClickedScrollLeft = true;
+ clickedScrollOffset = mouseY - offset;
+ }
+ } else if (mouseX > guiLeft + 344 && mouseX < guiLeft + 344 + 12) {
+ int offset;
+ if (removable.size() <= 6) {
+ offset = 0;
+ } else {
+ offset = Math.round((96 - 15) * (rightScroll.getValue() / (float) ((removable.size() - 6) * 16)));
+ }
+ if (mouseY >= guiTop + 18 + offset && mouseY < guiTop + 18 + offset + 15) {
+ isClickedScrollLeft = false;
+ clickedScrollOffset = mouseY - offset;
+ }
+ }
+ } else {
+ if (mouseX > guiLeft + 104 && mouseX < guiLeft + 104 + 12) {
+ int offset;
+ if (applicableItem.size() <= 6) {
+ offset = 0;
+ } else {
+ offset = Math.round((96 - 15) * (leftScroll.getValue() / (float) ((applicableItem.size() - 6) * 16)));
+ }
+ if (mouseY >= guiTop + 18 + offset && mouseY < guiTop + 18 + offset + 15) {
+ isClickedScrollLeft = true;
+ clickedScrollOffset = mouseY - offset;
+ }
+ } else if (mouseX > guiLeft + 344 && mouseX < guiLeft + 344 + 12) {
+ int offset;
+ if (removableItem.size() <= 6) {
+ offset = 0;
+ } else {
+ offset = Math.round((96 - 15) * (rightScroll.getValue() / (float) ((removableItem.size() - 6) * 16)));
+ }
+ if (mouseY >= guiTop + 18 + offset && mouseY < guiTop + 18 + offset + 15) {
+ isClickedScrollLeft = false;
+ clickedScrollOffset = mouseY - offset;
+ }
+ }
+ }
+ } else {
+ clickedScrollOffset = -1;
+ }
+ }
+
+ if (mouseY > guiTop + 18 && mouseY < guiTop + 18 + 96) {
+ if (mouseX > guiLeft + 8 && mouseX < guiLeft + 8 + 96) {
+ if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState() &&
+ Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
+ if (isInEnchanting()) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+ if (applicable.size() <= index) break;
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ Enchantment ench = applicable.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.HAS_ITEM) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(ench.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ ench.slotIndex, 0, 0, stack, transactionID
+ ));
+ } else if (currentState == EnchantState.ADDING_ENCHANT) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ }
+
+ return true;
+ }
+ }
+ } else if (!isInHex() && !isInGemstones()) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+ if (applicableItem.size() <= index) break;
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = applicableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS) {
+ currentState = EnchantState.ADDING_BOOK;
+ enchanterCurrentItem = item;
+ } else if (currentState == EnchantState.ADDING_BOOK && enchanterCurrentItem == item) {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ } else {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchanterCurrentItem = null;
+ }
+
+ return true;
+ }
+ }
+ } else if (isInHex() && !isInGemstones()) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+ if (applicableItem.size() <= index) break;
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = applicableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ //cancelButtonAnimTime = System.currentTimeMillis();
+
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.ADDING_GEMSTONE || currentState == EnchantState.APPLYING_GEMSTONE) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+ if (applicableItem.size() <= index) break;
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = applicableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.ADDING_GEMSTONE) {
+ currentState = EnchantState.APPLYING_GEMSTONE;
+ enchanterCurrentItem = item;
+ } else if (currentState == EnchantState.APPLYING_GEMSTONE && enchanterCurrentItem == item) {
+ currentState = EnchantState.ADDING_GEMSTONE;
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ } else {
+ currentState = EnchantState.ADDING_GEMSTONE;
+ enchanterCurrentItem = null;
+ }
+
+ //cancelButtonAnimTime = System.currentTimeMillis();
+
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.HAS_ITEM_IN_GEMSTONE) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + leftScroll.getValue() / 16;
+ if (applicableItem.size() <= index) break;
+
+ int top = guiTop - (leftScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 8 && mouseX <= guiLeft + 8 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = applicableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+
+ //cancelButtonAnimTime = System.currentTimeMillis();
+
+ return true;
+ }
+ }
+ }
+ }
+
+ isScrollingLeft = true;
+ } else if (mouseX > guiLeft + 248 && mouseX < guiLeft + 248 + 96) {
+ if (Mouse.getEventButton() == 0 && Mouse.getEventButtonState() &&
+ Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
+ if (isInEnchanting()) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+ if (removable.size() <= index) break;
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ Enchantment ench = removable.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.HAS_ITEM || currentState == EnchantState.HAS_ITEM_IN_HEX) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(ench.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ ench.slotIndex, 0, 0, stack, transactionID
+ ));
+ } else if (currentState == EnchantState.ADDING_ENCHANT) {
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ }
+
+ return true;
+ }
+ }
+ } else if (currentState == EnchantState.ADDING_GEMSTONE) {
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+ if (removableItem.size() <= index) break;
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = removableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.ADDING_GEMSTONE) {
+ currentState = EnchantState.APPLYING_GEMSTONE;
+ enchanterCurrentItem = item;
+ } else if (currentState == EnchantState.APPLYING_GEMSTONE && enchanterCurrentItem == item) {
+ currentState = EnchantState.ADDING_GEMSTONE;
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ } else {
+ currentState = EnchantState.ADDING_GEMSTONE;
+ enchanterCurrentItem = null;
+ }
+
+ return true;
+ }
+ }
+
+ } else {
+ for (int i = 0; i < 7; i++) {
+ int index = i + rightScroll.getValue() / 16;
+ if (removableItem.size() <= index) break;
+
+ int top = guiTop - (rightScroll.getValue() % 16) + 18 + 16 * i;
+ if (mouseX > guiLeft + 248 && mouseX <= guiLeft + 248 + 96 &&
+ mouseY > top && mouseY <= top + 16) {
+ HexItem item = removableItem.get(index);
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ if (currentState == EnchantState.HAS_ITEM_IN_BOOKS) {
+ currentState = EnchantState.ADDING_BOOK;
+ enchanterCurrentItem = item;
+ } else if (currentState == EnchantState.ADDING_BOOK && enchanterCurrentItem == item) {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack =
+ ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(item.slotIndex);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId,
+ item.slotIndex, 0, 0, stack, transactionID
+ ));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ } else {
+ currentState = EnchantState.HAS_ITEM_IN_BOOKS;
+ enchanterCurrentItem = null;
+ }
+
+ return true;
+ }
+ }
+ }
+ }
+ isScrollingLeft = false;
+ }
+ }
+ if (Mouse.getEventDWheel() != 0) {
+ int scroll = Mouse.getEventDWheel();
+ if (scroll > 0) {
+ scroll = -16;
+ } else {
+ scroll = 16;
+ }
+
+ LerpingInteger lerpingInteger = isScrollingLeft ? leftScroll : rightScroll;
+ int elementsCount;
+ if (isInEnchanting()) {
+ elementsCount = isScrollingLeft ? applicable.size() : removable.size();
+ } else {
+ elementsCount = isScrollingLeft ? applicableItem.size() : removableItem.size();
+ }
+ int max = (elementsCount - 6) * 16;
+
+ int newTarget = lerpingInteger.getTarget() + scroll;
+ if (newTarget > max) newTarget = max;
+ if (newTarget < 0) newTarget = 0;
+
+ if (newTarget != lerpingInteger.getTarget()) {
+ lerpingInteger.resetTimer();
+ lerpingInteger.setTarget(newTarget);
+ }
+ }
+
+ if (mouseX > guiLeft + 102 && mouseX < guiLeft + 102 + 160) {
+ if ((mouseY > guiTop + 133 && mouseY < guiTop + 133 + 54) ||
+ (mouseY > guiTop + 133 + 54 + 4 && mouseY < guiTop + 133 + 54 + 4 + 18)) {
+ if (currentState == EnchantState.ADDING_ENCHANT) {
+ if (Mouse.getEventButtonState()) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+ if (mouseX >= guiLeft + 173 && mouseX < guiLeft + 173 + 18 &&
+ mouseY >= guiTop + 57 && mouseY < guiTop + 57 + 18) {
+ if (currentState == EnchantState.ADDING_ENCHANT) {
+ if (Mouse.getEventButtonState()) {
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return true;
+ GuiContainer chest = ((GuiContainer) Minecraft.getMinecraft().currentScreen);
+
+ EntityPlayerSP playerIn = Minecraft.getMinecraft().thePlayer;
+ short transactionID = playerIn.openContainer.getNextTransactionID(playerIn.inventory);
+ ItemStack stack = ((ContainerChest) chest.inventorySlots).getLowerChestInventory().getStackInSlot(45);
+ Minecraft.getMinecraft().getNetHandler().addToSendQueue(new C0EPacketClickWindow(
+ chest.inventorySlots.windowId, 45, 0, 0, stack, transactionID));
+
+ cancelButtonAnimTime = System.currentTimeMillis();
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean keyboardInput() {
+ if (currentState == EnchantState.HAS_ITEM && searchField.getFocus()) {
+ if (Keyboard.getEventKeyState()) {
+ searchField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ }
+ return true;
+ }
+ if (Keyboard.getEventKey() == Minecraft.getMinecraft().gameSettings.keyBindScreenshot.getKeyCode()) {
+ return false;
+ }
+
+ return Keyboard.getEventKey() != Keyboard.KEY_ESCAPE &&
+ Keyboard.getEventKey() != Minecraft.getMinecraft().gameSettings.keyBindInventory.getKeyCode() &&
+ (!NotEnoughUpdates.INSTANCE.config.slotLocking.enableSlotLocking ||
+ Keyboard.getEventKey() != NotEnoughUpdates.INSTANCE.config.slotLocking.slotLockKey);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/HexItem.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/HexItem.java
new file mode 100644
index 00000000..5b3b30ea
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/HexItem.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.hex;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.util.StringUtils;
+
+import java.util.List;
+
+public class HexItem {
+ public int slotIndex;
+ public String itemName;
+ public String itemId;
+ public List<String> displayLore;
+ public int level;
+ public int price = -1;
+ public boolean overMaxLevel = false;
+ public boolean conflicts = false;
+ public ItemType itemType;
+ public int gemstoneLevel = -1;
+
+ public HexItem(
+ int slotIndex, String itemName, String itemId, List<String> displayLore,
+ boolean useMaxLevelForCost, boolean checkConflicts
+ ) {
+ this.slotIndex = slotIndex;
+ this.itemName = itemName;
+ this.itemId = itemId.replace("'S", "");
+ this.displayLore = displayLore;
+ switch (itemId) {
+ default:
+ this.itemType = ItemType.UNKNOWN;
+ break;
+ case "HOT_POTATO_BOOK":
+ this.itemType = ItemType.HOT_POTATO;
+ break;
+ case "FUMING_POTATO_BOOK":
+ this.itemType = ItemType.FUMING_POTATO;
+ break;
+ case "BOOK_OF_STATS":
+ this.itemType = ItemType.BOOK_OF_STATS;
+ break;
+ case "THE_ART_OF_WAR":
+ this.itemType = ItemType.ART_OF_WAR;
+ break;
+ case "FARMING_FOR_DUMMIES":
+ this.itemType = ItemType.FARMING_DUMMY;
+ break;
+ case "THE_ART_OF_PEACE":
+ this.itemType = ItemType.ART_OF_PEACE;
+ break;
+ case "RECOMBOBULATOR_3000":
+ this.itemType = ItemType.RECOMB;
+ break;
+ case "SILEX":
+ this.itemId = "SIL_EX";
+ this.itemType = ItemType.SILEX;
+ break;
+ case "RUBY_POWER_SCROLL":
+ this.itemType = ItemType.RUBY_SCROLL;
+ break;
+ case "SAPPHIRE_POWER_SCROLL":
+ this.itemType = ItemType.SAPPHIRE_SCROLL;
+ break;
+ case "JASPER_POWER_SCROLL":
+ this.itemType = ItemType.JASPER_SCROLL;
+ break;
+ case "AMETHYST_POWER_SCROLL":
+ this.itemType = ItemType.AMETHYST_SCROLL;
+ break;
+ case "AMBER_POWER_SCROLL":
+ this.itemType = ItemType.AMBER_SCROLL;
+ break;
+ case "OPAL_POWER_SCROLL":
+ this.itemType = ItemType.OPAL_SCROLL;
+ break;
+ case "FIRST_MASTER_STAR":
+ this.itemType = ItemType.FIRST_MASTER_STAR;
+ break;
+ case "SECOND_MASTER_STAR":
+ this.itemType = ItemType.SECOND_MASTER_STAR;
+ break;
+ case "THIRD_MASTER_STAR":
+ this.itemType = ItemType.THIRD_MASTER_STAR;
+ break;
+ case "FOURTH_MASTER_STAR":
+ this.itemType = ItemType.FOURTH_MASTER_STAR;
+ break;
+ case "FIFTH_MASTER_STAR":
+ this.itemType = ItemType.FIFTH_MASTER_STAR;
+ break;
+ case "WOOD_SINGULARITY":
+ this.itemType = ItemType.WOOD_SINGULARITY;
+ break;
+ case "IMPLOSION":
+ this.itemType = ItemType.IMPLOSION_SCROLL;
+ break;
+ case "WITHER_SHIELD":
+ this.itemType = ItemType.WITHER_SHIELD_SCROLL;
+ break;
+ case "SHADOW_WARP":
+ this.itemType = ItemType.SHADOW_WARP_SCROLL;
+ break;
+ case "TRANSMISSION_TUNER":
+ this.itemType = ItemType.TUNER;
+ break;
+ case "RANDOM_REFORGE":
+ this.itemType = ItemType.RANDOM_REFORGE;
+ break;
+ case "MANA_DISINTEGRATOR":
+ this.itemType = ItemType.MANA_DISINTEGRATOR;
+ break;
+ case "TOTAL_UPGRADES":
+ this.itemType = ItemType.TOTAL_UPGRADES;
+ break;
+ case "CONVERT_TO_DUNGEON":
+ this.itemType = ItemType.CONVERT_TO_DUNGEON;
+ break;
+ case "EXPERIENCE_BOTTLE":
+ this.itemType = ItemType.EXPERIENCE_BOTTLE;
+ break;
+ case "GRAND_EXPERIENCE_BOTTLE":
+ this.itemType = ItemType.GRAND_EXPERIENCE_BOTTLE;
+ break;
+ case "TITANIC_EXPERIENCE_BOTTLE":
+ this.itemType = ItemType.TITANIC_EXPERIENCE_BOTTLE;
+ break;
+ case "COLOSSAL_EXPERIENCE_BOTTLE":
+ this.itemType = ItemType.COLOSSAL_EXPERIENCE_BOTTLE;
+ break;
+ }
+ if (this.itemType == ItemType.UNKNOWN) {
+ for (String string : displayLore) {
+ if ((string.contains("Applies the") && string.contains("reforge")) ||
+ string.contains("reforge when combined")) {
+ this.itemType = ItemType.REFORGE;
+ break;
+ }
+ }
+ }
+ if (!this.isMasterStar() && itemId.contains("✪")) {
+ if (itemId.contains("✪✪✪✪✪")) this.itemType = ItemType.FIFTH_STAR;
+ else if (itemId.contains("✪✪✪✪")) this.itemType = ItemType.FOURTH_STAR;
+ else if (itemId.contains("✪✪✪")) this.itemType = ItemType.THIRD_STAR;
+ else if (itemId.contains("✪✪")) this.itemType = ItemType.SECOND_STAR;
+ else if (itemId.contains("✪")) this.itemType = ItemType.FIRST_STAR;
+ }
+ if (this.itemId.contains("EXPERIENCE_BOTTLE")) {
+ this.itemId = this.itemId.replace("EXPERIENCE_BOTTLE", "EXP_BOTTLE");
+ }
+ if (this.itemId.contains("END_STONE_GEODE")) {
+ this.itemId = this.itemId.replace("END_STONE_GEODE", "ENDSTONE_GEODE");
+ }
+ if (itemId.contains("HEX_ITEM")) this.itemType = ItemType.HEX_ITEM;
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(this.itemId);
+ if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
+ this.price = bazaarInfo.get("curr_buy").getAsInt();
+ }
+ if ("SIL_EX".equals(this.itemId)) this.itemId = "SILEX";
+ if (itemName.contains("Amethyst Gemstone")) this.itemType = ItemType.AMETHYST_GEMSTONE;
+ if (itemName.contains("Ruby Gemstone")) this.itemType = ItemType.RUBY_GEMSTONE;
+ if (itemName.contains("Sapphire Gemstone")) this.itemType = ItemType.SAPPHIRE_GEMSTONE;
+ if (itemName.contains("Jasper Gemstone")) this.itemType = ItemType.JASPER_GEMSTONE;
+ if (itemName.contains("Jade Gemstone")) this.itemType = ItemType.JADE_GEMSTONE;
+ if (itemName.contains("Amber Gemstone")) this.itemType = ItemType.AMBER_GEMSTONE;
+ if (itemName.contains("Opal Gemstone")) this.itemType = ItemType.OPAL_GEMSTONE;
+ if (itemName.contains("Topaz Gemstone")) this.itemType = ItemType.TOPAZ_GEMSTONE;
+ if (itemName.contains("Gemstone Slot")) this.itemType = ItemType.GEMSTONE_SLOT;
+ if (this.itemName.contains(" Gemstone")) {
+ this.itemName = this.itemName.replace(" Gemstone", "").substring(2);
+ } else if (this.itemName.contains(" Experience Bottle")) {
+ this.itemName = this.itemName.replace("Experience Bottle", "");
+ } else if (this.itemName.equals("Experience Bottle")) {
+ this.itemName = "Exp Bottle";
+ }
+ if (isGemstone()) {
+ if (this.itemName.contains("Rough")) this.gemstoneLevel = 0;
+ if (this.itemName.contains("Flawed")) this.gemstoneLevel = 1;
+ if (this.itemName.contains("Fine")) this.gemstoneLevel = 2;
+ if (this.itemName.contains("Flawless")) this.gemstoneLevel = 3;
+ if (this.itemName.contains("Perfect")) this.gemstoneLevel = 4;
+ }
+ }
+
+ public boolean isPowerScroll() {
+ return itemType == ItemType.RUBY_SCROLL || itemType == ItemType.SAPPHIRE_SCROLL ||
+ itemType == ItemType.JASPER_SCROLL || itemType == ItemType.AMETHYST_SCROLL ||
+ itemType == ItemType.AMBER_SCROLL || itemType == ItemType.OPAL_SCROLL;
+ }
+
+ public boolean isDungeonStar() {
+ return itemType == ItemType.FIRST_STAR || itemType == ItemType.SECOND_STAR ||
+ itemType == ItemType.THIRD_STAR || itemType == ItemType.FOURTH_STAR ||
+ itemType == ItemType.FIFTH_STAR;
+ }
+
+ public boolean isMasterStar() {
+ return itemType == ItemType.FIRST_MASTER_STAR || itemType == ItemType.SECOND_MASTER_STAR ||
+ itemType == ItemType.THIRD_MASTER_STAR || itemType == ItemType.FOURTH_MASTER_STAR ||
+ itemType == ItemType.FIFTH_MASTER_STAR;
+ }
+
+ public String getReforge() {
+ JsonObject reforgeStones = Constants.REFORGESTONES;
+ if (reforgeStones != null && reforgeStones.has(this.itemId.toUpperCase())) {
+ JsonObject reforgeInfo = reforgeStones.get(this.itemId.toUpperCase()).getAsJsonObject();
+ if (reforgeInfo != null) {
+ return Utils.getElementAsString(reforgeInfo.get("reforgeName"), "");
+ }
+
+ }
+ return "";
+ }
+
+ public int getPrice() {
+ if (this.itemType == ItemType.RANDOM_REFORGE) {
+ for (String string : displayLore) {
+ if (string.contains("Coins")) {
+ try {
+ price = Integer.parseInt(StringUtils
+ .stripControlCodes(string)
+ .replace(" Coins", "")
+ .replace(",", "")
+ .trim());
+ } catch (NumberFormatException ignored) {
+ }
+ }
+ }
+ }
+ return price;
+ }
+
+ public boolean isHypeScroll() {
+ return itemType == ItemType.IMPLOSION_SCROLL || itemType == ItemType.WITHER_SHIELD_SCROLL ||
+ itemType == ItemType.SHADOW_WARP_SCROLL;
+ }
+
+ public boolean isGemstone() {
+ return itemType == ItemType.RUBY_GEMSTONE || itemType == ItemType.AMETHYST_GEMSTONE ||
+ itemType == ItemType.SAPPHIRE_GEMSTONE || itemType == ItemType.JASPER_GEMSTONE ||
+ itemType == ItemType.JADE_GEMSTONE || itemType == ItemType.AMBER_GEMSTONE ||
+ itemType == ItemType.OPAL_GEMSTONE || itemType == ItemType.TOPAZ_GEMSTONE;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/ItemType.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/ItemType.java
new file mode 100644
index 00000000..3b47a86d
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/hex/ItemType.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.hex;
+
+enum ItemType {
+ HOT_POTATO,
+ FUMING_POTATO,
+ BOOK_OF_STATS,
+ ART_OF_WAR,
+ ART_OF_PEACE,
+ FARMING_DUMMY,
+ RECOMB,
+ SILEX,
+ RUBY_SCROLL,
+ SAPPHIRE_SCROLL,
+ JASPER_SCROLL,
+ AMETHYST_SCROLL,
+ AMBER_SCROLL,
+ OPAL_SCROLL,
+ FIRST_STAR(1),
+ SECOND_STAR(2),
+ THIRD_STAR(3),
+ FOURTH_STAR(4),
+ FIFTH_STAR(5),
+ FIRST_MASTER_STAR(6),
+ SECOND_MASTER_STAR(7),
+ THIRD_MASTER_STAR(8),
+ FOURTH_MASTER_STAR(9),
+ FIFTH_MASTER_STAR(10),
+ WOOD_SINGULARITY,
+ IMPLOSION_SCROLL,
+ SHADOW_WARP_SCROLL,
+ WITHER_SHIELD_SCROLL,
+ TUNER,
+ REFORGE,
+ RANDOM_REFORGE,
+ MANA_DISINTEGRATOR,
+ HEX_ITEM,
+ TOTAL_UPGRADES,
+ RUBY_GEMSTONE,
+ AMETHYST_GEMSTONE,
+ SAPPHIRE_GEMSTONE,
+ JASPER_GEMSTONE,
+ JADE_GEMSTONE,
+ AMBER_GEMSTONE,
+ OPAL_GEMSTONE,
+ TOPAZ_GEMSTONE,
+ CONVERT_TO_DUNGEON,
+ GEMSTONE_SLOT,
+ EXPERIENCE_BOTTLE,
+ GRAND_EXPERIENCE_BOTTLE,
+ TITANIC_EXPERIENCE_BOTTLE,
+ COLOSSAL_EXPERIENCE_BOTTLE,
+ UNKNOWN;
+
+ private int starLevel = -1;
+
+ ItemType() {}
+
+ ItemType(int starLevel) {
+ this.starLevel = starLevel;
+ }
+
+ public int getStarLevel() {
+ return starLevel;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java
index 938f3f98..6a2602f8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuConfigTutorial.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui.tutorials;
public class NeuConfigTutorial extends TutorialBase {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java
index 24c6bb7f..c0a5d8c8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/NeuTutorial.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui.tutorials;
import net.minecraft.client.Minecraft;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java
index 433bb996..27172ed8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/tutorials/TutorialBase.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.miscgui.tutorials;
import com.google.gson.JsonArray;
@@ -43,7 +62,6 @@ public class TutorialBase extends GuiScreen {
@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
- Keyboard.enableRepeatEvents(true);
super.keyTyped(typedChar, keyCode);
if (keyCode == Keyboard.KEY_LEFT) {
page--;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/ExperienceOrb.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/ExperienceOrb.java
new file mode 100644
index 00000000..9da4f553
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/ExperienceOrb.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.util;
+
+import org.lwjgl.util.vector.Vector2f;
+
+public class ExperienceOrb {
+ public Vector2f position;
+ public Vector2f positionLast;
+ public Vector2f velocity;
+ public Vector2f target;
+
+ public int type;
+ public int rotationDeg;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/OrbDisplay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/OrbDisplay.java
new file mode 100644
index 00000000..42e935f5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/util/OrbDisplay.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.miscgui.util;
+
+import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.vector.Vector2f;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Random;
+
+public class OrbDisplay {
+ private static final ResourceLocation TEXTURE = new ResourceLocation("notenoughupdates:custom_enchant_gui.png");
+ private static final int DEFAULT_COUNT = 30;
+
+ private final List<ExperienceOrb> experienceOrbList = new ArrayList<>();
+
+ public ExperienceOrb spawnExperienceOrb(Random random, Vector2f start, Vector2f target, int baseType) {
+ ExperienceOrb orb = new ExperienceOrb();
+ orb.position = new Vector2f(start);
+ orb.positionLast = new Vector2f(orb.position);
+ orb.velocity = new Vector2f(
+ random.nextFloat() * 20 - 10,
+ random.nextFloat() * 20 - 10
+ );
+ orb.target = new Vector2f(target);
+ orb.type = baseType;
+ orb.rotationDeg = random.nextInt(4) * 90;
+
+ float v = random.nextFloat();
+ if (v > 0.6) {
+ orb.type += 1;
+ }
+ if (v > 0.9) {
+ orb.type += 1;
+ }
+
+ experienceOrbList.add(orb);
+
+ return orb;
+ }
+
+ public void spawnExperienceOrbs(int startX, int startY, int targetX, int targetY, int baseType) {
+ spawnExperienceOrbs(new Random(),new Vector2f(startX, startY), new Vector2f(targetX, targetY), baseType, DEFAULT_COUNT);
+ }
+
+ public void spawnExperienceOrbs(Random random, Vector2f start, Vector2f target, int baseType, int count) {
+ for (int i = 0; i < count; i++) {
+ spawnExperienceOrb(random, start, target, baseType);
+ }
+ }
+
+ public void physicsTickOrbs() {
+ for (ListIterator<ExperienceOrb> it = experienceOrbList.listIterator(); it.hasNext(); ) {
+ ExperienceOrb orb = it.next();
+
+ Vector2f delta = Vector2f.sub(orb.target, orb.position, null);
+ float length = delta.length();
+
+ // Remove close Orbs
+ if (length < 8 && orb.velocity.lengthSquared() < 20) {
+ it.remove();
+ continue;
+ }
+
+ // Update velocity
+ Vector2f.add(orb.velocity, (Vector2f) delta.scale(2 / length), orb.velocity);
+ orb.velocity.scale(0.9F);
+
+ // Update position
+ orb.positionLast.set(orb.position);
+ Vector2f.add(orb.position, orb.velocity, orb.position);
+ }
+ }
+
+ public void renderOrbs(float partialTicks) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE);
+ GlStateManager.disableDepth();
+
+ for (ExperienceOrb orb : experienceOrbList) {
+ int orbX = Math.round(LerpUtils.lerp(orb.position.x, orb.positionLast.x, partialTicks));
+ int orbY = Math.round(LerpUtils.lerp(orb.position.y, orb.positionLast.y, partialTicks));
+
+ GlStateManager.pushMatrix();
+
+ GlStateManager.translate(orbX, orbY, 0);
+ GlStateManager.rotate(orb.rotationDeg, 0, 0, 1);
+
+ Vector2f delta = Vector2f.sub(orb.position, orb.target, null);
+
+ float length = delta.length();
+ float velocitySquared = orb.velocity.lengthSquared();
+ float opacity = (float) Math.sqrt(
+ Math.min(
+ 1,
+ Math.min(2, Math.max(0.5F, length / 16))
+ * Math.min(2, Math.max(0.5F, velocitySquared / 40))
+ ));
+ GlStateManager.color(1, 1, 1, opacity);
+
+ int orbU = (orb.type % 3) * 16;
+ int orbV = (orb.type / 3) * 16 + 217;
+
+ Utils.drawTexturedRect(
+ -8, -8, 16, 16,
+ orbU / 512f,
+ (orbU + 16) / 512f,
+ orbV / 512f,
+ (orbV + 16) / 512f,
+ GL11.GL_NEAREST
+ );
+
+ GlStateManager.popMatrix();
+ }
+
+ GlStateManager.enableDepth();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityAgeable.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityAgeable.java
new file mode 100644
index 00000000..d30cb9b3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityAgeable.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.EntityAgeable;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(EntityAgeable.class)
+public interface AccessorEntityAgeable {
+ @Accessor(value = "growingAge")
+ void setGrowingAgeDirect(int newValue);
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityArmorStand.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityArmorStand.java
new file mode 100644
index 00000000..50bbe135
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorEntityArmorStand.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.item.EntityArmorStand;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(EntityArmorStand.class)
+public interface AccessorEntityArmorStand {
+ @Invoker(value = "setSmall")
+ void setSmallDirect(boolean isSmall);
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiContainer.java
new file mode 100644
index 00000000..a12cd9c8
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiContainer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.inventory.Slot;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+import org.spongepowered.asm.mixin.gen.Invoker;
+
+@Mixin(GuiContainer.class)
+public interface AccessorGuiContainer {
+
+ @Invoker("getSlotAtPosition")
+ Slot doGetSlotAtPosition(int x, int y);
+
+ @Invoker("drawSlot")
+ void doDrawSlot(Slot slot);
+
+ @Invoker("isMouseOverSlot")
+ boolean doIsMouseOverSlot(Slot slot, int x, int y);
+
+ @Accessor("guiLeft")
+ int getGuiLeft();
+
+ @Accessor("guiTop")
+ int getGuiTop();
+
+ @Accessor("xSize")
+ int getXSize();
+
+ @Accessor("ySize")
+ int getYSize();
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiEditSign.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiEditSign.java
new file mode 100644
index 00000000..d1cd7069
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiEditSign.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.tileentity.TileEntitySign;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(GuiEditSign.class)
+public interface AccessorGuiEditSign {
+ @Accessor("tileSign")
+ TileEntitySign getTileSign();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiPlayerTabOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiPlayerTabOverlay.java
new file mode 100644
index 00000000..0189e2fc
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorGuiPlayerTabOverlay.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.client.gui.GuiPlayerTabOverlay;
+import net.minecraft.util.IChatComponent;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(GuiPlayerTabOverlay.class)
+public interface AccessorGuiPlayerTabOverlay {
+ @Accessor("footer")
+ IChatComponent getFooter();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorMinecraft.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorMinecraft.java
new file mode 100644
index 00000000..6d8c941c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/AccessorMinecraft.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.resources.IResourcePack;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+import java.util.List;
+
+@Mixin(Minecraft.class)
+public interface AccessorMinecraft {
+ @Accessor(value = "defaultResourcePacks")
+ List<IResourcePack> onGetDefaultResourcePacks();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinAbstractClientPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinAbstractClientPlayer.java
index 5c81c758..685528e0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinAbstractClientPlayer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinAbstractClientPlayer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
index 80d79712..53643fb0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinContainer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
index 8d0b291a..451fff3a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java
index 86995647..39951ba4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import net.minecraft.entity.Entity;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java
index b8f07b53..d9b60a13 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import net.minecraft.entity.EntityAgeable;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityHorse.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityHorse.java
new file mode 100644
index 00000000..50eb15ba
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityHorse.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.passive.EntityHorse;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(EntityHorse.class)
+public class MixinEntityHorse {
+ @Redirect(method = "updateHorseSlots", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;isRemote:Z"))
+ public boolean onUpdateHorseSlots(World instance) {
+ if (instance == null)
+ return true;
+ return instance.isRemote;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
index e15d18eb..573b2ad5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
@@ -8,7 +27,7 @@ import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
-import org.spongepowered.asm.lib.Opcodes;
+import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java
index 573eac22..765ed372 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayerSP.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java
index 26923726..12ff1cb4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java
@@ -1,39 +1,53 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
-import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
-import net.minecraft.util.MathHelper;
import net.minecraftforge.client.ForgeHooksClient;
-import org.lwjgl.util.glu.Project;
import org.lwjgl.util.vector.Vector3f;
-import org.spongepowered.asm.lib.Opcodes;
+import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Redirect;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(EntityRenderer.class)
public abstract class MixinEntityRenderer {
@Shadow
- protected abstract float getFOVModifier(float partialTicks, boolean useFOVSetting);
-
- @Shadow
private Minecraft mc;
-
@Shadow
private float farPlaneDistance;
@Shadow
+ protected abstract float getFOVModifier(float partialTicks, boolean useFOVSetting);
+
+ @Shadow
protected abstract void orientCamera(float partialTicks);
@Inject(method = "getFOVModifier", at = @At("RETURN"), cancellable = true)
@@ -52,38 +66,6 @@ public abstract class MixinEntityRenderer {
@Redirect(method = "renderWorldPass", at = @At(
value = "INVOKE",
- target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V",
- remap = false)
- )
- public void perspective(float f1, float f2, float f3, float f4) {
- if (!FancyPortals.overridePerspective()) {
- Project.gluPerspective(f1, f2, f3, f4);
- }
- }
-
- @Inject(method = "updateCameraAndRender", at = @At("RETURN"))
- public void onUpdateCameraAndRender(float partialTicks, long nanoTime, CallbackInfo ci) {
- if (Minecraft.getMinecraft().getRenderViewEntity() == null) return;
-
- if (FancyPortals.shouldRenderWorldOverlay()) {
- GlStateManager.matrixMode(5889);
- GlStateManager.loadIdentity();
- Project.gluPerspective(getFOVModifier(partialTicks, true),
- (float) mc.displayWidth / (float) this.mc.displayHeight, 0.05F,
- farPlaneDistance * MathHelper.SQRT_2
- );
- GlStateManager.matrixMode(5888);
- GlStateManager.loadIdentity();
- orientCamera(partialTicks);
-
- FancyPortals.onUpdateCameraAndRender(partialTicks, nanoTime);
-
- Minecraft.getMinecraft().entityRenderer.setupOverlayRendering();
- }
- }
-
- @Redirect(method = "renderWorldPass", at = @At(
- value = "INVOKE",
target = "Lnet/minecraftforge/client/ForgeHooksClient;dispatchRenderLast(Lnet/minecraft/client/renderer/RenderGlobal;F)V",
remap = false)
)
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntitySkeleton.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntitySkeleton.java
new file mode 100644
index 00000000..49c7ccb2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntitySkeleton.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.monster.EntitySkeleton;
+import net.minecraft.world.World;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(EntitySkeleton.class)
+public class MixinEntitySkeleton {
+ @Redirect(method = "setCurrentItemOrArmor", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;isRemote:Z"))
+ public boolean onSetCurrentItemOrArmor(World instance) {
+ if (instance == null)
+ return true;
+ return instance.isRemote;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java
index c0d5627d..94b1c704 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
@@ -41,7 +60,7 @@ public class MixinGuiChest {
private static final String TARGET_SBADRAWSTRING = "Lcodes/biscuit/skyblockaddons/asm/hooks/GuiChestHook;" +
"drawString(Lnet/minecraft/client/gui/FontRenderer;Ljava/lang/String;III)I";
- @Redirect(method = "drawGuiContainerForegroundLayer", at = @At(value = "INVOKE", target = TARGET_SBADRAWSTRING, remap = false))
+ @Redirect(method = "drawGuiContainerForegroundLayer", at = @At(value = "INVOKE", target = TARGET_SBADRAWSTRING, remap = false), expect = 0)
public int drawGuiContainerForegroundLayer_SBA_drawString(
FontRenderer fontRenderer,
String text,
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
index 4d1545b6..81918939 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
@@ -1,11 +1,37 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.miscfeatures.*;
+import io.github.moulberry.notenoughupdates.events.SlotClickEvent;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
+import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.AuctionSortModeWarning;
+import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
+import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
+import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant;
import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
@@ -33,7 +59,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
@Mixin(GuiContainer.class)
public abstract class MixinGuiContainer extends GuiScreen {
@@ -70,8 +95,9 @@ public abstract class MixinGuiContainer extends GuiScreen {
NBTTagCompound tag = eventGui.inventorySlots.inventorySlots.get(22).getStack().getTagCompound();
if (tag.hasKey("SkullOwner") && tag.getCompoundTag("SkullOwner").hasKey("Name")) {
String tagName = tag.getCompoundTag("SkullOwner").getString("Name");
- String displayname = Utils.cleanColour(cc.inventorySlots.get(22).getStack().getDisplayName());
- if (tagName.equals(displayname.substring(displayname.length() - tagName.length()))) {
+ String displayName = Utils.cleanColour(cc.inventorySlots.get(22).getStack().getDisplayName());
+ if (displayName.length() - tagName.length() >= 0 && tagName.equals(displayName.substring(
+ displayName.length() - tagName.length()))) {
ci.cancel();
this.zLevel = 100.0F;
@@ -100,7 +126,8 @@ public abstract class MixinGuiContainer extends GuiScreen {
else if (!($this instanceof GuiChest))
BetterContainers.profileViewerStackIndex = -1;
- if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ if (slot.getStack() == null && NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen &&
+ NotEnoughUpdates.INSTANCE.isOnSkyblock()) {
GlStateManager.pushMatrix();
GlStateManager.translate(0, 0, 100 + Minecraft.getMinecraft().getRenderItem().zLevel);
GlStateManager.depthMask(false);
@@ -164,7 +191,9 @@ public abstract class MixinGuiContainer extends GuiScreen {
public void isMouseOverSlot(Slot slotIn, int mouseX, int mouseY, CallbackInfoReturnable<Boolean> cir) {
StorageOverlay.getInstance().overrideIsMouseOverSlot(slotIn, mouseX, mouseY, cir);
GuiCustomEnchant.getInstance().overrideIsMouseOverSlot(slotIn, mouseX, mouseY, cir);
+ GuiCustomHex.getInstance().overrideIsMouseOverSlot(slotIn, mouseX, mouseY, cir);
AuctionBINWarning.getInstance().overrideIsMouseOverSlot(slotIn, mouseX, mouseY, cir);
+ AbiphoneWarning.getInstance().overrideIsMouseOverSlot(slotIn, mouseX, mouseY, cir);
}
@Redirect(method = "drawScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/inventory/GuiContainer;drawGradientRect(IIIIII)V"))
@@ -274,60 +303,20 @@ public abstract class MixinGuiContainer extends GuiScreen {
@Inject(method = "handleMouseClick", at = @At(value = "HEAD"), cancellable = true)
public void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType, CallbackInfo ci) {
+ if (slotIn == null) return;
GuiContainer $this = (GuiContainer) (Object) this;
-
- if (AuctionBINWarning.getInstance().onMouseClick(slotIn, slotId, clickedButton, clickType)) {
+ SlotClickEvent event = new SlotClickEvent($this, slotIn, slotId, clickedButton, clickType);
+ event.post();
+ if (event.isCanceled()) {
ci.cancel();
return;
}
-
- AtomicBoolean ret = new AtomicBoolean(false);
- SlotLocking.getInstance().onWindowClick(slotIn, slotId, clickedButton, clickType, (tuple) -> {
+ if (event.usePickblockInstead) {
+ $this.mc.playerController.windowClick(
+ $this.inventorySlots.windowId,
+ slotId, 2, 3, $this.mc.thePlayer
+ );
ci.cancel();
-
- if (tuple == null) {
- ret.set(true);
- } else {
- int newSlotId = tuple.getLeft();
- int newClickedButton = tuple.getMiddle();
- int newClickedType = tuple.getRight();
-
- ret.set(true);
- $this.mc.playerController.windowClick(
- $this.inventorySlots.windowId,
- newSlotId,
- newClickedButton,
- newClickedType,
- $this.mc.thePlayer
- );
- }
- });
- if (ret.get()) return;
-
- if (slotIn != null && slotIn.getStack() != null) {
- if (EnchantingSolvers.onStackClick(slotIn.getStack(), $this.inventorySlots.windowId,
- slotId, clickedButton, clickType
- )) {
- ci.cancel();
- } else {
- PetInfoOverlay.onStackClick(slotIn.getStack(), $this.inventorySlots.windowId,
- slotId, clickedButton, clickType
- );
- }
- }
- if (slotIn != null && BetterContainers.isOverriding() && (BetterContainers.isBlankStack(
- slotIn.slotNumber,
- slotIn.getStack()
- ) ||
- BetterContainers.isButtonStack(slotIn.slotNumber, slotIn.getStack()))) {
- BetterContainers.clickSlot(slotIn.getSlotIndex());
-
- if (BetterContainers.isBlankStack(slotIn.slotNumber, slotIn.getStack())) {
- $this.mc.playerController.windowClick($this.inventorySlots.windowId, slotId, 2, clickType, $this.mc.thePlayer);
- ci.cancel();
- } else {
- Utils.playPressSound();
- }
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiEditSign.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiEditSign.java
new file mode 100644
index 00000000..bfdf05ab
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiEditSign.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.events.SignSubmitEvent;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.tileentity.TileEntitySign;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.IChatComponent;
+import org.objectweb.asm.Opcodes;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(GuiEditSign.class)
+public class MixinGuiEditSign {
+
+ @Redirect(method = "onGuiClosed", at = @At(value = "FIELD", opcode = Opcodes.GETFIELD, target = "Lnet/minecraft/tileentity/TileEntitySign;signText:[Lnet/minecraft/util/IChatComponent;"))
+ public IChatComponent[] onOnGuiClosed(TileEntitySign instance) {
+ String[] x = new String[4];
+ for (int i = 0; i < 4; i++) {
+ x[i] = instance.signText[i].getUnformattedText();
+ }
+ SignSubmitEvent signSubmitEvent = new SignSubmitEvent((GuiEditSign) (Object) this, x);
+ signSubmitEvent.post();
+ IChatComponent[] arr = new IChatComponent[4];
+ for (int i = 0; i < 4; i++) {
+ arr[i] = new ChatComponentText(signSubmitEvent.lines[i]);
+ }
+ return arr;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java
index 7f7f25c8..381f5934 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiIngame.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -24,7 +43,7 @@ public class MixinGuiIngame {
@Redirect(method = "renderScoreboard", at = @At(value = "INVOKE", target = TARGET))
public String renderScoreboard_formatPlayerName(Team team, String name) {
- if (NotEnoughUpdates.INSTANCE.isOnSkyblock() && NotEnoughUpdates.INSTANCE.config.misc.streamerMode) {
+ if (NotEnoughUpdates.INSTANCE.config.misc.streamerMode) {
return StreamerMode.filterScoreboard(ScorePlayerTeam.formatPlayerName(team, name));
}
return ScorePlayerTeam.formatPlayerName(team, name);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java
index 25b036ab..86ed9b8f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiInventory.java
@@ -1,7 +1,28 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.GuiInventoryBackgroundDrawnEvent;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
+import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiInventory;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -13,8 +34,13 @@ public class MixinGuiInventory {
@Inject(method = "drawGuiContainerForegroundLayer", at = @At("HEAD"), cancellable = true)
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY, CallbackInfo ci) {
if (NotEnoughUpdates.INSTANCE.config.inventoryButtons.hideCrafting ||
- NEUEventListener.disableCraftingText) {
+ RenderListener.disableCraftingText) {
ci.cancel();
}
}
+
+ @Inject(method = "drawGuiContainerBackgroundLayer", at = @At("TAIL"))
+ public void onDrawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY, CallbackInfo ci) {
+ new GuiInventoryBackgroundDrawnEvent((GuiContainer) (Object) this, partialTicks).post();
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiScreen.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiScreen.java
index eac2b2d5..b978b433 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiScreen.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiScreen.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.util.SBInfo;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
index fb5707fe..dbcb260d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java
index 345b5171..de117002 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryPlayer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemCameraTransforms.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemCameraTransforms.java
index da2b2e08..bbe0f842 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemCameraTransforms.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemCameraTransforms.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomSkulls;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemRenderer.java
index d691b79f..c2739ad8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscgui.InventoryStorageSelector;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
index 25109704..83379a18 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerArmorBase.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerArmorBase.java
index a085c5d1..773e7ebe 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerArmorBase.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerArmorBase.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.core.ChromaColour;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCustomHead.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCustomHead.java
index a2785ec7..90101696 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCustomHead.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLayerCustomHead.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import com.mojang.authlib.GameProfile;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java
deleted file mode 100644
index dbdad65a..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package io.github.moulberry.notenoughupdates.mixins;
-
-import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals;
-import net.minecraft.client.LoadingScreenRenderer;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(LoadingScreenRenderer.class)
-public class MixinLoadingScreenRenderer {
- @Inject(method = "setLoadingProgress", at = @At(value = "HEAD"), cancellable = true)
- public void setLoadingProgress(int progress, CallbackInfo ci) {
- if (progress < 0 && !FancyPortals.shouldRenderLoadingScreen()) {
- ci.cancel();
- }
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMinecraft.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMinecraft.java
index b01e9609..abc9d8c6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMinecraft.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMinecraft.java
@@ -1,8 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
import net.minecraft.client.Minecraft;
-import org.spongepowered.asm.lib.Opcodes;
+import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java
index 4d8df949..a89893b9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinMouseHelper.java
@@ -1,6 +1,25 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
import net.minecraft.util.MouseHelper;
import org.lwjgl.input.Mouse;
import org.spongepowered.asm.mixin.Mixin;
@@ -12,7 +31,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class MixinMouseHelper {
@Inject(method = {"ungrabMouseCursor"}, at = {@At("HEAD")}, cancellable = true)
public void ungrabMouseCursor(final CallbackInfo ci) {
- if (System.currentTimeMillis() - NEUEventListener.lastGuiClosed < 150L) {
+ if (System.currentTimeMillis() - RenderListener.lastGuiClosed < 150L) {
ci.cancel();
Mouse.setGrabbed(false);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
index d47dce2c..0b33609d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
@@ -1,13 +1,45 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
-import io.github.moulberry.notenoughupdates.miscfeatures.*;
+import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver;
+import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
+import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
+import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
+import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
+import io.github.moulberry.notenoughupdates.miscfeatures.NewApiKeyHelper;
+import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.Packet;
+import net.minecraft.network.play.client.C01PacketChatMessage;
import net.minecraft.network.play.client.C0EPacketClickWindow;
-import net.minecraft.network.play.server.*;
+import net.minecraft.network.play.server.S23PacketBlockChange;
+import net.minecraft.network.play.server.S2DPacketOpenWindow;
+import net.minecraft.network.play.server.S2EPacketCloseWindow;
+import net.minecraft.network.play.server.S2FPacketSetSlot;
+import net.minecraft.network.play.server.S30PacketWindowItems;
+import net.minecraft.network.play.server.S47PacketPlayerListHeaderFooter;
import net.minecraft.util.EnumParticleTypes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -47,6 +79,12 @@ public class MixinNetHandlerPlayClient {
double xCoord, double yCoord, double zCoord,
double xOffset, double yOffset, double zOffset, int[] params
) {
+ CrystalWishingCompassSolver.getInstance().onSpawnParticle(
+ particleTypes,
+ xCoord,
+ yCoord,
+ zCoord
+ );
boolean override = FishingHelper.getInstance().onSpawnParticle(
particleTypes,
xCoord,
@@ -61,11 +99,6 @@ public class MixinNetHandlerPlayClient {
}
}
- @Inject(method = "handleSpawnMob", at = @At("RETURN"))
- public void handleSpawnMob(S0FPacketSpawnMob packetIn, CallbackInfo ci) {
- //CollectionLogManager.getInstance().onEntityMetadataUpdated(packetIn.getEntityID());
- }
-
@Inject(method = "handleSetSlot", at = @At("RETURN"))
public void handleSetSlot(S2FPacketSetSlot packetIn, CallbackInfo ci) {
EnchantingSolvers.processInventoryContents(false);
@@ -87,25 +120,20 @@ public class MixinNetHandlerPlayClient {
StorageManager.getInstance().setItemsPacket(packetIn);
}
- @Inject(method = "handleRespawn", at = @At(
- value = "INVOKE",
- target = "Lnet/minecraft/network/PacketThreadUtil;checkThreadAndEnqueue(Lnet/minecraft/network/Packet;Lnet/minecraft/network/INetHandler;Lnet/minecraft/util/IThreadListener;)V",
- shift = At.Shift.AFTER))
- public void handleOpenWindow(S07PacketRespawn packetIn, CallbackInfo ci) {
- FancyPortals.onRespawnPacket(packetIn);
- }
-
@Inject(method = "handleBlockChange", at = @At("HEAD"))
public void handleBlockChange(S23PacketBlockChange packetIn, CallbackInfo ci) {
MiningStuff.processBlockChangePacket(packetIn);
ItemCooldowns.processBlockChangePacket(packetIn);
}
- @Inject(method = "addToSendQueue", at = @At("HEAD"))
+ @Inject(method = "addToSendQueue", at = @At("HEAD"), cancellable = true)
public void addToSendQueue(Packet packet, CallbackInfo ci) {
if (packet instanceof C0EPacketClickWindow) {
StorageManager.getInstance().clientSendWindowClick((C0EPacketClickWindow) packet);
}
+ if (packet instanceof C01PacketChatMessage) {
+ NewApiKeyHelper.getInstance().hookPacketChatMessage((C01PacketChatMessage) packet);
+ }
}
@Inject(method = "handlePlayerListHeaderFooter", at = @At("HEAD"))
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
index b4481a73..fc8fee02 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.events.OnBlockBreakSoundEffect;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java
index 14aad887..db35fcb9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java
index 9e989311..ca40c5e7 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -178,4 +197,4 @@ public abstract class MixinRenderFish extends Render<EntityFishHook> {
private static double mathLerp(double var1, double var2, double var3) {
return var2 + var1 * (var3 - var2);
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java
index fc3347bf..30c6b36e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
index 630874ab..7c2cfcbf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
@@ -1,11 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
-import io.github.moulberry.notenoughupdates.NEUEventListener;
import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.ChromaColour;
+import io.github.moulberry.notenoughupdates.listener.RenderListener;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.Gui;
@@ -176,7 +196,7 @@ public abstract class MixinRenderItem {
@Inject(method = "renderItemIntoGUI", at = @At("HEAD"))
public void renderItemHead(ItemStack stack, int x, int y, CallbackInfo ci) {
- if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock() && !(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer)) {
boolean matches = false;
GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
@@ -202,7 +222,7 @@ public abstract class MixinRenderItem {
@Inject(method = "renderItemIntoGUI", at = @At("RETURN"))
public void renderItemReturn(ItemStack stack, int x, int y, CallbackInfo ci) {
if (stack != null && stack.stackSize != 1) return;
- if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock() && !(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer)) {
boolean matches = false;
GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
@@ -233,7 +253,7 @@ public abstract class MixinRenderItem {
CallbackInfo ci
) {
if (stack != null && stack.stackSize != 1) {
- if (NotEnoughUpdates.INSTANCE.overlay.searchMode && NEUEventListener.drawingGuiScreen) {
+ if (NotEnoughUpdates.INSTANCE.overlay.searchMode && RenderListener.drawingGuiScreen && NotEnoughUpdates.INSTANCE.isOnSkyblock() && !(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer)) {
boolean matches = false;
GuiTextField textField = NotEnoughUpdates.INSTANCE.overlay.getTextField();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java
index 8c1cc247..e7782bcd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRendererLivingEntity.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRendererLivingEntity.java
index 16c6c99c..5503c8cf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRendererLivingEntity.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRendererLivingEntity.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTextureManager.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTextureManager.java
index de6d1537..d8a48ecd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTextureManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTextureManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySkullRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySkullRenderer.java
index 71750fec..0b70f790 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySkullRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySkullRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import com.mojang.authlib.GameProfile;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java
index f93608b1..2f342614 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java
index 73cb19d3..22448944 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorld.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorld.java
index 86073984..b738359a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorld.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorld.java
@@ -1,8 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
+import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeGenBase;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java
index b20ff8fd..84e6da86 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
index 470b0381..4d04bfbc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
@@ -1,6 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options;
import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
@@ -8,20 +28,52 @@ import io.github.moulberry.notenoughupdates.core.config.Config;
import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.core.config.annotations.Category;
import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
+import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
import io.github.moulberry.notenoughupdates.miscgui.GuiEnchantColour;
import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor;
import io.github.moulberry.notenoughupdates.miscgui.NEUOverlayPlacements;
-import io.github.moulberry.notenoughupdates.options.seperateSections.*;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
+import io.github.moulberry.notenoughupdates.options.seperateSections.AHGraph;
+import io.github.moulberry.notenoughupdates.options.seperateSections.AHTweaks;
+import io.github.moulberry.notenoughupdates.options.seperateSections.AccessoryBag;
+import io.github.moulberry.notenoughupdates.options.seperateSections.ApiData;
+import io.github.moulberry.notenoughupdates.options.seperateSections.BazaarTweaks;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Calendar;
import io.github.moulberry.notenoughupdates.options.seperateSections.CustomArmour;
+import io.github.moulberry.notenoughupdates.options.seperateSections.DungeonMapConfig;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Dungeons;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Enchanting;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Fishing;
+import io.github.moulberry.notenoughupdates.options.seperateSections.ImprovedSBMenu;
+import io.github.moulberry.notenoughupdates.options.seperateSections.InventoryButtons;
+import io.github.moulberry.notenoughupdates.options.seperateSections.ItemOverlays;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Itemlist;
+import io.github.moulberry.notenoughupdates.options.seperateSections.LocationEdit;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Mining;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Misc;
+import io.github.moulberry.notenoughupdates.options.seperateSections.MiscOverlays;
+import io.github.moulberry.notenoughupdates.options.seperateSections.NeuAuctionHouse;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Notifications;
+import io.github.moulberry.notenoughupdates.options.seperateSections.PetOverlay;
+import io.github.moulberry.notenoughupdates.options.seperateSections.ProfileViewer;
+import io.github.moulberry.notenoughupdates.options.seperateSections.SkillOverlays;
+import io.github.moulberry.notenoughupdates.options.seperateSections.SlayerOverlay;
+import io.github.moulberry.notenoughupdates.options.seperateSections.SlotLocking;
+import io.github.moulberry.notenoughupdates.options.seperateSections.StorageGUI;
+import io.github.moulberry.notenoughupdates.options.seperateSections.Toolbar;
+import io.github.moulberry.notenoughupdates.options.seperateSections.TooltipTweaks;
+import io.github.moulberry.notenoughupdates.options.seperateSections.TradeMenu;
import io.github.moulberry.notenoughupdates.overlays.MiningOverlay;
import io.github.moulberry.notenoughupdates.overlays.OverlayManager;
import io.github.moulberry.notenoughupdates.overlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.util.NotificationHandler;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import net.minecraft.client.Minecraft;
import net.minecraftforge.client.ClientCommandHandler;
import org.lwjgl.util.vector.Vector2f;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -49,6 +101,8 @@ public class NEUConfig extends Config {
}
switch (runnableId) {
+ case -1:
+ return;
case 0:
ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neumap");
return;
@@ -100,6 +154,10 @@ public class NEUConfig extends Config {
case 14:
editOverlay(activeConfigCategory, OverlayManager.fishingSkillOverlay, skillOverlays.fishingPosition);
return;
+ case 15:
+ String command = NotEnoughUpdates.INSTANCE.config.misc.fariySoul ? "/neusouls on" : "/neusouls off";
+ ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, command);
+ return;
case 16:
ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neusouls clear");
return;
@@ -111,7 +169,36 @@ public class NEUConfig extends Config {
return;
case 19:
editOverlay(activeConfigCategory, OverlayManager.combatSkillOverlay, skillOverlays.combatPosition);
-
+ return;
+ case 20:
+ FairySouls.getInstance().setTrackFairySouls(NotEnoughUpdates.INSTANCE.config.misc.trackFairySouls);
+ return;
+ case 21:
+ NotEnoughUpdates.INSTANCE.overlay.updateSearch();
+ return;
+ case 22:
+ NotEnoughUpdates.INSTANCE.manager
+ .userFacingRepositoryReload()
+ .thenAccept(strings ->
+ NotificationHandler.displayNotification(strings, true, true));
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ return;
+ case 23:
+ NotEnoughUpdates.INSTANCE.config.apiData.repoUser = "NotEnoughUpdates";
+ NotEnoughUpdates.INSTANCE.config.apiData.repoName = "NotEnoughUpdates-REPO";
+ NotEnoughUpdates.INSTANCE.config.apiData.repoBranch = "master";
+ NotEnoughUpdates.INSTANCE.openGui =
+ new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config, "apis"));
+ return;
+ case 24:
+ NotEnoughUpdates.INSTANCE.config.apiData.repoUser = "NotEnoughUpdates";
+ NotEnoughUpdates.INSTANCE.config.apiData.repoName = "NotEnoughUpdates-REPO";
+ NotEnoughUpdates.INSTANCE.config.apiData.repoBranch = "dangerous";
+ NotEnoughUpdates.INSTANCE.openGui =
+ new GuiScreenElementWrapper(new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config, "apis"));
+ return;
+ default:
+ System.err.printf("Unknown runnableId = %d in category %s%n", runnableId, activeConfigCategory);
}
}
@@ -250,8 +337,8 @@ public class NEUConfig extends Config {
@Expose
@Category(
- name = "Custom Armour Hud",
- desc = "Custom Armour Hud"
+ name = "Equipment Hud",
+ desc = "Equipment Hud"
)
public CustomArmour customArmour = new CustomArmour();
@@ -285,6 +372,13 @@ public class NEUConfig extends Config {
@Expose
@Category(
+ name = "Bazaar Tweaks",
+ desc = "Tweaks for the Bazaar"
+ )
+ public BazaarTweaks bazaarTweaks = new BazaarTweaks();
+
+ @Expose
+ @Category(
name = "AH/BZ Graph",
desc = "Graph of auction and bazaar prices"
)
@@ -299,10 +393,26 @@ public class NEUConfig extends Config {
@Expose
@Category(
- name = "Api Key",
- desc = "Api Key"
+ name = "Profile Viewer",
+ desc = "Profile Viewer"
)
- public ApiKey apiKey = new ApiKey();
+ public ProfileViewer profileViewer = new ProfileViewer();
+
+ @Expose
+ @Category(
+ name = "Apis",
+ desc = "Api Data"
+ )
+ public ApiData apiData = new ApiData();
+
+ @Expose
+ public LegacyApiKey apiKey = null;
+
+ public static class LegacyApiKey {
+ // Blame Ironmoon for this (still better than my idea tho)
+ @Expose
+ public String apiKey = null;
+ }
@Expose
public Hidden hidden = new Hidden();
@@ -319,12 +429,10 @@ public class NEUConfig extends Config {
public List<NEUConfig.InventoryButton> inventoryButtons = createDefaultInventoryButtons();
@Expose
- public boolean enableItemEditing = false;
+ public EnumSet<NEUDebugFlag> debugFlags = EnumSet.noneOf(NEUDebugFlag.class);
@Expose
public boolean cacheRenderedItempane = true;
@Expose
- public boolean autoupdate = true;
- @Expose
public String overlaySearchBar = "";
@Expose
public String overlayQuickCommand = "";
@@ -345,15 +453,13 @@ public class NEUConfig extends Config {
@Expose
public ArrayList<String> previousAuctionSearches = new ArrayList<>();
@Expose
+ public ArrayList<String> previousBazaarSearches = new ArrayList<>();
+ @Expose
public ArrayList<String> eventFavourites = new ArrayList<>();
@Expose
public ArrayList<String> quickCommands = createDefaultQuickCommands();
@Expose
public ArrayList<String> enchantColours = createDefaultEnchantColours();
- @Expose
- public String repoURL = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
- @Expose
- public String repoCommitsURL = "https://api.github.com/repos/Moulberry/NotEnoughUpdates-REPO/commits/master";
@Expose
public boolean firstTimeSearchFocus = true;
@@ -366,6 +472,9 @@ public class NEUConfig extends Config {
@Expose
public boolean npcRetextureOnSelf = false;
+ @Expose
+ public boolean hasOpenedWaypointMenu = false;
+
}
public static ArrayList<String> createDefaultEnchantColours() {
@@ -459,6 +568,14 @@ public class NEUConfig extends Config {
public long dailyGemstonePowderCompleted = 0L;
@Expose
public long dailyMithrilPowerCompleted = 0L;
+ @Expose
+ public HashMap<String, Boolean> unlockedWarpScrolls = new HashMap<>();
+ @Expose
+ public long dailyHeavyPearlCompleted = 0L;
+ @Expose
+ public HashMap<Integer, JsonObject> savedEquipment = new HashMap<>();
+ @Expose
+ public int magicalPower = 0;
}
public HiddenLocationSpecific getLocationSpecific() {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
index 6681a994..17bc57e9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options;
import com.google.common.collect.Lists;
@@ -27,14 +46,22 @@ import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.*;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
-import static io.github.moulberry.notenoughupdates.util.GuiTextures.*;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.DISCORD;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.GITHUB;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.PATREON;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.TWITCH;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.TWITTER;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.YOUTUBE;
public class NEUConfigEditor extends GuiElement {
- public static NEUConfigEditor editor = new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config);
-
private static final ResourceLocation[] socialsIco = new ResourceLocation[]{
DISCORD,
GITHUB,
@@ -51,27 +78,25 @@ public class NEUConfigEditor extends GuiElement {
"https://patreon.com/moulberry",
"https://www.twitch.tv/moulberry2"
};
-
private static final ResourceLocation SEARCH_ICON = new ResourceLocation("notenoughupdates:core/search.png");
-
+ public static NEUConfigEditor editor = new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config);
private final long openedMillis;
-
- private String selectedCategory = null;
-
private final LerpingInteger optionsScroll = new LerpingInteger(0, 150);
private final LerpingInteger categoryScroll = new LerpingInteger(0, 150);
-
private final LinkedHashMap<String, ConfigProcessor.ProcessedCategory> processedConfig;
private final TreeMap<String, Set<ConfigProcessor.ProcessedOption>> searchOptionMap = new TreeMap<>();
private final HashMap<ConfigProcessor.ProcessedOption, ConfigProcessor.ProcessedCategory> categoryForOption =
new HashMap<>();
-
+ private final LerpingInteger minimumSearchSize = new LerpingInteger(0, 150);
+ private final GuiElementTextField searchField = new GuiElementTextField("", 0, 20, 0);
+ private String selectedCategory = null;
private Set<ConfigProcessor.ProcessedCategory> searchedCategories = null;
private Map<ConfigProcessor.ProcessedCategory, Set<Integer>> searchedAccordions = null;
private Set<ConfigProcessor.ProcessedOption> searchedOptions = null;
-
- private final LerpingInteger minimumSearchSize = new LerpingInteger(0, 150);
- private final GuiElementTextField searchField = new GuiElementTextField("", 0, 20, 0);
+ private float optionsBarStart;
+ private float optionsBarend;
+ private int lastMouseX = 0;
+ private int keyboardScrollXCutoff = 0;
public NEUConfigEditor(Config config) {
this(config, null);
@@ -160,15 +185,15 @@ public class NEUConfigEditor extends GuiElement {
return selectedCategory;
}
- public String getSelectedCategoryName() {
- return processedConfig.get(selectedCategory).name;
- }
-
private void setSelectedCategory(String category) {
selectedCategory = category;
optionsScroll.setValue(0);
}
+ public String getSelectedCategoryName() {
+ return processedConfig.get(selectedCategory).name;
+ }
+
public void search() {
String search = searchField.getText().trim().replaceAll("[^a-zA-Z_ ]", "").toLowerCase();
searchedCategories = null;
@@ -215,6 +240,7 @@ public class NEUConfigEditor extends GuiElement {
public void render() {
optionsScroll.tick();
categoryScroll.tick();
+ handleKeyboardPresses();
List<String> tooltipToDisplay = null;
@@ -486,10 +512,10 @@ public class NEUConfigEditor extends GuiElement {
}
GL11.glEnable(GL11.GL_SCISSOR_TEST);
- float barStart = optionsScroll.getValue() / (float) (optionY + optionsScroll.getValue());
- float barEnd = barStart + barSize;
- if (barEnd > 1) {
- barEnd = 1;
+ optionsBarStart = optionsScroll.getValue() / (float) (optionY + optionsScroll.getValue());
+ optionsBarend = optionsBarStart + barSize;
+ if (optionsBarend > 1) {
+ optionsBarend = 1;
if (optionsScroll.getTarget() / (float) (optionY + optionsScroll.getValue()) + barSize < 1) {
int target = optionsScroll.getTarget();
optionsScroll.setValue((int) Math.ceil(
@@ -504,9 +530,9 @@ public class NEUConfigEditor extends GuiElement {
Gui.drawRect(innerRight - 10, innerTop + 5, innerRight - 5, innerBottom - 5, 0xff101010);
Gui.drawRect(
innerRight - 9,
- innerTop + 6 + (int) (dist * barStart),
+ innerTop + 6 + (int) (dist * optionsBarStart),
innerRight - 6,
- innerTop + 6 + (int) (dist * barEnd),
+ innerTop + 6 + (int) (dist * optionsBarend),
0xff303030
);
@@ -533,6 +559,7 @@ public class NEUConfigEditor extends GuiElement {
}
public boolean mouseInput(int mouseX, int mouseY) {
+ lastMouseX = mouseX;
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
int height = scaledResolution.getScaledHeight();
@@ -551,7 +578,40 @@ public class NEUConfigEditor extends GuiElement {
int innerLeft = x + 149 + innerPadding;
int innerRight = x + xSize - 5 - innerPadding;
+ int dist = innerBottom - innerTop - 12;
+ int optionsBarStartY = innerTop + 6 + (int) (dist * optionsBarStart);
+ int optionsBarEndY = innerTop + 6 + (int) (dist * optionsBarend);
+ int optionsBarStartX = innerRight - 12;
+ int optionsBarEndX = innerRight - 3;
+
+ int categoryY = -categoryScroll.getValue();
+ categoryY += 15 * getCurrentConfigEditing().size();
+ int catDist = innerBottom - innerTop - 12;
+ float catBarStart = categoryScroll.getValue() / (float) (categoryY + categoryScroll.getValue());
+ float categoryBarSize = LerpUtils.clampZeroOne(
+ (float) (innerBottom - innerTop - 2) / (categoryY + 5 + categoryScroll.getValue()));
+ float catBarEnd = catBarStart + categoryBarSize;
+ int categoryBarStartY = innerTop + 6 + (int) (catDist * catBarStart);
+ int categoryBarEndY = innerTop + 6 + (int) (catDist * catBarEnd);
+ int categoryBarStartX = x + innerPadding + 7;
+ int categoryBarEndX = x + innerPadding + 12;
+ keyboardScrollXCutoff = innerLeft - 10;
if (Mouse.getEventButtonState()) {
+ if ((mouseY < optionsBarStartY || mouseY > optionsBarEndY) &&
+ (mouseX >= optionsBarStartX && mouseX <= optionsBarEndX) && mouseY > innerTop + 6 && mouseY < innerBottom - 6) {
+ optionsScroll.setTimeToReachTarget(200);
+ optionsScroll.resetTimer();
+ optionsScroll.setTarget(mouseY - innerTop);
+ return true;
+ } else if ((mouseY < categoryBarStartY || mouseY > categoryBarEndY) &&
+ (mouseX >= categoryBarStartX && mouseX <= categoryBarEndX) && mouseY > innerTop + 6 &&
+ mouseY < innerBottom - 6) {
+ categoryScroll.setTimeToReachTarget(200);
+ categoryScroll.resetTimer();
+ categoryScroll.setTarget(mouseY - innerTop);
+ return true;
+ }
+
searchField.setFocus(mouseX >= innerRight - 20 && mouseX <= innerRight - 2 &&
mouseY >= innerTop - (20 + innerPadding) / 2 - 9 && mouseY <= innerTop - (20 + innerPadding) / 2 + 9);
@@ -788,7 +848,6 @@ public class NEUConfigEditor extends GuiElement {
int innerWidth = xSize - 154 - innerPadding * 2;
if (Keyboard.getEventKeyState()) {
- Keyboard.enableRepeatEvents(true);
String old = searchField.getText();
searchField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
searchField.setText(Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(
@@ -832,4 +891,22 @@ public class NEUConfigEditor extends GuiElement {
return true;
}
+
+ private void handleKeyboardPresses() {
+ LerpingInteger target = lastMouseX < keyboardScrollXCutoff ? categoryScroll : optionsScroll;
+ if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
+ target.setTimeToReachTarget(50);
+ target.resetTimer();
+ target.setTarget(target.getTarget() + 5);
+ } else if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
+ target.setTimeToReachTarget(50);
+ target.resetTimer();
+ if (target.getTarget() >= 0) {
+ target.setTarget(target.getTarget() - 5);
+ }
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
+ NotEnoughUpdates.INSTANCE.saveConfig();
+ }
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java
new file mode 100644
index 00000000..50f459c0
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/customtypes/NEUDebugFlag.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.customtypes;
+
+import io.github.moulberry.notenoughupdates.util.NEUDebugLogger;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public enum NEUDebugFlag {
+ // NOTE: Removing enum values causes gson to remove all debugFlags on load if any removed value is present
+ METAL("Metal Detector Solver"),
+ WISHING("Wishing Compass Solver"),
+ MAP("Dungeon Map Player Information"),
+ SEARCH("SearchString Matches"),
+ ;
+
+ private final String description;
+
+ NEUDebugFlag(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public boolean isSet() {
+ return NEUDebugLogger.isFlagEnabled(this);
+ }
+
+ public static String getFlagList() {
+ return renderFlagInformation(Arrays.asList(values()));
+ }
+
+ public static String getEnabledFlags() {
+ return renderFlagInformation(Arrays.stream(values())
+ .filter(NEUDebugFlag::isSet)
+ .collect(Collectors.toList()));
+ }
+
+ public static String renderFlagInformation(List<NEUDebugFlag> flags) {
+ int maxNameLength = flags.stream()
+ .mapToInt(it -> it.name().length())
+ .max()
+ .orElse(0);
+ return flags.stream()
+ .map(it -> (CharSequence) String.format(
+ "%-" + maxNameLength + "s" + " - %s",
+ it.name(),
+ it.getDescription()
+ ))
+ .collect(Collectors.joining("\n"));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHGraph.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHGraph.java
index 8d3acaf9..ce931392 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHGraph.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHGraph.java
@@ -1,7 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
import org.lwjgl.input.Keyboard;
public class AHGraph {
@@ -27,7 +51,7 @@ public class AHGraph {
desc = "Change the style of the graph GUI"
)
@ConfigEditorDropdown(
- values = {"Minecraft", "Dark", "PacksHQ Dark", "FSR"}
+ values = {"Minecraft", "Grey", "PacksHQ Dark", "FSR"}
)
public int graphStyle = 0;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHTweaks.java
index 0d21a96f..298ddeda 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHTweaks.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AHTweaks.java
@@ -1,7 +1,30 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
public class AHTweaks {
@ConfigOption(
@@ -57,17 +80,26 @@ public class AHTweaks {
@Expose
@ConfigOption(
- name = "Enable BIN Warning",
+ name = "Enable Undercut BIN Warning",
desc = "Ask for confirmation when BINing an item for below X% of lowestbin"
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 1)
- public boolean enableBINWarning = true;
+ public boolean underCutWarning = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Overcut BIN Warning",
+ desc = "Ask for confirmation when BINing an item for over X% of lowestbin"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean overCutWarning = true;
@Expose
@ConfigOption(
- name = "Warning Threshold",
- desc = "Threshold for BIN warning\nExample: 10% means warn if sell price is 10% lower than lowestbin"
+ name = "Undercut Warning Threshold",
+ desc = "Threshold for BIN warning\nExample: 10% means warn if sell price is 10% lower than lowest bin"
)
@ConfigEditorSlider(
minValue = 0.0f,
@@ -77,6 +109,19 @@ public class AHTweaks {
@ConfigAccordionId(id = 1)
public float warningThreshold = 10f;
+ @Expose
+ @ConfigOption(
+ name = "Overcut Warning Threshold",
+ desc = "Threshold for BIN warning\nExample: 50% means warn if sell price is 50% higher than lowest bin"
+ )
+ @ConfigEditorSlider(
+ minValue = 0.0f,
+ maxValue = 100.0f,
+ minStep = 5f
+ )
+ @ConfigAccordionId(id = 1)
+ public float overcutWarningThreshold = 50f;
+
@ConfigOption(
name = "Sort Warning",
desc = ""
@@ -92,4 +137,13 @@ public class AHTweaks {
@ConfigEditorBoolean
@ConfigAccordionId(id = 2)
public boolean enableSortWarning = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable AH Sell Value",
+ desc = "Display profit information (coins to collect, value if all sold, expired and unclaimed auctions)"
+ )
+ @ConfigEditorBoolean
+ public boolean enableAhSellValue = true;
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AccessoryBag.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AccessoryBag.java
index 9a3d0946..b87db1d6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AccessoryBag.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/AccessoryBag.java
@@ -1,15 +1,34 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class AccessoryBag {
- @Expose
- @ConfigOption(
- name = "Enable Accessory Bag Overlay",
- desc = "Show an overlay on the accessory bag screen which gives useful information about your accessories"
- )
- @ConfigEditorBoolean
- public boolean enableOverlay = true;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class AccessoryBag {
+ @Expose
+ @ConfigOption(
+ name = "Enable Accessory Bag Overlay",
+ desc = "Show an overlay on the accessory bag screen which gives useful information about your accessories"
+ )
+ @ConfigEditorBoolean
+ public boolean enableOverlay = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiData.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiData.java
new file mode 100644
index 00000000..9ed09ac3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiData.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorText;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class ApiData {
+ @Expose
+ @ConfigOption(
+ name = "Api Key",
+ desc = "Hypixel api key\nYou can run §a/api new§r to autofill this value."
+ )
+ @ConfigEditorText
+ public String apiKey = "";
+
+ @ConfigEditorAccordion(id = 0)
+ @ConfigOption(name = "Repository", desc = "")
+ public boolean repository = false;
+
+ @Expose
+ @ConfigOption(name = "Automatically Update Repository", desc = "Update the repository on every startup")
+ @ConfigEditorBoolean()
+ @ConfigAccordionId(id = 0)
+ public boolean autoupdate = true;
+
+ @ConfigAccordionId(id = 0)
+ @ConfigOption(name = "Update Repository now", desc = "Refresh your repository")
+ @ConfigEditorButton(runnableId = 22, buttonText = "Update")
+ public int updateRepositoryButton = 0;
+
+ @ConfigEditorAccordion(id = 1)
+ @ConfigAccordionId(id = 0)
+ @ConfigOption(name = "Repository Location", desc = "")
+ public boolean repositoryLocation = false;
+
+ @ConfigAccordionId(id = 1)
+ @ConfigOption(name = "Use default repository", desc = "The latest, most up to date item list for the official NEU releases.")
+ @ConfigEditorButton(runnableId = 23, buttonText = "Reset")
+ public int setRepositoryToDefaultButton = 0;
+
+ @ConfigAccordionId(id = 1)
+ @ConfigOption(name = "Use pre-release repository", desc = "The latest, most up to date item list for the NEU pre-releases.\n§4Use §lonly§r§4 with the pre-releases.")
+ @ConfigEditorButton(runnableId = 24, buttonText = "Use")
+ public int setRepositoryToDangerousButton = 0;
+
+ @Expose
+ @ConfigAccordionId(id = 1)
+ @ConfigOption(name = "Repository User", desc = "Repository User")
+ @ConfigEditorText
+ public String repoUser = "NotEnoughUpdates";
+
+ @Expose
+ @ConfigAccordionId(id = 1)
+ @ConfigOption(name = "Repository Name", desc = "Repository Name")
+ @ConfigEditorText
+ public String repoName = "NotEnoughUpdates-REPO";
+
+ @Expose
+ @ConfigAccordionId(id = 1)
+ @ConfigOption(name = "Repository Branch", desc = "Repository Branch")
+ @ConfigEditorText
+ public String repoBranch = "master";
+
+ @Expose
+ @ConfigAccordionId(id = 0)
+ @ConfigOption(name = "Edit Mode", desc = "Enables you to edit items in the item list.\n§4Recommended for repository maintainers only.\n§4§lRemember: §rTurn off auto update as well")
+ @ConfigEditorBoolean
+ public boolean repositoryEditing = false;
+
+ @Expose
+ @ConfigOption(name = "Lowestbin API", desc = "§4Do §lNOT §r§4change this, unless you know exactly what you are doing\n§fDefault: §amoulberry.codes")
+ @ConfigEditorText
+ public String moulberryCodesApi = "moulberry.codes";
+
+ public String getCommitApiUrl() {
+ return String.format("https://api.github.com/repos/%s/%s/commits/%s", repoUser, repoName, repoBranch);
+ }
+
+ public String getDownloadUrl(String commitId) {
+ return String.format("https://github.com/%s/%s/archive/%s.zip", repoUser, repoName, commitId);
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiKey.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiKey.java
deleted file mode 100644
index 0c5e4d2d..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ApiKey.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorText;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class ApiKey {
- @Expose
- @ConfigOption(
- name = "Api Key",
- desc = "Hypixel api key"
- )
- @ConfigEditorText
- public String apiKey = "";
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java
new file mode 100644
index 00000000..954af02d
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/BazaarTweaks.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class BazaarTweaks {
+
+ @ConfigOption(
+ name = "Search GUI",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean searchAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Search GUI",
+ desc = "Use the advanced search GUI with autocomplete and history instead of the normal sign GUI"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableSearchOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Keep Previous Search",
+ desc = "Don't clear the search bar after closing the GUI"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean keepPreviousSearch = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Past Searches",
+ desc = "Show past searches below the autocomplete box"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showPastSearches = true;
+
+ @Expose
+ @ConfigOption(
+ name = "ESC to Full Close",
+ desc = "Make pressing ESCAPE close the search GUI without opening up the Bazaar again\n" +
+ "ENTER can still be used to search"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean escFullClose = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Calendar.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Calendar.java
index 332f5e8d..fe593f56 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Calendar.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Calendar.java
@@ -1,53 +1,72 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class Calendar {
- @Expose
- @ConfigOption(
- name = "Event Notifications",
- desc = "Display notifications for skyblock calendar events"
- )
- @ConfigEditorBoolean
- public boolean eventNotifications = true;
-
- @Expose
- @ConfigOption(
- name = "Starting Soon Time",
- desc = "Display a notification before events start, time in seconds.\n" +
- "0 = No prior notification"
- )
- @ConfigEditorSlider(
- minValue = 0f,
- maxValue = 600f,
- minStep = 30f
- )
- public int startingSoonTime = 300;
-
- @Expose
- @ConfigOption(
- name = "Timer In Inventory",
- desc = "Displays the time until the next event at the top of your screen when in inventories"
- )
- @ConfigEditorBoolean
- public boolean showEventTimerInInventory = true;
-
- @Expose
- @ConfigOption(
- name = "Notification Sounds",
- desc = "Play a sound whenever events start"
- )
- @ConfigEditorBoolean
- public boolean eventNotificationSounds = true;
-
- @Expose
- @ConfigOption(
- name = "Spooky Night Notification",
- desc = "Send a notification during spooky event when the time reaches 7pm"
- )
- @ConfigEditorBoolean
- public boolean spookyNightNotification = true;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Calendar {
+ @Expose
+ @ConfigOption(
+ name = "Event Notifications",
+ desc = "Display notifications for skyblock calendar events"
+ )
+ @ConfigEditorBoolean
+ public boolean eventNotifications = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Starting Soon Time",
+ desc = "Display a notification before events start, time in seconds.\n" +
+ "0 = No prior notification"
+ )
+ @ConfigEditorSlider(
+ minValue = 0f,
+ maxValue = 600f,
+ minStep = 30f
+ )
+ public int startingSoonTime = 300;
+
+ @Expose
+ @ConfigOption(
+ name = "Timer In Inventory",
+ desc = "Displays the time until the next event at the top of your screen when in inventories"
+ )
+ @ConfigEditorBoolean
+ public boolean showEventTimerInInventory = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Notification Sounds",
+ desc = "Play a sound whenever events start"
+ )
+ @ConfigEditorBoolean
+ public boolean eventNotificationSounds = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Spooky Night Notification",
+ desc = "Send a notification during spooky event when the time reaches 7pm"
+ )
+ @ConfigEditorBoolean
+ public boolean spookyNightNotification = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/CustomArmour.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/CustomArmour.java
index 57a5e1d7..92b4b2ab 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/CustomArmour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/CustomArmour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
@@ -9,27 +28,28 @@ public class CustomArmour {
@Expose
@ConfigOption(
- name = "Enable Custom Armour Hud",
- desc = "Shows an overlay in your inventory showing your 4 extra armour slots"
+ name = "Enable Equipment Hud",
+ desc = "Shows an overlay in your inventory showing your 4 extra armour slots\n" +
+ "\u00A7cRequires Hide Potion Effects to be enabled"
)
@ConfigEditorBoolean
public boolean enableArmourHud = true;
@Expose
@ConfigOption(
- name = "Click To Open Wardrobe",
- desc = "Click on the hud to open /wardrobe"
+ name = "Click To Open Equipment Menu",
+ desc = "Click on the hud to open /equipment"
)
@ConfigEditorBoolean
public boolean sendWardrobeCommand = true;
@Expose
@ConfigOption(
- name = "GUI Colour",
+ name = "GUI Style",
desc = "Change the colour of the GUI"
)
@ConfigEditorDropdown(
- values = {"Vanilla", "Grey", "Dark", "Transparent", "FSR"}
+ values = {"Minecraft", "Grey", "PacksHQ Dark", "Transparent", "FSR"}
)
public int colourStyle = 0;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/DungeonMapConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/DungeonMapConfig.java
index b46eafd9..8e211bd6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/DungeonMapConfig.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/DungeonMapConfig.java
@@ -1,142 +1,161 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class DungeonMapConfig {
- @Expose
- @ConfigOption(
- name = "Border Size",
- desc = "Changes the size of the map border, without changing the size of the contents"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 5,
- minStep = 0.25f
- )
- public float dmBorderSize = 1;
-
- @Expose
- @ConfigOption(
- name = "Room Size",
- desc = "Changes the size of rooms. Useful for higher dungeons with larger maps"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 5,
- minStep = 0.25f
- )
- public float dmRoomSize = 1;
-
- @Expose
- @ConfigOption(
- name = "Icon Size",
- desc = "Changes the scale of room indicators and player icons"
- )
- @ConfigEditorSlider(
- minValue = 0.5f,
- maxValue = 3f,
- minStep = 0.25f
- )
- public float dmIconScale = 1.0f;
-
- @Expose
- @ConfigOption(
- name = "Border Style",
- desc = "Various custom borders from various talented artists.\nUse 'custom' if your texture pack has a custom border"
- )
- public int dmBorderStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Show Dungeon Map",
- desc = "Show/hide the NEU dungeon map"
- )
- public boolean dmEnable = true;
-
- @Expose
- @ConfigOption(
- name = "Map Center",
- desc = "Center on rooms, or center on your player"
- )
- public boolean dmCenterPlayer = true;
-
- @Expose
- @ConfigOption(
- name = "Rotate with Player",
- desc = "Rotate the map to face the same direction as your player"
- )
- public boolean dmRotatePlayer = true;
-
- @Expose
- @ConfigOption(
- name = "Orient Checkmarks",
- desc = "Checkmarks will always show vertically, regardless of rotation"
- )
- public boolean dmOrientCheck = true;
-
- @Expose
- @ConfigOption(
- name = "Center Checkmarks",
- desc = "Checkmarks will show closer to the center of rooms"
- )
- public boolean dmCenterCheck = false;
-
- @Expose
- @ConfigOption(
- name = "Player Icon Style",
- desc = "Various player icon styles"
- )
- public int dmPlayerHeads = 0;
-
- @Expose
- @ConfigOption(
- name = "Interpolate Far Players",
- desc = "Will make players far away move smoothly"
- )
- public boolean dmPlayerInterp = true;
-
- @Expose
- @ConfigOption(
- name = "OpenGL Compatibility",
- desc = "Compatiblity options for people with bad computers. ONLY use this if you know what you are doing, otherwise the map will look worse"
- )
- public int dmCompat = 0;
-
- @Expose
- @ConfigOption(
- name = "Background Colour",
- desc = "Colour of the map background. Supports opacity & chroma"
- )
- public String dmBackgroundColour = "00:170:75:75:75";
-
- @Expose
- @ConfigOption(
- name = "Border Colour",
- desc = "Colour of the map border. Supports opacity & chroma. Turn off custom borders to see"
- )
- public String dmBorderColour = "00:0:0:0:0";
-
- @Expose
- @ConfigOption(
- name = "Chroma Border Mode",
- desc = "Applies a hue offset around the map border"
- )
- public boolean dmChromaBorder = false;
-
- @Expose
- @ConfigOption(
- name = "Background Blur Factor",
- desc = "Changes the blur factor behind the map. Set to 0 to disable blur"
- )
- public float dmBackgroundBlur = 0;
-
- @Expose
- @ConfigOption(
- name = "Position",
- desc = "The position of the map"
- )
- public Position dmPosition = new Position(10, 10);
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class DungeonMapConfig {
+ @Expose
+ @ConfigOption(
+ name = "Border Size",
+ desc = "Changes the size of the map border, without changing the size of the contents"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 5,
+ minStep = 0.25f
+ )
+ public float dmBorderSize = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Room Size",
+ desc = "Changes the size of rooms. Useful for higher dungeons with larger maps"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 5,
+ minStep = 0.25f
+ )
+ public float dmRoomSize = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Icon Size",
+ desc = "Changes the scale of room indicators and player icons"
+ )
+ @ConfigEditorSlider(
+ minValue = 0.5f,
+ maxValue = 3f,
+ minStep = 0.25f
+ )
+ public float dmIconScale = 1.0f;
+
+ @Expose
+ @ConfigOption(
+ name = "Border Style",
+ desc = "Various custom borders from various talented artists.\nUse 'custom' if your texture pack has a custom border"
+ )
+ public int dmBorderStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Dungeon Map",
+ desc = "Show/hide the NEU dungeon map"
+ )
+ public boolean dmEnable = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Map Center",
+ desc = "Center on rooms, or center on your player"
+ )
+ public boolean dmCenterPlayer = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Rotate with Player",
+ desc = "Rotate the map to face the same direction as your player"
+ )
+ public boolean dmRotatePlayer = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Orient Checkmarks",
+ desc = "Checkmarks will always show vertically, regardless of rotation"
+ )
+ public boolean dmOrientCheck = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Center Checkmarks",
+ desc = "Checkmarks will show closer to the center of rooms"
+ )
+ public boolean dmCenterCheck = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Player Icon Style",
+ desc = "Various player icon styles"
+ )
+ public int dmPlayerHeads = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Interpolate Far Players",
+ desc = "Will make players far away move smoothly"
+ )
+ public boolean dmPlayerInterp = true;
+
+ @Expose
+ @ConfigOption(
+ name = "OpenGL Compatibility",
+ desc = "Compatiblity options for people with bad computers. ONLY use this if you know what you are doing, otherwise the map will look worse"
+ )
+ public int dmCompat = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Background Colour",
+ desc = "Colour of the map background. Supports opacity & chroma"
+ )
+ public String dmBackgroundColour = "00:170:75:75:75";
+
+ @Expose
+ @ConfigOption(
+ name = "Border Colour",
+ desc = "Colour of the map border. Supports opacity & chroma. Turn off custom borders to see"
+ )
+ public String dmBorderColour = "00:0:0:0:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Chroma Border Mode",
+ desc = "Applies a hue offset around the map border"
+ )
+ public boolean dmChromaBorder = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Background Blur Factor",
+ desc = "Changes the blur factor behind the map. Set to 0 to disable blur"
+ )
+ public float dmBackgroundBlur = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Position",
+ desc = "Change the position of the map"
+ )
+ public Position dmPosition = new Position(10, 10);
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java
index ce164c9a..c94bd181 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java
@@ -1,229 +1,275 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-public class Dungeons {
- @ConfigOption(
- name = "Dungeon Map",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean dungeonMapAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "\u00A7cWarning",
- desc = "If you are on Entrance, Floor 1 or Master 1 the map wont work properly"
- )
- @ConfigEditorFSR(
- runnableId = 12,
- buttonText = ""
- )
- @ConfigAccordionId(id = 0)
- public boolean dungeonF1Warning = false;
-
- @Expose
- @ConfigOption(
- name = "Edit Dungeon Map",
- desc = "The NEU dungeon map has it's own editor (/neumap).\n" +
- "Click the button on the left to open it"
- )
- @ConfigEditorButton(
- runnableId = 0,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 0)
- public int editDungeonMap = 0;
-
- @Expose
- @ConfigOption(
- name = "Show Own Head As Marker",
- desc = "If you have the \"Head\" icon style selected, don't replace your green marker with a head"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean showOwnHeadAsMarker = false;
-
- @ConfigOption(
- name = "Dungeon Profit",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- public boolean dungeonProfitAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Profit Type",
- desc = "Set the price dataset used for calculating profit"
- )
- @ConfigEditorDropdown(
- values = {"Lowest BIN", "24 AVG Lowest Bin", "Auction AVG"}
- )
- @ConfigAccordionId(id = 1)
- public int profitType = 0;
-
- @Expose
- @ConfigOption(
- name = "Profit Display Location",
- desc = "Set where the profit information is displayed\n" +
- "Overlay = Overlay on right side of inventory\n" +
- "GUI Title = Text displayed next to the inventory title\n" +
- "Lore = Inside the \"Open Reward Chest\" item"
- )
- @ConfigEditorDropdown(
- values = {"Overlay", "GUI Title", "Lore", "Off"}
- )
- @ConfigAccordionId(id = 1)
- public int profitDisplayLoc = 0;
-
- @Expose
- @ConfigOption(
- name = "Include Kismet Feather",
- desc = "Include Kismet Feathers in the Profit Calculation after rerolling"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean useKismetOnDungeonProfit = true;
-
- @ConfigOption(
- name = "Dungeon Win Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 3)
- public boolean dungeonWinAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Dungeon Win",
- desc = "Show a fancy win screen and stats when completing a dungeon"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean enableDungeonWin = true;
-
- @Expose
- @ConfigOption(
- name = "Dungeon Win Time",
- desc = "Change the amount of time (milliseconds) that the win screen shows for"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 20000,
- minStep = 500
- )
- @ConfigAccordionId(id = 3)
- public int dungeonWinMillis = 8000;
-
- @ConfigOption(
- name = "Dungeon Block Overlay",
- desc = ""
- )
-
- @ConfigEditorAccordion(id = 2)
- public boolean dungeonBlocksAccordion = false;
- @ConfigOption(
- name = "\u00A7cWarning",
- desc = "You need Fast Render and Antialiasing off for these settings to work\n" +
- "You can find these in your video settings"
- )
- @ConfigEditorFSR(
- runnableId = 12,
- buttonText = ""
- )
- @ConfigAccordionId(id = 2)
- public boolean dungeonBlockWarning = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Block Overlay",
- desc = "Change the colour of certain blocks / entities while inside dungeons, but keeps the normal texture outside of dungeons"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean enableDungBlockOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Show Overlay Everywhere",
- desc = "Show the dungeon block overlay even when not inside dungeons. Should only be used for testing."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean dungeonBlocksEverywhere = false;
-
- @Expose
- @ConfigOption(
- name = "Slow Update",
- desc = "Updates the colour every second instead of every tick.\n" +
- "\u00A7cWARNING: This will cause all texture animations (eg. flowing water) to update slowly.\n" +
- "This should only be used on low-end machines"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean slowDungeonBlocks = false;
-
- @Expose
- @ConfigOption(
- name = "Cracked Bricks",
- desc = "Change the colour of: Cracked Bricks"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungCrackedColour = "0:255:7:255:217";
-
- @Expose
- @ConfigOption(
- name = "Dispensers",
- desc = "Change the colour of: Dispensers"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungDispenserColour = "0:255:255:76:0";
-
- @Expose
- @ConfigOption(
- name = "Levers",
- desc = "Change the colour of: Levers"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungLeverColour = "0:252:24:249:255";
-
- @Expose
- @ConfigOption(
- name = "Tripwire String",
- desc = "Change the colour of: Tripwire String"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungTripWireColour = "0:255:255:0:0";
-
- @Expose
- @ConfigOption(
- name = "Normal Chests",
- desc = "Change the colour of: Normal Chests"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungChestColour = "0:255:0:163:36";
-
- @Expose
- @ConfigOption(
- name = "Trapped Chests",
- desc = "Change the colour of: Trapped Chests"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungTrappedChestColour = "0:255:0:163:36";
-
- @Expose
- @ConfigOption(
- name = "Bats",
- desc = "Change the colour of: Bats"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String dungBatColour = "0:255:12:255:0";
-
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Dungeons {
+
+ @ConfigOption(
+ name = "Dungeon Map",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean dungeonMapAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "\u00A7cWarning",
+ desc = "If you are on Entrance, Floor 1 or Master 1 the map wont work properly"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ @ConfigAccordionId(id = 0)
+ public boolean dungeonF1Warning = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Dungeon Map",
+ desc = "The NEU dungeon map has it's own editor (/neumap).\n" +
+ "Click the button on the left to open it"
+ )
+ @ConfigEditorButton(
+ runnableId = 0,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 0)
+ public int editDungeonMap = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Own Head As Marker",
+ desc = "If you have the \"Head\" icon style selected, don't replace your green marker with a head"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showOwnHeadAsMarker = false;
+
+ @ConfigOption(
+ name = "Dungeon Profit",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean dungeonProfitAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Profit Type",
+ desc = "Set the price dataset used for calculating profit"
+ )
+ @ConfigEditorDropdown(
+ values = {"Lowest BIN", "24 AVG Lowest Bin", "Auction AVG"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int profitType = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Profit Display Location",
+ desc = "Set where the profit information is displayed\n" +
+ "Overlay = Overlay on right side of inventory\n" +
+ "GUI Title = Text displayed next to the inventory title\n" +
+ "Lore = Inside the \"Open Reward Chest\" item"
+ )
+ @ConfigEditorDropdown(
+ values = {"Overlay", "GUI Title", "Lore", "Off"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int profitDisplayLoc = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Include Kismet Feather",
+ desc = "Include Kismet Feathers in the Profit Calculation after rerolling"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean useKismetOnDungeonProfit = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Include Essence Cost",
+ desc = "Include Bazaar Essence Sell Cost in the Profit Calculation for Dungeon Chests"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean useEssenceCostFromBazaar = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Warning if Derpy active",
+ desc = "Shows a warning if the mayor Derpy is active"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean shouldWarningDerpy = true;
+
+ @ConfigOption(
+ name = "Dungeon Win Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 3)
+ public boolean dungeonWinAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Dungeon Win",
+ desc = "Show a fancy win screen and stats when completing a dungeon"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean enableDungeonWin = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Dungeon Win Time",
+ desc = "Change the amount of time (milliseconds) that the win screen shows for"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 20000,
+ minStep = 500
+ )
+ @ConfigAccordionId(id = 3)
+ public int dungeonWinMillis = 8000;
+
+ @ConfigOption(
+ name = "Dungeon Block Overlay",
+ desc = ""
+ )
+
+ @ConfigEditorAccordion(id = 2)
+ public boolean dungeonBlocksAccordion = false;
+ @ConfigOption(
+ name = "\u00A7cWarning",
+ desc = "You need Fast Render and Antialiasing off for these settings to work\n" +
+ "You can find these in your video settings"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ @ConfigAccordionId(id = 2)
+ public boolean dungeonBlockWarning = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Block Overlay",
+ desc = "Change the colour of certain blocks / entities while inside dungeons, but keeps the normal texture outside of dungeons"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean enableDungBlockOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Overlay Everywhere",
+ desc = "Show the dungeon block overlay even when not inside dungeons. Should only be used for testing."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean dungeonBlocksEverywhere = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Slow Update",
+ desc = "Updates the colour every second instead of every tick.\n" +
+ "\u00A7cWARNING: This will cause all texture animations (eg. flowing water) to update slowly.\n" +
+ "This should only be used on low-end machines"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean slowDungeonBlocks = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Cracked Bricks",
+ desc = "Change the colour of: Cracked Bricks"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungCrackedColour = "0:255:7:255:217";
+
+ @Expose
+ @ConfigOption(
+ name = "Dispensers",
+ desc = "Change the colour of: Dispensers"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungDispenserColour = "0:255:255:76:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Levers",
+ desc = "Change the colour of: Levers"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungLeverColour = "0:252:24:249:255";
+
+ @Expose
+ @ConfigOption(
+ name = "Tripwire String",
+ desc = "Change the colour of: Tripwire String"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungTripWireColour = "0:255:255:0:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Normal Chests",
+ desc = "Change the colour of: Normal Chests"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungChestColour = "0:255:0:163:36";
+
+ @Expose
+ @ConfigOption(
+ name = "Trapped Chests",
+ desc = "Change the colour of: Trapped Chests"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungTrappedChestColour = "0:255:0:163:36";
+
+ @Expose
+ @ConfigOption(
+ name = "Bats",
+ desc = "Change the colour of: Bats"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String dungBatColour = "0:255:12:255:0";
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Enchanting.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Enchanting.java
index e9add7b4..b596d180 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Enchanting.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Enchanting.java
@@ -1,11 +1,34 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
public class Enchanting {
@ConfigOption(
- name = "Enchant Table GUI",
+ name = "Enchant Table / Hex GUI",
desc = ""
)
@ConfigEditorAccordion(id = 1)
@@ -20,6 +43,15 @@ public class Enchanting {
@ConfigAccordionId(id = 1)
public boolean enableTableGUI = true;
+ @Expose
+ @ConfigOption(
+ name = "Enable Hex GUI",
+ desc = "Show a custom GUI when using the Hex"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean enableHexGUI = true;
+
/*@Expose
@ConfigOption(
name = "Incompatible Enchants",
@@ -53,6 +85,15 @@ public class Enchanting {
@ConfigAccordionId(id = 1)
public int enchantOrdering = 0;
+ @Expose
+ @ConfigOption(
+ name = "Use highest level from /et in /hex",
+ desc = "Show max level from /et in hex instead of highest possible"
+ )
+ @ConfigEditorBoolean()
+ @ConfigAccordionId(id = 1)
+ public boolean maxEnchLevel = false;
+
@ConfigOption(
name = "Enchanting Solvers",
desc = ""
@@ -91,7 +132,7 @@ public class Enchanting {
@Expose
@ConfigOption(
name = "Ultrasequencer Numbers",
- desc = "Replace the items in the supersequencer with only numbers"
+ desc = "Replace the items in the Ultrasequencer with only numbers"
)
@ConfigEditorBoolean
@ConfigAccordionId(id = 0)
@@ -108,6 +149,15 @@ public class Enchanting {
@Expose
@ConfigOption(
+ name = "Hide Buttons",
+ desc = "Hide Inventory Buttons and Quick Commands while in the experimentation table"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean hideButtons = false;
+
+ @Expose
+ @ConfigOption(
name = "Ultrasequencer Next",
desc = "Set the colour of the glass pane shown behind the element in the ultrasequencer which is next"
)
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Fishing.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Fishing.java
index aa2bacd3..b6075794 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Fishing.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Fishing.java
@@ -1,207 +1,301 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-public class Fishing {
- @Expose
- @ConfigOption(
- name = "Hide Other Players Fishing",
- desc = "Convenience option to easily hide \u00a7lother players'\u00a7r bobbers, rod lines and fishing particles\n" +
- "The advanced options below allow you to set the precise colour, particles, etc."
- )
- @ConfigEditorBoolean
- public boolean hideOtherPlayerAll = false;
-
- @ConfigOption(
- name = "Incoming Fish Warning",
- desc = ""
- )
- @ConfigEditorAccordion(id = 3)
- public boolean incomingFishAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Fish Warning (R)",
- desc = "Display a red '!' when you need to pull the fish up. The warning takes your ping into account"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean incomingFishWarningR = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Fish Warning (Y)",
- desc = "Display a yellow '!' when a fish is approaching your bobber"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean incomingFishWarning = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Hooked Sound",
- desc = "Play a high-pitched ding sound when the '!' turns red"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean incomingFishHookedSounds = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Approach Sound",
- desc = "Play low-pitched ding sounds while the yellow '!' is visible"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean incomingFishIncSounds = false;
-
- @ConfigOption(
- name = "Volumes",
- desc = ""
- )
- @ConfigAccordionId(id = 3)
- @ConfigEditorAccordion(id = 5)
- public boolean incomingFishVolumeAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Hooked Sound Vol.",
- desc = "Set the volume of the hooked sound"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 100,
- minStep = 1
- )
- @ConfigAccordionId(id = 5)
- public float incomingFishHookedSoundsVol = 25;
-
- @Expose
- @ConfigOption(
- name = "Approach Sound Vol.",
- desc = "Set the volume of the approaching sound"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 100,
- minStep = 1
- )
- @ConfigAccordionId(id = 5)
- public float incomingFishIncSoundsVol = 10;
-
- @ConfigOption(
- name = "Fishing Particles",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean particleAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Custom Particles",
- desc = "Allow you to modify the particles that appear when a fish is incoming for you and other players"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableCustomParticles = false;
-
- @ConfigOption(
- name = "Your Particles",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- @ConfigAccordionId(id = 0)
- public boolean yourParticlesAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Particle Type",
- desc = "Change the type of the particle that is spawned\n" +
- "Particle types with (RGB) support custom colours\n" +
- "Set to 'NONE' to disable particles"
- )
- @ConfigEditorDropdown(
- values = {"Default", "None", "Spark (RGB)", "Swirl (RGB)", "Dust (RGB)", "Flame", "Crit", "Magic Crit"}
- )
- @ConfigAccordionId(id = 1)
- public int yourParticleType = 0;
-
- @Expose
- @ConfigOption(
- name = "Custom Colour",
- desc = "Set a custom colour for the particle\n" +
- "Only works for particle types with (RGB)"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 1)
- public String yourParticleColour = "0:255:255:255:255";
-
- @ConfigOption(
- name = "Other Players' Particles",
- desc = ""
- )
- @ConfigEditorAccordion(id = 2)
- @ConfigAccordionId(id = 0)
- public boolean otherParticlesAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Particle Type",
- desc = "Change the type of the particle that is spawned\n" +
- "Particle types with (RGB) support custom colours\n" +
- "Set to 'NONE' to disable particles"
- )
- @ConfigEditorDropdown(
- values = {"Default", "None", "Spark (RGB)", "Swirl (RGB)", "Dust (RGB)", "Flame", "Crit", "Magic Crit"}
- )
- @ConfigAccordionId(id = 2)
- public int otherParticleType = 0;
-
- @Expose
- @ConfigOption(
- name = "Custom Colour",
- desc = "Set a custom colour for the particle\n" +
- "Only works for particle types with (RGB)"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 2)
- public String otherParticleColour = "0:255:255:255:255";
-
- @ConfigOption(
- name = "Rod Line Colours",
- desc = ""
- )
- @ConfigEditorAccordion(id = 4)
- public boolean rodAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Rod Line Colours",
- desc = "Change the colour of your and other players' rod lines\n" +
- "Also fixes the position of the rod line"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean enableRodColours = true;
-
- @Expose
- @ConfigOption(
- name = "Own Rod Colour",
- desc = "Change the colour of your own rod lines\n" +
- "You can set the opacity to '0' to HIDE"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 4)
- public String ownRodColour = "0:255:0:0:0";
-
- @Expose
- @ConfigOption(
- name = "Other Rod Colour",
- desc = "Change the colour of other players' rod lines\n" +
- "You can set the opacity to '0' to HIDE"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 4)
- public String otherRodColour = "0:255:0:0:0";
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Fishing {
+ @Expose
+ @ConfigOption(
+ name = "Hide Other Players Fishing",
+ desc = "Convenience option to easily hide \u00a7lother players'\u00a7r bobbers, rod lines and fishing particles\n" +
+ "The advanced options below allow you to set the precise colour, particles, etc."
+ )
+ @ConfigEditorBoolean
+ public boolean hideOtherPlayerAll = false;
+
+ @ConfigOption(
+ name = "Incoming Fish Warning",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 3)
+ public boolean incomingFishAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Fish Warning (R)",
+ desc = "Display a red '!' when you need to pull the fish up. The warning takes your ping into account"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean incomingFishWarningR = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Fish Warning (Y)",
+ desc = "Display a yellow '!' when a fish is approaching your bobber"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean incomingFishWarning = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Hooked Sound",
+ desc = "Play a high-pitched ding sound when the '!' turns red"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean incomingFishHookedSounds = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Approach Sound",
+ desc = "Play low-pitched ding sounds while the yellow '!' is visible"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean incomingFishIncSounds = false;
+
+ @ConfigOption(
+ name = "Volumes",
+ desc = ""
+ )
+ @ConfigAccordionId(id = 3)
+ @ConfigEditorAccordion(id = 5)
+ public boolean incomingFishVolumeAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Hooked Sound Vol.",
+ desc = "Set the volume of the hooked sound"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 100,
+ minStep = 1
+ )
+ @ConfigAccordionId(id = 5)
+ public float incomingFishHookedSoundsVol = 25;
+
+ @Expose
+ @ConfigOption(
+ name = "Approach Sound Vol.",
+ desc = "Set the volume of the approaching sound"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 100,
+ minStep = 1
+ )
+ @ConfigAccordionId(id = 5)
+ public float incomingFishIncSoundsVol = 10;
+
+ @ConfigOption(
+ name = "Fishing Particles",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean particleAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Custom Particles",
+ desc = "Allow you to modify the particles that appear when a fish is incoming for you and other players"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableCustomParticles = false;
+
+ @ConfigOption(
+ name = "Your Particles",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ @ConfigAccordionId(id = 0)
+ public boolean yourParticlesAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Particle Type",
+ desc = "Change the type of the particle that is spawned\n" +
+ "Particle types with (RGB) support custom colours\n" +
+ "Set to 'NONE' to disable particles"
+ )
+ @ConfigEditorDropdown(
+ values = {"Default", "None", "Spark (RGB)", "Swirl (RGB)", "Dust (RGB)", "Flame", "Crit", "Magic Crit"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int yourParticleType = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Custom Colour",
+ desc = "Set a custom colour for the particle\n" +
+ "Only works for particle types with (RGB)"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 1)
+ public String yourParticleColour = "0:255:255:255:255";
+
+ @ConfigOption(
+ name = "Other Players' Particles",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 2)
+ @ConfigAccordionId(id = 0)
+ public boolean otherParticlesAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Particle Type",
+ desc = "Change the type of the particle that is spawned\n" +
+ "Particle types with (RGB) support custom colours\n" +
+ "Set to 'NONE' to disable particles"
+ )
+ @ConfigEditorDropdown(
+ values = {"Default", "None", "Spark (RGB)", "Swirl (RGB)", "Dust (RGB)", "Flame", "Crit", "Magic Crit"}
+ )
+ @ConfigAccordionId(id = 2)
+ public int otherParticleType = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Custom Colour",
+ desc = "Set a custom colour for the particle\n" +
+ "Only works for particle types with (RGB)"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 2)
+ public String otherParticleColour = "0:255:255:255:255";
+
+ @ConfigOption(
+ name = "Rod Line Colours",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 4)
+ public boolean rodAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Rod Line Colours",
+ desc = "Change the colour of your and other players' rod lines\n" +
+ "Also fixes the position of the rod line"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean enableRodColours = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Own Rod Colour",
+ desc = "Change the colour of your own rod lines\n" +
+ "You can set the opacity to '0' to HIDE"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 4)
+ public String ownRodColour = "0:255:0:0:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Other Rod Colour",
+ desc = "Change the colour of other players' rod lines\n" +
+ "You can set the opacity to '0' to HIDE"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 4)
+ public String otherRodColour = "0:255:0:0:0";
+
+ @ConfigOption(
+ name = "Fishing Timer",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 6)
+ public boolean fishingAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Display a Fishing Timer",
+ desc = "Display a timer above your bobber showing your current time"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean fishingTimer = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing timer color",
+ desc = "Color of the fishing timer"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 6)
+ public String fishingTimerColor = "0:255:0:0:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing timer color (30s)",
+ desc = "Color of the fishing timer after 30 seconds or more have passed"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 6)
+ public String fishingTimerColor30SecPlus = "0:255:0:0:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing timer ping (30s)",
+ desc = "Play a sound after 30 seconds passed"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean fishingSound30Sec = true;
+
+ @ConfigOption(
+ name = "Trophy Reward",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 7)
+ public boolean trophyReward = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Trophy Reward Overlay",
+ desc = "Displays an overlay at Odger that shows information about your trophies"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean trophyRewardOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Trophy Reward Tooltips",
+ desc = "Displays the exchange of your trophies as a tooltip in the Odger Inventory"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean trophyRewardTooltips = true;
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ImprovedSBMenu.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ImprovedSBMenu.java
index 7d943501..8216c892 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ImprovedSBMenu.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ImprovedSBMenu.java
@@ -1,50 +1,69 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class ImprovedSBMenu {
- @Expose
- @ConfigOption(
- name = "Enable Improved SB Menus",
- desc = "Change the way that skyblock menus (eg. /sbmenu) look"
- )
- @ConfigEditorBoolean
- public boolean enableSbMenus = true;
-
- @Expose
- @ConfigOption(
- name = "Menu Background Style",
- desc = "Change the style of the background of skyblock menus"
- )
- @ConfigEditorDropdown(
- values = {
- "Dark 1", "Dark 2", "Transparent", "Light 1", "Light 2", "Light 3",
- "Unused 1", "Unused 2", "Unused 3", "Unused 4"
- }
- )
- public int backgroundStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Button Background Style",
- desc = "Change the style of the foreground elements in skyblock menus"
- )
- @ConfigEditorDropdown(
- values = {
- "Dark 1", "Dark 2", "Transparent", "Light 1", "Light 2", "Light 3",
- "Unused 1", "Unused 2", "Unused 3", "Unused 4"
- }
- )
- public int buttonStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Hide Empty Tooltips",
- desc = "Hide the tooltips of glass panes with no text"
- )
- @ConfigEditorBoolean
- public boolean hideEmptyPanes = true;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class ImprovedSBMenu {
+ @Expose
+ @ConfigOption(
+ name = "Enable Improved SB Menus",
+ desc = "Change the way that skyblock menus (eg. /sbmenu) look"
+ )
+ @ConfigEditorBoolean
+ public boolean enableSbMenus = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Menu Background Style",
+ desc = "Change the style of the background of skyblock menus"
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Dark 1", "Dark 2", "Transparent", "Light 1", "Light 2", "Light 3",
+ "Unused 1", "Unused 2", "Unused 3", "Unused 4"
+ }
+ )
+ public int backgroundStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Button Background Style",
+ desc = "Change the style of the foreground elements in skyblock menus"
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Dark 1", "Dark 2", "Transparent", "Light 1", "Light 2", "Light 3",
+ "Unused 1", "Unused 2", "Unused 3", "Unused 4"
+ }
+ )
+ public int buttonStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide Empty Tooltips",
+ desc = "Hide the tooltips of glass panes with no text"
+ )
+ @ConfigEditorBoolean
+ public boolean hideEmptyPanes = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/InventoryButtons.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/InventoryButtons.java
index 9c698b9c..685aeb98 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/InventoryButtons.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/InventoryButtons.java
@@ -1,35 +1,54 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class InventoryButtons {
- @Expose
- @ConfigOption(
- name = "Open Button Editor",
- desc = "Open button editor GUI (/neubuttons)"
- )
- @ConfigEditorButton(runnableId = 7, buttonText = "Open")
- public boolean openEditorButton = true;
-
- @Expose
- @ConfigOption(
- name = "Always Hide \"Crafting\" Text",
- desc = "Hide crafting text in inventory, even when no button is there"
- )
- @ConfigEditorBoolean
- public boolean hideCrafting = false;
-
- @Expose
- @ConfigOption(
- name = "Button Click Type",
- desc = "Change the click type needed to trigger commands"
- )
- @ConfigEditorDropdown(
- values = {"Mouse Down", "Mouse Up"}
- )
- public int clickType = 0;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class InventoryButtons {
+ @Expose
+ @ConfigOption(
+ name = "Open Button Editor",
+ desc = "Open button editor GUI (/neubuttons)"
+ )
+ @ConfigEditorButton(runnableId = 7, buttonText = "Open")
+ public boolean openEditorButton = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Always Hide \"Crafting\" Text",
+ desc = "Hide crafting text in inventory, even when no button is there"
+ )
+ @ConfigEditorBoolean
+ public boolean hideCrafting = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Button Click Type",
+ desc = "Change the click type needed to trigger commands"
+ )
+ @ConfigEditorDropdown(
+ values = {"Mouse Down", "Mouse Up"}
+ )
+ public int clickType = 0;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java
index 7d08d038..5fde76a5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ItemOverlays.java
@@ -1,356 +1,392 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class ItemOverlays {
- @ConfigOption(
- name = "Treecapitator Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean treecapAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Treecap Overlay",
- desc = "Show which blocks will be broken when using a Jungle Axe or Treecapitator"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableTreecapOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Show in Item durability",
- desc = "Show the cooldown of the Treecapitator in the item durability"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableCooldownInItemDurability = true;
-
- @Expose
- @ConfigOption(
- name = "Overlay Colour",
- desc = "Change the colour of the overlay"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 0)
- public String treecapOverlayColour = "00:50:64:224:208";
-
- @Expose
- @ConfigOption(
- name = "Enable Monkey Pet Check",
- desc = "Will check using the API to check what pet you're using\nto determine the cooldown based off of if you have a monkey pet."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableMonkeyCheck = true;
-
- @ConfigOption(
- name = "Builder's Wand Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- public boolean wandAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Wand Overlay",
- desc = "Show which blocks will be placed when using the Builder's Wand"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean enableWandOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Wand Block Count",
- desc = "Shows the total count of a block in your inventory"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean wandBlockCount = true;
-
- @Expose
- @ConfigOption(
- name = "Overlay Colour",
- desc = "Change the colour of the ghost block outline"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 1)
- public String wandOverlayColour = "00:50:64:224:208";
-
- @ConfigOption(
- name = "Block Zapper Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 6)
- public boolean zapperAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Zapper Overlay",
- desc = "Show which blocks will be destroyed when using the Block Zapper"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 6)
- public boolean enableZapperOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Overlay Colour",
- desc = "Change the colour of the ghost block outline"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 6)
- public String zapperOverlayColour = "0:102:171:5:0";
-
- @ConfigOption(
- name = "Smooth AOTE/AOTV/Hyp",
- desc = ""
- )
- @ConfigEditorAccordion(id = 2)
- public boolean aoteAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Smooth AOTE",
- desc = "Teleport smoothly to your destination when using AOTE or AOTV"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean enableSmoothAOTE = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Smooth Hyperion",
- desc = "Teleport smoothly to your destination when using Hyperion"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean enableSmoothHyperion = true;
-
- @Expose
- @ConfigOption(
- name = "Smooth TP Time",
- desc = "Change the amount of time (milliseconds) taken to teleport"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 500,
- minStep = 25
- )
- @ConfigAccordionId(id = 2)
- public int smoothTpMillis = 125;
-
- @Expose
- @ConfigOption(
- name = "Smooth TP Time (Etherwarp)",
- desc = "Teleport smoothly to your destination when using AOTV Etherwarp"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 500,
- minStep = 25
- )
- @ConfigAccordionId(id = 2)
- public int smoothTpMillisEtherwarp = 50;
-
- @Expose
- @ConfigOption(
- name = "Disable Hyperion Particles",
- desc = "Remove the explosion effect when using a hyperion"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean disableHyperionParticles = true;
-
- @ConfigOption(
- name = "Etherwarp",
- desc = ""
- )
- @ConfigEditorAccordion(id = 7)
- public boolean etherwarpAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Etherwarp Zoom",
- desc = "Zoom in on targeted blocks with etherwarp, making it easier to adjust at a distance"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 7)
- public boolean etherwarpZoom = true;
-
- @Expose
- @ConfigOption(
- name = "Enable etherwarp helper overlay",
- desc = "Display an overlay which tells you if the etherwarp will fail."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 7)
- public boolean enableEtherwarpHelperOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Enable etherwarp block overlay",
- desc = "Display an overlay that tells you what block you will TP to."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 7)
- public boolean enableEtherwarpBlockOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Highlight Colour",
- desc = "Change the colour of the etherwarp target block outline"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 7)
- public String etherwarpHighlightColour = "00:70:156:8:96";
-
- @ConfigOption(
- name = "Bonemerang Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 3)
- public boolean bonemerangAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Bonemerang Overlay",
- desc = "Shows info about the bonemerang while holding it."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean enableBonemerangOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Highlight Targeted Entities",
- desc = "Highlight entities that will be hit by your bonemerang"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean highlightTargeted = true;
-
- @Expose
- @ConfigOption(
- name = "Bonemerang Overlay Position",
- desc = "The position of the Bonemerang overlay."
- )
- @ConfigEditorButton(
- runnableId = 9,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 3)
- public Position bonemerangPosition = new Position(-1, -1);
-
- @Expose
- @ConfigOption(
- name = "Bonemerang Overlay Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rHold a Bonemerang to display the overlay"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7cBonemerang will break!",
- "\u00a77Targets: \u00a76\u00a7l10"
- }
- )
- @ConfigAccordionId(id = 3)
- public List<Integer> bonemerangOverlayText = new ArrayList<>(Arrays.asList(0, 1));
-
- @Expose
- @ConfigOption(
- name = "Bonemerang Overlay Style",
- desc = "Change the style of the Bonemerang overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow Only", "Full Shadow"}
- )
- @ConfigAccordionId(id = 3)
- public int bonemerangOverlayStyle = 0;
- @Expose
- @ConfigOption(
- name = "Fast update",
- desc = "Updates the bonemerang overlay faster.\n" +
- "Might cause some lag."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean bonemerangFastUpdate = false;
-
- @ConfigOption(
- name = "Minion Crystal Radius Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 5)
- public boolean crystalAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Crystal Overlay",
- desc = "Show a block overlay for the effective radius of minion crystals (farming, mining, etc)."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 5)
- public boolean enableCrystalOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Always Show Crystal Overlay",
- desc = "Show the crystal overlay, even when a minion crystal is not being held."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 5)
- public boolean alwaysShowCrystal = false;
-
- @ConfigOption(
- name = "Farming Overlays",
- desc = ""
- )
- @ConfigEditorAccordion(id = 6)
- public boolean farmingAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Prismapump Overlay",
- desc = "Show a block overlay for the effected blocks of prismapump's ability."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 6)
- public boolean enablePrismapumpOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Hoe Of Tilling Overlay",
- desc = "Show a block overlay for the effected blocks of the hoe of tilling's ability."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 6)
- public boolean enableHoeOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Enable Dirt Wand Overlay",
- desc = "Show a block overlay for the effected blocks of dirt wand's ability."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 6)
- public boolean enableDirtWandOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Pickaxe Ability Cooldown",
- desc = "Show the cooldown duration off the pickaxe ability as the durability."
- )
- @ConfigEditorBoolean
- public boolean pickaxeAbility = true;
-
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ItemOverlays {
+ @ConfigOption(
+ name = "Treecapitator Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean treecapAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Treecap Overlay",
+ desc = "Show which blocks will be broken when using a Jungle Axe or Treecapitator"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableTreecapOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show in Item durability",
+ desc = "Show the cooldown of the Treecapitator in the item durability"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableCooldownInItemDurability = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Colour",
+ desc = "Change the colour of the overlay"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 0)
+ public String treecapOverlayColour = "00:50:64:224:208";
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Monkey Pet Check",
+ desc = "Will check using the API to check what pet you're using\nto determine the cooldown based off of if you have a monkey pet."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableMonkeyCheck = true;
+
+ @ConfigOption(
+ name = "Builder's Wand Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean wandAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Wand Overlay",
+ desc = "Show which blocks will be placed when using the Builder's Wand"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean enableWandOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Wand Block Count",
+ desc = "Shows the total count of a block in your inventory"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean wandBlockCount = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Colour",
+ desc = "Change the colour of the ghost block outline"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 1)
+ public String wandOverlayColour = "00:50:64:224:208";
+
+ @ConfigOption(
+ name = "Block Zapper Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 6)
+ public boolean zapperAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Zapper Overlay",
+ desc = "Show which blocks will be destroyed when using the Block Zapper"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean enableZapperOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Colour",
+ desc = "Change the colour of the ghost block outline"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 6)
+ public String zapperOverlayColour = "0:102:171:5:0";
+
+ @ConfigOption(
+ name = "Smooth AOTE/AOTV/Hyp",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 2)
+ public boolean aoteAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Smooth AOTE",
+ desc = "Teleport smoothly to your destination when using AOTE or AOTV"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean enableSmoothAOTE = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Smooth Hyperion",
+ desc = "Teleport smoothly to your destination when using Hyperion"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean enableSmoothHyperion = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Smooth TP Time",
+ desc = "Change the amount of time (milliseconds) taken to teleport"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 500,
+ minStep = 25
+ )
+ @ConfigAccordionId(id = 2)
+ public int smoothTpMillis = 125;
+
+ @Expose
+ @ConfigOption(
+ name = "Smooth TP Time (Etherwarp)",
+ desc = "Teleport smoothly to your destination when using AOTV Etherwarp"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 500,
+ minStep = 25
+ )
+ @ConfigAccordionId(id = 2)
+ public int smoothTpMillisEtherwarp = 50;
+
+ @Expose
+ @ConfigOption(
+ name = "Disable Hyperion Particles",
+ desc = "Remove the explosion effect when using a hyperion"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean disableHyperionParticles = true;
+
+ @ConfigOption(
+ name = "Etherwarp",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 7)
+ public boolean etherwarpAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Etherwarp Zoom",
+ desc = "Zoom in on targeted blocks with etherwarp, making it easier to adjust at a distance"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean etherwarpZoom = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable etherwarp helper overlay",
+ desc = "Display an overlay which tells you if the etherwarp will fail."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean enableEtherwarpHelperOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable etherwarp block overlay",
+ desc = "Display an overlay that tells you what block you will TP to."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean enableEtherwarpBlockOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Disable overlay when fail",
+ desc = "Don't display the etherwarp block overlay when you can't TP to the block"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 7)
+ public boolean disableOverlayWhenFailed = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Highlight Colour",
+ desc = "Change the colour of the etherwarp target block outline"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 7)
+ public String etherwarpHighlightColour = "00:70:156:8:96";
+
+ @ConfigOption(
+ name = "Bonemerang Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 3)
+ public boolean bonemerangAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Bonemerang Overlay",
+ desc = "Shows info about the bonemerang while holding it."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean enableBonemerangOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Highlight Targeted Entities",
+ desc = "Highlight entities that will be hit by your bonemerang"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean highlightTargeted = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Bonemerang Overlay Position",
+ desc = "Change the position of the Bonemerang overlay."
+ )
+ @ConfigEditorButton(
+ runnableId = 9,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 3)
+ public Position bonemerangPosition = new Position(-1, -1);
+
+ @Expose
+ @ConfigOption(
+ name = "Bonemerang Overlay Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rHold a Bonemerang to display the overlay"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7cBonemerang will break!",
+ "\u00a77Targets: \u00a76\u00a7l10"
+ }
+ )
+ @ConfigAccordionId(id = 3)
+ public List<Integer> bonemerangOverlayText = new ArrayList<>(Arrays.asList(0, 1));
+
+ @Expose
+ @ConfigOption(
+ name = "Bonemerang Overlay Style",
+ desc = "Change the style of the Bonemerang overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow Only", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 3)
+ public int bonemerangOverlayStyle = 0;
+ @Expose
+ @ConfigOption(
+ name = "Fast update",
+ desc = "Updates the bonemerang overlay faster.\n" +
+ "Might cause some lag."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean bonemerangFastUpdate = false;
+
+ @ConfigOption(
+ name = "Minion Crystal Radius Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 5)
+ public boolean crystalAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Crystal Overlay",
+ desc = "Show a block overlay for the effective radius of minion crystals (farming, mining, etc)."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 5)
+ public boolean enableCrystalOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Always Show Crystal Overlay",
+ desc = "Show the crystal overlay, even when a minion crystal is not being held."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 5)
+ public boolean alwaysShowCrystal = false;
+
+ @ConfigOption(
+ name = "Farming Overlays",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 6)
+ public boolean farmingAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Prismapump Overlay",
+ desc = "Show a block overlay for the effected blocks of prismapump's ability."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean enablePrismapumpOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Hoe Of Tilling Overlay",
+ desc = "Show a block overlay for the effected blocks of the hoe of tilling's ability."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean enableHoeOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Dirt Wand Overlay",
+ desc = "Show a block overlay for the effected blocks of dirt wand's ability."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 6)
+ public boolean enableDirtWandOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Pickaxe Ability Cooldown",
+ desc = "Show the cooldown duration of the pickaxe ability as the durability."
+ )
+ @ConfigEditorBoolean
+ public boolean pickaxeAbility = true;
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Itemlist.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Itemlist.java
index e1c11f99..72a45930 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Itemlist.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Itemlist.java
@@ -1,110 +1,152 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-public class Itemlist {
- @Expose
- @ConfigOption(
- name = "Show Vanilla Items",
- desc = "Vanilla items are included in the item list"
- )
- @ConfigEditorBoolean
- public boolean showVanillaItems = true;
-
- @Expose
- @ConfigOption(
- name = "Open Itemlist Arrow",
- desc = "Creates an arrow on the right-side to open the item list when hovered"
- )
- @ConfigEditorBoolean
- public boolean tabOpen = true;
-
- @Expose
- @ConfigOption(
- name = "Keep Open",
- desc = "Keeps the Itemlist open after the inventory is closed"
- )
- @ConfigEditorBoolean
- public boolean keepopen = false;
-
- @Expose
- @ConfigOption(
- name = "Item Style",
- desc = "Sets the style of the background behind items"
- )
- @ConfigEditorDropdown(
- values = {"Round", "Square"}
- )
- public int itemStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Pane Gui Scale",
- desc = "Change the gui scale of the Itemlist"
- )
- @ConfigEditorDropdown(
- values = {"Default", "Small", "Medium", "Large", "Auto"}
- )
- public int paneGuiScale = 0;
-
- @Expose
- @ConfigOption(
- name = "Background Blur",
- desc = "Change the blur amount behind the Itemlist. 0 = off"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 20,
- minStep = 1
- )
- public int bgBlurFactor = 5;
-
- @Expose
- @ConfigOption(
- name = "Pane Width Multiplier",
- desc = "Change the width of the Itemlist"
- )
- @ConfigEditorSlider(
- minValue = 0.5f,
- maxValue = 1.5f,
- minStep = 0.1f
- )
- public float paneWidthMult = 1.0f;
-
- @Expose
- @ConfigOption(
- name = "Pane Padding",
- desc = "Change the padding around the Itemlist"
- )
- @ConfigEditorSlider(
- minValue = 0f,
- maxValue = 20f,
- minStep = 1f
- )
- public int panePadding = 10;
-
- @Expose
- @ConfigOption(
- name = "Foreground Colour",
- desc = "Change the colour of foreground elements in the Itemlist"
- )
- @ConfigEditorColour
- public String foregroundColour = "00:255:100:100:100";
-
- @Expose
- @ConfigOption(
- name = "Favourite Colour",
- desc = "Change the colour of favourited elements in the Itemlist"
- )
- @ConfigEditorColour
- public String favouriteColour = "00:255:200:150:50";
-
- @Expose
- @ConfigOption(
- name = "Pane Background Colour",
- desc = "Change the colour of the Itemlist background"
- )
- @ConfigEditorColour
- public String backgroundColour = "15:6:0:0:255";
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Itemlist {
+ @Expose
+ @ConfigOption(
+ name = "Show Vanilla Items",
+ desc = "Vanilla items are included in the item list"
+ )
+ @ConfigEditorBoolean
+ public boolean showVanillaItems = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Open Itemlist Arrow",
+ desc = "Creates an arrow on the right-side to open the item list when hovered"
+ )
+ @ConfigEditorBoolean
+ public boolean tabOpen = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Keep Open",
+ desc = "Keeps the Itemlist open after the inventory is closed"
+ )
+ @ConfigEditorBoolean
+ public boolean keepopen = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Open when searching",
+ desc = "Open the Itemlist when in container search mode by double clicking the search bar"
+ )
+ @ConfigEditorBoolean
+ public boolean openWhenSearching = true;
+
+
+ @Expose
+ @ConfigOption(
+ name = "Item Style",
+ desc = "Sets the style of the background behind items"
+ )
+ @ConfigEditorDropdown(
+ values = {"Round", "Square"}
+ )
+ public int itemStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Pane Gui Scale",
+ desc = "Change the gui scale of the Itemlist"
+ )
+ @ConfigEditorDropdown(
+ values = {"Default", "Small", "Medium", "Large", "Auto"}
+ )
+ public int paneGuiScale = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Background Blur",
+ desc = "Change the blur amount behind the Itemlist. 0 = off"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 20,
+ minStep = 1
+ )
+ public int bgBlurFactor = 5;
+
+ @Expose
+ @ConfigOption(
+ name = "Pane Width Multiplier",
+ desc = "Change the width of the Itemlist"
+ )
+ @ConfigEditorSlider(
+ minValue = 0.5f,
+ maxValue = 1.5f,
+ minStep = 0.1f
+ )
+ public float paneWidthMult = 1.0f;
+
+ @Expose
+ @ConfigOption(
+ name = "Pane Padding",
+ desc = "Change the padding around the Itemlist"
+ )
+ @ConfigEditorSlider(
+ minValue = 0f,
+ maxValue = 20f,
+ minStep = 1f
+ )
+ public int panePadding = 10;
+
+ @Expose
+ @ConfigOption(
+ name = "Foreground Colour",
+ desc = "Change the colour of foreground elements in the Itemlist"
+ )
+ @ConfigEditorColour
+ public String foregroundColour = "00:255:100:100:100";
+
+ @Expose
+ @ConfigOption(
+ name = "Favourite Colour",
+ desc = "Change the colour of favourited elements in the Itemlist"
+ )
+ @ConfigEditorColour
+ public String favouriteColour = "00:255:200:150:50";
+
+ @Expose
+ @ConfigOption(
+ name = "Pane Background Colour",
+ desc = "Change the colour of the Itemlist background"
+ )
+ @ConfigEditorColour
+ public String backgroundColour = "15:6:0:0:255";
+
+ @Expose
+ @ConfigOption(
+ name = "Always show Monsters",
+ desc = "Always show Monster Items in the item list"
+ )
+ @ConfigEditorBoolean(
+ runnableId = 21
+ )
+ public boolean alwaysShowMonsters = false;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/LocationEdit.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/LocationEdit.java
index 385a3cc1..42316592 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/LocationEdit.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/LocationEdit.java
@@ -1,8 +1,30 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
public class LocationEdit {
@Expose
@@ -20,7 +42,7 @@ public class LocationEdit {
@Expose
@ConfigOption(
name = "Edit Pet Info Position",
- desc = "The position of the pet info overlay."
+ desc = "Change the position of the pet info overlay"
)
@ConfigEditorButton(
runnableId = 4,
@@ -37,13 +59,12 @@ public class LocationEdit {
runnableId = 5,
buttonText = "Edit"
)
- @ConfigAccordionId(id = 0)
public Position todoPosition = new Position(100, 0);
@Expose
@ConfigOption(
name = "Edit Bonemerang Overlay Position",
- desc = "The position of the Bonemerang overlay."
+ desc = "Change the position of the Bonemerang overlay"
)
@ConfigEditorButton(
runnableId = 9,
@@ -72,7 +93,7 @@ public class LocationEdit {
@Expose
@ConfigOption(
name = "Edit Toolbar Positions",
- desc = "Edit the position of the QuickCommands / Search Bar"
+ desc = "Change the position of the QuickCommands / Search Bar"
)
@ConfigAccordionId(id = 1)
@ConfigEditorButton(runnableId = 6, buttonText = "Edit")
@@ -109,7 +130,7 @@ public class LocationEdit {
@Expose
@ConfigOption(
name = "Edit Crystal Overlay Position",
- desc = "Change the position of the Crystal Hollows Overlay."
+ desc = "Change the position of the Crystal Hollows Overlay"
)
@ConfigEditorButton(
runnableId = 10,
@@ -121,7 +142,7 @@ public class LocationEdit {
@Expose
@ConfigOption(
name = "Edit Fuel Bar Position",
- desc = "Set the position of the drill fuel bar"
+ desc = "Change the position of the drill fuel bar"
)
@ConfigEditorButton(
runnableId = 2,
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java
index 6ebd7f42..727ad329 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Mining.java
@@ -1,710 +1,782 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class Mining {
- @ConfigOption(
- name = "Waypoints",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean waypointsAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Mines Waypoints",
- desc = "Show waypoints in the Dwarven mines to the various locations\n" +
- "Use \"Commissions Only\" to only show active commission locations"
- )
- @ConfigEditorDropdown(
- values = {"Hide", "Commissions Only", "Always"},
- initialIndex = 1
- )
- @ConfigAccordionId(id = 0)
- public int locWaypoints = 1;
-
- @Expose
- @ConfigOption(
- name = "Hide waypoints when at Location",
- desc = "Hides the Commission Waypoints if you are already at the location of the waypoint.\n" +
- "Only active if Waypoints are set to \"Commissions Only\""
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean hideWaypointIfAtLocation = true;
-
- @Expose
- @ConfigOption(
- name = "Emissary Waypoints",
- desc = "Show waypoints in the Dwarven mines to emissaries\n" +
- "Use \"Commission End\" to only show after finishing commissions"
- )
- @ConfigEditorDropdown(
- values = {"Hide", "Commission End", "Always"},
- initialIndex = 1
- )
- @ConfigAccordionId(id = 0)
- public int emissaryWaypoints = 1;
-
- @ConfigOption(
- name = "Drill Fuel Bar",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- public boolean drillAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Drill Fuel Bar",
- desc = "Show a fancy drill fuel bar when holding a drill in mining areas"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean drillFuelBar = true;
-
- @Expose
- @ConfigOption(
- name = "Fuel Bar Width",
- desc = "Change the width of the drill fuel bar"
- )
- @ConfigEditorSlider(
- minValue = 50,
- maxValue = 400,
- minStep = 10
- )
- @ConfigAccordionId(id = 1)
- public int drillFuelBarWidth = 200;
-
- @Expose
- @ConfigOption(
- name = "Edit Fuel Bar Position",
- desc = "Set the position of the drill fuel bar"
- )
- @ConfigEditorButton(
- runnableId = 2,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 1)
- public Position drillFuelBarPosition = new Position(0, -100, true, false);
-
- @ConfigOption(
- name = "Dwarven Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 2)
- public boolean overlayAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Dwarven Overlay",
- desc = "Show an Overlay with useful information on the screen while in Dwarven Mines"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean dwarvenOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Dwarven Text",
- desc = "\u00a7eDrag text to change the appearance of the Overlay\n" +
- "\u00a7rGo to the Dwarven Mines to show this Overlay with useful information"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a73Goblin Slayer: \u00a7626.5%\n\u00a73Lucky Raffle: \u00a7c0.0%",
- "\u00a73Mithril Powder: \u00a726,243",
- "\u00a73Gemstone Powder: \u00a7d6,243",
- "\u00a73Forge 1) \u00a79Diamonite\u00a77: \u00a7aReady!",
- "\u00a73Pickaxe CD: \u00a7a78s"
- }
- )
- @ConfigAccordionId(id = 2)
- public List<Integer> dwarvenText2 = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4));
-
- @Expose
- @ConfigOption(
- name = "Edit Dwarven Overlay Position",
- desc = "Change the position of the Dwarven Mines information Overlay (commisions, powder & forge statuses)"
- )
- @ConfigEditorButton(
- runnableId = 1,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 2)
- public Position overlayPosition = new Position(10, 100);
-
- @Expose
- @ConfigOption(
- name = "Overlay Style",
- desc = "Change the style of the Dwarven Mines information Overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 2)
- public int overlayStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Show Icons",
- desc = "Show Icons representing the part of the overlay."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 2)
- public boolean dwarvenOverlayIcons = true;
-
- @Expose
- @ConfigOption(
- name = "Forge Display",
- desc = "Change what gets shown in the Forge Display"
- )
- @ConfigEditorDropdown(
- values = {"Only Done", "Only Working", "Everything Except Locked", "Everything"}
- )
- @ConfigAccordionId(id = 2)
- public int forgeDisplay = 1;
-
- @Expose
- @ConfigOption(
- name = "Forge Location",
- desc = "Change when the forge display gets shown"
- )
- @ConfigEditorDropdown(
- values = {"Dwarven Mines+Crystal Hollows", "Everywhere except dungeons", "Everywhere"}
- )
- @ConfigAccordionId(id = 2)
- public int forgeDisplayEnabledLocations = 0;
-
- @ConfigOption(
- name = "Metal Detector Solver",
- desc = ""
- )
- @ConfigEditorAccordion(id = 3)
- public boolean metalDetectorSolverAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Waypoints",
- desc =
- "Enabled the metal detector solver for Mines of Divan, to use this stand still to calculate possible blocks and then if required stand" +
- " still on another block."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean metalDetectorEnabled = true;
-
- @Expose
- @ConfigOption(
- name = "Show Possible Blocks",
- desc = "Show waypoints on possible locations when NEU isn't sure about what block the treasure is."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean metalDetectorShowPossible = false;
-
- @ConfigOption(
- name = "Crystal Hollows Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 4)
- public boolean crystalHollowOverlayAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Crystal Overlay",
- desc = "Enables the Crystal Hollows Overlay."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean crystalHollowOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Edit Crystal Overlay Position",
- desc = "Change the position of the Crystal Hollows Overlay."
- )
- @ConfigEditorButton(
- runnableId = 10,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 4)
- public Position crystalHollowOverlayPosition = new Position(200, 0);
-
- @Expose
- @ConfigOption(
- name = "Options",
- desc = "Drag text to change the appearance of the overlay!\n" +
- "Click add to add extra things!"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a73Amber Crystal: \u00a7aPlaced\n" +
- "\u00a73Sapphire Crystal: \u00a7eCollected\n" +
- "\u00a73Jade Crystal: \u00a7eMissing\n" +
- "\u00a73Amethyst Crystal: \u00a7cMissing\n" +
- "\u00a73Topaz Crystal: \u00a7cMissing\n",
- "\u00a73Crystals: \u00a7a4/5",
- "\u00a73Crystals: \u00a7a80%",
- "\u00a73Electron Transmitter: \u00a7aDone\n" +
- "\u00a73Robotron Reflector: \u00a7eIn Storage\n" +
- "\u00a73Superlite Motor: \u00a7eIn Inventory\n" +
- "\u00a73Synthetic Hearth: \u00a7cMissing\n" +
- "\u00a73Control Switch: \u00a7cMissing\n" +
- "\u00a73FTX 3070: \u00a7cMissing",
- "\u00a73Electron Transmitter: \u00a7a3\n" +
- "\u00a73Robotron Reflector: \u00a7e2\n" +
- "\u00a73Superlite Motor: \u00a7e1\n" +
- "\u00a73Synthetic Hearth: \u00a7c0\n" +
- "\u00a73Control Switch: \u00a7c0\n" +
- "\u00a73FTX 3070: \u00a7c0",
- "\u00a73Automaton parts: \u00a7a5/6",
- "\u00a73Automaton parts: \u00a7a83%",
- "\u00a73Scavenged Lapis Sword: \u00a7aDone\n" +
- "\u00a73Scavenged Golden Hammer: \u00a7eIn Storage\n" +
- "\u00a73Scavenged Diamond Axe: \u00a7eIn Inventory\n" +
- "\u00a73Scavenged Emerald Hammer: \u00a7cMissing\n",
- "\u00a73Scavenged Lapis Sword: \u00a7a3\n" +
- "\u00a73Scavenged Golden Hammer: \u00a7e2\n" +
- "\u00a73Scavenged Diamond Axe: \u00a7e1\n" +
- "\u00a73Scavenged Emerald Hammer: \u00a7c0\n",
- "\u00a73Mines of Divan parts: \u00a7a3/4",
- "\u00a73Mines of Divan parts: \u00a7a75%"
- }
- )
- @ConfigAccordionId(id = 4)
- public List<Integer> crystalHollowText = new ArrayList<>(Arrays.asList(0, 3, 7));
-
- @Expose
- @ConfigOption(
- name = "Style",
- desc = "Change the style of the Crystal Hollows Overlay."
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 4)
- public int crystalHollowOverlayStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Show Icons",
- desc = "Show icons in the Overlay that represent the part."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean crystalHollowIcons = true;
-
- @Expose
- @ConfigOption(
- name = "Hide Done",
- desc = "Don't show parts you've given to the NPC."
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean crystalHollowHideDone = false;
-
- @ConfigOption(
- name = "Locations",
- desc = ""
- )
- @ConfigEditorAccordion(id = 5)
- @ConfigAccordionId(id = 4)
- public boolean crystalHollowLocationAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Show Automaton",
- desc = "Change where to show Automaton parts."
- )
- @ConfigEditorDropdown(
- values = {"Crystal Hollows", "Precursor Remnants", "Lost Precursor City"}
- )
- @ConfigAccordionId(id = 5)
- public int crystalHollowAutomatonLocation = 2;
-
- @Expose
- @ConfigOption(
- name = "Show Divan",
- desc = "Change where to show Mines of Divan parts."
- )
- @ConfigEditorDropdown(
- values = {"Crystal Hollows", "Mithril Deposits", "Mines of Divan"}
- )
- @ConfigAccordionId(id = 5)
- public int crystalHollowDivanLocation = 2;
-
- @Expose
- @ConfigOption(
- name = "Show Crystal",
- desc = "Change where to show Collected Crystals."
- )
- @ConfigEditorDropdown(
- values = {"Crystal Hollows", "When No Other Overlays"}
- )
- @ConfigAccordionId(id = 5)
- public int crystalHollowCrystalLocation = 1;
-
- @ConfigOption(
- name = "Colours",
- desc = ""
- )
- @ConfigEditorAccordion(id = 6)
- @ConfigAccordionId(id = 4)
- public boolean crystalHollowColourAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Main Color",
- desc = "Change the main color of the overlay."
-
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowPartColor = 3;
-
- @Expose
- @ConfigOption(
- name = "Done Color",
- desc = "Change the colour when the part is given to the NPC."
-
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
-
- @ConfigAccordionId(id = 6)
- public int crystalHollowDoneColor = 10;
-
- @Expose
- @ConfigOption(
- name = "In Inventory Color",
- desc = "Change the colour when the part is in the inventory."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowInventoryColor = 14;
-
- @Expose
- @ConfigOption(
- name = "In Storage Color",
- desc = "Change the colour when the part is in the storage."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowStorageColor = 14;
-
- @Expose
- @ConfigOption(
- name = "Missing Color",
- desc = "Change the colour when the part is missing."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowMissingColor = 12;
-
- @Expose
- @ConfigOption(
- name = "Placed Color",
- desc = "Change the colour when the crystal is placed."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowPlacedColor = 10;
-
- @Expose
- @ConfigOption(
- name = "Collected Color",
- desc = "Change the colour when the crystal is collected"
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowCollectedColor = 14;
-
- @Expose
- @ConfigOption(
- name = "All Color",
- desc = "Change the colour when you have 2/3-all of the parts collected in the count overlay."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowAllColor = 10;
-
- @Expose
- @ConfigOption(
- name = "1/3 Color",
- desc = "Change the colour when you have 1/3-2/3 of the parts collected in the count overlay."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowMiddleColor = 14;
-
- @Expose
- @ConfigOption(
- name = "0 Color",
- desc = "Change the colour when you have 0-1/3 of the parts collected in the count overlay."
- )
- @ConfigEditorDropdown(
- values = {
- "Black",
- "Dark Blue",
- "Dark Green",
- "Dark Aqua",
- "Dark Red",
- "Dark Purple",
- "Gold",
- "Gray",
- "Dark Gray",
- "Blue",
- "Green",
- "Aqua",
- "Red",
- "Light Purple",
- "Yellow",
- "White"
- }
- )
- @ConfigAccordionId(id = 6)
- public int crystalHollowNoneColor = 12;
-
- @Expose
- @ConfigOption(
- name = "Puzzler Solver",
- desc = "Show the correct block to mine for the puzzler puzzle in Dwarven Mines"
- )
- @ConfigEditorBoolean
- public boolean puzzlerSolver = true;
-
- @Expose
- @ConfigOption(
- name = "Titanium Alert",
- desc = "Show an alert whenever titanium appears nearby"
- )
- @ConfigEditorBoolean
- public boolean titaniumAlert = true;
-
- @Expose
- @ConfigOption(
- name = "Titanium must touch air",
- desc = "Only show an alert if the Titanium touches air. (kinda sus)"
- )
- @ConfigEditorBoolean
- public boolean titaniumAlertMustBeVisible = false;
-
- @ConfigOption(
- name = "Custom Textures",
- desc = ""
- )
- @ConfigEditorAccordion(id = 7)
- public boolean texturesAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Dwarven Mines Textures",
- desc = "Allows texture packs to retexture blocks in the Dwarven Mines. If you don't have a texture pack that does this, you should leave this off"
- )
- @ConfigAccordionId(id = 7)
- @ConfigEditorBoolean
- public boolean dwarvenTextures = false;
- @Expose
- @ConfigOption(
- name = "Crystal Hollows Textures",
- desc = "Allows texture packs to retexture blocks in the Crystal Hollows. If you don't have a texture pack that does this, you should leave this off"
- )
- @ConfigAccordionId(id = 7)
- @ConfigEditorBoolean
- public boolean crystalHollowTextures = false;
-
- @Expose
- @ConfigOption(
- name = "Replace Gemstone sounds",
- desc = "Replace the break sounds of crystals in the Crystal Hollows. Requires a texture pack with this feature"
- )
- @ConfigAccordionId(id = 7)
- @ConfigEditorBoolean
- public boolean gemstoneSounds = false;
-
- @Expose
- @ConfigOption(
- name = "Replace Mithril sounds",
- desc = "Replace the break sounds of mithril and titanium in the Dwarven mines. Requires a texture pack with this feature"
- )
- @ConfigAccordionId(id = 7)
- @ConfigEditorBoolean
- public boolean mithrilSounds = false;
-
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class Mining {
+ @ConfigOption(
+ name = "Waypoints",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean waypointsAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Mines Waypoints",
+ desc = "Show waypoints in the Dwarven mines to the various locations\n" +
+ "Use \"Commissions Only\" to only show active commission locations"
+ )
+ @ConfigEditorDropdown(
+ values = {"Hide", "Commissions Only", "Always"},
+ initialIndex = 1
+ )
+ @ConfigAccordionId(id = 0)
+ public int locWaypoints = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide waypoints when at Location",
+ desc = "Hides the Commission Waypoints if you are already at the location of the waypoint.\n" +
+ "Only active if Waypoints are set to \"Commissions Only\""
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean hideWaypointIfAtLocation = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Emissary Waypoints",
+ desc = "Show waypoints in the Dwarven mines to emissaries\n" +
+ "Use \"Commission End\" to only show after finishing commissions"
+ )
+ @ConfigEditorDropdown(
+ values = {"Hide", "Commission End", "Always"},
+ initialIndex = 1
+ )
+ @ConfigAccordionId(id = 0)
+ public int emissaryWaypoints = 1;
+
+ @ConfigOption(
+ name = "Drill Fuel Bar",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean drillAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Drill Fuel Bar",
+ desc = "Show a fancy drill fuel bar when holding a drill in mining areas"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean drillFuelBar = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Fuel Bar Width",
+ desc = "Change the width of the drill fuel bar"
+ )
+ @ConfigEditorSlider(
+ minValue = 50,
+ maxValue = 400,
+ minStep = 10
+ )
+ @ConfigAccordionId(id = 1)
+ public int drillFuelBarWidth = 200;
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Fuel Bar Position",
+ desc = "Change the position of the drill fuel bar"
+ )
+ @ConfigEditorButton(
+ runnableId = 2,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 1)
+ public Position drillFuelBarPosition = new Position(0, -100, true, false);
+
+ @ConfigOption(
+ name = "Dwarven Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 2)
+ public boolean overlayAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Dwarven Overlay",
+ desc = "Show an Overlay with useful information on the screen while in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean dwarvenOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Dwarven Text",
+ desc = "\u00a7eDrag text to change the appearance of the Overlay\n" +
+ "\u00a7rGo to the Dwarven Mines to show this Overlay with useful information"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a73Goblin Slayer: \u00a7626.5%\n\u00a73Lucky Raffle: \u00a7c0.0%",
+ "\u00a73Mithril Powder: \u00a726,243",
+ "\u00a73Gemstone Powder: \u00a7d6,243",
+ "\u00a73Forge 1) \u00a79Diamonite\u00a77: \u00a7aReady!",
+ "\u00a73Pickaxe CD: \u00a7a78s"
+ }
+ )
+ @ConfigAccordionId(id = 2)
+ public List<Integer> dwarvenText2 = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4));
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Dwarven Overlay Position",
+ desc = "Change the position of the Dwarven Mines information Overlay (commisions, powder & forge statuses)"
+ )
+ @ConfigEditorButton(
+ runnableId = 1,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 2)
+ public Position overlayPosition = new Position(10, 100);
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Style",
+ desc = "Change the style of the Dwarven Mines information Overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 2)
+ public int overlayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Icons",
+ desc = "Show Icons representing the part of the overlay."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean dwarvenOverlayIcons = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Forge Display",
+ desc = "Change what gets shown in the Forge Display"
+ )
+ @ConfigEditorDropdown(
+ values = {"Only Done", "Only Working", "Everything Except Locked", "Everything"}
+ )
+ @ConfigAccordionId(id = 2)
+ public int forgeDisplay = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Forge Location",
+ desc = "Change when the forge display gets shown"
+ )
+ @ConfigEditorDropdown(
+ values = {"Dwarven Mines+Crystal Hollows", "Everywhere except dungeons", "Everywhere"}
+ )
+ @ConfigAccordionId(id = 2)
+ public int forgeDisplayEnabledLocations = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Forge Tab",
+ desc = "Only show the forge display when tab list is open\n" +
+ "\u00A7cThis only works outside of Dwarven Caves!"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 2)
+ public boolean forgeDisplayOnlyShowTab = false;
+
+ @ConfigOption(
+ name = "Metal Detector Solver",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 3)
+ public boolean metalDetectorSolverAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Waypoints",
+ desc =
+ "Enabled the metal detector solver for Mines of Divan, to use this stand still to calculate possible blocks and then if required stand" +
+ " still on another block."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean metalDetectorEnabled = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Possible Blocks",
+ desc = "Show waypoints on possible locations when NEU isn't sure about what block the treasure is."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean metalDetectorShowPossible = false;
+
+ @ConfigOption(
+ name = "Crystal Hollows Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 4)
+ public boolean crystalHollowOverlayAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Crystal Overlay",
+ desc = "Enables the Crystal Hollows Overlay."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean crystalHollowOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Crystal Overlay Position",
+ desc = "Change the position of the Crystal Hollows Overlay."
+ )
+ @ConfigEditorButton(
+ runnableId = 10,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 4)
+ public Position crystalHollowOverlayPosition = new Position(200, 0);
+
+ @Expose
+ @ConfigOption(
+ name = "Options",
+ desc = "Drag text to change the appearance of the overlay!\n" +
+ "Click add to add extra things!"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a73Amber Crystal: \u00a7aPlaced\n" +
+ "\u00a73Sapphire Crystal: \u00a7eCollected\n" +
+ "\u00a73Jade Crystal: \u00a7eMissing\n" +
+ "\u00a73Amethyst Crystal: \u00a7cMissing\n" +
+ "\u00a73Topaz Crystal: \u00a7cMissing\n",
+ "\u00a73Crystals: \u00a7a4/5",
+ "\u00a73Crystals: \u00a7a80%",
+ "\u00a73Electron Transmitter: \u00a7aDone\n" +
+ "\u00a73Robotron Reflector: \u00a7eIn Storage\n" +
+ "\u00a73Superlite Motor: \u00a7eIn Inventory\n" +
+ "\u00a73Synthetic Hearth: \u00a7cMissing\n" +
+ "\u00a73Control Switch: \u00a7cMissing\n" +
+ "\u00a73FTX 3070: \u00a7cMissing",
+ "\u00a73Electron Transmitter: \u00a7a3\n" +
+ "\u00a73Robotron Reflector: \u00a7e2\n" +
+ "\u00a73Superlite Motor: \u00a7e1\n" +
+ "\u00a73Synthetic Hearth: \u00a7c0\n" +
+ "\u00a73Control Switch: \u00a7c0\n" +
+ "\u00a73FTX 3070: \u00a7c0",
+ "\u00a73Automaton parts: \u00a7a5/6",
+ "\u00a73Automaton parts: \u00a7a83%",
+ "\u00a73Scavenged Lapis Sword: \u00a7aDone\n" +
+ "\u00a73Scavenged Golden Hammer: \u00a7eIn Storage\n" +
+ "\u00a73Scavenged Diamond Axe: \u00a7eIn Inventory\n" +
+ "\u00a73Scavenged Emerald Hammer: \u00a7cMissing\n",
+ "\u00a73Scavenged Lapis Sword: \u00a7a3\n" +
+ "\u00a73Scavenged Golden Hammer: \u00a7e2\n" +
+ "\u00a73Scavenged Diamond Axe: \u00a7e1\n" +
+ "\u00a73Scavenged Emerald Hammer: \u00a7c0\n",
+ "\u00a73Mines of Divan parts: \u00a7a3/4",
+ "\u00a73Mines of Divan parts: \u00a7a75%"
+ }
+ )
+ @ConfigAccordionId(id = 4)
+ public List<Integer> crystalHollowText = new ArrayList<>(Arrays.asList(0, 3, 7));
+
+ @Expose
+ @ConfigOption(
+ name = "Style",
+ desc = "Change the style of the Crystal Hollows Overlay."
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 4)
+ public int crystalHollowOverlayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Icons",
+ desc = "Show icons in the Overlay that represent the part."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean crystalHollowIcons = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide Done",
+ desc = "Don't show parts you've given to the NPC."
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean crystalHollowHideDone = false;
+
+ @ConfigOption(
+ name = "Locations",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 5)
+ @ConfigAccordionId(id = 4)
+ public boolean crystalHollowLocationAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Automaton",
+ desc = "Change where to show Automaton parts."
+ )
+ @ConfigEditorDropdown(
+ values = {"Crystal Hollows", "Precursor Remnants", "Lost Precursor City"}
+ )
+ @ConfigAccordionId(id = 5)
+ public int crystalHollowAutomatonLocation = 2;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Divan",
+ desc = "Change where to show Mines of Divan parts."
+ )
+ @ConfigEditorDropdown(
+ values = {"Crystal Hollows", "Mithril Deposits", "Mines of Divan"}
+ )
+ @ConfigAccordionId(id = 5)
+ public int crystalHollowDivanLocation = 2;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Crystal",
+ desc = "Change where to show Collected Crystals."
+ )
+ @ConfigEditorDropdown(
+ values = {"Crystal Hollows", "When No Other Overlays"}
+ )
+ @ConfigAccordionId(id = 5)
+ public int crystalHollowCrystalLocation = 1;
+
+ @ConfigOption(
+ name = "Colours",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 6)
+ @ConfigAccordionId(id = 4)
+ public boolean crystalHollowColourAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Main Color",
+ desc = "Change the main color of the overlay."
+
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowPartColor = 3;
+
+ @Expose
+ @ConfigOption(
+ name = "Done Color",
+ desc = "Change the colour when the part is given to the NPC."
+
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowDoneColor = 10;
+
+ @Expose
+ @ConfigOption(
+ name = "In Inventory Color",
+ desc = "Change the colour when the part is in the inventory."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowInventoryColor = 14;
+
+ @Expose
+ @ConfigOption(
+ name = "In Storage Color",
+ desc = "Change the colour when the part is in the storage."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowStorageColor = 14;
+
+ @Expose
+ @ConfigOption(
+ name = "Missing Color",
+ desc = "Change the colour when the part is missing."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowMissingColor = 12;
+
+ @Expose
+ @ConfigOption(
+ name = "Placed Color",
+ desc = "Change the colour when the crystal is placed."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowPlacedColor = 10;
+
+ @Expose
+ @ConfigOption(
+ name = "Collected Color",
+ desc = "Change the colour when the crystal is collected"
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowCollectedColor = 14;
+
+ @Expose
+ @ConfigOption(
+ name = "All Color",
+ desc = "Change the colour when you have 2/3-all of the parts collected in the count overlay."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowAllColor = 10;
+
+ @Expose
+ @ConfigOption(
+ name = "1/3 Color",
+ desc = "Change the colour when you have 1/3-2/3 of the parts collected in the count overlay."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowMiddleColor = 14;
+
+ @Expose
+ @ConfigOption(
+ name = "0 Color",
+ desc = "Change the colour when you have 0-1/3 of the parts collected in the count overlay."
+ )
+ @ConfigEditorDropdown(
+ values = {
+ "Black",
+ "Dark Blue",
+ "Dark Green",
+ "Dark Aqua",
+ "Dark Red",
+ "Dark Purple",
+ "Gold",
+ "Gray",
+ "Dark Gray",
+ "Blue",
+ "Green",
+ "Aqua",
+ "Red",
+ "Light Purple",
+ "Yellow",
+ "White"
+ }
+ )
+ @ConfigAccordionId(id = 6)
+ public int crystalHollowNoneColor = 12;
+
+ @ConfigOption(
+ name = "Wishing Compass Solver",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 7)
+ public boolean wishingCompassSolverAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Solver",
+ desc = "Show wishing compass target coordinates based on two samples"
+ )
+ @ConfigAccordionId(id = 7)
+ @ConfigEditorBoolean
+ public boolean wishingCompassSolver = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Skytils Waypoints",
+ desc = "Automatically create Skytils waypoints for well-known targets"
+ )
+ @ConfigAccordionId(id = 7)
+ @ConfigEditorBoolean
+ public boolean wishingCompassAutocreateKnownWaypoints = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Waypoint Names",
+ desc = "NOTE: Skytils overwrites waypoint coordinates with less accurate values for Skytils names."
+ )
+ @ConfigAccordionId(id = 7)
+ @ConfigEditorDropdown(
+ values = {"NEU", "Skytils"}
+ )
+ public int wishingCompassWaypointNames = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Puzzler Solver",
+ desc = "Show the correct block to mine for the puzzler puzzle in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ public boolean puzzlerSolver = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Titanium Alert",
+ desc = "Show an alert whenever titanium appears nearby"
+ )
+ @ConfigEditorBoolean
+ public boolean titaniumAlert = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Titanium must touch air",
+ desc = "Only show an alert if the Titanium touches air. (kinda sus)"
+ )
+ @ConfigEditorBoolean
+ public boolean titaniumAlertMustBeVisible = false;
+
+ @ConfigOption(
+ name = "Custom Textures",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 8)
+ public boolean texturesAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Dwarven Mines Textures",
+ desc = "Allows texture packs to retexture blocks in the Dwarven Mines. If you don't have a texture pack that does this, you should leave this off"
+ )
+ @ConfigAccordionId(id = 8)
+ @ConfigEditorBoolean
+ public boolean dwarvenTextures = false;
+ @Expose
+ @ConfigOption(
+ name = "Crystal Hollows Textures",
+ desc = "Allows texture packs to retexture blocks in the Crystal Hollows. If you don't have a texture pack that does this, you should leave this off"
+ )
+ @ConfigAccordionId(id = 8)
+ @ConfigEditorBoolean
+ public boolean crystalHollowTextures = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Replace Gemstone sounds",
+ desc = "Replace the break sounds of crystals in the Crystal Hollows. Requires a texture pack with this feature"
+ )
+ @ConfigAccordionId(id = 8)
+ @ConfigEditorBoolean
+ public boolean gemstoneSounds = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Replace Mithril sounds",
+ desc = "Replace the break sounds of mithril and titanium in the Dwarven mines. Requires a texture pack with this feature"
+ )
+ @ConfigAccordionId(id = 8)
+ @ConfigEditorBoolean
+ public boolean mithrilSounds = false;
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java
index 01a4576d..c6f00182 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Misc.java
@@ -1,144 +1,240 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-public class Misc {
- @Expose
- @ConfigOption(
- name = "Only Show on Skyblock",
- desc = "The item list and some other GUI elements will only show on skyblock"
- )
- @ConfigEditorBoolean
- public boolean onlyShowOnSkyblock = true;
-
- @Expose
- @ConfigOption(
- name = "Hide Potion Effects",
- desc = "Hide the potion effects inside your inventory while on skyblock"
- )
- @ConfigEditorBoolean
- public boolean hidePotionEffect = true;
-
- @Expose
- @ConfigOption(
- name = "Streamer Mode",
- desc = "Randomize lobby names in the scoreboard and chat messages to help prevent stream sniping"
- )
- @ConfigEditorBoolean
- public boolean streamerMode = false;
-
- @ConfigOption(
- name = "Fairy Soul Waypoints",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean fariySoulAccordion = false;
- @Expose
- @ConfigOption(
- name = "Fairy Souls Finder",
- desc = "Shows waypoints to fairy souls (/neusouls)"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean fariySoul = false;
-
- @Expose
- @ConfigOption(
- name = "Clear Fairy Souls",
- desc = "Clears waypoints to fairy souls (/neusouls clear)"
- )
- @ConfigEditorButton(
- runnableId = 16,
- buttonText = "Clear"
- )
- @ConfigAccordionId(id = 0)
- public boolean fariySoulClear = false;
-
- @Expose
- @ConfigOption(
- name = "Unclear Fairy Souls",
- desc = "Shows all waypoints to fairy souls (/neusouls unclear)"
- )
- @ConfigEditorButton(
- runnableId = 17,
- buttonText = "Unclear"
- )
- @ConfigAccordionId(id = 0)
- public boolean fariySoulUnclear = false;
-
- @Expose
- @ConfigOption(
- name = "GUI Click Sounds",
- desc = "Play click sounds in various NEU-related GUIs when pressing buttons"
- )
- @ConfigEditorBoolean
- public boolean guiButtonClicks = true;
-
- @Expose
- @ConfigOption(
- name = "Replace Chat Social Options",
- desc = "Replace Hypixel's chat social options with NEU's profile viewer or with /ah"
- )
- @ConfigEditorDropdown(
- values = {"Off", "/pv", "/ah"}
- )
- public int replaceSocialOptions1 = 1;
-
- @Expose
- @ConfigOption(
- name = "Damage Indicator Style",
- desc = "Change the style of Skyblock damage indicators to be easier to read\n" +
- "\u00A7cSome old animations mods break this feature"
- )
- @ConfigEditorDropdown(
- values = {"Off", "Commas", "Shortened"}
- )
- public int damageIndicatorStyle = 1;
-
- @Expose
- @ConfigOption(
- name = "Profile Viewer",
- desc = "Brings up the profile viewer (/pv)\n" +
- "Shows stats and networth of players"
- )
- @ConfigEditorButton(runnableId = 13, buttonText = "Open")
- public boolean openPV = true;
-
- @Expose
- @ConfigOption(
- name = "Edit Enchant Colours",
- desc = "Change the colours of certain skyblock enchants (/neuec)"
- )
- @ConfigEditorButton(runnableId = 8, buttonText = "Open")
- public boolean editEnchantColoursButton = true;
-
- @Expose
- @ConfigOption(
- name = "Chroma Text Speed",
- desc = "Change the speed of chroma text for items names (/neucustomize) and enchant colours (/neuec) with the chroma colour code (&z)"
- )
- @ConfigEditorSlider(
- minValue = 10,
- maxValue = 500,
- minStep = 10
- )
- public int chromaSpeed = 100;
-
- @Expose
- @ConfigOption(
- name = "Disable Skull retexturing",
- desc = "Disables the skull retexturing."
- )
- @ConfigEditorBoolean
- public boolean disableSkullRetexturing = false;
-
- @Expose
- @ConfigOption(
- name = "Disable NPC retexturing",
- desc = "Disables the NPC retexturing."
- )
- @ConfigEditorBoolean
- public boolean disableNPCRetexturing = false;
-
-} \ No newline at end of file
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import org.lwjgl.input.Keyboard;
+
+public class Misc {
+ @Expose
+ @ConfigOption(
+ name = "Only Show on Skyblock",
+ desc = "The item list and some other GUI elements will only show on skyblock"
+ )
+ @ConfigEditorBoolean
+ public boolean onlyShowOnSkyblock = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide Potion Effects",
+ desc = "Hide the potion effects inside your inventory while on skyblock"
+ )
+ @ConfigEditorBoolean
+ public boolean hidePotionEffect = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Streamer Mode",
+ desc = "Randomize lobby names in the scoreboard and chat messages to help prevent stream sniping"
+ )
+ @ConfigEditorBoolean
+ public boolean streamerMode = false;
+
+ @ConfigOption(
+ name = "Fairy Soul Waypoints",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean fariySoulAccordion = false;
+ @Expose
+ @ConfigOption(
+ name = "Track Fairy Souls",
+ desc = "Track Found Fairy Souls"
+ )
+ @ConfigEditorBoolean(runnableId = 20)
+ @ConfigAccordionId(id = 0)
+ public boolean trackFairySouls = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Waypoints",
+ desc = "Show Fairy Soul Waypoints (Requires fairy soul tracking)"
+ )
+ @ConfigEditorBoolean(
+ runnableId = 15
+ )
+ @ConfigAccordionId(id = 0)
+ public boolean fariySoul = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Mark All As Found",
+ desc = "Mark all fairy souls in current location as found"
+ )
+ @ConfigEditorButton(
+ runnableId = 16,
+ buttonText = "Clear"
+ )
+ @ConfigAccordionId(id = 0)
+ public boolean fariySoulClear = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Mark All As Missing",
+ desc = "Mark all fairy souls in current location as missing"
+ )
+ @ConfigEditorButton(
+ runnableId = 17,
+ buttonText = "Unclear"
+ )
+ @ConfigAccordionId(id = 0)
+ public boolean fariySoulUnclear = false;
+
+ @Expose
+ @ConfigOption(
+ name = "GUI Click Sounds",
+ desc = "Play click sounds in various NEU-related GUIs when pressing buttons"
+ )
+ @ConfigEditorBoolean
+ public boolean guiButtonClicks = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Replace Chat Social Options",
+ desc = "Replace Hypixel's chat social options with NEU's profile viewer or with /ah"
+ )
+ @ConfigEditorDropdown(
+ values = {"Off", "/pv", "/ah"}
+ )
+ public int replaceSocialOptions1 = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Damage Indicator Style",
+ desc = "Change Skyblock damage indicators to use shortened numbers\n" +
+ "\u00A7cSome old animations mods break this feature"
+ )
+ @ConfigEditorBoolean
+ public boolean damageIndicatorStyle2 = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Profile Viewer",
+ desc = "Brings up the profile viewer (/pv)\n" +
+ "Shows stats and networth of players"
+ )
+ @ConfigEditorButton(runnableId = 13, buttonText = "Open")
+ public boolean openPV = true;
+
+ @Expose
+ @ConfigOption(
+
+ name = "Edit Enchant Colours",
+ desc = "Change the colours of certain skyblock enchants (/neuec)"
+ )
+ @ConfigEditorButton(runnableId = 8, buttonText = "Open")
+ public boolean editEnchantColoursButton = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Chroma Text Speed",
+ desc = "Change the speed of chroma text for items names (/neucustomize) and enchant colours (/neuec) with the chroma colour code (&z)"
+ )
+ @ConfigEditorSlider(
+ minValue = 10,
+ maxValue = 500,
+ minStep = 10
+ )
+ public int chromaSpeed = 100;
+
+ @Expose
+ @ConfigOption(
+ name = "Disable Skull retexturing",
+ desc = "Disables the skull retexturing."
+ )
+ @ConfigEditorBoolean
+ public boolean disableSkullRetexturing = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Disable NPC retexturing",
+ desc = "Disables the NPC retexturing."
+ )
+ @ConfigEditorBoolean
+ public boolean disableNPCRetexturing = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Wiki",
+ desc = "The wiki to use in the wiki renderer."
+ )
+ @ConfigEditorDropdown(values = {
+ "Hypixel",
+ "Fandom"
+ })
+ public int wiki = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Waypoint Keybind",
+ desc = "Press this keybind to show waypoints to various NPCs"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
+ public int keybindWaypoint = Keyboard.KEY_NONE;
+
+ @Expose
+ @ConfigOption(
+ name = "Untrack close Waypoints",
+ desc = "Automatically untrack waypoints once you get close to them."
+ )
+ @ConfigEditorBoolean
+ public boolean untrackCloseWaypoints = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Warp twice",
+ desc = "Warp twice when using SHIFT+<waypoint keybind> to /warp to a waypoint."
+ )
+ @ConfigEditorBoolean
+ public boolean warpTwice = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Calculator",
+ desc = "Replace calculations like §9\"1+2\"§7 with the calculation result in sign popups (AH/BZ) and in the neu search bar"
+ )
+ @ConfigEditorDropdown(values = {"Off", "Enabled with ! Prefix", "Always enabled"})
+ public int calculationMode = 2;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Abiphone Warning",
+ desc = "Asks for confirmation when removing a contact in the abiphone"
+ )
+ @ConfigEditorBoolean
+ public boolean abiphoneWarning = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Coop Warning",
+ desc = "Asks for confirmation when clicking the coop diamond in profile menu"
+ )
+ @ConfigEditorBoolean
+ public boolean coopWarning = true;
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MiscOverlays.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MiscOverlays.java
index 849f5823..18b89733 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MiscOverlays.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/MiscOverlays.java
@@ -1,8 +1,33 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
import java.util.ArrayList;
import java.util.Arrays;
@@ -27,6 +52,15 @@ public class MiscOverlays {
@Expose
@ConfigOption(
+ name = "Todo Overlay Tab",
+ desc = "Only show the todo overlay when tab list is open"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean todoOverlayOnlyShowTab = false;
+
+ @Expose
+ @ConfigOption(
name = "Todo Text",
desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
"\u00a7rIf you want to see the time until something is available, click \"Add\" and then the respective timer"
@@ -40,12 +74,13 @@ public class MiscOverlays {
"\u00a73Fetchur: \u00a7e3h38m",
"\u00a73Commissions: \u00a7e3h38m",
"\u00a73Experiments: \u00a7e3h38m",
- "\u00a73Daily Mithril Powder: \u00a7e3h38m",
- "\u00a73Daily Gemstone Powder: \u00a7e3h38m",
+ "\u00a73Mithril Powder: \u00a7e3h38m",
+ "\u00a73Gemstone Powder: \u00a7e3h38m",
+ "\u00a73Heavy Pearls: \u00a7e3h38m",
}
)
@ConfigAccordionId(id = 0)
- public List<Integer> todoText2 = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8));
+ public List<Integer> todoText2 = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
@ConfigOption(
name = "Show Only If Soon",
@@ -141,8 +176,8 @@ public class MiscOverlays {
@Expose
@ConfigOption(
- name = "Daily Mithril Powder Display",
- desc = "Change the way the daily mithril powder displays\n" +
+ name = "Mithril Powder Display",
+ desc = "Change the way the mithril powder displays\n" +
"Only when ready, When very Soon, When soon, When kinda soon or always."
)
@ConfigAccordionId(id = 1)
@@ -153,8 +188,8 @@ public class MiscOverlays {
@Expose
@ConfigOption(
- name = "Daily Gemstone Powder Display",
- desc = "Change the way the daily gemstone powder displays\n" +
+ name = "Gemstone Powder Display",
+ desc = "Change the way the gemstone powder displays\n" +
"Only when ready, When very Soon, When soon, When kinda soon or always."
)
@ConfigAccordionId(id = 1)
@@ -163,6 +198,19 @@ public class MiscOverlays {
)
public int dailyGemstonePowderDisplay = 0;
+ @Expose
+ @ConfigOption(
+ name = "Heavy Pearl Display",
+ desc = "Change the way the heavy pearl displays\n" +
+ "Only when ready, When very Soon, When soon, When kinda soon or always."
+ )
+ @ConfigAccordionId(id = 1)
+ @ConfigEditorDropdown(
+ values = {"Only when ready", "When very Soon", "When soon", "When Kinda Soon", "Always"}
+ )
+
+ public int dailyHeavyPearlDisplay = 0;
+
@ConfigOption(
name = "Colours",
desc = ""
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java
index 82b0f22a..6c55fd09 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/NeuAuctionHouse.java
@@ -1,45 +1,73 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class NeuAuctionHouse {
- @Expose
- @ConfigOption(
- name = "Enable NeuAH",
- desc = "Turn on the NEU Auction House. \u00A7cWARNING: May negatively impact performance on low-end machines"
- )
- @ConfigEditorBoolean
- public boolean enableNeuAuctionHouse = false;
-
- @Expose
- @ConfigOption(
- name = "Disable AH Scroll",
- desc = "Disable scrolling using the scroll wheel inside NeuAH.\n" +
- "This should be used if you want to be able to scroll through tooltips"
- )
- @ConfigEditorBoolean
- public boolean disableAhScroll = false;
-
- @Expose
- @ConfigOption(
- name = "AH Notification (Mins)",
- desc = "Change the amount of time (in minutes) before the \"Ending Soon\" notification for an auction you have bid on"
- )
- @ConfigEditorSlider(
- minValue = 1f,
- maxValue = 10f,
- minStep = 1f
- )
- public int ahNotification = 5;
-
- @Expose
- @ConfigOption(
- name = "Price Filtering in NEU AH",
- desc = "The ability to filter the price of items and their respective average BIN values"
- )
- @ConfigEditorBoolean
- public boolean priceFiltering = false;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class
+NeuAuctionHouse {
+ @Expose
+ @ConfigOption(
+ name = "Enable NeuAH",
+ desc = "Turn on the NEU Auction House. \u00A7cWARNING: May negatively impact performance on low-end machines"
+ )
+ @ConfigEditorBoolean
+ public boolean enableNeuAuctionHouse = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Disable AH Scroll",
+ desc = "Disable scrolling using the scroll wheel inside NeuAH.\n" +
+ "This should be used if you want to be able to scroll through tooltips"
+ )
+ @ConfigEditorBoolean
+ public boolean disableAhScroll = false;
+
+ @Expose
+ @ConfigOption(
+ name = "AH Notification (Mins)",
+ desc = "Change the amount of time (in minutes) before the \"Ending Soon\" notification for an auction you have bid on"
+ )
+ @ConfigEditorSlider(
+ minValue = 1f,
+ maxValue = 10f,
+ minStep = 1f
+ )
+ public int ahNotification = 5;
+
+ @Expose
+ @ConfigOption(
+ name = "Price Filtering in NEU AH",
+ desc = "The ability to filter the price of items and their respective average BIN values"
+ )
+ @ConfigEditorBoolean
+ public boolean priceFiltering = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Save Last Search",
+ desc = "Saving the last query when closing the neuah"
+ )
+ @ConfigEditorBoolean
+ public boolean saveLastSearch = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java
index 9fae1d01..85ad2093 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Notifications.java
@@ -1,32 +1,89 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class Notifications {
- @Expose
- @ConfigOption(
- name = "Update Messages",
- desc = "Give a notification in chat whenever a new version of NEU is released"
- )
- @ConfigEditorBoolean
- public boolean showUpdateMsg = true;
-
- @Expose
- @ConfigOption(
- name = "RAM Warning",
- desc = "Warning when game starts with lots of RAM allocated\n" +
- "\u00a7cBefore disabling this, please seriously read the message. If you complain about FPS issues without listening to the warning, that's your fault."
- )
- @ConfigEditorBoolean
- public boolean doRamNotif = true;
-
- /*@Expose
- @ConfigOption(
- name = "Wrong Pet",
- desc = "Gives a notification in chat whenever you're using a pet that doesnt match the same xp you're gathering."
- )
- @ConfigEditorBoolean
- public boolean showWrongPetMsg = false;*/
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Notifications {
+ @Expose
+ @ConfigOption(
+ name = "Update Messages",
+ desc = "Give a notification in chat whenever a new version of NEU is released"
+ )
+ @ConfigEditorDropdown(values = {"Off", "Releases", "Pre-Releases"})
+ public int updateChannel = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Missing repo warning",
+ desc = "Warning when repo data is missing or out of date"
+ )
+ @ConfigEditorBoolean
+ public boolean outdatedRepo = true;
+
+ @Expose
+ @ConfigOption(
+ name = "RAM Warning",
+ desc = "Warning when game starts with lots of RAM allocated\n" +
+ "\u00a7cBefore disabling this, please seriously read the message. If you complain about FPS issues without listening to the warning, that's your fault."
+ )
+ @ConfigEditorBoolean
+ public boolean doRamNotif = true;
+
+ @Expose
+ @ConfigOption(
+ name = "OldAnimations Warning",
+ desc = "Warning when an unsupported OldAnimations mod is used"
+ )
+ @ConfigEditorBoolean
+ public boolean doOamNotif = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Fast Render Warning",
+ desc = "\u00a7cIf and ONLY if you have Fast Render disabled and are still seeing the warning, you can disable it here.\nDisabling it with Fast Render still on will lead to broken features."
+ )
+ @ConfigEditorBoolean
+ public boolean doFastRenderNotif = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Booster Cookie Warning",
+ desc = "Warning when a booster cookie is about to expire"
+ )
+ @ConfigEditorBoolean
+ public boolean doBoosterNotif = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Booster Cookie Warning Minutes",
+ desc = "Change the minimum time required for the Booster Cookie warning to activate"
+ )
+ @ConfigEditorSlider(
+ minValue = 10,
+ maxValue = 5760,
+ minStep = 25
+ )
+ public int boosterCookieWarningMins = 1440;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/PetOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/PetOverlay.java
index f0d0c22c..353c4e08 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/PetOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/PetOverlay.java
@@ -1,118 +1,141 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class PetOverlay {
- @Expose
- @ConfigOption(
- name = "Enable Pet Info Overlay",
- desc = "Shows current active pet and pet exp on screen."
- )
- @ConfigEditorBoolean
- public boolean enablePetInfo = false;
-
- @Expose
- @ConfigOption(
- name = "Edit Pet Info Position",
- desc = "The position of the pet info."
- )
- @ConfigEditorButton(
- runnableId = 4,
- buttonText = "Edit"
- )
- public Position petInfoPosition = new Position(-1, -1);
-
- @Expose
- @ConfigOption(
- name = "Pet Overlay Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rEquip a pet to show the overlay"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7a[Lvl 37] \u00a7fRock",
- "\u00a7b2,312.9/2,700\u00a7e (85.7%)",
- "\u00a7b2.3k/2.7k\u00a7e (85.7%)",
- "\u00a7bXP/h: \u00a7e27,209",
- "\u00a7bTotal XP: \u00a7e30,597.9",
- "\u00a7bHeld Item: \u00a7fMining Exp Boost",
- "\u00a7bUntil L38: \u00a7e5m13s",
- "\u00a7bUntil L100: \u00a7e2d13h"
- }
- )
- public List<Integer> petOverlayText = new ArrayList<>(Arrays.asList(0, 2, 3, 6, 4));
-
- @Expose
- @ConfigOption(
- name = "Pet Overlay Icon",
- desc = "Show the icon of the pet you have equiped in the overlay"
- )
- @ConfigEditorBoolean
- public boolean petOverlayIcon = true;
-
- @Expose
- @ConfigOption(
- name = "Pet Info Overlay Style",
- desc = "Change the style of the Pet Info overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow Only", "Full Shadow"}
- )
- public int petInfoOverlayStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Show Last Pet",
- desc = "Show 2 pets on the overlay\nUseful if training two pets at once with autopet"
- )
- @ConfigEditorBoolean
- public boolean dualPets = false;
-
- @Expose
- @ConfigOption(
- name = "Pet Inventory Display",
- desc = "Shows an overlay in your inventory showing your current pet"
- )
- @ConfigEditorBoolean
- public boolean petInvDisplay = false;
-
- @Expose
- @ConfigOption(
- name = "GUI Colour",
- desc = "Change the colour of the GUI"
- )
- @ConfigEditorDropdown(
- values = {"Vanilla", "Grey", "Dark", "Transparent", "FSR"}
- )
- public int colourStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Click To Open Pets",
- desc = "Click on the hud to open /pets"
- )
- @ConfigEditorBoolean
- public boolean sendPetsCommand = true;
-
- @Expose
- @ConfigOption(
- name = "Hide Pet Inventory Tooltip",
- desc = "Hides the tooltip of your active in your inventory"
- )
- @ConfigEditorBoolean
- public boolean hidePetTooltip = false;
-
- @Expose
- @ConfigOption(
- name = "Show upgraded Pet Level",
- desc = "Show the estimated pet level after an upgrade at Kats"
- )
- @ConfigEditorBoolean
- public boolean showKatSitting = true;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class PetOverlay {
+ @Expose
+ @ConfigOption(
+ name = "Enable Pet Info Overlay",
+ desc = "Shows current active pet and pet exp on screen."
+ )
+ @ConfigEditorBoolean
+ public boolean enablePetInfo = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Pet Info Position",
+ desc = "Change the position of the pet info overlay"
+ )
+ @ConfigEditorButton(
+ runnableId = 4,
+ buttonText = "Edit"
+ )
+ public Position petInfoPosition = new Position(-1, -1);
+
+ @Expose
+ @ConfigOption(
+ name = "Pet Overlay Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rEquip a pet to show the overlay"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7a[Lvl 37] \u00a7fRock",
+ "\u00a7b2,312.9/2,700\u00a7e (85.7%)",
+ "\u00a7b2.3k/2.7k\u00a7e (85.7%)",
+ "\u00a7bXP/h: \u00a7e27,209",
+ "\u00a7bTotal XP: \u00a7e30,597.9",
+ "\u00a7bHeld Item: \u00a7fMining Exp Boost",
+ "\u00a7bUntil L38: \u00a7e5m13s",
+ "\u00a7bUntil L100: \u00a7e2d13h"
+ }
+ )
+ public List<Integer> petOverlayText = new ArrayList<>(Arrays.asList(0, 2, 3, 6, 4));
+
+ @Expose
+ @ConfigOption(
+ name = "Pet Overlay Icon",
+ desc = "Show the icon of the pet you have equiped in the overlay"
+ )
+ @ConfigEditorBoolean
+ public boolean petOverlayIcon = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Pet Info Overlay Style",
+ desc = "Change the style of the Pet Info overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ public int petInfoOverlayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Last Pet",
+ desc = "Show 2 pets on the overlay\nUseful if training two pets at once with autopet"
+ )
+ @ConfigEditorBoolean
+ public boolean dualPets = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Pet Inventory Display",
+ desc = "Shows an overlay in your inventory showing your current pet"
+ )
+ @ConfigEditorBoolean
+ public boolean petInvDisplay = false;
+
+ @Expose
+ @ConfigOption(
+ name = "GUI Style",
+ desc = "Change the colour of the GUI"
+ )
+ @ConfigEditorDropdown(
+ values = {"Minecraft", "Grey", "PacksHQ Dark", "Transparent", "FSR"}
+ )
+ public int colourStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Click To Open Pets",
+ desc = "Click on the hud to open /pets"
+ )
+ @ConfigEditorBoolean
+ public boolean sendPetsCommand = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide Pet Inventory Tooltip",
+ desc = "Hides the tooltip of your active in your inventory"
+ )
+ @ConfigEditorBoolean
+ public boolean hidePetTooltip = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show upgraded Pet Level",
+ desc = "Show the estimated pet level after an upgrade at Kats"
+ )
+ @ConfigEditorBoolean
+ public boolean showKatSitting = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java
new file mode 100644
index 00000000..673e1015
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/ProfileViewer.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.BuildFlags;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class ProfileViewer {
+
+ @ConfigOption(
+ name = "Profile Viewer info",
+ desc =
+ "The Profile Viewer requires you to have an \u00A72api key\u00A77 set (if you don't have one set do \u00A72/api new\u00A77)\n"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ public boolean pvInfo = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Open Profile Viewer",
+ desc = "Brings up the profile viewer (/pv)\n" +
+ "Shows stats and networth of players"
+ )
+ @ConfigEditorButton(
+ runnableId = 13,
+ buttonText = "Open"
+ )
+ public boolean openPV = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Page layout",
+ desc = "\u00a7rSelect the order of the pages at the top of the Profile Viewer\n" +
+ "\u00a7eDrag text to rearrange"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7eBasic Info",
+ "\u00a7eDungeons",
+ "\u00a7eExtra Info",
+ "\u00a7eInventories",
+ "\u00a7eCollections",
+ "\u00a7ePets",
+ "\u00a7eMining",
+ "\u00a7eBingo",
+ "\u00a7eTrophy Fish",
+ "\u00a7eBestiary",
+ },
+ allowDeleting = false
+ )
+ public List<Integer> pageLayout = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+
+ @Expose
+ @ConfigOption(
+ name = "Always show bingo tab",
+ desc = "Always show bingo tab or only show it when the bingo profile is selected"
+ )
+ @ConfigEditorBoolean
+ public boolean alwaysShowBingoTab = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Pronouns in /pv",
+ desc = "Shows the pronouns of a player in /pv. Data sourced from pronoundb.org"
+ )
+ @ConfigEditorBoolean
+ public boolean showPronounsInPv = BuildFlags.ENABLE_PRONOUNS_IN_PV_BY_DEFAULT;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java
index 71b41329..943417e6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SkillOverlays.java
@@ -1,317 +1,346 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-import org.lwjgl.input.Keyboard;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class SkillOverlays {
- @ConfigOption(
- name = "Skill Overlay info",
- desc =
- "The skill trackers need you to have an \u00A72api key\u00A77 set (if you don't have one set do \u00A72/api new\u00A77)\n" +
- "For the overlays to show you need a \u00A7bmathematical hoe\u00A77 or an axe with \u00A7bcultivating\u00A77 " +
- "enchant for farming, a pickaxe with \u00A7bcompact\u00A77 for mining or a rod with \u00A7bexpertise\u00A77"
- )
- @ConfigEditorFSR(
- runnableId = 12,
- buttonText = ""
- )
- public boolean skillInfo = false;
- @ConfigOption(
- name = "Farming",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean farmingAccordion = false;
- @Expose
- @ConfigOption(
- name = "Enable Farming Overlay",
- desc = "Show an overlay while farming with useful information"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean farmingOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Farming Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rHold a mathematical hoe or use an axe with cultivating enchantment while gaining farming xp to show the overlay"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7bCounter: \u00a7e37,547,860",
- "\u00a7bCrops/m: \u00a7e38.29",
- "\u00a7bFarm: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
- "\u00a7bCurrent XP: \u00a7e6,734",
- "\u00a7bRemaining XP: \u00a7e3,265",
- "\u00a7bXP/h: \u00a7e238,129",
- "\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
- "\u00a7bETA: \u00a7e13h12m",
- "\u00a7bPitch: \u00a7e69.42\u00a7l\u1D52",
- "\u00a7bCultivating: \u00a7e10,137,945/20,000,000",
- "\u00a7bCoins/m \u00a7e57,432"
- }
- )
- @ConfigAccordionId(id = 0)
- public List<Integer> farmingText = new ArrayList<>(Arrays.asList(0, 9, 10, 1, 2, 3, 4, 5, 7, 6));
-
- @Expose
- @ConfigOption(
- name = "Use BZ Price For Coins/m",
- desc = "Uses the bazzar price instead of NPC price for coins/m"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean useBZPrice = true;
-
- @Expose
- @ConfigOption(
- name = "Edit Farming Overlay Position",
- desc = "Change the position of the Farming overlay"
- )
- @ConfigEditorButton(
- runnableId = 3,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 0)
- public Position farmingPosition = new Position(10, 200);
-
- @Expose
- @ConfigOption(
- name = "Farming Style",
- desc = "Change the style of the Farming overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 0)
- public int farmingStyle = 0;
- @ConfigOption(
- name = "Mining",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- public boolean miningAccordion = false;
- @Expose
- @ConfigOption(
- name = "Enable Mining Overlay",
- desc = "Show an overlay while Mining with useful information"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean miningSkillOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Mining Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rHold a pickaxe with compact while gaining mining xp to show the overlay"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7bCompact: \u00a7e547,860",
- "\u00a7bBlocks/m: \u00a7e38.29",
- "\u00a7bMine: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
- "\u00a7bCurrent XP: \u00a7e6,734",
- "\u00a7bRemaining XP: \u00a7e3,265",
- "\u00a7bXP/h: \u00a7e238,129",
- "\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
- "\u00a7bETA: \u00a7e13h12m",
- "\u00a7bCompact Progress: \u00a7e137,945/150,000"
- }
- )
- @ConfigAccordionId(id = 1)
- public List<Integer> miningText = new ArrayList<>(Arrays.asList(0, 8, 1, 2, 3, 4, 5, 7));
-
- @Expose
- @ConfigOption(
- name = "Edit Mining Overlay Position",
- desc = "Change the position of the Mining overlay"
- )
- @ConfigEditorButton(
- runnableId = 11,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 1)
- public Position miningPosition = new Position(10, 200);
-
- @Expose
- @ConfigOption(
- name = "Mining Style",
- desc = "Change the style of the Mining overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 1)
- public int miningStyle = 0;
-
- @ConfigOption(
- name = "Fishing",
- desc = ""
- )
- @ConfigEditorAccordion(id = 3)
- public boolean fishingAccordion = false;
- @Expose
- @ConfigOption(
- name = "Enable Fishing Overlay",
- desc = "Show an overlay while Fishing with useful information"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 3)
- public boolean FishingSkillOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Fishing Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rHold a fishing rod with expertise enchantment while gaining fishing xp to show the overlay"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7bExpertise: \u00a7e7,945/10,000",
- //"\u00a7bCatches/m: \u00a7e38.29",
- "\u00a7bFishing: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
- "\u00a7bCurrent XP: \u00a7e6,734",
- "\u00a7bRemaining XP: \u00a7e3,265",
- "\u00a7bXP/h: \u00a7e238,129",
- //"\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
- "\u00a7bETA: \u00a7e13h12m",
- //"\u00a7bExpertise Progress: \u00a7e7,945/10,000",
- "\u00a7bTimer: \u00a7e1m15s"
- }
- )
- @ConfigAccordionId(id = 3)
- public List<Integer> fishingText = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6));
-
- @Expose
- @ConfigOption(
- name = "Edit Fishing Overlay Position",
- desc = "Change the position of the Fishing overlay"
- )
- @ConfigEditorButton(
- runnableId = 14,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 3)
- public Position fishingPosition = new Position(10, 200);
-
- @Expose
- @ConfigOption(
- name = "Fishing Style",
- desc = "Change the style of the Fishing overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 3)
- public int fishingStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Toggle Fishing timer",
- desc = "Start or stop the timer on the fishing overlay\n" +
- "Also can plays a ding customizable below"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_END)
- @ConfigAccordionId(id = 3)
- public int fishKey = Keyboard.KEY_END;
-
- @Expose
- @ConfigOption(
- name = "Fishing Timer Alert",
- desc = "Change the amount of time (seconds) until the timer dings"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 600,
- minStep = 20
- )
- @ConfigAccordionId(id = 3)
- public int customFishTimer = 300;
-
- @ConfigOption(
- name = "Combat",
- desc = ""
- )
- @ConfigEditorAccordion(id = 4)
- public boolean combatAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "\u00A7cWarning",
- desc = "The combat display will only show if you have a Book of Stats on the item you are using"
- )
- @ConfigEditorFSR(
- runnableId = 12,
- buttonText = ""
- )
- @ConfigAccordionId(id = 4)
- public boolean combatInfo = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Combat Overlay",
- desc = "Show an overlay while Combat with useful information"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean combatSkillOverlay = true;
-
- @Expose
- @ConfigOption(
- name = "Combat Text",
- desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
- "\u00a7rHold an item with Book of Stats to show the display"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7bKills: \u00a7e547,860",
- "\u00a7bCombat: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
- "\u00a7bCurrent XP: \u00a7e6,734",
- "\u00a7bRemaining XP: \u00a7e3,265",
- "\u00a7bXP/h: \u00a7e238,129",
- "\u00a7bETA: \u00a7e13h12m"
- }
- )
- @ConfigAccordionId(id = 4)
- public List<Integer> combatText = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5));
-
- @Expose
- @ConfigOption(
- name = "Edit Combat Overlay Position",
- desc = "Change the position of the Combat overlay"
- )
- @ConfigEditorButton(
- runnableId = 19,
- buttonText = "Edit"
- )
- @ConfigAccordionId(id = 4)
- public Position combatPosition = new Position(10, 200);
-
- @Expose
- @ConfigOption(
- name = "Combat Style",
- desc = "Change the style of the Combat overlay"
- )
- @ConfigEditorDropdown(
- values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
- )
- @ConfigAccordionId(id = 4)
- public int combatStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Always show combat overlay",
- desc = "Shows combat overlay even if you dont have Book of Stats"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 4)
- public boolean alwaysShowCombatOverlay = false;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import org.lwjgl.input.Keyboard;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class SkillOverlays {
+ @ConfigOption(
+ name = "Skill Overlay info",
+ desc =
+ "The skill trackers need you to have an \u00A72api key\u00A77 set (if you don't have one set do \u00A72/api new\u00A77)\n" +
+ "For the overlays to show you need a \u00A7bmathematical hoe\u00A77 or an axe with \u00A7bcultivating\u00A77 " +
+ "enchant for farming, a pickaxe with \u00A7bcompact\u00A77 for mining or a rod with \u00A7bexpertise\u00A77"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ public boolean skillInfo = false;
+ @ConfigOption(
+ name = "Farming",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean farmingAccordion = false;
+ @Expose
+ @ConfigOption(
+ name = "Enable Farming Overlay",
+ desc = "Show an overlay while farming with useful information"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean farmingOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Farming Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rHold a mathematical hoe or use an axe with cultivating enchantment while gaining farming xp to show the overlay"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7bCounter: \u00a7e37,547,860",
+ "\u00a7bCrops/m: \u00a7e38.29",
+ "\u00a7bFarming: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bCurrent XP: \u00a7e6,734",
+ "\u00a7bRemaining XP: \u00a7e3,265",
+ "\u00a7bXP/h: \u00a7e238,129",
+ "\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
+ "\u00a7bETA: \u00a7e13h12m",
+ "\u00a7bPitch: \u00a7e69.42\u00a7l\u1D52",
+ "\u00a7bCultivating: \u00a7e10,137,945/20,000,000",
+ "\u00a7bCoins/m \u00a7e57,432"
+ }
+ )
+ @ConfigAccordionId(id = 0)
+ public List<Integer> farmingText = new ArrayList<>(Arrays.asList(0, 9, 10, 1, 2, 3, 4, 5, 7, 6));
+
+ @Expose
+ @ConfigOption(
+ name = "Use BZ Price For Coins/m",
+ desc = "Uses the bazzar price instead of NPC price for coins/m"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean useBZPrice = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Farming Overlay Position",
+ desc = "Change the position of the Farming overlay"
+ )
+ @ConfigEditorButton(
+ runnableId = 3,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 0)
+ public Position farmingPosition = new Position(10, 200);
+
+ @Expose
+ @ConfigOption(
+ name = "Farming Style",
+ desc = "Change the style of the Farming overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 0)
+ public int farmingStyle = 0;
+ @ConfigOption(
+ name = "Mining",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean miningAccordion = false;
+ @Expose
+ @ConfigOption(
+ name = "Enable Mining Overlay",
+ desc = "Show an overlay while Mining with useful information"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean miningSkillOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Mining Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rHold a pickaxe with compact while gaining mining xp to show the overlay"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7bCompact: \u00a7e547,860",
+ "\u00a7bBlocks/m: \u00a7e38.29",
+ "\u00a7bMining: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bCurrent XP: \u00a7e6,734",
+ "\u00a7bRemaining XP: \u00a7e3,265",
+ "\u00a7bXP/h: \u00a7e238,129",
+ "\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
+ "\u00a7bETA: \u00a7e13h12m",
+ "\u00a7bCompact Progress: \u00a7e137,945/150,000"
+ }
+ )
+ @ConfigAccordionId(id = 1)
+ public List<Integer> miningText = new ArrayList<>(Arrays.asList(0, 8, 1, 2, 3, 4, 5, 7));
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Mining Overlay Position",
+ desc = "Change the position of the Mining overlay"
+ )
+ @ConfigEditorButton(
+ runnableId = 11,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 1)
+ public Position miningPosition = new Position(10, 200);
+
+ @Expose
+ @ConfigOption(
+ name = "Mining Style",
+ desc = "Change the style of the Mining overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int miningStyle = 0;
+
+ @ConfigOption(
+ name = "Fishing",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 3)
+ public boolean fishingAccordion = false;
+ @Expose
+ @ConfigOption(
+ name = "Enable Fishing Overlay",
+ desc = "Show an overlay while Fishing with useful information"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 3)
+ public boolean FishingSkillOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rHold a fishing rod with expertise enchantment while gaining fishing xp to show the overlay"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7bExpertise: \u00a7e7,945/10,000",
+ //"\u00a7bCatches/m: \u00a7e38.29",
+ "\u00a7bFishing: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bCurrent XP: \u00a7e6,734",
+ "\u00a7bRemaining XP: \u00a7e3,265",
+ "\u00a7bXP/h: \u00a7e238,129",
+ //"\u00a7bYaw: \u00a7e68.25\u00a7l\u1D52",
+ "\u00a7bETA: \u00a7e13h12m",
+ //"\u00a7bExpertise Progress: \u00a7e7,945/10,000",
+ "\u00a7bTimer: \u00a7e1m15s"
+ }
+ )
+ @ConfigAccordionId(id = 3)
+ public List<Integer> fishingText = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4, 5, 6));
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Fishing Overlay Position",
+ desc = "Change the position of the Fishing overlay"
+ )
+ @ConfigEditorButton(
+ runnableId = 14,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 3)
+ public Position fishingPosition = new Position(10, 200);
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing Style",
+ desc = "Change the style of the Fishing overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 3)
+ public int fishingStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Toggle Fishing timer",
+ desc = "Start or stop the timer on the fishing overlay\n" +
+ "Also can plays a ding customizable below"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_END)
+ @ConfigAccordionId(id = 3)
+ public int fishKey = Keyboard.KEY_END;
+
+ @Expose
+ @ConfigOption(
+ name = "Fishing Timer Alert",
+ desc = "Change the amount of time (seconds) until the timer dings"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 600,
+ minStep = 20
+ )
+ @ConfigAccordionId(id = 3)
+ public int customFishTimer = 300;
+
+ @ConfigOption(
+ name = "Combat",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 4)
+ public boolean combatAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "\u00A7cWarning",
+ desc = "The combat display will only show if you have a Book of Stats or the Champion enchant"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ @ConfigAccordionId(id = 4)
+ public boolean combatInfo = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Combat Overlay",
+ desc = "Show an overlay while Combat with useful information"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean combatSkillOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Combat Text",
+ desc = "\u00a7eDrag text to change the appearance of the overlay\n" +
+ "\u00a7rHold an item with Book of Stats to show the display"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7bKills: \u00a7e547,860",
+ "\u00a7bCombat: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bCurrent XP: \u00a7e6,734",
+ "\u00a7bRemaining XP: \u00a7e3,265",
+ "\u00a7bXP/h: \u00a7e238,129",
+ "\u00a7bETA: \u00a7e13h12m",
+ "\u00a7bChampion XP: \u00a7e3,523"
+ }
+ )
+ @ConfigAccordionId(id = 4)
+ public List<Integer> combatText = new ArrayList<>(Arrays.asList(0, 6, 1, 2, 3, 4, 5));
+
+ @Expose
+ @ConfigOption(
+ name = "Edit Combat Overlay Position",
+ desc = "Change the position of the Combat overlay"
+ )
+ @ConfigEditorButton(
+ runnableId = 19,
+ buttonText = "Edit"
+ )
+ @ConfigAccordionId(id = 4)
+ public Position combatPosition = new Position(10, 200);
+
+ @Expose
+ @ConfigOption(
+ name = "Combat Style",
+ desc = "Change the style of the Combat overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ @ConfigAccordionId(id = 4)
+ public int combatStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Always show combat overlay",
+ desc = "Shows combat overlay even if you dont have Book of Stats or the Champion enchant"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 4)
+ public boolean alwaysShowCombatOverlay = false;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlayerOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlayerOverlay.java
index 220b992b..927d00e5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlayerOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlayerOverlay.java
@@ -1,8 +1,32 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.options.seperateSections;
import com.google.gson.annotations.Expose;
import io.github.moulberry.notenoughupdates.core.config.Position;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
import java.util.ArrayList;
import java.util.Arrays;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlotLocking.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlotLocking.java
index f9d1eef1..22286808 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlotLocking.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/SlotLocking.java
@@ -1,91 +1,114 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-import org.lwjgl.input.Keyboard;
-
-public class SlotLocking {
- @Expose
- @ConfigOption(
- name = "\u00A7cWarning",
- desc = "Make sure you have SBA's locked slots off before you turn NEU's on"
- )
- @ConfigEditorFSR(
- runnableId = 12
- )
- public boolean slotLockWarning = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Slot Locking",
- desc = "Allows you to lock slots and create slot bindings"
- )
- @ConfigEditorBoolean
- public boolean enableSlotLocking = false;
-
- @Expose
- @ConfigOption(
- name = "Enable Slot Binding",
- desc = "Allows you to create slot bindings\nNote: \"Enable Slot Locking\" must be on"
- )
- @ConfigEditorBoolean
- public boolean enableSlotBinding = true;
-
- @Expose
- @ConfigOption(
- name = "Don't Drop Bound Slots",
- desc = "Slot bindings also act as locked slots (prevents dropping / moving in inventory)"
- )
- @ConfigEditorBoolean
- public boolean bindingAlsoLocks = false;
-
- @Expose
- @ConfigOption(
- name = "Slot Lock Key",
- desc = "Click this key to LOCK a slot\n" +
- "Hold this key and drag to BIND a slot"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_L)
- public int slotLockKey = Keyboard.KEY_L;
-
- @Expose
- @ConfigOption(
- name = "Lock Slots in Trade",
- desc = "Prevents trading locked items in the custom trade windows"
- )
- @ConfigEditorBoolean
- public boolean lockSlotsInTrade = true;
-
- @Expose
- /*@ConfigOption(
- name = "Item Swap drop delay",
- desc = "Set the delay between swapping to another item and being able to drop it.\n"+
- "This is to fix a bug that allowed you to drop slot locked items."
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 500,
- minStep = 5
- )*/
- public int slotLockSwapDelay = 100;
-
- @Expose
- @ConfigOption(
- name = "Slot Lock Sound",
- desc = "Play a ding when locking/unlocking slots"
- )
- @ConfigEditorBoolean
- public boolean slotLockSound = true;
-
- @Expose
- @ConfigOption(
- name = "Slot Lock Sound Vol.",
- desc = "Set the volume of the ding sound"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 100,
- minStep = 1
- )
- public float slotLockSoundVol = 20;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import org.lwjgl.input.Keyboard;
+
+public class SlotLocking {
+ @Expose
+ @ConfigOption(
+ name = "\u00A7cWarning",
+ desc = "Make sure you have SBA's locked slots off before you turn NEU's on"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12
+ )
+ public boolean slotLockWarning = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Slot Locking",
+ desc = "Allows you to lock slots and create slot bindings"
+ )
+ @ConfigEditorBoolean
+ public boolean enableSlotLocking = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Enable Slot Binding",
+ desc = "Allows you to create slot bindings\nNote: \"Enable Slot Locking\" must be on"
+ )
+ @ConfigEditorBoolean
+ public boolean enableSlotBinding = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Don't Drop Bound Slots",
+ desc = "Slot bindings also act as locked slots (prevents dropping / moving in inventory)"
+ )
+ @ConfigEditorBoolean
+ public boolean bindingAlsoLocks = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Slot Lock Key",
+ desc = "Click this key to LOCK a slot\n" +
+ "Hold this key and drag to BIND a slot"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_L)
+ public int slotLockKey = Keyboard.KEY_L;
+
+ @Expose
+ @ConfigOption(
+ name = "Lock Slots in Trade",
+ desc = "Prevents trading locked items in the custom trade windows"
+ )
+ @ConfigEditorBoolean
+ public boolean lockSlotsInTrade = true;
+
+ @Expose
+ /*@ConfigOption(
+ name = "Item Swap drop delay",
+ desc = "Set the delay between swapping to another item and being able to drop it.\n"+
+ "This is to fix a bug that allowed you to drop slot locked items."
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 500,
+ minStep = 5
+ )*/
+ public int slotLockSwapDelay = 100;
+
+ @Expose
+ @ConfigOption(
+ name = "Slot Lock Sound",
+ desc = "Play a ding when locking/unlocking slots"
+ )
+ @ConfigEditorBoolean
+ public boolean slotLockSound = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Slot Lock Sound Vol.",
+ desc = "Set the volume of the ding sound"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 100,
+ minStep = 1
+ )
+ public float slotLockSoundVol = 20;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java
index a2d50409..e43fa5cf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/StorageGUI.java
@@ -1,260 +1,287 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-import org.lwjgl.input.Keyboard;
-
-public class StorageGUI {
- @ConfigOption(
- name = "Storage Overlay",
- desc = ""
- )
- @ConfigEditorAccordion(id = 1)
- public boolean storageOverlayAccordion = false;
-
- @Expose
- public int selectedIndex = 0;
- @ConfigOption(
- name = "\u00A7cWarning",
- desc = "You need Fast Render and Antialiasing off for these settings to work\n" +
- "You can find these in your video settings"
- )
- @ConfigEditorFSR(
- runnableId = 12,
- buttonText = ""
- )
- @ConfigAccordionId(id = 1)
- public boolean storageGUIWarning = false;
- @Expose
- @ConfigOption(
- name = "Enable Storage GUI",
- desc = "Show a custom storage overlay when accessing /storage. " +
- "Makes switching between pages much easier and also allows for searching through all storages"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean enableStorageGUI3 = true;
-
- @Expose
- @ConfigOption(
- name = "Storage Height",
- desc = "Change the height of the storage preview section. Increasing this allows more storages to be seen at once"
- )
- @ConfigEditorSlider(
- minValue = 104,
- maxValue = 312,
- minStep = 26
- )
- @ConfigAccordionId(id = 1)
- public int storageHeight = 208;
-
- @Expose
- @ConfigOption(
- name = "Storage Style",
- desc = "Change the visual style of the overlay"
- )
- @ConfigEditorDropdown(
- values = {"Transparent", "Minecraft", "Dark", "Custom"}
- )
- @ConfigAccordionId(id = 1)
- public int displayStyle = 0;
-
- @Expose
- @ConfigOption(
- name = "Enderchest Preview",
- desc = "Preview Enderchest pages when hovering over the selector on the left side"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean enderchestPreview = true;
-
- @Expose
- @ConfigOption(
- name = "Backpack Preview",
- desc = "Preview Backpacks when hovering over the selector on the left side"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean backpackPreview = true;
-
- @Expose
- @ConfigOption(
- name = "Compact Vertically",
- desc = "Remove the space between backpacks when there is a size discrepancy"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean masonryMode = false;
-
- @Expose
- @ConfigOption(
- name = "Fancy Glass Panes",
- desc = "Replace the glass pane textures in your storage containers with a fancy connected texture"
- )
- @ConfigEditorDropdown(
- values = {"On", "Locked", "Off"}
- )
- @ConfigAccordionId(id = 1)
- public int fancyPanes = 0;
-
- @Expose
- @ConfigOption(
- name = "Search Bar Autofocus",
- desc = "Automatically focus the search bar when pressing keys"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean searchBarAutofocus = true;
-
- @Expose
- @ConfigOption(
- name = "Show Enchant Glint",
- desc = "Toggle enchant glint in storage GUI"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 1)
- public boolean showEnchantGlint = true;
-
- @Expose
- @ConfigOption(
- name = "Selected Storage Colour",
- desc = "Change the colour used to draw the selected backpack border"
- )
- @ConfigEditorColour
- @ConfigAccordionId(id = 1)
- public String selectedStorageColour = "0:255:255:223:0";
-
- @Expose
- @ConfigOption(
- name = "Scrollable Tooltips",
- desc = "Support for scrolling tooltips for users with small monitors\n" +
- "This will prevent the menu from scrolling while holding the key, allowing you to scroll tooltips"
- )
- @ConfigEditorKeybind(defaultKey = 0)
- @ConfigAccordionId(id = 1)
- public int cancelScrollKey = 0;
-
- @ConfigOption(
- name = "Inventory Backpacks",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean inventorySlotAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Inventory Backpacks",
- desc = "Add a \"10th slot\" to your inventory which allows you to quickly access your backpacks"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean showInvBackpack = false;
-
- //public boolean showInvBackpack = false;
- @Expose
- @ConfigOption(
- name = "Scroll to Backpack",
- desc = "Allow scrolling to the backpack using the mouse wheel.\n" +
- "\"Scroll (Key)\" = Allow scrolling to 10th slot only while 'Backpack Scroll Key' (default: SHIFT) is pressed"
- )
- @ConfigEditorDropdown(
- values = {"Scroll (Key)", "Scroll (Always)", "Don't Scroll"}
- )
- @ConfigAccordionId(id = 0)
- public int scrollToBackpack2 = 0;
-
- @Expose
- @ConfigOption(
- name = "Backpack Side",
- desc = "Set which side of the hotbar the backpack slot shows"
- )
- @ConfigEditorDropdown(
- values = {"Left", "Right"}
- )
- @ConfigAccordionId(id = 0)
- public int backpackHotbarSide = 0;
-
- @Expose
- @ConfigOption(
- name = "Backpack Peeking",
- desc = "When the backpack is selected, show it's contents on your screen"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean showInvBackpackPreview = true;
-
- @Expose
- @ConfigOption(
- name = "Backpack Opacity%",
- desc = "Change the opacity of the backpack preview background"
- )
- @ConfigEditorSlider(
- minValue = 0,
- maxValue = 100,
- minStep = 5
- )
- @ConfigAccordionId(id = 0)
- public int backpackOpacity = 50;
-
- @Expose
- @ConfigOption(
- name = "Backpack Scroll Key",
- desc = "Change the key which needs to be pressed in order to allow backpacks to be scrolled between"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_LSHIFT)
- @ConfigAccordionId(id = 0)
- public int backpackScrollKey = Keyboard.KEY_LSHIFT;
-
- @Expose
- @ConfigOption(
- name = "Backpack Hotkey",
- desc = "Hotkey to quickly switch to the backpack slot"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_GRAVE)
- @ConfigAccordionId(id = 0)
- public int backpackHotkey = Keyboard.KEY_GRAVE;
-
- @Expose
- @ConfigOption(
- name = "Arrow Key Backpacks",
- desc = "Use arrow keys [LEFT],[RIGHT] to move between backpacks and [DOWN] to navigate backpack even when the slot is not selected. Keys are customizable below"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean arrowKeyBackpacks = false;
-
- @ConfigOption(
- name = "Arrow Key Backpack Keybinds",
- desc = ""
- )
- @ConfigEditorAccordion(id = 2)
- @ConfigAccordionId(id = 0)
- public boolean backpackArrowAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Backpack Left",
- desc = "Select the backpack to the left"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_LEFT)
- @ConfigAccordionId(id = 2)
- public int arrowLeftKey = Keyboard.KEY_LEFT;
-
- @Expose
- @ConfigOption(
- name = "Backpack Right",
- desc = "Select the backpack to the right"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_RIGHT)
- @ConfigAccordionId(id = 2)
- public int arrowRightKey = Keyboard.KEY_RIGHT;
-
- @Expose
- @ConfigOption(
- name = "Backpack Open",
- desc = "Open the selected backpack"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_DOWN)
- @ConfigAccordionId(id = 2)
- public int arrowDownKey = Keyboard.KEY_DOWN;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorColour;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorFSR;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import org.lwjgl.input.Keyboard;
+
+public class StorageGUI {
+ @ConfigOption(
+ name = "Storage Overlay",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean storageOverlayAccordion = false;
+
+ @Expose
+ public int selectedIndex = 0;
+ @ConfigOption(
+ name = "\u00A7cWarning",
+ desc = "You need Fast Render and Antialiasing off for these settings to work\n" +
+ "You can find these in your video settings"
+ )
+ @ConfigEditorFSR(
+ runnableId = 12,
+ buttonText = ""
+ )
+ @ConfigAccordionId(id = 1)
+ public boolean storageGUIWarning = false;
+ @Expose
+ @ConfigOption(
+ name = "Enable Storage GUI",
+ desc = "Show a custom storage overlay when accessing /storage. " +
+ "Makes switching between pages much easier and also allows for searching through all storages"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean enableStorageGUI3 = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Storage Height",
+ desc = "Change the height of the storage preview section. Increasing this allows more storages to be seen at once"
+ )
+ @ConfigEditorSlider(
+ minValue = 104,
+ maxValue = 312,
+ minStep = 26
+ )
+ @ConfigAccordionId(id = 1)
+ public int storageHeight = 208;
+
+ @Expose
+ @ConfigOption(
+ name = "Storage Style",
+ desc = "Change the visual style of the overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Transparent", "Minecraft", "Grey", "Custom"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int displayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Enderchest Preview",
+ desc = "Preview Enderchest pages when hovering over the selector on the left side"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean enderchestPreview = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Preview",
+ desc = "Preview Backpacks when hovering over the selector on the left side"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean backpackPreview = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Compact Vertically",
+ desc = "Remove the space between backpacks when there is a size discrepancy"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean masonryMode = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Fancy Glass Panes",
+ desc = "Replace the glass pane textures in your storage containers with a fancy connected texture"
+ )
+ @ConfigEditorDropdown(
+ values = {"On", "Locked", "Off"}
+ )
+ @ConfigAccordionId(id = 1)
+ public int fancyPanes = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Search Bar Autofocus",
+ desc = "Automatically focus the search bar when pressing keys"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean searchBarAutofocus = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Enchant Glint",
+ desc = "Toggle enchant glint in storage GUI"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean showEnchantGlint = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Selected Storage Colour",
+ desc = "Change the colour used to draw the selected backpack border"
+ )
+ @ConfigEditorColour
+ @ConfigAccordionId(id = 1)
+ public String selectedStorageColour = "0:255:255:223:0";
+
+ @Expose
+ @ConfigOption(
+ name = "Scrollable Tooltips",
+ desc = "Support for scrolling tooltips for users with small monitors\n" +
+ "This will prevent the menu from scrolling while holding the key, allowing you to scroll tooltips"
+ )
+ @ConfigEditorKeybind(defaultKey = 0)
+ @ConfigAccordionId(id = 1)
+ public int cancelScrollKey = 0;
+
+ @ConfigOption(
+ name = "Inventory Backpacks",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean inventorySlotAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Inventory Backpacks",
+ desc = "Add a \"10th slot\" to your inventory which allows you to quickly access your backpacks"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showInvBackpack = false;
+
+ //public boolean showInvBackpack = false;
+ @Expose
+ @ConfigOption(
+ name = "Scroll to Backpack",
+ desc = "Allow scrolling to the backpack using the mouse wheel.\n" +
+ "\"Scroll (Key)\" = Allow scrolling to 10th slot only while 'Backpack Scroll Key' (default: SHIFT) is pressed"
+ )
+ @ConfigEditorDropdown(
+ values = {"Scroll (Key)", "Scroll (Always)", "Don't Scroll"}
+ )
+ @ConfigAccordionId(id = 0)
+ public int scrollToBackpack2 = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Side",
+ desc = "Set which side of the hotbar the backpack slot shows"
+ )
+ @ConfigEditorDropdown(
+ values = {"Left", "Right"}
+ )
+ @ConfigAccordionId(id = 0)
+ public int backpackHotbarSide = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Peeking",
+ desc = "When the backpack is selected, show it's contents on your screen"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean showInvBackpackPreview = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Opacity%",
+ desc = "Change the opacity of the backpack preview background"
+ )
+ @ConfigEditorSlider(
+ minValue = 0,
+ maxValue = 100,
+ minStep = 5
+ )
+ @ConfigAccordionId(id = 0)
+ public int backpackOpacity = 50;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Scroll Key",
+ desc = "Change the key which needs to be pressed in order to allow backpacks to be scrolled between"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_LSHIFT)
+ @ConfigAccordionId(id = 0)
+ public int backpackScrollKey = Keyboard.KEY_LSHIFT;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Hotkey",
+ desc = "Hotkey to quickly switch to the backpack slot"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_GRAVE)
+ @ConfigAccordionId(id = 0)
+ public int backpackHotkey = Keyboard.KEY_GRAVE;
+
+ @Expose
+ @ConfigOption(
+ name = "Arrow Key Backpacks",
+ desc = "Use arrow keys [LEFT],[RIGHT] to move between backpacks and [DOWN] to navigate backpack even when the slot is not selected. Keys are customizable below"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean arrowKeyBackpacks = false;
+
+ @ConfigOption(
+ name = "Arrow Key Backpack Keybinds",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 2)
+ @ConfigAccordionId(id = 0)
+ public boolean backpackArrowAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Left",
+ desc = "Select the backpack to the left"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_LEFT)
+ @ConfigAccordionId(id = 2)
+ public int arrowLeftKey = Keyboard.KEY_LEFT;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Right",
+ desc = "Select the backpack to the right"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_RIGHT)
+ @ConfigAccordionId(id = 2)
+ public int arrowRightKey = Keyboard.KEY_RIGHT;
+
+ @Expose
+ @ConfigOption(
+ name = "Backpack Open",
+ desc = "Open the selected backpack"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_DOWN)
+ @ConfigAccordionId(id = 2)
+ public int arrowDownKey = Keyboard.KEY_DOWN;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Toolbar.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Toolbar.java
index 39674459..7d2f4fc4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Toolbar.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Toolbar.java
@@ -1,101 +1,126 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-
-public class Toolbar {
- @Expose
- @ConfigOption(
- name = "Edit Toolbar Positions",
- desc = "Edit the position of the QuickCommands / Search Bar"
- )
- @ConfigEditorButton(runnableId = 6, buttonText = "Edit")
- public boolean positionButton = true;
-
- @ConfigOption(
- name = "Search Bar",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean searchBarAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Show Search Bar",
- desc = "Show Itemlist search bar in the NEU toolbar"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean searchBar = true;
-
- @Expose
- @ConfigOption(
- name = "Show a quick settings button",
- desc = "Show quick settings button in the NEU toolbar"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableSettingsButton = true;
-
- @Expose
- @ConfigOption(
- name = "Show a help settings button",
- desc = "Show quick settings button in the NEU toolbar"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean enableHelpButton = true;
-
- @Expose
- @ConfigOption(
- name = "Search Bar Width",
- desc = "Change the width of the search bar"
- )
- @ConfigEditorSlider(
- minValue = 50f,
- maxValue = 300f,
- minStep = 10f
- )
- @ConfigAccordionId(id = 0)
- public int searchBarWidth = 200;
-
- @Expose
- @ConfigOption(
- name = "Search Bar Height",
- desc = "Change the height of the search bar"
- )
- @ConfigEditorSlider(
- minValue = 15f,
- maxValue = 50f,
- minStep = 1f
- )
- @ConfigAccordionId(id = 0)
- public int searchBarHeight = 40;
-
- @Expose
- @ConfigOption(
- name = "Auto turnoff search mode",
- desc = "Turns off the inventory search mode after 2 minutes"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean autoTurnOffSearchMode = true;
-
- @Expose
- @ConfigOption(
- name = "Show Quick Commands",
- desc = "Show QuickCommands\u2122 in the NEU toolbar"
- )
- @ConfigEditorBoolean
- public boolean quickCommands = false;
-
- @Expose
- @ConfigOption(
- name = "Quick Commands Click Type",
- desc = "Change the click type needed to trigger quick commands"
- )
- @ConfigEditorDropdown(
- values = {"Mouse Up", "Mouse Down"}
- )
- public int quickCommandsClickType = 0;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorButton;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDropdown;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class Toolbar {
+ @Expose
+ @ConfigOption(
+ name = "Edit Toolbar Positions",
+ desc = "Change the position of the QuickCommands / Search Bar"
+ )
+ @ConfigEditorButton(runnableId = 6, buttonText = "Edit")
+ public boolean positionButton = true;
+
+ @ConfigOption(
+ name = "Search Bar",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean searchBarAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Search Bar",
+ desc = "Show Itemlist search bar in the NEU toolbar"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean searchBar = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show a quick settings button",
+ desc = "Show quick settings button in the NEU toolbar"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableSettingsButton = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show a help settings button",
+ desc = "Show quick settings button in the NEU toolbar"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean enableHelpButton = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Search Bar Width",
+ desc = "Change the width of the search bar"
+ )
+ @ConfigEditorSlider(
+ minValue = 50f,
+ maxValue = 300f,
+ minStep = 10f
+ )
+ @ConfigAccordionId(id = 0)
+ public int searchBarWidth = 200;
+
+ @Expose
+ @ConfigOption(
+ name = "Search Bar Height",
+ desc = "Change the height of the search bar"
+ )
+ @ConfigEditorSlider(
+ minValue = 15f,
+ maxValue = 50f,
+ minStep = 1f
+ )
+ @ConfigAccordionId(id = 0)
+ public int searchBarHeight = 40;
+
+ @Expose
+ @ConfigOption(
+ name = "Auto turnoff search mode",
+ desc = "Turns off the inventory search mode after 2 minutes"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean autoTurnOffSearchMode = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Quick Commands",
+ desc = "Show QuickCommands\u2122 in the NEU toolbar"
+ )
+ @ConfigEditorBoolean
+ public boolean quickCommands = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Quick Commands Click Type",
+ desc = "Change the click type needed to trigger quick commands"
+ )
+ @ConfigEditorDropdown(
+ values = {"Mouse Up", "Mouse Down"}
+ )
+ public int quickCommandsClickType = 0;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
index 52d2a5d1..1edc0921 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TooltipTweaks.java
@@ -1,142 +1,225 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.*;
-import org.lwjgl.input.Keyboard;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class TooltipTweaks {
- @ConfigOption(
- name = "Tooltip Price Information",
- desc = ""
- )
- @ConfigEditorAccordion(id = 0)
- public boolean priceInfoAccordion = false;
-
- @Expose
- @ConfigOption(
- name = "Price Info (Auc)",
- desc = "\u00a7rSelect what price information you would like to see on auctionable item tooltips\n" +
- "\u00a7eDrag text to rearrange"
- )
- @ConfigEditorDraggableList(
- exampleText = {
- "\u00a7eLowest BIN",
- "\u00a7eAH Price",
- "\u00a7eAH Sales",
- "\u00a7eRaw Craft Cost",
- "\u00a7eAVG Lowest BIN",
- "\u00a7eDungeon Costs"
- }
- )
- @ConfigAccordionId(id = 0)
- public List<Integer> priceInfoAuc = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 5));
-
- @Expose
- @ConfigOption(
- name = "Price Info (Baz)",
- desc = "\u00a7rSelect what price information you would like to see on bazaar item tooltips\n" +
- "\u00a7eDrag text to rearrange"
- )
- @ConfigEditorDraggableList(
- exampleText = {"\u00a7eBuy", "\u00a7eSell", "\u00a7eBuy (Insta)", "\u00a7eSell (Insta)", "\u00a7eRaw Craft Cost"}
- )
- @ConfigAccordionId(id = 0)
- public List<Integer> priceInfoBaz = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4));
-
- @Expose
- @ConfigOption(
- name = "Use Short Number Format",
- desc = "Use Short Numbers (5.1m) instead of 5,130,302"
- )
- @ConfigEditorBoolean
- @ConfigAccordionId(id = 0)
- public boolean shortNumberFormatPrices = false;
-
- @Expose
- @ConfigOption(
- name = "Price Info (Inv)",
- desc = "Show price information for items in your inventory"
- )
- @ConfigEditorBoolean
- public boolean showPriceInfoInvItem = true;
-
- @Expose
- @ConfigOption(
- name = "Price Info (AH)",
- desc = "Show price information for auctioned items"
- )
- @ConfigEditorBoolean
- public boolean showPriceInfoAucItem = true;
-
- @Expose
- @ConfigOption(
- name = "Price info keybind",
- desc = "Only show price info if holding a key."
- )
- @ConfigEditorBoolean
- public boolean disablePriceKey = false;
-
- @Expose
- @ConfigOption(
- name = "Show Price info Keybind",
- desc = "Hold this key to show a price info tooltip"
- )
- @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
- public int disablePriceKeyKeybind = Keyboard.KEY_NONE;
-
- @Expose
- @ConfigOption(
- name = "Show reforge stats",
- desc = "Show statistics a reforge stone will apply."
- )
- @ConfigEditorBoolean
- public boolean showReforgeStats = true;
-
- @Expose
- @ConfigOption(
- name = "Hide default reforge stats",
- desc = "Hides the reforge stats only for Legendary items that Hypixel adds to the Reforge stones"
- )
- @ConfigEditorBoolean
- public boolean hideDefaultReforgeStats = true;
-
- @Expose
- @ConfigOption(
- name = "Missing Enchant List",
- desc = "Show which enchants are missing on an item when pressing LSHIFT"
- )
- @ConfigEditorBoolean
- public boolean missingEnchantList = true;
-
- @Expose
- @ConfigOption(
- name = "Expand Pet Exp Requirement",
- desc = "Show which the full amount of pet xp required"
- )
- @ConfigEditorBoolean
- public boolean petExtendExp = false;
-
- @Expose
- @ConfigOption(
- name = "Tooltip Border Colours",
- desc = "Make the borders of tooltips match the rarity of the item (NEU Tooltips Only)"
- )
- @ConfigEditorBoolean
- public boolean tooltipBorderColours = true;
-
- @Expose
- @ConfigOption(
- name = "Tooltip Border Opacity",
- desc = "Change the opacity of the rarity highlight (NEU Tooltips Only)"
- )
- @ConfigEditorSlider(
- minValue = 0f,
- maxValue = 255f,
- minStep = 1f
- )
- public int tooltipBorderOpacity = 200;
-} \ No newline at end of file
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigAccordionId;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorAccordion;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorDraggableList;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorKeybind;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorSlider;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+import org.lwjgl.input.Keyboard;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class TooltipTweaks {
+ @ConfigOption(
+ name = "Tooltip Price Information",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 0)
+ public boolean priceInfoAccordion = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Price Info (Auc)",
+ desc = "\u00a7rSelect what price information you would like to see on auctionable item tooltips\n" +
+ "\u00a7eDrag text to rearrange"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {
+ "\u00a7eLowest BIN",
+ "\u00a7eAH Price",
+ "\u00a7eAH Sales",
+ "\u00a7eRaw Craft Cost",
+ "\u00a7eAVG Lowest BIN",
+ "\u00a7eDungeon Costs"
+ }
+ )
+ @ConfigAccordionId(id = 0)
+ public List<Integer> priceInfoAuc = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 5));
+
+ @Expose
+ @ConfigOption(
+ name = "Price Info (Baz)",
+ desc = "\u00a7rSelect what price information you would like to see on bazaar item tooltips\n" +
+ "\u00a7eDrag text to rearrange"
+ )
+ @ConfigEditorDraggableList(
+ exampleText = {"\u00a7eBuy", "\u00a7eSell", "\u00a7eBuy (Insta)", "\u00a7eSell (Insta)", "\u00a7eRaw Craft Cost"}
+ )
+ @ConfigAccordionId(id = 0)
+ public List<Integer> priceInfoBaz = new ArrayList<>(Arrays.asList(0, 1, 2, 3, 4));
+
+ @Expose
+ @ConfigOption(
+ name = "Use Short Number Format",
+ desc = "Use Short Numbers (5.1m) instead of 5,130,302"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 0)
+ public boolean shortNumberFormatPrices = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Price Info (Inv)",
+ desc = "Show price information for items in your inventory"
+ )
+ @ConfigEditorBoolean
+ public boolean showPriceInfoInvItem = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Price Info (AH)",
+ desc = "Show price information for auctioned items"
+ )
+ @ConfigEditorBoolean
+ public boolean showPriceInfoAucItem = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Price info keybind",
+ desc = "Only show price info if holding a key."
+ )
+ @ConfigEditorBoolean
+ public boolean disablePriceKey = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show Price info Keybind",
+ desc = "Hold this key to show a price info tooltip"
+ )
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
+ public int disablePriceKeyKeybind = Keyboard.KEY_NONE;
+
+ @Expose
+ @ConfigOption(
+ name = "Always show required dungeon items",
+ desc = "Always show the required items to upgrade to the next star if more than just Essence is needed"
+ )
+ @ConfigEditorBoolean
+ public boolean alwaysShowRequiredItems = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Show reforge stats",
+ desc = "Show statistics a reforge stone will apply."
+ )
+ @ConfigEditorBoolean
+ public boolean showReforgeStats = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide default reforge stats",
+ desc = "Hides the reforge stats only for Legendary items that Hypixel adds to the Reforge stones"
+ )
+ @ConfigEditorBoolean
+ public boolean hideDefaultReforgeStats = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Missing Enchant List",
+ desc = "Show which enchants are missing on an item when pressing LSHIFT"
+ )
+ @ConfigEditorBoolean
+ public boolean missingEnchantList = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Expand Pet Exp Requirement",
+ desc = "Show which the full amount of pet xp required"
+ )
+ @ConfigEditorBoolean
+ public boolean petExtendExp = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Tooltip Border Colours",
+ desc = "Make the borders of tooltips match the rarity of the item (NEU Tooltips Only)"
+ )
+ @ConfigEditorBoolean
+ public boolean tooltipBorderColours = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Tooltip Border Opacity",
+ desc = "Change the opacity of the rarity highlight (NEU Tooltips Only)"
+ )
+ @ConfigEditorSlider(
+ minValue = 0f,
+ maxValue = 255f,
+ minStep = 1f
+ )
+ public int tooltipBorderOpacity = 200;
+
+ @Expose
+ @ConfigOption(
+ name = "Power Stone Stats",
+ desc = "Show your real magical power and real stat increase on power stones"
+ )
+ @ConfigEditorBoolean
+ public boolean powerStoneStats = true;
+
+ @ConfigOption(
+ name = "RNG Meter",
+ desc = ""
+ )
+ @ConfigEditorAccordion(id = 1)
+ public boolean rngMeter = false;
+
+ @Expose
+ @ConfigOption(
+ name = "Fraction Display",
+ desc = "Show the fraction instead of the percentage in the slayer and dungeon rng meter inventory"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean rngMeterFractionDisplay = true;
+
+ @Expose
+ @ConfigOption(
+ name = " Profit Per Score/XP",
+ desc = "Show the amount of coins per Score/XP in the rng meter inventory"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean rngMeterProfitPerUnit = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Dungeon/Slayer Needed Counter",
+ desc = "Show the amount of dungeon runs or slayer bosses needed for the rng meter to fill up"
+ )
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 1)
+ public boolean rngMeterRunsNeeded = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Essence Price In Shop",
+ desc = "Show the essence price in the essence shop in the dungeon hub"
+ )
+ @ConfigEditorBoolean
+ public boolean essencePriceInEssenceShop = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TradeMenu.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TradeMenu.java
index cb0c5dd1..d2b4e0bb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TradeMenu.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/TradeMenu.java
@@ -1,26 +1,45 @@
-package io.github.moulberry.notenoughupdates.options.seperateSections;
-
-import com.google.gson.annotations.Expose;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
-import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
-
-public class TradeMenu {
- @Expose
- @ConfigOption(
- name = "Enable Custom Trade Menu",
- desc = "When trading with other players in skyblock, display a special GUI designed to prevent scamming"
- )
- @ConfigEditorBoolean
- public boolean enableCustomTrade = true;
-
- @Expose
- @ConfigOption(
- name = "Price Information",
- desc = "Show the price of items in the trade window on both sides"
- )
- @ConfigEditorBoolean
- public boolean customTradePrices = true;
-
- @Expose
- public boolean customTradePriceStyle = true;
-}
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.options.seperateSections;
+
+import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigEditorBoolean;
+import io.github.moulberry.notenoughupdates.core.config.annotations.ConfigOption;
+
+public class TradeMenu {
+ @Expose
+ @ConfigOption(
+ name = "Enable Custom Trade Menu",
+ desc = "When trading with other players in skyblock, display a special GUI designed to prevent scamming"
+ )
+ @ConfigEditorBoolean
+ public boolean enableCustomTrade = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Price Information",
+ desc = "Show the price of items in the trade window on both sides"
+ )
+ @ConfigEditorBoolean
+ public boolean customTradePrices = true;
+
+ @Expose
+ public boolean customTradePriceStyle = true;
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java
index 7281eecf..fcea79dd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/AuctionSearchOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import com.google.common.base.Splitter;
@@ -5,9 +24,9 @@ import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign;
import io.github.moulberry.notenoughupdates.options.NEUConfigEditor;
import io.github.moulberry.notenoughupdates.util.Constants;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
@@ -24,7 +43,11 @@ import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
@@ -35,6 +58,8 @@ public class AuctionSearchOverlay {
private static final ResourceLocation SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED = new ResourceLocation(
"notenoughupdates:auc_search/ah_search_overlay_tab_completed.png");
private static final ResourceLocation STAR = new ResourceLocation("notenoughupdates:auc_search/star.png");
+ private static final ResourceLocation MASTER_STAR =
+ new ResourceLocation("notenoughupdates:auc_search/master_star.png");
private static final ResourceLocation STAR_BOARD = new ResourceLocation("notenoughupdates:auc_search/star_board.png");
private static final GuiElementTextField textField = new GuiElementTextField("", 200, 20, 0);
@@ -47,6 +72,7 @@ public class AuctionSearchOverlay {
private static int selectedStars = 0;
private static boolean atLeast = true;
+ private static boolean onlyLevel100 = false;
private static final int AUTOCOMPLETE_HEIGHT = 118;
@@ -80,12 +106,10 @@ public class AuctionSearchOverlay {
return false;
}
- String lastContainer = SBInfo.getInstance().lastOpenContainerName;
-
- if (lastContainer == null) return false;
+ String lastContainer = Utils.getLastOpenChestName();
if (!lastContainer.equals("Auctions Browser") && !lastContainer.startsWith("Auctions: ")) return false;
- TileEntitySign tes = ((GuiEditSign) Minecraft.getMinecraft().currentScreen).tileSign;
+ TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign();
if (tes == null) return false;
if (tes.getPos().getY() != 0) return false;
@@ -114,22 +138,38 @@ public class AuctionSearchOverlay {
Utils.drawTexturedRect(width / 2 - 100, topY - 1, 203, h, 0, 203 / 512f, 0, h / 256f, GL11.GL_NEAREST);
Minecraft.getMinecraft().getTextureManager().bindTexture(STAR_BOARD);
- Utils.drawTexturedRect(width / 2 + 105, topY + 27, 55, 13, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(width / 2 + 105, topY + 27, 105, 13, GL11.GL_NEAREST);
Minecraft.getMinecraft().getTextureManager().bindTexture(STAR);
GlStateManager.color(1, 1, 1, 1);
- int stars = atLeast && selectedStars > 0 ? 5 : selectedStars;
+ int stars = atLeast && selectedStars > 0 ? 10 : selectedStars;
for (int i = 0; i < stars; i++) {
+ if (i >= 5) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(MASTER_STAR);
+ GlStateManager.color(1, 1, 1, 1);
+ }
if (i >= selectedStars) {
GlStateManager.color(1, 1, 1, 0.3f);
}
Utils.drawTexturedRect(width / 2 + 108 + 10 * i, topY + 29, 9, 10, GL11.GL_NEAREST);
}
- Gui.drawRect(width / 2 + 106, topY + 42, width / 2 + 115, topY + 51, 0xffffffff);
- Gui.drawRect(width / 2 + 107, topY + 43, width / 2 + 114, topY + 50, 0xff000000);
- if (atLeast) Gui.drawRect(width / 2 + 108, topY + 44, width / 2 + 113, topY + 49, 0xffffffff);
- Minecraft.getMinecraft().fontRendererObj.drawString("At Least?", width / 2 + 117, topY + 43, 0xffffff);
+ if (selectedStars < 6) {
+ Gui.drawRect(width / 2 + 106, topY + 42, width / 2 + 115, topY + 51, 0xffffffff);
+ Gui.drawRect(width / 2 + 107, topY + 43, width / 2 + 114, topY + 50, 0xff000000);
+ Minecraft.getMinecraft().fontRendererObj.drawString("At Least?", width / 2 + 117, topY + 43, 0xffffff);
+
+ if (atLeast) {
+ Gui.drawRect(width / 2 + 108, topY + 44, width / 2 + 113, topY + 49, 0xffffffff);
+ }
+ }
+
+ Gui.drawRect(width / 2 + 106, topY + 53, width / 2 + 115, topY + 62, 0xffffffff);
+ Gui.drawRect(width / 2 + 107, topY + 54, width / 2 + 114, topY + 61, 0xff000000);
+ if (onlyLevel100) {
+ Gui.drawRect(width / 2 + 108, topY + 55, width / 2 + 113, topY + 60, 0xffffffff);
+ }
+ Minecraft.getMinecraft().fontRendererObj.drawString("Level 100 pets only?", width / 2 + 117, topY + 54, 0xffffff);
Minecraft.getMinecraft().fontRendererObj.drawString("Enter Query:", width / 2 - 100, topY - 10, 0xdddddd, true);
@@ -258,17 +298,13 @@ public class AuctionSearchOverlay {
}
String searchString = autocompletedItems.toArray()[i].toString();
JsonObject repoObject = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(searchString);
- String displayname = repoObject.get("displayname").getAsString();
- if (displayname.contains("Enchanted Book")) {
- String lore = repoObject.get("lore").getAsJsonArray().get(0).getAsString();
- String name = lore.substring(0, lore.lastIndexOf(" "));
- return Utils.cleanColour(name);
- } else {
- return Utils.cleanColour(displayname);
+ if (repoObject != null) {
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(repoObject);
+ return Utils.cleanColour(stack.getDisplayName().replaceAll("\\[.+]", ""));
}
- } else {
- return null;
+
}
+ return null;
}
public static void close() {
@@ -284,12 +320,18 @@ public class AuctionSearchOverlay {
}
}
- TileEntitySign tes = ((GuiEditSign) Minecraft.getMinecraft().currentScreen).tileSign;
+ TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign();
- String search = searchString.trim();
- if (searchStringExtra != null && !searchStringExtra.isEmpty()) {
- search += " " + searchStringExtra.trim();
+ StringBuilder stringBuilder = new StringBuilder(searchString.trim());
+ if (!searchStringExtra.isEmpty()) {
+ stringBuilder.append(searchStringExtra);
+ }
+ if (onlyLevel100) {
+ stringBuilder.insert(0, "[Lvl 100] ");
}
+
+ String search = stringBuilder.toString();
+
if (search.length() <= 15) {
tes.signText[0] = new ChatComponentText(search.substring(0, Math.min(search.length(), 15)));
} else {
@@ -507,10 +549,10 @@ public class AuctionSearchOverlay {
topY = height / 2 - h / 2 + 5;
}
- if (Mouse.getEventButtonState() && mouseX > width / 2 + 105 && mouseX < width / 2 + 105 + 55 &&
+ if (Mouse.getEventButtonState() && mouseX > width / 2 + 105 && mouseX < width / 2 + 105 + 105 &&
mouseY > topY + 27 && mouseY < topY + 40) {
- int starClicked = 5;
- for (int i = 1; i <= 5; i++) {
+ int starClicked = 10;
+ for (int i = 1; i <= 10; i++) {
if (mouseX < width / 2 + 108 + 10 * i) {
starClicked = i;
break;
@@ -530,6 +572,12 @@ public class AuctionSearchOverlay {
return;
}
+ if (Mouse.getEventButtonState() && mouseX >= width / 2 + 106 && mouseX <= width / 2 + 116 &&
+ mouseY >= topY + 53 && mouseY <= topY + 62) {
+ onlyLevel100 = !onlyLevel100;
+ return;
+ }
+
if (!Mouse.getEventButtonState() && Mouse.getEventButton() == -1 && searchFieldClicked) {
textField.mouseClickMove(mouseX - 2, topY + 10, 0, 0);
}
@@ -559,7 +607,7 @@ public class AuctionSearchOverlay {
close();
Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(Minecraft.getMinecraft().thePlayer.openContainer.windowId));
NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor(
- NotEnoughUpdates.INSTANCE.config, "AH Search GUI"));
+ NotEnoughUpdates.INSTANCE.config, "AH Tweaks"));
}
}
} else if (Mouse.getEventButton() == 0) {
@@ -581,12 +629,30 @@ public class AuctionSearchOverlay {
}
JsonObject essenceCosts = Constants.ESSENCECOSTS;
- searchStringExtra = "";
+ searchStringExtra = " ";
if (essenceCosts != null && essenceCosts.has(str) && selectedStars > 0) {
for (int i = 0; i < selectedStars; i++) {
+ if (i > 4) break;
searchStringExtra += "\u272A";
}
- if (selectedStars < 5 && !atLeast) {
+ switch (selectedStars) {
+ case 6:
+ searchStringExtra += "\u278A";
+ break;
+ case 7:
+ searchStringExtra += "\u278B";
+ break;
+ case 8:
+ searchStringExtra += "\u278C";
+ break;
+ case 9:
+ searchStringExtra += "\u278D";
+ break;
+ case 10:
+ searchStringExtra += "\u278E";
+ break;
+ }
+ if (selectedStars < 6 && !atLeast) {
searchStringExtra += " ";
searchStringExtra += stack.getItem().getItemStackDisplayName(stack).substring(0, 1);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java
new file mode 100644
index 00000000..66dacda3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BazaarSearchOverlay.java
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.overlays;
+
+import com.google.common.base.Splitter;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign;
+import io.github.moulberry.notenoughupdates.options.NEUConfigEditor;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.item.ItemStack;
+import net.minecraft.network.play.client.C0DPacketCloseWindow;
+import net.minecraft.tileentity.TileEntitySign;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class BazaarSearchOverlay {
+ private static final ResourceLocation SEARCH_OVERLAY_TEXTURE = new ResourceLocation(
+ "notenoughupdates:auc_search/ah_search_overlay.png");
+ private static final ResourceLocation SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED = new ResourceLocation(
+ "notenoughupdates:auc_search/ah_search_overlay_tab_completed.png");
+
+ private static final GuiElementTextField textField = new GuiElementTextField("", 200, 20, 0);
+ private static boolean searchFieldClicked = false;
+ private static String searchString = "";
+ private static String searchStringExtra = "";
+ private static final Splitter SPACE_SPLITTER = Splitter.on(" ").omitEmptyStrings().trimResults();
+ private static boolean tabCompleted = false;
+ private static int tabCompletionIndex = -1;
+
+ private static final int AUTOCOMPLETE_HEIGHT = 118;
+
+ private static final Set<String> autocompletedItems = new LinkedHashSet<>();
+
+ private static final Comparator<String> salesComparator = (o1, o2) -> {
+ JsonObject bazaarInfo1 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(o1);
+ JsonObject bazaarInfo2 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(o2);
+
+ boolean auc1Invalid = bazaarInfo1 == null || !bazaarInfo1.has("curr_sell");
+ boolean auc2Invalid = bazaarInfo2 == null || !bazaarInfo2.has("curr_sell");
+
+ if (auc1Invalid && auc2Invalid) return o1.compareTo(o2);
+ if (auc1Invalid) return -1;
+ if (auc2Invalid) return 1;
+
+ int sales1 = bazaarInfo1.get("curr_sell").getAsInt();
+ int sales2 = bazaarInfo2.get("curr_sell").getAsInt();
+
+ if (sales1 == sales2) return o1.compareTo(o2);
+ if (sales1 > sales2) return -1;
+ return 1;
+ };
+
+ public static boolean shouldReplace() {
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return false;
+ if (!NotEnoughUpdates.INSTANCE.config.bazaarTweaks.enableSearchOverlay) return false;
+
+ if (!(Minecraft.getMinecraft().currentScreen instanceof GuiEditSign)) {
+ if (!NotEnoughUpdates.INSTANCE.config.bazaarTweaks.keepPreviousSearch) searchString = "";
+ return false;
+ }
+
+ String lastContainer = Utils.getLastOpenChestName();
+ if (!lastContainer.startsWith("Bazaar ➜ ")) return false;
+
+ TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign();
+
+ if (tes == null) return false;
+ if (tes.getPos().getY() != 0) return false;
+ if (!tes.signText[2].getUnformattedText().equals("^^^^^^^^^^^^^^^")) return false;
+ return tes.signText[3].getUnformattedText().equals("Enter query");
+ }
+
+ public static void render() {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
+
+ int h = NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches ? 219 : 145;
+
+ int topY = height / 4;
+ if (scaledResolution.getScaleFactor() >= 4) {
+ topY = height / 2 - h / 2 + 5;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(width / 2 - 100, topY - 1, 203, h, 0, 203 / 512f, 0, h / 256f, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("Enter Query:", width / 2 - 100, topY - 10, 0xdddddd, true);
+
+ textField.setFocus(true);
+ textField.setText(searchString);
+ textField.setSize(149, 20);
+ textField.setCustomBorderColour(0xffffff);
+ textField.render(width / 2 - 100 + 1, topY + 1);
+
+ if (textField.getText().trim().isEmpty()) autocompletedItems.clear();
+
+ List<String> tooltipToDisplay = null;
+
+ int num = 0;
+ synchronized (autocompletedItems) {
+ String[] autoCompletedItemsArray = autocompletedItems.toArray(new String[0]);
+ for (int i = 0; i < autoCompletedItemsArray.length; i++) {
+ String str = autoCompletedItemsArray[i];
+ JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str);
+ if (obj != null) {
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj);
+ if (i == tabCompletionIndex) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE_TAB_COMPLETED);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(
+ width / 2 - 96 + 1,
+ topY + 30 + num * 22 + 1,
+ 193,
+ 21,
+ 0 / 512f,
+ 193 / 512f,
+ 0,
+ 21 / 256f,
+ GL11.GL_NEAREST
+ );
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SEARCH_OVERLAY_TEXTURE);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(
+ width / 2 - 96 + 1,
+ topY + 30 + num * 22 + 1,
+ 193,
+ 21,
+ 214 / 512f,
+ 407 / 512f,
+ 0,
+ 21 / 256f,
+ GL11.GL_NEAREST
+ );
+
+ }
+ String itemName = Utils.trimIgnoreColour(stack.getDisplayName().replaceAll("\\[.+]", ""));
+ if (itemName.contains("Enchanted Book") && str.contains(";")) {
+ String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
+ itemName = lore[0].trim();
+ }
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(
+ itemName,
+ 165
+ ),
+ width / 2 - 74, topY + 35 + num * 22 + 1, 0xdddddd, true
+ );
+
+ GlStateManager.enableDepth();
+ Utils.drawItemStack(stack, width / 2 - 94 + 2, topY + 32 + num * 22 + 1);
+
+ if (mouseX > width / 2 - 96 && mouseX < width / 2 + 96 && mouseY > topY + 30 + num * 22 &&
+ mouseY < topY + 30 + num * 22 + 20) {
+ tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+
+ if (++num >= 5) break;
+ }
+ }
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches) {
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ "Past Searches:",
+ width / 2 - 100,
+ topY + 25 + AUTOCOMPLETE_HEIGHT + 5,
+ 0xdddddd,
+ true
+ );
+
+ for (int i = 0; i < 5; i++) {
+ if (i >= NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.size()) break;
+
+ String s = NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.get(i);
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ s,
+ width / 2 - 95 + 1,
+ topY + 45 + AUTOCOMPLETE_HEIGHT + i * 10 + 2,
+ 0xdddddd,
+ true
+ );
+ }
+
+ if (tooltipToDisplay != null) {
+ Utils.drawHoveringText(
+ tooltipToDisplay,
+ mouseX,
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+
+ }
+
+ private static final ExecutorService searchES = Executors.newSingleThreadExecutor();
+ private static final AtomicInteger searchId = new AtomicInteger(0);
+
+ private static String getItemIdAtIndex(int i) {
+ if (!autocompletedItems.isEmpty()) {
+ if ((i > autocompletedItems.size() - 1) || i < 0 || i > 4) {
+ return "";
+ }
+ String searchString = autocompletedItems.toArray()[i].toString();
+ JsonObject repoObject = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(searchString);
+ if (repoObject != null) {
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(repoObject);
+ return Utils.cleanColour(stack.getDisplayName().replaceAll("\\[.+]", ""));
+ }
+
+ }
+ return null;
+ }
+
+ public static void close() {
+ if (tabCompleted) {
+ tabCompletionIndex = -1;
+ tabCompleted = false;
+ }
+ if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.keepPreviousSearch) {
+ search();
+ } else {
+ synchronized (autocompletedItems) {
+ autocompletedItems.clear();
+ }
+ }
+
+ TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign();
+
+ StringBuilder stringBuilder = new StringBuilder(searchString.trim());
+ if (!searchStringExtra.isEmpty()) {
+ stringBuilder.append(searchStringExtra);
+ }
+
+ String search = stringBuilder.toString();
+
+ if (search.length() <= 15) {
+ tes.signText[0] = new ChatComponentText(search.substring(0, Math.min(search.length(), 15)));
+ } else {
+ List<String> words = SPACE_SPLITTER.splitToList(search);
+
+ StringBuilder line0 = new StringBuilder();
+ StringBuilder line1 = new StringBuilder();
+
+ int currentLine = 0;
+ for (String word : words) {
+ if (currentLine == 0) {
+ if (line0.length() + word.length() > 15) {
+ currentLine++;
+ } else {
+ line0.append(word);
+ if (line0.length() >= 15) {
+ currentLine++;
+ continue;
+ } else {
+ line0.append(" ");
+ }
+ }
+ }
+ if (currentLine == 1) {
+ if (line1.length() + word.length() > 15) {
+ line1.append(word, 0, 15 - line1.length());
+ break;
+ } else {
+ line1.append(word);
+ if (line1.length() >= 15) {
+ break;
+ } else {
+ line1.append(" ");
+ }
+ }
+ }
+ if (line1.length() >= 15) break;
+ }
+
+ tes.signText[0] = new ChatComponentText(line0.toString().trim());
+ tes.signText[1] = new ChatComponentText(line1.toString().trim());
+ }
+
+ if (!searchString.trim().isEmpty()) {
+ List<String> previousBazaarSearches = NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches;
+ previousBazaarSearches.remove(searchString);
+ previousBazaarSearches.remove(searchString);
+ previousBazaarSearches.add(0, searchString);
+ while (previousBazaarSearches.size() > 5) {
+ previousBazaarSearches.remove(previousBazaarSearches.size() - 1);
+ }
+ }
+
+ Minecraft.getMinecraft().displayGuiScreen(null);
+
+ if (Minecraft.getMinecraft().currentScreen == null) {
+ Minecraft.getMinecraft().setIngameFocus();
+ }
+ }
+
+ private static boolean updateTabCompletedSearch(int key) {
+ String id;
+ if (key == Keyboard.KEY_DOWN || key == Keyboard.KEY_TAB) {
+ id = getItemIdAtIndex(tabCompletionIndex + 1);
+ if (id == null) {
+ textField.setFocus(true);
+ textField.setText(searchString);
+ tabCompleted = false;
+ tabCompletionIndex = -1;
+ return true;
+ } else if (id.equals("")) {
+ tabCompletionIndex = 0;
+ return true;
+ } else {
+ searchString = id;
+ tabCompletionIndex += 1;
+ return true;
+ }
+ } else if (key == Keyboard.KEY_UP) {
+ id = getItemIdAtIndex(tabCompletionIndex - 1);
+ if (id == null) {
+ textField.setFocus(true);
+ textField.setText(searchString);
+ tabCompleted = false;
+ tabCompletionIndex = -1;
+ return true;
+ } else if (id.equals("")) {
+ if (autocompletedItems.size() > 4) tabCompletionIndex = 4;
+ else tabCompletionIndex = autocompletedItems.size() - 1;
+ tabCompletionIndex = autocompletedItems.size() - 1;
+ return true;
+ } else {
+ searchString = id;
+ tabCompletionIndex -= 1;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static void search() {
+ final int thisSearchId = searchId.incrementAndGet();
+
+ searchES.submit(() -> {
+ if (thisSearchId != searchId.get()) return;
+
+ List<String> title = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("title:" + searchString.trim()));
+
+ if (thisSearchId != searchId.get()) return;
+
+ if (!searchString.trim().contains(" ")) {
+ StringBuilder sb = new StringBuilder();
+ for (char c : searchString.toCharArray()) {
+ sb.append(c).append(" ");
+ }
+ title.addAll(NotEnoughUpdates.INSTANCE.manager.search("title:" + sb.toString().trim()));
+ }
+
+ if (thisSearchId != searchId.get()) return;
+
+ List<String> desc = new ArrayList<>(NotEnoughUpdates.INSTANCE.manager.search("desc:" + searchString.trim()));
+ desc.removeAll(title);
+
+ if (thisSearchId != searchId.get()) return;
+
+ Set<String> bazaarItems = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarKeySet();
+ // Amalgamated Crimsonite (Old) // TODO remove from repo
+ bazaarItems.remove("AMALGAMATED_CRIMSONITE");
+
+ title.retainAll(bazaarItems);
+ desc.retainAll(bazaarItems);
+
+ title.sort(salesComparator);
+ desc.sort(salesComparator);
+
+ if (thisSearchId != searchId.get()) return;
+
+ synchronized (autocompletedItems) {
+ autocompletedItems.clear();
+ autocompletedItems.addAll(title);
+ autocompletedItems.addAll(desc);
+ }
+ });
+ }
+
+ public static void keyEvent() {
+ boolean ignoreKey = false;
+
+ if (Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
+ searchStringExtra = "";
+ close();
+ if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.escFullClose) {
+ Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(Minecraft.getMinecraft().thePlayer.openContainer.windowId));
+ }
+ return;
+ } else if (Keyboard.getEventKey() == Keyboard.KEY_RETURN) {
+ searchStringExtra = "";
+ close();
+ return;
+ } else if (Keyboard.getEventKey() == Keyboard.KEY_TAB) {
+ //autocomplete to first item in the list
+ if (!tabCompleted) {
+ tabCompleted = true;
+ ignoreKey = true;
+ String id = getItemIdAtIndex(0);
+ if (id == null) {
+ tabCompleted = false;
+ textField.setFocus(true);
+ textField.setText(searchString);
+ } else {
+ tabCompletionIndex = 0;
+ searchString = id;
+ }
+ }
+ }
+
+ if (Keyboard.getEventKeyState()) {
+ if (tabCompleted) {
+ if (!ignoreKey) {
+ boolean success = updateTabCompletedSearch(Keyboard.getEventKey());
+ if (success) return;
+ textField.setFocus(true);
+ textField.setText(searchString);
+ tabCompleted = false;
+ tabCompletionIndex = -1;
+ } else return;
+
+ }
+ textField.setFocus(true);
+ textField.setText(searchString);
+ textField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ searchString = textField.getText();
+
+ search();
+ }
+ }
+
+ public static void mouseEvent() {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ int h = NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches ? 219 : 145;
+
+ int topY = height / 4;
+ if (scaledResolution.getScaleFactor() >= 4) {
+ topY = height / 2 - h / 2 + 5;
+ }
+
+ if (!Mouse.getEventButtonState() && Mouse.getEventButton() == -1 && searchFieldClicked) {
+ textField.mouseClickMove(mouseX - 2, topY + 10, 0, 0);
+ }
+
+ if (Mouse.getEventButton() != -1) {
+ searchFieldClicked = false;
+ }
+
+ if (Mouse.getEventButtonState()) {
+ if (mouseY > topY && mouseY < topY + 20) {
+ if (mouseX > width / 2 - 100) {
+ if (mouseX < width / 2 + 49) {
+ searchFieldClicked = true;
+ textField.mouseClicked(mouseX - 2, mouseY, Mouse.getEventButton());
+
+ if (Mouse.getEventButton() == 1) {
+ searchString = "";
+ synchronized (autocompletedItems) {
+ autocompletedItems.clear();
+ }
+ }
+ } else if (mouseX < width / 2 + 75) {
+ searchStringExtra = "";
+ close();
+ } else if (mouseX < width / 2 + 100) {
+ searchStringExtra = "";
+ close();
+ Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(Minecraft.getMinecraft().thePlayer.openContainer.windowId));
+ NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(new NEUConfigEditor(
+ NotEnoughUpdates.INSTANCE.config, "Bazaar Tweaks"));
+ }
+ }
+ } else if (Mouse.getEventButton() == 0) {
+ int num = 0;
+ synchronized (autocompletedItems) {
+ for (String str : autocompletedItems) {
+ JsonObject obj = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(str);
+ if (obj != null) {
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(obj);
+ if (mouseX >= width / 2 - 96 && mouseX <= width / 2 + 96 && mouseY >= topY + 30 + num * 22 &&
+ mouseY <= topY + 30 + num * 22 + 20) {
+ searchString = Utils.cleanColour(stack.getDisplayName().replaceAll("\\[.+]", "")).trim();
+ if (searchString.contains("Enchanted Book") && str.contains(";")) {
+ String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
+ if (lore != null) {
+ searchString = Utils.cleanColour(lore[0]);
+ }
+ }
+
+ searchStringExtra = " ";
+
+ close();
+ return;
+ }
+
+ if (++num >= 5) break;
+ }
+ }
+ }
+
+ if (NotEnoughUpdates.INSTANCE.config.bazaarTweaks.showPastSearches) {
+ for (int i = 0; i < 5; i++) {
+ if (i >= NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.size()) break;
+
+ String s = NotEnoughUpdates.INSTANCE.config.hidden.previousBazaarSearches.get(i);
+ if (mouseX >= width / 2 - 95 && mouseX <= width / 2 + 95 &&
+ mouseY >= topY + 45 + AUTOCOMPLETE_HEIGHT + i * 10 &&
+ mouseY <= topY + 45 + AUTOCOMPLETE_HEIGHT + i * 10 + 10) {
+ searchString = s;
+ searchStringExtra = "";
+ close();
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BonemerangOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BonemerangOverlay.java
index aa8a15ce..e8447699 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/BonemerangOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/BonemerangOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -14,7 +33,11 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.Vec3;
import org.lwjgl.util.vector.Vector3f;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.function.Supplier;
public class BonemerangOverlay extends TextOverlay {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CombatSkillOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CombatSkillOverlay.java
index 6d46dfd6..d73b5eb2 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CombatSkillOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CombatSkillOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -22,6 +41,10 @@ public class CombatSkillOverlay
private long lastUpdate = -1;
private int killLast = -1;
private int kill = -1;
+ private int championTier = -1;
+ private String championTierAmount = "1";
+ private int championXp = -1;
+ private int championXpLast = -1;
private final LinkedList<Integer> killQueue = new LinkedList<>();
private XPInformation.SkillInfo skillInfo = null;
@@ -59,14 +82,17 @@ public class CombatSkillOverlay
public void update() {
if (!NotEnoughUpdates.INSTANCE.config.skillOverlays.combatSkillOverlay) {
kill = -1;
+ championXp = -1;
overlayStrings = null;
return;
}
lastUpdate = System.currentTimeMillis();
killLast = kill;
+ championXpLast = championXp;
xpGainHourLast = xpGainHour;
kill = -1;
+ championXp = -1;
if (Minecraft.getMinecraft().thePlayer == null) return;
@@ -81,9 +107,67 @@ public class CombatSkillOverlay
kill = ea.getInteger("stats_book");
killQueue.add(0, kill);
}
+ if (ea.hasKey("champion_combat_xp", 99)) {
+ championXp = (int) ea.getDouble("champion_combat_xp");
+ }
}
}
+ if (championXp < 50000) {
+ championTier = 1;
+ } else if (championXp < 100000) {
+ championTier = 2;
+ } else if (championXp < 250000) {
+ championTier = 3;
+ } else if (championXp < 500000) {
+ championTier = 4;
+ } else if (championXp < 1000000) {
+ championTier = 5;
+ } else if (championXp < 1500000) {
+ championTier = 6;
+ } else if (championXp < 2000000) {
+ championTier = 7;
+ } else if (championXp < 2500000) {
+ championTier = 8;
+ } else if (championXp < 3000000) {
+ championTier = 9;
+ } else if (championXp > 3000000) {
+ championTier = 10;
+ }
+
+ switch (championTier) {
+ case 1:
+ championTierAmount = "50,000";
+ break;
+ case 2:
+ championTierAmount = "100,000";
+ break;
+ case 3:
+ championTierAmount = "250,000";
+ break;
+ case 4:
+ championTierAmount = "500,000";
+ break;
+ case 5:
+ championTierAmount = "1,000,000";
+ break;
+ case 6:
+ championTierAmount = "1,500,000";
+ break;
+ case 7:
+ championTierAmount = "2,000,000";
+ break;
+ case 8:
+ championTierAmount = "2,500,000";
+ break;
+ case 9:
+ championTierAmount = "3,000,000";
+ break;
+ case 10:
+ championTierAmount = "Maxed";
+ break;
+ }
+
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
skillInfoLast = skillInfo;
@@ -134,7 +218,7 @@ public class CombatSkillOverlay
killQueue.removeLast();
}
- if (kill != -1) {
+ if (kill != -1 || championXp != -1) {
overlayStrings = new ArrayList<>();
} else {
overlayStrings = null;
@@ -146,7 +230,7 @@ public class CombatSkillOverlay
public void updateFrequent() {
super.updateFrequent();
- if (kill < 0 && !NotEnoughUpdates.INSTANCE.config.skillOverlays.alwaysShowCombatOverlay) {
+ if ((kill < 0 && championXp < 0) && !NotEnoughUpdates.INSTANCE.config.skillOverlays.alwaysShowCombatOverlay) {
overlayStrings = null;
} else {
HashMap<Integer, String> lineMap = new HashMap<>();
@@ -161,6 +245,23 @@ public class CombatSkillOverlay
lineMap.put(0, EnumChatFormatting.AQUA + "Kills: " + EnumChatFormatting.YELLOW + format.format(counterInterp));
}
+ if (championTier <= 9) {
+ int counterInterp = (int) interp(championXp, championXpLast);
+ lineMap.put(
+ 6,
+ EnumChatFormatting.AQUA + "Champion: " + EnumChatFormatting.YELLOW + format.format(counterInterp) + "/" +
+ championTierAmount
+ );
+ }
+ if (championTier == 10) {
+ int counterInterp = (int) interp(championXp, championXpLast);
+ lineMap.put(
+ 6,
+ EnumChatFormatting.AQUA + "Champion: " + EnumChatFormatting.YELLOW + format.format(counterInterp) + " " +
+ EnumChatFormatting.RED + championTierAmount
+ );
+ }
+
float xpInterp = xpGainHour;
if (xpGainHourLast == xpGainHour && xpGainHour <= 0) {
lineMap.put(4, EnumChatFormatting.AQUA + "XP/h: " + EnumChatFormatting.YELLOW + "N/A");
@@ -255,4 +356,4 @@ public class CombatSkillOverlay
if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java
index 529f132a..aae5d028 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/CrystalHollowOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -7,13 +26,19 @@ import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.util.SBInfo;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.util.vector.Vector2f;
import java.text.DecimalFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -49,6 +74,60 @@ public class CrystalHollowOverlay extends TextOverlay {
super(position, dummyStrings, styleSupplier);
}
+ private final Pattern hotmCrystalNotFoundPattern = Pattern.compile("(?<crystal>[a-zA-Z]+) \\u2716 Not Found");
+ private final Pattern hotmCrystalNotPlacedPattern = Pattern.compile("(?<crystal>[a-zA-Z]+) \\u2716 Not Placed");
+ private final Pattern hotmCrystalPlacedPattern = Pattern.compile("(?<crystal>[a-zA-Z]+) \\u2714 Placed");
+
+ private void updateHotmCrystalState(IInventory lower) {
+ NEUConfig.HiddenProfileSpecific perProfileConfig = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
+ if (perProfileConfig == null) return;
+
+ ItemStack crystalStateStack = lower.getStackInSlot(50);
+ if (crystalStateStack == null || !crystalStateStack.hasTagCompound()) {
+ return;
+ }
+
+ String name = Utils.cleanColour(crystalStateStack.getDisplayName()).trim();
+ if (!name.equals("Crystal Hollows Crystals")) {
+ return;
+ }
+
+ String[] lore = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(crystalStateStack.getTagCompound());
+ for (String line : lore) {
+ if (line == null) {
+ continue;
+ }
+ String cleanLine = Utils.cleanColour(line).trim();
+ Matcher hotmCrystalNotPlacedMatcher = hotmCrystalNotPlacedPattern.matcher(cleanLine);
+ Matcher hotmCrystalNotFoundMatcher = hotmCrystalNotFoundPattern.matcher(cleanLine);
+ Matcher hotmCrystalPlacedMatcher = hotmCrystalPlacedPattern.matcher(cleanLine);
+ if (hotmCrystalNotFoundMatcher.matches() &&
+ perProfileConfig.crystals.containsKey(hotmCrystalNotFoundMatcher.group("crystal"))) {
+ perProfileConfig.crystals.put(hotmCrystalNotFoundMatcher.group("crystal"), 0);
+ } else if (hotmCrystalNotPlacedMatcher.matches() && perProfileConfig.crystals.containsKey(
+ hotmCrystalNotPlacedMatcher.group("crystal"))) {
+ perProfileConfig.crystals.put(hotmCrystalNotPlacedMatcher.group("crystal"), 1);
+ } else if (hotmCrystalPlacedMatcher.matches() &&
+ perProfileConfig.crystals.containsKey(hotmCrystalPlacedMatcher.group("crystal"))) {
+ perProfileConfig.crystals.put(hotmCrystalPlacedMatcher.group("crystal"), 2);
+ }
+ }
+ }
+
+ @Override
+ public void updateFrequent() {
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ IInventory lower = container.getLowerChestInventory();
+ String containerName = lower.getDisplayName().getUnformattedText();
+
+ if (containerName.equals("Heart of the Mountain") && lower.getSizeInventory() >= 54) {
+ updateHotmCrystalState(lower);
+ }
+ }
+ }
+
@Override
public void update() {
overlayStrings = null;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java
new file mode 100644
index 00000000..5cd8f6b3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/EquipmentOverlay.java
@@ -0,0 +1,461 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.overlays;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.events.GuiInventoryBackgroundDrawnEvent;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.miscgui.GuiInvButtonEditor;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
+import io.github.moulberry.notenoughupdates.options.NEUConfig;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiInventory;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import net.minecraftforge.fml.relauncher.Side;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+public class EquipmentOverlay {
+ public static EquipmentOverlay INSTANCE = new EquipmentOverlay();
+
+ // <editor-fold desc="resources">
+ private static final ResourceLocation ARMOR_DISPLAY = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay.png");
+ private static final ResourceLocation ARMOR_DISPLAY_GREY = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay_grey.png");
+ private static final ResourceLocation ARMOR_DISPLAY_DARK = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay_phq_dark.png");
+ private static final ResourceLocation ARMOR_DISPLAY_FSR = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay_fsr.png");
+ private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay_transparent.png");
+ private static final ResourceLocation ARMOR_DISPLAY_TRANSPARENT_PET = new ResourceLocation(
+ "notenoughupdates:armordisplay/armordisplay_transparent_pet.png");
+
+ private static final ResourceLocation QUESTION_MARK = new ResourceLocation("notenoughupdates:pv_unknown.png");
+
+ private static final ResourceLocation PET_DISPLAY = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplaysolo.png");
+ private static final ResourceLocation PET_DISPLAY_GREY = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplaysolo_dark.png");
+ private static final ResourceLocation PET_DISPLAY_DARK = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplaysolo_phqdark.png");
+ private static final ResourceLocation PET_DISPLAY_FSR = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplaysolo_fsr.png");
+ private static final ResourceLocation PET_DISPLAY_TRANSPARENT = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplaysolo_transparent.png");
+
+ private static final ResourceLocation PET_ARMOR_DISPLAY = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplayarmor.png");
+ private static final ResourceLocation PET_ARMOR_DISPLAY_GREY = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplayarmor_dark.png");
+ private static final ResourceLocation PET_ARMOR_DISPLAY_DARK = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplayarmor_phqdark.png");
+ private static final ResourceLocation PET_ARMOR_DISPLAY_FSR = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplayarmor_fsr.png");
+ private static final ResourceLocation PET_ARMOR_DISPLAY_TRANSPARENT = new ResourceLocation(
+ "notenoughupdates:petdisplay/petdisplayarmor_transparent.png");
+ //</editor-fold>
+
+ //<editor-fold desc="dynamic resources">
+ public ResourceLocation getCustomEquipmentTexture(boolean isPetRendering) {
+ switch (NotEnoughUpdates.INSTANCE.config.customArmour.colourStyle) {
+ case 0:
+ return ARMOR_DISPLAY;
+ case 1:
+ return ARMOR_DISPLAY_GREY;
+ case 2:
+ return ARMOR_DISPLAY_DARK;
+ case 3:
+ return NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle == 3 && isPetRendering ? ARMOR_DISPLAY_TRANSPARENT_PET : ARMOR_DISPLAY_TRANSPARENT;
+ case 4:
+ return ARMOR_DISPLAY_FSR;
+ }
+ return null;
+ }
+
+ public ResourceLocation getCustomPetTexture(boolean isArmorRendering) {
+ switch (NotEnoughUpdates.INSTANCE.config.petOverlay.colourStyle) {
+ case 0:
+ return isArmorRendering ? PET_ARMOR_DISPLAY : PET_DISPLAY;
+ case 1:
+ return isArmorRendering ? PET_ARMOR_DISPLAY_GREY : PET_DISPLAY_GREY;
+ case 2:
+ return isArmorRendering ? PET_ARMOR_DISPLAY_DARK : PET_DISPLAY_DARK;
+ case 3:
+ return isArmorRendering ? PET_ARMOR_DISPLAY_TRANSPARENT : PET_DISPLAY_TRANSPARENT;
+ case 4:
+ return isArmorRendering ? PET_ARMOR_DISPLAY_FSR : PET_DISPLAY_FSR;
+ }
+ return null;
+ }
+ //</editor-fold>
+
+ //<editor-fold desc="pixel constants">
+ public static final int EQUIPMENT_SLOT_OFFSET_Y = 8;
+ public static final int ARMOR_OVERLAY_OVERHAND_WIDTH = 24;
+ public static final int ARMOR_OVERLAY_HEIGHT = 86;
+ public static final int ARMOR_OVERLAY_WIDTH = 31;
+ final static int PET_OVERLAY_HEIGHT = 32;
+ final static int PET_OVERLAY_WIDTH = 31;
+ public static final int PET_OVERLAY_OFFSET_Y = ARMOR_OVERLAY_HEIGHT - 14 /* overlaying pixels */;
+ //</editor-fold>
+
+
+ public boolean shouldRenderPets;
+ public boolean shouldRenderArmorHud;
+
+ public ItemStack petStack;
+
+ //<editor-fold desc="events">
+
+ @SubscribeEvent
+ public void onGuiTick(TickEvent.ClientTickEvent event) {
+ if (event.phase != TickEvent.Phase.START || event.side != Side.CLIENT) return;
+ updateGuiInfo(Minecraft.getMinecraft().currentScreen);
+ }
+
+ @SubscribeEvent
+ public void onGuiInit(GuiScreenEvent.InitGuiEvent event) {
+ updateGuiInfo(event.gui);
+ }
+
+ @SubscribeEvent
+ public void onRenderGuiPost(GuiInventoryBackgroundDrawnEvent event) {
+ if (!(event.getContainer() instanceof GuiInventory)) return;
+ GuiInventory inventory = ((GuiInventory) event.getContainer());
+ renderGuis(inventory);
+ }
+
+ //</editor-fold>
+
+ public void renderGuis(GuiInventory inventory) {
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ GL11.glColor4f(1F, 1F, 1F, 1F);
+ if (shouldRenderArmorHud) {
+ renderEquipmentGui(inventory, mouseX, mouseY, width, height);
+ }
+
+ if (shouldRenderPets) {
+ renderPets(inventory, mouseX, mouseY, width, height);
+ }
+ }
+
+ public void renderEquipmentGui(GuiInventory guiScreen, int mouseX, int mouseY, int width, int height) {
+ AccessorGuiContainer container = ((AccessorGuiContainer) guiScreen);
+
+ int overlayLeft = container.getGuiLeft() - ARMOR_OVERLAY_OVERHAND_WIDTH;
+ int overlayTop = container.getGuiTop();
+
+ ResourceLocation equipmentTexture = getCustomEquipmentTexture(shouldRenderPets);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(equipmentTexture);
+
+ Utils.drawTexturedRect(overlayLeft, overlayTop, ARMOR_OVERLAY_WIDTH, ARMOR_OVERLAY_HEIGHT, GL11.GL_NEAREST);
+
+ List<String> tooltipToDisplay = new ArrayList<>();
+ drawSlot(slot1, overlayLeft + 8, overlayTop + EQUIPMENT_SLOT_OFFSET_Y, mouseX, mouseY, tooltipToDisplay);
+ drawSlot(slot2, overlayLeft + 8, overlayTop + EQUIPMENT_SLOT_OFFSET_Y + 18, mouseX, mouseY, tooltipToDisplay);
+ drawSlot(slot3, overlayLeft + 8, overlayTop + EQUIPMENT_SLOT_OFFSET_Y + 36, mouseX, mouseY, tooltipToDisplay);
+ drawSlot(slot4, overlayLeft + 8, overlayTop + EQUIPMENT_SLOT_OFFSET_Y + 54, mouseX, mouseY, tooltipToDisplay);
+
+ if (slot1 == null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(QUESTION_MARK);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(overlayLeft + 8, overlayTop + EQUIPMENT_SLOT_OFFSET_Y, 16, 16, GL11.GL_NEAREST);
+
+ tooltipToDisplay = Lists.newArrayList(
+ EnumChatFormatting.RED + "Warning",
+ EnumChatFormatting.GREEN + "You need to open /equipment",
+ EnumChatFormatting.GREEN + "to cache your armour"
+ );
+ if (Utils.isWithinRect(mouseX, mouseY, overlayLeft + 8, overlayTop + 8, 16, 16)
+ && NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand
+ && Mouse.getEventButtonState()
+ && Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null) {
+ NotEnoughUpdates.INSTANCE.trySendCommand("/equipment");
+ }
+
+ }
+ if (tooltipToDisplay.size() > 0 &&
+ Utils.isWithinRect(
+ mouseX, mouseY,
+ overlayLeft, overlayTop,
+ ARMOR_OVERLAY_OVERHAND_WIDTH, ARMOR_OVERLAY_HEIGHT
+ )) {
+ Utils.drawHoveringText(
+ tooltipToDisplay,
+ mouseX - calculateTooltipXOffset(tooltipToDisplay, Minecraft.getMinecraft().fontRendererObj),
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+
+ }
+
+ private ItemStack getRepoPetStack() {
+ NEUManager manager = NotEnoughUpdates.INSTANCE.manager;
+ PetInfoOverlay.Pet currentPet = PetInfoOverlay.getCurrentPet();
+ if (currentPet == null) return null;
+
+ ItemStack item = ItemUtils.createPetItemstackFromPetInfo(currentPet);
+ item = ItemUtils.petToolTipXPExtendPetOverlay(item);
+
+ if (item != null) {
+ return item;
+ }
+ item = manager.createItem(currentPet.getPetId(true));
+ return item;
+ }
+
+ private void updateGuiInfo(GuiScreen screen) {
+ if (getWardrobeSlot(10) != null) {
+ slot1 = getWardrobeSlot(10);
+ slot2 = getWardrobeSlot(19);
+ slot3 = getWardrobeSlot(28);
+ slot4 = getWardrobeSlot(37);
+ }
+
+ if ((screen instanceof GuiChest || screen instanceof GuiInventory) && NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay){
+ petStack = getRepoPetStack();
+ }
+ if ((!(screen instanceof GuiInventory) && !(screen instanceof GuiInvButtonEditor))
+ || !NotEnoughUpdates.INSTANCE.config.misc.hidePotionEffect
+ || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) {
+ shouldRenderPets = shouldRenderArmorHud = false;
+ return;
+ }
+ shouldRenderPets = NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay && petStack != null;
+ shouldRenderArmorHud = NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud;
+ }
+
+ private void drawSlot(ItemStack stack, int x, int y, int mouseX, int mouseY, List<String> tooltip) {
+ if (stack == null) return;
+ Utils.drawItemStack(stack, x, y, true);
+ if (Utils.isWithinRect(mouseX, mouseY, x, y, 16, 16)) {
+ List<String> tt = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ if (shouldShowEquipmentTooltip(tt))
+ tooltip.addAll(tt);
+ if (NotEnoughUpdates.INSTANCE.config.customArmour.sendWardrobeCommand
+ && Mouse.getEventButtonState()) {
+ NotEnoughUpdates.INSTANCE.trySendCommand("/equipment");
+ }
+ }
+ }
+
+ public void renderPets(GuiInventory inventory, int mouseX, int mouseY, int width, int height) {
+ ItemUtils.getOrCreateTag(petStack).setBoolean(
+ "NEUHIDEPETTOOLTIP",
+ NotEnoughUpdates.INSTANCE.config.petOverlay.hidePetTooltip
+ );
+ ItemStack petInfo = petStack;
+
+ ResourceLocation customPetTexture = getCustomPetTexture(isRenderingArmorHud());
+ Minecraft.getMinecraft().getTextureManager().bindTexture(customPetTexture);
+ GlStateManager.color(1, 1, 1, 1);
+
+ AccessorGuiContainer container = ((AccessorGuiContainer) inventory);
+
+ int overlayLeft = container.getGuiLeft() - ARMOR_OVERLAY_OVERHAND_WIDTH;
+ int overlayTop = container.getGuiTop() + PET_OVERLAY_OFFSET_Y;
+
+ Utils.drawTexturedRect(overlayLeft, overlayTop, PET_OVERLAY_WIDTH, PET_OVERLAY_HEIGHT, GL11.GL_NEAREST);
+ GlStateManager.bindTexture(0);
+
+ Utils.drawItemStack(petInfo, overlayLeft + 8, overlayTop + 8, true);
+
+ List<String> tooltipToDisplay;
+ if (Utils.isWithinRect(mouseX, mouseY, overlayLeft + 8, overlayTop + 8, 16, 16)) {
+ if (NotEnoughUpdates.INSTANCE.config.petOverlay.sendPetsCommand
+ && Minecraft.getMinecraft().thePlayer.inventory.getItemStack() == null
+ && Mouse.getEventButtonState()) {
+ NotEnoughUpdates.INSTANCE.trySendCommand("/pets");
+ }
+ tooltipToDisplay = petInfo.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ Utils.drawHoveringText(
+ tooltipToDisplay,
+ mouseX - calculateTooltipXOffset(tooltipToDisplay, Minecraft.getMinecraft().fontRendererObj),
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+
+ private ItemStack getWardrobeSlot(int armourSlot) {
+ if (SBInfo.getInstance().currentProfile == null) {
+ return null;
+ }
+
+ if (!Objects.equals(SBInfo.getInstance().currentProfile, lastProfile)) {
+ lastProfile = SBInfo.getInstance().currentProfile;
+ slot1 = null;
+ slot2 = null;
+ slot3 = null;
+ slot4 = null;
+ }
+
+ NEUConfig.HiddenProfileSpecific profileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
+ if (profileSpecific == null) return null;
+
+ if (isInNamedGui("Your Equipment")) {
+ ItemStack itemStack = getChestSlotsAsItemStack(armourSlot);
+ if (itemStack != null) {
+ JsonObject itemToSave = NotEnoughUpdates.INSTANCE.manager.getJsonForItem(itemStack);
+ if (!itemToSave.has("internalname")) {
+ //would crash without internalName when trying to construct the ItemStack again
+ itemToSave.add("internalname", new JsonPrimitive("_"));
+ }
+ profileSpecific.savedEquipment.put(armourSlot, itemToSave);
+ return itemStack;
+ }
+ } else {
+ if (profileSpecific.savedEquipment.containsKey(armourSlot)) {
+ //don't use cache since the internalName is identical in most cases
+ JsonObject jsonObject = profileSpecific.savedEquipment
+ .get(armourSlot);
+ if (jsonObject != null) return NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonObject
+ .getAsJsonObject(), false);
+ }
+ }
+ return null;
+ }
+
+ private boolean wardrobeOpen = false;
+
+ private boolean isInNamedGui(String guiName) {
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if (guiScreen instanceof GuiChest) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ IInventory lower = container.getLowerChestInventory();
+ String containerName = lower.getDisplayName().getUnformattedText();
+ wardrobeOpen = containerName.contains(guiName);
+ }
+ if (guiScreen instanceof GuiInventory) {
+ wardrobeOpen = false;
+ }
+ return wardrobeOpen;
+ }
+
+ private ItemStack getChestSlotsAsItemStack(int slot) {
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if (guiScreen instanceof GuiChest) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ return chest.inventorySlots.getSlot(slot).getStack();
+ } else {
+ return null;
+ }
+ }
+
+ public static boolean isRenderingArmorHud() {
+ return INSTANCE.shouldRenderArmorHud;
+ }
+
+ public static boolean isRenderingPetHud() {
+ return INSTANCE.shouldRenderPets;
+ }
+
+ private boolean shouldShowEquipmentTooltip(List<String> toolTip) {
+ return !toolTip.get(0).equals("§o§7Empty Equipment Slot§r");
+ }
+
+ /**
+ * Calculates the width of the longest String in the tooltip, which can be used to offset the entire tooltip to the left more precisely
+ *
+ * @param tooltipToDisplay tooltip
+ * @param fr FontRenderer object
+ * @return offset to apply
+ */
+ private int calculateTooltipXOffset(List<String> tooltipToDisplay, FontRenderer fr) {
+ int offset = 0;
+ if (tooltipToDisplay != null) {
+ for (String line : tooltipToDisplay) {
+ int lineWidth = fr.getStringWidth(line);
+ if (lineWidth > offset) {
+ offset = lineWidth;
+ }
+ }
+ }
+ return offset + 20;
+ }
+
+ public void renderPreviewArmorHud() {
+ if (!NotEnoughUpdates.INSTANCE.config.customArmour.enableArmourHud || !(Minecraft.getMinecraft().currentScreen instanceof GuiInvButtonEditor)) return;
+ GuiInvButtonEditor container = (GuiInvButtonEditor) Minecraft.getMinecraft().currentScreen;
+
+ int overlayLeft = container.getGuiLeft() - ARMOR_OVERLAY_OVERHAND_WIDTH;
+ int overlayTop = container.getGuiTop();
+
+ ResourceLocation equipmentTexture = getCustomEquipmentTexture(shouldRenderPets);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(equipmentTexture);
+
+ Utils.drawTexturedRect(overlayLeft, overlayTop, ARMOR_OVERLAY_WIDTH, ARMOR_OVERLAY_HEIGHT, GL11.GL_NEAREST);
+ }
+
+ public void renderPreviewPetInvHud() {
+ if (!NotEnoughUpdates.INSTANCE.config.petOverlay.petInvDisplay || !(Minecraft.getMinecraft().currentScreen instanceof GuiInvButtonEditor)) return;
+ GuiInvButtonEditor container = (GuiInvButtonEditor) Minecraft.getMinecraft().currentScreen;
+ int overlayLeft = container.getGuiLeft() - ARMOR_OVERLAY_OVERHAND_WIDTH;
+ int overlayTop = container.getGuiTop() + PET_OVERLAY_OFFSET_Y;
+
+ ResourceLocation petHudTexture = getCustomPetTexture(shouldRenderArmorHud);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(petHudTexture);
+
+ Utils.drawTexturedRect(overlayLeft, overlayTop, PET_OVERLAY_WIDTH, PET_OVERLAY_HEIGHT, GL11.GL_NEAREST);
+ }
+
+ public ItemStack slot1 = null;
+ public ItemStack slot2 = null;
+ public ItemStack slot3 = null;
+ public ItemStack slot4 = null;
+ private String lastProfile;
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FarmingOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FarmingOverlay.java
index f2c7e396..970c74ab 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FarmingOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FarmingOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import com.google.gson.JsonObject;
@@ -175,18 +194,17 @@ public class FarmingOverlay extends TextOverlay {
}
if (!NotEnoughUpdates.INSTANCE.config.skillOverlays.useBZPrice || internalname != null && (internalname.equals(
- "TREECAPITATOR_AXE"))
- || internalname != null && (internalname.equals("JUNGLE_AXE"))) {
- if (internalname != null && internalname.startsWith("THEORETICAL_HOE_WARTS") ||
- (internalname != null && internalname.equals("COCO_CHOPPER"))) {
+ "TREECAPITATOR_AXE")) || internalname != null && (internalname.equals("JUNGLE_AXE"))) {
+ if ((internalname != null && internalname.equals("COCO_CHOPPER"))) {
Coins = 3;
} else if (internalname != null && internalname.startsWith("THEORETICAL_HOE_POTATO") ||
- (internalname != null && internalname.startsWith("THEORETICAL_HOE_CARROT"))
- || (internalname != null && internalname.equals("CACTUS_KNIFE")) ||
+ (internalname != null && internalname.startsWith("THEORETICAL_HOE_CARROT")) ||
+ (internalname != null && internalname.equals("CACTUS_KNIFE")) ||
(internalname != null && internalname.startsWith("THEORETICAL_HOE_WHEAT"))) {
Coins = 1;
- } else if (internalname != null && internalname.startsWith("THEORETICAL_HOE_CANE") ||
- (internalname != null && internalname.equals("TREECAPITATOR_AXE"))
+ } else if (internalname != null && internalname.startsWith("THEORETICAL_HOE_CANE")
+ || (internalname != null && internalname.equals("TREECAPITATOR_AXE"))
+ || (internalname != null && internalname.startsWith("THEORETICAL_HOE_WARTS"))
|| (internalname != null && internalname.equals("JUNGLE_AXE"))) {
Coins = 2;
} else if ((internalname != null && internalname.equals("PUMPKIN_DICER")) ||
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FishingSkillOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FishingSkillOverlay.java
index 6f7b21d8..717ff944 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FishingSkillOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FishingSkillOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -402,4 +421,4 @@ public class FishingSkillOverlay
if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java
index fa2db8b5..d180efcf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/FuelBar.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java
index bfbe367f..03fe9eff 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import com.google.common.collect.ComparisonChain;
@@ -24,16 +43,29 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.world.WorldSettings;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
+import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector2f;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import java.util.function.Supplier;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static net.minecraft.util.EnumChatFormatting.*;
+import static net.minecraft.util.EnumChatFormatting.BLUE;
+import static net.minecraft.util.EnumChatFormatting.BOLD;
+import static net.minecraft.util.EnumChatFormatting.DARK_AQUA;
+import static net.minecraft.util.EnumChatFormatting.GOLD;
+import static net.minecraft.util.EnumChatFormatting.GREEN;
+import static net.minecraft.util.EnumChatFormatting.RED;
+import static net.minecraft.util.EnumChatFormatting.RESET;
+import static net.minecraft.util.EnumChatFormatting.YELLOW;
-public class MiningOverlay extends TextOverlay {
+public class MiningOverlay extends TextTabOverlay {
public MiningOverlay(
Position position,
Supplier<List<String>> dummyStrings,
@@ -54,7 +86,7 @@ public class MiningOverlay extends TextOverlay {
String containerName = lower.getDisplayName().getUnformattedText();
if (containerName.equals("Commissions") && lower.getSizeInventory() >= 27) {
- UpdateCommissions(lower);
+ updateCommissions(lower);
} else if (containerName.equals("Forge") && lower.getSizeInventory() >= 36) {
updateForge(lower);
}
@@ -127,7 +159,7 @@ public class MiningOverlay extends TextOverlay {
}
}
- private void UpdateCommissions(IInventory lower) {
+ private void updateCommissions(IInventory lower) {
// Get the location (type) of the currently shown commissions
ItemStack commTypeStack = lower.getStackInSlot(27);
if (commTypeStack == null || !commTypeStack.hasTagCompound()) {
@@ -202,93 +234,32 @@ public class MiningOverlay extends TextOverlay {
"\\xA77Time Remaining: \\xA7a((?<Completed>Completed!)|(((?<days>[0-9]+)d)? ?((?<hours>[0-9]+)h)? ?((?<minutes>[0-9]+)m)? ?((?<seconds>[0-9]+)s)?))");
private static final Pattern timeRemainingTab = Pattern.compile(
".*[1-5]\\) (?<ItemName>.*): ((?<Ready>Ready!)|(((?<days>[0-9]+)d)? ?((?<hours>[0-9]+)h)? ?((?<minutes>[0-9]+)m)? ?((?<seconds>[0-9]+)s)?))");
+ private static final Pattern forgesHeaderPattern = Pattern.compile(
+ "\\xa7r\\xa79\\xa7lForges \\xa7r(?:\\xa7f\\(\\+1 more\\)\\xa7r)?");
@Override
public void update() {
overlayStrings = null;
- NEUConfig.HiddenProfileSpecific hidden = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
-
-
- /*if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
-
-
- long currentTime = System.currentTimeMillis();
- if(currentTime - lastSkymallSync > 60*1000) {
- if(CapeManager.getInstance().lastJsonSync != null) {
- JsonObject obj = CapeManager.getInstance().lastJsonSync;
- if(obj.has("skymall") && obj.get("skymall").isJsonPrimitive()) {
- activeSkymall = obj.get("skymall").getAsString();
- }
- }
- }
-
- if(containerName.equals("Heart of the Mountain") && container.getLowerChestInventory().getSizeInventory() > 10) {
- System.out.println("HOTM Container");
- ItemStack stack = container.getLowerChestInventory().getStackInSlot(10);
- if(stack != null && stack.getDisplayName().equals(GREEN+"Sky Mall")) {
- NotEnoughUpdates.INSTANCE.config.hidden.skymallActive = false;
-
- String[] lines = NotEnoughUpdates.INSTANCE.manager.getLoreFromNBT(stack.getTagCompound());
-
- for(String line : lines) {
- if(line.equals("\u00a7aYour Current Effect")) {
- System.out.println("Current effect");
- NotEnoughUpdates.INSTANCE.config.hidden.skymallActive = true;
- } else if(NotEnoughUpdates.INSTANCE.config.hidden.skymallActive) {
- String prevActiveSkymall = activeSkymall;
- System.out.println("Setting");
- if(line.contains("Gain \u00a7a+100 \u00a76\u2E15 Mining Speed")) {
- activeSkymall = "mining_speed";
- } else if(line.contains("Gain \u00a7a+50 \u00a76\u2618 Mining Fortune")) {
- activeSkymall = "mining_fortune";
- } else if(line.contains("Gain \u00a7a+15% \u00a77Powder from mining")) {
- activeSkymall = "powder";
- } else if(line.contains("Reduce Pickaxe Ability cooldown")) {
- activeSkymall = "pickaxe_ability";
- } else if(line.contains("10x \u00a77chance to find Goblins")) {
- activeSkymall = "goblin";
- } else if(line.contains("Gain \u00a7a5x \u00a79Titanium \u00a77drops")) {
- activeSkymall = "titanium";
- } else {
- System.out.println("Unknown");
- activeSkymall = "unknown";
- }
- if(!activeSkymall.equals(prevActiveSkymall)) {
- System.out.println("Maybe sending to server");
- if(currentTime - lastSkymallSync > 60*1000) {
- lastSkymallSync = currentTime;
- System.out.println("Sending to server");
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("skymall?"+activeSkymall, (jsonObject) -> {
- System.out.println("Success!");
- }, () -> {
- System.out.println("Error!");
- });
- }
- }
- break;
- }
- }
- }
- }
- }*/
+ NEUConfig.HiddenProfileSpecific profileConfig = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
if (!NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay &&
NotEnoughUpdates.INSTANCE.config.mining.emissaryWaypoints == 0 &&
!NotEnoughUpdates.INSTANCE.config.mining.titaniumAlert &&
- NotEnoughUpdates.INSTANCE.config.mining.locWaypoints == 0) return;
+ NotEnoughUpdates.INSTANCE.config.mining.locWaypoints == 0) {
+ return;
+ }
+
+ // Get commission and forge info even if the overlay isn't going to be rendered since it is used elsewhere
//thanks to "Pure Genie#7250" for helping with this (makes tita alert and waypoints work without mine overlay)
if (SBInfo.getInstance().getLocation() == null) return;
- if (SBInfo.getInstance().getLocation().equals("mining_3") || SBInfo.getInstance().getLocation().equals(
- "crystal_hollows")) {
-
- overlayStrings = new ArrayList<>();
+ if (SBInfo.getInstance().getLocation().equals("mining_3") ||
+ SBInfo.getInstance().getLocation().equals("crystal_hollows")) {
commissionProgress.clear();
- String mithrilPowder = null;
- String gemstonePowder = null;
+ // These strings will be displayed one after the other when the player list is disabled
+ String mithrilPowder = RED + "[NEU] Failed to get data from your tablist";
+ String gemstonePowder = RED + "Please enable player list info in your skyblock settings";
+
int forgeInt = 0;
boolean commissions = false;
boolean forges = false;
@@ -298,48 +269,43 @@ public class MiningOverlay extends TextOverlay {
for (NetworkPlayerInfo info : players) {
String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info);
if (name.contains("Mithril Powder:")) {
- mithrilPowder = DARK_AQUA + Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", "");
- continue;
- } else if (mithrilPowder == null) {
- mithrilPowder = RED + "[NEU] Failed to get data from your tablist";
+ mithrilPowder = DARK_AQUA + Utils.trimWhitespaceAndFormatCodes(name).replaceAll("\u00a7[f|F|r]", "");
continue;
}
if (name.contains("Gemstone Powder:")) {
- gemstonePowder = DARK_AQUA + Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", "");
- continue;
- } else if (gemstonePowder == null) {
- gemstonePowder = RED + "Please enable player list info in your skyblock settings";
+ gemstonePowder = DARK_AQUA + Utils.trimWhitespaceAndFormatCodes(name).replaceAll("\u00a7[f|F|r]", "");
continue;
}
- if (name.matches("\\xa7r\\xa79\\xa7lForges \\xa7r(?:\\xa7f\\(\\+1 more\\)\\xa7r)?") && hidden != null) {
+ Matcher forgesMatcher = forgesHeaderPattern.matcher(name);
+ if (forgesMatcher.matches() && profileConfig != null) {
commissions = false;
forges = true;
continue;
- } else if (name.equals(RESET.toString() + BLUE + BOLD + "Commissions" + RESET) && hidden != null) {
+ }
+
+ // Commissions appear after Forges, start enumerating Commissions instead of Forges
+ if (name.equals(RESET.toString() + BLUE + BOLD + "Commissions" + RESET) && profileConfig != null) {
commissions = true;
forges = false;
continue;
}
- String clean = StringUtils.cleanColour(name);
- if (forges && clean.startsWith(" ") && hidden != null) {
- char firstChar = clean.trim().charAt(0);
+ String cleanName = StringUtils.cleanColour(name);
+ if (forges && cleanName.startsWith(" ") && profileConfig != null) {
+ char firstChar = cleanName.trim().charAt(0);
if (firstChar < '0' || firstChar > '9') {
forges = false;
} else {
if (name.contains("LOCKED")) {
ForgeItem item = new ForgeItem(forgeInt, 1, true);
- replaceForgeOrAdd(item, hidden.forgeItems, true);
+ replaceForgeOrAdd(item, profileConfig.forgeItems, true);
} else if (name.contains("EMPTY")) {
ForgeItem item = new ForgeItem(forgeInt, 0, true);
- replaceForgeOrAdd(item, hidden.forgeItems, true);
- //forgeStringsEmpty.add(DARK_AQUA+"Forge "+ Utils.trimIgnoreColour(name).replaceAll("\u00a7[f|F|r]", ""));
+ replaceForgeOrAdd(item, profileConfig.forgeItems, true);
} else {
- String cleanName = Utils.cleanColour(name);
-
Matcher matcher = timeRemainingTab.matcher(cleanName);
if (matcher.matches()) {
@@ -348,7 +314,7 @@ public class MiningOverlay extends TextOverlay {
if (matcher.group("Ready") != null && !matcher.group("Ready").equals("")) {
ForgeItem item = new ForgeItem(Utils.cleanColour(itemName), 0, forgeInt, true);
- replaceForgeOrAdd(item, hidden.forgeItems, true);
+ replaceForgeOrAdd(item, profileConfig.forgeItems, true);
} else {
long duration = 0;
try {
@@ -374,15 +340,15 @@ public class MiningOverlay extends TextOverlay {
forgeInt,
true
);
- replaceForgeOrAdd(item, hidden.forgeItems, false);
+ replaceForgeOrAdd(item, profileConfig.forgeItems, false);
}
}
}
}
forgeInt++;
}
- } else if (commissions && clean.startsWith(" ") && hidden != null) {
- String[] split = clean.trim().split(": ");
+ } else if (commissions && cleanName.startsWith(" ") && profileConfig != null) {
+ String[] split = cleanName.trim().split(": ");
if (split.length == 2) {
if (split[1].endsWith("%")) {
try {
@@ -400,8 +366,8 @@ public class MiningOverlay extends TextOverlay {
forges = false;
}
}
+
if (!NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay) {
- overlayStrings = null;
return;
}
@@ -430,22 +396,6 @@ public class MiningOverlay extends TextOverlay {
}
}
}
- /*boolean hasAny = false;
- if(NotEnoughUpdates.INSTANCE.config.mining.dwarvenOverlay) {
- overlayStrings.addAll(commissionsStrings);
- hasAny = true;
- }
- if(NotEnoughUpdates.INSTANCE.config.mining.powderOverlay) {
- if(mithrilPowder != null) {
- if(hasAny) overlayStrings.add(null);
- overlayStrings.add(DARK_AQUA+mithrilPowder);
- hasAny = true;
- }
- }
- if(NotEnoughUpdates.INSTANCE.config.mining.forgeOverlay) {
- if(hasAny) overlayStrings.add(null);
- overlayStrings.addAll(forgeStrings);
- }*/
String pickaxeCooldown;
if (ItemCooldowns.pickaxeUseCooldownMillisRemaining <= 0) {
@@ -455,6 +405,7 @@ public class MiningOverlay extends TextOverlay {
DARK_AQUA + "Pickaxe CD: \u00a7a" + (ItemCooldowns.pickaxeUseCooldownMillisRemaining / 1000) + "s";
}
+ overlayStrings = new ArrayList<>();
for (int index : NotEnoughUpdates.INSTANCE.config.mining.dwarvenText2) {
switch (index) {
case 0:
@@ -467,8 +418,8 @@ public class MiningOverlay extends TextOverlay {
overlayStrings.add(gemstonePowder);
break;
case 3:
- if (hidden != null) {
- overlayStrings.addAll(getForgeStrings(hidden.forgeItems));
+ if (profileConfig != null) {
+ overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems));
}
break;
case 4:
@@ -479,8 +430,7 @@ public class MiningOverlay extends TextOverlay {
}
}
} else {
- overlayStrings = new ArrayList<>();
- if (hidden == null) {
+ if (profileConfig == null) {
return;
}
boolean forgeDisplay = false;
@@ -490,16 +440,21 @@ public class MiningOverlay extends TextOverlay {
}
}
if (forgeDisplay) {
- if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 1 &&
- !SBInfo.getInstance().isInDungeon) {
- overlayStrings.addAll(getForgeStrings(hidden.forgeItems));
- } else if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 2) {
- overlayStrings.addAll(getForgeStrings(hidden.forgeItems));
+ overlayStrings = new ArrayList<>();
+
+ if (!NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayOnlyShowTab ||
+ Keyboard.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindPlayerList.getKeyCode())) {
+ if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 1 &&
+ !SBInfo.getInstance().isInDungeon) {
+ overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems));
+ } else if (NotEnoughUpdates.INSTANCE.config.mining.forgeDisplayEnabledLocations == 2) {
+ overlayStrings.addAll(getForgeStrings(profileConfig.forgeItems));
+ }
}
}
}
- if (overlayStrings.isEmpty()) overlayStrings = null;
+ if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
private static List<String> getForgeStrings(List<ForgeItem> forgeItems) {
@@ -851,6 +806,7 @@ public class MiningOverlay extends TextOverlay {
.getItemInformation()
.get("ANVIL"))
);
+ put("First Event", new ItemStack(Items.fireworks, 1, 0));
}};
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningSkillOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningSkillOverlay.java
index fb7cdab5..a20b1d27 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningSkillOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/MiningSkillOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -358,4 +377,4 @@ public class MiningSkillOverlay
if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java
index 8c25594e..fef11a45 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/OverlayManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import com.google.common.collect.Lists;
@@ -31,8 +50,8 @@ public class OverlayManager {
"\u00a73Fetchur: \u00a7eReady!",
"\u00a73Commissions: \u00a7eReady!",
"\u00a73Experiments: \u00a7eReady!",
- "\u00a73Daily Mithril Powder: \u00a7eReady",
- "\u00a73Daily Gemstone Powder: \u00a7eReady",
+ "\u00a73Mithril Powder: \u00a7eReady",
+ "\u00a73Gemstone Powder: \u00a7eReady",
"\u00a73Cakes: \u00a7e1d21h",
"\u00a73Cookie Buff: \u00a7e2d23h",
"\u00a73Godpot: \u00a7e19h",
@@ -40,8 +59,8 @@ public class OverlayManager {
"\u00a73Fetchur: \u00a7e3h38m",
"\u00a73Commissions: \u00a7e3h38m",
"\u00a73Experiments: \u00a7e3h38m",
- "\u00a73Daily Mithril Powder: \u00a7e3h38m",
- "\u00a73Daily Gemstone Powder: \u00a7e3h38m"
+ "\u00a73Mithril Powder: \u00a7e3h38m",
+ "\u00a73Gemstone Powder: \u00a7e3h38m"
);
textOverlays.add(
timersOverlay = new TimersOverlay(NotEnoughUpdates.INSTANCE.config.miscOverlays.todoPosition, () -> {
@@ -81,7 +100,7 @@ public class OverlayManager {
List<String> farmingDummy = Lists.newArrayList(
"\u00a7bCounter: \u00a7e37,547,860",
"\u00a7bCrops/m: \u00a7e38.29",
- "\u00a7bFarm: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bFarming: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
"\u00a7bCurrent XP: \u00a7e6,734",
"\u00a7bRemaining XP: \u00a7e3,265",
"\u00a7bXP/h: \u00a7e238,129",
@@ -103,7 +122,7 @@ public class OverlayManager {
List<String> miningSkillDummy = Lists.newArrayList(
"\u00a7bCompact: \u00a7e547,860",
"\u00a7bBlocks/m: \u00a7e38.29",
- "\u00a7bMine: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
+ "\u00a7bMining: \u00a7e12\u00a77 [\u00a7e|||||||||||||||||\u00a78||||||||\u00a77] \u00a7e67%",
"\u00a7bCurrent XP: \u00a7e6,734",
"\u00a7bRemaining XP: \u00a7e3,265",
"\u00a7bXP/h: \u00a7e238,129",
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/RancherBootOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/RancherBootOverlay.java
index 94bd53a2..2a30f6f1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/RancherBootOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/RancherBootOverlay.java
@@ -1,7 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.core.GuiElementTextField;
import io.github.moulberry.notenoughupdates.core.util.GuiElementSlider;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiEditSign;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Gui;
@@ -31,7 +51,7 @@ public class RancherBootOverlay {
if (!(Minecraft.getMinecraft().currentScreen instanceof GuiEditSign)) return false;
- TileEntitySign tes = ((GuiEditSign) Minecraft.getMinecraft().currentScreen).tileSign;
+ TileEntitySign tes = ((AccessorGuiEditSign) Minecraft.getMinecraft().currentScreen).getTileSign();
if (tes == null) return false;
if (tes.getPos().getY() != 0) return false;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/SlayerOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/SlayerOverlay.java
index 89fce0f2..00e13016 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/SlayerOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/SlayerOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -8,7 +27,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.util.EnumChatFormatting;
import java.text.NumberFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
import java.util.function.Supplier;
public class SlayerOverlay extends TextOverlay {
@@ -66,6 +89,9 @@ public class SlayerOverlay extends TextOverlay {
case "Enderman":
if (!locrawLocation.equals("combat_3")) return false;
break;
+ case "Blaze":
+ if (!locrawLocation.equals("crimson_isle")) return false;
+ break;
default:
//A new slayer would need an update (see SBInfo)
return false;
@@ -97,10 +123,11 @@ public class SlayerOverlay extends TextOverlay {
slayerIntXP = 0;
isSlayerNine = false;
}
- //System.out.println(slayerEXP);
+
if (SBInfo.getInstance().slayer.equals("Tarantula") || SBInfo.getInstance().slayer.equals("Revenant")) {
useSmallXpNext = true;
- } else if (SBInfo.getInstance().slayer.equals("Sven") || SBInfo.getInstance().slayer.equals("Enderman")) {
+ } else if (SBInfo.getInstance().slayer.equals("Sven") || SBInfo.getInstance().slayer.equals("Enderman") ||
+ SBInfo.getInstance().slayer.equals("Blaze")) {
useSmallXpNext = false;
}
switch (slayerLVL) {
@@ -185,7 +212,7 @@ public class SlayerOverlay extends TextOverlay {
HashMap<Integer, String> lineMap = new HashMap<>();
NumberFormat format = NumberFormat.getIntegerInstance();
- //System.out.println(SBInfo.getInstance().isSlain);
+
overlayStrings = new ArrayList<>();
lineMap.put(
0,
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlay.java
index 5fe066f2..f8e02fef 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.core.config.Position;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlayStyle.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlayStyle.java
index 4a3a2b73..2ccc3ace 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlayStyle.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextOverlayStyle.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
public enum TextOverlayStyle {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextTabOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextTabOverlay.java
new file mode 100644
index 00000000..fa263db7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TextTabOverlay.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.overlays;
+
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiChat;
+import org.lwjgl.input.Keyboard;
+
+import java.util.List;
+import java.util.function.Supplier;
+
+public abstract class TextTabOverlay extends TextOverlay {
+ public TextTabOverlay(
+ Position position,
+ Supplier<List<String>> dummyStrings,
+ Supplier<TextOverlayStyle> styleSupplier
+ ) {
+ super(position, dummyStrings, styleSupplier);
+ }
+
+ private boolean lastTabState = false;
+ private boolean shouldUpdateOverlay = true;
+
+ @Override
+ public void tick() {
+ if (shouldUpdateOverlay) {
+ update();
+ }
+ }
+
+ public void realTick() {
+ shouldUpdateOverlay = shouldUpdate();
+ if (shouldUpdateOverlay) {
+ int keycode = Minecraft.getMinecraft().gameSettings.keyBindPlayerList.getKeyCode();
+ boolean currentTabState;
+ if (keycode > 0) {
+ currentTabState = Keyboard.isKeyDown(keycode);
+ } else {
+ currentTabState = false;
+ }
+ if (lastTabState != currentTabState) {
+ lastTabState = currentTabState;
+ update();
+ }
+ }
+ }
+
+ private boolean shouldUpdate() {
+ //prevent rendering when tab completing a command
+ if (Minecraft.getMinecraft().currentScreen instanceof GuiChat) {
+ return false;
+ }
+
+ //prevent rendering when tab completing in ah search overlay
+ if (AuctionSearchOverlay.shouldReplace()) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
index ede30448..4d82ebaf 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/overlays/TimersOverlay.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
@@ -13,10 +32,12 @@ import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector2f;
import java.time.ZoneId;
@@ -30,7 +51,7 @@ import java.util.regex.Pattern;
import static net.minecraft.util.EnumChatFormatting.DARK_AQUA;
-public class TimersOverlay extends TextOverlay {
+public class TimersOverlay extends TextTabOverlay {
private static final Pattern PATTERN_ACTIVE_EFFECTS = Pattern.compile(
"\u00a7r\u00a7r\u00a77You have a \u00a7r\u00a7cGod Potion \u00a7r\u00a77active! \u00a7r\u00a7d([0-9]*?:?[0-9]*?:?[0-9]*)\u00a7r");
@@ -176,16 +197,21 @@ public class TimersOverlay extends TextOverlay {
case "Cookie Buff":
icon = COOKIE_ICON;
break;
- case "Daily Mithril Powder":
+ case "Mithril Powder":
icon = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
.getItemInformation()
.get("MITHRIL_ORE"));
break;
- case "Daily Gemstone Powder":
+ case "Gemstone Powder":
icon = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
.getItemInformation()
.get("PERFECT_AMETHYST_GEM"));
break;
+ case "Heavy Pearls":
+ icon = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("HEAVY_PEARL"));
+ break;
}
if (icon != null) {
@@ -209,6 +235,12 @@ public class TimersOverlay extends TextOverlay {
NEUConfig.HiddenProfileSpecific hidden = NotEnoughUpdates.INSTANCE.config.getProfileSpecific();
if (hidden == null) return;
+ if (NotEnoughUpdates.INSTANCE.config.miscOverlays.todoOverlayOnlyShowTab &&
+ !Keyboard.isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindPlayerList.getKeyCode())) {
+ overlayStrings = null;
+ return;
+ }
+
if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
ContainerChest container = (ContainerChest) chest.inventorySlots;
@@ -529,6 +561,7 @@ public class TimersOverlay extends TextOverlay {
}
long midnightReset = (currentTime - 18000000) / 86400000 * 86400000 + 18000000; // 12am est
+ long pearlsReset = midnightReset - 18000000; //8pm est
long catacombsReset = currentTime / 86400000 * 86400000; // 7pm est
long timeDiffMidnightNow = midnightReset + 86400000 - currentTime;
long catacombsDiffNow = catacombsReset + 86400000 - currentTime;
@@ -627,7 +660,7 @@ public class TimersOverlay extends TextOverlay {
6,
DARK_AQUA + "Experiments: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.verySoonColour] +
- Utils.prettyTime(catacombsReset)
+ Utils.prettyTime(catacombsReset + 86400000 - currentTime)
);
} else if (NotEnoughUpdates.INSTANCE.config.miscOverlays.experimentationDisplay >= DISPLAYTYPE.SOON.ordinal() &&
(hidden.experimentsCompleted < (midnightReset - TimeEnums.HOUR.time))) {
@@ -635,7 +668,7 @@ public class TimersOverlay extends TextOverlay {
6,
DARK_AQUA + "Experiments: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.soonColour] +
- Utils.prettyTime(catacombsReset)
+ Utils.prettyTime(catacombsReset + 86400000 - currentTime)
);
} else if (
NotEnoughUpdates.INSTANCE.config.miscOverlays.experimentationDisplay >= DISPLAYTYPE.KINDASOON.ordinal() &&
@@ -644,14 +677,14 @@ public class TimersOverlay extends TextOverlay {
6,
DARK_AQUA + "Experiments: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.kindaSoonColour] +
- Utils.prettyTime(catacombsReset)
+ Utils.prettyTime(catacombsReset + 86400000 - currentTime)
);
} else if (NotEnoughUpdates.INSTANCE.config.miscOverlays.experimentationDisplay >= DISPLAYTYPE.ALWAYS.ordinal()) {
map.put(
6,
DARK_AQUA + "Experiments: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.defaultColour] +
- Utils.prettyTime(catacombsReset)
+ Utils.prettyTime(catacombsReset + 86400000 - currentTime)
);
}
@@ -661,7 +694,7 @@ public class TimersOverlay extends TextOverlay {
if (hidden.dailyMithrilPowerCompleted < midnightReset) {
map.put(
7,
- DARK_AQUA + "Daily Mithril Powder: " +
+ DARK_AQUA + "Mithril Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.readyColour] + "Ready!"
);
} else if (
@@ -669,7 +702,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyMithrilPowerCompleted < (midnightReset - TimeEnums.HALFANHOUR.time))) {
map.put(
7,
- DARK_AQUA + "Daily Mithril Powder: " +
+ DARK_AQUA + "Mithril Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.verySoonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -677,7 +710,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyMithrilPowerCompleted < (midnightReset - TimeEnums.HOUR.time))) {
map.put(
7,
- DARK_AQUA + "Daily Mithril Powder: " +
+ DARK_AQUA + "Mithril Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.soonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -686,7 +719,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyMithrilPowerCompleted < (midnightReset - (TimeEnums.HOUR.time * 3)))) {
map.put(
7,
- DARK_AQUA + "Daily Mithril Powder: " +
+ DARK_AQUA + "Mithril Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.kindaSoonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -694,7 +727,7 @@ public class TimersOverlay extends TextOverlay {
DISPLAYTYPE.ALWAYS.ordinal()) {
map.put(
7,
- DARK_AQUA + "Daily Mithril Powder: " +
+ DARK_AQUA + "Mithril Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.defaultColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -704,7 +737,7 @@ public class TimersOverlay extends TextOverlay {
if (hidden.dailyGemstonePowderCompleted < midnightReset) {
map.put(
8,
- DARK_AQUA + "Daily Gemstone Powder: " +
+ DARK_AQUA + "Gemstone Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.readyColour] + "Ready!"
);
} else if (
@@ -712,7 +745,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyGemstonePowderCompleted < (midnightReset - TimeEnums.HALFANHOUR.time))) {
map.put(
8,
- DARK_AQUA + "Daily Gemstone Powder: " +
+ DARK_AQUA + "Gemstone Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.verySoonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -720,7 +753,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyGemstonePowderCompleted < (midnightReset - TimeEnums.HOUR.time))) {
map.put(
8,
- DARK_AQUA + "Daily Gemstone Powder: " +
+ DARK_AQUA + "Gemstone Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.soonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -729,7 +762,7 @@ public class TimersOverlay extends TextOverlay {
(hidden.dailyGemstonePowderCompleted < (midnightReset - (TimeEnums.HOUR.time * 3)))) {
map.put(
8,
- DARK_AQUA + "Daily Gemstone Powder: " +
+ DARK_AQUA + "Gemstone Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.kindaSoonColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
@@ -737,12 +770,55 @@ public class TimersOverlay extends TextOverlay {
DISPLAYTYPE.ALWAYS.ordinal()) {
map.put(
8,
- DARK_AQUA + "Daily Gemstone Powder: " +
+ DARK_AQUA + "Gemstone Powder: " +
EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.defaultColour] +
Utils.prettyTime(timeDiffMidnightNow)
);
}
+ //Daily Heavy Pearl Display
+ if (hidden.dailyHeavyPearlCompleted < pearlsReset) {
+ map.put(
+ 9,
+ DARK_AQUA + "Heavy Pearls: " +
+ EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.readyColour] + "Ready!"
+ );
+ } else if (
+ NotEnoughUpdates.INSTANCE.config.miscOverlays.dailyHeavyPearlDisplay >= DISPLAYTYPE.VERYSOON.ordinal() &&
+ (hidden.dailyHeavyPearlCompleted < (pearlsReset - TimeEnums.HALFANHOUR.time))) {
+ map.put(
+ 9,
+ DARK_AQUA + "Heavy Pearls: " +
+ EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.verySoonColour] +
+ Utils.prettyTime(pearlsReset + 86400000 - currentTime)
+ );
+ } else if (NotEnoughUpdates.INSTANCE.config.miscOverlays.dailyHeavyPearlDisplay >= DISPLAYTYPE.SOON.ordinal() &&
+ (hidden.dailyHeavyPearlCompleted < (pearlsReset - TimeEnums.HOUR.time))) {
+ map.put(
+ 9,
+ DARK_AQUA + "Heavy Pearls: " +
+ EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.soonColour] +
+ Utils.prettyTime(pearlsReset + 86400000 - currentTime)
+ );
+ } else if (
+ NotEnoughUpdates.INSTANCE.config.miscOverlays.dailyHeavyPearlDisplay >= DISPLAYTYPE.KINDASOON.ordinal() &&
+ (hidden.dailyHeavyPearlCompleted < (pearlsReset - (TimeEnums.HOUR.time * 3)))) {
+ map.put(
+ 9,
+ DARK_AQUA + "Heavy Pearls: " +
+ EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.kindaSoonColour] +
+ Utils.prettyTime(pearlsReset + 86400000 - currentTime)
+ );
+ } else if (NotEnoughUpdates.INSTANCE.config.miscOverlays.dailyHeavyPearlDisplay >=
+ DISPLAYTYPE.ALWAYS.ordinal()) {
+ map.put(
+ 9,
+ DARK_AQUA + "Heavy Pearls: " +
+ EnumChatFormatting.values()[NotEnoughUpdates.INSTANCE.config.miscOverlays.defaultColour] +
+ Utils.prettyTime(pearlsReset + 86400000 - currentTime)
+ );
+ }
+
overlayStrings = new ArrayList<>();
for (int index : NotEnoughUpdates.INSTANCE.config.miscOverlays.todoText2) {
if (map.containsKey(index)) {
@@ -752,8 +828,41 @@ public class TimersOverlay extends TextOverlay {
if (overlayStrings.isEmpty()) overlayStrings = null;
}
- public String compactRemaining(int amount) {
- return (5 - amount) + " remaining";
+ public static int beforePearls = -1;
+ public static int afterPearls = -1;
+ public static int availablePearls = -1;
+
+ public static int heavyPearlCount() {
+ int heavyPearls = 0;
+
+ List<ItemStack> inventory = Minecraft.getMinecraft().thePlayer.inventoryContainer.getInventory();
+ for (ItemStack item : inventory) {
+ if (item == null) {
+ continue;
+ } else if (!item.hasTagCompound()) {
+ continue;
+ }
+ NBTTagCompound itemData = item.getSubCompound("ExtraAttributes", false);
+ if (itemData == null) {
+ continue;
+ }
+ if (itemData.getString("id").equals("HEAVY_PEARL")) {
+ heavyPearls += item.stackSize;
+ }
+ }
+ return heavyPearls;
+ }
+
+ public static void processActionBar(String msg) {
+ if (SBInfo.getInstance().location.equals("Belly of the Beast")) {
+ try {
+ msg = Utils.cleanColour(msg);
+ msg = msg.substring(msg.indexOf("Pearls Collected: ") + 18);
+ availablePearls = Integer.parseInt(msg.substring(msg.indexOf("/") + 1));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
}
private enum TimeEnums {
@@ -777,4 +886,3 @@ public class TimersOverlay extends TextOverlay {
ALWAYS,
}
}
-
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java
new file mode 100644
index 00000000..a72e0a24
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BasicPage.java
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.common.base.Splitter;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.mojang.authlib.GameProfile;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.lily.LilyWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.senither.SenitherWeight;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.PronounDB;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityOtherPlayerMP;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.enchantment.Enchantment;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EnumPlayerModelParts;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import static io.github.moulberry.notenoughupdates.util.Utils.roundToNearestInt;
+
+public class BasicPage extends GuiProfileViewerPage {
+
+ private static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png");
+ private static final ExecutorService profileLoader = Executors.newFixedThreadPool(1);
+ public EntityOtherPlayerMP entityPlayer = null;
+ private ResourceLocation playerLocationSkin = null;
+ private ResourceLocation playerLocationCape = null;
+ private String skinType = null;
+ private boolean loadingProfile = false;
+
+ private int backgroundClickedX = -1;
+
+ public BasicPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ String location = null;
+ JsonObject status = profile.getPlayerStatus();
+ if (status != null && status.has("mode")) {
+ location = status.get("mode").getAsString();
+ }
+
+ int extraRotation = 0;
+ if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
+ if (backgroundClickedX == -1) {
+ if (mouseX > guiLeft + 23 && mouseX < guiLeft + 23 + 81) {
+ if (mouseY > guiTop + 44 && mouseY < guiTop + 44 + 108) {
+ backgroundClickedX = mouseX;
+ }
+ }
+ }
+ } else {
+ if (backgroundClickedX != -1) {
+ getInstance().backgroundRotation += mouseX - backgroundClickedX;
+ backgroundClickedX = -1;
+ }
+ }
+ if (backgroundClickedX == -1) {
+ getInstance().backgroundRotation += (getInstance().currentTime - getInstance().lastTime) / 400f;
+ } else {
+ extraRotation = mouseX - backgroundClickedX;
+ }
+ getInstance().backgroundRotation %= 360;
+
+ String panoramaIdentifier = "day";
+ if (SBInfo.getInstance().currentTimeDate != null) {
+ if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
+ panoramaIdentifier = "night";
+ }
+ }
+
+ Panorama.drawPanorama(
+ -getInstance().backgroundRotation - extraRotation,
+ guiLeft + 23,
+ guiTop + 44,
+ 81,
+ 108,
+ 0.37f,
+ 0.8f,
+ Panorama.getPanoramasForLocation(location == null ? "unknown" : location, panoramaIdentifier)
+ );
+
+ if (Utils.isWithinRect(mouseX, mouseY, guiLeft + 23, guiTop + 44, 81, 108)) {
+ Optional<PronounDB.PronounChoice> pronounChoice =
+ GuiProfileViewer.pronouns
+ .peekValue()
+ .flatMap(it -> it); // Flatten: First optional is whether it loaded, second optional is whether it was successful
+ if (pronounChoice.isPresent()) {
+ PronounDB.PronounChoice pronouns = pronounChoice.get();
+ if (pronouns.isConsciousChoice()) {
+ getInstance().tooltipToDisplay = pronouns.render();
+ }
+ }
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ if (entityPlayer != null && profile.getHypixelProfile() != null) {
+ String playerName = null;
+ if (profile.getHypixelProfile().has("prefix")) {
+ playerName = Utils.getElementAsString(profile.getHypixelProfile().get("prefix"), "") + " " +
+ entityPlayer.getName();
+ } else {
+ String rank = Utils.getElementAsString(
+ profile.getHypixelProfile().get("rank"),
+ Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE")
+ );
+ String monthlyPackageRank = Utils.getElementAsString(
+ profile.getHypixelProfile().get("monthlyPackageRank"),
+ "NONE"
+ );
+ if (!rank.equals("YOUTUBER") && !monthlyPackageRank.equals("NONE")) {
+ rank = monthlyPackageRank;
+ }
+ EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName(
+ Utils.getElementAsString(profile.getHypixelProfile().get("rankPlusColor"), "GOLD")
+ );
+ String rankPlusColor = EnumChatFormatting.GOLD.toString();
+ if (rankPlusColorECF != null) {
+ rankPlusColor = rankPlusColorECF.toString();
+ }
+
+ JsonObject misc = Constants.MISC;
+ if (misc != null) {
+ if (misc.has("ranks")) {
+ String rankName = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".tag"), null);
+ String rankColor = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".color"), "7");
+ String rankPlus = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".plus"), "");
+
+ String name = entityPlayer.getName();
+
+ if (misc.has("special_bois")) {
+ JsonArray special_bois = misc.get("special_bois").getAsJsonArray();
+ for (int i = 0; i < special_bois.size(); i++) {
+ if (special_bois.get(i).getAsString().equals(profile.getUuid())) {
+ name = Utils.chromaString(name);
+ break;
+ }
+ }
+ }
+
+ playerName = EnumChatFormatting.GRAY + name;
+ if (rankName != null) {
+ playerName =
+ "\u00A7" + rankColor + "[" + rankName + rankPlusColor + rankPlus + "\u00A7" + rankColor + "] " + name;
+ }
+ }
+ }
+ }
+ if (playerName != null) {
+ int rankPrefixLen = fr.getStringWidth(playerName);
+ int halfRankPrefixLen = rankPrefixLen / 2;
+
+ int x = guiLeft + 63;
+ int y = guiTop + 54;
+
+ GuiScreen.drawRect(
+ x - halfRankPrefixLen - 1,
+ y - 1,
+ x + halfRankPrefixLen + 1,
+ y + 8,
+ new Color(0, 0, 0, 64).getRGB()
+ );
+
+ fr.drawString(playerName, x - halfRankPrefixLen, y, 0, true);
+ }
+ }
+
+ long networth = profile.getNetWorth(profileId);
+ if (networth > 0) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.GREEN + "Net Worth: " + EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(networth),
+ fr,
+ guiLeft + 63,
+ guiTop + 38,
+ true,
+ 0
+ );
+ try {
+ double networthInCookies =
+ (
+ networth /
+ NotEnoughUpdates.INSTANCE.manager.auctionManager
+ .getBazaarInfo("BOOSTER_COOKIE")
+ .get("avg_buy")
+ .getAsDouble()
+ );
+ String networthIRLMoney = Long.toString(Math.round(((networthInCookies * 325) / 675) * 4.99));
+ if (
+ mouseX > guiLeft + 8 &&
+ mouseX < guiLeft + 8 + fr.getStringWidth("Net Worth: " + GuiProfileViewer.numberFormat.format(networth))
+ ) {
+ if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + fr.FONT_HEIGHT) {
+ getInstance().tooltipToDisplay = new ArrayList<>();
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Net worth in IRL money: " +
+ EnumChatFormatting.DARK_GREEN +
+ "$" +
+ EnumChatFormatting.GOLD +
+ networthIRLMoney
+ );
+ getInstance().tooltipToDisplay.add("");
+ if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "This is calculated using the current");
+ getInstance().tooltipToDisplay.add(
+ EnumChatFormatting.RED + "price of booster cookies on bazaar and the price");
+ getInstance().tooltipToDisplay.add(
+ EnumChatFormatting.RED + "for cookies using gems, then the price of gems");
+ getInstance().tooltipToDisplay.add(
+ EnumChatFormatting.RED + "is where we get the amount of IRL money you");
+ getInstance().tooltipToDisplay.add(
+ EnumChatFormatting.RED + "theoretically have on skyblock in net worth.");
+ } else {
+ getInstance().tooltipToDisplay.add(EnumChatFormatting.GRAY + "[SHIFT for Info]");
+ }
+ if (!NotEnoughUpdates.INSTANCE.config.hidden.dev) {
+ getInstance().tooltipToDisplay.add("");
+ getInstance().tooltipToDisplay.add(EnumChatFormatting.RED + "THIS IS IN NO WAY ENDORSING IRL TRADING!");
+ }
+ }
+ }
+ } catch (Exception ignored) {
+ }
+ }
+
+ if (status != null) {
+ JsonElement onlineElement = Utils.getElement(status, "online");
+ boolean online = onlineElement != null && onlineElement.isJsonPrimitive() && onlineElement.getAsBoolean();
+ String statusStr = online ? EnumChatFormatting.GREEN + "ONLINE" : EnumChatFormatting.RED + "OFFLINE";
+ String locationStr = null;
+ if (profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) {
+ locationStr = "Ignoring DMs";
+ } else if (profile.getUuid().equals("b876ec32e396476ba1158438d83c67d4")) {
+ statusStr = EnumChatFormatting.LIGHT_PURPLE + "Long live Potato King";
+ ItemStack potato_crown = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("POTATO_CROWN")
+ );
+ potato_crown.addEnchantment(Enchantment.unbreaking, 1656638942); // this number may be useful
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(
+ new ItemStack(Items.potato),
+ guiLeft + 35,
+ guiTop + 160
+ );
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(potato_crown, guiLeft + 50, guiTop + 162);
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(
+ new ItemStack(Items.potato),
+ guiLeft + 63,
+ guiTop + 160
+ );
+ } else if (online) {
+ locationStr = NotEnoughUpdates.INSTANCE.navigation.getNameForAreaModeOrUnknown(location);
+ }
+ if (locationStr != null) {
+ statusStr += EnumChatFormatting.GRAY + " - " + EnumChatFormatting.GREEN + locationStr;
+ }
+
+ Utils.drawStringCentered(statusStr, fr, guiLeft + 63, guiTop + 160, true, 0);
+ }
+
+ if (entityPlayer == null) {
+ if (!loadingProfile || ((ThreadPoolExecutor) profileLoader).getActiveCount() == 0) {
+ loadingProfile = true;
+ UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid()));
+
+ profileLoader.submit(() -> {
+ GameProfile fakeProfile = Minecraft
+ .getMinecraft()
+ .getSessionService()
+ .fillProfileProperties(new GameProfile(playerUUID, "CoolGuy123"), false);
+ entityPlayer =
+ new EntityOtherPlayerMP(Minecraft.getMinecraft().theWorld, fakeProfile) {
+ public ResourceLocation getLocationSkin() {
+ return playerLocationSkin == null
+ ? DefaultPlayerSkin.getDefaultSkin(this.getUniqueID())
+ : playerLocationSkin;
+ }
+
+ public ResourceLocation getLocationCape() {
+ return playerLocationCape;
+ }
+
+ public String getSkinType() {
+ return skinType == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : skinType;
+ }
+ };
+ entityPlayer.setAlwaysRenderNameTag(false);
+ entityPlayer.setCustomNameTag("");
+ });
+ }
+ } else {
+ entityPlayer.refreshDisplayName();
+ byte b = 0;
+ for (EnumPlayerModelParts part : EnumPlayerModelParts.values()) {
+ b |= part.getPartMask();
+ }
+ entityPlayer.getDataWatcher().updateObject(10, b);
+ }
+
+ JsonObject profileInfo = profile.getProfileInformation(profileId);
+ if (profileInfo == null) return;
+
+ Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profileId);
+ JsonObject inventoryInfo = profile.getInventoryInfo(profileId);
+
+ if (entityPlayer != null) {
+ if (backgroundClickedX != -1 && Mouse.isButtonDown(1)) {
+ Arrays.fill(entityPlayer.inventory.armorInventory, null);
+ } else {
+ if (inventoryInfo != null && inventoryInfo.has("inv_armor")) {
+ JsonArray items = inventoryInfo.get("inv_armor").getAsJsonArray();
+ if (items != null && items.size() == 4) {
+ for (int i = 0; i < entityPlayer.inventory.armorInventory.length; i++) {
+ JsonElement itemElement = items.get(i);
+ if (itemElement != null && itemElement.isJsonObject()) {
+ entityPlayer.inventory.armorInventory[i] =
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(itemElement.getAsJsonObject(), false);
+ }
+ }
+ }
+ } else {
+ Arrays.fill(entityPlayer.inventory.armorInventory, null);
+ }
+ }
+ if (entityPlayer.getUniqueID().toString().equals("ae6193ab-494a-4719-b6e7-d50392c8f012")) {
+ entityPlayer.inventory.armorInventory[3] =
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SMALL_BACKPACK")
+ );
+ }
+ }
+
+ if (entityPlayer != null && playerLocationSkin == null) {
+ try {
+ Minecraft
+ .getMinecraft()
+ .getSkinManager()
+ .loadProfileTextures(
+ entityPlayer.getGameProfile(),
+ (type, location1, profileTexture) -> {
+ switch (type) {
+ case SKIN:
+ playerLocationSkin = location1;
+ skinType = profileTexture.getMetadata("model");
+
+ if (skinType == null) {
+ skinType = "default";
+ }
+
+ break;
+ case CAPE:
+ playerLocationCape = location1;
+ }
+ },
+ false
+ );
+ } catch (Exception ignored) {
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ JsonObject petsInfo = profile.getPetsInfo(profileId);
+ if (petsInfo != null) {
+ JsonElement activePetElement = petsInfo.get("active_pet");
+ if (activePetElement != null && activePetElement.isJsonObject()) {
+ JsonObject activePet = activePetElement.getAsJsonObject();
+
+ String type = activePet.get("type").getAsString();
+
+ for (int i = 0; i < 4; i++) {
+ JsonObject item = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(type + ";" + i);
+ if (item != null) {
+ int x = guiLeft + 20;
+ float y =
+ guiTop +
+ 82 +
+ 15 *
+ (float) Math.sin(((getInstance().currentTime - getInstance().startTime) / 800f) % (2 * Math.PI));
+ GlStateManager.translate(x, y, 0);
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false);
+
+ //Remove extra attributes so no CIT
+ NBTTagCompound stackTag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound();
+ stackTag.removeTag("ExtraAttributes");
+ stack.setTagCompound(stackTag);
+
+ GlStateManager.scale(1.5f, 1.5f, 1);
+ GlStateManager.enableDepth();
+ Utils.drawItemStack(stack, 0, 0);
+ GlStateManager.scale(1 / 1.5f, 1 / 1.5f, 1);
+ GlStateManager.translate(-x, -y, 0);
+ break;
+ }
+ }
+ }
+ }
+ if (entityPlayer != null) {
+ drawEntityOnScreen(
+ guiLeft + 63,
+ guiTop + 128 + 7,
+ 36,
+ guiLeft + 63 - mouseX,
+ guiTop + 129 - mouseY,
+ entityPlayer
+ );
+ }
+
+ PlayerStats.Stats stats = profile.getStats(profileId);
+
+ if (stats != null) {
+ Splitter splitter = Splitter.on(" ").omitEmptyStrings().limit(2);
+ for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) {
+ String statName = PlayerStats.defaultStatNames[i];
+ //if (statName.equals("mining_fortune") || statName.equals("mining_speed")) continue;
+ String statNamePretty = PlayerStats.defaultStatNamesPretty[i];
+
+ int val = Math.round(stats.get(statName));
+
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(
+ GL11.GL_SRC_ALPHA,
+ GL11.GL_ONE_MINUS_SRC_ALPHA,
+ GL11.GL_ONE,
+ GL11.GL_ONE_MINUS_SRC_ALPHA
+ );
+ Utils.renderAlignedString(
+ statNamePretty,
+ EnumChatFormatting.WHITE.toString() + val,
+ guiLeft + 132,
+ guiTop + 21 + 11f * i,
+ 80
+ );
+
+ if (mouseX > guiLeft + 132 && mouseX < guiLeft + 212) {
+ if (mouseY > guiTop + 21 + 11f * i && mouseY < guiTop + 37 + 11f * i) {
+ List<String> split = splitter.splitToList(statNamePretty);
+ PlayerStats.Stats baseStats = PlayerStats.getBaseStats();
+ getInstance().tooltipToDisplay = new ArrayList<>();
+ getInstance().tooltipToDisplay.add(statNamePretty);
+ int base = Math.round(baseStats.get(statName));
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GRAY +
+ "Base " +
+ split.get(1) +
+ ": " +
+ EnumChatFormatting.GREEN +
+ base +
+ " " +
+ split.get(0)
+ );
+ int passive = Math.round(profile.getPassiveStats(profileId).get(statName) - baseStats.get(statName));
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GRAY +
+ "Passive " +
+ split.get(1) +
+ " Bonus: +" +
+ EnumChatFormatting.YELLOW +
+ passive +
+ " " +
+ split.get(0)
+ );
+ int itemBonus = Math.round(stats.get(statName) - profile.getPassiveStats(profileId).get(statName));
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GRAY +
+ "Item " +
+ split.get(1) +
+ " Bonus: +" +
+ EnumChatFormatting.DARK_PURPLE +
+ itemBonus +
+ " " +
+ split.get(0)
+ );
+ int finalStat = Math.round(stats.get(statName));
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GRAY +
+ "Final " +
+ split.get(1) +
+ ": +" +
+ EnumChatFormatting.RED +
+ finalStat +
+ " " +
+ split.get(0)
+ );
+ }
+ }
+ }
+ } else {
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "Skill/Inv/Coll",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 172,
+ guiTop + 101 - 10,
+ true,
+ 0
+ );
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "APIs not",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 172,
+ guiTop + 101,
+ true,
+ 0
+ );
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "enabled!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 172,
+ guiTop + 101 + 10,
+ true,
+ 0
+ );
+ }
+
+ if (skyblockInfo != null) {
+ int position = 0;
+ for (Map.Entry<String, ItemStack> entry : ProfileViewer.getSkillToSkillDisplayMap().entrySet()) {
+ if (entry.getValue() == null || entry.getKey() == null) {
+ position++;
+ continue;
+ }
+
+ int yPosition = position % 8;
+ int xPosition = position / 8;
+
+ String skillName = entry.getValue().getDisplayName();
+
+ float level = skyblockInfo.get(entry.getKey()).level;
+ int levelFloored = (int) Math.floor(level);
+
+ int x = guiLeft + 237 + 86 * xPosition;
+ int y = guiTop + 24 + 21 * yPosition;
+
+ Utils.renderAlignedString(skillName, EnumChatFormatting.WHITE.toString() + levelFloored, x + 14, y - 4, 60);
+
+ if (skyblockInfo.get(entry.getKey()).maxed) {
+ getInstance().renderGoldBar(x, y + 6, 80);
+ } else {
+ getInstance().renderBar(x, y + 6, 80, level % 1);
+ }
+
+ if (mouseX > x && mouseX < x + 80) {
+ if (mouseY > y - 4 && mouseY < y + 13) {
+ getInstance().tooltipToDisplay = new ArrayList<>();
+ getInstance().tooltipToDisplay.add(skillName);
+ if (skyblockInfo.get(entry.getKey()).maxed) {
+ getInstance().tooltipToDisplay.add(
+ EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.GOLD + "MAXED!");
+ } else {
+ int maxXp = (int) skyblockInfo.get(entry.getKey()).maxXpForLevel;
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GRAY +
+ "Progress: " +
+ EnumChatFormatting.DARK_PURPLE +
+ StringUtils.shortNumberFormat(Math.round((level % 1) * maxXp)) +
+ "/" +
+ StringUtils.shortNumberFormat(maxXp)
+ );
+ }
+ String totalXpS = GuiProfileViewer.numberFormat.format((int) skyblockInfo.get(entry.getKey()).totalXp);
+ getInstance()
+ .tooltipToDisplay.add(EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE + totalXpS);
+ }
+ }
+
+ GL11.glTranslatef((x), (y - 6f), 0);
+ GL11.glScalef(0.7f, 0.7f, 1);
+ Utils.drawItemStackLinear(entry.getValue(), 0, 0);
+ GL11.glScalef(1 / 0.7f, 1 / 0.7f, 1);
+ GL11.glTranslatef(-(x), -(y - 6f), 0);
+
+ position++;
+ }
+ } else {
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "Skills API not enabled!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 322,
+ guiTop + 101,
+ true,
+ 0
+ );
+ }
+
+ renderWeight(mouseX, mouseY, skyblockInfo, profileInfo);
+ }
+
+ @Override
+ public void resetCache() {
+ entityPlayer = null;
+ playerLocationSkin = null;
+ playerLocationCape = null;
+ skinType = null;
+ }
+
+ private String niceUuid(String uuidStr) {
+ if (uuidStr.length() != 32) return uuidStr;
+
+ return (
+ uuidStr.substring(0, 8) +
+ "-" +
+ uuidStr.substring(8, 12) +
+ "-" +
+ uuidStr.substring(12, 16) +
+ "-" +
+ uuidStr.substring(16, 20) +
+ "-" +
+ uuidStr.substring(20, 32)
+ );
+ }
+
+ private void renderWeight(
+ int mouseX,
+ int mouseY,
+ Map<String, ProfileViewer.Level> skyblockInfo,
+ JsonObject profileInfo
+ ) {
+ if (skyblockInfo == null) {
+ return;
+ }
+
+ if (Constants.WEIGHT == null || Utils.getElement(Constants.WEIGHT, "lily.skills.overall") == null ||
+ !Utils.getElement(Constants.WEIGHT, "lily.skills.overall").isJsonPrimitive()) {
+ Utils.showOutdatedRepoNotification();
+ return;
+ }
+
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ SenitherWeight senitherWeight = new SenitherWeight(skyblockInfo);
+ LilyWeight lilyWeight = new LilyWeight(skyblockInfo, profileInfo);
+
+ Utils.drawStringCentered(
+ EnumChatFormatting.GREEN +
+ "Senither Weight: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw())),
+ fr,
+ guiLeft + 63,
+ guiTop + 18,
+ true,
+ 0
+ );
+
+ int textWidth = fr.getStringWidth(
+ "Senither Weight: " +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight.getTotalWeight().getRaw()))
+ );
+ if (mouseX > guiLeft + 63 - textWidth / 2 && mouseX < guiLeft + 63 + textWidth / 2) {
+ if (mouseY > guiTop + 12 && mouseY < guiTop + 12 + fr.FONT_HEIGHT) {
+ getInstance().tooltipToDisplay = new ArrayList<>();
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Skills: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight
+ .getSkillsWeight()
+ .getWeightStruct()
+ .getRaw()))
+ );
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Slayer: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(senitherWeight
+ .getSlayerWeight()
+ .getWeightStruct()
+ .getRaw()))
+ );
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Dungeons: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(
+ roundToNearestInt(senitherWeight.getDungeonsWeight().getWeightStruct().getRaw())
+ )
+ );
+ }
+ }
+
+ Utils.drawStringCentered(
+ EnumChatFormatting.GREEN +
+ "Lily Weight: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw())),
+ fr,
+ guiLeft + 63,
+ guiTop + 28,
+ true,
+ 0
+ );
+
+ int fontWidth = fr.getStringWidth(
+ "Lily Weight: " + GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight.getTotalWeight().getRaw()))
+ );
+ if (mouseX > guiLeft + 63 - fontWidth / 2 && mouseX < guiLeft + 63 + fontWidth / 2) {
+ if (mouseY > guiTop + 22 && mouseY < guiTop + 22 + fr.FONT_HEIGHT) {
+ getInstance().tooltipToDisplay = new ArrayList<>();
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Skills: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight
+ .getSkillsWeight()
+ .getWeightStruct()
+ .getRaw()))
+ );
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Slayer: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight
+ .getSlayerWeight()
+ .getWeightStruct()
+ .getRaw()))
+ );
+ getInstance()
+ .tooltipToDisplay.add(
+ EnumChatFormatting.GREEN +
+ "Dungeons: " +
+ EnumChatFormatting.GOLD +
+ GuiProfileViewer.numberFormat.format(roundToNearestInt(lilyWeight
+ .getDungeonsWeight()
+ .getWeightStruct()
+ .getRaw()))
+ );
+ }
+ }
+ }
+
+ private void drawEntityOnScreen(int posX, int posY, int scale, float mouseX, float mouseY, EntityLivingBase ent) {
+ GlStateManager.enableColorMaterial();
+ GlStateManager.pushMatrix();
+ GlStateManager.translate((float) posX, (float) posY, 50.0F);
+ GlStateManager.scale((float) (-scale), (float) scale, (float) scale);
+ GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
+ float renderYawOffset = ent.renderYawOffset;
+ float f1 = ent.rotationYaw;
+ float f2 = ent.rotationPitch;
+ float f3 = ent.prevRotationYawHead;
+ float f4 = ent.rotationYawHead;
+ GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
+ RenderHelper.enableStandardItemLighting();
+ GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
+ GlStateManager.rotate(25, 1.0F, 0.0F, 0.0F);
+ ent.renderYawOffset = (float) Math.atan(mouseX / 40.0F) * 20.0F;
+ ent.rotationYaw = (float) Math.atan(mouseX / 40.0F) * 40.0F;
+ ent.rotationPitch = -((float) Math.atan(mouseY / 40.0F)) * 20.0F;
+ ent.rotationYawHead = ent.rotationYaw;
+ ent.prevRotationYawHead = ent.rotationYaw;
+ RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
+ rendermanager.setPlayerViewY(180.0F);
+ rendermanager.setRenderShadow(false);
+ rendermanager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F);
+
+ ent.renderYawOffset = renderYawOffset;
+ ent.rotationYaw = f1;
+ ent.rotationPitch = f2;
+ ent.prevRotationYawHead = f3;
+ ent.rotationYawHead = f4;
+ GlStateManager.popMatrix();
+ RenderHelper.disableStandardItemLighting();
+ GlStateManager.disableRescaleNormal();
+ GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
+ GlStateManager.disableTexture2D();
+ GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java
new file mode 100644
index 00000000..ab80afab
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/BingoPage.java
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BingoPage extends GuiProfileViewerPage {
+
+ private static final ResourceLocation BINGO_GUI_TEXTURE = new ResourceLocation("notenoughupdates:pv_bingo_tab.png");
+ private long lastResourceRequest;
+ private List<JsonObject> bingoGoals = null;
+ private int currentEventId;
+
+ public BingoPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ processBingoResources();
+ JsonObject bingoInfo = GuiProfileViewer.getProfile().getBingoInformation();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+ //check if the player has created a bingo profile for the current event
+ if (bingoInfo == null) {
+ showMissingDataMessage(guiLeft, guiTop);
+ return;
+ }
+
+ JsonArray events = bingoInfo.get("events").getAsJsonArray();
+ JsonObject lastEvent = events.get(events.size() - 1).getAsJsonObject();
+ int lastParticipatedId = lastEvent.get("key").getAsInt();
+ if (currentEventId != lastParticipatedId) {
+ showMissingDataMessage(guiLeft, guiTop);
+ return;
+ }
+
+ List<String> completedGoals = jsonArrayToStringList(lastEvent.get("completed_goals").getAsJsonArray());
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BINGO_GUI_TEXTURE);
+ Utils.drawTexturedRect(guiLeft, guiTop, 431, 202, GL11.GL_NEAREST);
+
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+
+ int row = 0;
+ int col = 0;
+ int initialY = guiTop + 46;
+ int initialX = guiLeft + 231;
+ int xAdjustment = 0;
+ int yAdjustment = 0;
+ for (JsonObject bingoGoal : bingoGoals) {
+ boolean dye = false;
+ boolean completed = false;
+ boolean communityGoal = false;
+ Item material;
+ if (bingoGoal.has("tiers")) {
+ if (isCommunityGoalFinished(bingoGoal)) {
+ material = Item.getItemFromBlock(Blocks.emerald_block);
+ } else {
+ material = Item.getItemFromBlock(Blocks.iron_block);
+ }
+ RenderHelper.enableGUIStandardItemLighting();
+ completed = true;
+ communityGoal = true;
+ yAdjustment = -1;
+ xAdjustment = -1;
+ } else {
+ if (completedGoals.contains(bingoGoal.get("id").getAsString())) {
+ material = Items.dye;
+ xAdjustment = -1;
+ dye = true;
+ completed = true;
+ } else {
+ material = Items.paper;
+ }
+ }
+
+ ItemStack itemStack = new ItemStack(material);
+ if (dye) {
+ itemStack.setItemDamage(10);
+ }
+ int x = col == 0 ? initialX + xAdjustment : initialX + (24 * col) + xAdjustment;
+ int y = row == 0 ? initialY + yAdjustment : initialY + (24 * row) + yAdjustment;
+
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y);
+ y = communityGoal ? y - 1 : y;
+ if (mouseX >= x && mouseX < x + 24) {
+ if (mouseY >= y && mouseY <= y + 24) {
+ Utils.drawHoveringText(
+ getTooltip(bingoGoal, completed, communityGoal),
+ mouseX,
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+ col++;
+ if (col == 5) {
+ col = 0;
+ row++;
+ }
+ }
+
+ String totalPointsString =
+ EnumChatFormatting.AQUA + "Collected Points: " + EnumChatFormatting.WHITE + lastEvent.get("points").getAsInt();
+ int totalGoals = completedGoals.size();
+ String personalGoalsString;
+ if (totalGoals == 20) {
+ personalGoalsString = EnumChatFormatting.AQUA + "Personal Goals: " + EnumChatFormatting.GOLD + "20/20";
+ } else {
+ personalGoalsString =
+ EnumChatFormatting.AQUA +
+ "Personal Goals: " +
+ EnumChatFormatting.WHITE +
+ completedGoals.size() +
+ EnumChatFormatting.GOLD +
+ "/" +
+ EnumChatFormatting.WHITE +
+ 20;
+ }
+ Utils.drawStringF(totalPointsString, Minecraft.getMinecraft().fontRendererObj, guiLeft + 22, guiTop + 19, true, 0);
+ Utils.drawStringF(
+ personalGoalsString,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 22,
+ guiTop + 31,
+ true,
+ 0
+ );
+
+ GlStateManager.enableLighting();
+ }
+
+ private boolean isCommunityGoalFinished(JsonObject goal) {
+ JsonArray tiers = goal.get("tiers").getAsJsonArray();
+ int totalTiers = tiers.size();
+ long progress = goal.get("progress").getAsLong();
+ int finalTier = 0;
+ for (JsonElement tier : tiers) {
+ long currentTier = tier.getAsLong();
+ if (progress < currentTier) {
+ break;
+ }
+ finalTier++;
+ }
+ return finalTier == totalTiers;
+ }
+
+ private String generateProgressIndicator(double progress, double goal) {
+ int totalFields = 20;
+ int filled;
+ double percentage = progress / goal * 100;
+ if (percentage >= 100) {
+ filled = 20;
+ } else {
+ filled = (int) Math.round((percentage / 100) * 20);
+ }
+ StringBuilder stringBuilder = new StringBuilder();
+ stringBuilder.append(EnumChatFormatting.DARK_GREEN);
+ for (int i = 0; i < totalFields; i++) {
+ stringBuilder.append("-");
+ if (i > filled) {
+ stringBuilder.append(EnumChatFormatting.GRAY);
+ }
+ }
+
+ return stringBuilder.toString();
+ }
+
+ private List<String> getTooltip(JsonObject goal, boolean completed, boolean communityGoal) {
+ List<String> tooltip = new ArrayList<>();
+ if (communityGoal) {
+ //get current tier
+ JsonArray tiers = goal.get("tiers").getAsJsonArray();
+ int totalTiers = tiers.size();
+ double progress = goal.get("progress").getAsLong();
+ int finalTier = 0;
+ for (JsonElement tier : tiers) {
+ double currentTier = tier.getAsLong();
+ if (progress < currentTier) {
+ break;
+ }
+ finalTier++;
+ }
+ double nextTier = finalTier < totalTiers ? tiers.get(totalTiers - 1).getAsLong() : tiers
+ .get(finalTier - 1)
+ .getAsLong();
+ int progressToNextTier = (int) Math.round(progress / nextTier * 100);
+ if (progressToNextTier > 100) progressToNextTier = 100;
+ String progressBar = generateProgressIndicator(progress, nextTier);
+ String name = goal.get("name").getAsString();
+ int nextTierNum = finalTier < totalTiers ? finalTier + 1 : totalTiers;
+
+ String nextTierString = Utils.shortNumberFormat(nextTier, 0);
+ String progressString = Utils.shortNumberFormat(progress, 0);
+ tooltip.add(EnumChatFormatting.GREEN + name + " " + finalTier);
+ tooltip.add(EnumChatFormatting.DARK_GRAY + "Community Goal");
+ tooltip.add("");
+ tooltip.add(
+ EnumChatFormatting.GRAY +
+ "Progress to " +
+ name +
+ " " +
+ nextTierNum +
+ ": " +
+ EnumChatFormatting.YELLOW +
+ progressToNextTier +
+ EnumChatFormatting.GOLD +
+ "%"
+ );
+ tooltip.add(
+ progressBar +
+ EnumChatFormatting.YELLOW +
+ " " +
+ progressString +
+ EnumChatFormatting.GOLD +
+ "/" +
+ EnumChatFormatting.YELLOW +
+ nextTierString
+ );
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Community Goals are");
+ tooltip.add(
+ EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "collaborative - anyone with a");
+ tooltip.add(
+ EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "Bingo profile can help to reach");
+ tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "the goal!");
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "The more you contribute");
+ tooltip.add(
+ EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "towards the goal, the more you");
+ tooltip.add(EnumChatFormatting.DARK_GRAY.toString() + EnumChatFormatting.ITALIC + "will be rewarded");
+
+ if (finalTier == totalTiers) {
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.GREEN + "GOAL REACHED");
+ }
+ } else {
+ tooltip.add(EnumChatFormatting.GREEN + goal.get("name").getAsString());
+ tooltip.add(EnumChatFormatting.DARK_GRAY + "Personal Goal");
+ tooltip.add("");
+ tooltip.add(goal.get("lore").getAsString());
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.GRAY + "Reward");
+ tooltip.add(EnumChatFormatting.GOLD + "1 Bingo Point");
+ if (completed) {
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.GREEN + "GOAL REACHED");
+ } else {
+ tooltip.add("");
+ tooltip.add(EnumChatFormatting.RED + "You have not reached this goal!");
+ }
+ }
+ return tooltip;
+ }
+
+ private void showMissingDataMessage(int guiLeft, int guiTop) {
+ String message = EnumChatFormatting.RED + "No Bingo data for current event!";
+ Utils.drawStringCentered(
+ message,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 431 / 2f,
+ guiTop + 101,
+ true,
+ 0
+ );
+ }
+
+ private List<String> jsonArrayToStringList(JsonArray completedGoals) {
+ List<String> list = new ArrayList<>();
+ for (JsonElement completedGoal : completedGoals) {
+ list.add(completedGoal.getAsString());
+ }
+ return list;
+ }
+
+ private List<JsonObject> jsonArrayToJsonObjectList(JsonArray goals) {
+ List<JsonObject> list = new ArrayList<>();
+ for (JsonElement goal : goals) {
+ list.add(goal.getAsJsonObject());
+ }
+
+ return list;
+ }
+
+ private void processBingoResources() {
+ long currentTime = System.currentTimeMillis();
+
+ //renew every 2 minutes
+ if (currentTime - lastResourceRequest < 120 * 1000 && bingoGoals != null) return;
+ lastResourceRequest = currentTime;
+
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newAnonymousHypixelApiRequest("resources/skyblock/bingo")
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ bingoGoals = jsonArrayToJsonObjectList(jsonObject.get("goals").getAsJsonArray());
+ currentEventId = jsonObject.get("id").getAsInt();
+ }
+ });
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java
new file mode 100644
index 00000000..554e204c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/CollectionsPage.java
@@ -0,0 +1,495 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.IOException;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+public class CollectionsPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_cols = new ResourceLocation("notenoughupdates:pv_cols.png");
+ public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
+ private static final int COLLS_XCOUNT = 5;
+ private static final int COLLS_YCOUNT = 4;
+ private static final float COLLS_XPADDING = (190 - COLLS_XCOUNT * 20) / (float) (COLLS_XCOUNT + 1);
+ private static final float COLLS_YPADDING = (202 - COLLS_YCOUNT * 20) / (float) (COLLS_YCOUNT + 1);
+ private static final String[] romans = new String[] {
+ "I",
+ "II",
+ "III",
+ "IV",
+ "V",
+ "VI",
+ "VII",
+ "VIII",
+ "IX",
+ "X",
+ "XI",
+ "XII",
+ "XIII",
+ "XIV",
+ "XV",
+ "XVI",
+ "XVII",
+ "XIX",
+ "XX",
+ };
+ private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
+ private static List<String> tooltipToDisplay = null;
+ private static ItemStack selectedCollectionCategory = null;
+ private int page = 0;
+ private int maxPage = 0;
+
+ public CollectionsPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_cols);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ JsonObject collectionInfo = GuiProfileViewer.getProfile().getCollectionInfo(GuiProfileViewer.getProfileId());
+ if (collectionInfo == null) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "Collection API not enabled!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 134,
+ guiTop + 101,
+ true,
+ 0
+ );
+ return;
+ }
+
+ JsonObject resourceCollectionInfo = ProfileViewer.getResourceCollectionInformation();
+ if (resourceCollectionInfo == null) return;
+
+ int collectionCatSize = ProfileViewer.getCollectionCatToCollectionMap().size();
+ int collectionCatYSize = (int) (162f / (collectionCatSize - 1 + 0.0000001f));
+ {
+ int yIndex = 0;
+ for (ItemStack stack : ProfileViewer.getCollectionCatToCollectionMap().keySet()) {
+ if (selectedCollectionCategory == null) selectedCollectionCategory = stack;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ if (stack == selectedCollectionCategory) {
+ Utils.drawTexturedRect(
+ guiLeft + 7,
+ guiTop + 10 + collectionCatYSize * yIndex,
+ 20,
+ 20,
+ 20 / 256f,
+ 0,
+ 20 / 256f,
+ 0,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStackWithText(stack, guiLeft + 10, guiTop + 13 + collectionCatYSize * yIndex, "" + (yIndex + 1));
+ } else {
+ Utils.drawTexturedRect(
+ guiLeft + 7,
+ guiTop + 10 + collectionCatYSize * yIndex,
+ 20,
+ 20,
+ 0,
+ 20 / 256f,
+ 0,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStackWithText(stack, guiLeft + 9, guiTop + 12 + collectionCatYSize * yIndex, "" + (yIndex + 1));
+ }
+ yIndex++;
+ }
+ }
+
+ List<String> collections = ProfileViewer.getCollectionCatToCollectionMap().get(selectedCollectionCategory);
+ List<String> minions = ProfileViewer.getCollectionCatToMinionMap().get(selectedCollectionCategory);
+
+ maxPage = Math.max((collections != null ? collections.size() : 0) / 20, (minions != null ? minions.size() : 0) / 20);
+
+ if (maxPage != 0) {
+ boolean leftHovered = false;
+ boolean rightHovered = false;
+ if (Mouse.isButtonDown(0)) {
+ if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
+ if (mouseX > guiLeft + 100 - 20 - 12 && mouseX < guiLeft + 100 - 20) {
+ leftHovered = true;
+ } else if (mouseX > guiLeft + 100 + 20 + 250 && mouseX < guiLeft + 100 + 20 + 12 + 250) {
+ rightHovered = true;
+ }
+ }
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs);
+
+ if (page > 0) {
+ Utils.drawTexturedRect(
+ guiLeft + 100 - 15 - 12,
+ guiTop + 6,
+ 12,
+ 16,
+ 29 / 256f,
+ 53 / 256f,
+ !leftHovered ? 0 : 32 / 256f,
+ !leftHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+ if (page < 1) {
+ Utils.drawTexturedRect(
+ guiLeft + 100 + 15 + 250,
+ guiTop + 6,
+ 12,
+ 16,
+ 5 / 256f,
+ 29 / 256f,
+ !rightHovered ? 0 : 32 / 256f,
+ !rightHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+ }
+
+ Utils.drawStringCentered(
+ selectedCollectionCategory.getDisplayName() + " Collections",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 134,
+ guiTop + 14,
+ true,
+ 4210752
+ );
+
+ JsonObject minionTiers = collectionInfo.get("minion_tiers").getAsJsonObject();
+ JsonObject collectionTiers = collectionInfo.get("collection_tiers").getAsJsonObject();
+ JsonObject maxAmounts = collectionInfo.get("max_amounts").getAsJsonObject();
+ JsonObject totalAmounts = collectionInfo.get("total_amounts").getAsJsonObject();
+ JsonObject personalAmounts = collectionInfo.get("personal_amounts").getAsJsonObject();
+
+ if (collections != null) {
+ for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, collections.size()); i++, j++) {
+ String collection = collections.get(i);
+ if (collection != null) {
+ ItemStack collectionItem = ProfileViewer.getCollectionToCollectionDisplayMap().get(collection);
+ if (collectionItem != null) {
+ int xIndex = j % COLLS_XCOUNT;
+ int yIndex = j / COLLS_XCOUNT;
+
+ float x = 39 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
+ float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
+
+ String tierString;
+ int tier = (int) Utils.getElementAsFloat(collectionTiers.get(collection), 0);
+ if (tier > 20 || tier < 0) {
+ tierString = String.valueOf(tier);
+ } else {
+ tierString = romans[tier];
+ }
+ float amount = Utils.getElementAsFloat(totalAmounts.get(collection), 0);
+ float maxAmount = Utils.getElementAsFloat(maxAmounts.get(collection), 0);
+ Color color = new Color(128, 128, 128, 255);
+ int tierStringColour = color.getRGB();
+ float completedness = 0;
+ if (maxAmount > 0) {
+ completedness = amount / maxAmount;
+ }
+ completedness = Math.min(1, completedness);
+ if (maxAmounts.has(collection) && completedness >= 1) {
+ tierStringColour = new Color(255, 215, 0).getRGB();
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y,
+ 20,
+ 20 * (1 - completedness),
+ 0,
+ 20 / 256f,
+ 0,
+ 20 * (1 - completedness) / 256f,
+ GL11.GL_NEAREST
+ );
+ GlStateManager.color(1, 185 / 255f, 0, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y + 20 * (1 - completedness),
+ 20,
+ 20 * (completedness),
+ 0,
+ 20 / 256f,
+ 20 * (1 - completedness) / 256f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStack(collectionItem, guiLeft + (int) x + 2, guiTop + (int) y + 2);
+
+ if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
+ if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(
+ collectionItem.getDisplayName() +
+ " " +
+ (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) +
+ tierString
+ );
+ tooltipToDisplay.add(
+ "Collected: " + numberFormat.format(Utils.getElementAsFloat(personalAmounts.get(collection), 0))
+ );
+ tooltipToDisplay.add("Total Collected: " + numberFormat.format(amount));
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ if (tier >= 0) {
+ Utils.drawStringCentered(
+ tierString,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + x + 10,
+ guiTop + y - 4,
+ true,
+ tierStringColour
+ );
+ }
+
+ Utils.drawStringCentered(
+ StringUtils.shortNumberFormat(amount) + "",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + x + 10,
+ guiTop + y + 26,
+ true,
+ color.getRGB()
+ );
+ }
+ }
+ }
+ }
+
+ Utils.drawStringCentered(
+ selectedCollectionCategory.getDisplayName() + " Minions",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 326,
+ guiTop + 14,
+ true,
+ 4210752
+ );
+
+ if (minions != null) {
+ for (int i = page * 20, j = 0; i < Math.min((page + 1) * 20, minions.size()); i++, j++) {
+ String minion = minions.get(i);
+ if (minion != null) {
+ JsonObject misc = Constants.MISC;
+ float MAX_MINION_TIER = Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11);
+
+ int tier = (int) Utils.getElementAsFloat(minionTiers.get(minion), 0);
+ JsonObject minionJson;
+ if (tier == 0) {
+ minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_1");
+ } else {
+ minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_" + tier);
+ }
+
+ if (minionJson != null) {
+ int xIndex = j % COLLS_XCOUNT;
+ int yIndex = j / COLLS_XCOUNT;
+
+ float x = 231 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
+ float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
+
+ String tierString;
+
+ if (tier - 1 >= romans.length || tier - 1 < 0) {
+ tierString = String.valueOf(tier);
+ } else {
+ tierString = romans[tier - 1];
+ }
+
+ Color color = new Color(128, 128, 128, 255);
+ int tierStringColour = color.getRGB();
+ float completedness = tier / MAX_MINION_TIER;
+
+ completedness = Math.min(1, completedness);
+ if (completedness >= 1) {
+ tierStringColour = new Color(255, 215, 0).getRGB();
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y,
+ 20,
+ 20 * (1 - completedness),
+ 0,
+ 20 / 256f,
+ 0,
+ 20 * (1 - completedness) / 256f,
+ GL11.GL_NEAREST
+ );
+ GlStateManager.color(1, 185 / 255f, 0, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y + 20 * (1 - completedness),
+ 20,
+ 20 * (completedness),
+ 0,
+ 20 / 256f,
+ 20 * (1 - completedness) / 256f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ );
+
+ Utils.drawItemStack(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson),
+ guiLeft + (int) x + 2,
+ guiTop + (int) y + 2
+ );
+
+ if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
+ if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
+ tooltipToDisplay =
+ NotEnoughUpdates.INSTANCE.manager
+ .jsonToStack(minionJson)
+ .getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ if (tier >= 0) {
+ Utils.drawStringCentered(
+ tierString,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + x + 10,
+ guiTop + y - 4,
+ true,
+ tierStringColour
+ );
+ }
+ }
+ }
+ }
+ }
+
+ if (tooltipToDisplay != null) {
+ List<String> grayTooltip = new ArrayList<>(tooltipToDisplay.size());
+ for (String line : tooltipToDisplay) {
+ grayTooltip.add(EnumChatFormatting.GRAY + line);
+ }
+ Utils.drawHoveringText(
+ grayTooltip,
+ mouseX,
+ mouseY,
+ getInstance().width,
+ getInstance().height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ tooltipToDisplay = null;
+ }
+ }
+
+ @Override
+ public void keyTyped(char typedChar, int keyCode) throws IOException {
+ ItemStack stack = null;
+ Iterator<ItemStack> items = ProfileViewer.getCollectionCatToCollectionMap().keySet().iterator();
+ switch (keyCode) {
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_NUMPAD5:
+ stack = items.next();
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_NUMPAD4:
+ stack = items.next();
+ case Keyboard.KEY_3:
+ case Keyboard.KEY_NUMPAD3:
+ stack = items.next();
+ case Keyboard.KEY_2:
+ case Keyboard.KEY_NUMPAD2:
+ stack = items.next();
+ case Keyboard.KEY_1:
+ case Keyboard.KEY_NUMPAD1:
+ stack = items.next();
+ }
+ if (stack != null) {
+ selectedCollectionCategory = stack;
+ page = 0;
+ }
+ Utils.playPressSound();
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY, int mouseButton) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ if (maxPage != 0) {
+ if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
+ if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) {
+ if (page > 0) {
+ page--;
+ return;
+ }
+ } else if (mouseX > guiLeft + 100 + 15 + 250 && mouseX < guiLeft + 100 + 20 + 12 + 250) {
+ if (page < 1) {
+ page++;
+ return;
+ }
+ }
+ }
+ }
+
+ int collectionCatSize = ProfileViewer.getCollectionCatToCollectionMap().size();
+ int collectionCatYSize = (int) (162f / (collectionCatSize - 1 + 0.0000001f));
+ int yIndex = 0;
+ for (ItemStack stack : ProfileViewer.getCollectionCatToCollectionMap().keySet()) {
+ if (mouseX > guiLeft + 7 && mouseX < guiLeft + 7 + 20) {
+ if (mouseY > guiTop + 10 + collectionCatYSize * yIndex && mouseY < guiTop + 10 + collectionCatYSize * yIndex + 20) {
+ selectedCollectionCategory = stack;
+ page = 0;
+ Utils.playPressSound();
+ return;
+ }
+ }
+ yIndex++;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java
new file mode 100644
index 00000000..15a70ded
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/DungeonPage.java
@@ -0,0 +1,841 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.UUID;
+
+public class DungeonPage extends GuiProfileViewerPage {
+
+ private static final ResourceLocation pv_dung = new ResourceLocation("notenoughupdates:pv_dung.png");
+ private static final ItemStack DEADBUSH = new ItemStack(Item.getItemFromBlock(Blocks.deadbush));
+ private static final String[] dungSkillsName = { "Healer", "Mage", "Berserk", "Archer", "Tank" };
+ private static final ItemStack[] BOSS_HEADS = new ItemStack[7];
+ private static final ItemStack[] dungSkillsStack = {
+ new ItemStack(Items.potionitem, 1, 16389),
+ new ItemStack(Items.blaze_rod),
+ new ItemStack(Items.iron_sword),
+ new ItemStack(Items.bow),
+ new ItemStack(Items.leather_chestplate),
+ };
+ private static final String[] bossFloorArr = { "Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron" };
+ private static final String[] bossFloorHeads = {
+ "12716ecbf5b8da00b05f316ec6af61e8bd02805b21eb8e440151468dc656549c",
+ "7de7bbbdf22bfe17980d4e20687e386f11d59ee1db6f8b4762391b79a5ac532d",
+ "9971cee8b833a62fc2a612f3503437fdf93cad692d216b8cf90bbb0538c47dd8",
+ "8b6a72138d69fbbd2fea3fa251cabd87152e4f1c97e5f986bf685571db3cc0",
+ "c1007c5b7114abec734206d4fc613da4f3a0e99f71ff949cedadc99079135a0b",
+ "fa06cb0c471c1c9bc169af270cd466ea701946776056e472ecdaeb49f0f4a4dc",
+ "a435164c05cea299a3f016bbbed05706ebb720dac912ce4351c2296626aecd9a",
+ };
+
+ private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() {
+ {
+ put(
+ "catacombs",
+ Utils.editItemStackInfo(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("DUNGEON_STONE")
+ ),
+ EnumChatFormatting.GRAY + "Normal Mode",
+ true
+ )
+ );
+ put(
+ "master_catacombs",
+ Utils.editItemStackInfo(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("MASTER_SKULL_TIER_7")
+ ),
+ EnumChatFormatting.GRAY + "Master Mode",
+ true
+ )
+ );
+ }
+ };
+
+ private static int floorTime = 7;
+ private final HashMap<String, HashMap<String, ProfileViewer.Level>> levelObjClasseses = new HashMap<>();
+
+ private final HashMap<String, ProfileViewer.Level> levelObjCatas = new HashMap<>();
+ private final GuiElementTextField dungeonLevelTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT);
+ private int floorLevelTo = -1;
+ private long floorLevelToXP = -1;
+ private boolean onMasterMode = false;
+
+ public DungeonPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dung);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ JsonObject hypixelInfo = profile.getHypixelProfile();
+ if (hypixelInfo == null) return;
+ JsonObject profileInfo = profile.getProfileInformation(profileId);
+ if (profileInfo == null) return;
+
+ JsonObject leveling = Constants.LEVELING;
+ if (leveling == null) return;
+
+ int sectionWidth = 110;
+
+ String dungeonString = onMasterMode ? "master_catacombs" : "catacombs";
+
+ Utils.renderShadowedString(
+ EnumChatFormatting.RED + (onMasterMode ? "Master Mode" : "Catacombs"),
+ (guiLeft + getInstance().sizeX / 2),
+ guiTop + 5,
+ sectionWidth
+ );
+
+ ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId);
+ //Catacombs level thingy
+ {
+ if (levelObjCata == null) {
+ float cataXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0);
+ levelObjCata =
+ ProfileViewer.getLevel(
+ Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(),
+ cataXp,
+ 99,
+ false
+ );
+ levelObjCata.totalXp = cataXp;
+ levelObjCatas.put(profileId, levelObjCata);
+ }
+
+ String skillName = EnumChatFormatting.RED + "Catacombs";
+ float level = levelObjCata.level;
+ int levelFloored = (int) Math.floor(level);
+
+ if (floorLevelTo == -1 && levelFloored >= 0) {
+ dungeonLevelTextField.setText("" + (levelFloored + 1));
+ calculateFloorLevelXP();
+ }
+
+ int x = guiLeft + 23;
+ int y = guiTop + 25;
+
+ getInstance().renderXpBar(skillName, DEADBUSH, x, y, sectionWidth, levelObjCata, mouseX, mouseY);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Until Cata " + floorLevelTo + ": ",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat((double) floorLevelToXP),
+ x,
+ y + 16,
+ sectionWidth
+ );
+
+ if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && !onMasterMode) {
+ float F5 =
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 5), 0)); //this can prob be done better
+ float F6 =
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 6), 0));
+ float F7 =
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + 7), 0));
+ if (F5 > 150) {
+ F5 = 150;
+ }
+ if (F6 > 100) {
+ F6 = 100;
+ }
+ if (F7 > 50) {
+ F7 = 50;
+ }
+ float xpF5 = 2400 * (F5 / 100 + 1);
+ float xpF6 = 4880 * (F6 / 100 + 1);
+ float xpF7 = 28000 * (F7 / 100 + 1);
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ xpF5 *= 1.1;
+ xpF6 *= 1.1;
+ xpF7 *= 1.1;
+ }
+
+ long runsF5 = (int) Math.ceil(floorLevelToXP / xpF5);
+ long runsF6 = (int) Math.ceil(floorLevelToXP / xpF6);
+ long runsF7 = (int) Math.ceil(floorLevelToXP / xpF7);
+
+ float timeF5 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5"),
+ 0
+ );
+ float timeF6 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6"),
+ 0
+ );
+ float timeF7 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7"),
+ 0
+ );
+
+ getInstance().tooltipToDisplay =
+ Lists.newArrayList(
+ String.format("# F5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF5), runsF5),
+ String.format("# F6 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF6), runsF6),
+ String.format("# F7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpF7), runsF7),
+ ""
+ );
+ boolean hasTime = false;
+ if (timeF5 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (F5) : %s", Utils.prettyTime(runsF5 * (long) (timeF5 * 1.2))));
+ hasTime = true;
+ }
+ if (timeF6 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (F6) : %s", Utils.prettyTime(runsF6 * (long) (timeF6 * 1.2))));
+ hasTime = true;
+ }
+ if (timeF7 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (F7) : %s", Utils.prettyTime(runsF7 * (long) (timeF7 * 1.2))));
+ hasTime = true;
+ }
+ if (hasTime) {
+ getInstance().tooltipToDisplay.add("");
+ }
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ getInstance()
+ .tooltipToDisplay.add(
+ "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]"
+ );
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) getInstance().tooltipToDisplay.add("");
+ getInstance().tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run].");
+ getInstance().tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run");
+ getInstance()
+ .tooltipToDisplay.add(
+ "The " +
+ EnumChatFormatting.DARK_PURPLE +
+ "Catacombs Expert Ring" +
+ EnumChatFormatting.GRAY +
+ " is assumed to be used, unless " +
+ EnumChatFormatting.YELLOW +
+ "SHIFT" +
+ EnumChatFormatting.GRAY +
+ " is held."
+ );
+ getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%");
+ } else {
+ getInstance()
+ .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]");
+ }
+ }
+
+ if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && onMasterMode) {
+ float M3 =
+ (
+ Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 3),
+ 0
+ )
+ );
+ float M4 =
+ (
+ Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 4),
+ 0
+ )
+ );
+ float M5 =
+ (
+ Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 5),
+ 0
+ )
+ ); //this can prob be done better
+ float M6 =
+ (
+ Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 6),
+ 0
+ )
+ );
+ float M7 =
+ (
+ Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + 7),
+ 0
+ )
+ );
+ if (M3 > 50) {
+ M3 = 50;
+ }
+ if (M4 > 50) {
+ M4 = 50;
+ }
+ if (M5 > 50) {
+ M5 = 50;
+ }
+ if (M6 > 50) {
+ M6 = 50;
+ }
+ if (M7 > 50) {
+ M7 = 50;
+ }
+ float xpM3 = 35000 * (M3 / 100 + 1);
+ float xpM4 = 55000 * (M4 / 100 + 1);
+ float xpM5 = 70000 * (M5 / 100 + 1);
+ float xpM6 = 100000 * (M6 / 100 + 1);
+ float xpM7 = 300000 * (M7 / 100 + 1);
+ //No clue if M3 or M4 xp values are right
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ xpM3 *= 1.1;
+ xpM4 *= 1.1;
+ xpM5 *= 1.1;
+ xpM6 *= 1.1;
+ xpM7 *= 1.1;
+ }
+
+ long runsM3 = (int) Math.ceil(floorLevelToXP / xpM3);
+ long runsM4 = (int) Math.ceil(floorLevelToXP / xpM4);
+ long runsM5 = (int) Math.ceil(floorLevelToXP / xpM5);
+ long runsM6 = (int) Math.ceil(floorLevelToXP / xpM6);
+ long runsM7 = (int) Math.ceil(floorLevelToXP / xpM7);
+
+ float timeM3 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3"),
+ 0
+ );
+ float timeM4 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4"),
+ 0
+ );
+ float timeM5 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5"),
+ 0
+ );
+ float timeM6 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6"),
+ 0
+ );
+ float timeM7 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.7"),
+ 0
+ );
+
+ getInstance().tooltipToDisplay =
+ Lists.newArrayList(
+ String.format("# M3 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM3), runsM3),
+ String.format("# M4 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM4), runsM4),
+ String.format("# M5 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM5), runsM5),
+ String.format("# M6 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM6), runsM6),
+ String.format("# M7 Runs (%s xp) : %d", StringUtils.shortNumberFormat(xpM7), runsM7),
+ ""
+ );
+ boolean hasTime = false;
+ if (timeM3 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (M3) : %s", Utils.prettyTime(runsM3 * (long) (timeM3 * 1.2))));
+ hasTime = true;
+ }
+ if (timeM4 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (M4) : %s", Utils.prettyTime(runsM4 * (long) (timeM4 * 1.2))));
+ hasTime = true;
+ }
+ if (timeM5 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (M5) : %s", Utils.prettyTime(runsM5 * (long) (timeM5 * 1.2))));
+ hasTime = true;
+ }
+ if (timeM6 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (M6) : %s", Utils.prettyTime(runsM6 * (long) (timeM6 * 1.2))));
+ hasTime = true;
+ }
+ if (timeM7 > 1000) {
+ getInstance()
+ .tooltipToDisplay.add(String.format("Expected Time (M7) : %s", Utils.prettyTime(runsM7 * (long) (timeM7 * 1.2))));
+ hasTime = true;
+ }
+ if (hasTime) {
+ getInstance().tooltipToDisplay.add("");
+ }
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ getInstance()
+ .tooltipToDisplay.add(
+ "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]"
+ );
+ }
+ if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
+ if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) getInstance().tooltipToDisplay.add("");
+ getInstance().tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run].");
+ getInstance().tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run");
+ getInstance()
+ .tooltipToDisplay.add(
+ "The " +
+ EnumChatFormatting.DARK_PURPLE +
+ "Catacombs Expert Ring" +
+ EnumChatFormatting.GRAY +
+ " is assumed to be used, unless " +
+ EnumChatFormatting.YELLOW +
+ "SHIFT" +
+ EnumChatFormatting.GRAY +
+ " is held."
+ );
+ getInstance().tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%");
+ } else {
+ getInstance()
+ .tooltipToDisplay.add("[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]");
+ }
+ }
+
+ dungeonLevelTextField.setSize(20, 10);
+ dungeonLevelTextField.render(x + 22, y + 29);
+ int calcLen = fontRendererObj.getStringWidth("Calculate");
+ Utils.renderShadowedString(EnumChatFormatting.WHITE + "Calculate", x + sectionWidth - 17 - calcLen / 2f, y + 30, 100);
+
+ //Random stats
+
+ float secrets = Utils.getElementAsFloat(Utils.getElement(hypixelInfo, "achievements.skyblock_treasure_hunter"), 0);
+ float totalRunsF = 0;
+ float totalRunsF5 = 0;
+ for (int i = 1; i <= 7; i++) {
+ float runs = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.tier_completions." + i),
+ 0
+ );
+ totalRunsF += runs;
+ if (i >= 5) {
+ totalRunsF5 += runs;
+ }
+ }
+ float totalRunsM = 0;
+ float totalRunsM5 = 0;
+ for (int i = 1; i <= 7; i++) {
+ float runs = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.tier_completions." + i),
+ 0
+ );
+ totalRunsM += runs;
+ if (i >= 5) {
+ totalRunsM5 += runs;
+ }
+ }
+ float totalRuns = totalRunsF + totalRunsM;
+
+ float mobKills;
+ float mobKillsF = 0;
+ for (int i = 1; i <= 7; i++) {
+ float kills = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.mobs_killed." + i),
+ 0
+ );
+ mobKillsF += kills;
+ }
+ float mobKillsM = 0;
+ for (int i = 1; i <= 7; i++) {
+ float kills = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types.master_catacombs.mobs_killed." + i),
+ 0
+ );
+ mobKillsM += kills;
+ }
+ mobKills = mobKillsF + mobKillsM;
+
+ int miscTopY = y + 55;
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Total Runs " + (onMasterMode ? "M" : "F"),
+ EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM : totalRunsF)),
+ x,
+ miscTopY,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Total Runs (" + (onMasterMode ? "M" : "F") + "5-7) ",
+ EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM5 : totalRunsF5)),
+ x,
+ miscTopY + 10,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Secrets (Total) ",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(secrets),
+ x,
+ miscTopY + 20,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Secrets (/Run) ",
+ EnumChatFormatting.WHITE.toString() + (Math.round(secrets / Math.max(1, totalRuns) * 100) / 100f),
+ x,
+ miscTopY + 30,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Mob Kills (Total) ",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(mobKills),
+ x,
+ miscTopY + 40,
+ sectionWidth
+ );
+
+ int y3 = y + 117;
+
+ for (int i = 1; i <= 7; i++) {
+ int w = fontRendererObj.getStringWidth("" + i);
+
+ int bx = x + sectionWidth * i / 8 - w / 2;
+
+ boolean invert = i == floorTime;
+ float uMin = 20 / 256f;
+ float uMax = 29 / 256f;
+ float vMin = 0 / 256f;
+ float vMax = 11 / 256f;
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements);
+ Utils.drawTexturedRect(
+ bx - 2,
+ y3 - 2,
+ 9,
+ 11,
+ invert ? uMax : uMin,
+ invert ? uMin : uMax,
+ invert ? vMax : vMin,
+ invert ? vMin : vMax,
+ GL11.GL_NEAREST
+ );
+
+ Utils.renderShadowedString(EnumChatFormatting.WHITE.toString() + i, bx + w / 2, y3, 10);
+ }
+
+ float timeNorm = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime),
+ 0
+ );
+ float timeS = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime),
+ 0
+ );
+ float timeSPLUS = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime),
+ 0
+ );
+ String timeNormStr = timeNorm <= 0 ? "N/A" : Utils.prettyTime((long) timeNorm);
+ String timeSStr = timeS <= 0 ? "N/A" : Utils.prettyTime((long) timeS);
+ String timeSPlusStr = timeSPLUS <= 0 ? "N/A" : Utils.prettyTime((long) timeSPLUS);
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Floor " + floorTime + " ",
+ EnumChatFormatting.WHITE + timeNormStr,
+ x,
+ y3 + 10,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Floor " + floorTime + " S",
+ EnumChatFormatting.WHITE + timeSStr,
+ x,
+ y3 + 20,
+ sectionWidth
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Floor " + floorTime + " S+",
+ EnumChatFormatting.WHITE + timeSPlusStr,
+ x,
+ y3 + 30,
+ sectionWidth
+ );
+ }
+
+ //Completions
+ {
+ int x = guiLeft + 161;
+ int y = guiTop + 27;
+
+ Utils.renderShadowedString(EnumChatFormatting.RED + "Boss Collections", x + sectionWidth / 2, y, sectionWidth);
+ for (int i = 1; i <= 7; i++) {
+ float compl = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i),
+ 0
+ );
+
+ if (BOSS_HEADS[i - 1] == null) {
+ String textureLink = bossFloorHeads[i - 1];
+
+ String b64Decoded = "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + textureLink + "\"}}}";
+ String b64Encoded = new String(Base64.getEncoder().encode(b64Decoded.getBytes()));
+
+ ItemStack stack = new ItemStack(Items.skull, 1, 3);
+ NBTTagCompound nbt = new NBTTagCompound();
+ NBTTagCompound skullOwner = new NBTTagCompound();
+ NBTTagCompound properties = new NBTTagCompound();
+ NBTTagList textures = new NBTTagList();
+ NBTTagCompound textures_0 = new NBTTagCompound();
+
+ String uuid = UUID.nameUUIDFromBytes(b64Encoded.getBytes()).toString();
+ skullOwner.setString("Id", uuid);
+ skullOwner.setString("Name", uuid);
+
+ textures_0.setString("Value", b64Encoded);
+ textures.appendTag(textures_0);
+
+ properties.setTag("textures", textures);
+ skullOwner.setTag("Properties", properties);
+ nbt.setTag("SkullOwner", skullOwner);
+ stack.setTagCompound(nbt);
+
+ BOSS_HEADS[i - 1] = stack;
+ }
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x - 4, y + 10 + 20 * (i - 1), 0);
+ GlStateManager.scale(1.3f, 1.3f, 1);
+ Utils.drawItemStack(BOSS_HEADS[i - 1], 0, 0);
+ GlStateManager.popMatrix();
+
+ Utils.renderAlignedString(
+ String.format(EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ", bossFloorArr[i - 1], i),
+ EnumChatFormatting.WHITE.toString() + (int) compl,
+ x + 16,
+ y + 18 + 20 * (i - 1),
+ sectionWidth - 15
+ );
+ }
+ }
+
+ //Skills
+ {
+ int x = guiLeft + 298;
+ int y = guiTop + 27;
+
+ //Gui.drawRect(x, y, x+120, y+147, 0xffffffff);
+
+ Utils.renderShadowedString(EnumChatFormatting.DARK_PURPLE + "Class Levels", x + sectionWidth / 2, y, sectionWidth);
+
+ JsonElement activeClassElement = Utils.getElement(profileInfo, "dungeons.selected_dungeon_class");
+ String activeClass = null;
+ if (activeClassElement instanceof JsonPrimitive && ((JsonPrimitive) activeClassElement).isString()) {
+ activeClass = activeClassElement.getAsString();
+ }
+
+ for (int i = 0; i < dungSkillsName.length; i++) {
+ String skillName = dungSkillsName[i];
+
+ HashMap<String, ProfileViewer.Level> levelObjClasses = levelObjClasseses.computeIfAbsent(profileId, k -> new HashMap<>());
+ if (!levelObjClasses.containsKey(skillName)) {
+ float cataXp = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.player_classes." + skillName.toLowerCase() + ".experience"),
+ 0
+ );
+ ProfileViewer.Level levelObj = ProfileViewer.getLevel(
+ Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray(),
+ cataXp,
+ 50,
+ false
+ );
+ levelObjClasses.put(skillName, levelObj);
+ }
+
+ String colour = EnumChatFormatting.WHITE.toString();
+ if (skillName.toLowerCase().equals(activeClass)) {
+ colour = EnumChatFormatting.GREEN.toString();
+ }
+
+ ProfileViewer.Level levelObj = levelObjClasses.get(skillName);
+
+ getInstance()
+ .renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 29 * i, sectionWidth, levelObj, mouseX, mouseY);
+ }
+ }
+
+ drawSideButtons();
+ }
+
+ @Override
+ public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ if (mouseX >= guiLeft + 50 && mouseX <= guiLeft + 70 && mouseY >= guiTop + 54 && mouseY <= guiTop + 64) {
+ dungeonLevelTextField.mouseClicked(mouseX, mouseY, mouseButton);
+ } else {
+ dungeonLevelTextField.otherComponentClick();
+ }
+
+ int cW = fontRendererObj.getStringWidth("Calculate");
+ if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 && mouseY >= guiTop + 55 && mouseY <= guiTop + 65) {
+ calculateFloorLevelXP();
+ }
+
+ int y = guiTop + 142;
+
+ if (mouseY >= y - 2 && mouseY <= y + 9) {
+ for (int i = 1; i <= 7; i++) {
+ int w = fontRendererObj.getStringWidth("" + i);
+
+ int x = guiLeft + 23 + 110 * i / 8 - w / 2;
+
+ if (mouseX >= x - 2 && mouseX <= x + 7) {
+ floorTime = i;
+ return false;
+ }
+ }
+ }
+ if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) {
+ if (mouseY >= guiTop && mouseY <= guiTop + 28) {
+ onMasterMode = false;
+ } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) {
+ onMasterMode = true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void keyTyped(char typedChar, int keyCode) throws IOException {
+ dungeonLevelTextField.keyTyped(typedChar, keyCode);
+ }
+
+ private void drawSideButtons() {
+ GlStateManager.enableDepth();
+ GlStateManager.translate(0, 0, 5);
+ if (onMasterMode) {
+ drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true);
+ } else {
+ drawSideButton(0, dungeonsModeIcons.get("catacombs"), true);
+ }
+ GlStateManager.translate(0, 0, -3);
+
+ GlStateManager.translate(0, 0, -2);
+ if (!onMasterMode) {
+ drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), false);
+ } else {
+ drawSideButton(0, dungeonsModeIcons.get("catacombs"), false);
+ }
+ GlStateManager.disableDepth();
+ }
+
+ private void drawSideButton(int yIndex, ItemStack itemStack, boolean pressed) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ GlStateManager.disableLighting();
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1F);
+
+ int x = guiLeft - 28;
+ int y = guiTop + yIndex * 28;
+
+ float uMin = 193 / 256f;
+ float uMax = 223 / 256f;
+ float vMin = 200 / 256f;
+ float vMax = 228 / 256f;
+ if (pressed) {
+ uMin = 224 / 256f;
+ uMax = 1f;
+
+ if (yIndex != 0) {
+ vMin = 228 / 256f;
+ vMax = 1f;
+ }
+
+ getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 30, 28 - 4);
+ } else {
+ getInstance().renderBlurredBackground(getInstance().width, getInstance().height, x + 2, y + 2, 28 - 2, 28 - 4);
+ }
+
+ GlStateManager.disableLighting();
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1F);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements);
+
+ Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST);
+
+ GlStateManager.enableDepth();
+ Utils.drawItemStack(itemStack, x + 8, y + 7);
+ }
+
+ private void calculateFloorLevelXP() {
+ JsonObject leveling = Constants.LEVELING;
+ if (leveling == null) return;
+ ProfileViewer.Level levelObjCata = levelObjCatas.get(GuiProfileViewer.getProfileId());
+ if (levelObjCata == null) return;
+
+ try {
+ dungeonLevelTextField.setCustomBorderColour(0xffffffff);
+ floorLevelTo = Integer.parseInt(dungeonLevelTextField.getText());
+
+ JsonArray levelingArray = Utils.getElementOrDefault(leveling, "catacombs", new JsonArray()).getAsJsonArray();
+
+ float remaining = -((levelObjCata.level % 1) * levelObjCata.maxXpForLevel);
+
+ for (int level = 0; level < Math.min(floorLevelTo, levelingArray.size()); level++) {
+ if (level < Math.floor(levelObjCata.level)) {
+ continue;
+ }
+ remaining += levelingArray.get(level).getAsFloat();
+ }
+
+ if (remaining < 0) {
+ remaining = 0;
+ }
+ floorLevelToXP = (long) remaining;
+ } catch (Exception e) {
+ dungeonLevelTextField.setCustomBorderColour(0xffff0000);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java
new file mode 100644
index 00000000..3b30b9b7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ExtraPage.java
@@ -0,0 +1,542 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.opengl.GL11;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.TreeMap;
+
+public class ExtraPage extends GuiProfileViewerPage {
+
+ private static final ResourceLocation pv_extra = new ResourceLocation("notenoughupdates:pv_extra.png");
+ private TreeMap<Integer, Set<String>> topKills = null;
+ private TreeMap<Integer, Set<String>> topDeaths = null;
+
+ public ExtraPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_extra);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ JsonObject profileInfo = profile.getProfileInformation(profileId);
+ if (profileInfo == null) return;
+ Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(profileId);
+
+ float xStart = 22;
+ float xOffset = 103;
+ float yStartTop = 27;
+ float yStartBottom = 105;
+ float yOffset = 10;
+
+ float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0);
+ float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.GOLD + "Bank Balance",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(bankBalance),
+ guiLeft + xStart,
+ guiTop + yStartTop,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.GOLD + "Purse",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(purseBalance),
+ guiLeft + xStart,
+ guiTop + yStartTop + yOffset,
+ 76
+ );
+
+ {
+ String first_join = getTimeSinceString(profileInfo, "first_join");
+ if (first_join != null) {
+ Utils.renderAlignedString(
+ EnumChatFormatting.AQUA + "Joined",
+ EnumChatFormatting.WHITE + first_join,
+ guiLeft + xStart,
+ guiTop + yStartTop + yOffset * 2,
+ 76
+ );
+ }
+ }
+ JsonObject guildInfo = profile.getGuildInformation(null);
+ boolean shouldRenderGuild = guildInfo != null && guildInfo.has("name");
+ {
+ if (shouldRenderGuild) {
+ Utils.renderAlignedString(
+ EnumChatFormatting.AQUA + "Guild",
+ EnumChatFormatting.WHITE + guildInfo.get("name").getAsString(),
+ guiLeft + xStart,
+ guiTop + yStartTop + yOffset * 3,
+ 76
+ );
+ }
+ }
+ {
+ GuiProfileViewer.pronouns.peekValue().flatMap(it -> it).ifPresent(choice -> Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Pronouns",
+ EnumChatFormatting.WHITE + String.join(" / ", choice.render()),
+ guiLeft + xStart,
+ guiTop + yStartTop + yOffset * (shouldRenderGuild ? 4 : 3),
+ 76
+ ));
+ }
+
+ float fairySouls = Utils.getElementAsFloat(Utils.getElement(profileInfo, "fairy_souls_collected"), 0);
+
+ int fairySoulMax = 227;
+ if (Constants.FAIRYSOULS != null && Constants.FAIRYSOULS.has("Max Souls")) {
+ fairySoulMax = Constants.FAIRYSOULS.get("Max Souls").getAsInt();
+ }
+ Utils.renderAlignedString(
+ EnumChatFormatting.LIGHT_PURPLE + "Fairy Souls",
+ EnumChatFormatting.WHITE.toString() + (int) fairySouls + "/" + fairySoulMax,
+ guiLeft + xStart,
+ guiTop + yStartBottom,
+ 76
+ );
+
+ if (skyblockInfo != null) {
+ float totalSkillLVL = 0;
+ float totalTrueSkillLVL = 0;
+ float totalSlayerLVL = 0;
+ float totalSkillCount = 0;
+ float totalSlayerCount = 0;
+ float totalSlayerXP = 0;
+
+ List<String> skills = Arrays.asList(
+ "taming",
+ "mining",
+ "foraging",
+ "enchanting",
+ "farming",
+ "combat",
+ "fishing",
+ "alchemy",
+ "carpentry"
+ );
+ List<String> slayers = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze");
+
+ for (Map.Entry<String, ProfileViewer.Level> entry : skyblockInfo.entrySet()) {
+ if (skills.contains(entry.getKey())) {
+ totalSkillLVL += entry.getValue().level;
+ totalTrueSkillLVL += Math.floor(entry.getValue().level);
+ totalSkillCount++;
+ } else if (slayers.contains(entry.getKey())) {
+ totalSlayerLVL += entry.getValue().level;
+ totalSlayerCount++;
+ totalSlayerXP += entry.getValue().totalXp;
+ }
+ }
+
+ float avgSkillLVL = totalSkillLVL / totalSkillCount;
+ float avgTrueSkillLVL = totalTrueSkillLVL / totalSkillCount;
+ float avgSlayerLVL = totalSlayerLVL / totalSlayerCount;
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "AVG Skill Level",
+ EnumChatFormatting.WHITE.toString() + Math.floor(avgSkillLVL * 10) / 10,
+ guiLeft + xStart,
+ guiTop + yStartBottom + yOffset,
+ 76
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "True AVG Skill Level",
+ EnumChatFormatting.WHITE.toString() + Math.floor(avgTrueSkillLVL * 10) / 10,
+ guiLeft + xStart,
+ guiTop + yStartBottom + yOffset * 2,
+ 76
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "AVG Slayer Level",
+ EnumChatFormatting.WHITE.toString() + Math.floor(avgSlayerLVL * 10) / 10,
+ guiLeft + xStart,
+ guiTop + yStartBottom + yOffset * 3,
+ 76
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "Total Slayer XP",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(totalSlayerXP),
+ guiLeft + xStart,
+ guiTop + yStartBottom + yOffset * 4,
+ 76
+ );
+ }
+
+ float auctions_bids = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_bids"), 0);
+ float auctions_highest_bid = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "stats.auctions_highest_bid"),
+ 0
+ );
+ float auctions_won = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_won"), 0);
+ float auctions_created = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_created"), 0);
+ float auctions_gold_spent = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_spent"), 0);
+ float auctions_gold_earned = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "stats.auctions_gold_earned"),
+ 0
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Auction Bids",
+ EnumChatFormatting.WHITE.toString() + (int) auctions_bids,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Highest Bid",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(auctions_highest_bid),
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop + yOffset,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Auctions Won",
+ EnumChatFormatting.WHITE.toString() + (int) auctions_won,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop + yOffset * 2,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Auctions Created",
+ EnumChatFormatting.WHITE.toString() + (int) auctions_created,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop + yOffset * 3,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Gold Spent",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(auctions_gold_spent),
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop + yOffset * 4,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Gold Earned",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(auctions_gold_earned),
+ guiLeft + xStart + xOffset,
+ guiTop + yStartTop + yOffset * 5,
+ 76
+ );
+
+ //Slayer values
+ float zombie_boss_kills_tier_2 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_2"),
+ 0
+ );
+ float zombie_boss_kills_tier_3 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_3"),
+ 0
+ );
+ float zombie_boss_kills_tier_4 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_4"),
+ 0
+ );
+ float wolf_boss_kills_tier_2 = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "slayer_bosses.wolf.boss_kills_tier_2"
+ ), 0);
+ float wolf_boss_kills_tier_3 = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "slayer_bosses.wolf.boss_kills_tier_3"
+ ), 0);
+ float spider_boss_kills_tier_2 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_2"),
+ 0
+ );
+ float spider_boss_kills_tier_3 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_3"),
+ 0
+ );
+ float enderman_boss_kills_tier_2 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_2"),
+ 0
+ );
+ float enderman_boss_kills_tier_3 = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_3"),
+ 0
+ );
+ float blaze_boss_kills_tier_2 = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "slayer_bosses.blaze.boss_kills_tier_2"
+ ), 0);
+ float blaze_boss_kills_tier_3 = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "slayer_bosses.blaze.boss_kills_tier_3"
+ ), 0);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Revenant T3",
+ EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_2,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartBottom,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Revenant T4",
+ EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_3,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartBottom + yOffset,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Revenant T5",
+ EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_4,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartBottom + yOffset * 2,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Tarantula T3",
+ EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_2,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartBottom + yOffset * 3,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Tarantula T4",
+ EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_3,
+ guiLeft + xStart + xOffset,
+ guiTop + yStartBottom + yOffset * 4,
+ 76
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Sven T3",
+ EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_2,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 0,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Sven T4",
+ EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_3,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 1,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Voidgloom T3",
+ EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_2,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 2,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Voidgloom T4",
+ EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_3,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 3,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Inferno T3",
+ EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_2,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 4,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_AQUA + "Inferno T4",
+ EnumChatFormatting.WHITE.toString() + (int) blaze_boss_kills_tier_3,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartBottom + yOffset * 5,
+ 76
+ );
+
+ float pet_milestone_ores_mined = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "stats.pet_milestone_ores_mined"
+ ), 0);
+ float pet_milestone_sea_creatures_killed = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "stats.pet_milestone_sea_creatures_killed"),
+ 0
+ );
+
+ float items_fished = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished"), 0);
+ float items_fished_treasure = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "stats.items_fished_treasure"),
+ 0
+ );
+ float items_fished_large_treasure = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "stats.items_fished_large_treasure"
+ ), 0);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Ores Mined",
+ EnumChatFormatting.WHITE.toString() + (int) pet_milestone_ores_mined,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartTop,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Sea Creatures Killed",
+ EnumChatFormatting.WHITE.toString() + (int) pet_milestone_sea_creatures_killed,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartTop + yOffset,
+ 76
+ );
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Items Fished",
+ EnumChatFormatting.WHITE.toString() + (int) items_fished,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartTop + yOffset * 3,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Treasures Fished",
+ EnumChatFormatting.WHITE.toString() + (int) items_fished_treasure,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartTop + yOffset * 4,
+ 76
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Large Treasures",
+ EnumChatFormatting.WHITE.toString() + (int) items_fished_large_treasure,
+ guiLeft + xStart + xOffset * 2,
+ guiTop + yStartTop + yOffset * 5,
+ 76
+ );
+
+ if (topKills == null) {
+ topKills = new TreeMap<>();
+ JsonObject stats = profileInfo.get("stats").getAsJsonObject();
+ for (Map.Entry<String, JsonElement> entry : stats.entrySet()) {
+ if (entry.getKey().startsWith("kills_")) {
+ if (entry.getValue().isJsonPrimitive()) {
+ JsonPrimitive prim = (JsonPrimitive) entry.getValue();
+ if (prim.isNumber()) {
+ String name = WordUtils.capitalizeFully(entry.getKey().substring("kills_".length()).replace("_", " "));
+ Set<String> kills = topKills.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>());
+ kills.add(name);
+ }
+ }
+ }
+ }
+ }
+ if (topDeaths == null) {
+ topDeaths = new TreeMap<>();
+ JsonObject stats = profileInfo.get("stats").getAsJsonObject();
+ for (Map.Entry<String, JsonElement> entry : stats.entrySet()) {
+ if (entry.getKey().startsWith("deaths_")) {
+ if (entry.getValue().isJsonPrimitive()) {
+ JsonPrimitive prim = (JsonPrimitive) entry.getValue();
+ if (prim.isNumber()) {
+ String name = WordUtils.capitalizeFully(entry.getKey().substring("deaths_".length()).replace("_", " "));
+ Set<String> deaths = topDeaths.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>());
+ deaths.add(name);
+ }
+ }
+ }
+ }
+ }
+
+ int index = 0;
+ for (int killCount : topKills.descendingKeySet()) {
+ if (index >= 6) break;
+ Set<String> kills = topKills.get(killCount);
+ for (String killType : kills) {
+ if (index >= 6) break;
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + killType + " Kills",
+ EnumChatFormatting.WHITE.toString() + killCount,
+ guiLeft + xStart + xOffset * 3,
+ guiTop + yStartTop + yOffset * index,
+ 76
+ );
+ index++;
+ }
+ }
+ index = 0;
+ for (int deathCount : topDeaths.descendingKeySet()) {
+ if (index >= 6) break;
+ Set<String> deaths = topDeaths.get(deathCount);
+ for (String deathType : deaths) {
+ if (index >= 6) break;
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Deaths: " + deathType,
+ EnumChatFormatting.WHITE.toString() + deathCount,
+ guiLeft + xStart + xOffset * 3,
+ guiTop + yStartBottom + yOffset * index,
+ 76
+ );
+ index++;
+ }
+ }
+ }
+
+ private String getTimeSinceString(JsonObject profileInfo, String path) {
+ JsonElement lastSaveElement = Utils.getElement(profileInfo, path);
+
+ if (lastSaveElement != null && lastSaveElement.isJsonPrimitive()) {
+ Instant lastSave = Instant.ofEpochMilli(lastSaveElement.getAsLong());
+ LocalDateTime lastSaveTime = LocalDateTime.ofInstant(lastSave, TimeZone.getDefault().toZoneId());
+ long timeDiff = System.currentTimeMillis() - lastSave.toEpochMilli();
+ LocalDateTime sinceOnline = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeDiff), ZoneId.of("UTC"));
+ String renderText;
+
+ if (timeDiff < 60000L) {
+ renderText = sinceOnline.getSecond() + " seconds ago.";
+ } else if (timeDiff < 3600000L) {
+ renderText = sinceOnline.getMinute() + " minutes ago.";
+ } else if (timeDiff < 86400000L) {
+ renderText = sinceOnline.getHour() + " hours ago.";
+ } else if (timeDiff < 31556952000L) {
+ renderText = sinceOnline.getDayOfYear() + " days ago.";
+ } else {
+ renderText = lastSaveTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
+ }
+ return renderText;
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
index 44ea686d..98f186cb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
@@ -1,43 +1,55 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.profileviewer;
-import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import com.google.gson.JsonPrimitive;
-import com.mojang.authlib.GameProfile;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager;
import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.profileviewer.bestiary.BestiaryPage;
+import io.github.moulberry.notenoughupdates.profileviewer.trophy.TrophyFishPage;
+import io.github.moulberry.notenoughupdates.util.AsyncDependencyLoader;
import io.github.moulberry.notenoughupdates.util.Constants;
-import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.PronounDB;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityOtherPlayerMP;
-import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
-import net.minecraft.client.renderer.RenderHelper;
-import net.minecraft.client.renderer.entity.RenderManager;
-import net.minecraft.client.resources.DefaultPlayerSkin;
import net.minecraft.client.shader.Framebuffer;
import net.minecraft.client.shader.Shader;
-import net.minecraft.entity.EntityLivingBase;
-import net.minecraft.entity.player.EnumPlayerModelParts;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.*;
+import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.Matrix4f;
import net.minecraft.util.ResourceLocation;
-import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.input.Keyboard;
-import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL20;
@@ -47,29 +59,18 @@ import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.NumberFormat;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
-import java.util.*;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.function.Supplier;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
public class GuiProfileViewer extends GuiScreen {
- private static final ResourceLocation CHEST_GUI_TEXTURE =
- new ResourceLocation("textures/gui/container/generic_54.png");
- public static final ResourceLocation pv_basic = new ResourceLocation("notenoughupdates:pv_basic.png");
- public static final ResourceLocation pv_dung = new ResourceLocation("notenoughupdates:pv_dung.png");
- public static final ResourceLocation pv_extra = new ResourceLocation("notenoughupdates:pv_extra.png");
- public static final ResourceLocation pv_mining = new ResourceLocation("notenoughupdates:pv_mining.png");
- public static final ResourceLocation pv_invs = new ResourceLocation("notenoughupdates:pv_invs.png");
- public static final ResourceLocation pv_cols = new ResourceLocation("notenoughupdates:pv_cols.png");
- public static final ResourceLocation pv_pets = new ResourceLocation("notenoughupdates:pv_pets.png");
+
public static final ResourceLocation pv_dropdown = new ResourceLocation("notenoughupdates:pv_dropdown.png");
public static final ResourceLocation pv_bg = new ResourceLocation("notenoughupdates:pv_bg.png");
public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
@@ -80,64 +81,232 @@ public class GuiProfileViewer extends GuiScreen {
public static final ResourceLocation resource_packs =
new ResourceLocation("minecraft:textures/gui/resource_packs.png");
public static final ResourceLocation icons = new ResourceLocation("textures/gui/icons.png");
+ public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS =
+ new HashMap<String, HashMap<String, Float>>() {
+ {
+ put(
+ "PET_ITEM_BIG_TEETH_COMMON",
+ new HashMap<String, Float>() {
+ {
+ put("CRIT_CHANCE", 5f);
+ }
+ }
+ );
+ put(
+ "PET_ITEM_HARDENED_SCALES_UNCOMMON",
+ new HashMap<String, Float>() {
+ {
+ put("DEFENCE", 25f);
+ }
+ }
+ );
+ put(
+ "PET_ITEM_LUCKY_CLOVER",
+ new HashMap<String, Float>() {
+ {
+ put("MAGIC_FIND", 7f);
+ }
+ }
+ );
+ put(
+ "PET_ITEM_SHARPENED_CLAWS_UNCOMMON",
+ new HashMap<String, Float>() {
+ {
+ put("CRIT_DAMAGE", 15f);
+ }
+ }
+ );
+ }
+ };
+ public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS_MULT =
+ new HashMap<String, HashMap<String, Float>>() {
+ {
+ put(
+ "PET_ITEM_IRON_CLAWS_COMMON",
+ new HashMap<String, Float>() {
+ {
+ put("CRIT_DAMAGE", 1.4f);
+ put("CRIT_CHANCE", 1.4f);
+ }
+ }
+ );
+ put(
+ "PET_ITEM_TEXTBOOK",
+ new HashMap<String, Float>() {
+ {
+ put("INTELLIGENCE", 2f);
+ }
+ }
+ );
+ }
+ };
- private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
+ public static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
- private final ProfileViewer.Profile profile;
+ private static final char[] c = new char[]{'k', 'm', 'b', 't'};
public static ProfileViewerPage currentPage = ProfileViewerPage.BASIC;
- private int sizeX;
- private int sizeY;
- private int guiLeft;
- private int guiTop;
-
- private float backgroundRotation = 0;
-
- private long currentTime = 0;
- private long lastTime = 0;
- private long startTime = 0;
-
- private List<String> tooltipToDisplay = null;
-
- private String profileId = null;
+ public static HashMap<String, String> MINION_RARITY_TO_NUM = new HashMap<String, String>() {
+ {
+ put("COMMON", "0");
+ put("UNCOMMON", "1");
+ put("RARE", "2");
+ put("EPIC", "3");
+ put("LEGENDARY", "4");
+ put("MYTHIC", "5");
+ }
+ };
+ private static int guiLeft;
+ private static int guiTop;
+ private static ProfileViewer.Profile profile;
+ private static String profileId = null;
+ public static AsyncDependencyLoader<Optional<PronounDB.PronounChoice>> pronouns =
+ AsyncDependencyLoader.withEqualsInvocation(
+ () ->
+ NotEnoughUpdates.INSTANCE.config.profileViewer.showPronounsInPv
+ ? Optional.ofNullable(profile).map(it -> Utils.parseDashlessUUID(it.getUuid()))
+ : Optional.<UUID>empty(),
+ uuid -> uuid.isPresent()
+ ? PronounDB.getPronounsFor(uuid.get())
+ : CompletableFuture.completedFuture(Optional.empty())
+ );
+ public final GuiElementTextField playerNameTextField;
+ public final GuiElementTextField inventoryTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT);
+ private final Map<ProfileViewerPage, GuiProfileViewerPage> pages = new HashMap<>();
+ public int sizeX;
+ public int sizeY;
+ public float backgroundRotation = 0;
+ public long currentTime = 0;
+ public long lastTime = 0;
+ public long startTime = 0;
+ public List<String> tooltipToDisplay = null;
+ Shader blurShaderHorz = null;
+ Framebuffer blurOutputHorz = null;
+ Shader blurShaderVert = null;
+ Framebuffer blurOutputVert = null;
private boolean profileDropdownSelected = false;
- public enum ProfileViewerPage {
- LOADING(null),
- INVALID_NAME(null),
- NO_SKYBLOCK(null),
- BASIC(new ItemStack(Items.paper)),
- DUNG(new ItemStack(Item.getItemFromBlock(Blocks.deadbush))),
- EXTRA(new ItemStack(Items.book)),
- INVS(new ItemStack(Item.getItemFromBlock(Blocks.ender_chest))),
- COLS(new ItemStack(Items.painting)),
- PETS(new ItemStack(Items.bone)),
- MINING(new ItemStack(Items.iron_pickaxe));
-
- public final ItemStack stack;
-
- ProfileViewerPage(ItemStack stack) {
- this.stack = stack;
- }
- }
+ private double lastBgBlurFactor = -1;
+ private boolean showBingoPage;
public GuiProfileViewer(ProfileViewer.Profile profile) {
- this.profile = profile;
+ GuiProfileViewer.profile = profile;
+ GuiProfileViewer.profileId = profile.getLatestProfile();
String name = "";
- if (profile != null && profile.getHypixelProfile() != null) {
+ if (profile.getHypixelProfile() != null) {
name = profile.getHypixelProfile().get("displayname").getAsString();
}
- playerNameTextField = new GuiElementTextField(
- name,
- GuiElementTextField.SCALE_TEXT
- );
+ playerNameTextField = new GuiElementTextField(name, GuiElementTextField.SCALE_TEXT);
playerNameTextField.setSize(100, 20);
if (currentPage == ProfileViewerPage.LOADING) {
currentPage = ProfileViewerPage.BASIC;
}
+
+ pages.put(ProfileViewerPage.BASIC, new BasicPage(this));
+ pages.put(ProfileViewerPage.DUNGEON, new DungeonPage(this));
+ pages.put(ProfileViewerPage.EXTRA, new ExtraPage(this));
+ pages.put(ProfileViewerPage.INVENTORIES, new InventoriesPage(this));
+ pages.put(ProfileViewerPage.COLLECTIONS, new CollectionsPage(this));
+ pages.put(ProfileViewerPage.PETS, new PetsPage(this));
+ pages.put(ProfileViewerPage.MINING, new MiningPage(this));
+ pages.put(ProfileViewerPage.BINGO, new BingoPage(this));
+ pages.put(ProfileViewerPage.TROPHY_FISH, new TrophyFishPage(this));
+ pages.put(ProfileViewerPage.BESTIARY, new BestiaryPage(this));
+ }
+
+ private static float getMaxLevelXp(JsonArray levels, int offset, int maxLevel) {
+ float xpTotal = 0;
+
+ for (int i = offset; i < offset + maxLevel - 1; i++) {
+ xpTotal += levels.get(i).getAsFloat();
+ }
+
+ return xpTotal;
+ }
+
+ public static PetLevel getPetLevel(
+ String petType,
+ String rarity,
+ float exp
+ ) {
+ int offset = PetInfoOverlay.Rarity.valueOf(rarity).petOffset;
+ int maxLevel = 100;
+
+ JsonArray levels = new JsonArray();
+ levels.addAll(Constants.PETS.get("pet_levels").getAsJsonArray());
+ JsonElement customLevelingJson = Constants.PETS.get("custom_pet_leveling").getAsJsonObject().get(petType);
+ if (customLevelingJson != null) {
+ switch (Utils.getElementAsInt(Utils.getElement(customLevelingJson, "type"), 0)) {
+ case 1:
+ levels.addAll(customLevelingJson.getAsJsonObject().get("pet_levels").getAsJsonArray());
+ break;
+ case 2:
+ levels = customLevelingJson.getAsJsonObject().get("pet_levels").getAsJsonArray();
+ break;
+ }
+ maxLevel = Utils.getElementAsInt(Utils.getElement(customLevelingJson, "max_level"), 100);
+ }
+
+ float maxXP = getMaxLevelXp(levels, offset, maxLevel);
+ boolean isMaxed = exp >= maxXP;
+
+ int level = 1;
+ float currentLevelRequirement = 0;
+ float xpThisLevel = 0;
+ float pct = 0;
+
+ if (isMaxed) {
+ level = maxLevel;
+ currentLevelRequirement = levels.get(offset + level - 2).getAsFloat();
+ xpThisLevel = currentLevelRequirement;
+ pct = 1;
+ } else {
+ long totalExp = 0;
+ for (int i = offset; i < levels.size(); i++) {
+ currentLevelRequirement = levels.get(i).getAsLong();
+ totalExp += currentLevelRequirement;
+ if (totalExp >= exp) {
+ xpThisLevel = currentLevelRequirement - (totalExp - exp);
+ level = Math.min(i - offset + 1, maxLevel);
+ break;
+ }
+ }
+ pct = currentLevelRequirement != 0 ? xpThisLevel / currentLevelRequirement : 0;
+ level += pct;
+ }
+
+ GuiProfileViewer.PetLevel levelObj = new GuiProfileViewer.PetLevel();
+ levelObj.level = level;
+ levelObj.maxLevel = maxLevel;
+ levelObj.currentLevelRequirement = currentLevelRequirement;
+ levelObj.maxXP = maxXP;
+ levelObj.levelPercentage = pct;
+ levelObj.levelXp = xpThisLevel;
+ levelObj.totalXp = exp;
+ return levelObj;
}
- private final GuiElementTextField playerNameTextField;
+ @Deprecated
+ public static String shortNumberFormat(double n, int iteration) {
+ return StringUtils.shortNumberFormat(n, iteration
+ );
+ }
+
+ public static int getGuiLeft() {
+ return guiLeft;
+ }
+
+ public static int getGuiTop() {
+ return guiTop;
+ }
+
+ public static ProfileViewer.Profile getProfile() {
+ return profile;
+ }
+
+ public static String getProfileId() {
+ return profileId;
+ }
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
@@ -147,7 +316,7 @@ public class GuiProfileViewer extends GuiScreen {
ProfileViewerPage page = currentPage;
if (profile == null) {
page = ProfileViewerPage.INVALID_NAME;
- } else if (profile.getPlayerInformation(null) == null) {
+ } else if (profile.getSkyblockProfiles(null) == null) {
page = ProfileViewerPage.LOADING;
} else if (profile.getLatestProfile() == null) {
page = ProfileViewerPage.NO_SKYBLOCK;
@@ -159,14 +328,26 @@ public class GuiProfileViewer extends GuiScreen {
{
//this is just to cache the guild info
if (profile != null) {
- JsonObject guildinfo = profile.getGuildInfo(null);
+ profile.getGuildInformation(null);
}
}
this.sizeX = 431;
this.sizeY = 202;
- this.guiLeft = (this.width - this.sizeX) / 2;
- this.guiTop = (this.height - this.sizeY) / 2;
+ guiLeft = (this.width - this.sizeX) / 2;
+ guiTop = (this.height - this.sizeY) / 2;
+
+ JsonObject currProfileInfo = profile != null ? profile.getProfileInformation(profileId) : null;
+ if (NotEnoughUpdates.INSTANCE.config.profileViewer.alwaysShowBingoTab) {
+ showBingoPage = true;
+ } else {
+ showBingoPage =
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("bingo");
+ }
+
+ if (!showBingoPage && currentPage == ProfileViewerPage.BINGO) currentPage = ProfileViewerPage.BASIC;
super.drawScreen(mouseX, mouseY, partialTicks);
drawDefaultBackground();
@@ -199,42 +380,57 @@ public class GuiProfileViewer extends GuiScreen {
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
if (profile != null) {
- JsonObject currProfileInfo = profile.getProfileInformation(profileId);
//Render Profile chooser button
renderBlurredBackground(width, height, guiLeft + 2, guiTop + sizeY + 3 + 2, 100 - 4, 20 - 4);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
- Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 3, 100, 20,
- 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST
- );
- Utils.drawStringCenteredScaledMaxWidth(profileId, Minecraft.getMinecraft().fontRendererObj, guiLeft + 50,
- guiTop + sizeY + 3 + 10, true, 90, new Color(63, 224, 208, 255).getRGB()
+ Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 3, 100, 20, 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST);
+ Utils.drawStringCenteredScaledMaxWidth(
+ profileId,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 50,
+ guiTop + sizeY + 3 + 10,
+ true,
+ 90,
+ new Color(63, 224, 208, 255).getRGB()
);
//ironman icon
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("ironman")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("ironman")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_ironman);
Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST);
}
//bingo! icon
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("bingo")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("bingo")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bingo);
Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST);
}
//stranded icon
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("island")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("island")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_stranded);
Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST);
}
//icon if game mode is unknown
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- !currProfileInfo.get("game_mode").getAsString().equals("island") &&
- !currProfileInfo.get("game_mode").getAsString().equals("bingo") &&
- !currProfileInfo.get("game_mode").getAsString().equals("ironman")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("island") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("bingo") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("ironman")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_unknown);
Utils.drawTexturedRect(guiLeft - 16 - 5, guiTop + sizeY + 5, 16, 16, GL11.GL_NEAREST);
@@ -242,8 +438,16 @@ public class GuiProfileViewer extends GuiScreen {
//Render Open In Skycrypt button
renderBlurredBackground(width, height, guiLeft + 100 + 6 + 2, guiTop + sizeY + 3 + 2, 100 - 4, 20 - 4);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
- Utils.drawTexturedRect(guiLeft + 100 + 6, guiTop + sizeY + 3, 100, 20,
- 0, 100 / 200f, 0, 20 / 185f, GL11.GL_NEAREST
+ Utils.drawTexturedRect(
+ guiLeft + 100 + 6,
+ guiTop + sizeY + 3,
+ 100,
+ 20,
+ 0,
+ 100 / 200f,
+ 0,
+ 20 / 185f,
+ GL11.GL_NEAREST
);
Utils.drawStringCenteredScaledMaxWidth(
"Open in Skycrypt",
@@ -255,25 +459,39 @@ public class GuiProfileViewer extends GuiScreen {
new Color(63, 224, 208, 255).getRGB()
);
- if (profileDropdownSelected && !profile.getProfileIds().isEmpty() && scaledResolution.getScaleFactor() != 4) {
+ if (profileDropdownSelected && !profile.getProfileNames().isEmpty() && scaledResolution.getScaleFactor() < 4) {
int dropdownOptionSize = scaledResolution.getScaleFactor() == 3 ? 10 : 20;
- int numProfiles = profile.getProfileIds().size();
+ int numProfiles = profile.getProfileNames().size();
int sizeYDropdown = numProfiles * dropdownOptionSize;
renderBlurredBackground(width, height, guiLeft + 2, guiTop + sizeY + 23, 100 - 4, sizeYDropdown - 2);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
- Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 - 3, 100, 3,
- 100 / 200f, 1, 0, 3 / 185f, GL11.GL_NEAREST
+ Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 - 3, 100, 3, 100 / 200f, 1, 0, 3 / 185f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(
+ guiLeft,
+ guiTop + sizeY + 23 + sizeYDropdown - 4,
+ 100,
+ 4,
+ 100 / 200f,
+ 1,
+ 181 / 185f,
+ 1,
+ GL11.GL_NEAREST
);
- Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23 + sizeYDropdown - 4, 100, 4,
- 100 / 200f, 1, 181 / 185f, 1, GL11.GL_NEAREST
- );
- Utils.drawTexturedRect(guiLeft, guiTop + sizeY + 23, 100, sizeYDropdown - 4,
- 100 / 200f, 1, (181 - sizeYDropdown) / 185f, 181 / 185f, GL11.GL_NEAREST
+ Utils.drawTexturedRect(
+ guiLeft,
+ guiTop + sizeY + 23,
+ 100,
+ sizeYDropdown - 4,
+ 100 / 200f,
+ 1,
+ (181 - sizeYDropdown) / 185f,
+ 181 / 185f,
+ GL11.GL_NEAREST
);
- for (int yIndex = 0; yIndex < profile.getProfileIds().size(); yIndex++) {
- String otherProfileId = profile.getProfileIds().get(yIndex);
+ for (int yIndex = 0; yIndex < profile.getProfileNames().size(); yIndex++) {
+ String otherProfileId = profile.getProfileNames().get(yIndex);
Utils.drawStringCenteredScaledMaxWidth(
otherProfileId,
Minecraft.getMinecraft().fontRendererObj,
@@ -284,8 +502,11 @@ public class GuiProfileViewer extends GuiScreen {
new Color(33, 112, 104, 255).getRGB()
);
currProfileInfo = profile.getProfileInformation(otherProfileId);
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("ironman")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("ironman")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_ironman);
Utils.drawTexturedRect(
@@ -296,8 +517,11 @@ public class GuiProfileViewer extends GuiScreen {
GL11.GL_NEAREST
);
}
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("bingo")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("bingo")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_bingo);
Utils.drawTexturedRect(
@@ -308,8 +532,11 @@ public class GuiProfileViewer extends GuiScreen {
GL11.GL_NEAREST
);
}
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- currProfileInfo.get("game_mode").getAsString().equals("island")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ currProfileInfo.get("game_mode").getAsString().equals("island")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_stranded);
Utils.drawTexturedRect(
@@ -320,10 +547,13 @@ public class GuiProfileViewer extends GuiScreen {
GL11.GL_NEAREST
);
}
- if (currProfileInfo != null && currProfileInfo.has("game_mode") &&
- !currProfileInfo.get("game_mode").getAsString().equals("island") &&
- !currProfileInfo.get("game_mode").getAsString().equals("bingo") &&
- !currProfileInfo.get("game_mode").getAsString().equals("ironman")) {
+ if (
+ currProfileInfo != null &&
+ currProfileInfo.has("game_mode") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("island") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("bingo") &&
+ !currProfileInfo.get("game_mode").getAsString().equals("ironman")
+ ) {
GlStateManager.color(1, 1, 1, 1);
Minecraft.getMinecraft().getTextureManager().bindTexture(pv_unknown);
Utils.drawTexturedRect(
@@ -335,163 +565,156 @@ public class GuiProfileViewer extends GuiScreen {
);
}
}
-
}
}
}
GlStateManager.color(1, 1, 1, 1);
- switch (page) {
- case BASIC:
- drawBasicPage(mouseX, mouseY, partialTicks);
- break;
- case DUNG:
- drawDungPage(mouseX, mouseY, partialTicks);
- break;
- case EXTRA:
- drawExtraPage(mouseX, mouseY, partialTicks);
- break;
- case INVS:
- drawInvsPage(mouseX, mouseY, partialTicks);
- break;
- case COLS:
- drawColsPage(mouseX, mouseY, partialTicks);
- break;
- case PETS:
- drawPetsPage(mouseX, mouseY, partialTicks);
- break;
- case MINING:
- drawMiningPage(mouseX, mouseY, partialTicks);
- break;
- case LOADING:
- String str = EnumChatFormatting.YELLOW + "Loading player profiles.";
- long currentTimeMod = System.currentTimeMillis() % 1000;
- if (currentTimeMod > 333) {
- if (currentTimeMod < 666) {
- str += ".";
- } else {
- str += "..";
- }
- }
-
- Utils.drawStringCentered(str, Minecraft.getMinecraft().fontRendererObj,
- guiLeft + sizeX / 2f, guiTop + 101, true, 0
- );
- //This is just here to inform the player what to do
- //like typing /api new or telling them to go find a psychotherapist
- long timeDiff = System.currentTimeMillis() - startTime;
+ if (pages.containsKey(page)) {
+ pages.get(page).drawPage(mouseX, mouseY, partialTicks);
+ } else {
+ switch (page) {
+ case LOADING:
+ String str = EnumChatFormatting.YELLOW + "Loading player profiles.";
+ long currentTimeMod = System.currentTimeMillis() % 1000;
+ if (currentTimeMod > 333) {
+ if (currentTimeMod < 666) {
+ str += ".";
+ } else {
+ str += "..";
+ }
+ }
- if (timeDiff > 20000) {
- Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "Its taking a while...",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + sizeX / 2f,
- guiTop + 111,
- true,
- 0
- );
Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "Try \"/api new\".",
+ str,
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 121,
+ guiTop + 101,
true,
0
);
- if (timeDiff > 60000) {
+
+ //This is just here to inform the player what to do
+ //like typing /api new or telling them to go find a psychotherapist
+ long timeDiff = System.currentTimeMillis() - startTime;
+
+ if (timeDiff > 20000) {
Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "Might be hypixel's fault.",
+ EnumChatFormatting.YELLOW + "Its taking a while...",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 131,
+ guiTop + 111,
true,
0
);
- if (timeDiff > 180000) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.YELLOW + "Try \"/api new\".",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + sizeX / 2f,
+ guiTop + 121,
+ true,
+ 0
+ );
+ if (timeDiff > 60000) {
Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "Wow you're still here?",
+ EnumChatFormatting.YELLOW + "Might be hypixel's fault.",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 141,
+ guiTop + 131,
true,
0
);
- if (timeDiff > 360000) {
- long second = (timeDiff / 1000) % 60;
- long minute = (timeDiff / (1000 * 60)) % 60;
- long hour = (timeDiff / (1000 * 60 * 60)) % 24;
-
- String time = String.format("%02d:%02d:%02d", hour, minute, second);
- Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "You've wasted your time here for: " + time,
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + sizeX / 2f,
- guiTop + 151,
- true,
- 0
- );
+ if (timeDiff > 180000) {
Utils.drawStringCentered(
- EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "What are you doing with your life?",
+ EnumChatFormatting.YELLOW + "Wow you're still here?",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 161,
+ guiTop + 141,
true,
0
);
- if (timeDiff > 600000) {
+ if (timeDiff > 360000) {
+ long second = (timeDiff / 1000) % 60;
+ long minute = (timeDiff / (1000 * 60)) % 60;
+ long hour = (timeDiff / (1000 * 60 * 60)) % 24;
+
+ String time = String.format("%02d:%02d:%02d", hour, minute, second);
Utils.drawStringCentered(
- EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "Maniac",
+ EnumChatFormatting.YELLOW + "You've wasted your time here for: " + time,
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 171,
+ guiTop + 151,
true,
0
);
- if (timeDiff > 1200000) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.YELLOW + "" + EnumChatFormatting.BOLD + "What are you doing with your life?",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + sizeX / 2f,
+ guiTop + 161,
+ true,
+ 0
+ );
+ if (timeDiff > 600000) {
Utils.drawStringCentered(
- EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You're a menace to society",
+ EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "Maniac",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 181,
+ guiTop + 171,
true,
0
);
- if (timeDiff > 1800000) {
+ if (timeDiff > 1200000) {
Utils.drawStringCentered(
- EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD +
- "You don't know what's gonna happen to you",
+ EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You're a menace to society",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 191,
+ guiTop + 181,
true,
0
);
- if (timeDiff > 3000000) {
+ if (timeDiff > 1800000) {
Utils.drawStringCentered(
- EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You really want this?",
+ EnumChatFormatting.RED +
+ "" +
+ EnumChatFormatting.BOLD +
+ "You don't know what's gonna happen to you",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 91,
+ guiTop + 191,
true,
0
);
- if (timeDiff > 3300000) {
+ if (timeDiff > 3000000) {
Utils.drawStringCentered(
- EnumChatFormatting.DARK_RED + "" + EnumChatFormatting.BOLD + "OW LORD FORGIVE ME FOR THIS",
+ EnumChatFormatting.RED + "" + EnumChatFormatting.BOLD + "You really want this?",
Minecraft.getMinecraft().fontRendererObj,
guiLeft + sizeX / 2f,
- guiTop + 71,
+ guiTop + 91,
true,
0
);
- if (timeDiff > 3600000) {
- throw new Error("Go do something productive") {
- @Override
- public void printStackTrace() {
- throw new Error("Go do something productive");
- }
- };
+ if (timeDiff > 3300000) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.DARK_RED +
+ "" +
+ EnumChatFormatting.BOLD +
+ "OW LORD FORGIVE ME FOR THIS",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + sizeX / 2f,
+ guiTop + 71,
+ true,
+ 0
+ );
+ if (timeDiff > 3600000) {
+ throw new Error("Go do something productive") {
+ @Override
+ public void printStackTrace() {
+ throw new Error("Go do something productive");
+ }
+ };
+ }
}
}
}
@@ -501,33 +724,61 @@ public class GuiProfileViewer extends GuiScreen {
}
}
}
- }
- break;
- case INVALID_NAME:
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "Invalid name or API is down!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + sizeX / 2f,
- guiTop + 101,
- true,
- 0
- );
- break;
- case NO_SKYBLOCK:
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "No skyblock data found!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + sizeX / 2f,
- guiTop + 101,
- true,
- 0
- );
- break;
+ break;
+ case INVALID_NAME:
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "Invalid name or API is down!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + sizeX / 2f,
+ guiTop + 101,
+ true,
+ 0
+ );
+ break;
+ case NO_SKYBLOCK:
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "No skyblock data found!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + sizeX / 2f,
+ guiTop + 101,
+ true,
+ 0
+ );
+ break;
+ }
}
lastTime = currentTime;
+ if (currentPage != ProfileViewerPage.LOADING && currentPage != ProfileViewerPage.INVALID_NAME) {
+ int ignoredTabs = 0;
+ List<Integer> configList = NotEnoughUpdates.INSTANCE.config.profileViewer.pageLayout;
+ for (int i = 0; i < configList.size(); i++) {
+ ProfileViewerPage iPage = ProfileViewerPage.getById(configList.get(i));
+ if (iPage == null) continue;
+ if (iPage.stack == null || (iPage == ProfileViewerPage.BINGO && !showBingoPage)) {
+ ignoredTabs++;
+ continue;
+ }
+ int i2 = i - ignoredTabs;
+ int x = guiLeft + i2 * 28;
+ int y = guiTop - 28;
+
+ if (mouseX > x && mouseX < x + 28) {
+ if (mouseY > y && mouseY < y + 32) {
+ if (!iPage.stack
+ .getTooltip(Minecraft.getMinecraft().thePlayer, false)
+ .isEmpty()) {
+ tooltipToDisplay = Collections.singletonList(iPage.stack
+ .getTooltip(Minecraft.getMinecraft().thePlayer, false)
+ .get(0));
+ }
+ }
+ }
+ }
+ }
+
if (tooltipToDisplay != null) {
List<String> grayTooltip = new ArrayList<>(tooltipToDisplay.size());
for (String line : tooltipToDisplay) {
@@ -540,9 +791,11 @@ public class GuiProfileViewer extends GuiScreen {
private void renderTabs(boolean renderPressed) {
int ignoredTabs = 0;
- for (int i = 0; i < ProfileViewerPage.values().length; i++) {
- ProfileViewerPage page = ProfileViewerPage.values()[i];
- if (page.stack == null) {
+ List<Integer> configList = NotEnoughUpdates.INSTANCE.config.profileViewer.pageLayout;
+ for (int i = 0; i < configList.size(); i++) {
+ ProfileViewerPage page = ProfileViewerPage.getById(configList.get(i));
+ if (page == null) continue;
+ if (page.stack == null || (page == ProfileViewerPage.BINGO && !showBingoPage)) {
ignoredTabs++;
continue;
}
@@ -598,9 +851,11 @@ public class GuiProfileViewer extends GuiScreen {
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
if (currentPage != ProfileViewerPage.LOADING && currentPage != ProfileViewerPage.INVALID_NAME) {
int ignoredTabs = 0;
- for (int i = 0; i < ProfileViewerPage.values().length; i++) {
- ProfileViewerPage page = ProfileViewerPage.values()[i];
- if (page.stack == null) {
+ List<Integer> configList = NotEnoughUpdates.INSTANCE.config.profileViewer.pageLayout;
+ for (int i = 0; i < configList.size(); i++) {
+ ProfileViewerPage page = ProfileViewerPage.getById(configList.get(i));
+ if (page == null) continue;
+ if (page.stack == null || (page == ProfileViewerPage.BINGO && !showBingoPage)) {
ignoredTabs++;
continue;
}
@@ -619,38 +874,13 @@ public class GuiProfileViewer extends GuiScreen {
}
}
}
- switch (currentPage) {
- case DUNG:
- mouseClickedDung(mouseX, mouseY, mouseButton);
- break;
- case INVS:
- inventoryTextField.setSize(88, 20);
- if (mouseX > guiLeft + 19 && mouseX < guiLeft + 19 + 88) {
- if (mouseY > guiTop + sizeY - 26 - 20 && mouseY < guiTop + sizeY - 26) {
- inventoryTextField.mouseClicked(mouseX, mouseY, mouseButton);
- playerNameTextField.otherComponentClick();
- return;
- }
- }
- break;
- case PETS:
- if (sortedPets == null) break;
- for (int i = petsPage * 20; i < Math.min(petsPage * 20 + 20, sortedPets.size()); i++) {
- int xIndex = (i % 20) % COLLS_XCOUNT;
- int yIndex = (i % 20) / COLLS_XCOUNT;
- float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
- float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
-
- if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) {
- if (mouseY > guiTop + y && mouseY < guiTop + y + 20) {
- selectedPet = i;
- return;
- }
- }
- }
- break;
+ if (pages.containsKey(currentPage)) {
+ if (pages.get(currentPage).mouseClicked(mouseX, mouseY, mouseButton)) {
+ return;
+ }
}
+
if (mouseX > guiLeft + sizeX - 100 && mouseX < guiLeft + sizeX) {
if (mouseY > guiTop + sizeY + 5 && mouseY < guiTop + sizeY + 25) {
playerNameTextField.mouseClicked(mouseX, mouseY, mouseButton);
@@ -658,14 +888,22 @@ public class GuiProfileViewer extends GuiScreen {
return;
}
}
- if (mouseX > guiLeft + 106 && mouseX < guiLeft + 106 + 100 && profile != null &&
- !profile.getProfileIds().isEmpty() && profileId != null) {
+ if (
+ mouseX > guiLeft + 106 &&
+ mouseX < guiLeft + 106 + 100 &&
+ profile != null &&
+ !profile.getProfileNames().isEmpty() &&
+ profileId != null
+ ) {
if (mouseY > guiTop + sizeY + 3 && mouseY < guiTop + sizeY + 23) {
try {
Desktop desk = Desktop.getDesktop();
- desk.browse(new URI(
- "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" +
- profileId));
+ desk.browse(
+ new URI(
+ "https://sky.shiiyu.moe/stats/" + profile.getHypixelProfile().get("displayname").getAsString() + "/" +
+ profileId
+ )
+ );
Utils.playPressSound();
return;
} catch (UnsupportedOperationException | IOException | URISyntaxException ignored) {
@@ -676,14 +914,14 @@ public class GuiProfileViewer extends GuiScreen {
}
}
- if (mouseX > guiLeft && mouseX < guiLeft + 100 && profile != null && !profile.getProfileIds().isEmpty()) {
+ if (mouseX > guiLeft && mouseX < guiLeft + 100 && profile != null && !profile.getProfileNames().isEmpty()) {
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
if (mouseY > guiTop + sizeY + 3 && mouseY < guiTop + sizeY + 23) {
- if (scaledResolution.getScaleFactor() == 4) {
+ if (scaledResolution.getScaleFactor() >= 4) {
profileDropdownSelected = false;
int profileNum = 0;
- for (int index = 0; index < profile.getProfileIds().size(); index++) {
- if (profile.getProfileIds().get(index).equals(profileId)) {
+ for (int index = 0; index < profile.getProfileNames().size(); index++) {
+ if (profile.getProfileNames().get(index).equals(profileId)) {
profileNum = index;
break;
}
@@ -693,10 +931,10 @@ public class GuiProfileViewer extends GuiScreen {
} else {
profileNum--;
}
- if (profileNum >= profile.getProfileIds().size()) profileNum = 0;
- if (profileNum < 0) profileNum = profile.getProfileIds().size() - 1;
+ if (profileNum >= profile.getProfileNames().size()) profileNum = 0;
+ if (profileNum < 0) profileNum = profile.getProfileNames().size() - 1;
- String newProfileId = profile.getProfileIds().get(profileNum);
+ String newProfileId = profile.getProfileNames().get(profileNum);
if (profileId != null && !profileId.equals(newProfileId)) {
resetCache();
}
@@ -704,12 +942,12 @@ public class GuiProfileViewer extends GuiScreen {
} else {
profileDropdownSelected = !profileDropdownSelected;
}
- } else if (scaledResolution.getScaleFactor() != 4 && profileDropdownSelected) {
+ } else if (scaledResolution.getScaleFactor() < 4 && profileDropdownSelected) {
int dropdownOptionSize = scaledResolution.getScaleFactor() == 3 ? 10 : 20;
int extraY = mouseY - (guiTop + sizeY + 23);
int index = extraY / dropdownOptionSize;
- if (index >= 0 && index < profile.getProfileIds().size()) {
- String newProfileId = profile.getProfileIds().get(index);
+ if (index >= 0 && index < profile.getProfileNames().size()) {
+ String newProfileId = profile.getProfileNames().get(index);
if (profileId != null && !profileId.equals(newProfileId)) {
resetCache();
}
@@ -728,25 +966,21 @@ public class GuiProfileViewer extends GuiScreen {
@Override
protected void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
- switch (currentPage) {
- case INVS:
- keyTypedInvs(typedChar, keyCode);
- inventoryTextField.keyTyped(typedChar, keyCode);
- break;
- case COLS:
- keyTypedCols(typedChar, keyCode);
- break;
- case DUNG:
- keyTypedDung(typedChar, keyCode);
- break;
+
+ if (pages.containsKey(currentPage)) {
+ pages.get(currentPage).keyTyped(typedChar, keyCode);
}
- if (playerNameTextField.getFocus() && !(currentPage == ProfileViewerPage.LOADING)) {
+
+ if (playerNameTextField.getFocus()) {
if (keyCode == Keyboard.KEY_RETURN) {
currentPage = ProfileViewerPage.LOADING;
- NotEnoughUpdates.profileViewer.getProfileByName(playerNameTextField.getText(), profile -> { //todo: invalid name
- if (profile != null) profile.resetCache();
- Minecraft.getMinecraft().displayGuiScreen(new GuiProfileViewer(profile));
- });
+ NotEnoughUpdates.profileViewer.getProfileByName(
+ playerNameTextField.getText(),
+ profile -> { //todo: invalid name
+ if (profile != null) profile.resetCache();
+ Minecraft.getMinecraft().displayGuiScreen(new GuiProfileViewer(profile));
+ }
+ );
}
playerNameTextField.keyTyped(typedChar, keyCode);
}
@@ -756,887 +990,12 @@ public class GuiProfileViewer extends GuiScreen {
protected void mouseReleased(int mouseX, int mouseY, int mouseButton) {
super.mouseReleased(mouseX, mouseY, mouseButton);
- switch (currentPage) {
- case INVS:
- mouseReleasedInvs(mouseX, mouseY, mouseButton);
- break;
- case COLS:
- mouseReleasedCols(mouseX, mouseY, mouseButton);
- break;
- case PETS:
- mouseReleasedPets(mouseX, mouseY, mouseButton);
- }
- }
-
- protected void mouseClickedDung(int mouseX, int mouseY, int mouseButton) {
- if (mouseX >= guiLeft + 50 && mouseX <= guiLeft + 70 &&
- mouseY >= guiTop + 54 && mouseY <= guiTop + 64) {
- dungeonLevelTextField.mouseClicked(mouseX, mouseY, mouseButton);
- } else {
- dungeonLevelTextField.otherComponentClick();
- }
-
- int cW = fontRendererObj.getStringWidth("Calculate");
- if (mouseX >= guiLeft + 23 + 110 - 17 - cW && mouseX <= guiLeft + 23 + 110 - 17 &&
- mouseY >= guiTop + 55 && mouseY <= guiTop + 65) {
- calculateFloorLevelXP();
- }
-
- int y = guiTop + 142;
-
- if (mouseY >= y - 2 && mouseY <= y + 9) {
- for (int i = 1; i <= 7; i++) {
- int w = fontRendererObj.getStringWidth("" + i);
-
- int x = guiLeft + 23 + 110 * i / 8 - w / 2;
-
- if (mouseX >= x - 2 && mouseX <= x + 7) {
- floorTime = i;
- return;
- }
- }
- }
- if (mouseX >= guiLeft - 29 && mouseX <= guiLeft) {
- if (mouseY >= guiTop && mouseY <= guiTop + 28) {
- onMasterMode = false;
- return;
- } else if (mouseY + 28 >= guiTop && mouseY <= guiTop + 28 * 2) {
- onMasterMode = true;
- return;
- }
- }
- }
-
- protected void keyTypedDung(char typedChar, int keyCode) {
- dungeonLevelTextField.keyTyped(typedChar, keyCode);
- }
-
- protected void keyTypedInvs(char typedChar, int keyCode) throws IOException {
- switch (keyCode) {
- case Keyboard.KEY_1:
- case Keyboard.KEY_NUMPAD1:
- selectedInventory = "inv_contents";
- break;
- case Keyboard.KEY_2:
- case Keyboard.KEY_NUMPAD2:
- selectedInventory = "ender_chest_contents";
- break;
- case Keyboard.KEY_3:
- case Keyboard.KEY_NUMPAD3:
- selectedInventory = "backpack_contents";
- break;
- case Keyboard.KEY_4:
- case Keyboard.KEY_NUMPAD4:
- selectedInventory = "personal_vault_contents";
- break;
- case Keyboard.KEY_5:
- case Keyboard.KEY_NUMPAD5:
- selectedInventory = "talisman_bag";
- break;
- case Keyboard.KEY_6:
- case Keyboard.KEY_NUMPAD6:
- selectedInventory = "wardrobe_contents";
- break;
- case Keyboard.KEY_7:
- case Keyboard.KEY_NUMPAD7:
- selectedInventory = "fishing_bag";
- break;
- case Keyboard.KEY_8:
- case Keyboard.KEY_NUMPAD8:
- selectedInventory = "potion_bag";
- break;
-
- }
- Utils.playPressSound();
- }
-
- protected void keyTypedCols(char typedChar, int keyCode) throws IOException {
- ItemStack stack = null;
- Iterator<ItemStack> items = ProfileViewer.getCollectionCatToCollectionMap().keySet().iterator();
- switch (keyCode) {
- case Keyboard.KEY_5:
- case Keyboard.KEY_NUMPAD5:
- stack = items.next();
- case Keyboard.KEY_4:
- case Keyboard.KEY_NUMPAD4:
- stack = items.next();
- case Keyboard.KEY_3:
- case Keyboard.KEY_NUMPAD3:
- stack = items.next();
- case Keyboard.KEY_2:
- case Keyboard.KEY_NUMPAD2:
- stack = items.next();
- case Keyboard.KEY_1:
- case Keyboard.KEY_NUMPAD1:
- stack = items.next();
- }
- if (stack != null) {
- selectedCollectionCategory = stack;
- }
- Utils.playPressSound();
- }
-
- private void mouseReleasedPets(int mouseX, int mouseY, int mouseButton) {
- if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
- if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) {
- if (petsPage > 0) {
- petsPage--;
- }
- return;
- } else if (mouseX > guiLeft + 100 + 15 && mouseX < guiLeft + 100 + 20 + 12) {
- if (sortedPets != null && petsPage < Math.ceil(sortedPets.size() / 20f) - 1) {
- petsPage++;
- }
- return;
- }
- }
- }
-
- private void mouseReleasedInvs(int mouseX, int mouseY, int mouseButton) {
- if (mouseButton == 0) {
- int i = 0;
- for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) {
- int xIndex = i % 3;
- int yIndex = i / 3;
-
- int x = guiLeft + 19 + 34 * xIndex;
- int y = guiTop + 26 + 34 * yIndex;
-
- if (mouseX >= x && mouseX <= x + 16) {
- if (mouseY >= y && mouseY <= y + 16) {
- if (selectedInventory != entry.getKey()) Utils.playPressSound();
- selectedInventory = entry.getKey();
- return;
- }
- }
-
- i++;
- }
-
- JsonObject inventoryInfo = profile.getInventoryInfo(profileId);
- if (inventoryInfo == null) return;
-
- ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory);
- if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1;
- if (currentInventoryIndex < 0) currentInventoryIndex = 0;
-
- ItemStack[][] inventory = inventories[currentInventoryIndex];
- if (inventory == null) return;
-
- int inventoryRows = inventory.length;
- int invSizeY = inventoryRows * 18 + 17 + 7;
-
- int y = guiTop + 101 - invSizeY / 2;
- int staticSelectorHeight = guiTop + 177;
-
- if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) {
- if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) {
- if (mouseX < guiLeft + 320) {
- currentInventoryIndex--;
- } else {
- currentInventoryIndex++;
- }
- }
- }
- }
- }
-
- private ItemStack selectedCollectionCategory = null;
-
- private void mouseReleasedCols(int mouseX, int mouseY, int mouseButton) {
- int collectionCatSize = ProfileViewer.getCollectionCatToCollectionMap().size();
- int collectionCatYSize = (int) (162f / (collectionCatSize - 1 + 0.0000001f));
- int yIndex = 0;
- for (ItemStack stack : ProfileViewer.getCollectionCatToCollectionMap().keySet()) {
- if (mouseX > guiLeft + 7 && mouseX < guiLeft + 7 + 20) {
- if (mouseY > guiTop + 10 + collectionCatYSize * yIndex &&
- mouseY < guiTop + 10 + collectionCatYSize * yIndex + 20) {
- selectedCollectionCategory = stack;
- Utils.playPressSound();
- return;
- }
- }
- yIndex++;
- }
- }
-
- private static final ItemStack DEADBUSH = new ItemStack(Item.getItemFromBlock(Blocks.deadbush));
- private static final ItemStack iron_pick = new ItemStack(Items.iron_pickaxe);
- private static final ItemStack[] BOSS_HEADS = new ItemStack[7];
-
- private final HashMap<String, ProfileViewer.Level> levelObjCatas = new HashMap<>();
- private final HashMap<String, ProfileViewer.Level> levelObjhotms = new HashMap<>();
- private final HashMap<String, HashMap<String, ProfileViewer.Level>> levelObjClasseses = new HashMap<>();
-
- private final GuiElementTextField dungeonLevelTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT);
-
- private static final String[] dungSkillsName = {"Healer", "Mage", "Berserk", "Archer", "Tank"};
- private static final ItemStack[] dungSkillsStack = {
- new ItemStack(Items.potionitem, 1, 16389),
- new ItemStack(Items.blaze_rod),
- new ItemStack(Items.iron_sword),
- new ItemStack(Items.bow),
- new ItemStack(Items.leather_chestplate)
- };
- private static final String[] bossFloorArr = {"Bonzo", "Scarf", "Professor", "Thorn", "Livid", "Sadan", "Necron"};
- private static final String[] bossFloorHeads = {
- "12716ecbf5b8da00b05f316ec6af61e8bd02805b21eb8e440151468dc656549c",
- "7de7bbbdf22bfe17980d4e20687e386f11d59ee1db6f8b4762391b79a5ac532d",
- "9971cee8b833a62fc2a612f3503437fdf93cad692d216b8cf90bbb0538c47dd8",
- "8b6a72138d69fbbd2fea3fa251cabd87152e4f1c97e5f986bf685571db3cc0",
- "c1007c5b7114abec734206d4fc613da4f3a0e99f71ff949cedadc99079135a0b",
- "fa06cb0c471c1c9bc169af270cd466ea701946776056e472ecdaeb49f0f4a4dc",
- "a435164c05cea299a3f016bbbed05706ebb720dac912ce4351c2296626aecd9a"
- };
- private static int floorTime = 7;
- private int floorLevelTo = -1;
- private int floorLevelToXP = -1;
-
- private void calculateFloorLevelXP() {
- JsonObject leveling = Constants.LEVELING;
- if (leveling == null) return;
- ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId);
- if (levelObjCata == null) return;
-
- try {
- dungeonLevelTextField.setCustomBorderColour(0xffffffff);
- floorLevelTo = Integer.parseInt(dungeonLevelTextField.getText());
-
- JsonArray levelingArray = Utils.getElement(leveling, "catacombs").getAsJsonArray();
-
- float remaining = -((levelObjCata.level % 1) * levelObjCata.maxXpForLevel);
-
- for (int level = 0; level < Math.min(floorLevelTo, levelingArray.size()); level++) {
- if (level < Math.floor(levelObjCata.level)) {
- continue;
- }
- remaining += levelingArray.get(level).getAsFloat();
- }
-
- if (remaining < 0) {
- remaining = 0;
- }
- floorLevelToXP = (int) remaining;
- } catch (Exception e) {
- dungeonLevelTextField.setCustomBorderColour(0xffff0000);
- }
- }
-
- private static final LinkedHashMap<String, ItemStack> dungeonsModeIcons = new LinkedHashMap<String, ItemStack>() {{
- put(
- "catacombs",
- Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get("DUNGEON_STONE")), EnumChatFormatting.GRAY + "Normal Mode", true)
- );
- put(
- "master_catacombs",
- Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get("MASTER_SKULL_TIER_7")), EnumChatFormatting.GRAY + "Master Mode", true)
- );
- }};
-
- private void drawDungPage(int mouseX, int mouseY, float partialTicks) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dung);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- JsonObject hypixelInfo = profile.getHypixelProfile();
- if (hypixelInfo == null) return;
- JsonObject profileInfo = profile.getProfileInformation(profileId);
- if (profileInfo == null) return;
-
- JsonObject leveling = Constants.LEVELING;
- if (leveling == null) return;
-
- int sectionWidth = 110;
-
- String dungeonString = onMasterMode ? "master_catacombs" : "catacombs";
-
- //Utils.drawStringCentered((onMasterMode?"Master Mode":"Catacombs"),fontRendererObj,(guiLeft+sizeX/2), guiTop+10, true, 0xffff0000);
- Utils.renderShadowedString(EnumChatFormatting.RED + (onMasterMode ? "Master Mode" : "Catacombs"),
- (guiLeft + sizeX / 2), guiTop + 5, sectionWidth
- );
-
- ProfileViewer.Level levelObjCata = levelObjCatas.get(profileId);
- //Catacombs level thingy
- {
- if (levelObjCata == null) {
- float cataXp = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.experience"
- ), 0);
- levelObjCata = ProfileViewer.getLevel(Utils.getElement(leveling, "catacombs").getAsJsonArray(),
- cataXp, 50, false
- );
- levelObjCata.totalXp = cataXp;
- levelObjCatas.put(profileId, levelObjCata);
- }
-
- String skillName = EnumChatFormatting.RED + "Catacombs";
- float level = levelObjCata.level;
- int levelFloored = (int) Math.floor(level);
-
- if (floorLevelTo == -1 && levelFloored >= 0) {
- dungeonLevelTextField.setText("" + (levelFloored + 1));
- calculateFloorLevelXP();
- }
-
- int x = guiLeft + 23;
- int y = guiTop + 25;
-
- renderXpBar(skillName, DEADBUSH, x, y, sectionWidth, levelObjCata, mouseX, mouseY);
-
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Until Cata " + floorLevelTo + ": ",
- EnumChatFormatting.WHITE + shortNumberFormat(floorLevelToXP, 0), x, y + 16, sectionWidth
- );
-
- if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && !onMasterMode) {
- float F5 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.tier_completions." + 5
- ), 0)); //this can prob be done better
- float F6 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.tier_completions." + 6
- ), 0));
- float F7 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.tier_completions." + 7
- ), 0));
- if (F5 > 150) {
- F5 = 150;
- }
- if (F6 > 100) {
- F6 = 100;
- }
- if (F7 > 50) {
- F7 = 50;
- }
- float xpF5 = 2000 * (F5 / 100 + 1);
- float xpF6 = 4000 * (F6 / 100 + 1);
- float xpF7 = 20000 * (F7 / 100 + 1);
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- xpF5 *= 1.1;
- xpF6 *= 1.1;
- xpF7 *= 1.1;
- }
-
- long runsF5 = (int) Math.ceil(floorLevelToXP / xpF5);
- long runsF6 = (int) Math.ceil(floorLevelToXP / xpF6);
- long runsF7 = (int) Math.ceil(floorLevelToXP / xpF7);
-
- float timeF5 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.fastest_time_s_plus.5"
- ), 0);
- float timeF6 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.fastest_time_s_plus.6"
- ), 0);
- float timeF7 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.fastest_time_s_plus.7"
- ), 0);
-
- tooltipToDisplay = Lists.newArrayList(
- String.format("# F5 Runs (%s xp) : %d", shortNumberFormat(xpF5, 0), runsF5),
- String.format("# F6 Runs (%s xp) : %d", shortNumberFormat(xpF6, 0), runsF6),
- String.format("# F7 Runs (%s xp) : %d", shortNumberFormat(xpF7, 0), runsF7),
- ""
- );
- boolean hasTime = false;
- if (timeF5 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (F5) : %s",
- Utils.prettyTime(runsF5 * (long) (timeF5 * 1.2))
- ));
- hasTime = true;
- }
- if (timeF6 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (F6) : %s",
- Utils.prettyTime(runsF6 * (long) (timeF6 * 1.2))
- ));
- hasTime = true;
- }
- if (timeF7 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (F7) : %s",
- Utils.prettyTime(runsF7 * (long) (timeF7 * 1.2))
- ));
- hasTime = true;
- }
- if (hasTime) {
- tooltipToDisplay.add("");
- }
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- tooltipToDisplay.add(
- "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]");
- }
- if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) tooltipToDisplay.add("");
- tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run].");
- tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run");
- tooltipToDisplay.add(
- "The " + EnumChatFormatting.DARK_PURPLE + "Catacombs Expert Ring" + EnumChatFormatting.GRAY +
- " is assumed to be used, unless " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY +
- " is held.");
- tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%");
- } else {
- tooltipToDisplay.add(
- "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]");
- }
- }
-
- if (mouseX > x && mouseX < x + sectionWidth && mouseY > y + 16 && mouseY < y + 24 && onMasterMode) {
- float M3 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.tier_completions." + 3
- ), 0));
- float M4 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.tier_completions." + 4
- ), 0));
- float M5 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.tier_completions." + 5
- ), 0)); //this can prob be done better
- float M6 = (Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.tier_completions." + 6
- ), 0));
- if (M3 > 50) {
- M3 = 50;
- }
- if (M4 > 50) {
- M4 = 50;
- }
- if (M5 > 50) {
- M5 = 50;
- }
- if (M6 > 50) {
- M6 = 50;
- }
- float xpM3 = 36500 * (M3 / 100 + 1);
- float xpM4 = 48500 * (M4 / 100 + 1);
- float xpM5 = 70000 * (M5 / 100 + 1);
- float xpM6 = 100000 * (M6 / 100 + 1);
- //No clue if M3 or M4 xp values are right
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- xpM3 *= 1.1;
- xpM4 *= 1.1;
- xpM5 *= 1.1;
- xpM6 *= 1.1;
- }
-
- long runsM3 = (int) Math.ceil(floorLevelToXP / xpM3);
- long runsM4 = (int) Math.ceil(floorLevelToXP / xpM4);
- long runsM5 = (int) Math.ceil(floorLevelToXP / xpM5);
- long runsM6 = (int) Math.ceil(floorLevelToXP / xpM6);
-
- float timeM3 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.3"
- ), 0);
- float timeM4 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.4"
- ), 0);
- float timeM5 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.5"
- ), 0);
- float timeM6 = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.fastest_time_s_plus.6"
- ), 0);
-
- tooltipToDisplay = Lists.newArrayList(
- String.format("# M3 Runs (%s xp) : %d", shortNumberFormat(xpM3, 0), runsM3),
- String.format("# M4 Runs (%s xp) : %d", shortNumberFormat(xpM4, 0), runsM4),
- String.format("# M5 Runs (%s xp) : %d", shortNumberFormat(xpM5, 0), runsM5),
- String.format("# M6 Runs (%s xp) : %d", shortNumberFormat(xpM6, 0), runsM6),
- ""
- );
- boolean hasTime = false;
- if (timeM3 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (M3) : %s",
- Utils.prettyTime(runsM3 * (long) (timeM3 * 1.2))
- ));
- hasTime = true;
- }
- if (timeM4 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (M4) : %s",
- Utils.prettyTime(runsM4 * (long) (timeM4 * 1.2))
- ));
- hasTime = true;
- }
- if (timeM5 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (M5) : %s",
- Utils.prettyTime(runsM5 * (long) (timeM5 * 1.2))
- ));
- hasTime = true;
- }
- if (timeM6 > 1000) {
- tooltipToDisplay.add(String.format(
- "Expected Time (M6) : %s",
- Utils.prettyTime(runsM6 * (long) (timeM6 * 1.2))
- ));
- hasTime = true;
- }
- if (hasTime) {
- tooltipToDisplay.add("");
- }
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- tooltipToDisplay.add(
- "[Hold " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY + " to show without Expert Ring]");
- }
- if (Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
- if (!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) tooltipToDisplay.add("");
- tooltipToDisplay.add("Number of runs is calculated as [Remaining XP]/[XP per Run].");
- tooltipToDisplay.add("The [XP per Run] is the average xp gained from an S+ run");
- tooltipToDisplay.add(
- "The " + EnumChatFormatting.DARK_PURPLE + "Catacombs Expert Ring" + EnumChatFormatting.GRAY +
- " is assumed to be used, unless " + EnumChatFormatting.YELLOW + "SHIFT" + EnumChatFormatting.GRAY +
- " is held.");
- tooltipToDisplay.add("[Time per run] is calculated using Fastest S+ x 120%");
- } else {
- tooltipToDisplay.add(
- "[Hold " + EnumChatFormatting.YELLOW + "CTRL" + EnumChatFormatting.GRAY + " to see details]");
- }
- }
-
- dungeonLevelTextField.setSize(20, 10);
- dungeonLevelTextField.render(x + 22, y + 29);
- int calcLen = fontRendererObj.getStringWidth("Calculate");
- Utils.renderShadowedString(EnumChatFormatting.WHITE + "Calculate", x + sectionWidth - 17 - calcLen / 2f,
- y + 30, 100
- );
-
- //Random stats
-
- float secrets = Utils.getElementAsFloat(Utils.getElement(
- hypixelInfo,
- "achievements.skyblock_treasure_hunter"
- ), 0);
- float totalRuns = 0;
- float totalRunsF = 0;
- float totalRunsF5 = 0;
- for (int i = 1; i <= 7; i++) {
- float runs = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.tier_completions." + i
- ), 0);
- totalRunsF += runs;
- if (i >= 5) {
- totalRunsF5 += runs;
- }
- }
- float totalRunsM = 0;
- float totalRunsM5 = 0;
- for (int i = 1; i <= 7; i++) {
- float runs = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.tier_completions." + i
- ), 0);
- totalRunsM += runs;
- if (i >= 5) {
- totalRunsM5 += runs;
- }
- }
- totalRuns = totalRunsF + totalRunsM;
-
- float mobKills = 0;
- float mobKillsF = 0;
- float mobKillsF5 = 0;
- for (int i = 1; i <= 7; i++) {
- float kills = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.catacombs.mobs_killed." + i
- ), 0);
- mobKillsF += kills;
- if (i >= 5) {
- mobKillsF5 += kills;
- }
- }
- float mobKillsM = 0;
- float mobKillsM5 = 0;
- for (int i = 1; i <= 7; i++) {
- float kills = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types.master_catacombs.mobs_killed." + i
- ), 0);
- mobKillsM += kills;
- if (i >= 5) {
- mobKillsM5 += kills;
- }
- }
- mobKills = mobKillsF + mobKillsM;
-
- int miscTopY = y + 55;
-
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Total Runs " + (onMasterMode ? "M" : "F"),
- EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM : totalRunsF)),
- x,
- miscTopY,
- sectionWidth
- );
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Total Runs (" + (onMasterMode ? "M" : "F") + "5-7) ",
- EnumChatFormatting.WHITE.toString() + ((int) (onMasterMode ? totalRunsM5 : totalRunsF5)),
- x,
- miscTopY + 10,
- sectionWidth
- );
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Secrets (Total) ",
- EnumChatFormatting.WHITE + shortNumberFormat(secrets, 0), x, miscTopY + 20, sectionWidth
- );
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Secrets (/Run) ",
- EnumChatFormatting.WHITE.toString() + (Math.round(secrets / Math.max(1, totalRuns) * 100) / 100f),
- x,
- miscTopY + 30,
- sectionWidth
- );
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Mob Kills (Total) ",
- EnumChatFormatting.WHITE + shortNumberFormat(mobKills, 0), x, miscTopY + 40, sectionWidth
- );
-
- int y3 = y + 117;
-
- for (int i = 1; i <= 7; i++) {
- int w = fontRendererObj.getStringWidth("" + i);
-
- int bx = x + sectionWidth * i / 8 - w / 2;
-
- boolean invert = i == floorTime;
- float uMin = 20 / 256f;
- float uMax = 29 / 256f;
- float vMin = 0 / 256f;
- float vMax = 11 / 256f;
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(bx - 2, y3 - 2, 9, 11,
- invert ? uMax : uMin, invert ? uMin : uMax,
- invert ? vMax : vMin, invert ? vMin : vMax, GL11.GL_NEAREST
- );
-
- Utils.renderShadowedString(EnumChatFormatting.WHITE.toString() + i, bx + w / 2, y3, 10);
- }
-
- float timeNorm = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types." + dungeonString + ".fastest_time." + floorTime
- ), 0);
- float timeS = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types." + dungeonString + ".fastest_time_s." + floorTime
- ), 0);
- float timeSPLUS = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types." + dungeonString + ".fastest_time_s_plus." + floorTime
- ), 0);
- String timeNormStr = timeNorm <= 0 ? "N/A" : Utils.prettyTime((long) timeNorm);
- String timeSStr = timeS <= 0 ? "N/A" : Utils.prettyTime((long) timeS);
- String timeSPlusStr = timeSPLUS <= 0 ? "N/A" : Utils.prettyTime((long) timeSPLUS);
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " ",
- EnumChatFormatting.WHITE + timeNormStr, x, y3 + 10, sectionWidth
- );
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " S",
- EnumChatFormatting.WHITE + timeSStr, x, y3 + 20, sectionWidth
- );
- Utils.renderAlignedString(EnumChatFormatting.YELLOW + "Floor " + floorTime + " S+",
- EnumChatFormatting.WHITE + timeSPlusStr, x, y3 + 30, sectionWidth
- );
- }
-
- //Completions
- {
- int x = guiLeft + 161;
- int y = guiTop + 27;
-
- Utils.renderShadowedString(EnumChatFormatting.RED + "Boss Collections",
- x + sectionWidth / 2, y, sectionWidth
- );
- for (int i = 1; i <= 7; i++) {
- float compl = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.dungeon_types." + dungeonString + ".tier_completions." + i
- ), 0);
-
- if (BOSS_HEADS[i - 1] == null) {
- String textureLink = bossFloorHeads[i - 1];
-
- String b64Decoded =
- "{\"textures\":{\"SKIN\":{\"url\":\"http://textures.minecraft.net/texture/" + textureLink + "\"}}}";
- String b64Encoded = new String(Base64.getEncoder().encode(b64Decoded.getBytes()));
-
- ItemStack stack = new ItemStack(Items.skull, 1, 3);
- NBTTagCompound nbt = new NBTTagCompound();
- NBTTagCompound skullOwner = new NBTTagCompound();
- NBTTagCompound properties = new NBTTagCompound();
- NBTTagList textures = new NBTTagList();
- NBTTagCompound textures_0 = new NBTTagCompound();
-
- String uuid = UUID.nameUUIDFromBytes(b64Encoded.getBytes()).toString();
- skullOwner.setString("Id", uuid);
- skullOwner.setString("Name", uuid);
-
- textures_0.setString("Value", b64Encoded);
- textures.appendTag(textures_0);
-
- properties.setTag("textures", textures);
- skullOwner.setTag("Properties", properties);
- nbt.setTag("SkullOwner", skullOwner);
- stack.setTagCompound(nbt);
-
- BOSS_HEADS[i - 1] = stack;
- }
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(x - 4, y + 10 + 20 * (i - 1), 0);
- GlStateManager.scale(1.3f, 1.3f, 1);
- Utils.drawItemStack(BOSS_HEADS[i - 1], 0, 0);
- GlStateManager.popMatrix();
-
- Utils.renderAlignedString(String.format(
- EnumChatFormatting.YELLOW + "%s (" + (onMasterMode ? "M" : "F") + "%d) ",
- bossFloorArr[i - 1],
- i
- ),
- EnumChatFormatting.WHITE.toString() + (int) compl,
- x + 16, y + 18 + 20 * (i - 1), sectionWidth - 15
- );
-
- }
- }
-
- //Skills
- {
- int x = guiLeft + 298;
- int y = guiTop + 27;
-
- //Gui.drawRect(x, y, x+120, y+147, 0xffffffff);
-
- Utils.renderShadowedString(EnumChatFormatting.DARK_PURPLE + "Class Levels",
- x + sectionWidth / 2, y, sectionWidth
- );
-
- JsonElement activeClassElement = Utils.getElement(profileInfo, "dungeons.selected_dungeon_class");
- String activeClass = null;
- if (activeClassElement instanceof JsonPrimitive && ((JsonPrimitive) activeClassElement).isString()) {
- activeClass = activeClassElement.getAsString();
- }
-
- for (int i = 0; i < dungSkillsName.length; i++) {
- String skillName = dungSkillsName[i];
-
- HashMap<String, ProfileViewer.Level> levelObjClasses =
- levelObjClasseses.computeIfAbsent(profileId, k -> new HashMap<>());
- if (!levelObjClasses.containsKey(skillName)) {
- float cataXp = Utils.getElementAsFloat(Utils.getElement(
- profileInfo,
- "dungeons.player_classes." + skillName.toLowerCase() + ".experience"
- ), 0);
- ProfileViewer.Level levelObj =
- ProfileViewer.getLevel(Utils.getElement(leveling, "catacombs").getAsJsonArray(),
- cataXp, 50, false
- );
- levelObjClasses.put(skillName, levelObj);
- }
-
- String colour = EnumChatFormatting.WHITE.toString();
- if (skillName.toLowerCase().equals(activeClass)) {
- colour = EnumChatFormatting.GREEN.toString();
- }
-
- ProfileViewer.Level levelObj = levelObjClasses.get(skillName);
-
- renderXpBar(colour + skillName, dungSkillsStack[i], x, y + 20 + 29 * i, sectionWidth, levelObj, mouseX, mouseY);
- }
+ if (pages.containsKey(currentPage)) {
+ pages.get(currentPage).mouseReleased(mouseX, mouseY, mouseButton);
}
-
- drawSideButtons();
-
- //drawSideButton(0, dungeonsModeIcons.get("catacombs"), true);
- //drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true);
- //drawSideButton(1, dungeonsModeIcons.get("catacombs"), true);
- //drawSideButton(2, dungeonsModeIcons.get("catacombs"), false);
}
- private boolean onMasterMode = false;
-
- //TODO: improve this shit
- private void drawSideButtons() {
- // GlStateManager.pushMatrix();
- GlStateManager.enableDepth();
- GlStateManager.translate(0, 0, 5);
- if (onMasterMode) {
- drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), true);
- } else {
- drawSideButton(0, dungeonsModeIcons.get("catacombs"), true);
- }
- GlStateManager.translate(0, 0, -3);
-
- GlStateManager.translate(0, 0, -2);
- if (!onMasterMode) {
- drawSideButton(1, dungeonsModeIcons.get("master_catacombs"), false);
- } else {
- drawSideButton(0, dungeonsModeIcons.get("catacombs"), false);
- }
- GlStateManager.disableDepth();
- //GlStateManager.popMatrix();
- }
-
- private void drawSideButton(int yIndex, ItemStack itemStack, boolean pressed) {
- GlStateManager.disableLighting();
- GlStateManager.enableBlend();
- GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
- GlStateManager.enableAlpha();
- GlStateManager.alphaFunc(516, 0.1F);
-
- int x = guiLeft - 28;
- int y = guiTop + yIndex * 28;
-
- float uMin = 193 / 256f;
- float uMax = 223 / 256f;
- float vMin = 200 / 256f;
- float vMax = 228 / 256f;
- if (pressed) {
- uMin = 224 / 256f;
- uMax = 1f;
-
- if (yIndex != 0) {
- vMin = 228 / 256f;
- vMax = 1f;
- }
-
- renderBlurredBackground(width, height, x + 2, y + 2, 30, 28 - 4);
- } else {
- renderBlurredBackground(width, height, x + 2, y + 2, 28 - 2, 28 - 4);
- }
-
- GlStateManager.disableLighting();
- GlStateManager.enableBlend();
- GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
- GlStateManager.enableAlpha();
- GlStateManager.alphaFunc(516, 0.1F);
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
-
- Utils.drawTexturedRect(x, y, pressed ? 32 : 28, 28, uMin, uMax, vMin, vMax, GL11.GL_NEAREST);
-
- GlStateManager.enableDepth();
- Utils.drawItemStack(itemStack, x + 8, y + 7);
- }
-
- private void renderXpBar(
+ public void renderXpBar(
String skillName,
ItemStack stack,
int x,
@@ -1654,24 +1013,29 @@ public class GuiProfileViewer extends GuiScreen {
if (levelObj.maxed) {
renderGoldBar(x, y + 6, xSize);
} else {
- renderBar(x, y + 6, xSize, level % 1);
+ if (skillName.contains("Catacombs") && levelObj.level >= 50) {
+ renderGoldBar(x, y + 6, xSize);
+ } else {
+ renderBar(x, y + 6, xSize, level % 1);
+ }
}
if (mouseX > x && mouseX < x + 120) {
if (mouseY > y - 4 && mouseY < y + 13) {
String levelStr;
String totalXpStr = null;
+ if (skillName.contains("Catacombs")) totalXpStr =
+ EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE +
+ numberFormat.format(levelObj.totalXp);
if (levelObj.maxed) {
levelStr = EnumChatFormatting.GOLD + "MAXED!";
- if (skillName.contains("Catacombs"))
- totalXpStr = EnumChatFormatting.GRAY + "Total XP: " + EnumChatFormatting.DARK_PURPLE +
- Utils.formatNumberWithDots((long) levelObj.totalXp);
} else {
int maxXp = (int) levelObj.maxXpForLevel;
- levelStr = EnumChatFormatting.DARK_PURPLE + shortNumberFormat(
- Math.round((level % 1) * maxXp),
- 0
- ) + "/" + shortNumberFormat(maxXp, 0);
+ levelStr =
+ EnumChatFormatting.DARK_PURPLE +
+ StringUtils.shortNumberFormat(Math.round((level % 1) * maxXp)) +
+ "/" +
+ StringUtils.shortNumberFormat(maxXp);
}
if (totalXpStr != null) {
tooltipToDisplay = Utils.createList(levelStr, totalXpStr);
@@ -1681,6 +1045,12 @@ public class GuiProfileViewer extends GuiScreen {
}
}
+ NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs
+ NBTTagCompound display = new NBTTagCompound();
+ display.setString("Name", skillName);
+ nbt.setTag("display", display);
+ stack.setTagCompound(nbt);
+
GL11.glTranslatef((x), (y - 6f), 0);
GL11.glScalef(0.7f, 0.7f, 1);
Utils.drawItemStackLinear(stack, 0, 0);
@@ -1688,3146 +1058,11 @@ public class GuiProfileViewer extends GuiScreen {
GL11.glTranslatef(-(x), -(y - 6f), 0);
}
- public static class PetLevel {
- public float level;
- public float currentLevelRequirement;
- public float maxXP;
- public float levelPercentage;
- public float levelXp;
- public float totalXp;
- }
-
- private static JsonObject getPetInfo(String pet_name, String rarity) {
- JsonObject petInfo = new JsonObject();
- //System.out.println(pet_name);
- //System.out.println(rarity);
-
- if (Constants.PETS.has("custom_pet_leveling") &&
- Constants.PETS.getAsJsonObject("custom_pet_leveling").has(pet_name)) {
- JsonObject pet = Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(pet_name);
- if (pet.has("type") && pet.has("pet_levels")) {
- int type = pet.get("type").getAsInt();
- switch (type) {
- case 1:
- JsonArray defaultLevels = Constants.PETS.getAsJsonArray("pet_levels");
- defaultLevels.addAll(pet.getAsJsonArray("pet_levels"));
- petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels"));
- break;
- case 2:
- petInfo.add("pet_levels", pet.getAsJsonArray("pet_levels"));
- break;
- default:
- petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels"));
- break;
- }
- } else {
- petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels"));
- }
- if (pet.has("max_level")) {
- petInfo.add("max_level", pet.get("max_level"));
- } else {
- petInfo.add("max_level", new JsonPrimitive(100));
- }
-
- if (pet.has("pet_rarity_offset")) {
- petInfo.add("offset", pet.get("pet_rarity_offset"));
- } else {
- petInfo.add("offset", Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity));
- }
-
- } else {
- //System.out.println("Default Path");
- petInfo.add("offset", Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity));
- petInfo.add("max_level", new JsonPrimitive(100));
- petInfo.add("pet_levels", Constants.PETS.getAsJsonArray("pet_levels"));
- }
-
- return petInfo;
-
- }
-
- public static PetLevel getPetLevel(String pet_name, String rarity, float exp) {
- JsonObject petInfo = getPetInfo(pet_name, rarity);
- int offset = petInfo.get("offset").getAsInt();
- int maxPetLevel = petInfo.get("max_level").getAsInt();
- JsonArray levels = petInfo.getAsJsonArray("pet_levels");
-
- float xpTotal = 0;
- float level = 1;
- float currentLevelRequirement = 0;
- float currentLevelProgress = 0;
-
- boolean addLevel = true;
-
- for (int i = offset; i < offset + maxPetLevel - 1; i++) {
- if (addLevel) {
- currentLevelRequirement = levels.get(i).getAsFloat();
- xpTotal += currentLevelRequirement;
- if (xpTotal > exp) {
- currentLevelProgress = (exp - (xpTotal - currentLevelRequirement));
- addLevel = false;
- } else {
- level += 1;
- }
- } else {
-
- xpTotal += levels.get(i).getAsFloat();
-
- }
- }
-
- level += currentLevelProgress / currentLevelRequirement;
- if (level <= 0) {
- level = 1;
- } else if (level > maxPetLevel) {
- level = maxPetLevel;
- }
- PetLevel levelObj = new PetLevel();
- levelObj.level = level;
- levelObj.currentLevelRequirement = currentLevelRequirement;
- levelObj.maxXP = xpTotal;
- levelObj.levelPercentage = currentLevelProgress / currentLevelRequirement;
- levelObj.levelXp = currentLevelProgress;
- levelObj.totalXp = exp;
- return levelObj;
- }
-
- public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS =
- new HashMap<String, HashMap<String, Float>>() {{
- put("PET_ITEM_BIG_TEETH_COMMON", new HashMap<String, Float>() {{
- put("CRIT_CHANCE", 5f);
- }});
- put("PET_ITEM_HARDENED_SCALES_UNCOMMON", new HashMap<String, Float>() {{
- put("DEFENCE", 25f);
- }});
- put("PET_ITEM_LUCKY_CLOVER", new HashMap<String, Float>() {{
- put("MAGIC_FIND", 7f);
- }});
- put("PET_ITEM_SHARPENED_CLAWS_UNCOMMON", new HashMap<String, Float>() {{
- put("CRIT_DAMAGE", 15f);
- }});
- }};
-
- public static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS_MULT =
- new HashMap<String, HashMap<String, Float>>() {{
- put("PET_ITEM_IRON_CLAWS_COMMON", new HashMap<String, Float>() {{
- put("CRIT_DAMAGE", 1.4f);
- put("CRIT_CHANCE", 1.4f);
- }});
- put("PET_ITEM_TEXTBOOK", new HashMap<String, Float>() {{
- put("INTELLIGENCE", 2f);
- }});
- }};
-
- private int selectedPet = -1;
- private int petsPage = 0;
- private List<JsonObject> sortedPets = null;
- private List<ItemStack> sortedPetsStack = null;
- public static HashMap<String, String> MINION_RARITY_TO_NUM = new HashMap<String, String>() {{
- put("COMMON", "0");
- put("UNCOMMON", "1");
- put("RARE", "2");
- put("EPIC", "3");
- put("LEGENDARY", "4");
- put("MYTHIC", "5");
- }};
-
- private void drawPetsPage(int mouseX, int mouseY, float partialTicks) {
- JsonObject petsInfo = profile.getPetsInfo(profileId);
- if (petsInfo == null) return;
- JsonObject petsJson = Constants.PETS;
- if (petsJson == null) return;
-
- String location = null;
- JsonObject status = profile.getPlayerStatus();
- if (status != null && status.has("mode")) {
- location = status.get("mode").getAsString();
- }
-
- backgroundRotation += (currentTime - lastTime) / 400f;
- backgroundRotation %= 360;
-
- String panoramaIdentifier = "day";
- if (SBInfo.getInstance().currentTimeDate != null) {
- if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
- SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
- panoramaIdentifier = "night";
- }
- }
-
- JsonArray pets = petsInfo.get("pets").getAsJsonArray();
- if (sortedPets == null) {
- sortedPets = new ArrayList<>();
- sortedPetsStack = new ArrayList<>();
- for (int i = 0; i < pets.size(); i++) {
- sortedPets.add(pets.get(i).getAsJsonObject());
- }
- sortedPets.sort((pet1, pet2) -> {
- String tier1 = pet1.get("tier").getAsString();
- String tierNum1 = MINION_RARITY_TO_NUM.get(tier1);
- if (tierNum1 == null) return 1;
- int tierNum1I = Integer.parseInt(tierNum1);
- float exp1 = pet1.get("exp").getAsFloat();
-
- String tier2 = pet2.get("tier").getAsString();
- String tierNum2 = MINION_RARITY_TO_NUM.get(tier2);
- if (tierNum2 == null) return -1;
- int tierNum2I = Integer.parseInt(tierNum2);
- float exp2 = pet2.get("exp").getAsFloat();
-
- if (tierNum1I != tierNum2I) {
- return tierNum2I - tierNum1I;
- } else {
- return (int) (exp2 - exp1);
- }
- });
- for (JsonObject pet : sortedPets) {
- String petname = pet.get("type").getAsString();
- String tier = pet.get("tier").getAsString();
- String heldItem = Utils.getElementAsString(pet.get("heldItem"), null);
- String skin = Utils.getElementAsString(pet.get("skin"), null);
- int candy = pet.get("candyUsed").getAsInt();
- JsonObject heldItemJson =
- heldItem == null ? null : NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(heldItem);
- String tierNum = MINION_RARITY_TO_NUM.get(tier);
- float exp = pet.get("exp").getAsFloat();
- if (tierNum == null) continue;
-
- if (pet.has("heldItem") && !pet.get("heldItem").isJsonNull() &&
- pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST")) {
- tierNum = "" + (Integer.parseInt(tierNum) + 1);
- }
-
- PetLevel levelObj = GuiProfileViewer.getPetLevel(petname, tier, exp);
-
- float level = levelObj.level;
- float currentLevelRequirement = levelObj.currentLevelRequirement;
- float maxXP = levelObj.maxXP;
- pet.addProperty("level", level);
- pet.addProperty("currentLevelRequirement", currentLevelRequirement);
- pet.addProperty("maxXP", maxXP);
-
- JsonObject petItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(petname + ";" + tierNum);
- if (petItem == null) continue;
-
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(petItem, false, false);
- HashMap<String, String> replacements =
- NotEnoughUpdates.INSTANCE.manager.getLoreReplacements(petname, tier, (int) Math.floor(level));
-
- if (heldItem != null) {
- HashMap<String, Float> petStatBoots = PET_STAT_BOOSTS.get(heldItem);
- HashMap<String, Float> petStatBootsMult = PET_STAT_BOOSTS_MULT.get(heldItem);
- if (petStatBoots != null) {
- for (Map.Entry<String, Float> entryBoost : petStatBoots.entrySet()) {
- try {
- float value = Float.parseFloat(replacements.get(entryBoost.getKey()));
- replacements.put(entryBoost.getKey(), String.valueOf((int) Math.floor(value + entryBoost.getValue())));
- } catch (Exception ignored) {
- }
- }
-
- }
- if (petStatBootsMult != null) {
- for (Map.Entry<String, Float> entryBoost : petStatBootsMult.entrySet()) {
- try {
- float value = Float.parseFloat(replacements.get(entryBoost.getKey()));
- replacements.put(entryBoost.getKey(), String.valueOf((int) Math.floor(value * entryBoost.getValue())));
- } catch (Exception ignored) {
- }
- }
- }
- }
-
- NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound();
- if (tag.hasKey("display", 10)) {
- NBTTagCompound display = tag.getCompoundTag("display");
- if (display.hasKey("Lore", 9)) {
- NBTTagList newLore = new NBTTagList();
- NBTTagList lore = display.getTagList("Lore", 8);
- HashMap<Integer, Integer> blankLocations = new HashMap<>();
- for (int j = 0; j < lore.tagCount(); j++) {
- String line = lore.getStringTagAt(j);
- if (line.trim().isEmpty()) {
- blankLocations.put(blankLocations.size(), j);
- }
- for (Map.Entry<String, String> replacement : replacements.entrySet()) {
- line = line.replace("{" + replacement.getKey() + "}", replacement.getValue());
- }
- newLore.appendTag(new NBTTagString(line));
- }
- Integer secondLastBlank = blankLocations.get(blankLocations.size() - 2);
- if (skin != null) {
- JsonObject petSkin = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("PET_SKIN_" + skin);
- if (petSkin != null) {
- try {
- NBTTagCompound nbt = JsonToNBT.getTagFromJson(petSkin.get("nbttag").getAsString());
- tag.setTag("SkullOwner", nbt.getTag("SkullOwner"));
- String name = petSkin.get("displayname").getAsString();
- if (name != null) {
- name = Utils.cleanColour(name);
- newLore.set(0, new NBTTagString(newLore.get(0).toString().replace("\"", "") + ", " + name));
- }
- } catch (NBTException e) {
- e.printStackTrace();
- }
- }
- }
- for (int i = 0; i < newLore.tagCount(); i++) {
- String cleaned = Utils.cleanColour(newLore.get(i).toString());
- if (cleaned.equals("\"Right-click to add this pet to\"")) {
- newLore.removeTag(i + 1);
- newLore.removeTag(i);
- secondLastBlank = i - 1;
- break;
- }
- }
- NBTTagList temp = new NBTTagList();
- for (int i = 0; i < newLore.tagCount(); i++) {
- temp.appendTag(newLore.get(i));
- if (secondLastBlank != null && i == secondLastBlank) {
- if (heldItem != null) {
- temp.appendTag(new NBTTagString(
- EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString()));
- int blanks = 0;
- JsonArray heldItemLore = heldItemJson.get("lore").getAsJsonArray();
- for (int k = 0; k < heldItemLore.size(); k++) {
- String heldItemLine = heldItemLore.get(k).getAsString();
- if (heldItemLine.trim().isEmpty()) {
- blanks++;
- } else if (blanks == 2) {
- temp.appendTag(new NBTTagString(heldItemLine));
- } else if (blanks > 2) {
- break;
- }
- }
- temp.appendTag(new NBTTagString());
- }
- if (candy != 0) {
- temp.appendTag(new NBTTagString(EnumChatFormatting.GREEN + "(" + candy + "/10) Pet Candy Used"));
- temp.appendTag(new NBTTagString());
- }
- temp.removeTag(temp.tagCount() - 1);
- }
- }
- newLore = temp;
- display.setTag("Lore", newLore);
- }
- if (display.hasKey("Name", 8)) {
- String displayName = display.getString("Name");
- for (Map.Entry<String, String> replacement : replacements.entrySet()) {
- displayName = displayName.replace("{" + replacement.getKey() + "}", replacement.getValue());
- }
- display.setTag("Name", new NBTTagString(displayName));
- }
- tag.setTag("display", display);
- }
- stack.setTagCompound(tag);
-
- sortedPetsStack.add(stack);
- }
- }
-
- Panorama.drawPanorama(-backgroundRotation, guiLeft + 212, guiTop + 44, 81, 108, -0.37f, 0.6f,
- getPanoramasForLocation(location == null ? "dynamic" : location, panoramaIdentifier)
- );
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_pets);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- Utils.drawStringCentered(EnumChatFormatting.DARK_PURPLE + "Pets", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 100, guiTop + 14, true, 4210752
- );
- GlStateManager.color(1, 1, 1, 1);
-
- JsonElement activePetElement = petsInfo.get("active_pet");
- if (selectedPet == -1 && activePetElement != null && activePetElement.isJsonObject()) {
- JsonObject active = activePetElement.getAsJsonObject();
- for (int i = 0; i < sortedPets.size(); i++) {
- if (sortedPets.get(i) == active) {
- selectedPet = i;
- break;
- }
- }
- }
-
- boolean leftHovered = false;
- boolean rightHovered = false;
- if (Mouse.isButtonDown(0)) {
- if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
- if (mouseX > guiLeft + 100 - 20 - 12 && mouseX < guiLeft + 100 - 20) {
- leftHovered = true;
- } else if (mouseX > guiLeft + 100 + 20 && mouseX < guiLeft + 100 + 20 + 12) {
- rightHovered = true;
- }
- }
- }
- Minecraft.getMinecraft().getTextureManager().bindTexture(resource_packs);
-
- if (petsPage > 0) {
- Utils.drawTexturedRect(guiLeft + 100 - 15 - 12, guiTop + 6, 12, 16,
- 29 / 256f, 53 / 256f, !leftHovered ? 0 : 32 / 256f, !leftHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST
- );
- }
- if (petsPage < Math.ceil(pets.size() / 20f) - 1) {
- Utils.drawTexturedRect(guiLeft + 100 + 15, guiTop + 6, 12, 16,
- 5 / 256f, 29 / 256f, !rightHovered ? 0 : 32 / 256f, !rightHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST
- );
- }
-
- for (
- int i = petsPage * 20;
- i < Math.min(petsPage * 20 + 20, Math.min(sortedPetsStack.size(), sortedPets.size()));
- i++
- ) {
- JsonObject pet = sortedPets.get(i);
- ItemStack stack = sortedPetsStack.get(i);
-
- if (pet != null) {
- {
- NBTTagCompound tag = stack.getTagCompound();
- tag.setBoolean("DisablePetExp", true);
- stack.setTagCompound(tag);
- }
- int xIndex = (i % 20) % COLLS_XCOUNT;
- int yIndex = (i % 20) / COLLS_XCOUNT;
-
- float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
- float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- if (i == selectedPet) {
- GlStateManager.color(1, 185 / 255f, 0, 1);
- } else {
- GlStateManager.color(1, 1, 1, 1);
- }
- Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
-
- Utils.drawItemStack(stack, guiLeft + (int) x + 2, guiTop + (int) y + 2);
-
- if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) {
- if (mouseY > guiTop + y && mouseY < guiTop + y + 20) {
- tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
- }
- }
- }
-
- if (selectedPet >= 0) {
- ItemStack petStack = sortedPetsStack.get(selectedPet);
- String display = petStack.getDisplayName();
- JsonObject pet = sortedPets.get(selectedPet);
-
- int x = guiLeft + 280;
- float y = guiTop + 67 + 15 * (float) Math.sin(((currentTime - startTime) / 800f) % (2 * Math.PI));
-
- int displayLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(display);
- int halfDisplayLen = displayLen / 2;
-
- GlStateManager.pushMatrix();
- GlStateManager.translate(x, y, 0);
-
- drawRect(-halfDisplayLen - 1 - 28, -1, halfDisplayLen + 1 - 28, 8, new Color(0, 0, 0, 100).getRGB());
-
- Minecraft.getMinecraft().fontRendererObj.drawString(display, -halfDisplayLen - 28, 0, 0, true);
-
- GlStateManager.enableDepth();
- GlStateManager.translate(-55, 0, 0);
- GlStateManager.scale(3.5f, 3.5f, 1);
- Utils.drawItemStack(petStack, 0, 0);
- GlStateManager.popMatrix();
-
- float level = pet.get("level").getAsFloat();
- float currentLevelRequirement = pet.get("currentLevelRequirement").getAsFloat();
- float exp = pet.get("exp").getAsFloat();
- float maxXP = pet.get("maxXP").getAsFloat();
-
- String[] split = display.split("] ");
- String colouredName = split[split.length - 1];
-
- Utils.renderAlignedString(
- colouredName,
- EnumChatFormatting.WHITE + "Level " + (int) Math.floor(level),
- guiLeft + 319,
- guiTop + 28,
- 98
- );
-
- //Utils.drawStringCenteredScaledMaxWidth(, Minecraft.getMinecraft().fontRendererObj, guiLeft+368, guiTop+28+4, true, 98, 0);
- //renderAlignedString(display, EnumChatFormatting.YELLOW+"[LVL "+Math.floor(level)+"]", guiLeft+319, guiTop+28, 98);
- renderBar(guiLeft + 319, guiTop + 38, 98, (float) Math.floor(level) / 100f);
-
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "To Next LVL",
- EnumChatFormatting.WHITE.toString() + (int) (level % 1 * 100) + "%",
- guiLeft + 319,
- guiTop + 46,
- 98
- );
- renderBar(guiLeft + 319, guiTop + 56, 98, level % 1);
-
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "To Max LVL",
- EnumChatFormatting.WHITE.toString() + Math.min(100, (int) (exp / maxXP * 100)) + "%",
- guiLeft + 319,
- guiTop + 64,
- 98
- );
- renderBar(guiLeft + 319, guiTop + 74, 98, exp / maxXP);
-
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Total XP",
- EnumChatFormatting.WHITE + shortNumberFormat(exp, 0),
- guiLeft + 319,
- guiTop + 125,
- 98
- );
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Current LVL XP",
- EnumChatFormatting.WHITE + shortNumberFormat((level % 1) * currentLevelRequirement, 0),
- guiLeft + 319,
- guiTop + 143,
- 98
- );
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Required LVL XP",
- EnumChatFormatting.WHITE + shortNumberFormat(currentLevelRequirement, 0),
- guiLeft + 319,
- guiTop + 161,
- 98
- );
- }
- }
-
- private final String[] romans = new String[]{
- "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI",
- "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XIX", "XX"
- };
-
- private final int COLLS_XCOUNT = 5;
- private final int COLLS_YCOUNT = 4;
- private final float COLLS_XPADDING = (190 - COLLS_XCOUNT * 20) / (float) (COLLS_XCOUNT + 1);
- private final float COLLS_YPADDING = (202 - COLLS_YCOUNT * 20) / (float) (COLLS_YCOUNT + 1);
-
- private void drawColsPage(int mouseX, int mouseY, float partialTicks) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_cols);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- JsonObject collectionInfo = profile.getCollectionInfo(profileId);
- if (collectionInfo == null) {
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "Collection API not enabled!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 134,
- guiTop + 101,
- true,
- 0
- );
- return;
- }
- JsonObject resourceCollectionInfo = ProfileViewer.getResourceCollectionInformation();
- if (resourceCollectionInfo == null) return;
-
- int collectionCatSize = ProfileViewer.getCollectionCatToCollectionMap().size();
- int collectionCatYSize = (int) (162f / (collectionCatSize - 1 + 0.0000001f));
- {
- int yIndex = 0;
- for (ItemStack stack : ProfileViewer.getCollectionCatToCollectionMap().keySet()) {
- if (selectedCollectionCategory == null) selectedCollectionCategory = stack;
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- if (stack == selectedCollectionCategory) {
- Utils.drawTexturedRect(guiLeft + 7, guiTop + 10 + collectionCatYSize * yIndex, 20, 20,
- 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST
- );
- Utils.drawItemStackWithText(
- stack,
- guiLeft + 10,
- guiTop + 13 + collectionCatYSize * yIndex,
- "" + (yIndex + 1)
- );
- } else {
- Utils.drawTexturedRect(guiLeft + 7, guiTop + 10 + collectionCatYSize * yIndex, 20, 20,
- 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST
- );
- Utils.drawItemStackWithText(stack, guiLeft + 9, guiTop + 12 + collectionCatYSize * yIndex, "" + (yIndex + 1));
- }
- yIndex++;
- }
- }
-
- Utils.drawStringCentered(
- selectedCollectionCategory.getDisplayName() + " Collections",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 134,
- guiTop + 14,
- true,
- 4210752
- );
-
- JsonObject minionTiers = collectionInfo.get("minion_tiers").getAsJsonObject();
- JsonObject collectionTiers = collectionInfo.get("collection_tiers").getAsJsonObject();
- JsonObject maxAmounts = collectionInfo.get("max_amounts").getAsJsonObject();
- JsonObject totalAmounts = collectionInfo.get("total_amounts").getAsJsonObject();
- JsonObject personalAmounts = collectionInfo.get("personal_amounts").getAsJsonObject();
-
- List<String> collections = ProfileViewer.getCollectionCatToCollectionMap().get(selectedCollectionCategory);
- if (collections != null) {
- for (int i = 0; i < collections.size(); i++) {
- String collection = collections.get(i);
- if (collection != null) {
- ItemStack collectionItem = ProfileViewer.getCollectionToCollectionDisplayMap().get(collection);
- if (collectionItem != null) {
- int xIndex = i % COLLS_XCOUNT;
- int yIndex = i / COLLS_XCOUNT;
-
- float x = 39 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
- float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
-
- String tierString;
- int tier = (int) Utils.getElementAsFloat(collectionTiers.get(collection), 0);
- if (tier > 20 || tier < 0) {
- tierString = String.valueOf(tier);
- } else {
- tierString = romans[tier];
- }
- float amount = Utils.getElementAsFloat(totalAmounts.get(collection), 0);
- float maxAmount = Utils.getElementAsFloat(maxAmounts.get(collection), 0);
- Color color = new Color(128, 128, 128, 255);
- int tierStringColour = color.getRGB();
- float completedness = 0;
- if (maxAmount > 0) {
- completedness = amount / maxAmount;
- }
- completedness = Math.min(1, completedness);
- if (maxAmounts.has(collection) && completedness >= 1) {
- tierStringColour = new Color(255, 215, 0).getRGB();
- }
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20 * (1 - completedness),
- 0, 20 / 256f, 0, 20 * (1 - completedness) / 256f, GL11.GL_NEAREST
- );
- GlStateManager.color(1, 185 / 255f, 0, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(guiLeft + x, guiTop + y + 20 * (1 - completedness), 20, 20 * (completedness),
- 0, 20 / 256f, 20 * (1 - completedness) / 256f, 20 / 256f, GL11.GL_NEAREST
- );
- Utils.drawItemStack(collectionItem, guiLeft + (int) x + 2, guiTop + (int) y + 2);
-
- if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
- if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
- tooltipToDisplay = new ArrayList<>();
- tooltipToDisplay.add(collectionItem.getDisplayName() + " " +
- (completedness >= 1 ? EnumChatFormatting.GOLD : EnumChatFormatting.GRAY) + tierString);
- tooltipToDisplay.add(
- "Collected: " + numberFormat.format(Utils.getElementAsFloat(personalAmounts.get(collection), 0)));
- tooltipToDisplay.add("Total Collected: " + numberFormat.format(amount));
- }
- }
-
- GlStateManager.color(1, 1, 1, 1);
- if (tier >= 0) {
- Utils.drawStringCentered(tierString, fontRendererObj,
- guiLeft + x + 10, guiTop + y - 4, true,
- tierStringColour
- );
- }
-
- Utils.drawStringCentered(shortNumberFormat(amount, 0) + "", fontRendererObj,
- guiLeft + x + 10, guiTop + y + 26, true,
- color.getRGB()
- );
- }
- }
- }
- }
-
- Utils.drawStringCentered(
- selectedCollectionCategory.getDisplayName() + " Minions",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 326,
- guiTop + 14,
- true,
- 4210752
- );
-
- List<String> minions = ProfileViewer.getCollectionCatToMinionMap().get(selectedCollectionCategory);
- if (minions != null) {
- for (int i = 0; i < minions.size(); i++) {
- String minion = minions.get(i);
- if (minion != null) {
- JsonObject misc = Constants.MISC;
- float MAX_MINION_TIER =
- Utils.getElementAsFloat(Utils.getElement(misc, "minions." + minion + "_GENERATOR"), 11);
-
- int tier = (int) Utils.getElementAsFloat(minionTiers.get(minion), 0);
- JsonObject minionJson;
- if (tier == 0) {
- minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_1");
- } else {
- minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion + "_GENERATOR_" + tier);
- }
-
- if (minionJson != null) {
- int xIndex = i % COLLS_XCOUNT;
- int yIndex = i / COLLS_XCOUNT;
-
- float x = 231 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
- float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
-
- String tierString;
-
- if (tier - 1 >= romans.length || tier - 1 < 0) {
- tierString = String.valueOf(tier);
- } else {
- tierString = romans[tier - 1];
- }
-
- Color color = new Color(128, 128, 128, 255);
- int tierStringColour = color.getRGB();
- float completedness = tier / MAX_MINION_TIER;
-
- completedness = Math.min(1, completedness);
- if (completedness >= 1) {
- tierStringColour = new Color(255, 215, 0).getRGB();
- }
-
- GlStateManager.color(1, 1, 1, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20 * (1 - completedness),
- 0, 20 / 256f, 0, 20 * (1 - completedness) / 256f, GL11.GL_NEAREST
- );
- GlStateManager.color(1, 185 / 255f, 0, 1);
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- Utils.drawTexturedRect(guiLeft + x, guiTop + y + 20 * (1 - completedness), 20, 20 * (completedness),
- 0, 20 / 256f, 20 * (1 - completedness) / 256f, 20 / 256f, GL11.GL_NEAREST
- );
-
- Utils.drawItemStack(
- NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson),
- guiLeft + (int) x + 2,
- guiTop + (int) y + 2
- );
-
- if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
- if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
- tooltipToDisplay = NotEnoughUpdates.INSTANCE.manager.jsonToStack(minionJson)
- .getTooltip(
- Minecraft.getMinecraft().thePlayer,
- false
- );
- }
- }
-
- GlStateManager.color(1, 1, 1, 1);
- if (tier >= 0) {
- Utils.drawStringCentered(tierString, fontRendererObj,
- guiLeft + x + 10, guiTop + y - 4, true,
- tierStringColour
- );
- }
- }
- }
- }
- }
-
- //190
- }
-
- private static final LinkedHashMap<String, ItemStack> invNameToDisplayMap = new LinkedHashMap<String, ItemStack>() {{
- put(
- "inv_contents",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.chest), EnumChatFormatting.GRAY + "Inventory")
- );
- put(
- "ender_chest_contents",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.GRAY + "Ender Chest")
- );
- // put("backpack_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.dropper), EnumChatFormatting.GRAY+"Backpacks"));
- put(
- "backpack_contents",
- Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get("JUMBO_BACKPACK")), EnumChatFormatting.GRAY + "Backpacks", true)
- );
- put(
- "personal_vault_contents",
- Utils.editItemStackInfo(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
- .getItemInformation()
- .get("IRON_CHEST")), EnumChatFormatting.GRAY + "Personal vault", true)
- );
- put("talisman_bag", Utils.createItemStack(Items.golden_apple, EnumChatFormatting.GRAY + "Accessory Bag"));
- put("wardrobe_contents", Utils.createItemStack(Items.leather_chestplate, EnumChatFormatting.GRAY + "Wardrobe"));
- put("fishing_bag", Utils.createItemStack(Items.fish, EnumChatFormatting.GRAY + "Fishing Bag"));
- put("potion_bag", Utils.createItemStack(Items.potionitem, EnumChatFormatting.GRAY + "Potion Bag"));
- }};
-
- public int countItemsInInventory(
- String internalname,
- JsonObject inventoryInfo,
- boolean specific,
- String... invsToSearch
- ) {
- int count = 0;
- for (String inv : invsToSearch) {
- JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray();
- for (int i = 0; i < invItems.size(); i++) {
- if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue;
- JsonObject item = invItems.get(i).getAsJsonObject();
- if ((specific && item.get("internalname").getAsString().equals(internalname)) ||
- (!specific && item.get("internalname").getAsString().contains(internalname))) {
- if (item.has("count")) {
- count += item.get("count").getAsInt();
- } else {
- count += 1;
- }
- }
- }
- }
- return count;
- }
-
- private static final Pattern DAMAGE_PATTERN = Pattern.compile("^Damage: \\+([0-9]+)");
- private static final Pattern STRENGTH_PATTERN = Pattern.compile("^Strength: \\+([0-9]+)");
- private static final Pattern FISHSPEED_PATTERN = Pattern.compile("^Increases fishing speed by \\+([0-9]+)");
-
- private ItemStack[] findBestItems(
- JsonObject inventoryInfo,
- int numItems,
- String[] invsToSearch,
- String[] typeMatches,
- Pattern... importantPatterns
- ) {
- ItemStack[] bestItems = new ItemStack[numItems];
- TreeMap<Integer, Set<ItemStack>> map = new TreeMap<>();
- for (String inv : invsToSearch) {
- JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray();
- for (int i = 0; i < invItems.size(); i++) {
- if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue;
- JsonObject item = invItems.get(i).getAsJsonObject();
- JsonArray lore = item.get("lore").getAsJsonArray();
- if (Utils.checkItemType(lore, true, typeMatches) >= 0) {
- int importance = 0;
- for (int j = 0; j < lore.size(); j++) {
- String line = lore.get(j).getAsString();
- for (Pattern pattern : importantPatterns) {
- Matcher matcher = pattern.matcher(Utils.cleanColour(line));
- if (matcher.find()) {
- importance += Integer.parseInt(matcher.group(1));
- }
- }
- }
- map.computeIfAbsent(importance, k -> new HashSet<>()).add(
- NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false));
- }
- }
- }
- int i = 0;
- outer:
- for (int key : map.descendingKeySet()) {
- Set<ItemStack> items = map.get(key);
- for (ItemStack item : items) {
- bestItems[i] = item;
- if (++i >= bestItems.length) break outer;
- }
- }
-
- return bestItems;
- }
-
- private int getRowsForInventory(String invName) {
- switch (invName) {
- case "wardrobe_contents":
- return 4;
- case "backpack_contents":
- return 5;
- case "ender_chest_contents":
- return 5;
- }
- return 6;
- }
-
- private boolean useActualMax(String invName) {
- switch (invName) {
- case "talisman_bag":
- case "fishing_bag":
- case "potion_bag":
- case "personal_vault_contents":
- return true;
- }
- return false;
- }
-
- private int getIgnoredRowsForInventory(String invName) {
- switch (invName) {
- case "talisman_bag":
- case "fishing_bag":
- case "potion_bag":
- return 1;
- }
- return 0;
- }
-
- private final ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15);
-
- public ItemStack[][][] getItemsForInventory(JsonObject inventoryInfo, String invName) {
- if (inventoryItems.containsKey(invName)) return inventoryItems.get(invName);
-
- JsonArray jsonInv = Utils.getElement(inventoryInfo, invName).getAsJsonArray();
-
- if (jsonInv.size() == 0) return new ItemStack[1][][];
-
- int jsonInvSize;
- if (useActualMax(invName)) {
- jsonInvSize = (int) Math.ceil(jsonInv.size() / 9f) * 9;
- } else {
- jsonInvSize = 9 * 4;
- float divideBy = 9f;
- if (invName.equals("wardrobe_contents")) {
- divideBy = 36f;
- }
- for (int i = 9 * 4; i < jsonInv.size(); i++) {
- JsonElement item = jsonInv.get(i);
- if (item != null && item.isJsonObject()) {
- jsonInvSize = (int) (Math.ceil((i + 1) / divideBy) * (int) divideBy);
- }
- }
- }
-
- int rowSize = 9;
- int rows = jsonInvSize / rowSize;
- int maxRowsPerPage = getRowsForInventory(invName);
- int maxInvSize = rowSize * maxRowsPerPage;
-
- int numInventories = (jsonInvSize - 1) / maxInvSize + 1;
- JsonArray backPackSizes = (JsonArray) inventoryInfo.get("backpack_sizes");
- if (invName.equals("backpack_contents")) {
- numInventories = backPackSizes.size();
- }
-
- ItemStack[][][] inventories = new ItemStack[numInventories][][];
-
- //int availableSlots = getAvailableSlotsForInventory(inventoryInfo, collectionInfo, invName);
- int startNumberJ = 0;
-
- for (int i = 0; i < numInventories; i++) {
- int thisRows = Math.min(maxRowsPerPage, rows - maxRowsPerPage * i);
- int invSize = 0;
-
- if (invName.equals("backpack_contents")) {
- thisRows = backPackSizes.get(i).getAsInt() / 9;
- invSize = startNumberJ + (thisRows * 9);
- maxInvSize = thisRows * 9;
- } else {
- startNumberJ = maxInvSize * i;
- invSize = Math.min(jsonInvSize, maxInvSize + maxInvSize * i);
- }
- if (thisRows <= 0) break;
-
- ItemStack[][] items = new ItemStack[thisRows][rowSize];
-
- for (int j = startNumberJ; j < invSize; j++) {
-
- int xIndex = (j % maxInvSize) % rowSize;
- int yIndex = (j % maxInvSize) / rowSize;
- if (invName.equals("inv_contents")) {
- yIndex--;
- if (yIndex < 0) yIndex = rows - 1;
- }
- if (yIndex >= thisRows) {
- break;
- }
-
- if (j >= jsonInv.size()) {
- items[yIndex][xIndex] = fillerStack;
- continue;
- }
- if (jsonInv.get(j) == null || !jsonInv.get(j).isJsonObject()) {
- continue;
- }
-
- JsonObject item = jsonInv.get(j).getAsJsonObject();
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false);
- if (item.has("item_contents")) {
- JsonArray bytesArr = item.get("item_contents").getAsJsonArray();
- byte[] bytes = new byte[bytesArr.size()];
- for (int bytesArrI = 0; bytesArrI < bytesArr.size(); bytesArrI++) {
- bytes[bytesArrI] = bytesArr.get(bytesArrI).getAsByte();
- }
- //byte[] bytes2 = null;
- NBTTagCompound tag = stack.getTagCompound();
- if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
- for (String key : ea.getKeySet()) {
- if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
- ea.setTag(key, new NBTTagByteArray(bytes));
- break;
- }
- }
- tag.setTag("ExtraAttributes", ea);
- stack.setTagCompound(tag);
- }
- }
-
- items[yIndex][xIndex] = stack;
- }
- inventories[i] = items;
- if (invName.equals("backpack_contents")) {
- startNumberJ = startNumberJ + backPackSizes.get(i).getAsInt();
- }
- }
-
- inventoryItems.put(invName, inventories);
- return inventories;
- }
-
- private ItemStack[] bestWeapons = null;
- private ItemStack[] bestRods = null;
- private ItemStack[] armorItems = null;
- private HashMap<String, ItemStack[][][]> inventoryItems = new HashMap<>();
- private String selectedInventory = "inv_contents";
- private int currentInventoryIndex = 0;
- private int arrowCount = -1;
- private int greenCandyCount = -1;
- private int purpleCandyCount = -1;
- private final GuiElementTextField inventoryTextField = new GuiElementTextField("", GuiElementTextField.SCALE_TEXT);
- private ItemStack lastBackpack;
- private int lastBackpackX;
- private int lastBackpackY;
-
- private void drawInvsPage(int mouseX, int mouseY, float partialTicks) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_invs);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
- inventoryTextField.setSize(88, 20);
-
- JsonObject inventoryInfo = profile.getInventoryInfo(profileId);
- if (inventoryInfo == null) return;
-
- int invNameIndex = 0;
- for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) {
- int xIndex = invNameIndex % 3;
- int yIndex = invNameIndex / 3;
-
- int x = 19 + 34 * xIndex;
- int y = 26 + 34 * yIndex;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
- if (entry.getKey().equals(selectedInventory)) {
- Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 20 / 256f, 0,
- 20 / 256f, 0, GL11.GL_NEAREST
- );
- x++;
- y++;
- } else {
- Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 0, 20 / 256f,
- 0, 20 / 256f, GL11.GL_NEAREST
- );
- }
-
- Utils.drawItemStackWithText(entry.getValue(), guiLeft + x, guiTop + y, "" + (invNameIndex + 1));
-
- if (mouseX >= guiLeft + x && mouseX <= guiLeft + x + 16) {
- if (mouseY >= guiTop + y && mouseY <= guiTop + y + 16) {
- tooltipToDisplay = entry.getValue().getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
- }
-
- invNameIndex++;
- }
-
- inventoryTextField.render(guiLeft + 19, guiTop + sizeY - 26 - 20);
-
- if (armorItems == null) {
- armorItems = new ItemStack[4];
- JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
- for (int i = 0; i < armor.size(); i++) {
- if (armor.get(i) == null || !armor.get(i).isJsonObject()) continue;
- armorItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(armor.get(i).getAsJsonObject(), false);
- }
- }
-
- for (int i = 0; i < armorItems.length; i++) {
- ItemStack stack = armorItems[i];
- if (stack != null) {
- Utils.drawItemStack(stack, guiLeft + 173, guiTop + 67 - 18 * i);
- if (stack != fillerStack) {
- if (mouseX >= guiLeft + 173 - 1 && mouseX <= guiLeft + 173 + 16 + 1) {
- if (mouseY >= guiTop + 67 - 18 * i - 1 && mouseY <= guiTop + 67 - 18 * i + 16 + 1) {
- tooltipToDisplay = stack.getTooltip(
- Minecraft.getMinecraft().thePlayer,
- Minecraft.getMinecraft().gameSettings.advancedItemTooltips
- );
- }
- }
- }
- }
- }
-
- ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory);
- if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1;
- if (currentInventoryIndex < 0) currentInventoryIndex = 0;
-
- ItemStack[][] inventory = inventories[currentInventoryIndex];
- if (inventory == null) {
- if (selectedInventory.equalsIgnoreCase("personal_vault_contents")) {
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "Personal Vault API not enabled!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 317,
- guiTop + 101,
- true,
- 0
- );
- } else {
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "Inventory API not enabled!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 317,
- guiTop + 101,
- true,
- 0
- );
- }
- return;
- }
-
- if (bestWeapons == null) {
- bestWeapons = findBestItems(inventoryInfo, 6, new String[]{"inv_contents", "ender_chest_contents"},
- new String[]{"SWORD", "BOW"}, DAMAGE_PATTERN, STRENGTH_PATTERN
- );
- }
- if (bestRods == null) {
- bestRods = findBestItems(inventoryInfo, 3, new String[]{"inv_contents", "ender_chest_contents"},
- new String[]{"FISHING ROD"}, FISHSPEED_PATTERN
- );
- }
-
- for (int i = 0; i < bestWeapons.length; i++) {
- if (bestWeapons[i] == null) continue;
- ItemStack stack = bestWeapons[i];
- Utils.drawItemStack(stack, guiLeft + 143, guiTop + 13 + 18 * i);
- if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) {
- if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) {
- tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
- }
- }
-
- for (int i = 0; i < bestRods.length; i++) {
- if (bestRods[i] == null) continue;
- ItemStack stack = bestRods[i];
- Utils.drawItemStack(stack, guiLeft + 143, guiTop + 137 + 18 * i);
- if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) {
- if (mouseY >= guiTop + 137 + 18 * i - 1 && mouseY <= guiTop + 137 + 18 * i + 16 + 1) {
- tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
- }
- }
-
- if (arrowCount == -1) {
- arrowCount = countItemsInInventory("ARROW", inventoryInfo, false, "quiver");
- }
- if (greenCandyCount == -1) {
- greenCandyCount = countItemsInInventory("GREEN_CANDY", inventoryInfo, true, "candy_inventory_contents");
- }
- if (purpleCandyCount == -1) {
- purpleCandyCount = countItemsInInventory("PURPLE_CANDY", inventoryInfo, true, "candy_inventory_contents");
- }
-
- Utils.drawItemStackWithText(NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("ARROW")), guiLeft + 173, guiTop + 101,
- "" + (arrowCount > 999 ? shortNumberFormat(arrowCount, 0) : arrowCount)
- );
- Utils.drawItemStackWithText(
- NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("GREEN_CANDY")),
- guiLeft + 173,
- guiTop + 119,
- "" + greenCandyCount
- );
- Utils.drawItemStackWithText(
- NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("PURPLE_CANDY")),
- guiLeft + 173,
- guiTop + 137,
- "" + purpleCandyCount
- );
- if (mouseX > guiLeft + 173 && mouseX < guiLeft + 173 + 16) {
- if (mouseY > guiTop + 101 && mouseY < guiTop + 137 + 16) {
- if (mouseY < guiTop + 101 + 17) {
- tooltipToDisplay =
- Utils.createList(EnumChatFormatting.WHITE + "Arrow " + EnumChatFormatting.GRAY + "x" + arrowCount);
- } else if (mouseY < guiTop + 119 + 17) {
- tooltipToDisplay = Utils.createList(
- EnumChatFormatting.GREEN + "Green Candy " + EnumChatFormatting.GRAY + "x" + greenCandyCount);
- } else {
- tooltipToDisplay = Utils.createList(
- EnumChatFormatting.DARK_PURPLE + "Purple Candy " + EnumChatFormatting.GRAY + "x" + purpleCandyCount);
- }
- }
- }
-
- int inventoryRows = inventory.length;
-
- GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
- Minecraft.getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
-
- int invSizeY = inventoryRows * 18 + 17 + 7;
-
- int x = guiLeft + 320 - 176 / 2;
- int y = guiTop + 101 - invSizeY / 2;
- int staticSelectorHeight = guiTop + 177;
-
- this.drawTexturedModalRect(x, y, 0, 0, 176, inventoryRows * 18 + 17);
- this.drawTexturedModalRect(x, y + inventoryRows * 18 + 17, 0, 215, 176, 7);
-
- boolean leftHovered = false;
- boolean rightHovered = false;
- if (Mouse.isButtonDown(0)) {
- if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) {
- if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) {
- if (mouseX < guiLeft + 320) {
- leftHovered = true;
- } else {
- rightHovered = true;
- }
- }
- }
- }
- Minecraft.getMinecraft().getTextureManager().bindTexture(resource_packs);
-
- if (currentInventoryIndex > 0) {
- Utils.drawTexturedRect(guiLeft + 320 - 12, staticSelectorHeight, 12, 16,
- 29 / 256f, 53 / 256f, !leftHovered ? 0 : 32 / 256f, !leftHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST
- );
- }
- if (currentInventoryIndex < inventories.length - 1) {
- Utils.drawTexturedRect(guiLeft + 320, staticSelectorHeight, 12, 16,
- 5 / 256f, 29 / 256f, !rightHovered ? 0 : 32 / 256f, !rightHovered ? 32 / 256f : 64 / 256f, GL11.GL_NEAREST
- );
- }
-
- fontRendererObj.drawString(
- Utils.cleanColour(invNameToDisplayMap.get(selectedInventory).getDisplayName()),
- x + 8,
- y + 6,
- 4210752
- );
-
- ItemStack stackToRender = null;
- int overlay = new Color(0, 0, 0, 100).getRGB();
- for (int yIndex = 0; yIndex < inventory.length; yIndex++) {
- if (inventory[yIndex] == null) continue;
-
- for (int xIndex = 0; xIndex < inventory[yIndex].length; xIndex++) {
- ItemStack stack = inventory[yIndex][xIndex];
-
- if (stack != null) Utils.drawItemStack(stack, x + 8 + xIndex * 18, y + 18 + yIndex * 18);
-
- if (inventoryTextField.getText() != null && !inventoryTextField.getText().isEmpty() &&
- (stack == null ||
- !NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(stack, inventoryTextField.getText()))) {
- GlStateManager.translate(0, 0, 50);
- drawRect(
- x + 8 + xIndex * 18,
- y + 18 + yIndex * 18,
- x + 8 + xIndex * 18 + 16,
- y + 18 + yIndex * 18 + 16,
- overlay
- );
- GlStateManager.translate(0, 0, -50);
- }
-
- if (stack == null || stack == fillerStack) continue;
-
- if (mouseX >= x + 8 + xIndex * 18 && mouseX <= x + 8 + xIndex * 18 + 16) {
- if (mouseY >= y + 18 + yIndex * 18 && mouseY <= y + 18 + yIndex * 18 + 16) {
- stackToRender = stack;
- }
- }
- }
- }
- if (stackToRender != null) {
- tooltipToDisplay = stackToRender.getTooltip(Minecraft.getMinecraft().thePlayer, false);
- }
-
- }
-
- private String niceUuid(String uuidStr) {
- if (uuidStr.length() != 32) return uuidStr;
-
- StringBuilder niceAucId = new StringBuilder();
- niceAucId.append(uuidStr, 0, 8);
- niceAucId.append("-");
- niceAucId.append(uuidStr, 8, 12);
- niceAucId.append("-");
- niceAucId.append(uuidStr, 12, 16);
- niceAucId.append("-");
- niceAucId.append(uuidStr, 16, 20);
- niceAucId.append("-");
- niceAucId.append(uuidStr, 20, 32);
- return niceAucId.toString();
- }
-
public EntityOtherPlayerMP getEntityPlayer() {
- return entityPlayer;
- }
-
- private EntityOtherPlayerMP entityPlayer = null;
- private ResourceLocation playerLocationSkin = null;
- private ResourceLocation playerLocationCape = null;
- private String skinType = null;
-
- private final HashMap<String, ResourceLocation[]> panoramasMap = new HashMap<>();
-
- public ResourceLocation[] getPanoramasForLocation(String location, String identifier) {
- if (panoramasMap.containsKey(location + identifier)) return panoramasMap.get(location + identifier);
- try {
- ResourceLocation[] panoramasArray = new ResourceLocation[6];
- for (int i = 0; i < 6; i++) {
- panoramasArray[i] =
- new ResourceLocation("notenoughupdates:panoramas/" + location + "_" + identifier + "/panorama_" + i + ".jpg");
- Minecraft.getMinecraft().getResourceManager().getResource(panoramasArray[i]);
- }
- panoramasMap.put(location + identifier, panoramasArray);
- return panoramasArray;
- } catch (IOException e) {
- try {
- ResourceLocation[] panoramasArray = new ResourceLocation[6];
- for (int i = 0; i < 6; i++) {
- panoramasArray[i] =
- new ResourceLocation("notenoughupdates:panoramas/" + location + "/panorama_" + i + ".jpg");
- Minecraft.getMinecraft().getResourceManager().getResource(panoramasArray[i]);
- }
- panoramasMap.put(location + identifier, panoramasArray);
- return panoramasArray;
- } catch (IOException e2) {
- ResourceLocation[] panoramasArray = new ResourceLocation[6];
- for (int i = 0; i < 6; i++) {
- panoramasArray[i] = new ResourceLocation("notenoughupdates:panoramas/unknown/panorama_" + i + ".jpg");
- }
- panoramasMap.put(location + identifier, panoramasArray);
- return panoramasArray;
- }
- }
- }
-
- private TreeMap<Integer, Set<String>> topKills = null;
- private TreeMap<Integer, Set<String>> topDeaths = null;
-
- private void drawExtraPage(int mouseX, int mouseY, float partialTicks) {
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_extra);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- JsonObject profileInfo = profile.getProfileInformation(profileId);
- if (profileInfo == null) return;
- JsonObject skillInfo = profile.getSkillInfo(profileId);
-
- float xStart = 22;
- float xOffset = 103;
- float yStartTop = 27;
- float yStartBottom = 105;
- float yOffset = 10;
-
- float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0);
- float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
-
- Utils.renderAlignedString(
- EnumChatFormatting.GOLD + "Bank Balance",
- EnumChatFormatting.WHITE + shortNumberFormat(bankBalance, 0),
- guiLeft + xStart,
- guiTop + yStartTop,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.GOLD + "Purse",
- EnumChatFormatting.WHITE + shortNumberFormat(purseBalance, 0),
- guiLeft + xStart,
- guiTop + yStartTop + yOffset,
- 76
- );
-
- {
- String lastSaveText = this.getTimeSinceString(profileInfo, "last_save");
- if (lastSaveText != null) {
- Utils.renderAlignedString(EnumChatFormatting.AQUA + "Last Seen", EnumChatFormatting.WHITE + lastSaveText,
- guiLeft + xStart, guiTop + yStartTop + yOffset * 2, 76
- );
- }
-
- }
- {
- String first_join = this.getTimeSinceString(profileInfo, "first_join");
- if (first_join != null) {
- Utils.renderAlignedString(EnumChatFormatting.AQUA + "Joined", EnumChatFormatting.WHITE + first_join,
- guiLeft + xStart, guiTop + yStartTop + yOffset * 3, 76
- );
- }
-
- }
- {
- JsonObject guildInfo = profile.getGuildInfo(null);
- if (guildInfo != null && guildInfo.has("name")) {
- Utils.renderAlignedString(
- EnumChatFormatting.AQUA + "Guild",
- EnumChatFormatting.WHITE + guildInfo.get("name").getAsString(),
- guiLeft + xStart,
- guiTop + yStartTop + yOffset * 4,
- 76
- );
- }
- }
-
- float fairySouls = Utils.getElementAsFloat(Utils.getElement(profileInfo, "fairy_souls_collected"), 0);
-
- int fairySoulMax = 227;
- if (Constants.FAIRYSOULS != null && Constants.FAIRYSOULS.has("Max Souls")) {
- fairySoulMax = Constants.FAIRYSOULS.get("Max Souls").getAsInt();
- }
- Utils.renderAlignedString(
- EnumChatFormatting.LIGHT_PURPLE + "Fairy Souls",
- EnumChatFormatting.WHITE.toString() + (int) fairySouls + "/" + fairySoulMax,
- guiLeft + xStart,
- guiTop + yStartBottom,
- 76
- );
- if (skillInfo != null) {
- float totalSkillLVL = 0;
- float totalTrueSkillLVL = 0;
- float totalSlayerLVL = 0;
- float totalSkillCount = 0;
- float totalSlayerCount = 0;
- float totalSlayerXP = 0;
-
- for (Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) {
- if (entry.getKey().startsWith("level_skill")) {
- if (entry.getKey().contains("runecrafting")) continue;
- if (entry.getKey().contains("carpentry")) continue;
- if (entry.getKey().contains("catacombs")) continue;
-
- totalSkillLVL += entry.getValue().getAsFloat();
- totalTrueSkillLVL += Math.floor(entry.getValue().getAsFloat());
- totalSkillCount++;
- } else if (entry.getKey().startsWith("level_slayer")) {
- totalSlayerLVL += entry.getValue().getAsFloat();
- totalSlayerCount++;
- } else if (entry.getKey().startsWith("experience_slayer")) {
- totalSlayerXP += entry.getValue().getAsFloat();
- }
- }
-
- float avgSkillLVL = totalSkillLVL / totalSkillCount;
- float avgTrueSkillLVL = totalTrueSkillLVL / totalSkillCount;
- float avgSlayerLVL = totalSlayerLVL / totalSlayerCount;
-
- Utils.renderAlignedString(
- EnumChatFormatting.RED + "AVG Skill Level",
- EnumChatFormatting.WHITE.toString() + Math.floor(avgSkillLVL * 10) / 10,
- guiLeft + xStart,
- guiTop + yStartBottom + yOffset,
- 76
- );
-
- Utils.renderAlignedString(
- EnumChatFormatting.RED + "True AVG Skill Level",
- EnumChatFormatting.WHITE.toString() + Math.floor(avgTrueSkillLVL * 10) / 10,
- guiLeft + xStart,
- guiTop + yStartBottom + yOffset * 2,
- 76
- );
-
- Utils.renderAlignedString(
- EnumChatFormatting.RED + "AVG Slayer Level",
- EnumChatFormatting.WHITE.toString() + Math.floor(avgSlayerLVL * 10) / 10,
- guiLeft + xStart,
- guiTop + yStartBottom + yOffset * 3,
- 76
- );
-
- Utils.renderAlignedString(
- EnumChatFormatting.RED + "Total Slayer XP",
- EnumChatFormatting.WHITE + shortNumberFormat(totalSlayerXP, 0),
- guiLeft + xStart,
- guiTop + yStartBottom + yOffset * 4,
- 76
- );
- }
-
- float auctions_bids = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_bids"), 0);
- float auctions_highest_bid =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_highest_bid"), 0);
- float auctions_won = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_won"), 0);
- float auctions_created = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_created"), 0);
- float auctions_gold_spent = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_spent"), 0);
- float auctions_gold_earned =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.auctions_gold_earned"), 0);
-
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Auction Bids",
- EnumChatFormatting.WHITE.toString() + (int) auctions_bids,
- guiLeft + xStart + xOffset,
- guiTop + yStartTop,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Highest Bid",
- EnumChatFormatting.WHITE + shortNumberFormat(auctions_highest_bid, 0),
- guiLeft + xStart + xOffset,
- guiTop + yStartTop + yOffset,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Auctions Won",
- EnumChatFormatting.WHITE.toString() + (int) auctions_won,
- guiLeft + xStart + xOffset,
- guiTop + yStartTop + yOffset * 2,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Auctions Created",
- EnumChatFormatting.WHITE.toString() + (int) auctions_created,
- guiLeft + xStart + xOffset,
- guiTop + yStartTop + yOffset * 3,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Gold Spent",
- EnumChatFormatting.WHITE + shortNumberFormat(auctions_gold_spent, 0),
- guiLeft + xStart + xOffset,
- guiTop + yStartTop + yOffset * 4,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Gold Earned",
- EnumChatFormatting.WHITE + shortNumberFormat(auctions_gold_earned, 0),
- guiLeft + xStart + xOffset,
- guiTop + yStartTop + yOffset * 5,
- 76
- );
-
- //Slayer values
- float zombie_boss_kills_tier_2 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_2"), 0);
- float zombie_boss_kills_tier_3 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_3"), 0);
- float zombie_boss_kills_tier_4 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.boss_kills_tier_4"), 0);
- float wolf_boss_kills_tier_2 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_2"), 0);
- float wolf_boss_kills_tier_3 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.boss_kills_tier_3"), 0);
- float spider_boss_kills_tier_2 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_2"), 0);
- float spider_boss_kills_tier_3 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.boss_kills_tier_3"), 0);
- float enderman_boss_kills_tier_2 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_2"), 0);
- float enderman_boss_kills_tier_3 =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.boss_kills_tier_3"), 0);
-
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Revenant T3",
- EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_2,
- guiLeft + xStart + xOffset,
- guiTop + yStartBottom,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Revenant T4",
- EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_3,
- guiLeft + xStart + xOffset,
- guiTop + yStartBottom + yOffset,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Revenant T5",
- EnumChatFormatting.WHITE.toString() + (int) zombie_boss_kills_tier_4,
- guiLeft + xStart + xOffset,
- guiTop + yStartBottom + yOffset * 2,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Tarantula T3",
- EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_2,
- guiLeft + xStart + xOffset,
- guiTop + yStartBottom + yOffset * 3,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Tarantula T4",
- EnumChatFormatting.WHITE.toString() + (int) spider_boss_kills_tier_3,
- guiLeft + xStart + xOffset,
- guiTop + yStartBottom + yOffset * 4,
- 76
- );
-
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Sven T3",
- EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_2,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartBottom + yOffset * 0,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Sven T4",
- EnumChatFormatting.WHITE.toString() + (int) wolf_boss_kills_tier_3,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartBottom + yOffset * 1,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Voidgloom T3",
- EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_2,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartBottom + yOffset * 2,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_AQUA + "Voidgloom T4",
- EnumChatFormatting.WHITE.toString() + (int) enderman_boss_kills_tier_3,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartBottom + yOffset * 3,
- 76
- );
-
- float pet_milestone_ores_mined =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.pet_milestone_ores_mined"), 0);
- float pet_milestone_sea_creatures_killed =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.pet_milestone_sea_creatures_killed"), 0);
-
- float items_fished = Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished"), 0);
- float items_fished_treasure =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_treasure"), 0);
- float items_fished_large_treasure =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "stats.items_fished_large_treasure"), 0);
-
- Utils.renderAlignedString(
- EnumChatFormatting.GREEN + "Ores Mined",
- EnumChatFormatting.WHITE.toString() + (int) pet_milestone_ores_mined,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartTop,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.GREEN + "Sea Creatures Killed",
- EnumChatFormatting.WHITE.toString() + (int) pet_milestone_sea_creatures_killed,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartTop + yOffset,
- 76
- );
-
- Utils.renderAlignedString(
- EnumChatFormatting.GREEN + "Items Fished",
- EnumChatFormatting.WHITE.toString() + (int) items_fished,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartTop + yOffset * 3,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.GREEN + "Treasures Fished",
- EnumChatFormatting.WHITE.toString() + (int) items_fished_treasure,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartTop + yOffset * 4,
- 76
- );
- Utils.renderAlignedString(
- EnumChatFormatting.GREEN + "Large Treasures",
- EnumChatFormatting.WHITE.toString() + (int) items_fished_large_treasure,
- guiLeft + xStart + xOffset * 2,
- guiTop + yStartTop + yOffset * 5,
- 76
- );
-
- if (topKills == null) {
- topKills = new TreeMap<>();
- JsonObject stats = profileInfo.get("stats").getAsJsonObject();
- for (Map.Entry<String, JsonElement> entry : stats.entrySet()) {
- if (entry.getKey().startsWith("kills_")) {
- if (entry.getValue().isJsonPrimitive()) {
- JsonPrimitive prim = (JsonPrimitive) entry.getValue();
- if (prim.isNumber()) {
- String name = WordUtils.capitalizeFully(entry.getKey().substring("kills_".length()).replace("_", " "));
- Set<String> kills = topKills.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>());
- kills.add(name);
- }
- }
- }
- }
- }
- if (topDeaths == null) {
- topDeaths = new TreeMap<>();
- JsonObject stats = profileInfo.get("stats").getAsJsonObject();
- for (Map.Entry<String, JsonElement> entry : stats.entrySet()) {
- if (entry.getKey().startsWith("deaths_")) {
- if (entry.getValue().isJsonPrimitive()) {
- JsonPrimitive prim = (JsonPrimitive) entry.getValue();
- if (prim.isNumber()) {
- String name = WordUtils.capitalizeFully(entry.getKey().substring("deaths_".length()).replace("_", " "));
- Set<String> deaths = topDeaths.computeIfAbsent(prim.getAsInt(), k -> new HashSet<>());
- deaths.add(name);
- }
- }
- }
- }
- }
-
- int index = 0;
- for (int killCount : topKills.descendingKeySet()) {
- if (index >= 6) break;
- Set<String> kills = topKills.get(killCount);
- for (String killType : kills) {
- if (index >= 6) break;
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + killType + " Kills",
- EnumChatFormatting.WHITE.toString() + killCount,
- guiLeft + xStart + xOffset * 3,
- guiTop + yStartTop + yOffset * index,
- 76
- );
- index++;
- }
- }
- index = 0;
- for (int deathCount : topDeaths.descendingKeySet()) {
- if (index >= 6) break;
- Set<String> deaths = topDeaths.get(deathCount);
- for (String deathType : deaths) {
- if (index >= 6) break;
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Deaths: " + deathType,
- EnumChatFormatting.WHITE.toString() + deathCount,
- guiLeft + xStart + xOffset * 3,
- guiTop + yStartBottom + yOffset * index,
- 76
- );
- index++;
- }
- }
- }
-
- private void drawMiningPage(int mouseX, int mouseY, float partialTicks) {
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_mining);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- JsonObject profileInfo = profile.getProfileInformation(profileId);
- if (profileInfo == null) return;
- JsonObject skillInfo = profile.getSkillInfo(profileId);
-
- float xStart = 22;
- float xOffset = 103;
- float yStartTop = 27;
- float yStartBottom = 105;
- float yOffset = 10;
-
- int x = guiLeft + 23;
- int y = guiTop + 25;
- int sectionWidth = 110;
- JsonObject leveling = Constants.LEVELING;
- ProfileViewer.Level levelObjhotm = levelObjhotms.get(profileId);
- if (levelObjhotm == null) {
- float hotmXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0);
- levelObjhotm = ProfileViewer.getLevel(Utils.getElement(leveling, "HOTM").getAsJsonArray(),
- hotmXp, 7, false
- );
- levelObjhotms.put(profileId, levelObjhotm);
- }
-
- String skillName = EnumChatFormatting.RED + "HOTM";
- //The stats that show
- float mithrilPowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_mithril"), 0);
- float gemstonePowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_gemstone"), 0);
- float mithrilPowderTotal =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_mithril"), 0);
- float gemstonePowderTotal =
- (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_spent_gemstone"), 0));
- String jadeCrystal =
- (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.state"), "Not Found"));
- float crystalPlacedAmount =
- (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.total_placed"), 0));
- String jadeCrystalString = "§c✖";
- String amethystCrystal = (Utils.getElementAsString(
- Utils.getElement(profileInfo, "mining_core.crystals.amethyst_crystal.state"),
- "Not Found"
- ));
- String amethystCrystalString = "§c✖";
- String amberCrystal = (Utils.getElementAsString(
- Utils.getElement(profileInfo, "mining_core.crystals.amber_crystal.state"),
- "Not Found"
- ));
- String amberCrystalString = "§c✖";
- String sapphireCrystal = (Utils.getElementAsString(
- Utils.getElement(profileInfo, "mining_core.crystals.sapphire_crystal.state"),
- "Not Found"
- ));
- String sapphireCrystalString = "§c✖";
- String topazCrystal = (Utils.getElementAsString(
- Utils.getElement(profileInfo, "mining_core.crystals.topaz_crystal.state"),
- "Not Found"
- ));
- String topazCrystalString = "§c✖";
- String jasperCrystal = (Utils.getElementAsString(
- Utils.getElement(profileInfo, "mining_core.crystals.jasper_crystal.state"),
- "Not Found"
- ));
- String jasperCrystalString = "§c✖";
- String rubyCrystal =
- (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.ruby_crystal.state"), "Not Found"));
- String rubyCrystalString = "§c✖";
- int miningFortune = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0)));
- int miningFortuneStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0)) * 5);
- int miningSpeed = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)));
- int miningSpeedStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)) * 20);
- int dailyPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)));
- int dailyPowderStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)) * 36 + 364);
- int effMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)));
- float effMinerStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * 0.4 +
- 10.4);
- float effMinerStat2 =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * .06 +
- 0.31);
- int tittyInsane =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0)));
- float tittyInsaneStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0)) * .1 +
- 2);
- int luckofcave = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0)));
- int luckofcaveStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0)));
- int madMining = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_madness"), 0)));
- int skyMall = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_effect"), 0)));
- int goblinKiller = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.goblin_killer"), 0)));
- int seasonMine = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)));
- float seasonMineStat = (float) (
- (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)) * 0.1 + 5);
- int quickForge = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)));
- float quickForgeStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)) * .5 + 10);
- int frontLoad = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.front_loaded"), 0)));
- int orbit = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)));
- float orbitStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)) * .01 +
- 0.2);
- int crystallized =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0)));
- int crystallizedStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"), 0)) * 6 + 14);
- int professional = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0)));
- int professionalStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0)) * 5 + 50);
- int greatExplorer = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0)));
- int greatExplorerStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0)) * 4 + 16);
- int fortunate = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)));
- int fortunateStat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)) * 4 + 20);
- int lonesomeMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)));
- float lonesomeMinerStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)) * .5 +
- 5);
- int miningFortune2 =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0)));
- int miningFortune2Stat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"), 0)) * 5);
- int miningSpeed2 = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0)));
- int miningSpeed2Stat =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0)) * 40);
- int miningSpeedBoost =
- ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_boost"), 0)));
- int veinSeeker = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.vein_seeker"), 0)));
- int powderBuff = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.powder_buff"), 0)));
- int potm = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.special_0"), 0)));
- int fortnite = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.precision_mining"), 0)));
- int starPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.star_powder"), 0)));
- int pickoblus = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.pickaxe_toss"), 0)));
- int maniacMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.maniac_miner"), 0)));
-
- if (effMinerStat2 < 1) {
- effMinerStat2 = 1;
- }
- int mole = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)));
- float moleStat =
- (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)) * 0.051);
- double moleperkstat = (double) mole / 20 - 0.55 + 50;
- double moleperkstat2 = (double) Math.round(moleperkstat * 100) / 100;
-
- float output = Math.round((float) (moleperkstat2 % 1) * 100);
- if (output == 0) {
- output = 100;
- }
-
- //The logic for some of the stats
- if (Objects.equals(jadeCrystal, "NOT_FOUND")) {
- jadeCrystalString = "§c✖";
- } else if (Objects.equals(jadeCrystal, "FOUND")) {
- jadeCrystalString = "§a✔";
- }
- if (Objects.equals(amethystCrystal, "NOT_FOUND")) {
- amethystCrystalString = "§c✖";
- } else if (Objects.equals(amethystCrystal, "FOUND")) {
- amethystCrystalString = "§a✔";
- }
- if (Objects.equals(amberCrystal, "NOT_FOUND")) {
- amberCrystalString = "§c✖";
- } else if (Objects.equals(amberCrystal, "FOUND")) {
- amberCrystalString = "§a✔";
- }
- if (Objects.equals(sapphireCrystal, "NOT_FOUND")) {
- sapphireCrystalString = "§c✖";
- } else if (Objects.equals(sapphireCrystal, "FOUND")) {
- sapphireCrystalString = "§a✔";
- }
- if (Objects.equals(topazCrystal, "NOT_FOUND")) {
- topazCrystalString = "§c✖";
- } else if (Objects.equals(topazCrystal, "FOUND")) {
- topazCrystalString = "§a✔";
- }
- if (Objects.equals(jasperCrystal, "NOT_FOUND")) {
- jasperCrystalString = "§c✖";
- } else if (Objects.equals(jasperCrystal, "FOUND")) {
- jasperCrystalString = "§a✔";
- }
- if (Objects.equals(rubyCrystal, "NOT_FOUND")) {
- rubyCrystalString = "§c✖";
- } else if (Objects.equals(rubyCrystal, "FOUND")) {
- rubyCrystalString = "§a✔";
- }
-
- //The rendering of the stats
- //hotm level
- renderXpBar(skillName, iron_pick, x, y, sectionWidth, levelObjhotm, mouseX, mouseY);
- //Powder
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_GREEN + "Mithril Powder",
- EnumChatFormatting.WHITE + shortNumberFormat(mithrilPowder, 0),
- guiLeft + xStart,
- guiTop + yStartTop + 24,
- 115
- );
- Utils.renderAlignedString(
- EnumChatFormatting.LIGHT_PURPLE + "Gemstone Powder",
- EnumChatFormatting.WHITE + shortNumberFormat(gemstonePowder, 0),
- guiLeft + xStart,
- guiTop + yStartTop + 44,
- 115
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_GREEN + "Total Mithril Powder",
- EnumChatFormatting.WHITE + shortNumberFormat(mithrilPowderTotal + mithrilPowder, 0),
- guiLeft + xStart,
- guiTop + yStartTop + 34,
- 115
- );
- Utils.renderAlignedString(
- EnumChatFormatting.LIGHT_PURPLE + "Total Gemstone Powder",
- EnumChatFormatting.WHITE + shortNumberFormat(gemstonePowderTotal + gemstonePowder, 0),
- guiLeft + xStart,
- guiTop + yStartTop + 54,
- 115
- );
- //Crystals
- Utils.renderAlignedString(EnumChatFormatting.GREEN + "Jade Crystal:", EnumChatFormatting.WHITE + jadeCrystalString,
- guiLeft + xStart, guiTop + yStartTop + 74, 110
- );
- Utils.renderAlignedString(EnumChatFormatting.GOLD + "Amber Crystal:", EnumChatFormatting.WHITE + amberCrystalString,
- guiLeft + xStart, guiTop + yStartTop + 84, 110
- );
- Utils.renderAlignedString(
- EnumChatFormatting.DARK_PURPLE + "Amethyst Crystal:",
- EnumChatFormatting.WHITE + amethystCrystalString,
- guiLeft + xStart,
- guiTop + yStartTop + 94,
- 110
- );
- Utils.renderAlignedString(
- EnumChatFormatting.AQUA + "Sapphire Crystal:",
- EnumChatFormatting.WHITE + sapphireCrystalString,
- guiLeft + xStart,
- guiTop + yStartTop + 104,
- 110
- );
- Utils.renderAlignedString(
- EnumChatFormatting.YELLOW + "Topaz Crystal:",
- EnumChatFormatting.WHITE + topazCrystalString,
- guiLeft + xStart,
- guiTop + yStartTop + 114,
- 110
- );
- Utils.renderAlignedString(
- EnumChatFormatting.LIGHT_PURPLE + "Jasper Crystal:",
- EnumChatFormatting.WHITE + jasperCrystalString,
- guiLeft + xStart,
- guiTop + yStartTop + 124,
- 110
- );
- Utils.renderAlignedString(EnumChatFormatting.RED + "Ruby Crystal:", EnumChatFormatting.WHITE + rubyCrystalString,
- guiLeft + xStart, guiTop + yStartTop + 134, 110
- );
- Utils.renderAlignedString(
- EnumChatFormatting.BLUE + "Total Placed Crystals:",
- EnumChatFormatting.WHITE + shortNumberFormat(crystalPlacedAmount, 0),
- guiLeft + xStart,
- guiTop + yStartTop + 149,
- 110
- );
-
- //hotm render
- //Pain
-
- renderHotmPerk(
- miningSpeed,
- (int) (guiLeft + xStart + 255),
- (int) (guiTop + yStartTop + 138),
- mouseX,
- mouseY,
- () -> Lists.newArrayList(
- "Mining Speed",
- EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningSpeedStat +
- EnumChatFormatting.GOLD + " ⸕ Mining",
- EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + "."
- ),
- 50
- );
-
- renderHotmPerk(
- miningFortune,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 114),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Mining Fortune",
- EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "+" + miningFortuneStat +
- EnumChatFormatting.GOLD + " ☘ Mining",
- EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + "."
- ),
- 50
- );
-
- renderHotmPerk(
- tittyInsane,
- (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 114),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Titanium Insanium",
- EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- EnumChatFormatting.GRAY + "When mining Mithril Ore, you",
- EnumChatFormatting.GRAY + "have a " + EnumChatFormatting.GREEN + tittyInsaneStat + "% " +
- EnumChatFormatting.GRAY + "chance to",
- EnumChatFormatting.GRAY + "convert the block into Titanium",
- EnumChatFormatting.GRAY + "Ore."
- ),
- 50
- );
-
- renderPickaxeAbility(
- miningSpeedBoost,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 114),
- mouseX, mouseY,
- () -> potm == 0 ? Lists.newArrayList( // Peak of the mountain == 0
- "Mining Speed Boost",
- "",
- EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost",
- EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "200% " + EnumChatFormatting.GOLD + "⸕ Mining",
- EnumChatFormatting.GOLD + "Speed " + EnumChatFormatting.GRAY + "for " + EnumChatFormatting.GREEN + "15s" +
- EnumChatFormatting.GRAY,
- EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s"
- ) : Lists.newArrayList( // Peak of the mountain > 0
- "Mining Speed Boost",
- "",
- EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost",
- EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "300% " + EnumChatFormatting.GOLD + "⸕ Mining",
- EnumChatFormatting.GOLD + "Speed " + EnumChatFormatting.GRAY + "for " + EnumChatFormatting.GREEN + "20s" +
- EnumChatFormatting.GRAY,
- EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s"
- )
- );
-
- renderPickaxeAbility(
- veinSeeker,
- (int) (guiLeft + xStart + 183), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Vein Seeker",
- "",
- "§6Pickaxe Ability: Vein Seeker",
- "§7Points in the direction of the",
- "§7nearest vein and grants §a+§a3§7",
- "§7§6Mining Spread §7for §a14s§7§7.",
- "§8Cooldown: §a60s"
- )
- );
-
- renderHotmPerk(
- luckofcave,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 90),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Luck of the Cave",
- "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45",
- "",
- "§7Increases the chance for you to",
- "§7trigger rare occurrences im",
- "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7."
- ),
- 45
- );
-
- renderHotmPerk(
- dailyPowder,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 90),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Daily Powder",
- EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100",
- "",
- EnumChatFormatting.GRAY + "Gains " + EnumChatFormatting.GREEN + dailyPowderStat + " Powder" +
- EnumChatFormatting.GRAY + " from the",
- EnumChatFormatting.GRAY + "first ore you mine every day.",
- EnumChatFormatting.GRAY + "Works for all Powder types."
- ),
- 100
- );
-
- float finalEffMinerStat2 = effMinerStat2;
- renderHotmPerk(
- effMiner,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Efficient Miner",
- EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100",
- "",
- EnumChatFormatting.GRAY + "When mining ores, you have a",
- EnumChatFormatting.GREEN + "" + effMinerStat + "%" + EnumChatFormatting.GRAY + " chance to mine " +
- EnumChatFormatting.GREEN + Math.round(finalEffMinerStat2),
- EnumChatFormatting.GRAY + "adjacent ores."
- ),
- 100
- );
-
- renderHotmPerk(
- potm,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 42),
- mouseX, mouseY,
- () -> {
- switch (potm) {
- case 0:
- return Lists.newArrayList(
- EnumChatFormatting.RED + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5"
- );
- case 1:
- return Lists.newArrayList(
- EnumChatFormatting.YELLOW + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5",
- "",
- "§7§8+§c1 Pickaxe Ability Level",
- "§7§8+§51 Token of the Mountain"
- );
- case 2:
- return Lists.newArrayList(
- EnumChatFormatting.YELLOW + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5",
- "",
- "§7§8+§c1 Pickaxe Ability Level",
- "§7§8+§51 Token of the Mountain",
- "§7§8+§a1 Forge Slot"
- );
- case 3:
- return Lists.newArrayList(
- EnumChatFormatting.YELLOW + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5",
- "",
- "§7§8+§c1 Pickaxe Ability Level",
- "§7§8+§51 Token of the Mountain",
- "§7§8+§a1 Forge Slot",
- "§7§8+§a1 Commission Slot"
- );
- case 4:
- return Lists.newArrayList(
- EnumChatFormatting.YELLOW + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5",
- "",
- "§7§8+§c1 Pickaxe Ability Level",
- "§7§8+§51 Token of the Mountain",
- "§7§8+§a1 Forge Slot",
- "§7§8+§a1 Commission Slot",
- "§7§8+§21 Mithril Powder §7when",
- "§7mining §fMithril"
- );
- case 5:
- return Lists.newArrayList(
- EnumChatFormatting.GREEN + "Peak of the Mountain",
- EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/5",
- "",
- "§7§8+§c1 Pickaxe Ability Level",
- "§7§8+§51 Token of the Mountain",
- "§7§8+§a1 Forge Slot",
- "§7§8+§a1 Commission Slot",
- "§7§8+§21 Mithril Powder §7when",
- "§7mining §fMithril",
- "§7§8+§51 Token of the Mountain"
- );
- }
- return null;
- },
- potm > 0 ? new ItemStack(Blocks.redstone_block) : new ItemStack(Blocks.bedrock),
- true // A redstone block or bedrock is being rendered, so standard GUI item lighting needs to be enabled.
- );
-
- float finalOutput = output;
- renderHotmPerk(
- mole,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Mole",
- EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190",
- "",
- EnumChatFormatting.GRAY + "When mining hard stone, you have",
- EnumChatFormatting.GRAY + "a " + EnumChatFormatting.GREEN + finalOutput + "% " + EnumChatFormatting.GRAY +
- "chance to mine " + EnumChatFormatting.GREEN,
- EnumChatFormatting.GREEN + "" + Math.round(moleStat) + EnumChatFormatting.GRAY + " adjacent hard stone block" +
- (moleStat == 1.0 ? "." : "s.")
- ),
- 190
- );
-
- renderHotmPerk(
- powderBuff,
- (int) (guiLeft + xStart + 255), (int) (guiTop + yStartTop - 6),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Powder Buff",
- EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- EnumChatFormatting.GRAY + "Gain " + EnumChatFormatting.GREEN + powderBuff + "% " + EnumChatFormatting.GRAY +
- "more Mithril",
- EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7."
- ),
- 50
- );
-
- renderHotmPerk(
- skyMall,
- (int) (guiLeft + xStart + 183), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Sky Mall",
- "§7Every SkyBlock day, you receive",
- "§7a random buff in the §2Dwarven",
- "§2Mines§7.",
- "",
- "§7Possible Buffs",
- "§8 ■ §7Gain §a+100 §6⸕ Mining Speed.",
- "§8 ■ §7Gain §a+50 §6☘ Mining Fortune.",
- "§8 ■ §7Gain §a+15% §7chance to gain",
- " §7extra Powder while mining.",
- "§8 ■ §7Reduce Pickaxe Ability cooldown",
- " §7by §a20%", "§8 ■ §7§a10x §7chance to find Goblins",
- " §7while mining.",
- "§8 ■ §7Gain §a5x §9Titanium §7drops."
- ),
- new ItemStack(skyMall > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- goblinKiller,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 42),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Goblin Killer",
- "§7Killing a §6Golden Goblin",
- "§6§7gives §2200 §7extra §2Mithril",
- "§2Powder§7, while killing other",
- "§7Goblins gives some based on",
- "§7their wits."
- ),
- new ItemStack(goblinKiller > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- seasonMine,
- (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Seasoned Mineman",
- "§7Level " + seasonMine + "§8/100",
- "",
- "§7Increases your Mining",
- "§7experience gain by " + EnumChatFormatting.GREEN + seasonMineStat + "%§7."
- ),
- 100
- );
-
- renderHotmPerk(
- madMining,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Mining Madness",
- "§7Grants §a+50 §6⸕ Mining Speed",
- "§7and §6☘ Mining Fortune§7."
- ),
- new ItemStack(madMining > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- lonesomeMiner,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Lonesome Miner",
- "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45",
- "",
- "§7Increases §c❁ Strength, §9☣ Crit",
- "§9Chance, §9☠ Crit Damage, §a❈",
- "§aDefense, and §c❤ Health",
- "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7",
- "§7while in the Crystal Hollows."
- ),
- 45
- );
-
- renderHotmPerk(
- professional,
- (int) (guiLeft + xStart + 231), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Professional",
- "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140",
- "",
- "§7Gain §a+" + professionalStat + "§6 ⸕ Mining",
- "§6Speed§7 when mining Gemstones."
- ),
- 140
- );
-
- renderHotmPerk(
- miningSpeed2,
- (int) (guiLeft + xStart + 207), (int) (guiTop + yStartTop - 6),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Mining Speed 2",
- "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining",
- "§6Speed§7."
- ),
- 50
- );
-
- renderHotmPerk(
- quickForge,
- (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 114),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Quick Forge",
- "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20",
- "",
- "§7Decreases the time it takes to",
- "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7."
- ),
- 20
- );
-
- renderHotmPerk(
- fortunate,
- (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Fortunate",
- "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20",
- "",
- "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining",
- "§6Fortune§7 when mining Gemstone."
- ),
- 20
- );
-
- renderHotmPerk(
- greatExplorer,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Great Explorer",
- "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20",
- "",
- "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY + "chance to",
- "§7find treasure."
- ),
- 20
- );
-
- renderHotmPerk(
- miningFortune2,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop - 6),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Mining Fortune 2",
- "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50",
- "",
- "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining", "§6Fortune§7."
- ),
- 50
- );
-
- renderHotmPerk(
- orbit,
- (int) (guiLeft + xStart + 279), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Orbiter",
- "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80",
- "",
- "§7When mining ores, you have a",
- EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random",
- "§7amount of experience orbs."
- ),
- 80
- );
-
- renderHotmPerk(
- frontLoad,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Front Loaded",
- "§7Grants §a+100 §6⸕ Mining Speed",
- "§7and §6☘ Mining Fortune §7for",
- "§7the first §e2,500 §7ores you",
- "§7mine in a day."
- ),
- new ItemStack(frontLoad > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- starPowder,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 42),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Star Powder",
- "§7Mining Mithril Ore near §5Fallen",
- "§5Crystals §7gives §a+3 §7extra",
- "§7Mithril Powder§7."
- ),
- new ItemStack(starPowder > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- fortnite,
- (int) (guiLeft + xStart + 327), (int) (guiTop + yStartTop + 66),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Precision Mining",
- "§7When mining ore, a particle",
- "§7target appears on the block that",
- "§7increases your §6⸕ Mining Speed",
- "§7by §a30% §7when aiming at it."
- ),
- new ItemStack(fortnite > 0 ? Items.diamond : Items.coal)
- );
-
- renderHotmPerk(
- crystallized,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 90),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Crystallized",
- "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30",
- "",
- "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining",
- "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance",
- "§7to deal §a+1 §7extra damage near",
- "§7§5Fallen Stars§7."
- ),
- 30
- );
-
- renderPickaxeAbility(
- pickoblus,
- (int) (guiLeft + xStart + 303), (int) (guiTop + yStartTop + 114),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- "Pickobulus",
- "",
- "§6Pickaxe Ability: Pickobulus",
- "§7Throw your pickaxe to create an",
- "§7explosion on impact, mining all",
- "§7ores within a §a2§7 block",
- "§7radius.",
- "§8Cooldown: §a" + (potm == 0 ? "120s" : "110s")
- )
- );
-
- renderPickaxeAbility(
- maniacMiner,
- (int) (guiLeft + xStart + 327), (int) (guiTop + yStartTop + 18),
- mouseX, mouseY,
- () -> Lists.newArrayList(
- EnumChatFormatting.RED + "Maniac Miner",
- "",
- "§6Pickaxe Ability: Maniac Miner",
- "§7Spends all your Mana and grants",
- "§7§a+1 §6⸕ Mining Speed §7for",
- "§7every 10 Mana spent, for",
- "§7§a§a15s§7§7.",
- "§8Cooldown: §a59s"
- )
- );
- }
-
- /**
- * Renders a standard HOTM perk that can be levelled.
- */
- private void renderHotmPerk(
- int perkLevel,
- int xPosition,
- int yPosition,
- int mouseX,
- int mouseY,
- Supplier<ArrayList<String>> tooltipSupplier,
- int maxLevel
- ) {
- renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, false, maxLevel);
- }
-
- /**
- * Renders a pickaxe ability that can be unlocked once and not levelled.
- */
- private void renderPickaxeAbility(
- int perkLevel,
- int xPosition,
- int yPosition,
- int mouseX,
- int mouseY,
- Supplier<ArrayList<String>> tooltipSupplier
- ) {
- renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, true, -1);
- }
-
- /**
- * Renders a HOTM perk. This method is only called from its overloads above.
- */
- private void renderHotmPerk(
- int perkLevel,
- int xPosition,
- int yPosition,
- int mouseX,
- int mouseY,
- Supplier<ArrayList<String>> tooltipSupplier,
- boolean isPickaxeAbility,
- int maxLevel
- ) {
- boolean unlocked = perkLevel > 0;
- GlStateManager.color(1, 1, 1, 1);
- GlStateManager.disableLighting();
-
- ItemStack itemStack;
- if (isPickaxeAbility) {
- RenderHelper.enableGUIStandardItemLighting(); // GUI standard item lighting must be enabled for items that are rendered as blocks, like emerald blocks.
- itemStack =
- new ItemStack(unlocked ? Blocks.emerald_block : Blocks.coal_block); // Pickaxe abilities are rendered as blocks
- } else { // Non-pickaxe abilities are rendered as items
- itemStack = new ItemStack(unlocked ? (perkLevel >= maxLevel ? Items.diamond : Items.emerald) : Items.coal);
- }
-
- ArrayList<String> tooltip = tooltipSupplier.get();
- // Prepend the green, yellow, or red color on the first line of each tooltip depending on if the perk is unlocked
- tooltip.set(
- 0,
- (unlocked
- ? (perkLevel >= maxLevel ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW)
- : EnumChatFormatting.RED) + tooltip.get(0)
- );
-
- NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs
- NBTTagCompound display = new NBTTagCompound();
- display.setString("Name", tooltip.get(0));
- nbt.setTag("display", display);
- itemStack.setTagCompound(nbt);
-
- Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition);
- GlStateManager.enableLighting();
- if (mouseX >= xPosition && mouseX < xPosition + 16) {
- if (mouseY >= yPosition && mouseY <= yPosition + 16) {
- Utils.drawHoveringText(tooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
- }
- }
- }
-
- /**
- * A separate method similar to the one above, but allowing the caller to specify an ItemStack to render.
- * Used for rendering Peak of the Mountain and perks that are unlocked once and not upgraded.
- */
- private void renderHotmPerk(
- int perkLevel,
- int xPosition,
- int yPosition,
- int mouseX,
- int mouseY,
- Supplier<ArrayList<String>> tooltipSupplier,
- ItemStack itemStack
- ) {
- renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, itemStack, false);
- }
-
- /**
- * This method renders a HOTM perk using the provided ItemStack.
- * It is overloaded by the method above, and is only called directly to render Peak of the Mountain.
- */
- private void renderHotmPerk(
- int perkLevel,
- int xPosition,
- int yPosition,
- int mouseX,
- int mouseY,
- Supplier<ArrayList<String>> tooltipSupplier,
- ItemStack itemStack,
- boolean isRenderingBlock
- ) {
- boolean unlocked = perkLevel > 0;
- GlStateManager.color(1, 1, 1, 1);
- GlStateManager.disableLighting();
- if (isRenderingBlock) RenderHelper.enableGUIStandardItemLighting();
-
- ArrayList<String> tooltip = tooltipSupplier.get();
- // Prepend the green or red color on the first line of each tooltip depending on if the perk is unlocked
- if (!tooltip.get(0).contains("Peak of the Mountain")) tooltip.set(
- 0,
- (unlocked ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + tooltip.get(0)
- ); //Peak of the Moutain has three color options, and is set already
-
- NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Resource Packs
- NBTTagCompound display = new NBTTagCompound();
- display.setString("Name", tooltip.get(0));
- if (tooltip.get(0).contains("Peak of the Mountain")) display.setString("Lore", tooltip.get(1)); //Set Lore to Level
- nbt.setTag("display", display);
- itemStack.setTagCompound(nbt);
-
- Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition);
- GlStateManager.enableLighting();
- if (mouseX >= xPosition && mouseX < xPosition + 16) {
- if (mouseY >= yPosition && mouseY <= yPosition + 16) {
- Utils.drawHoveringText(tooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
- }
- }
- }
-
- private String getTimeSinceString(JsonObject profileInfo, String path) {
- JsonElement lastSaveElement = Utils.getElement(profileInfo, path);
-
- if (lastSaveElement != null && lastSaveElement.isJsonPrimitive()) {
-
- Instant lastSave = Instant.ofEpochMilli(lastSaveElement.getAsLong());
- LocalDateTime lastSaveTime = LocalDateTime.ofInstant(lastSave, TimeZone.getDefault().toZoneId());
- long timeDiff = System.currentTimeMillis() - lastSave.toEpochMilli();
- LocalDateTime sinceOnline = LocalDateTime.ofInstant(Instant.ofEpochMilli(timeDiff), ZoneId.of("UTC"));
- String renderText;
-
- if (timeDiff < 60000L) {
- renderText = sinceOnline.getSecond() + " seconds ago.";
- } else if (timeDiff < 3600000L) {
- renderText = sinceOnline.getMinute() + " minutes ago.";
- } else if (timeDiff < 86400000L) {
- renderText = sinceOnline.getHour() + " hours ago.";
- } else if (timeDiff < 31556952000L) {
- renderText = sinceOnline.getDayOfYear() + " days ago.";
- } else {
- renderText = lastSaveTime.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
- }
- return renderText;
- }
- return null;
- }
-
- private int backgroundClickedX = -1;
-
- private static final char[] c = new char[]{'k', 'm', 'b', 't'};
-
- public static String shortNumberFormat(double n, int iteration) {
- if (n < 1000) {
- if (n % 1 == 0) {
- return Integer.toString((int) n);
- } else {
- return String.format("%.2f", n);
- }
- }
-
- double d = ((long) n / 100) / 10.0;
- boolean isRound = (d * 10) % 10 == 0;
- return (d < 1000 ?
- ((d > 99.9 || isRound || (!isRound && d > 9.99) ?
- (int) d * 10 / 10 : d + ""
- ) + "" + c[iteration])
- : shortNumberFormat(d, iteration + 1));
- }
-
- private boolean loadingProfile = false;
- private static final ExecutorService profileLoader = Executors.newFixedThreadPool(1);
-
- private void drawBasicPage(int mouseX, int mouseY, float partialTicks) {
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
-
- String location = null;
- JsonObject status = profile.getPlayerStatus();
- if (status != null && status.has("mode")) {
- location = status.get("mode").getAsString();
- }
-
- int extraRotation = 0;
- if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
- if (backgroundClickedX == -1) {
- if (mouseX > guiLeft + 23 && mouseX < guiLeft + 23 + 81) {
- if (mouseY > guiTop + 44 && mouseY < guiTop + 44 + 108) {
- backgroundClickedX = mouseX;
- }
- }
- }
- } else {
- if (backgroundClickedX != -1) {
- backgroundRotation += mouseX - backgroundClickedX;
- backgroundClickedX = -1;
- }
- }
- if (backgroundClickedX == -1) {
- backgroundRotation += (currentTime - lastTime) / 400f;
- } else {
- extraRotation = mouseX - backgroundClickedX;
- }
- backgroundRotation %= 360;
-
- String panoramaIdentifier = "day";
- if (SBInfo.getInstance().currentTimeDate != null) {
- if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
- SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
- panoramaIdentifier = "night";
- }
- }
-
- Panorama.drawPanorama(-backgroundRotation - extraRotation, guiLeft + 23, guiTop + 44, 81, 108, 0.37f, 0.8f,
- getPanoramasForLocation(location == null ? "unknown" : location, panoramaIdentifier)
- );
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic);
- Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
-
- if (entityPlayer != null && profile.getHypixelProfile() != null) {
- String playerName = null;
- if (profile.getHypixelProfile().has("prefix")) {
- playerName =
- Utils.getElementAsString(profile.getHypixelProfile().get("prefix"), "") + " " + entityPlayer.getName();
- } else {
- String rank = Utils.getElementAsString(
- profile.getHypixelProfile().get("rank"),
- Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE")
- );
- String monthlyPackageRank =
- Utils.getElementAsString(profile.getHypixelProfile().get("monthlyPackageRank"), "NONE");
- if (!rank.equals("YOUTUBER") && !monthlyPackageRank.equals("NONE")) {
- rank = monthlyPackageRank;
- }
- EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName(Utils.getElementAsString(
- profile.getHypixelProfile().get("rankPlusColor"),
- "GOLD"
- ));
- String rankPlusColor = EnumChatFormatting.GOLD.toString();
- if (rankPlusColorECF != null) {
- rankPlusColor = rankPlusColorECF.toString();
- }
-
- JsonObject misc = Constants.MISC;
- if (misc != null) {
- if (misc.has("ranks")) {
- String rankName = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".tag"), null);
- String rankColor = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".color"), "7");
- String rankPlus = Utils.getElementAsString(Utils.getElement(misc, "ranks." + rank + ".plus"), "");
-
- String name = entityPlayer.getName();
-
- if (misc.has("special_bois")) {
- JsonArray special_bois = misc.get("special_bois").getAsJsonArray();
- for (int i = 0; i < special_bois.size(); i++) {
- if (special_bois.get(i).getAsString().equals(profile.getUuid())) {
- name = Utils.chromaString(name);
- break;
- }
- }
- }
-
- playerName = EnumChatFormatting.GRAY + name;
- if (rankName != null) {
- StringBuilder sb = new StringBuilder();
- sb.append("\u00A7" + rankColor);
- sb.append("[");
- sb.append(rankName);
- sb.append(rankPlusColor);
- sb.append(rankPlus);
- sb.append("\u00A7" + rankColor);
- sb.append("] ");
- sb.append(name);
- playerName = sb.toString();
- }
- }
- }
-
- }
- if (playerName != null) {
- int rankPrefixLen = fr.getStringWidth(playerName);
- int halfRankPrefixLen = rankPrefixLen / 2;
-
- int x = guiLeft + 63;
- int y = guiTop + 54;
-
- drawRect(x - halfRankPrefixLen - 1, y - 1, x + halfRankPrefixLen + 1, y + 8, new Color(0, 0, 0, 64).getRGB());
-
- fr.drawString(playerName, x - halfRankPrefixLen, y, 0, true);
- }
- }
-
- long networth = profile.getNetWorth(profileId);
- if (networth > 0) {
- Utils.drawStringCentered(
- EnumChatFormatting.GREEN + "Net Worth: " + EnumChatFormatting.GOLD + numberFormat.format(networth),
- fr,
- guiLeft + 63,
- guiTop + 38,
- true,
- 0
- );
- try {
- double networthInCookies = (networth / NotEnoughUpdates.INSTANCE.manager.auctionManager
- .getBazaarInfo("BOOSTER_COOKIE")
- .get("avg_buy")
- .getAsDouble());
- String networthIRLMoney = Long.toString(Math.round(((networthInCookies * 325) / 675) * 4.99));
-
- if (mouseX > guiLeft + 8 &&
- mouseX < guiLeft + 8 + fontRendererObj.getStringWidth("Net Worth: " + numberFormat.format(networth))) {
- if (mouseY > guiTop + 32 && mouseY < guiTop + 32 + fontRendererObj.FONT_HEIGHT) {
- tooltipToDisplay = new ArrayList<>();
- tooltipToDisplay.add(
- EnumChatFormatting.GREEN + "Net worth in IRL money: " + EnumChatFormatting.DARK_GREEN + "$" +
- EnumChatFormatting.GOLD + networthIRLMoney);
- tooltipToDisplay.add("");
- if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
- tooltipToDisplay.add(EnumChatFormatting.RED + "This is calculated using the current");
- tooltipToDisplay.add(EnumChatFormatting.RED + "price of booster cookies on bazaar and the price");
- tooltipToDisplay.add(EnumChatFormatting.RED + "for cookies using gems, then the price of gems");
- tooltipToDisplay.add(EnumChatFormatting.RED + "is where we get the amount of IRL money you");
- tooltipToDisplay.add(EnumChatFormatting.RED + "theoretically have on skyblock in net worth.");
- } else {
- tooltipToDisplay.add(EnumChatFormatting.GRAY + "[SHIFT for Info]");
- }
- if (!NotEnoughUpdates.INSTANCE.config.hidden.dev) {
- tooltipToDisplay.add("");
- tooltipToDisplay.add(EnumChatFormatting.RED + "THIS IS IN NO WAY ENDORSING IRL TRADING!");
- }
- }
- }
- } catch (Exception ignored) {
- }
- }
-
- if (status != null) {
- JsonElement onlineElement = Utils.getElement(status, "online");
- boolean online = onlineElement != null && onlineElement.isJsonPrimitive() && onlineElement.getAsBoolean();
- String statusStr = online ? EnumChatFormatting.GREEN + "ONLINE" : EnumChatFormatting.RED + "OFFLINE";
- String locationStr = null;
- if (profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) {
- locationStr = "Ignoring DMs";
- } else {
- if (location != null) {
- JsonObject misc = Constants.MISC;
- if (misc != null) {
- locationStr = Utils.getElementAsString(Utils.getElement(misc, "area_names." + location), "Unknown");
- }
- }
- }
- if (locationStr != null) {
- statusStr += EnumChatFormatting.GRAY + " - " + EnumChatFormatting.GREEN + locationStr;
- }
-
- Utils.drawStringCentered(statusStr, fr, guiLeft + 63, guiTop + 160, true, 0);
- }
-
- if (entityPlayer == null) {
- if (!loadingProfile || ((ThreadPoolExecutor) profileLoader).getActiveCount() == 0) {
- loadingProfile = true;
- UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid()));
-
- profileLoader.submit(() -> {
- GameProfile fakeProfile = Minecraft
- .getMinecraft()
- .getSessionService()
- .fillProfileProperties(new GameProfile(playerUUID, "CoolGuy123"), false);
- entityPlayer = new EntityOtherPlayerMP(Minecraft.getMinecraft().theWorld, fakeProfile) {
- public ResourceLocation getLocationSkin() {
- return playerLocationSkin == null
- ? DefaultPlayerSkin.getDefaultSkin(this.getUniqueID())
- : playerLocationSkin;
- }
-
- public ResourceLocation getLocationCape() {
- return playerLocationCape;
- }
-
- public String getSkinType() {
- return skinType == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : skinType;
- }
- };
- entityPlayer.setAlwaysRenderNameTag(false);
- entityPlayer.setCustomNameTag("");
- });
- }
- } else {
- entityPlayer.refreshDisplayName();
- byte b = 0;
- for (EnumPlayerModelParts part : EnumPlayerModelParts.values()) {
- b |= part.getPartMask();
- }
- entityPlayer.getDataWatcher().updateObject(10, b);
- }
-
- JsonObject profileInfo = profile.getProfileInformation(profileId);
- if (profileInfo == null) return;
-
- JsonObject skillInfo = profile.getSkillInfo(profileId);
- JsonObject inventoryInfo = profile.getInventoryInfo(profileId);
-
- if (entityPlayer != null) {
- if (backgroundClickedX != -1 && Mouse.isButtonDown(1)) {
- Arrays.fill(entityPlayer.inventory.armorInventory, null);
- } else {
- if (inventoryInfo != null && inventoryInfo.has("inv_armor")) {
- JsonArray items = inventoryInfo.get("inv_armor").getAsJsonArray();
- if (items != null && items.size() == 4) {
- for (int i = 0; i < entityPlayer.inventory.armorInventory.length; i++) {
- JsonElement itemElement = items.get(i);
- if (itemElement != null && itemElement.isJsonObject()) {
- entityPlayer.inventory.armorInventory[i] =
- NotEnoughUpdates.INSTANCE.manager.jsonToStack(itemElement.getAsJsonObject(), false);
- }
- }
- }
- } else {
- Arrays.fill(entityPlayer.inventory.armorInventory, null);
- }
- }
- if (entityPlayer.getUniqueID().toString().equals("ae6193ab-494a-4719-b6e7-d50392c8f012")) {
- entityPlayer.inventory.armorInventory[3] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
- NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SMALL_BACKPACK"));
- }
- }
-
- if (entityPlayer != null && playerLocationSkin == null) {
- try {
- Minecraft
- .getMinecraft()
- .getSkinManager()
- .loadProfileTextures(entityPlayer.getGameProfile(), (type, location1, profileTexture) -> {
- switch (type) {
- case SKIN:
- playerLocationSkin = location1;
- skinType = profileTexture.getMetadata("model");
-
- if (skinType == null) {
- skinType = "default";
- }
-
- break;
- case CAPE:
- playerLocationCape = location1;
- }
- }, false);
- } catch (Exception ignored) {
- }
- }
-
- GlStateManager.color(1, 1, 1, 1);
- JsonObject petsInfo = profile.getPetsInfo(profileId);
- if (petsInfo != null) {
- JsonElement activePetElement = petsInfo.get("active_pet");
- if (activePetElement != null && activePetElement.isJsonObject()) {
- JsonObject activePet = activePetElement.getAsJsonObject();
-
- String type = activePet.get("type").getAsString();
-
- for (int i = 0; i < 4; i++) {
- JsonObject item = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(type + ";" + i);
- if (item != null) {
- int x = guiLeft + 20;
- float y = guiTop + 82 + 15 * (float) Math.sin(((currentTime - startTime) / 800f) % (2 * Math.PI));
- GlStateManager.translate(x, y, 0);
- ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false);
-
- //Remove extra attributes so no CIT
- NBTTagCompound stackTag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound();
- stackTag.removeTag("ExtraAttributes");
- stack.setTagCompound(stackTag);
-
- GlStateManager.scale(1.5f, 1.5f, 1);
- GlStateManager.enableDepth();
- Utils.drawItemStack(stack, 0, 0);
- GlStateManager.scale(1 / 1.5f, 1 / 1.5f, 1);
- GlStateManager.translate(-x, -y, 0);
- break;
- }
- }
- }
- }
- if (entityPlayer != null) {
- drawEntityOnScreen(
- guiLeft + 63,
- guiTop + 128 + 7,
- 36,
- guiLeft + 63 - mouseX,
- guiTop + 129 - mouseY,
- entityPlayer
- );
- }
-
- PlayerStats.Stats stats = profile.getStats(profileId);
-
- if (stats != null) {
- Splitter splitter = Splitter.on(" ").omitEmptyStrings().limit(2);
- for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) {
- String statName = PlayerStats.defaultStatNames[i];
- if (statName.equals("mining_fortune") || statName.equals("mining_speed")) continue;
- String statNamePretty = PlayerStats.defaultStatNamesPretty[i];
-
- int val = Math.round(stats.get(statName));
-
- GlStateManager.color(1, 1, 1, 1);
- GlStateManager.enableBlend();
- GL14.glBlendFuncSeparate(
- GL11.GL_SRC_ALPHA,
- GL11.GL_ONE_MINUS_SRC_ALPHA,
- GL11.GL_ONE,
- GL11.GL_ONE_MINUS_SRC_ALPHA
- );
- Utils.renderAlignedString(
- statNamePretty,
- EnumChatFormatting.WHITE.toString() + val,
- guiLeft + 132,
- guiTop + 27 + 11f * i,
- 80
- );
-
- if (mouseX > guiLeft + 132 && mouseX < guiLeft + 212) {
- if (mouseY > guiTop + 27 + 11f * i && mouseY < guiTop + 37 + 11f * i) {
- List<String> split = splitter.splitToList(statNamePretty);
- PlayerStats.Stats baseStats = PlayerStats.getBaseStats();
- tooltipToDisplay = new ArrayList<>();
- tooltipToDisplay.add(statNamePretty);
- int base = Math.round(baseStats.get(statName));
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Base " + split.get(1) + ": " + EnumChatFormatting.GREEN + base + " " +
- split.get(0));
- int passive = Math.round(profile.getPassiveStats(profileId).get(statName) - baseStats.get(statName));
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Passive " + split.get(1) + " Bonus: +" + EnumChatFormatting.YELLOW + passive +
- " " + split.get(0));
- int itemBonus = Math.round(stats.get(statName) - profile.getPassiveStats(profileId).get(statName));
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Item " + split.get(1) + " Bonus: +" + EnumChatFormatting.DARK_PURPLE +
- itemBonus + " " + split.get(0));
- int finalStat = Math.round(stats.get(statName));
- tooltipToDisplay.add(
- EnumChatFormatting.GRAY + "Final " + split.get(1) + ": +" + EnumChatFormatting.RED + finalStat + " " +
- split.get(0));
- }
- }
- }
- } else {
- Utils.drawStringCentered(EnumChatFormatting.RED + "Skill/Inv/Coll", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 172, guiTop + 101 - 10, true, 0
- );
- Utils.drawStringCentered(EnumChatFormatting.RED + "APIs not", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 172, guiTop + 101, true, 0
- );
- Utils.drawStringCentered(EnumChatFormatting.RED + "enabled!", Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 172, guiTop + 101 + 10, true, 0
- );
- }
-
- if (skillInfo != null) {
- int position = 0;
- for (Map.Entry<String, ItemStack> entry : ProfileViewer.getSkillToSkillDisplayMap().entrySet()) {
- if (entry.getValue() == null || entry.getKey() == null) {
- position++;
- continue;
- }
-
- int yPosition = position % 7;
- int xPosition = position / 7;
-
- String skillName = entry.getValue().getDisplayName();
-
- float level = Utils.getElementAsFloat(skillInfo.get("level_" + entry.getKey()), 0);
- int levelFloored = (int) Math.floor(level);
-
- int x = guiLeft + 237 + 86 * xPosition;
- int y = guiTop + 31 + 21 * yPosition;
-
- Utils.renderAlignedString(skillName, EnumChatFormatting.WHITE.toString() + levelFloored, x + 14, y - 4, 60);
-
- if (skillInfo.get("maxed_" + entry.getKey()).getAsBoolean()) {
- renderGoldBar(x, y + 6, 80);
- } else {
- renderBar(x, y + 6, 80, level % 1);
- }
-
- if (mouseX > x && mouseX < x + 80) {
- if (mouseY > y - 4 && mouseY < y + 13) {
- tooltipToDisplay = new ArrayList<>();
- tooltipToDisplay.add(skillName);
- if (skillInfo.get("maxed_" + entry.getKey()).getAsBoolean()) {
- tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.GOLD + "MAXED!");
- } else {
- int maxXp = (int) skillInfo.get("maxxp_" + entry.getKey()).getAsFloat();
- tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + EnumChatFormatting.DARK_PURPLE +
- shortNumberFormat(Math.round((level % 1) * maxXp), 0) + "/" + shortNumberFormat(maxXp, 0));
- }
- String totalXpS = NumberFormat
- .getIntegerInstance()
- .format((int) skillInfo.get("experience_" + entry.getKey()).getAsFloat());
- tooltipToDisplay.add(EnumChatFormatting.GRAY + "Total XP: " +
- EnumChatFormatting.DARK_PURPLE + totalXpS);
- }
- }
-
- GL11.glTranslatef((x), (y - 6f), 0);
- GL11.glScalef(0.7f, 0.7f, 1);
- Utils.drawItemStackLinear(entry.getValue(), 0, 0);
- GL11.glScalef(1 / 0.7f, 1 / 0.7f, 1);
- GL11.glTranslatef(-(x), -(y - 6f), 0);
-
- position++;
- }
- } else {
- Utils.drawStringCentered(
- EnumChatFormatting.RED + "Skills API not enabled!",
- Minecraft.getMinecraft().fontRendererObj,
- guiLeft + 322,
- guiTop + 101,
- true,
- 0
- );
- }
+ return ((BasicPage) pages.get(ProfileViewerPage.BASIC)).entityPlayer;
}
- private void renderGoldBar(float x, float y, float xSize) {
+ public void renderGoldBar(float x, float y, float xSize) {
if (!OpenGlHelper.areShadersSupported()) {
renderBar(x, y, xSize, 1);
return;
@@ -4854,19 +1089,15 @@ public class GuiProfileViewer extends GuiScreen {
GL20.glUseProgram(0);
}
- private void renderBar(float x, float y, float xSize, float completed) {
+ public void renderBar(float x, float y, float xSize, float completed) {
Minecraft.getMinecraft().getTextureManager().bindTexture(icons);
completed = Math.round(completed / 0.05f) * 0.05f;
-
- float notcompleted = 1 - completed;
-
- int displayNum = 0;//tl.x%5;
-
+ float notCompleted = 1 - completed;
GlStateManager.color(1, 1, 1, 1);
- float width = 0;
+ float width;
- if (completed < 0.5f && (displayNum == 1 || displayNum == 0)) {
+ if (completed < 0.5f) {
width = (0.5f - completed) * xSize;
Utils.drawTexturedRect(
x + xSize * completed,
@@ -4880,8 +1111,8 @@ public class GuiProfileViewer extends GuiScreen {
GL11.GL_NEAREST
);
}
- if (completed < 1f && (displayNum == 2 || displayNum == 0)) {
- width = Math.min(xSize * notcompleted, xSize / 2f);
+ if (completed < 1f) {
+ width = Math.min(xSize * notCompleted, xSize / 2f);
Utils.drawTexturedRect(
x + (xSize / 2f) + Math.max(xSize * (completed - 0.5f), 0),
y,
@@ -4895,127 +1126,30 @@ public class GuiProfileViewer extends GuiScreen {
);
}
- if (completed > 0f && (displayNum == 3 || displayNum == 0)) {
+ if (completed > 0f) {
width = Math.min(xSize * completed, xSize / 2f);
- Utils.drawTexturedRect(x, y, width, 5,
- 0 / 256f, width / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST
- );
+ Utils.drawTexturedRect(x, y, width, 5, 0 / 256f, width / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST);
}
- if (completed > 0.5f && (displayNum == 4 || displayNum == 0)) {
+ if (completed > 0.5f) {
width = Math.min(xSize * (completed - 0.5f), xSize / 2f);
- Utils.drawTexturedRect(x + (xSize / 2f), y, width, 5,
- (182 - (xSize / 2f)) / 256f, (182 - (xSize / 2f) + width) / 256f, 79 / 256f, 84 / 256f, GL11.GL_NEAREST
+ Utils.drawTexturedRect(
+ x + (xSize / 2f),
+ y,
+ width,
+ 5,
+ (182 - (xSize / 2f)) / 256f,
+ (182 - (xSize / 2f) + width) / 256f,
+ 79 / 256f,
+ 84 / 256f,
+ GL11.GL_NEAREST
);
}
}
- private static final ResourceLocation shadowTextures = new ResourceLocation("textures/misc/shadow.png");
-
- public static void drawEntityOnScreen(
- int posX,
- int posY,
- int scale,
- float mouseX,
- float mouseY,
- EntityLivingBase ent
- ) {
- GlStateManager.enableColorMaterial();
- GlStateManager.pushMatrix();
- GlStateManager.translate((float) posX, (float) posY, 50.0F);
- GlStateManager.scale((float) (-scale), (float) scale, (float) scale);
- GlStateManager.rotate(180.0F, 0.0F, 0.0F, 1.0F);
- float renderYawOffset = ent.renderYawOffset;
- float f1 = ent.rotationYaw;
- float f2 = ent.rotationPitch;
- float f3 = ent.prevRotationYawHead;
- float f4 = ent.rotationYawHead;
- GlStateManager.rotate(135.0F, 0.0F, 1.0F, 0.0F);
- RenderHelper.enableStandardItemLighting();
- GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
- GlStateManager.rotate(25, 1.0F, 0.0F, 0.0F);
- ent.renderYawOffset = (float) Math.atan(mouseX / 40.0F) * 20.0F;
- ent.rotationYaw = (float) Math.atan(mouseX / 40.0F) * 40.0F;
- ent.rotationPitch = -((float) Math.atan(mouseY / 40.0F)) * 20.0F;
- ent.rotationYawHead = ent.rotationYaw;
- ent.prevRotationYawHead = ent.rotationYaw;
- RenderManager rendermanager = Minecraft.getMinecraft().getRenderManager();
- rendermanager.setPlayerViewY(180.0F);
- rendermanager.setRenderShadow(false);
- rendermanager.renderEntityWithPosYaw(ent, 0.0D, 0.0D, 0.0D, 0.0F, 1.0F);
-
- /*{
- GlStateManager.enableBlend();
- GlStateManager.blendFunc(770, 771);
- rendermanager.renderEngine.bindTexture(shadowTextures);
- GlStateManager.depthMask(false);
- float f = 0.5f;
-
- if (ent instanceof EntityLiving) {
- EntityLiving entityliving = (EntityLiving)ent;
- f *= entityliving.getRenderSizeModifier();
-
- if (entityliving.isChild())
- {
- f *= 0.5F;
- }
- }
-
- /*Tessellator tessellator = Tessellator.getInstance();
- WorldRenderer worldrenderer = tessellator.getWorldRenderer();
- worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
-
- GlStateManager.color(1, 1, 1, 0.5f);
- Utils.drawTexturedRect(-0.5f*tl.x, -0.5f*tl.x, 1*tl.x, 1*tl.x);
-
- /*for (BlockPos blockpos : BlockPos.getAllInBoxMutable(new BlockPos(i, k, i1), new BlockPos(j, l, j1))) {
- Block block = world.getBlockState(blockpos.down()).getBlock();
-
- if (block.getRenderType() != -1 && world.getLightFromNeighbors(blockpos) > 3) {
- this.func_180549_a(block, x, y, z, blockpos, shadowAlpha, f, d2, d3, d4);
- }
- }
-
- GlStateManager.disableBlend();
- GlStateManager.depthMask(true);
- }*/
-
- ent.renderYawOffset = renderYawOffset;
- ent.rotationYaw = f1;
- ent.rotationPitch = f2;
- ent.prevRotationYawHead = f3;
- ent.rotationYawHead = f4;
- GlStateManager.popMatrix();
- RenderHelper.disableStandardItemLighting();
- GlStateManager.disableRescaleNormal();
- GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit);
- GlStateManager.disableTexture2D();
- GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit);
- }
-
public void resetCache() {
- bestWeapons = null;
- bestRods = null;
- armorItems = null;
- inventoryItems = new HashMap<>();
- currentInventoryIndex = 0;
- arrowCount = -1;
- greenCandyCount = -1;
- purpleCandyCount = -1;
- entityPlayer = null;
- playerLocationSkin = null;
- playerLocationCape = null;
- skinType = null;
- petsPage = 0;
- sortedPets = null;
- sortedPetsStack = null;
- selectedPet = -1;
+ pages.values().forEach(GuiProfileViewerPage::resetCache);
}
- Shader blurShaderHorz = null;
- Framebuffer blurOutputHorz = null;
- Shader blurShaderVert = null;
- Framebuffer blurOutputVert = null;
-
/**
* Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
* space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
@@ -5036,14 +1170,6 @@ public class GuiProfileViewer extends GuiScreen {
return projMatrix;
}
- /**
- * Renders whatever is currently in the Minecraft framebuffer to our two framebuffers, applying a horizontal
- * and vertical blur separately in order to significantly save computation time.
- * This is only possible if framebuffers are supported by the system, so this method will exit prematurely
- * if framebuffers are not available. (Apple machines, for example, have poor framebuffer support).
- */
- private double lastBgBlurFactor = -1;
-
private void blurBackground() {
if (!OpenGlHelper.isFramebufferEnabled()) return;
@@ -5071,9 +1197,13 @@ public class GuiProfileViewer extends GuiScreen {
if (blurShaderHorz == null) {
try {
- blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz
- );
+ blurShaderHorz =
+ new Shader(
+ Minecraft.getMinecraft().getResourceManager(),
+ "blur",
+ Minecraft.getMinecraft().getFramebuffer(),
+ blurOutputHorz
+ );
blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
} catch (Exception ignored) {
@@ -5081,8 +1211,11 @@ public class GuiProfileViewer extends GuiScreen {
}
if (blurShaderVert == null) {
try {
- blurShaderVert = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
- blurOutputHorz, blurOutputVert
+ blurShaderVert = new Shader(
+ Minecraft.getMinecraft().getResourceManager(),
+ "blur",
+ blurOutputHorz,
+ blurOutputVert
);
blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
@@ -5124,4 +1257,65 @@ public class GuiProfileViewer extends GuiScreen {
//Utils.setScreen(width, height, f);
blurOutputVert.unbindFramebufferTexture();
}
+
+ public enum ProfileViewerPage {
+ LOADING(),
+ INVALID_NAME(),
+ NO_SKYBLOCK(),
+ BASIC(0, Items.paper, "§9Your Skills"),
+ DUNGEON(1, Item.getItemFromBlock(Blocks.deadbush), "§eDungeoneering"),
+ EXTRA(2, Items.book, "§7Profile Stats"),
+ INVENTORIES(3, Item.getItemFromBlock(Blocks.ender_chest), "§bStorage"),
+ COLLECTIONS(4, Items.painting, "§6Collections"),
+ PETS(5, Items.bone, "§aPets"),
+ MINING(6, Items.iron_pickaxe, "§5Heart of the Mountain"),
+ BINGO(7, Items.filled_map, "§zBingo"),
+ TROPHY_FISH(8, Items.fishing_rod, "§3Trophy Fish"),
+ BESTIARY(9, Items.iron_sword, "§cBestiary");
+
+ public final ItemStack stack;
+ public final int id;
+
+ ProfileViewerPage() {
+ this(-1, null, null);
+ }
+
+ ProfileViewerPage(int id, Item item, String name) {
+ this.id = id;
+ if (item == null) {
+ stack = null;
+ } else {
+ stack = new ItemStack(item);
+ NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs
+ NBTTagCompound display = new NBTTagCompound();
+ display.setString("Name", name);
+ nbt.setTag("display", display);
+ stack.setTagCompound(nbt);
+ }
+ }
+
+ public static ProfileViewerPage getById(int id) {
+ for (ProfileViewerPage page : values()) {
+ if (page.id == id) {
+ return page;
+ }
+ }
+ return null;
+ }
+
+ public Optional<ItemStack> getItem() {
+ return Optional.ofNullable(stack);
+ }
+ }
+
+ public static class PetLevel {
+
+ public float level;
+ public float maxLevel;
+ public float currentLevelRequirement;
+ public float maxXP;
+ public float levelPercentage;
+ public float levelXp;
+ public float totalXp;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java
new file mode 100644
index 00000000..2c7fd9f4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewerPage.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import java.io.IOException;
+
+public abstract class GuiProfileViewerPage {
+
+ private final GuiProfileViewer instance;
+
+ public GuiProfileViewerPage(GuiProfileViewer instance) {
+ this.instance = instance;
+ }
+
+ /**
+ * @return Instance of the current {@link GuiProfileViewer}
+ */
+ public GuiProfileViewer getInstance() {
+ return instance;
+ }
+
+ public abstract void drawPage(int mouseX, int mouseY, float partialTicks);
+
+ /**
+ * @return Whether to return in calling method
+ */
+ public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ return false;
+ }
+
+ public void mouseReleased(int mouseX, int mouseY, int mouseButton) {}
+
+ public void keyTyped(char typedChar, int keyCode) throws IOException {}
+
+ public void resetCache() {}
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java
new file mode 100644
index 00000000..b4f1da30
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/InventoriesPage.java
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.profileviewer.info.QuiverInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagByteArray;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer.pv_elements;
+
+public class InventoriesPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_invs = new ResourceLocation("notenoughupdates:pv_invs.png");
+ private static final ResourceLocation CHEST_GUI_TEXTURE =
+ new ResourceLocation("textures/gui/container/generic_54.png");
+ private static final Pattern FISHING_SPEED_PATTERN = Pattern.compile("^Fishing Speed: \\+(\\d+)");
+ private static final LinkedHashMap<String, ItemStack> invNameToDisplayMap = new LinkedHashMap<String, ItemStack>() {
+ {
+ put(
+ "inv_contents",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.chest), EnumChatFormatting.GRAY + "Inventory")
+ );
+ put(
+ "ender_chest_contents",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.GRAY + "Ender Chest")
+ );
+ // put("backpack_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.dropper), EnumChatFormatting.GRAY+"Backpacks"));
+ put(
+ "backpack_contents",
+ Utils.editItemStackInfo(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("JUMBO_BACKPACK")
+ ),
+ EnumChatFormatting.GRAY + "Backpacks",
+ true
+ )
+ );
+ put(
+ "personal_vault_contents",
+ Utils.editItemStackInfo(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("IRON_CHEST")),
+ EnumChatFormatting.GRAY + "Personal Vault",
+ true
+ )
+ );
+ put("talisman_bag", Utils.createItemStack(Items.golden_apple, EnumChatFormatting.GRAY + "Accessory Bag"));
+ put("wardrobe_contents", Utils.createItemStack(Items.leather_chestplate, EnumChatFormatting.GRAY + "Wardrobe"));
+ put("fishing_bag", Utils.createItemStack(Items.fish, EnumChatFormatting.GRAY + "Fishing Bag"));
+ put("potion_bag", Utils.createItemStack(Items.potionitem, EnumChatFormatting.GRAY + "Potion Bag"));
+ }
+ };
+ private final ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15);
+ private HashMap<String, ItemStack[][][]> inventoryItems = new HashMap<>();
+
+ private ItemStack[] bestWeapons = null;
+ private ItemStack[] bestRods = null;
+ private ItemStack[] armorItems = null;
+ private ItemStack[] equipmentItems = null;
+ private String selectedInventory = "inv_contents";
+ private int currentInventoryIndex = 0;
+ private int arrowCount = -1;
+ private int greenCandyCount = -1;
+ private int purpleCandyCount = -1;
+
+ public InventoriesPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_invs);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+ getInstance().inventoryTextField.setSize(88, 20);
+
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ JsonObject inventoryInfo = profile.getInventoryInfo(profileId);
+ if (inventoryInfo == null) return;
+
+ int invNameIndex = 0;
+ for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) {
+ int xIndex = invNameIndex % 3;
+ int yIndex = invNameIndex / 3;
+
+ int x = 19 + 34 * xIndex;
+ int y = 26 + 34 * yIndex;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ if (entry.getKey().equals(selectedInventory)) {
+ Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 20 / 256f, 0, 20 / 256f, 0, GL11.GL_NEAREST);
+ x++;
+ y++;
+ } else {
+ Utils.drawTexturedRect(guiLeft + x - 2, guiTop + y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
+ }
+
+ Utils.drawItemStackWithText(entry.getValue(), guiLeft + x, guiTop + y, "" + (invNameIndex + 1), true);
+
+ if (mouseX >= guiLeft + x && mouseX <= guiLeft + x + 16) {
+ if (mouseY >= guiTop + y && mouseY <= guiTop + y + 16) {
+ getInstance().tooltipToDisplay = entry.getValue().getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ if (Objects.equals(entry.getKey(), "talisman_bag")) {
+ StringBuilder magicalPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Magical Power: ");
+ int magicalPower = PlayerStats.getMagicalPower(inventoryInfo);
+ getInstance()
+ .tooltipToDisplay.add(
+ magicalPower == -1
+ ? magicalPowerString.append(EnumChatFormatting.RED).append("Error while calculating!").toString()
+ : magicalPowerString
+ .append(EnumChatFormatting.GOLD)
+ .append(GuiProfileViewer.numberFormat.format(magicalPower))
+ .toString()
+ );
+
+ StringBuilder selectedPowerString = new StringBuilder(EnumChatFormatting.DARK_GRAY + "Selected Power: ");
+ String selectedPower = PlayerStats.getSelectedMagicalPower(profile.getProfileInformation(profileId));
+ getInstance()
+ .tooltipToDisplay.add(
+ selectedPower == null
+ ? selectedPowerString.append(EnumChatFormatting.RED).append("None!").toString()
+ : selectedPowerString.append(EnumChatFormatting.GREEN).append(selectedPower).toString()
+ );
+ }
+ }
+ }
+
+ invNameIndex++;
+ }
+
+ getInstance().inventoryTextField.render(guiLeft + 19, guiTop + getInstance().sizeY - 26 - 20);
+
+ if (armorItems == null) {
+ armorItems = new ItemStack[4];
+ JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
+ for (int i = 0; i < armor.size(); i++) {
+ if (armor.get(i) == null || !armor.get(i).isJsonObject()) continue;
+ armorItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(armor.get(i).getAsJsonObject(), false);
+ }
+ }
+
+ for (int i = 0; i < armorItems.length; i++) {
+ ItemStack stack = armorItems[i];
+ if (stack != null) {
+ Utils.drawItemStack(stack, guiLeft + 173, guiTop + 67 - 18 * i, true);
+ if (stack != fillerStack) {
+ if (mouseX >= guiLeft + 173 - 1 && mouseX <= guiLeft + 173 + 16 + 1) {
+ if (mouseY >= guiTop + 67 - 18 * i - 1 && mouseY <= guiTop + 67 - 18 * i + 16 + 1) {
+ getInstance().tooltipToDisplay =
+ stack.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+ }
+ }
+
+ if (equipmentItems == null) {
+ equipmentItems = new ItemStack[4];
+ JsonArray equippment = Utils.getElement(inventoryInfo, "equippment_contents").getAsJsonArray();
+ for (int i = 0; i < equippment.size(); i++) {
+ if (equippment.get(i) == null || !equippment.get(i).isJsonObject()) continue;
+ equipmentItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(equippment.get(i).getAsJsonObject(), false);
+ }
+ }
+
+ for (int i = 0; i < equipmentItems.length; i++) {
+ ItemStack stack = equipmentItems[i];
+ if (stack != null) {
+ Utils.drawItemStack(stack, guiLeft + 192, guiTop + 13 + 18 * i, true);
+ if (stack != fillerStack) {
+ if (mouseX >= guiLeft + 192 - 1 && mouseX <= guiLeft + 192 + 16 + 1) {
+ if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) {
+ getInstance().tooltipToDisplay =
+ stack.getTooltip(
+ Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips
+ );
+ }
+ }
+ }
+ }
+ }
+
+ ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory);
+ if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1;
+ if (currentInventoryIndex < 0) currentInventoryIndex = 0;
+
+ ItemStack[][] inventory = inventories[currentInventoryIndex];
+
+ if (bestWeapons == null) {
+ bestWeapons =
+ findBestItems(
+ inventoryInfo,
+ 6,
+ new String[]{"inv_contents", "ender_chest_contents"},
+ new String[]{"SWORD", "BOW"}
+ );
+ }
+ if (bestRods == null) {
+ bestRods = findBestItems(
+ inventoryInfo,
+ 3,
+ new String[]{"inv_contents", "ender_chest_contents"},
+ new String[]{"FISHING ROD", "FISHING WEAPON"},
+ FISHING_SPEED_PATTERN
+ );
+ }
+
+ for (int i = 0; i < bestWeapons.length; i++) {
+ if (bestWeapons[i] == null) continue;
+ ItemStack stack = bestWeapons[i];
+ Utils.drawItemStack(stack, guiLeft + 143, guiTop + 13 + 18 * i, true);
+ if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) {
+ if (mouseY >= guiTop + 13 + 18 * i - 1 && mouseY <= guiTop + 13 + 18 * i + 16 + 1) {
+ getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+ }
+
+ for (int i = 0; i < bestRods.length; i++) {
+ if (bestRods[i] == null) continue;
+ ItemStack stack = bestRods[i];
+ Utils.drawItemStack(stack, guiLeft + 143, guiTop + 137 + 18 * i, true);
+ if (mouseX >= guiLeft + 143 - 1 && mouseX <= guiLeft + 143 + 16 + 1) {
+ if (mouseY >= guiTop + 137 + 18 * i - 1 && mouseY <= guiTop + 137 + 18 * i + 16 + 1) {
+ getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+ }
+
+ if (arrowCount == -1) {
+ arrowCount = countItemsInInventory("ARROW", inventoryInfo, false, "quiver");
+ }
+ if (greenCandyCount == -1) {
+ greenCandyCount = countItemsInInventory("GREEN_CANDY", inventoryInfo, true, "candy_inventory_contents");
+ }
+ if (purpleCandyCount == -1) {
+ purpleCandyCount = countItemsInInventory("PURPLE_CANDY", inventoryInfo, true, "candy_inventory_contents");
+ }
+
+ Utils.drawItemStackWithText(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("ARROW")),
+ guiLeft + 173,
+ guiTop + 101,
+ "" + (arrowCount > 999 ? StringUtils.shortNumberFormat(arrowCount) : arrowCount),
+ true
+ );
+ Utils.drawItemStackWithText(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("GREEN_CANDY")),
+ guiLeft + 173,
+ guiTop + 119,
+ "" + greenCandyCount,
+ true
+ );
+ Utils.drawItemStackWithText(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .get("PURPLE_CANDY")),
+ guiLeft + 173,
+ guiTop + 137,
+ "" + purpleCandyCount,
+ true
+ );
+ if (mouseX > guiLeft + 173 && mouseX < guiLeft + 173 + 16) {
+ if (mouseY > guiTop + 101 && mouseY < guiTop + 137 + 16) {
+ if (mouseY < guiTop + 101 + 17) {
+ QuiverInfo quiverInfo = PlayerStats.getQuiverInfo(inventoryInfo, profile.getProfileInformation(profileId));
+ if (quiverInfo == null) {
+ getInstance().tooltipToDisplay = Utils.createList(EnumChatFormatting.RED + "Error checking Quiver");
+ } else {
+ getInstance().tooltipToDisplay = quiverInfo.generateProfileViewerTooltip();
+ }
+ } else if (mouseY < guiTop + 119 + 17) {
+ getInstance().tooltipToDisplay =
+ Utils.createList(
+ EnumChatFormatting.GREEN + "Green Candy " + EnumChatFormatting.GRAY + "x" + greenCandyCount);
+ } else {
+ getInstance().tooltipToDisplay =
+ Utils.createList(
+ EnumChatFormatting.DARK_PURPLE + "Purple Candy " + EnumChatFormatting.GRAY + "x" + purpleCandyCount
+ );
+ }
+ }
+ }
+
+ if (inventory == null) {
+ String strToRender = "Inventory API not enabled!";
+ if (selectedInventory.equalsIgnoreCase("personal_vault_contents")) {
+ strToRender = "Personal Vault API not enabled!";
+ } else if (selectedInventory.equalsIgnoreCase("backpack_contents")) {
+ strToRender = "Inventory API not enabled";
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "Or has no backpacks!",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 317,
+ guiTop + 112,
+ true,
+ 0
+ );
+ }
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + strToRender,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 317,
+ guiTop + 101,
+ true,
+ 0
+ );
+ return;
+ }
+
+ int inventoryRows = inventory.length;
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(CHEST_GUI_TEXTURE);
+
+ int invSizeY = inventoryRows * 18 + 17 + 7;
+
+ int x = guiLeft + 320 - 176 / 2;
+ int y = guiTop + 101 - invSizeY / 2;
+ int staticSelectorHeight = guiTop + 177;
+
+ getInstance().drawTexturedModalRect(x, y, 0, 0, 176, inventoryRows * 18 + 17);
+ getInstance().drawTexturedModalRect(x, y + inventoryRows * 18 + 17, 0, 215, 176, 7);
+
+ boolean leftHovered = false;
+ boolean rightHovered = false;
+ if (Mouse.isButtonDown(0)) {
+ if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) {
+ if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) {
+ if (mouseX < guiLeft + 320) {
+ leftHovered = true;
+ } else {
+ rightHovered = true;
+ }
+ }
+ }
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs);
+
+ if (currentInventoryIndex > 0) {
+ Utils.drawTexturedRect(
+ guiLeft + 320 - 12,
+ staticSelectorHeight,
+ 12,
+ 16,
+ 29 / 256f,
+ 53 / 256f,
+ !leftHovered ? 0 : 32 / 256f,
+ !leftHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+ if (currentInventoryIndex < inventories.length - 1) {
+ Utils.drawTexturedRect(
+ guiLeft + 320,
+ staticSelectorHeight,
+ 12,
+ 16,
+ 5 / 256f,
+ 29 / 256f,
+ !rightHovered ? 0 : 32 / 256f,
+ !rightHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+
+ Minecraft
+ .getMinecraft()
+ .fontRendererObj.drawString(
+ Utils.cleanColour(invNameToDisplayMap.get(selectedInventory).getDisplayName()),
+ x + 8,
+ y + 6,
+ 4210752
+ );
+
+ ItemStack stackToRender = null;
+ int overlay = new Color(0, 0, 0, 100).getRGB();
+ for (int yIndex = 0; yIndex < inventory.length; yIndex++) {
+ if (inventory[yIndex] == null) continue;
+
+ for (int xIndex = 0; xIndex < inventory[yIndex].length; xIndex++) {
+ ItemStack stack = inventory[yIndex][xIndex];
+
+ if (stack != null) Utils.drawItemStack(stack, x + 8 + xIndex * 18, y + 18 + yIndex * 18, true);
+
+ if (
+ getInstance().inventoryTextField.getText() != null &&
+ !getInstance().inventoryTextField.getText().isEmpty() &&
+ (
+ stack == null ||
+ !NotEnoughUpdates.INSTANCE.manager.doesStackMatchSearch(
+ stack,
+ getInstance().inventoryTextField.getText()
+ )
+ )
+ ) {
+ GlStateManager.translate(0, 0, 50);
+ GuiScreen.drawRect(
+ x + 8 + xIndex * 18,
+ y + 18 + yIndex * 18,
+ x + 8 + xIndex * 18 + 16,
+ y + 18 + yIndex * 18 + 16,
+ overlay
+ );
+ GlStateManager.translate(0, 0, -50);
+ }
+
+ if (stack == null || stack == fillerStack) continue;
+
+ if (mouseX >= x + 8 + xIndex * 18 && mouseX <= x + 8 + xIndex * 18 + 16) {
+ if (mouseY >= y + 18 + yIndex * 18 && mouseY <= y + 18 + yIndex * 18 + 16) {
+ stackToRender = stack;
+ }
+ }
+ }
+ }
+ if (stackToRender != null) {
+ getInstance().tooltipToDisplay = stackToRender.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+
+ @Override
+ public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ getInstance().inventoryTextField.setSize(88, 20);
+ if (mouseX > guiLeft + 19 && mouseX < guiLeft + 19 + 88) {
+ if (mouseY > guiTop + getInstance().sizeY - 26 - 20 && mouseY < guiTop + getInstance().sizeY - 26) {
+ getInstance().inventoryTextField.mouseClicked(mouseX, mouseY, mouseButton);
+ getInstance().playerNameTextField.otherComponentClick();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY, int mouseButton) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ if (mouseButton == 0) {
+ int i = 0;
+ for (Map.Entry<String, ItemStack> entry : invNameToDisplayMap.entrySet()) {
+ int xIndex = i % 3;
+ int yIndex = i / 3;
+
+ int x = guiLeft + 19 + 34 * xIndex;
+ int y = guiTop + 26 + 34 * yIndex;
+
+ if (mouseX >= x && mouseX <= x + 16) {
+ if (mouseY >= y && mouseY <= y + 16) {
+ if (!selectedInventory.equals(entry.getKey())) Utils.playPressSound();
+ selectedInventory = entry.getKey();
+ return;
+ }
+ }
+
+ i++;
+ }
+
+ JsonObject inventoryInfo = GuiProfileViewer.getProfile().getInventoryInfo(GuiProfileViewer.getProfileId());
+ if (inventoryInfo == null) return;
+
+ ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, selectedInventory);
+ if (currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length - 1;
+ if (currentInventoryIndex < 0) currentInventoryIndex = 0;
+
+ ItemStack[][] inventory = inventories[currentInventoryIndex];
+ if (inventory == null) return;
+
+ int inventoryRows = inventory.length;
+
+ int staticSelectorHeight = guiTop + 177;
+
+ if (mouseY > staticSelectorHeight && mouseY < staticSelectorHeight + 16) {
+ if (mouseX > guiLeft + 320 - 12 && mouseX < guiLeft + 320 + 12) {
+ if (mouseX < guiLeft + 320) {
+ currentInventoryIndex--;
+ } else {
+ currentInventoryIndex++;
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void keyTyped(char typedChar, int keyCode) throws IOException {
+ switch (keyCode) {
+ case Keyboard.KEY_1:
+ case Keyboard.KEY_NUMPAD1:
+ selectedInventory = "inv_contents";
+ break;
+ case Keyboard.KEY_2:
+ case Keyboard.KEY_NUMPAD2:
+ selectedInventory = "ender_chest_contents";
+ break;
+ case Keyboard.KEY_3:
+ case Keyboard.KEY_NUMPAD3:
+ selectedInventory = "backpack_contents";
+ break;
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_NUMPAD4:
+ selectedInventory = "personal_vault_contents";
+ break;
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_NUMPAD5:
+ selectedInventory = "talisman_bag";
+ break;
+ case Keyboard.KEY_6:
+ case Keyboard.KEY_NUMPAD6:
+ selectedInventory = "wardrobe_contents";
+ break;
+ case Keyboard.KEY_7:
+ case Keyboard.KEY_NUMPAD7:
+ selectedInventory = "fishing_bag";
+ break;
+ case Keyboard.KEY_8:
+ case Keyboard.KEY_NUMPAD8:
+ selectedInventory = "potion_bag";
+ break;
+ default:
+ getInstance().inventoryTextField.keyTyped(typedChar, keyCode);
+ return;
+ }
+ Utils.playPressSound();
+ getInstance().inventoryTextField.keyTyped(typedChar, keyCode);
+ }
+
+ @Override
+ public void resetCache() {
+ inventoryItems = new HashMap<>();
+ bestWeapons = null;
+ bestRods = null;
+ armorItems = null;
+ equipmentItems = null;
+ currentInventoryIndex = 0;
+ arrowCount = -1;
+ greenCandyCount = -1;
+ purpleCandyCount = -1;
+ }
+
+ private int countItemsInInventory(
+ String internalname,
+ JsonObject inventoryInfo,
+ boolean specific,
+ String... invsToSearch
+ ) {
+ int count = 0;
+ for (String inv : invsToSearch) {
+ JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray();
+ for (int i = 0; i < invItems.size(); i++) {
+ if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue;
+ JsonObject item = invItems.get(i).getAsJsonObject();
+ if (
+ (specific && item.get("internalname").getAsString().equals(internalname)) ||
+ (!specific && item.get("internalname").getAsString().contains(internalname))
+ ) {
+ if (item.has("count")) {
+ count += item.get("count").getAsInt();
+ } else {
+ count += 1;
+ }
+ }
+ }
+ }
+ return count;
+ }
+
+ private ItemStack[] findBestItems(
+ JsonObject inventoryInfo,
+ int numItems,
+ String[] invsToSearch,
+ String[] typeMatches,
+ Pattern... importantPatterns
+ ) {
+ ItemStack[] bestItems = new ItemStack[numItems];
+ TreeMap<Long, Set<ItemStack>> map = new TreeMap<>();
+ for (String inv : invsToSearch) {
+ JsonArray invItems = inventoryInfo.get(inv).getAsJsonArray();
+ for (int i = 0; i < invItems.size(); i++) {
+ if (invItems.get(i) == null || !invItems.get(i).isJsonObject()) continue;
+ JsonObject item = invItems.get(i).getAsJsonObject();
+ JsonArray lore = item.get("lore").getAsJsonArray();
+ if (Utils.checkItemType(lore, true, typeMatches) >= 0) {
+ long importance = 0;
+ int id = 0;
+ if (importantPatterns.length == 0) {
+ String internalName = item.get("internalname").getAsString();
+ importance += NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalName);
+ importance += ++id;
+ } else {
+ for (int j = 0; j < lore.size(); j++) {
+ String line = lore.get(j).getAsString();
+ for (Pattern pattern : importantPatterns) {
+ Matcher matcher = pattern.matcher(Utils.cleanColour(line));
+ if (matcher.find()) {
+ importance += Integer.parseInt(matcher.group(1));
+ }
+ }
+ }
+ }
+ map.computeIfAbsent(importance, k -> new HashSet<>()).add(NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ item,
+ false
+ ));
+ }
+ }
+ }
+ int i = 0;
+ outer:
+ for (long key : map.descendingKeySet()) {
+ Set<ItemStack> items = map.get(key);
+ for (ItemStack item : items) {
+ bestItems[i] = item;
+ if (++i >= bestItems.length) break outer;
+ }
+ }
+
+ return bestItems;
+ }
+
+ private ItemStack[][][] getItemsForInventory(JsonObject inventoryInfo, String invName) {
+ if (inventoryItems.containsKey(invName)) return inventoryItems.get(invName);
+
+ JsonArray jsonInv = Utils.getElement(inventoryInfo, invName).getAsJsonArray();
+
+ if (jsonInv.size() == 0) return new ItemStack[1][][];
+
+ int jsonInvSize;
+ if (useActualMax(invName)) {
+ jsonInvSize = (int) Math.ceil(jsonInv.size() / 9f) * 9;
+ } else {
+ jsonInvSize = 9 * 4;
+ float divideBy = 9f;
+ if (invName.equals("wardrobe_contents")) {
+ divideBy = 36f;
+ }
+ for (int i = 9 * 4; i < jsonInv.size(); i++) {
+ JsonElement item = jsonInv.get(i);
+ if (item != null && item.isJsonObject()) {
+ jsonInvSize = (int) (Math.ceil((i + 1) / divideBy) * (int) divideBy);
+ }
+ }
+ }
+
+ int rowSize = 9;
+ int rows = jsonInvSize / rowSize;
+ int maxRowsPerPage = getRowsForInventory(invName);
+ int maxInvSize = rowSize * maxRowsPerPage;
+
+ int numInventories = (jsonInvSize - 1) / maxInvSize + 1;
+ JsonArray backPackSizes = (JsonArray) inventoryInfo.get("backpack_sizes");
+ if (invName.equals("backpack_contents")) {
+ numInventories = backPackSizes.size();
+ }
+
+ ItemStack[][][] inventories = new ItemStack[numInventories][][];
+
+ //int availableSlots = getAvailableSlotsForInventory(inventoryInfo, collectionInfo, invName);
+ int startNumberJ = 0;
+
+ for (int i = 0; i < numInventories; i++) {
+ int thisRows = Math.min(maxRowsPerPage, rows - maxRowsPerPage * i);
+ int invSize;
+
+ if (invName.equals("backpack_contents")) {
+ thisRows = backPackSizes.get(i).getAsInt() / 9;
+ invSize = startNumberJ + (thisRows * 9);
+ maxInvSize = thisRows * 9;
+ } else {
+ startNumberJ = maxInvSize * i;
+ invSize = Math.min(jsonInvSize, maxInvSize + maxInvSize * i);
+ }
+ if (thisRows <= 0) break;
+
+ ItemStack[][] items = new ItemStack[thisRows][rowSize];
+
+ for (int j = startNumberJ; j < invSize; j++) {
+ int xIndex = (j % maxInvSize) % rowSize;
+ int yIndex = (j % maxInvSize) / rowSize;
+ if (invName.equals("inv_contents")) {
+ yIndex--;
+ if (yIndex < 0) yIndex = rows - 1;
+ }
+ if (yIndex >= thisRows) {
+ break;
+ }
+
+ if (j >= jsonInv.size()) {
+ items[yIndex][xIndex] = fillerStack;
+ continue;
+ }
+ if (jsonInv.get(j) == null || !jsonInv.get(j).isJsonObject()) {
+ continue;
+ }
+
+ JsonObject item = jsonInv.get(j).getAsJsonObject();
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item, false);
+ if (item.has("item_contents")) {
+ JsonArray bytesArr = item.get("item_contents").getAsJsonArray();
+ byte[] bytes = new byte[bytesArr.size()];
+ for (int bytesArrI = 0; bytesArrI < bytesArr.size(); bytesArrI++) {
+ bytes[bytesArrI] = bytesArr.get(bytesArrI).getAsByte();
+ }
+ //byte[] bytes2 = null;
+ NBTTagCompound tag = stack.getTagCompound();
+ if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ for (String key : ea.getKeySet()) {
+ if (key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
+ ea.setTag(key, new NBTTagByteArray(bytes));
+ break;
+ }
+ }
+ tag.setTag("ExtraAttributes", ea);
+ stack.setTagCompound(tag);
+ }
+ }
+
+ items[yIndex][xIndex] = stack;
+ }
+ inventories[i] = items;
+ if (invName.equals("backpack_contents")) {
+ startNumberJ = startNumberJ + backPackSizes.get(i).getAsInt();
+ }
+ }
+
+ inventoryItems.put(invName, inventories);
+ return inventories;
+ }
+
+ private boolean useActualMax(String invName) {
+ switch (invName) {
+ case "talisman_bag":
+ case "fishing_bag":
+ case "potion_bag":
+ case "personal_vault_contents":
+ return true;
+ }
+ return false;
+ }
+
+ private int getRowsForInventory(String invName) {
+ switch (invName) {
+ case "wardrobe_contents":
+ return 4;
+ case "backpack_contents":
+ case "ender_chest_contents":
+ return 5;
+ default:
+ return 6;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java
new file mode 100644
index 00000000..d3b43e20
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/MiningPage.java
@@ -0,0 +1,1534 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+public class MiningPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_mining = new ResourceLocation("notenoughupdates:pv_mining.png");
+ private static final ItemStack iron_pick = new ItemStack(Items.iron_pickaxe);
+ private final HashMap<String, ProfileViewer.Level> levelObjhotms = new HashMap<>();
+
+ public MiningPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_mining);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ JsonObject profileInfo = profile.getProfileInformation(profileId);
+ if (profileInfo == null) return;
+
+ float xStart = 22;
+ float yStartTop = 27;
+
+ int x = guiLeft + 23;
+ int y = guiTop + 25;
+ int sectionWidth = 110;
+ JsonObject leveling = Constants.LEVELING;
+ ProfileViewer.Level levelObjhotm = levelObjhotms.get(profileId);
+ if (levelObjhotm == null) {
+ float hotmXp = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0);
+ levelObjhotm =
+ ProfileViewer.getLevel(
+ Utils.getElementOrDefault(leveling, "HOTM", new JsonArray()).getAsJsonArray(),
+ hotmXp,
+ 7,
+ false
+ );
+ levelObjhotms.put(profileId, levelObjhotm);
+ }
+
+ String skillName = EnumChatFormatting.RED + "HOTM";
+ //The stats that show
+ float mithrilPowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_mithril"), 0);
+ float gemstonePowder = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.powder_gemstone"), 0);
+ float mithrilPowderTotal = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "mining_core.powder_spent_mithril"
+ ), 0);
+ float gemstonePowderTotal = (Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "mining_core.powder_spent_gemstone"
+ ), 0));
+ String jadeCrystal =
+ (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.state"), "Not Found"));
+ float crystalPlacedAmount =
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.crystals.jade_crystal.total_placed"), 0));
+ String jadeCrystalString = "§c✖";
+ String amethystCrystal =
+ (Utils.getElementAsString(
+ Utils.getElement(profileInfo, "mining_core.crystals.amethyst_crystal.state"),
+ "Not Found"
+ ));
+ String amethystCrystalString = "§c✖";
+ String amberCrystal =
+ (Utils.getElementAsString(
+ Utils.getElement(profileInfo, "mining_core.crystals.amber_crystal.state"),
+ "Not Found"
+ ));
+ String amberCrystalString = "§c✖";
+ String sapphireCrystal =
+ (Utils.getElementAsString(
+ Utils.getElement(profileInfo, "mining_core.crystals.sapphire_crystal.state"),
+ "Not Found"
+ ));
+ String sapphireCrystalString = "§c✖";
+ String topazCrystal =
+ (Utils.getElementAsString(
+ Utils.getElement(profileInfo, "mining_core.crystals.topaz_crystal.state"),
+ "Not Found"
+ ));
+ String topazCrystalString = "§c✖";
+ String jasperCrystal =
+ (Utils.getElementAsString(
+ Utils.getElement(profileInfo, "mining_core.crystals.jasper_crystal.state"),
+ "Not Found"
+ ));
+ String jasperCrystalString = "§c✖";
+ String rubyCrystal =
+ (Utils.getElementAsString(Utils.getElement(profileInfo, "mining_core.crystals.ruby_crystal.state"), "Not Found"));
+ String rubyCrystalString = "§c✖";
+ int miningFortune = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"), 0)));
+ int miningFortuneStat = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune"),
+ 0
+ )) * 5);
+ int miningSpeed = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)));
+ int miningSpeedStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed"), 0)) *
+ 20);
+ int dailyPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)));
+ int dailyPowderStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_powder"), 0)) *
+ 36 + 364);
+ int effMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)));
+ float effMinerStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * 0.4 + 10.4
+ );
+ float effMinerStat2 = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.efficient_miner"), 0)) * .06 + 0.31
+ );
+ int tittyInsane = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"),
+ 0
+ )));
+ float tittyInsaneStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.titanium_insanium"), 0)) * .1 + 2
+ );
+ int luckofcave = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0)));
+ int luckofcaveStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.random_event"), 0)));
+ int madMining = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_madness"), 0)));
+ int skyMall = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.daily_effect"), 0)));
+ int goblinKiller = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.goblin_killer"), 0)));
+ int seasonMine = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)));
+ float seasonMineStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mining_experience"), 0)) * 0.1 + 5
+ );
+ int quickForge = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)));
+ float quickForgeStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.forge_time"), 0)) * .5 + 10
+ );
+ int frontLoad = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.front_loaded"), 0)));
+ int orbit = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)));
+ float orbitStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.experience_orbs"), 0)) * .01 + 0.2
+ );
+ int crystallized = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"),
+ 0
+ )));
+ int crystallizedStat = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.fallen_star_bonus"),
+ 0
+ )) * 6 + 14);
+ int professional = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.professional"), 0)));
+ int professionalStat = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.professional"),
+ 0
+ )) * 5 + 50);
+ int greatExplorer = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"), 0)));
+ int greatExplorerStat = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.great_explorer"),
+ 0
+ )) * 4 + 16);
+ int fortunate = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)));
+ int fortunateStat = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.fortunate"), 0)) * 4 +
+ 20);
+ int lonesomeMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)));
+ float lonesomeMinerStat = (float) (
+ (Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.lonesome_miner"), 0)) * .5 + 5
+ );
+ int miningFortune2 = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.mining_fortune_2"),
+ 0
+ )));
+ int miningFortune2Stat = ((Utils.getElementAsInt(Utils.getElement(
+ profileInfo,
+ "mining_core.nodes.mining_fortune_2"
+ ), 0)) * 5);
+ int miningSpeed2 = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"), 0)));
+ int miningSpeed2Stat = ((Utils.getElementAsInt(
+ Utils.getElement(profileInfo, "mining_core.nodes.mining_speed_2"),
+ 0
+ )) * 40);
+ int miningSpeedBoost = ((Utils.getElementAsInt(Utils.getElement(
+ profileInfo,
+ "mining_core.nodes.mining_speed_boost"
+ ), 0)));
+ int veinSeeker = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.vein_seeker"), 0)));
+ int powderBuff = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.powder_buff"), 0)));
+ int potm = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.special_0"), 0)));
+ int fortnite = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.precision_mining"), 0)));
+ int starPowder = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.star_powder"), 0)));
+ int pickoblus = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.pickaxe_toss"), 0)));
+ int maniacMiner = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.maniac_miner"), 0)));
+
+ if (effMinerStat2 < 1) {
+ effMinerStat2 = 1;
+ }
+ int mole = ((Utils.getElementAsInt(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)));
+ float moleStat = (float) ((Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.nodes.mole"), 0)) *
+ 0.051);
+ double moleperkstat = (double) mole / 20 - 0.55 + 50;
+ double moleperkstat2 = (double) Math.round(moleperkstat * 100) / 100;
+
+ float output = Math.round((float) (moleperkstat2 % 1) * 100);
+ if (output == 0) {
+ output = 100;
+ }
+
+ //The logic for some of the stats
+ if (Objects.equals(jadeCrystal, "NOT_FOUND")) {
+ jadeCrystalString = "§c✖";
+ } else if (Objects.equals(jadeCrystal, "FOUND")) {
+ jadeCrystalString = "§a✔";
+ }
+ if (Objects.equals(amethystCrystal, "NOT_FOUND")) {
+ amethystCrystalString = "§c✖";
+ } else if (Objects.equals(amethystCrystal, "FOUND")) {
+ amethystCrystalString = "§a✔";
+ }
+ if (Objects.equals(amberCrystal, "NOT_FOUND")) {
+ amberCrystalString = "§c✖";
+ } else if (Objects.equals(amberCrystal, "FOUND")) {
+ amberCrystalString = "§a✔";
+ }
+ if (Objects.equals(sapphireCrystal, "NOT_FOUND")) {
+ sapphireCrystalString = "§c✖";
+ } else if (Objects.equals(sapphireCrystal, "FOUND")) {
+ sapphireCrystalString = "§a✔";
+ }
+ if (Objects.equals(topazCrystal, "NOT_FOUND")) {
+ topazCrystalString = "§c✖";
+ } else if (Objects.equals(topazCrystal, "FOUND")) {
+ topazCrystalString = "§a✔";
+ }
+ if (Objects.equals(jasperCrystal, "NOT_FOUND")) {
+ jasperCrystalString = "§c✖";
+ } else if (Objects.equals(jasperCrystal, "FOUND")) {
+ jasperCrystalString = "§a✔";
+ }
+ if (Objects.equals(rubyCrystal, "NOT_FOUND")) {
+ rubyCrystalString = "§c✖";
+ } else if (Objects.equals(rubyCrystal, "FOUND")) {
+ rubyCrystalString = "§a✔";
+ }
+
+ //The rendering of the stats
+ //hotm level
+ getInstance().renderXpBar(skillName, iron_pick, x, y, sectionWidth, levelObjhotm, mouseX, mouseY);
+ //Powder
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_GREEN + "Mithril Powder",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(mithrilPowder),
+ guiLeft + xStart,
+ guiTop + yStartTop + 24,
+ 115
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.LIGHT_PURPLE + "Gemstone Powder",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(gemstonePowder),
+ guiLeft + xStart,
+ guiTop + yStartTop + 44,
+ 115
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_GREEN + "Total Mithril Powder",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(mithrilPowderTotal + mithrilPowder),
+ guiLeft + xStart,
+ guiTop + yStartTop + 34,
+ 115
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.LIGHT_PURPLE + "Total Gemstone Powder",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(gemstonePowderTotal + gemstonePowder),
+ guiLeft + xStart,
+ guiTop + yStartTop + 54,
+ 115
+ );
+ //Crystals
+ Utils.renderAlignedString(
+ EnumChatFormatting.GREEN + "Jade Crystal:",
+ EnumChatFormatting.WHITE + jadeCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 74,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.GOLD + "Amber Crystal:",
+ EnumChatFormatting.WHITE + amberCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 84,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.DARK_PURPLE + "Amethyst Crystal:",
+ EnumChatFormatting.WHITE + amethystCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 94,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.AQUA + "Sapphire Crystal:",
+ EnumChatFormatting.WHITE + sapphireCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 104,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Topaz Crystal:",
+ EnumChatFormatting.WHITE + topazCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 114,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.LIGHT_PURPLE + "Jasper Crystal:",
+ EnumChatFormatting.WHITE + jasperCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 124,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "Ruby Crystal:",
+ EnumChatFormatting.WHITE + rubyCrystalString,
+ guiLeft + xStart,
+ guiTop + yStartTop + 134,
+ 110
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.BLUE + "Total Placed Crystals:",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(crystalPlacedAmount),
+ guiLeft + xStart,
+ guiTop + yStartTop + 149,
+ 110
+ );
+
+ //hotm render
+ //Pain
+
+ renderHotmPerk(
+ miningSpeed,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 138),
+ mouseX,
+ mouseY,
+ () ->
+ miningSpeed != 50 && miningSpeed != 0
+ ? Lists.newArrayList(
+ "Mining Speed",
+ EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Grants " +
+ EnumChatFormatting.GREEN +
+ "+" +
+ miningSpeedStat +
+ EnumChatFormatting.GOLD +
+ " ⸕ Mining",
+ EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + ".",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format(Math.pow(miningSpeed + 2, 3)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Mining Speed",
+ EnumChatFormatting.GRAY + "Level " + miningSpeed + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Grants " +
+ EnumChatFormatting.GREEN +
+ "+" +
+ miningSpeedStat +
+ EnumChatFormatting.GOLD +
+ " ⸕ Mining",
+ EnumChatFormatting.GOLD + "Speed" + EnumChatFormatting.GRAY + "."
+ ),
+ 50
+ );
+
+ renderHotmPerk(
+ miningFortune,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 114),
+ mouseX,
+ mouseY,
+ () ->
+ miningFortune != 0 && miningFortune != 50
+ ? Lists.newArrayList(
+ "Mining Fortune",
+ EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Grants " +
+ EnumChatFormatting.GREEN +
+ "+" +
+ miningFortuneStat +
+ EnumChatFormatting.GOLD +
+ " ☘ Mining",
+ EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + ".",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format(Math.pow(miningFortune + 2, 3)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Mining Fortune",
+ EnumChatFormatting.GRAY + "Level " + miningFortune + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Grants " +
+ EnumChatFormatting.GREEN +
+ "+" +
+ miningFortuneStat +
+ EnumChatFormatting.GOLD +
+ " ☘ Mining",
+ EnumChatFormatting.GOLD + "Fortune" + EnumChatFormatting.GRAY + "."
+ ),
+ 50
+ );
+
+ renderHotmPerk(
+ tittyInsane,
+ (int) (guiLeft + xStart + 231),
+ (int) (guiTop + yStartTop + 114),
+ mouseX,
+ mouseY,
+ () ->
+ tittyInsane != 0 && tittyInsane != 50
+ ? Lists.newArrayList(
+ "Titanium Insanium",
+ EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY + "When mining Mithril Ore, you",
+ EnumChatFormatting.GRAY +
+ "have a " +
+ EnumChatFormatting.GREEN +
+ tittyInsaneStat +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "chance to",
+ EnumChatFormatting.GRAY + "convert the block into Titanium",
+ EnumChatFormatting.GRAY + "Ore.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(tittyInsane + 2, 3)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Titanium Insanium",
+ EnumChatFormatting.GRAY + "Level " + tittyInsane + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY + "When mining Mithril Ore, you",
+ EnumChatFormatting.GRAY +
+ "have a " +
+ EnumChatFormatting.GREEN +
+ tittyInsaneStat +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "chance to",
+ EnumChatFormatting.GRAY + "convert the block into Titanium",
+ EnumChatFormatting.GRAY + "Ore."
+ ),
+ 50
+ );
+
+ renderPickaxeAbility(
+ miningSpeedBoost,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop + 114),
+ mouseX,
+ mouseY,
+ () ->
+ potm == 0
+ ? Lists.newArrayList( // Peak of the mountain == 0
+ "Mining Speed Boost",
+ "",
+ EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost",
+ EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "200% " + EnumChatFormatting.GOLD +
+ "⸕ Mining",
+ EnumChatFormatting.GOLD +
+ "Speed " +
+ EnumChatFormatting.GRAY +
+ "for " +
+ EnumChatFormatting.GREEN +
+ "15s" +
+ EnumChatFormatting.GRAY,
+ EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s"
+ )
+ : Lists.newArrayList( // Peak of the mountain > 0
+ "Mining Speed Boost",
+ "",
+ EnumChatFormatting.GRAY + "Pickaxe Ability: Mining Speed Boost",
+ EnumChatFormatting.GRAY + "Grants " + EnumChatFormatting.GREEN + "300% " + EnumChatFormatting.GOLD +
+ "⸕ Mining",
+ EnumChatFormatting.GOLD +
+ "Speed " +
+ EnumChatFormatting.GRAY +
+ "for " +
+ EnumChatFormatting.GREEN +
+ "20s" +
+ EnumChatFormatting.GRAY,
+ EnumChatFormatting.DARK_GRAY + "Cooldown: " + EnumChatFormatting.GREEN + "120s"
+ )
+ );
+
+ renderPickaxeAbility(
+ veinSeeker,
+ (int) (guiLeft + xStart + 183),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Vein Seeker",
+ "",
+ "§6Pickaxe Ability: Vein Seeker",
+ "§7Points in the direction of the",
+ "§7nearest vein and grants §a+§a3§7",
+ "§7§6Mining Spread §7for §a14s§7§7.",
+ "§8Cooldown: §a60s"
+ )
+ );
+
+ renderHotmPerk(
+ luckofcave,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop + 90),
+ mouseX,
+ mouseY,
+ () ->
+ luckofcave != 0 && luckofcave != 45
+ ? Lists.newArrayList(
+ "Luck of the Cave",
+ "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45",
+ "",
+ "§7Increases the chance for you to",
+ "§7trigger rare occurrences im",
+ "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(luckofcave + 2, 3.07)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Luck of the Cave",
+ "§7Level " + luckofcave + EnumChatFormatting.DARK_GRAY + "/45",
+ "",
+ "§7Increases the chance for you to",
+ "§7trigger rare occurrences im",
+ "§2Dwarven Mines " + EnumChatFormatting.GRAY + "by " + EnumChatFormatting.GREEN + luckofcaveStat + "%§7."
+ ),
+ 45
+ );
+
+ renderHotmPerk(
+ dailyPowder,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 90),
+ mouseX,
+ mouseY,
+ () ->
+ dailyPowder != 0 && dailyPowder != 100
+ ? Lists.newArrayList(
+ "Daily Powder",
+ EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100",
+ "",
+ EnumChatFormatting.GRAY +
+ "Gains " +
+ EnumChatFormatting.GREEN +
+ dailyPowderStat +
+ " Powder" +
+ EnumChatFormatting.GRAY +
+ " from the",
+ EnumChatFormatting.GRAY + "first ore you mine every day.",
+ EnumChatFormatting.GRAY + "Works for all Powder types.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "" + (200 + ((dailyPowder) * 18)) + " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Daily Powder",
+ EnumChatFormatting.GRAY + "Level " + dailyPowder + EnumChatFormatting.DARK_GRAY + "/100",
+ "",
+ EnumChatFormatting.GRAY +
+ "Gains " +
+ EnumChatFormatting.GREEN +
+ dailyPowderStat +
+ " Powder" +
+ EnumChatFormatting.GRAY +
+ " from the",
+ EnumChatFormatting.GRAY + "first ore you mine every day.",
+ EnumChatFormatting.GRAY + "Works for all Powder types."
+ ),
+ 100
+ );
+
+ float finalEffMinerStat2 = effMinerStat2;
+ renderHotmPerk(
+ effMiner,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ effMiner != 0 && effMiner != 100
+ ? Lists.newArrayList(
+ "Efficient Miner",
+ EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100",
+ "",
+ EnumChatFormatting.GRAY + "When mining ores, you have a",
+ EnumChatFormatting.GREEN +
+ "" +
+ effMinerStat +
+ "%" +
+ EnumChatFormatting.GRAY +
+ " chance to mine " +
+ EnumChatFormatting.GREEN +
+ Math.round(finalEffMinerStat2),
+ EnumChatFormatting.GRAY + "adjacent ores.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(effMiner + 2, 2.6)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Efficient Miner",
+ EnumChatFormatting.GRAY + "Level " + effMiner + EnumChatFormatting.DARK_GRAY + "/100",
+ "",
+ EnumChatFormatting.GRAY + "When mining ores, you have a",
+ EnumChatFormatting.GREEN +
+ "" +
+ effMinerStat +
+ "%" +
+ EnumChatFormatting.GRAY +
+ " chance to mine " +
+ EnumChatFormatting.GREEN +
+ Math.round(finalEffMinerStat2),
+ EnumChatFormatting.GRAY + "adjacent ores."
+ ),
+ 100
+ );
+
+ renderHotmPerk(
+ potm,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 42),
+ mouseX,
+ mouseY,
+ () -> {
+ switch (potm) {
+ case 0:
+ return Lists.newArrayList(
+ EnumChatFormatting.RED + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "50,000 Mithril Powder"
+ );
+ case 1:
+ return Lists.newArrayList(
+ EnumChatFormatting.YELLOW + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "50,000 Mithril Powder"
+ );
+ case 2:
+ return Lists.newArrayList(
+ EnumChatFormatting.YELLOW + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "75,000 Mithril Powder"
+ );
+ case 3:
+ return Lists.newArrayList(
+ EnumChatFormatting.YELLOW + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "§7§8+§a1 Commission Slot",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "100,000 Mithril Powder"
+ );
+ case 4:
+ return Lists.newArrayList(
+ EnumChatFormatting.YELLOW + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "§7§8+§a1 Commission Slot",
+ "§7§8+§21 Mithril Powder §7when",
+ "§7mining §fMithril",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "125,000 Mithril Powder"
+ );
+ case 5:
+ return Lists.newArrayList(
+ EnumChatFormatting.GREEN + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "§7§8+§a1 Commission Slot",
+ "§7§8+§21 Mithril Powder §7when",
+ "§7mining §fMithril",
+ "§7§8+§51 Token of the Mountain",
+ "",
+ "§7Cost",
+ "§d500,000 Gemstone Powder"
+ );
+ case 6:
+ return Lists.newArrayList(
+ EnumChatFormatting.GREEN + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "§7§8+§a1 Commission Slot",
+ "§7§8+§21 Mithril Powder §7when",
+ "§7mining §fMithril",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§d2 Gemstone Powder §7when",
+ "§7mining §dGemstones",
+ "",
+ "§7Cost",
+ "§d750,000 Gemstone Powder"
+ );
+ case 7:
+ return Lists.newArrayList(
+ EnumChatFormatting.GREEN + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/7",
+ "",
+ "§7§8+§c1 Pickaxe Ability Level",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§a1 Forge Slot",
+ "§7§8+§a1 Commission Slot",
+ "§7§8+§21 Mithril Powder §7when",
+ "§7mining §fMithril",
+ "§7§8+§51 Token of the Mountain",
+ "§7§8+§d2 Gemstone Powder §7when",
+ "§7mining §dGemstones",
+ "§7§8+§51 Token of the Mountain"
+ );
+ }
+ return Lists.newArrayList(
+ EnumChatFormatting.GREEN + "Peak of the Mountain",
+ EnumChatFormatting.GRAY + "Level " + potm + EnumChatFormatting.DARK_GRAY + "/???",
+ EnumChatFormatting.RED + "It looks like your NEU doesn't understand your peak of the mountain perks.",
+ EnumChatFormatting.RED + "Please patiently await an update to your NEU installation."
+ );
+ },
+ potm > 0 ? new ItemStack(Blocks.redstone_block) : new ItemStack(Blocks.bedrock),
+ true // A redstone block or bedrock is being rendered, so standard GUI item lighting needs to be enabled.
+ );
+
+ float finalOutput = output;
+ renderHotmPerk(
+ mole,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ mole != 0 && mole != 190
+ ? Lists.newArrayList(
+ "Mole",
+ EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190",
+ "",
+ EnumChatFormatting.GRAY + "When mining hard stone, you have",
+ EnumChatFormatting.GRAY +
+ "a " +
+ EnumChatFormatting.GREEN +
+ finalOutput +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "chance to mine " +
+ EnumChatFormatting.GREEN,
+ EnumChatFormatting.GREEN +
+ "" +
+ Math.round(moleStat) +
+ EnumChatFormatting.GRAY +
+ " adjacent hard stone block" +
+ (moleStat == 1.0 ? "." : "s."),
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(mole + 2, 2.2)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Mole",
+ EnumChatFormatting.GRAY + "Level " + mole + EnumChatFormatting.DARK_GRAY + "/190",
+ "",
+ EnumChatFormatting.GRAY + "When mining hard stone, you have",
+ EnumChatFormatting.GRAY +
+ "a " +
+ EnumChatFormatting.GREEN +
+ finalOutput +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "chance to mine " +
+ EnumChatFormatting.GREEN,
+ EnumChatFormatting.GREEN +
+ "" +
+ Math.round(moleStat) +
+ EnumChatFormatting.GRAY +
+ " adjacent hard stone block" +
+ (moleStat == 1.0 ? "." : "s.")
+ ),
+ 190
+ );
+
+ renderHotmPerk(
+ powderBuff,
+ (int) (guiLeft + xStart + 255),
+ (int) (guiTop + yStartTop - 6),
+ mouseX,
+ mouseY,
+ () ->
+ powderBuff != 0 && powderBuff != 50
+ ? Lists.newArrayList(
+ "Powder Buff",
+ EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Gain " +
+ EnumChatFormatting.GREEN +
+ powderBuff +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "more Mithril",
+ EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(powderBuff + 2, 3.2)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Powder Buff",
+ EnumChatFormatting.GRAY + "Level " + powderBuff + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ EnumChatFormatting.GRAY +
+ "Gain " +
+ EnumChatFormatting.GREEN +
+ powderBuff +
+ "% " +
+ EnumChatFormatting.GRAY +
+ "more Mithril",
+ EnumChatFormatting.GRAY + "Powder and Gemstone Powder§7."
+ ),
+ 50
+ );
+
+ renderHotmPerk(
+ skyMall,
+ (int) (guiLeft + xStart + 183),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Sky Mall",
+ "§7Every SkyBlock day, you receive",
+ "§7a random buff in the §2Dwarven",
+ "§2Mines§7.",
+ "",
+ "§7Possible Buffs",
+ "§8 ■ §7Gain §a+100 §6⸕ Mining Speed.",
+ "§8 ■ §7Gain §a+50 §6☘ Mining Fortune.",
+ "§8 ■ §7Gain §a+15% §7chance to gain",
+ " §7extra Powder while mining.",
+ "§8 ■ §7Reduce Pickaxe Ability cooldown",
+ " §7by §a20%",
+ "§8 ■ §7§a10x §7chance to find Goblins",
+ " §7while mining.",
+ "§8 ■ §7Gain §a5x §9Titanium §7drops."
+ ),
+ new ItemStack(skyMall > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ goblinKiller,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop + 42),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Goblin Killer",
+ "§7Killing a §6Golden Goblin",
+ "§6§7gives §2200 §7extra §2Mithril",
+ "§2Powder§7, while killing other",
+ "§7Goblins gives some based on",
+ "§7their wits."
+ ),
+ new ItemStack(goblinKiller > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ seasonMine,
+ (int) (guiLeft + xStart + 231),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ seasonMine != 0 && seasonMine != 100
+ ? Lists.newArrayList(
+ "Seasoned Mineman",
+ "§7Level " + seasonMine + "§8/100",
+ "",
+ "§7Grants §3+" + EnumChatFormatting.DARK_AQUA + seasonMineStat + "☯ Mining Wisdom§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(seasonMine + 2, 2.3)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Seasoned Mineman",
+ "§7Level " + seasonMine + "§8/100",
+ "",
+ "§7Grants §3+" + EnumChatFormatting.DARK_AQUA + seasonMineStat + "☯ Mining Wisdom§7."
+ ),
+ 100
+ );
+
+ renderHotmPerk(
+ madMining,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () -> Lists.newArrayList("Mining Madness", "§7Grants §a+50 §6⸕ Mining Speed", "§7and §6☘ Mining Fortune§7."),
+ new ItemStack(madMining > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ lonesomeMiner,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ lonesomeMiner != 0 && lonesomeMiner != 45
+ ? Lists.newArrayList(
+ "Lonesome Miner",
+ "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45",
+ "",
+ "§7Increases §c❁ Strength, §9☣ Crit",
+ "§9Chance, §9☠ Crit Damage, §a❈",
+ "§aDefense, and §c❤ Health",
+ "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7",
+ "§7while in the Crystal Hollows.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(lonesomeMiner + 2, 3.07)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Lonesome Miner",
+ "§7Level " + lonesomeMiner + EnumChatFormatting.DARK_GRAY + "/45",
+ "",
+ "§7Increases §c❁ Strength, §9☣ Crit",
+ "§9Chance, §9☠ Crit Damage, §a❈",
+ "§aDefense, and §c❤ Health",
+ "§c§7statistics gain by " + EnumChatFormatting.GREEN + lonesomeMinerStat + "%§7"
+ ),
+ 45
+ );
+
+ renderHotmPerk(
+ professional,
+ (int) (guiLeft + xStart + 231),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ professional != 0 && professional != 140
+ ? Lists.newArrayList(
+ "Professional",
+ "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140",
+ "",
+ "§7Gain §a+" + professionalStat + "§6 ⸕ Mining",
+ "§6Speed§7 when mining Gemstones.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(professional + 2, 2.3)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Professional",
+ "§7Level " + professional + EnumChatFormatting.DARK_GRAY + "/140",
+ "",
+ "§7Gain §a+" + professionalStat + "§6 ⸕ Mining",
+ "§6Speed§7 when mining Gemstones."
+ ),
+ 140
+ );
+
+ renderHotmPerk(
+ miningSpeed2,
+ (int) (guiLeft + xStart + 207),
+ (int) (guiTop + yStartTop - 6),
+ mouseX,
+ mouseY,
+ () ->
+ miningSpeed2 != 0 && miningSpeed2 != 50
+ ? Lists.newArrayList(
+ "Mining Speed 2",
+ "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining",
+ "§6Speed§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format(Math.pow(miningSpeed2 + 2, 3)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Mining Speed 2",
+ "§7Level " + miningSpeed2 + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ "§7Grants " + EnumChatFormatting.GREEN + "+" + miningSpeed2Stat + EnumChatFormatting.GOLD + " ⸕ Mining",
+ "§6Speed§7."
+ ),
+ 50
+ );
+
+ renderHotmPerk(
+ quickForge,
+ (int) (guiLeft + xStart + 279),
+ (int) (guiTop + yStartTop + 114),
+ mouseX,
+ mouseY,
+ () ->
+ quickForge != 0 && quickForge != 20
+ ? Lists.newArrayList(
+ "Quick Forge",
+ "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Decreases the time it takes to",
+ "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(quickForge + 2, 4)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Quick Forge",
+ "§7Level " + quickForge + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Decreases the time it takes to",
+ "§7forge by §a" + (quickForgeStat < 20 ? quickForgeStat : 30) + "%§7."
+ ),
+ 20
+ );
+
+ renderHotmPerk(
+ fortunate,
+ (int) (guiLeft + xStart + 279),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ fortunate != 0 && fortunate != 20
+ ? Lists.newArrayList(
+ "Fortunate",
+ "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining",
+ "§6Fortune§7 when mining Gemstone.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(fortunate + 2, 3.05)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Fortunate",
+ "§7Level " + fortunate + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Gain " + EnumChatFormatting.GREEN + "+" + fortunateStat + " §6☘ Mining",
+ "§6Fortune§7 when mining Gemstone."
+ ),
+ 20
+ );
+
+ renderHotmPerk(
+ greatExplorer,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ greatExplorer != 0 && greatExplorer != 20
+ ? Lists.newArrayList(
+ "Great Explorer",
+ "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY +
+ "chance to",
+ "§7find treasure.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(greatExplorer + 2, 4)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Great Explorer",
+ "§7Level " + greatExplorer + EnumChatFormatting.DARK_GRAY + "/20",
+ "",
+ "§7Grants " + EnumChatFormatting.GREEN + "+" + greatExplorerStat + "% " + EnumChatFormatting.GRAY +
+ "chance to",
+ "§7find treasure."
+ ),
+ 20
+ );
+
+ renderHotmPerk(
+ miningFortune2,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop - 6),
+ mouseX,
+ mouseY,
+ () ->
+ miningFortune2 != 0 && miningFortune2 != 50
+ ? Lists.newArrayList(
+ "Mining Fortune 2",
+ "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining",
+ "§6Fortune§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.LIGHT_PURPLE +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(miningFortune2 + 2, 3.2)) +
+ " Gemstone Powder"
+ )
+ : Lists.newArrayList(
+ "Mining Fortune 2",
+ "§7Level " + miningFortune2 + EnumChatFormatting.DARK_GRAY + "/50",
+ "",
+ "§7Grants §a+§a" + miningFortune2Stat + "§7 §6☘ Mining",
+ "§6Fortune§7."
+ ),
+ 50
+ );
+
+ renderHotmPerk(
+ orbit,
+ (int) (guiLeft + xStart + 279),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ orbit != 0 && orbit != 80
+ ? Lists.newArrayList(
+ "Orbiter",
+ "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80",
+ "",
+ "§7When mining ores, you have a",
+ EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random",
+ "§7amount of experience orbs.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN + "" + ((orbit + 1) * 70) + " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Orbiter",
+ "§7Level " + orbit + EnumChatFormatting.DARK_GRAY + "/80",
+ "",
+ "§7When mining ores, you have a",
+ EnumChatFormatting.GREEN + "" + orbitStat + "%" + EnumChatFormatting.GRAY + " chance to get a random",
+ "§7amount of experience orbs."
+ ),
+ 80
+ );
+
+ renderHotmPerk(
+ frontLoad,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Front Loaded",
+ "§7Grants §a+100 §6⸕ Mining Speed",
+ "§7and §6☘ Mining Fortune §7for",
+ "§7the first §e2,500 §7ores you",
+ "§7mine in a day."
+ ),
+ new ItemStack(frontLoad > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ starPowder,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop + 42),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Star Powder",
+ "§7Mining Mithril Ore near §5Fallen",
+ "§5Crystals §7gives §a+3 §7extra",
+ "§7Mithril Powder§7."
+ ),
+ new ItemStack(starPowder > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ fortnite,
+ (int) (guiLeft + xStart + 327),
+ (int) (guiTop + yStartTop + 66),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Precision Mining",
+ "§7When mining ore, a particle",
+ "§7target appears on the block that",
+ "§7increases your §6⸕ Mining Speed",
+ "§7by §a30% §7when aiming at it."
+ ),
+ new ItemStack(fortnite > 0 ? Items.diamond : Items.coal)
+ );
+
+ renderHotmPerk(
+ crystallized,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop + 90),
+ mouseX,
+ mouseY,
+ () ->
+ crystallized != 0 && crystallized != 30
+ ? Lists.newArrayList(
+ "Crystallized",
+ "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30",
+ "",
+ "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining",
+ "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance",
+ "§7to deal §a+1 §7extra damage near",
+ "§7§5Fallen Stars§7.",
+ "",
+ EnumChatFormatting.GRAY + "Cost",
+ EnumChatFormatting.DARK_GREEN +
+ "" +
+ GuiProfileViewer.numberFormat.format((int) Math.pow(crystallized + 2, 2.4)) +
+ " Mithril Powder"
+ )
+ : Lists.newArrayList(
+ "Crystallized",
+ "§7Level " + crystallized + EnumChatFormatting.DARK_GRAY + "/30",
+ "",
+ "§7Grants §a+§a" + crystallizedStat + "§7 §6⸕ Mining",
+ "§6Speed §7and a §a" + crystallizedStat + "%§7 §7chance",
+ "§7to deal §a+1 §7extra damage near",
+ "§7§5Fallen Stars§7."
+ ),
+ 30
+ );
+
+ renderPickaxeAbility(
+ pickoblus,
+ (int) (guiLeft + xStart + 303),
+ (int) (guiTop + yStartTop + 114),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ "Pickobulus",
+ "",
+ "§6Pickaxe Ability: Pickobulus",
+ "§7Throw your pickaxe to create an",
+ "§7explosion on impact, mining all",
+ "§7ores within a §a2§7 block",
+ "§7radius.",
+ "§8Cooldown: §a" + (potm == 0 ? "120s" : "110s")
+ )
+ );
+
+ renderPickaxeAbility(
+ maniacMiner,
+ (int) (guiLeft + xStart + 327),
+ (int) (guiTop + yStartTop + 18),
+ mouseX,
+ mouseY,
+ () ->
+ Lists.newArrayList(
+ EnumChatFormatting.RED + "Maniac Miner",
+ "",
+ "§6Pickaxe Ability: Maniac Miner",
+ "§7Spends all your Mana and grants",
+ "§7§a+1 §6⸕ Mining Speed §7for",
+ "§7every 10 Mana spent, for",
+ "§7§a§a15s§7§7.",
+ "§8Cooldown: §a59s"
+ )
+ );
+ }
+
+ /**
+ * Renders a standard HOTM perk that can be levelled.
+ */
+ private void renderHotmPerk(
+ int perkLevel,
+ int xPosition,
+ int yPosition,
+ int mouseX,
+ int mouseY,
+ Supplier<ArrayList<String>> tooltipSupplier,
+ int maxLevel
+ ) {
+ renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, false, maxLevel);
+ }
+
+ /**
+ * Renders a pickaxe ability that can be unlocked once and not levelled.
+ */
+ private void renderPickaxeAbility(
+ int perkLevel,
+ int xPosition,
+ int yPosition,
+ int mouseX,
+ int mouseY,
+ Supplier<ArrayList<String>> tooltipSupplier
+ ) {
+ renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, true, -1);
+ }
+
+ /**
+ * Renders a HOTM perk. This method is only called from its overloads above.
+ */
+ private void renderHotmPerk(
+ int perkLevel,
+ int xPosition,
+ int yPosition,
+ int mouseX,
+ int mouseY,
+ Supplier<ArrayList<String>> tooltipSupplier,
+ boolean isPickaxeAbility,
+ int maxLevel
+ ) {
+ boolean unlocked = perkLevel > 0;
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+
+ ItemStack itemStack;
+ if (isPickaxeAbility) {
+ RenderHelper.enableGUIStandardItemLighting(); // GUI standard item lighting must be enabled for items that are rendered as blocks, like emerald blocks.
+ itemStack = new ItemStack(unlocked
+ ? Blocks.emerald_block
+ : Blocks.coal_block); // Pickaxe abilities are rendered as blocks
+ } else { // Non-pickaxe abilities are rendered as items
+ itemStack = new ItemStack(unlocked ? (perkLevel >= maxLevel ? Items.diamond : Items.emerald) : Items.coal);
+ }
+
+ ArrayList<String> tooltip = tooltipSupplier.get();
+ // Prepend the green, yellow, or red color on the first line of each tooltip depending on if the perk is unlocked
+ tooltip.set(
+ 0,
+ (unlocked
+ ? (perkLevel >= maxLevel ? EnumChatFormatting.GREEN : EnumChatFormatting.YELLOW)
+ : EnumChatFormatting.RED) +
+ tooltip.get(0)
+ );
+
+ NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Custom Resource Packs
+ NBTTagCompound display = new NBTTagCompound();
+ display.setString("Name", tooltip.get(0));
+ nbt.setTag("display", display);
+ itemStack.setTagCompound(nbt);
+
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition);
+ GlStateManager.enableLighting();
+ if (mouseX >= xPosition && mouseX < xPosition + 16) {
+ if (mouseY >= yPosition && mouseY <= yPosition + 16) {
+ Utils.drawHoveringText(
+ tooltip,
+ mouseX,
+ mouseY,
+ getInstance().width,
+ getInstance().height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+ }
+
+ /**
+ * A separate method similar to the one above, but allowing the caller to specify an ItemStack to render.
+ * Used for rendering Peak of the Mountain and perks that are unlocked once and not upgraded.
+ */
+ private void renderHotmPerk(
+ int perkLevel,
+ int xPosition,
+ int yPosition,
+ int mouseX,
+ int mouseY,
+ Supplier<ArrayList<String>> tooltipSupplier,
+ ItemStack itemStack
+ ) {
+ renderHotmPerk(perkLevel, xPosition, yPosition, mouseX, mouseY, tooltipSupplier, itemStack, false);
+ }
+
+ /**
+ * This method renders a HOTM perk using the provided ItemStack.
+ * It is overloaded by the method above, and is only called directly to render Peak of the Mountain.
+ */
+ private void renderHotmPerk(
+ int perkLevel,
+ int xPosition,
+ int yPosition,
+ int mouseX,
+ int mouseY,
+ Supplier<ArrayList<String>> tooltipSupplier,
+ ItemStack itemStack,
+ boolean isRenderingBlock
+ ) {
+ boolean unlocked = perkLevel > 0;
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+ if (isRenderingBlock) RenderHelper.enableGUIStandardItemLighting();
+
+ ArrayList<String> tooltip = tooltipSupplier.get();
+ // Prepend the green or red color on the first line of each tooltip depending on if the perk is unlocked
+ if (!tooltip.get(0).contains("Peak of the Mountain")) tooltip.set(
+ 0,
+ (unlocked ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + tooltip.get(0)
+ ); //Peak of the Moutain has three color options, and is set already
+
+ NBTTagCompound nbt = new NBTTagCompound(); //Adding NBT Data for Resource Packs
+ NBTTagCompound display = new NBTTagCompound();
+ display.setString("Name", tooltip.get(0));
+ if (tooltip.get(0).contains("Peak of the Mountain")) display.setString("Lore", tooltip.get(1)); //Set Lore to Level
+ nbt.setTag("display", display);
+ itemStack.setTagCompound(nbt);
+
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, xPosition, yPosition);
+ GlStateManager.enableLighting();
+ if (mouseX >= xPosition && mouseX < xPosition + 16) {
+ if (mouseY >= yPosition && mouseY <= yPosition + 16) {
+ Utils.drawHoveringText(
+ tooltip,
+ mouseX,
+ mouseY,
+ getInstance().width,
+ getInstance().height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
index ac117bc2..41217201 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
@@ -1,7 +1,28 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.profileviewer;
import io.github.moulberry.notenoughupdates.util.TexLoc;
import io.github.moulberry.notenoughupdates.util.Utils;
+import java.io.IOException;
+import java.util.HashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
@@ -16,14 +37,45 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Project;
public class Panorama {
+
private static final TexLoc tl = new TexLoc(97, 19, Keyboard.KEY_P);
private static final TexLoc tl2 = new TexLoc(37, 80, Keyboard.KEY_L);
-
+ private static final HashMap<String, ResourceLocation[]> panoramasMap = new HashMap<>();
private static ResourceLocation backgroundTexture = null;
-
private static int lastWidth = 0;
private static int lastHeight = 0;
+ public static synchronized ResourceLocation[] getPanoramasForLocation(String location, String identifier) {
+ if (panoramasMap.containsKey(location + identifier)) return panoramasMap.get(location + identifier);
+ try {
+ ResourceLocation[] panoramasArray = new ResourceLocation[6];
+ for (int i = 0; i < 6; i++) {
+ panoramasArray[i] =
+ new ResourceLocation("notenoughupdates:panoramas/" + location + "_" + identifier + "/panorama_" + i + ".jpg");
+ Minecraft.getMinecraft().getResourceManager().getResource(panoramasArray[i]);
+ }
+ panoramasMap.put(location + identifier, panoramasArray);
+ return panoramasArray;
+ } catch (IOException e) {
+ try {
+ ResourceLocation[] panoramasArray = new ResourceLocation[6];
+ for (int i = 0; i < 6; i++) {
+ panoramasArray[i] = new ResourceLocation("notenoughupdates:panoramas/" + location + "/panorama_" + i + ".jpg");
+ Minecraft.getMinecraft().getResourceManager().getResource(panoramasArray[i]);
+ }
+ panoramasMap.put(location + identifier, panoramasArray);
+ return panoramasArray;
+ } catch (IOException e2) {
+ ResourceLocation[] panoramasArray = new ResourceLocation[6];
+ for (int i = 0; i < 6; i++) {
+ panoramasArray[i] = new ResourceLocation("notenoughupdates:panoramas/unknown/panorama_" + i + ".jpg");
+ }
+ panoramasMap.put(location + identifier, panoramasArray);
+ return panoramasArray;
+ }
+ }
+ }
+
public static void drawPanorama(
float angle,
int x,
@@ -116,7 +168,6 @@ public class Panorama {
float scale = (float) Math.sqrt(3 / distSq);
worldrenderer.pos(xr * scale, yr * scale, scale).tex(x2, y2).color(255, 255, 255, 255).endVertex();
-
}
tessellator.draw();
@@ -140,12 +191,16 @@ public class Panorama {
GlStateManager.enableDepth();
}
- if (backgroundTexture == null || lastWidth != width * scaledresolution.getScaleFactor() ||
- lastHeight != height * scaledresolution.getScaleFactor()) {
- DynamicTexture viewportTexture =
- new DynamicTexture(width * scaledresolution.getScaleFactor(), height * scaledresolution.getScaleFactor());
- backgroundTexture =
- Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("background", viewportTexture);
+ if (
+ backgroundTexture == null ||
+ lastWidth != width * scaledresolution.getScaleFactor() ||
+ lastHeight != height * scaledresolution.getScaleFactor()
+ ) {
+ DynamicTexture viewportTexture = new DynamicTexture(
+ width * scaledresolution.getScaleFactor(),
+ height * scaledresolution.getScaleFactor()
+ );
+ backgroundTexture = Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation("background", viewportTexture);
lastWidth = width * scaledresolution.getScaleFactor();
lastHeight = height * scaledresolution.getScaleFactor();
}
@@ -168,14 +223,10 @@ public class Panorama {
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
- worldrenderer.pos(x, y + height, 0)
- .tex(0, 1).endVertex();
- worldrenderer.pos(x + width, y + height, 0)
- .tex(0, 0).endVertex();
- worldrenderer.pos(x + width, y, 0)
- .tex(1, 0).endVertex();
- worldrenderer.pos(x, y, 0)
- .tex(1, 1).endVertex();
+ worldrenderer.pos(x, y + height, 0).tex(0, 1).endVertex();
+ worldrenderer.pos(x + width, y + height, 0).tex(0, 0).endVertex();
+ worldrenderer.pos(x + width, y, 0).tex(1, 0).endVertex();
+ worldrenderer.pos(x, y, 0).tex(1, 1).endVertex();
tessellator.draw();
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java
new file mode 100644
index 00000000..cb85bf79
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PetsPage.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PetsPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_pets = new ResourceLocation("notenoughupdates:pv_pets.png");
+ private static final int COLLS_XCOUNT = 5;
+ private static final int COLLS_YCOUNT = 4;
+ private static final float COLLS_XPADDING = (190 - COLLS_XCOUNT * 20) / (float) (COLLS_XCOUNT + 1);
+ private static final float COLLS_YPADDING = (202 - COLLS_YCOUNT * 20) / (float) (COLLS_YCOUNT + 1);
+ private List<JsonObject> sortedPets = null;
+ private List<ItemStack> sortedPetsStack = null;
+ private int selectedPet = -1;
+ private int petsPage = 0;
+
+ public PetsPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ ProfileViewer.Profile profile = GuiProfileViewer.getProfile();
+ String profileId = GuiProfileViewer.getProfileId();
+ JsonObject petsInfo = profile.getPetsInfo(profileId);
+ if (petsInfo == null) return;
+ JsonObject petsJson = Constants.PETS;
+ if (petsJson == null) return;
+
+ String location = null;
+ JsonObject status = profile.getPlayerStatus();
+ if (status != null && status.has("mode")) {
+ location = status.get("mode").getAsString();
+ }
+
+ getInstance().backgroundRotation += (getInstance().currentTime - getInstance().lastTime) / 400f;
+ getInstance().backgroundRotation %= 360;
+
+ String panoramaIdentifier = "day";
+ if (SBInfo.getInstance().currentTimeDate != null) {
+ if (SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
+ panoramaIdentifier = "night";
+ }
+ }
+
+ JsonArray pets = petsInfo.get("pets").getAsJsonArray();
+ if (sortedPets == null) {
+ sortedPets = new ArrayList<>();
+ sortedPetsStack = new ArrayList<>();
+ for (int i = 0; i < pets.size(); i++) {
+ sortedPets.add(pets.get(i).getAsJsonObject());
+ }
+ sortedPets.sort((pet1, pet2) -> {
+ String tier1 = pet1.get("tier").getAsString();
+ String tierNum1 = GuiProfileViewer.MINION_RARITY_TO_NUM.get(tier1);
+ if (tierNum1 == null) return 1;
+ int tierNum1I = Integer.parseInt(tierNum1);
+ float exp1 = pet1.get("exp").getAsFloat();
+
+ String tier2 = pet2.get("tier").getAsString();
+ String tierNum2 = GuiProfileViewer.MINION_RARITY_TO_NUM.get(tier2);
+ if (tierNum2 == null) return -1;
+ int tierNum2I = Integer.parseInt(tierNum2);
+ float exp2 = pet2.get("exp").getAsFloat();
+
+ if (tierNum1I != tierNum2I) {
+ return tierNum2I - tierNum1I;
+ } else {
+ return (int) (exp2 - exp1);
+ }
+ });
+ for (JsonObject pet : sortedPets) {
+ PetInfoOverlay.Pet parsedPet = new PetInfoOverlay.Pet();
+ parsedPet.petType = pet.get("type").getAsString();
+ parsedPet.rarity = PetInfoOverlay.Rarity.valueOf(pet.get("tier").getAsString());
+ parsedPet.petLevel = GuiProfileViewer.getPetLevel(
+ parsedPet.petType,
+ parsedPet.rarity.name(),
+ pet.get("exp").getAsFloat()
+ );
+ parsedPet.petXpType = "unknown";
+ parsedPet.petItem = Utils.getElementAsString(pet.get("heldItem"), null);
+ parsedPet.skin = Utils.getElementAsString(pet.get("skin"), null);
+ parsedPet.candyUsed = pet.get("candyUsed").getAsInt();
+ sortedPetsStack.add(ItemUtils.createPetItemstackFromPetInfo(parsedPet));
+ pet.addProperty("level", parsedPet.petLevel.level);
+ pet.addProperty("currentLevelRequirement", parsedPet.petLevel.currentLevelRequirement);
+ pet.addProperty("maxXP", parsedPet.petLevel.maxXP);
+ }
+ }
+
+ Panorama.drawPanorama(
+ -getInstance().backgroundRotation,
+ guiLeft + 212,
+ guiTop + 44,
+ 81,
+ 108,
+ -0.37f,
+ 0.6f,
+ Panorama.getPanoramasForLocation(location == null ? "dynamic" : location, panoramaIdentifier)
+ );
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_pets);
+ Utils.drawTexturedRect(guiLeft, guiTop, getInstance().sizeX, getInstance().sizeY, GL11.GL_NEAREST);
+
+ Utils.drawStringCentered(
+ EnumChatFormatting.DARK_PURPLE + "Pets",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 100,
+ guiTop + 14,
+ true,
+ 4210752
+ );
+ GlStateManager.color(1, 1, 1, 1);
+
+ JsonElement activePetElement = petsInfo.get("active_pet");
+ if (selectedPet == -1 && activePetElement != null && activePetElement.isJsonObject()) {
+ JsonObject active = activePetElement.getAsJsonObject();
+ for (int i = 0; i < sortedPets.size(); i++) {
+ if (sortedPets.get(i) == active) {
+ selectedPet = i;
+ break;
+ }
+ }
+ }
+
+ boolean leftHovered = false;
+ boolean rightHovered = false;
+ if (Mouse.isButtonDown(0)) {
+ if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
+ if (mouseX > guiLeft + 100 - 20 - 12 && mouseX < guiLeft + 100 - 20) {
+ leftHovered = true;
+ } else if (mouseX > guiLeft + 100 + 20 && mouseX < guiLeft + 100 + 20 + 12) {
+ rightHovered = true;
+ }
+ }
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.resource_packs);
+
+ if (petsPage > 0) {
+ Utils.drawTexturedRect(
+ guiLeft + 100 - 15 - 12,
+ guiTop + 6,
+ 12,
+ 16,
+ 29 / 256f,
+ 53 / 256f,
+ !leftHovered ? 0 : 32 / 256f,
+ !leftHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+ if (petsPage < Math.ceil(pets.size() / 20f) - 1) {
+ Utils.drawTexturedRect(
+ guiLeft + 100 + 15,
+ guiTop + 6,
+ 12,
+ 16,
+ 5 / 256f,
+ 29 / 256f,
+ !rightHovered ? 0 : 32 / 256f,
+ !rightHovered ? 32 / 256f : 64 / 256f,
+ GL11.GL_NEAREST
+ );
+ }
+
+ for (
+ int i = petsPage * 20;
+ i < Math.min(petsPage * 20 + 20, Math.min(sortedPetsStack.size(), sortedPets.size()));
+ i++
+ ) {
+ JsonObject pet = sortedPets.get(i);
+ ItemStack stack = sortedPetsStack.get(i);
+
+ if (pet != null) {
+ {
+ NBTTagCompound tag = stack.getTagCompound();
+ tag.setBoolean("DisablePetExp", true);
+ stack.setTagCompound(tag);
+ }
+ int xIndex = (i % 20) % COLLS_XCOUNT;
+ int yIndex = (i % 20) / COLLS_XCOUNT;
+
+ float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
+ float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiProfileViewer.pv_elements);
+ if (i == selectedPet) {
+ GlStateManager.color(1, 185 / 255f, 0, 1);
+ } else {
+ GlStateManager.color(1, 1, 1, 1);
+ }
+ Utils.drawTexturedRect(guiLeft + x, guiTop + y, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
+
+ Utils.drawItemStack(stack, guiLeft + (int) x + 2, guiTop + (int) y + 2, true);
+
+ if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) {
+ if (mouseY > guiTop + y && mouseY < guiTop + y + 20) {
+ getInstance().tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+ }
+ }
+
+ if (selectedPet >= 0) {
+ ItemStack petStack;
+ if (sortedPetsStack.size() <= selectedPet) {
+ petStack = ItemUtils.createQuestionMarkSkull("§cInvalid pet selection");
+ } else {
+ petStack = sortedPetsStack.get(selectedPet);
+ }
+ String display = petStack.getDisplayName();
+ JsonObject pet = sortedPets.get(selectedPet);
+
+ int x = guiLeft + 280;
+ float y = guiTop + 67 + 15 * (float) Math.sin(
+ ((getInstance().currentTime - getInstance().startTime) / 800f) % (2 * Math.PI));
+
+ int displayLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(display);
+ int halfDisplayLen = displayLen / 2;
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x, y, 0);
+
+ GuiScreen.drawRect(-halfDisplayLen - 1 - 28, -1, halfDisplayLen + 1 - 28, 8, new Color(0, 0, 0, 100).getRGB());
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(display, -halfDisplayLen - 28, 0, 0, true);
+
+ GlStateManager.enableDepth();
+ GlStateManager.translate(-55, 0, 0);
+ GlStateManager.scale(3.5f, 3.5f, 1);
+ Utils.drawItemStack(petStack, 0, 0);
+ GlStateManager.popMatrix();
+
+ float level = pet.get("level").getAsFloat();
+ float currentLevelRequirement = pet.get("currentLevelRequirement").getAsFloat();
+ float exp = pet.get("exp").getAsFloat();
+ float maxXP = pet.get("maxXP").getAsFloat();
+
+ String[] split = display.split("] ");
+ String colouredName = split[split.length - 1];
+
+ Utils.renderAlignedString(
+ colouredName,
+ EnumChatFormatting.WHITE + "Level " + (int) Math.floor(level),
+ guiLeft + 319,
+ guiTop + 28,
+ 98
+ );
+
+ //Utils.drawStringCenteredScaledMaxWidth(, Minecraft.getMinecraft().fontRendererObj, guiLeft+368, guiTop+28+4, true, 98, 0);
+ //renderAlignedString(display, EnumChatFormatting.YELLOW+"[LVL "+Math.floor(level)+"]", guiLeft+319, guiTop+28, 98);
+ getInstance().renderBar(guiLeft + 319, guiTop + 38, 98, (float) Math.floor(level) / 100f);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "To Next LVL",
+ EnumChatFormatting.WHITE.toString() + (int) (level % 1 * 100) + "%",
+ guiLeft + 319,
+ guiTop + 46,
+ 98
+ );
+ getInstance().renderBar(guiLeft + 319, guiTop + 56, 98, level % 1);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "To Max LVL",
+ EnumChatFormatting.WHITE.toString() + Math.min(100, (int) (exp / maxXP * 100)) + "%",
+ guiLeft + 319,
+ guiTop + 64,
+ 98
+ );
+ getInstance().renderBar(guiLeft + 319, guiTop + 74, 98, exp / maxXP);
+
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Total XP",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(exp),
+ guiLeft + 319,
+ guiTop + 125,
+ 98
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Current LVL XP",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat((level % 1) * currentLevelRequirement),
+ guiLeft + 319,
+ guiTop + 143,
+ 98
+ );
+ Utils.renderAlignedString(
+ EnumChatFormatting.YELLOW + "Required LVL XP",
+ EnumChatFormatting.WHITE + StringUtils.shortNumberFormat(currentLevelRequirement),
+ guiLeft + 319,
+ guiTop + 161,
+ 98
+ );
+ }
+ }
+
+ @Override
+ public boolean mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ if (sortedPets == null) return false;
+ for (int i = petsPage * 20; i < Math.min(petsPage * 20 + 20, sortedPets.size()); i++) {
+ int xIndex = (i % 20) % COLLS_XCOUNT;
+ int yIndex = (i % 20) / COLLS_XCOUNT;
+
+ float x = 5 + COLLS_XPADDING + (COLLS_XPADDING + 20) * xIndex;
+ float y = 7 + COLLS_YPADDING + (COLLS_YPADDING + 20) * yIndex;
+
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+ if (mouseX > guiLeft + x && mouseX < guiLeft + x + 20) {
+ if (mouseY > guiTop + y && mouseY < guiTop + y + 20) {
+ selectedPet = i;
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY, int mouseButton) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ if (mouseY > guiTop + 6 && mouseY < guiTop + 22) {
+ if (mouseX > guiLeft + 100 - 15 - 12 && mouseX < guiLeft + 100 - 20) {
+ if (petsPage > 0) {
+ petsPage--;
+ }
+ } else if (mouseX > guiLeft + 100 + 15 && mouseX < guiLeft + 100 + 20 + 12) {
+ if (sortedPets != null && petsPage < Math.ceil(sortedPets.size() / 20f) - 1) {
+ petsPage++;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void resetCache() {
+ petsPage = 0;
+ sortedPets = null;
+ sortedPetsStack = null;
+ selectedPet = -1;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
index 4a915111..b0cc930a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.profileviewer;
import com.google.gson.JsonArray;
@@ -5,23 +24,34 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.profileviewer.info.QuiverInfo;
import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.JsonToNBT;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.EnumChatFormatting;
import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.AbstractMap;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class PlayerStats {
+
public static final String HEALTH = "health";
public static final String DEFENCE = "defence";
public static final String STRENGTH = "strength";
@@ -33,8 +63,10 @@ public class PlayerStats {
public static final String SEA_CREATURE_CHANCE = "sea_creature_chance";
public static final String MAGIC_FIND = "magic_find";
public static final String PET_LUCK = "pet_luck";
+ public static final String MINING_FORTUNE = "mining_fortune";
+ public static final String MINING_SPEED = "mining_speed";
- public static final String[] defaultStatNames = new String[]{
+ public static final String[] defaultStatNames = new String[] {
"health",
"defence",
"strength",
@@ -49,9 +81,9 @@ public class PlayerStats {
"ferocity",
"ability_damage",
"mining_fortune",
- "mining_speed"
+ "mining_speed",
};
- public static final String[] defaultStatNamesPretty = new String[]{
+ public static final String[] defaultStatNamesPretty = new String[] {
EnumChatFormatting.RED + "\u2764 Health",
EnumChatFormatting.GREEN + "\u2748 Defence",
EnumChatFormatting.RED + "\u2741 Strength",
@@ -66,83 +98,23 @@ public class PlayerStats {
EnumChatFormatting.RED + "\u2AFD Ferocity",
EnumChatFormatting.RED + "\u2739 Ability Damage",
EnumChatFormatting.GOLD + "\u2618 Mining Fortune",
- EnumChatFormatting.GOLD + "\u2E15 Mining Speed"
+ EnumChatFormatting.GOLD + "\u2E15 Mining Speed",
};
-
- public static class Stats {
- JsonObject statsJson = new JsonObject();
-
- /*public float health;
- public float defence;
- public float strength;
- public float speed;
- public float crit_chance;
- public float crit_damage;
- public float bonus_attack_speed;
- public float intelligence;
- public float sea_creature_chance;
- public float magic_find;
- public float pet_luck;*/
-
- public Stats(Stats... statses) {
- for (Stats stats : statses) {
- add(stats);
- }
- }
-
- /*@Override
- public String toString() {
- return String.format("{health=%s,defence=%s,strength=%s,speed=%s,crit_chance=%s,crit_damage=%s," +
- "bonus_attack_speed=%s,intelligence=%s,sea_creature_chance=%s,magic_find=%s,pet_luck=%s}",
- stats.get("health"), defence, strength, speed, crit_chance, crit_damage, bonus_attack_speed, intelligence,
- sea_creature_chance, magic_find, pet_luck
- );
- }*/
-
- public float get(String statName) {
- if (statsJson.has(statName)) {
- return statsJson.get(statName).getAsFloat();
- } else {
- return 0;
- }
- }
-
- public Stats add(Stats stats) {
- for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) {
- if (statEntry.getValue().isJsonPrimitive() && ((JsonPrimitive) statEntry.getValue()).isNumber()) {
- if (!statsJson.has(statEntry.getKey())) {
- statsJson.add(statEntry.getKey(), statEntry.getValue());
- } else {
- JsonPrimitive e = statsJson.get(statEntry.getKey()).getAsJsonPrimitive();
- float statNum = e.getAsFloat() + statEntry.getValue().getAsFloat();
- statsJson.add(statEntry.getKey(), new JsonPrimitive(statNum));
- }
- }
- }
- return this;
- }
-
- public void scale(String statName, float scale) {
- if (statsJson.has(statName)) {
- statsJson.add(statName, new JsonPrimitive(statsJson.get(statName).getAsFloat() * scale));
- }
- }
-
- public void scaleAll(float scale) {
- for (Map.Entry<String, JsonElement> statEntry : statsJson.entrySet()) {
- statsJson.add(statEntry.getKey(), new JsonPrimitive(statEntry.getValue().getAsFloat() * scale));
- }
+ private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<String, Pattern>() {
+ {
+ put(HEALTH, Pattern.compile("^Health: ((?:\\+|-)[0-9]+)"));
+ put(DEFENCE, Pattern.compile("^Defense: ((?:\\+|-)[0-9]+)"));
+ put(STRENGTH, Pattern.compile("^Strength: ((?:\\+|-)[0-9]+)"));
+ put(SPEED, Pattern.compile("^Speed: ((?:\\+|-)[0-9]+)"));
+ put(CRIT_CHANCE, Pattern.compile("^Crit Chance: ((?:\\+|-)[0-9]+)"));
+ put(CRIT_DAMAGE, Pattern.compile("^Crit Damage: ((?:\\+|-)[0-9]+)"));
+ put(BONUS_ATTACK_SPEED, Pattern.compile("^Bonus Attack Speed: ((?:\\+|-)[0-9]+)"));
+ put(INTELLIGENCE, Pattern.compile("^Intelligence: ((?:\\+|-)[0-9]+)"));
+ put(SEA_CREATURE_CHANCE, Pattern.compile("^Sea Creature Chance: ((?:\\+|-)[0-9]+)"));
+ put("ferocity", Pattern.compile("^Ferocity: ((?:\\+|-)[0-9]+)"));
+ put("ability_damage", Pattern.compile("^Ability Damage: ((?:\\+|-)[0-9]+)"));
}
-
- public void addStat(String statName, float amount) {
- if (!statsJson.has(statName)) {
- statsJson.add(statName, new JsonPrimitive(amount));
- } else {
- JsonPrimitive e = statsJson.get(statName).getAsJsonPrimitive();
- statsJson.add(statName, new JsonPrimitive(e.getAsFloat() + amount));
- }
- }
- }
+ };
public static Stats getBaseStats() {
JsonObject misc = Constants.MISC;
@@ -169,29 +141,26 @@ public class PlayerStats {
return bonus;
}
- private static Stats getSkillBonus(JsonObject skillInfo) {
+ private static Stats getSkillBonus(Map<String, ProfileViewer.Level> skyblockInfo) {
JsonObject bonuses = Constants.BONUSES;
if (bonuses == null) return null;
Stats skillBonus = new Stats();
- for (Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) {
- if (entry.getKey().startsWith("level_")) {
- String skill = entry.getKey().substring("level_".length());
- JsonElement element = Utils.getElement(bonuses, "bonus_stats." + skill);
- if (element != null && element.isJsonObject()) {
- JsonObject skillStatMap = element.getAsJsonObject();
-
- Stats currentBonus = new Stats();
- for (int i = 1; i <= entry.getValue().getAsFloat(); i++) {
- if (skillStatMap.has("" + i)) {
- currentBonus = new Stats();
- for (Map.Entry<String, JsonElement> entry2 : skillStatMap.get("" + i).getAsJsonObject().entrySet()) {
- currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat());
- }
+ for (Map.Entry<String, ProfileViewer.Level> entry : skyblockInfo.entrySet()) {
+ JsonElement element = Utils.getElement(bonuses, "bonus_stats." + entry.getKey());
+ if (element != null && element.isJsonObject()) {
+ JsonObject skillStatMap = element.getAsJsonObject();
+
+ Stats currentBonus = new Stats();
+ for (int i = 1; i <= entry.getValue().level; i++) {
+ if (skillStatMap.has("" + i)) {
+ currentBonus = new Stats();
+ for (Map.Entry<String, JsonElement> entry2 : skillStatMap.get("" + i).getAsJsonObject().entrySet()) {
+ currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat());
}
- skillBonus.add(currentBonus);
}
+ skillBonus.add(currentBonus);
}
}
}
@@ -237,8 +206,7 @@ public class PlayerStats {
}
private static float harpBonus(JsonObject profile) {
- String talk_to_melody =
- Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE");
+ String talk_to_melody = Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE");
if (talk_to_melody.equalsIgnoreCase("COMPLETE")) {
return 26;
} else {
@@ -246,11 +214,24 @@ public class PlayerStats {
}
}
- public static Stats getPassiveBonuses(JsonObject skillInfo, JsonObject profile) {
+ private static float hotmFortune(JsonObject profile, Map<String, ProfileViewer.Level> skyblockInfo) {
+ int miningLevelFortune = (int) (4 * (float) Math.floor(skyblockInfo.get("mining").level));
+ int miningFortuneStat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune"), 0)) * 5);
+ int miningFortune2Stat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_fortune_2"), 0)) * 5);
+ return miningFortuneStat + miningFortune2Stat + miningLevelFortune;
+ }
+
+ private static float hotmSpeed(JsonObject profile) {
+ int miningSpeedStat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed"), 0)) * 20);
+ int miningSpeed2Stat = ((Utils.getElementAsInt(Utils.getElement(profile, "mining_core.nodes.mining_speed_2"), 0)) * 40);
+ return miningSpeedStat + miningSpeed2Stat;
+ }
+
+ public static Stats getPassiveBonuses(Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile) {
Stats passiveBonuses = new Stats();
Stats fairyBonus = getFairyBonus((int) Utils.getElementAsFloat(Utils.getElement(profile, "fairy_exchanges"), 0));
- Stats skillBonus = getSkillBonus(skillInfo);
+ Stats skillBonus = getSkillBonus(skyblockInfo);
Stats petBonus = getTamingBonus(profile);
if (skillBonus == null || petBonus == null) {
@@ -265,6 +246,15 @@ public class PlayerStats {
return passiveBonuses;
}
+ public static Stats getHOTMBonuses(Map<String, ProfileViewer.Level> skyblockInfo, JsonObject profile) {
+ Stats hotmBonuses = new Stats();
+
+ hotmBonuses.addStat(MINING_FORTUNE, hotmFortune(profile, skyblockInfo));
+ hotmBonuses.addStat(MINING_SPEED, hotmSpeed(profile));
+
+ return hotmBonuses;
+ }
+
private static String getFullset(JsonArray armor, int ignore) {
String fullset = null;
for (int i = 0; i < armor.size(); i++) {
@@ -296,7 +286,7 @@ public class PlayerStats {
Stats stats,
JsonObject inventoryInfo,
JsonObject collectionInfo,
- JsonObject skillInfo,
+ Map<String, ProfileViewer.Level> skyblockInfo,
JsonObject profile
) {
JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
@@ -310,7 +300,8 @@ public class PlayerStats {
case "LAPIS_ARMOR_":
bonuses.addStat(HEALTH, 60);
break;
- case "EMERALD_ARMOR_": {
+ case "EMERALD_ARMOR_":
+ {
int bonus = (int) Math.floor(Utils.getElementAsFloat(Utils.getElement(collectionInfo, "EMERALD"), 0) / 3000);
bonuses.addStat(HEALTH, bonus);
bonuses.addStat(DEFENCE, bonus);
@@ -329,10 +320,7 @@ public class PlayerStats {
bonuses.addStat(HEALTH, 50 * Math.round(stats.get(CRIT_DAMAGE)));
break;
case "ANGLER_":
- bonuses.addStat(
- HEALTH,
- 10 * (float) Math.floor(Utils.getElementAsFloat(Utils.getElement(skillInfo, "level_skill_fishing"), 0))
- );
+ bonuses.addStat(HEALTH, 10 * (float) Math.floor(skyblockInfo.get("fishing").level));
bonuses.addStat(SEA_CREATURE_CHANCE, 4);
break;
case "ARMOR_OF_MAGMA_":
@@ -373,20 +361,6 @@ public class PlayerStats {
return bonuses;
}
- private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<String, Pattern>() {{
- put(HEALTH, Pattern.compile("^Health: ((?:\\+|-)[0-9]+)"));
- put(DEFENCE, Pattern.compile("^Defense: ((?:\\+|-)[0-9]+)"));
- put(STRENGTH, Pattern.compile("^Strength: ((?:\\+|-)[0-9]+)"));
- put(SPEED, Pattern.compile("^Speed: ((?:\\+|-)[0-9]+)"));
- put(CRIT_CHANCE, Pattern.compile("^Crit Chance: ((?:\\+|-)[0-9]+)"));
- put(CRIT_DAMAGE, Pattern.compile("^Crit Damage: ((?:\\+|-)[0-9]+)"));
- put(BONUS_ATTACK_SPEED, Pattern.compile("^Bonus Attack Speed: ((?:\\+|-)[0-9]+)"));
- put(INTELLIGENCE, Pattern.compile("^Intelligence: ((?:\\+|-)[0-9]+)"));
- put(SEA_CREATURE_CHANCE, Pattern.compile("^Sea Creature Chance: ((?:\\+|-)[0-9]+)"));
- put("ferocity", Pattern.compile("^Ferocity: ((?:\\+|-)[0-9]+)"));
- put("ability_damage", Pattern.compile("^Ability Damage: ((?:\\+|-)[0-9]+)"));
- }};
-
private static Stats getStatForItem(String internalname, JsonObject item, JsonArray lore) {
Stats stats = new Stats();
for (int i = 0; i < lore.size(); i++) {
@@ -450,8 +424,7 @@ public class PlayerStats {
if (itemBonuses.containsKey(internalname)) {
continue;
}
- if (!talismanOnly ||
- Utils.checkItemType(item.get("lore").getAsJsonArray(), true, "ACCESSORY", "HATCCESSORY") >= 0) {
+ if (!talismanOnly || Utils.checkItemType(item.get("lore").getAsJsonArray(), true, "ACCESSORY", "HATCCESSORY") >= 0) {
Stats itemBonus = getStatForItem(internalname, item, item.get("lore").getAsJsonArray());
itemBonuses.put(internalname, itemBonus);
@@ -483,13 +456,21 @@ public class PlayerStats {
JsonObject petnums = Constants.PETNUMS;
if (petsJson == null || petnums == null) return new Stats();
- if (petsInfo != null && petsInfo.has("active_pet") && petsInfo.get("active_pet") != null &&
- petsInfo.get("active_pet").isJsonObject()) {
+ if (
+ petsInfo != null &&
+ petsInfo.has("active_pet") &&
+ petsInfo.get("active_pet") != null &&
+ petsInfo.get("active_pet").isJsonObject()
+ ) {
JsonObject pet = petsInfo.get("active_pet").getAsJsonObject();
- if (pet.has("type") && pet.get("type") != null &&
- pet.has("tier") && pet.get("tier") != null &&
- pet.has("exp") && pet.get("exp") != null) {
-
+ if (
+ pet.has("type") &&
+ pet.get("type") != null &&
+ pet.has("tier") &&
+ pet.get("tier") != null &&
+ pet.has("exp") &&
+ pet.get("exp") != null
+ ) {
String petname = pet.get("type").getAsString();
String tier = pet.get("tier").getAsString();
String heldItem = Utils.getElementAsString(pet.get("heldItem"), null);
@@ -502,13 +483,16 @@ public class PlayerStats {
float exp = pet.get("exp").getAsFloat();
if (tierNum == null) return new Stats();
- if (pet.has("heldItem") && !pet.get("heldItem").isJsonNull() &&
- pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST")) {
+ if (
+ pet.has("heldItem") &&
+ !pet.get("heldItem").isJsonNull() &&
+ pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST")
+ ) {
tierNum = "" + (Integer.parseInt(tierNum) + 1);
}
GuiProfileViewer.PetLevel levelObj = GuiProfileViewer.getPetLevel(petname, tier, exp);
-
+ if (levelObj == null) return null;
float level = levelObj.level;
float currentLevelRequirement = levelObj.currentLevelRequirement;
float maxXP = levelObj.maxXP;
@@ -551,18 +535,15 @@ public class PlayerStats {
String key = entryBoost.getKey().toLowerCase();
try {
stats.addStat(key, entryBoost.getValue());
- } catch (Exception ignored) {
- }
+ } catch (Exception ignored) {}
}
-
}
if (petStatBootsMult != null) {
for (Map.Entry<String, Float> entryBoost : petStatBootsMult.entrySet()) {
String key = entryBoost.getKey().toLowerCase();
try {
stats.scale(key, entryBoost.getValue());
- } catch (Exception ignored) {
- }
+ } catch (Exception ignored) {}
}
}
}
@@ -619,24 +600,30 @@ public class PlayerStats {
}
for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) {
- if (statEntry.getKey().equals(CRIT_DAMAGE) ||
- statEntry.getKey().equals(INTELLIGENCE) ||
- statEntry.getKey().equals(BONUS_ATTACK_SPEED)) continue;
+ if (
+ statEntry.getKey().equals(CRIT_DAMAGE) ||
+ statEntry.getKey().equals(INTELLIGENCE) ||
+ statEntry.getKey().equals(BONUS_ATTACK_SPEED)
+ ) continue;
stats.statsJson.add(statEntry.getKey(), new JsonPrimitive(Math.max(0, statEntry.getValue().getAsFloat())));
}
}
public static Stats getStats(
- JsonObject skillInfo, JsonObject inventoryInfo, JsonObject collectionInfo,
- JsonObject petsInfo, JsonObject profile
+ Map<String, ProfileViewer.Level> skyblockInfo,
+ JsonObject inventoryInfo,
+ JsonObject collectionInfo,
+ JsonObject petsInfo,
+ JsonObject profile
) {
- if (skillInfo == null || inventoryInfo == null || collectionInfo == null || profile == null) return null;
+ if (skyblockInfo == null || inventoryInfo == null || collectionInfo == null || profile == null) return null;
JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray();
JsonArray talisman_bag = Utils.getElement(inventoryInfo, "talisman_bag").getAsJsonArray();
- Stats passiveBonuses = getPassiveBonuses(skillInfo, profile);
+ Stats passiveBonuses = getPassiveBonuses(skyblockInfo, profile);
+ Stats hotmBonuses = getHOTMBonuses(skyblockInfo, profile);
Stats armorBonuses = getItemBonuses(false, armor);
Stats talismanBonuses = getItemBonuses(true, inventory, talisman_bag);
@@ -650,10 +637,11 @@ public class PlayerStats {
}
Stats petBonus = getPetStatBonuses(petsInfo);
+ if (petBonus == null) return null;
- stats = stats.add(passiveBonuses).add(armorBonuses).add(talismanBonuses).add(petBonus);
+ stats = stats.add(passiveBonuses).add(armorBonuses).add(talismanBonuses).add(petBonus).add(hotmBonuses);
- stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skillInfo, profile));
+ stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skyblockInfo, profile));
stats.scaleAll(getStatMult(inventoryInfo));
@@ -661,4 +649,215 @@ public class PlayerStats {
return stats;
}
+
+ /**
+ * Calculates the amount of Magical Power the player has using the list of accessories
+ *
+ * @param inventoryInfo inventory info object
+ * @return the amount of Magical Power or -1
+ * @see io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer.Profile#getInventoryInfo(String)
+ */
+ public static int getMagicalPower(JsonObject inventoryInfo) {
+ if (inventoryInfo == null || !inventoryInfo.has("talisman_bag") || !inventoryInfo.get("talisman_bag").isJsonArray()) {
+ return -1;
+ }
+
+ Map<String, Integer> accessories = JsonUtils.getJsonArrayAsStream(inventoryInfo.get("talisman_bag").getAsJsonArray())
+ .map(o -> {
+ try {
+ return JsonToNBT.getTagFromJson(o.getAsJsonObject().get("nbttag").getAsString());
+ } catch (Exception ignored) {
+ return null;
+ }
+ }).filter(Objects::nonNull).map(tag -> {
+ NBTTagList loreTagList = tag.getCompoundTag("display").getTagList("Lore", 8);
+ String lastElement = loreTagList.getStringTagAt(loreTagList.tagCount() - 1);
+ if (lastElement.contains(EnumChatFormatting.OBFUSCATED.toString())) {
+ lastElement = lastElement.substring(lastElement.indexOf(' ')).trim().substring(4);
+ }
+ JsonArray lastElementJsonArray = new JsonArray();
+ lastElementJsonArray.add(new JsonPrimitive(lastElement));
+ return new AbstractMap.SimpleEntry<>(
+ tag.getCompoundTag("ExtraAttributes").getString("id"),
+ Utils.getRarityFromLore(lastElementJsonArray)
+ );
+ }).sorted(Comparator.comparingInt(e -> -e.getValue())).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2)->v1, LinkedHashMap::new));
+
+ Set<String> ignoredTalismans = new HashSet<>();
+ int powderAmount = 0;
+ for (Map.Entry<String, Integer> entry : accessories.entrySet()) {
+ if (ignoredTalismans.contains(entry.getKey())) {
+ continue;
+ }
+
+ JsonArray children = Utils.getElementOrDefault(Constants.PARENTS, entry.getKey(), new JsonArray()).getAsJsonArray();
+ for (JsonElement child : children) {
+ ignoredTalismans.add(child.getAsString());
+ }
+
+ if (entry.getKey().equals("HEGEMONY_ARTIFACT")) {
+ switch (entry.getValue()) {
+ case 4:
+ powderAmount += 16;
+ break;
+ case 5:
+ powderAmount += 22;
+ break;
+ }
+ }
+ switch (entry.getValue()) {
+ case 0:
+ case 6:
+ powderAmount += 3;
+ break;
+ case 1:
+ case 7:
+ powderAmount += 5;
+ break;
+ case 2:
+ powderAmount += 8;
+ break;
+ case 3:
+ powderAmount += 12;
+ break;
+ case 4:
+ powderAmount += 16;
+ break;
+ case 5:
+ powderAmount += 22;
+ break;
+ }
+ }
+ return powderAmount;
+ }
+
+ /**
+ * Finds the Magical Power the player selected if applicable
+ *
+ * @param profileInfo profile information object
+ * @return selected magical power as a String or null
+ * @see io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer.Profile#getProfileInformation(String)
+ */
+ public static @Nullable String getSelectedMagicalPower(JsonObject profileInfo) {
+ String abs = "accessory_bag_storage";
+
+ if (
+ profileInfo == null ||
+ !profileInfo.has(abs) ||
+ !profileInfo.get(abs).isJsonObject() ||
+ !profileInfo.get(abs).getAsJsonObject().has("selected_power")
+ ) {
+ return null;
+ }
+ String selectedPower = profileInfo.get(abs).getAsJsonObject().get("selected_power").getAsString();
+ return selectedPower.substring(0, 1).toUpperCase() + selectedPower.substring(1);
+ }
+
+ public static @Nullable QuiverInfo getQuiverInfo(JsonObject inventoryInfo, JsonObject profileInfo) {
+ if (inventoryInfo == null
+ || !inventoryInfo.has("quiver")
+ || !inventoryInfo.get("quiver").isJsonArray()) {
+ return null;
+ }
+ QuiverInfo quiverInfo = new QuiverInfo();
+ quiverInfo.arrows = new HashMap<>();
+
+ JsonArray quiver = inventoryInfo.getAsJsonArray("quiver");
+ for (JsonElement quiverEntry : quiver) {
+ if (quiverEntry == null || quiverEntry.isJsonNull() || !quiverEntry.isJsonObject()) {
+ continue;
+ }
+ JsonObject stack = quiverEntry.getAsJsonObject();
+ if (!stack.has("internalname") || !stack.has("count")) {
+ continue;
+ }
+ String internalName = stack.get("internalname").getAsString();
+ int count = stack.get("count").getAsInt();
+
+ quiverInfo.arrows.computeIfPresent(internalName, (key, existing) -> existing + count);
+ quiverInfo.arrows.putIfAbsent(internalName, count);
+ }
+
+ if (profileInfo.has("favorite_arrow")) {
+ quiverInfo.selectedArrow = profileInfo.get("favorite_arrow").getAsString();
+ }
+
+ return quiverInfo;
+ }
+
+ public static class Stats {
+
+ JsonObject statsJson = new JsonObject();
+
+ /*public float health;
+ public float defence;
+ public float strength;
+ public float speed;
+ public float crit_chance;
+ public float crit_damage;
+ public float bonus_attack_speed;
+ public float intelligence;
+ public float sea_creature_chance;
+ public float magic_find;
+ public float pet_luck;*/
+
+ public Stats(Stats... statses) {
+ for (Stats stats : statses) {
+ add(stats);
+ }
+ }
+
+ /*@Override
+ public String toString() {
+ return String.format("{health=%s,defence=%s,strength=%s,speed=%s,crit_chance=%s,crit_damage=%s," +
+ "bonus_attack_speed=%s,intelligence=%s,sea_creature_chance=%s,magic_find=%s,pet_luck=%s}",
+ stats.get("health"), defence, strength, speed, crit_chance, crit_damage, bonus_attack_speed, intelligence,
+ sea_creature_chance, magic_find, pet_luck
+ );
+ }*/
+
+ public float get(String statName) {
+ if (statsJson.has(statName)) {
+ return statsJson.get(statName).getAsFloat();
+ } else {
+ return 0;
+ }
+ }
+
+ public Stats add(Stats stats) {
+ for (Map.Entry<String, JsonElement> statEntry : stats.statsJson.entrySet()) {
+ if (statEntry.getValue().isJsonPrimitive() && ((JsonPrimitive) statEntry.getValue()).isNumber()) {
+ if (!statsJson.has(statEntry.getKey())) {
+ statsJson.add(statEntry.getKey(), statEntry.getValue());
+ } else {
+ JsonPrimitive e = statsJson.get(statEntry.getKey()).getAsJsonPrimitive();
+ float statNum = e.getAsFloat() + statEntry.getValue().getAsFloat();
+ statsJson.add(statEntry.getKey(), new JsonPrimitive(statNum));
+ }
+ }
+ }
+ return this;
+ }
+
+ public void scale(String statName, float scale) {
+ if (statsJson.has(statName)) {
+ statsJson.add(statName, new JsonPrimitive(statsJson.get(statName).getAsFloat() * scale));
+ }
+ }
+
+ public void scaleAll(float scale) {
+ for (Map.Entry<String, JsonElement> statEntry : statsJson.entrySet()) {
+ statsJson.add(statEntry.getKey(), new JsonPrimitive(statEntry.getValue().getAsFloat() * scale));
+ }
+ }
+
+ public void addStat(String statName, float amount) {
+ if (!statsJson.has(statName)) {
+ statsJson.add(statName, new JsonPrimitive(amount));
+ } else {
+ JsonPrimitive e = statsJson.get(statName).getAsJsonPrimitive();
+ statsJson.add(statName, new JsonPrimitive(e.getAsFloat() + amount));
+ }
+ }
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
index 674f08af..4aeafb9e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.profileviewer;
import com.google.gson.JsonArray;
@@ -20,230 +39,419 @@ import net.minecraft.util.EnumChatFormatting;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ProfileViewer {
- private final NEUManager manager;
-
- public ProfileViewer(NEUManager manager) {
- this.manager = manager;
- }
-
- private static final HashMap<String, String> petRarityToNumMap = new HashMap<String, String>() {{
- put("COMMON", "0");
- put("UNCOMMON", "1");
- put("RARE", "2");
- put("EPIC", "3");
- put("LEGENDARY", "4");
- put("MYTHIC", "5");
- }};
+ private static final HashMap<String, String> petRarityToNumMap = new HashMap<String, String>() {
+ {
+ put("COMMON", "0");
+ put("UNCOMMON", "1");
+ put("RARE", "2");
+ put("EPIC", "3");
+ put("LEGENDARY", "4");
+ put("MYTHIC", "5");
+ }
+ };
private static final LinkedHashMap<String, ItemStack> skillToSkillDisplayMap =
- new LinkedHashMap<String, ItemStack>() {{
- put("skill_taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE + "Taming"));
- put("skill_mining", Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining"));
- put(
- "skill_foraging",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging")
- );
- put(
- "skill_enchanting",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.enchanting_table), EnumChatFormatting.GREEN + "Enchanting")
- );
- put(
- "skill_carpentry",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.crafting_table), EnumChatFormatting.DARK_RED + "Carpentry")
- );
- put("skill_farming", Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming"));
- put("skill_combat", Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat"));
- put("skill_fishing", Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing"));
- put("skill_alchemy", Utils.createItemStack(Items.brewing_stand, EnumChatFormatting.BLUE + "Alchemy"));
- put(
- "skill_runecrafting",
- Utils.createItemStack(Items.magma_cream, EnumChatFormatting.DARK_PURPLE + "Runecrafting")
- );
- // put("skill_catacombs", Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), EnumChatFormatting.GOLD+"Catacombs"));
- put("slayer_zombie", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.GOLD + "Rev Slayer"));
- put("slayer_spider", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.GOLD + "Tara Slayer"));
- put("slayer_wolf", Utils.createItemStack(Items.bone, EnumChatFormatting.GOLD + "Sven Slayer"));
- put("slayer_enderman", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.GOLD + "Ender Slayer"));
- }};
-
- private static final ItemStack CAT_FARMING =
- Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming");
- private static final ItemStack CAT_MINING =
- Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining");
- private static final ItemStack CAT_COMBAT =
- Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat");
- private static final ItemStack CAT_FORAGING =
- Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging");
- private static final ItemStack CAT_FISHING =
- Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing");
-
+ new LinkedHashMap<String, ItemStack>() {
+ {
+ put("taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE + "Taming"));
+ put("mining", Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY + "Mining"));
+ put(
+ "foraging",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN + "Foraging")
+ );
+ put(
+ "enchanting",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.enchanting_table), EnumChatFormatting.GREEN + "Enchanting")
+ );
+ put(
+ "carpentry",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.crafting_table), EnumChatFormatting.DARK_RED + "Carpentry")
+ );
+ put("farming", Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW + "Farming"));
+ put("combat", Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED + "Combat"));
+ put("fishing", Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA + "Fishing"));
+ put("alchemy", Utils.createItemStack(Items.brewing_stand, EnumChatFormatting.BLUE + "Alchemy"));
+ put("runecrafting", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.DARK_PURPLE + "Runecrafting"));
+ put("social", Utils.createItemStack(Items.emerald, EnumChatFormatting.DARK_GREEN + "Social"));
+ // put("catacombs", Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), EnumChatFormatting.GOLD+"Catacombs"));
+ put("zombie", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.GOLD + "Rev Slayer"));
+ put("spider", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.GOLD + "Tara Slayer"));
+ put("wolf", Utils.createItemStack(Items.bone, EnumChatFormatting.GOLD + "Sven Slayer"));
+ put("enderman", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.GOLD + "Ender Slayer"));
+ put("blaze", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.GOLD + "Blaze Slayer"));
+ }
+ };
+ private static final ItemStack CAT_FARMING = Utils.createItemStack(
+ Items.golden_hoe,
+ EnumChatFormatting.YELLOW + "Farming"
+ );
+ private static final ItemStack CAT_MINING = Utils.createItemStack(
+ Items.stone_pickaxe,
+ EnumChatFormatting.GRAY + "Mining"
+ );
+ private static final ItemStack CAT_COMBAT = Utils.createItemStack(
+ Items.stone_sword,
+ EnumChatFormatting.RED + "Combat"
+ );
+ private static final ItemStack CAT_FORAGING = Utils.createItemStack(
+ Item.getItemFromBlock(Blocks.sapling),
+ EnumChatFormatting.DARK_GREEN + "Foraging"
+ );
+ private static final ItemStack CAT_FISHING = Utils.createItemStack(
+ Items.fishing_rod,
+ EnumChatFormatting.AQUA + "Fishing"
+ );
private static final LinkedHashMap<ItemStack, List<String>> collectionCatToCollectionMap =
- new LinkedHashMap<ItemStack, List<String>>() {{
- put(CAT_FARMING, Utils.createList("WHEAT", "CARROT_ITEM", "POTATO_ITEM", "PUMPKIN", "MELON", "SEEDS",
- "MUSHROOM_COLLECTION", "INK_SACK:3", "CACTUS", "SUGAR_CANE", "FEATHER", "LEATHER", "PORK", "RAW_CHICKEN",
- "MUTTON", "RABBIT", "NETHER_STALK"
- ));
- put(CAT_MINING, Utils.createList("COBBLESTONE", "COAL", "IRON_INGOT", "GOLD_INGOT", "DIAMOND", "INK_SACK:4",
- "EMERALD", "REDSTONE", "QUARTZ", "OBSIDIAN", "GLOWSTONE_DUST", "GRAVEL", "ICE", "NETHERRACK", "SAND",
- "ENDER_STONE", null, "MITHRIL_ORE", "HARD_STONE", "GEMSTONE_COLLECTION"
- ));
- put(CAT_COMBAT, Utils.createList("ROTTEN_FLESH", "BONE", "STRING", "SPIDER_EYE", "SULPHUR", "ENDER_PEARL",
- "GHAST_TEAR", "SLIME_BALL", "BLAZE_ROD", "MAGMA_CREAM", null, null, null
- ));
- put(CAT_FORAGING, Utils.createList("LOG", "LOG:1", "LOG:2", "LOG_2:1", "LOG_2", "LOG:3", null));
- put(CAT_FISHING, Utils.createList("RAW_FISH", "RAW_FISH:1", "RAW_FISH:2", "RAW_FISH:3", "PRISMARINE_SHARD",
- "PRISMARINE_CRYSTALS", "CLAY_BALL", "WATER_LILY", "INK_SACK", "SPONGE"
- ));
-
- }};
-
+ new LinkedHashMap<ItemStack, List<String>>() {
+ {
+ put(
+ CAT_FARMING,
+ Utils.createList(
+ "WHEAT",
+ "CARROT_ITEM",
+ "POTATO_ITEM",
+ "PUMPKIN",
+ "MELON",
+ "SEEDS",
+ "MUSHROOM_COLLECTION",
+ "INK_SACK:3",
+ "CACTUS",
+ "SUGAR_CANE",
+ "FEATHER",
+ "LEATHER",
+ "PORK",
+ "RAW_CHICKEN",
+ "MUTTON",
+ "RABBIT",
+ "NETHER_STALK"
+ )
+ );
+ put(
+ CAT_MINING,
+ Utils.createList(
+ "COBBLESTONE",
+ "COAL",
+ "IRON_INGOT",
+ "GOLD_INGOT",
+ "DIAMOND",
+ "INK_SACK:4",
+ "EMERALD",
+ "REDSTONE",
+ "QUARTZ",
+ "OBSIDIAN",
+ "GLOWSTONE_DUST",
+ "GRAVEL",
+ "ICE",
+ "NETHERRACK",
+ "SAND",
+ "ENDER_STONE",
+ null,
+ "MITHRIL_ORE",
+ "HARD_STONE",
+ "GEMSTONE_COLLECTION",
+ "MYCEL",
+ "SAND:1",
+ "SULPHUR_ORE"
+ )
+ );
+ put(
+ CAT_COMBAT,
+ Utils.createList(
+ "ROTTEN_FLESH",
+ "BONE",
+ "STRING",
+ "SPIDER_EYE",
+ "SULPHUR",
+ "ENDER_PEARL",
+ "GHAST_TEAR",
+ "SLIME_BALL",
+ "BLAZE_ROD",
+ "MAGMA_CREAM",
+ null,
+ null,
+ null,
+ null,
+ "CHILI_PEPPER"
+ )
+ );
+ put(CAT_FORAGING, Utils.createList("LOG", "LOG:1", "LOG:2", "LOG_2:1", "LOG_2", "LOG:3", null));
+ put(
+ CAT_FISHING,
+ Utils.createList(
+ "RAW_FISH",
+ "RAW_FISH:1",
+ "RAW_FISH:2",
+ "RAW_FISH:3",
+ "PRISMARINE_SHARD",
+ "PRISMARINE_CRYSTALS",
+ "CLAY_BALL",
+ "WATER_LILY",
+ "INK_SACK",
+ "SPONGE",
+ "MAGMA_FISH"
+ )
+ );
+ }
+ };
private static final LinkedHashMap<ItemStack, List<String>> collectionCatToMinionMap =
- new LinkedHashMap<ItemStack, List<String>>() {{
- put(CAT_FARMING, Utils.createList("WHEAT", "CARROT", "POTATO", "PUMPKIN", "MELON", null, "MUSHROOM",
- "COCOA", "CACTUS", "SUGAR_CANE", "CHICKEN", "COW", "PIG", null, "SHEEP", "RABBIT", "NETHER_WARTS"
- ));
- put(CAT_MINING, Utils.createList("COBBLESTONE", "COAL", "IRON", "GOLD", "DIAMOND", "LAPIS", "EMERALD",
- "REDSTONE", "QUARTZ", "OBSIDIAN", "GLOWSTONE", "GRAVEL", "ICE", null, "SAND", "ENDER_STONE", "SNOW",
- "MITHRIL", "HARD_STONE", null
- ));
- put(CAT_COMBAT, Utils.createList("ZOMBIE", "SKELETON", "SPIDER", "CAVESPIDER", "CREEPER", "ENDERMAN",
- "GHAST", "SLIME", "BLAZE", "MAGMA_CUBE", "REVENANT", "TARANTULA", "VOIDLING"
- ));
- put(CAT_FORAGING, Utils.createList("OAK", "SPRUCE", "BIRCH", "DARK_OAK", "ACACIA", "JUNGLE", "FLOWER"));
- put(CAT_FISHING, Utils.createList("FISHING", null, null, null, null, null, "CLAY", null, null, null));
-
- }};
-
+ new LinkedHashMap<ItemStack, List<String>>() {
+ {
+ put(
+ CAT_FARMING,
+ Utils.createList(
+ "WHEAT",
+ "CARROT",
+ "POTATO",
+ "PUMPKIN",
+ "MELON",
+ null,
+ "MUSHROOM",
+ "COCOA",
+ "CACTUS",
+ "SUGAR_CANE",
+ "CHICKEN",
+ "COW",
+ "PIG",
+ null,
+ "SHEEP",
+ "RABBIT",
+ "NETHER_WARTS"
+ )
+ );
+ put(
+ CAT_MINING,
+ Utils.createList(
+ "COBBLESTONE",
+ "COAL",
+ "IRON",
+ "GOLD",
+ "DIAMOND",
+ "LAPIS",
+ "EMERALD",
+ "REDSTONE",
+ "QUARTZ",
+ "OBSIDIAN",
+ "GLOWSTONE",
+ "GRAVEL",
+ "ICE",
+ null,
+ "SAND",
+ "ENDER_STONE",
+ "SNOW",
+ "MITHRIL",
+ "HARD_STONE",
+ null,
+ "MYCELIUM",
+ "RED_SAND",
+ null
+ )
+ );
+ put(
+ CAT_COMBAT,
+ Utils.createList(
+ "ZOMBIE",
+ "SKELETON",
+ "SPIDER",
+ "CAVESPIDER",
+ "CREEPER",
+ "ENDERMAN",
+ "GHAST",
+ "SLIME",
+ "BLAZE",
+ "MAGMA_CUBE",
+ "REVENANT",
+ "TARANTULA",
+ "VOIDLING",
+ "INFERNO"
+ )
+ );
+ put(CAT_FORAGING, Utils.createList("OAK", "SPRUCE", "BIRCH", "DARK_OAK", "ACACIA", "JUNGLE", "FLOWER"));
+ put(CAT_FISHING, Utils.createList("FISHING", null, null, null, null, null, "CLAY", null, null, null));
+ }
+ };
private static final LinkedHashMap<String, ItemStack> collectionToCollectionDisplayMap =
- new LinkedHashMap<String, ItemStack>() {{
- /* FARMING COLLECTIONS */
- put("WHEAT", Utils.createItemStack(Items.wheat, EnumChatFormatting.YELLOW + "Wheat"));
- put("CARROT_ITEM", Utils.createItemStack(Items.carrot, EnumChatFormatting.YELLOW + "Carrot"));
- put("POTATO_ITEM", Utils.createItemStack(Items.potato, EnumChatFormatting.YELLOW + "Potato"));
- put(
- "PUMPKIN",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.pumpkin), EnumChatFormatting.YELLOW + "Pumpkin")
- );
- put("MELON", Utils.createItemStack(Items.melon, EnumChatFormatting.YELLOW + "Melon"));
- put("SEEDS", Utils.createItemStack(Items.wheat_seeds, EnumChatFormatting.YELLOW + "Seeds"));
- put(
- "MUSHROOM_COLLECTION",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.red_mushroom), EnumChatFormatting.YELLOW + "Mushroom")
- );
- put("INK_SACK:3", Utils.createItemStack(Items.dye, EnumChatFormatting.YELLOW + "Cocoa Beans", 3));
- put("CACTUS", Utils.createItemStack(Item.getItemFromBlock(Blocks.cactus), EnumChatFormatting.YELLOW + "Cactus"));
- put("SUGAR_CANE", Utils.createItemStack(Items.reeds, EnumChatFormatting.YELLOW + "Sugar Cane"));
- put("FEATHER", Utils.createItemStack(Items.feather, EnumChatFormatting.YELLOW + "Feather"));
- put("LEATHER", Utils.createItemStack(Items.leather, EnumChatFormatting.YELLOW + "Leather"));
- put("PORK", Utils.createItemStack(Items.porkchop, EnumChatFormatting.YELLOW + "Porkchop"));
- put("RAW_CHICKEN", Utils.createItemStack(Items.chicken, EnumChatFormatting.YELLOW + "Chicken"));
- put("MUTTON", Utils.createItemStack(Items.mutton, EnumChatFormatting.YELLOW + "Mutton"));
- put("RABBIT", Utils.createItemStack(Items.rabbit, EnumChatFormatting.YELLOW + "Rabbit"));
- put("NETHER_STALK", Utils.createItemStack(Items.nether_wart, EnumChatFormatting.YELLOW + "Nether Wart"));
-
- /* MINING COLLECTIONS */
- put(
- "COBBLESTONE",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.cobblestone), EnumChatFormatting.GRAY + "Cobblestone")
- );
- put("COAL", Utils.createItemStack(Items.coal, EnumChatFormatting.GRAY + "Coal"));
- put("IRON_INGOT", Utils.createItemStack(Items.iron_ingot, EnumChatFormatting.GRAY + "Iron Ingot"));
- put("GOLD_INGOT", Utils.createItemStack(Items.gold_ingot, EnumChatFormatting.GRAY + "Gold Ingot"));
- put("DIAMOND", Utils.createItemStack(Items.diamond, EnumChatFormatting.GRAY + "Diamond"));
- put("INK_SACK:4", Utils.createItemStack(Items.dye, EnumChatFormatting.GRAY + "Lapis Lazuli", 4));
- put("EMERALD", Utils.createItemStack(Items.emerald, EnumChatFormatting.GRAY + "Emerald"));
- put("REDSTONE", Utils.createItemStack(Items.redstone, EnumChatFormatting.GRAY + "Redstone"));
- put("QUARTZ", Utils.createItemStack(Items.quartz, EnumChatFormatting.GRAY + "Nether Quartz"));
- put(
- "OBSIDIAN",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.obsidian), EnumChatFormatting.GRAY + "Obsidian")
- );
- put("GLOWSTONE_DUST", Utils.createItemStack(Items.glowstone_dust, EnumChatFormatting.GRAY + "Glowstone"));
- put("GRAVEL", Utils.createItemStack(Item.getItemFromBlock(Blocks.gravel), EnumChatFormatting.GRAY + "Gravel"));
- put("ICE", Utils.createItemStack(Item.getItemFromBlock(Blocks.ice), EnumChatFormatting.GRAY + "Ice"));
- put(
- "NETHERRACK",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.netherrack), EnumChatFormatting.GRAY + "Netherrack")
- );
- put("SAND", Utils.createItemStack(Item.getItemFromBlock(Blocks.sand), EnumChatFormatting.GRAY + "Sand"));
- put(
- "ENDER_STONE",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.end_stone), EnumChatFormatting.GRAY + "End Stone")
- );
- put("MITHRIL_ORE", Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.GRAY + "Mithril"));
- put(
- "HARD_STONE",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.stone), EnumChatFormatting.GRAY + "Hard Stone")
- );
- put(
- "GEMSTONE_COLLECTION",
- Utils.createSkull(
- EnumChatFormatting.GRAY + "Gemstone",
- "e942eb66-a350-38e5-aafa-0dfc3e17b4ac",
- "ewogICJ0aW1lc3RhbXAiIDogMTYxODA4Mzg4ODc3MSwKICAicHJvZmlsZUlkIiA6ICJjNTBhZmE4YWJlYjk0ZTQ1OTRiZjFiNDI1YTk4MGYwMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUd29FQmFlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2FhYzE1ZjZmY2YyY2U5NjNlZjRjYTcxZjFhODY4NWFkYjk3ZWI3NjllMWQxMTE5NGNiYmQyZTk2NGE4ODk3OGMiCiAgICB9CiAgfQp9"
- )
- );
+ new LinkedHashMap<String, ItemStack>() {
+ {
+ /* FARMING COLLECTIONS */
+ put("WHEAT", Utils.createItemStack(Items.wheat, EnumChatFormatting.YELLOW + "Wheat"));
+ put("CARROT_ITEM", Utils.createItemStack(Items.carrot, EnumChatFormatting.YELLOW + "Carrot"));
+ put("POTATO_ITEM", Utils.createItemStack(Items.potato, EnumChatFormatting.YELLOW + "Potato"));
+ put(
+ "PUMPKIN",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.pumpkin), EnumChatFormatting.YELLOW + "Pumpkin")
+ );
+ put("MELON", Utils.createItemStack(Items.melon, EnumChatFormatting.YELLOW + "Melon"));
+ put("SEEDS", Utils.createItemStack(Items.wheat_seeds, EnumChatFormatting.YELLOW + "Seeds"));
+ put(
+ "MUSHROOM_COLLECTION",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.red_mushroom), EnumChatFormatting.YELLOW + "Mushroom")
+ );
+ put("INK_SACK:3", Utils.createItemStack(Items.dye, EnumChatFormatting.YELLOW + "Cocoa Beans", 3));
+ put(
+ "CACTUS",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.cactus), EnumChatFormatting.YELLOW + "Cactus")
+ );
+ put("SUGAR_CANE", Utils.createItemStack(Items.reeds, EnumChatFormatting.YELLOW + "Sugar Cane"));
+ put("FEATHER", Utils.createItemStack(Items.feather, EnumChatFormatting.YELLOW + "Feather"));
+ put("LEATHER", Utils.createItemStack(Items.leather, EnumChatFormatting.YELLOW + "Leather"));
+ put("PORK", Utils.createItemStack(Items.porkchop, EnumChatFormatting.YELLOW + "Raw Porkchop"));
+ put("RAW_CHICKEN", Utils.createItemStack(Items.chicken, EnumChatFormatting.YELLOW + "Raw Chicken"));
+ put("MUTTON", Utils.createItemStack(Items.mutton, EnumChatFormatting.YELLOW + "Mutton"));
+ put("RABBIT", Utils.createItemStack(Items.rabbit, EnumChatFormatting.YELLOW + "Raw Rabbit"));
+ put("NETHER_STALK", Utils.createItemStack(Items.nether_wart, EnumChatFormatting.YELLOW + "Nether Wart"));
+
+ /* MINING COLLECTIONS */
+ put(
+ "COBBLESTONE",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.cobblestone), EnumChatFormatting.GRAY + "Cobblestone")
+ );
+ put("COAL", Utils.createItemStack(Items.coal, EnumChatFormatting.GRAY + "Coal"));
+ put("IRON_INGOT", Utils.createItemStack(Items.iron_ingot, EnumChatFormatting.GRAY + "Iron Ingot"));
+ put("GOLD_INGOT", Utils.createItemStack(Items.gold_ingot, EnumChatFormatting.GRAY + "Gold Ingot"));
+ put("DIAMOND", Utils.createItemStack(Items.diamond, EnumChatFormatting.GRAY + "Diamond"));
+ put("INK_SACK:4", Utils.createItemStack(Items.dye, EnumChatFormatting.GRAY + "Lapis Lazuli", 4));
+ put("EMERALD", Utils.createItemStack(Items.emerald, EnumChatFormatting.GRAY + "Emerald"));
+ put("REDSTONE", Utils.createItemStack(Items.redstone, EnumChatFormatting.GRAY + "Redstone"));
+ put("QUARTZ", Utils.createItemStack(Items.quartz, EnumChatFormatting.GRAY + "Nether Quartz"));
+ put(
+ "OBSIDIAN",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.obsidian), EnumChatFormatting.GRAY + "Obsidian")
+ );
+ put("GLOWSTONE_DUST", Utils.createItemStack(Items.glowstone_dust, EnumChatFormatting.GRAY + "Glowstone Dust"));
+ put("GRAVEL", Utils.createItemStack(Item.getItemFromBlock(Blocks.gravel), EnumChatFormatting.GRAY + "Gravel"));
+ put("ICE", Utils.createItemStack(Item.getItemFromBlock(Blocks.ice), EnumChatFormatting.GRAY + "Ice"));
+ put(
+ "NETHERRACK",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.netherrack), EnumChatFormatting.GRAY + "Netherrack")
+ );
+ put("SAND", Utils.createItemStack(Item.getItemFromBlock(Blocks.sand), EnumChatFormatting.GRAY + "Sand"));
+ put(
+ "ENDER_STONE",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.end_stone), EnumChatFormatting.GRAY + "End Stone")
+ );
+ put("MITHRIL_ORE", Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.GRAY + "Mithril"));
+ put(
+ "HARD_STONE",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.stone), EnumChatFormatting.GRAY + "Hard Stone")
+ );
+ put(
+ "GEMSTONE_COLLECTION",
+ Utils.createSkull(
+ EnumChatFormatting.GRAY + "Gemstone",
+ "e942eb66-a350-38e5-aafa-0dfc3e17b4ac",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYxODA4Mzg4ODc3MSwKICAicHJvZmlsZUlkIiA6ICJjNTBhZmE4YWJlYjk0ZTQ1OTRiZjFiNDI1YTk4MGYwMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUd29FQmFlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2FhYzE1ZjZmY2YyY2U5NjNlZjRjYTcxZjFhODY4NWFkYjk3ZWI3NjllMWQxMTE5NGNiYmQyZTk2NGE4ODk3OGMiCiAgICB9CiAgfQp9"
+ )
+ );
+ put(
+ "MYCEL",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.mycelium), EnumChatFormatting.GRAY + "Mycelium")
+ );
+ put(
+ "SAND:1",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.sand), EnumChatFormatting.GRAY + "Red Sand", 1)
+ );
+ put("SULPHUR_ORE", Utils.createItemStack(Items.glowstone_dust, EnumChatFormatting.GRAY + "Sulphur"));
+
+ /* COMBAT COLLECTIONS */
+ put("ROTTEN_FLESH", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.RED + "Rotten Flesh"));
+ put("BONE", Utils.createItemStack(Items.bone, EnumChatFormatting.RED + "Bone"));
+ put("STRING", Utils.createItemStack(Items.string, EnumChatFormatting.RED + "String"));
+ put("SPIDER_EYE", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.RED + "Spider Eye"));
+ put("SULPHUR", Utils.createItemStack(Items.gunpowder, EnumChatFormatting.RED + "Gunpowder"));
+ put("ENDER_PEARL", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.RED + "Ender Pearl"));
+ put("GHAST_TEAR", Utils.createItemStack(Items.ghast_tear, EnumChatFormatting.RED + "Ghast Tear"));
+ put("SLIME_BALL", Utils.createItemStack(Items.slime_ball, EnumChatFormatting.RED + "Slimeball"));
+ put("BLAZE_ROD", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.RED + "Blaze Rod"));
+ put("MAGMA_CREAM", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.RED + "Magma Cream"));
+ put(
+ "CHILI_PEPPER",
+ Utils.createSkull(
+ EnumChatFormatting.RED + "Chili Pepper",
+ "3d47abaa-b40b-3826-b20c-d83a7f053bd9",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjg1OWM4ZGYxMTA5YzA4YTc1NjI3NWYxZDI4ODdjMjc0ODA0OWZlMzM4Nzc3NjlhN2I0MTVkNTZlZGE0NjlkOCJ9fX0"
+ )
+ );
- /* COMBAT COLLECTIONS */
- put("ROTTEN_FLESH", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.RED + "Rotten Flesh"));
- put("BONE", Utils.createItemStack(Items.bone, EnumChatFormatting.RED + "Bone"));
- put("STRING", Utils.createItemStack(Items.string, EnumChatFormatting.RED + "String"));
- put("SPIDER_EYE", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.RED + "Spider Eye"));
- put("SULPHUR", Utils.createItemStack(Items.gunpowder, EnumChatFormatting.RED + "Gunpowder"));
- put("ENDER_PEARL", Utils.createItemStack(Items.ender_pearl, EnumChatFormatting.RED + "Ender Pearl"));
- put("GHAST_TEAR", Utils.createItemStack(Items.ghast_tear, EnumChatFormatting.RED + "Ghast Tear"));
- put("SLIME_BALL", Utils.createItemStack(Items.slime_ball, EnumChatFormatting.RED + "Slimeball"));
- put("BLAZE_ROD", Utils.createItemStack(Items.blaze_rod, EnumChatFormatting.RED + "Blaze Rod"));
- put("MAGMA_CREAM", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.RED + "Magma Cream"));
-
- /* FORAGING COLLECTIONS */
- put("LOG", Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Oak"));
- put(
- "LOG:1",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Spruce", 1)
- );
- put(
- "LOG:2",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Birch", 2)
- );
- put(
- "LOG_2:1",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Dark Oak", 1)
- );
- put("LOG_2", Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Acacia"));
- put(
- "LOG:3",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Jungle", 3)
- );
+ /* FORAGING COLLECTIONS */
+ put(
+ "LOG",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Oak Wood")
+ );
+ put(
+ "LOG:1",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Spruce Wood", 1)
+ );
+ put(
+ "LOG:2",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Birch Wood", 2)
+ );
+ put(
+ "LOG_2:1",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Dark Oak Wood", 1)
+ );
+ put(
+ "LOG_2",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log2), EnumChatFormatting.DARK_GREEN + "Acacia Wood")
+ );
+ put(
+ "LOG:3",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.log), EnumChatFormatting.DARK_GREEN + "Jungle Wood", 3)
+ );
- /* FISHING COLLECTIONS */
- put("RAW_FISH", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Fish"));
- put("RAW_FISH:1", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Salmon", 1));
- put("RAW_FISH:2", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Clownfish", 2));
- put("RAW_FISH:3", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Pufferfish", 3));
- put(
- "PRISMARINE_SHARD",
- Utils.createItemStack(Items.prismarine_shard, EnumChatFormatting.AQUA + "Prismarine Shard")
- );
- put(
- "PRISMARINE_CRYSTALS",
- Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.AQUA + "Prismarine Crystals")
- );
- put("CLAY_BALL", Utils.createItemStack(Items.clay_ball, EnumChatFormatting.AQUA + "Clay"));
- put(
- "WATER_LILY",
- Utils.createItemStack(Item.getItemFromBlock(Blocks.waterlily), EnumChatFormatting.AQUA + "Lilypad")
- );
- put("INK_SACK", Utils.createItemStack(Items.dye, EnumChatFormatting.AQUA + "Ink Sack"));
- put("SPONGE", Utils.createItemStack(Item.getItemFromBlock(Blocks.sponge), EnumChatFormatting.AQUA + "Sponge"));
- }};
+ /* FISHING COLLECTIONS */
+ put("RAW_FISH", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Raw Fish"));
+ put("RAW_FISH:1", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Raw Salmon", 1));
+ put("RAW_FISH:2", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Clownfish", 2));
+ put("RAW_FISH:3", Utils.createItemStack(Items.fish, EnumChatFormatting.AQUA + "Pufferfish", 3));
+ put(
+ "PRISMARINE_SHARD",
+ Utils.createItemStack(Items.prismarine_shard, EnumChatFormatting.AQUA + "Prismarine Shard")
+ );
+ put(
+ "PRISMARINE_CRYSTALS",
+ Utils.createItemStack(Items.prismarine_crystals, EnumChatFormatting.AQUA + "Prismarine Crystals")
+ );
+ put("CLAY_BALL", Utils.createItemStack(Items.clay_ball, EnumChatFormatting.AQUA + "Clay"));
+ put(
+ "WATER_LILY",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.waterlily), EnumChatFormatting.AQUA + "Lily Pad")
+ );
+ put("INK_SACK", Utils.createItemStack(Items.dye, EnumChatFormatting.AQUA + "Ink Sac"));
+ put("SPONGE", Utils.createItemStack(Item.getItemFromBlock(Blocks.sponge), EnumChatFormatting.AQUA + "Sponge"));
+ put(
+ "MAGMA_FISH",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Magmafish",
+ "5c53195c-5b98-3476-9731-c32647b22723",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0MjQ4ODA3MDY2NiwKICAicHJvZmlsZUlkIiA6ICIzNDkxZjJiOTdjMDE0MWE2OTM2YjFjMjJhMmEwMGZiNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJKZXNzc3N1aGgiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjU2YjU5NTViMjk1NTIyYzk2ODk0ODE5NjBjMDFhOTkyY2ExYzc3NTRjZjRlZTMxM2M4ZGQwYzM1NmQzMzVmIgogICAgfQogIH0KfQ"
+ )
+ );
+ }
+ };
+ private static final AtomicBoolean updatingResourceCollection = new AtomicBoolean(false);
+ private static JsonObject resourceCollection = null;
+ private final NEUManager manager;
+ private final HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>();
+ private final HashMap<String, Profile> uuidToProfileMap = new HashMap<>();
+ private final HashMap<String, String> nameToUuid = new HashMap<>();
+
+ public ProfileViewer(NEUManager manager) {
+ this.manager = manager;
+ }
public static LinkedHashMap<ItemStack, List<String>> getCollectionCatToMinionMap() {
return collectionCatToMinionMap;
@@ -261,105 +469,262 @@ public class ProfileViewer {
return Collections.unmodifiableMap(skillToSkillDisplayMap);
}
- public static class Level {
- public float level = 0;
- public float maxXpForLevel = 0;
- public boolean maxed = false;
- public double totalXp;
- }
-
public static Level getLevel(JsonArray levelingArray, float xp, int levelCap, boolean cumulative) {
Level levelObj = new Level();
+ levelObj.totalXp = xp;
+ levelObj.maxLevel = levelCap;
+
for (int level = 0; level < levelingArray.size(); level++) {
float levelXp = levelingArray.get(level).getAsFloat();
+
if (levelXp > xp) {
if (cumulative) {
- float previous = 0;
- if (level > 0) previous = levelingArray.get(level - 1).getAsFloat();
+ float previous = level > 0 ? levelingArray.get(level - 1).getAsFloat() : 0;
levelObj.maxXpForLevel = (levelXp - previous);
levelObj.level = 1 + level + (xp - levelXp) / levelObj.maxXpForLevel;
} else {
levelObj.maxXpForLevel = levelXp;
levelObj.level = level + xp / levelXp;
}
+
if (levelObj.level > levelCap) {
levelObj.level = levelCap;
levelObj.maxed = true;
}
+
return levelObj;
} else {
- if (!cumulative) xp -= levelXp;
+ if (!cumulative) {
+ xp -= levelXp;
+ }
}
}
- levelObj.level = levelingArray.size();
- if (levelObj.level > levelCap) {
- levelObj.level = levelCap;
- }
+
+ levelObj.level = Math.min(levelingArray.size(), levelCap);
levelObj.maxed = true;
return levelObj;
}
- public class Profile {
- private final String uuid;
- private String latestProfile = null;
+ public static JsonObject getResourceCollectionInformation() {
+ if (resourceCollection != null) return resourceCollection;
+ if (updatingResourceCollection.get()) return null;
- private JsonArray playerInformation = null;
- private JsonObject guildInformation = null;
- private JsonObject basicInfo = null;
+ updatingResourceCollection.set(true);
+
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newHypixelApiRequest("resources/skyblock/collections")
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ updatingResourceCollection.set(false);
+ if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ resourceCollection = jsonObject.get("collections").getAsJsonObject();
+ }
+ });
+ return null;
+ }
+
+ public void getHypixelProfile(String name, Consumer<JsonObject> callback) {
+ String nameF = name.toLowerCase();
+ manager.apiUtils
+ .newHypixelApiRequest("player")
+ .queryArgument("name", nameF)
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (
+ jsonObject != null &&
+ jsonObject.has("success") &&
+ jsonObject.get("success").getAsBoolean() &&
+ jsonObject.get("player").isJsonObject()
+ ) {
+ nameToUuid.put(nameF, jsonObject.get("player").getAsJsonObject().get("uuid").getAsString());
+ uuidToHypixelProfile.put(
+ jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(),
+ jsonObject.get("player").getAsJsonObject()
+ );
+ if (callback != null) callback.accept(jsonObject);
+ } else {
+ if (callback != null) callback.accept(null);
+ }
+ }
+ );
+ }
+
+ public void putNameUuid(String name, String uuid) {
+ nameToUuid.put(name, uuid);
+ }
+ public void getPlayerUUID(String name, Consumer<String> uuidCallback) {
+ String nameF = name.toLowerCase();
+ if (nameToUuid.containsKey(nameF)) {
+ uuidCallback.accept(nameToUuid.get(nameF));
+ return;
+ }
+
+ manager.apiUtils
+ .request()
+ .url("https://api.mojang.com/users/profiles/minecraft/" + nameF)
+ .requestJson()
+ .thenAccept(jsonObject -> {
+ if (jsonObject.has("id") && jsonObject.get("id").isJsonPrimitive() &&
+ ((JsonPrimitive) jsonObject.get("id")).isString()) {
+ String uuid = jsonObject.get("id").getAsString();
+ nameToUuid.put(nameF, uuid);
+ uuidCallback.accept(uuid);
+ return;
+ }
+ uuidCallback.accept(null);
+ });
+ }
+
+ public void getProfileByName(String name, Consumer<Profile> callback) {
+ String nameF = name.toLowerCase();
+
+ if (nameToUuid.containsKey(nameF) && nameToUuid.get(nameF) == null) {
+ callback.accept(null);
+ return;
+ }
+
+ getPlayerUUID(
+ nameF,
+ uuid -> {
+ if (uuid == null) {
+ getHypixelProfile(
+ nameF,
+ jsonObject -> {
+ if (jsonObject != null) {
+ callback.accept(getProfileReset(nameToUuid.get(nameF), ignored -> {}));
+ } else {
+ callback.accept(null);
+ nameToUuid.put(nameF, null);
+ }
+ }
+ );
+ } else {
+ if (!uuidToHypixelProfile.containsKey(uuid)) {
+ getHypixelProfile(nameF, jsonObject -> {});
+ }
+ callback.accept(getProfileReset(uuid, ignored -> {}));
+ }
+ }
+ );
+ }
+
+ public Profile getProfile(String uuid, Consumer<Profile> callback) {
+ Profile profile = uuidToProfileMap.computeIfAbsent(uuid, k -> new Profile(uuid));
+ if (profile.skyblockProfiles != null) {
+ callback.accept(profile);
+ } else {
+ profile.getSkyblockProfiles(() -> callback.accept(profile));
+ }
+ return profile;
+ }
+
+ public Profile getProfileReset(String uuid, Consumer<Profile> callback) {
+ if (uuidToProfileMap.containsKey(uuid)) uuidToProfileMap.get(uuid).resetCache();
+ return getProfile(uuid, callback);
+ }
+
+ public static class Level {
+
+ public float level = 0;
+ public float maxXpForLevel = 0;
+ public boolean maxed = false;
+ public int maxLevel;
+ public float totalXp;
+ }
+
+ public class Profile {
+
+ private final String uuid;
private final HashMap<String, JsonObject> profileMap = new HashMap<>();
private final HashMap<String, JsonObject> petsInfoMap = new HashMap<>();
private final HashMap<String, List<JsonObject>> coopProfileMap = new HashMap<>();
- private final HashMap<String, JsonObject> skillInfoMap = new HashMap<>();
- private final HashMap<String, JsonObject> inventoryInfoMap = new HashMap<>();
+ private final HashMap<String, Map<String, Level>> skyblockInfoCache = new HashMap<>();
+ private final HashMap<String, JsonObject> inventoryCacheMap = new HashMap<>();
private final HashMap<String, JsonObject> collectionInfoMap = new HashMap<>();
- private final List<String> profileIds = new ArrayList<>();
- private JsonObject playerStatus = null;
+ private final List<String> profileNames = new ArrayList<>();
private final HashMap<String, PlayerStats.Stats> stats = new HashMap<>();
private final HashMap<String, PlayerStats.Stats> passiveStats = new HashMap<>();
private final HashMap<String, Long> networth = new HashMap<>();
+ private final AtomicBoolean updatingSkyblockProfilesState = new AtomicBoolean(false);
+ private final AtomicBoolean updatingGuildInfoState = new AtomicBoolean(false);
+ private final AtomicBoolean updatingPlayerStatusState = new AtomicBoolean(false);
+ private final AtomicBoolean updatingBingoInfo = new AtomicBoolean(false);
+ private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?\\d+)");
+ private String latestProfile = null;
+ private JsonArray skyblockProfiles = null;
+ private JsonObject guildInformation = null;
+ private JsonObject playerStatus = null;
+ private JsonObject bingoInformation = null;
+ private long lastPlayerInfoState = 0;
+ private long lastStatusInfoState = 0;
+ private long lastGuildInfoState = 0;
+ private long lastBingoInfoState = 0;
public Profile(String uuid) {
this.uuid = uuid;
}
- private final AtomicBoolean updatingPlayerInfoState = new AtomicBoolean(false);
- private long lastPlayerInfoState = 0;
- private final AtomicBoolean updatingPlayerStatusState = new AtomicBoolean(false);
- private final AtomicBoolean updatingGuildInfoState = new AtomicBoolean(false);
- private long lastGuildInfoState = 0;
- private final AtomicBoolean updatingGuildStatusState = new AtomicBoolean(false);
-
public JsonObject getPlayerStatus() {
if (playerStatus != null) return playerStatus;
if (updatingPlayerStatusState.get()) return null;
+ long currentTime = System.currentTimeMillis();
+ if (currentTime - lastStatusInfoState < 15 * 1000) return null;
+ lastStatusInfoState = currentTime;
updatingPlayerStatusState.set(true);
HashMap<String, String> args = new HashMap<>();
args.put("uuid", "" + uuid);
- manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, "status",
- args, jsonObject -> {
- if (jsonObject == null) return;
-
+ manager.apiUtils
+ .newHypixelApiRequest("status")
+ .queryArgument("uuid", "" + uuid)
+ .requestJson()
+ .handle((jsonObject, ex) -> {
updatingPlayerStatusState.set(false);
- if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+
+ if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
playerStatus = jsonObject.get("session").getAsJsonObject();
}
- }, () -> updatingPlayerStatusState.set(false)
- );
-
+ return null;
+ });
return null;
}
- public long getNetWorth(String profileId) {
- if (profileId == null) profileId = latestProfile;
- if (networth.get(profileId) != null) return networth.get(profileId);
- if (getProfileInformation(profileId) == null) return -1;
- if (getInventoryInfo(profileId) == null) return -1;
+ public JsonObject getBingoInformation() {
+ long currentTime = System.currentTimeMillis();
+ if (bingoInformation != null && currentTime - lastBingoInfoState < 15 * 1000) return bingoInformation;
+ if (updatingBingoInfo.get() && bingoInformation != null) return bingoInformation;
+ if (updatingBingoInfo.get() && bingoInformation == null) return null;
+
+ lastBingoInfoState = currentTime;
+ updatingBingoInfo.set(true);
+
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newHypixelApiRequest("skyblock/bingo")
+ .queryArgument("uuid", "" + uuid)
+ .requestJson()
+ .handle(((jsonObject, throwable) -> {
+ updatingBingoInfo.set(false);
+
+ if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ bingoInformation = jsonObject;
+ } else {
+ bingoInformation = null;
+ }
+ return null;
+ }));
+ return bingoInformation != null ? bingoInformation : null;
+ }
+
+ public long getNetWorth(String profileName) {
+ if (profileName == null) profileName = latestProfile;
+ if (networth.get(profileName) != null) return networth.get(profileName);
+ if (getProfileInformation(profileName) == null) return -1;
+ if (getInventoryInfo(profileName) == null) return -1;
- JsonObject inventoryInfo = getInventoryInfo(profileId);
- JsonObject profileInfo = getProfileInformation(profileId);
+ JsonObject inventoryInfo = getInventoryInfo(profileName);
+ JsonObject profileInfo = getProfileInformation(profileName);
HashMap<String, Long> mostExpensiveInternal = new HashMap<>();
@@ -375,11 +740,11 @@ public class ProfileViewer {
JsonObject bzInfo = manager.auctionManager.getBazaarInfo(internalname);
- int auctionPrice;
+ long auctionPrice;
if (bzInfo != null && bzInfo.has("curr_sell")) {
auctionPrice = (int) bzInfo.get("curr_sell").getAsFloat();
} else {
- auctionPrice = (int) manager.auctionManager.getItemAvgBin(internalname);
+ auctionPrice = (long) manager.auctionManager.getItemAvgBin(internalname);
if (auctionPrice <= 0) {
auctionPrice = manager.auctionManager.getLowestBin(internalname);
}
@@ -403,11 +768,11 @@ public class ProfileViewer {
JsonObject bzInfo2 = manager.auctionManager.getBazaarInfo(internalname2);
- int auctionPrice2;
+ long auctionPrice2;
if (bzInfo2 != null && bzInfo2.has("curr_sell")) {
auctionPrice2 = (int) bzInfo2.get("curr_sell").getAsFloat();
} else {
- auctionPrice2 = (int) manager.auctionManager.getItemAvgBin(internalname2);
+ auctionPrice2 = (long) manager.auctionManager.getItemAvgBin(internalname2);
if (auctionPrice2 <= 0) {
auctionPrice2 = manager.auctionManager.getLowestBin(internalname2);
}
@@ -442,14 +807,9 @@ public class ProfileViewer {
}
if (networth == 0) return -1;
- //System.out.println(profileId);
- //for (Map.Entry<String, Long> entry : mostExpensiveInternal.entrySet()) {
- //System.out.println(entry.getKey() + ":" + entry.getValue());
- //}
-
networth = (int) (networth * 1.3f);
- JsonObject petsInfo = getPetsInfo(profileId);
+ JsonObject petsInfo = getPetsInfo(profileName);
if (petsInfo != null && petsInfo.has("pets")) {
if (petsInfo.get("pets").isJsonArray()) {
JsonArray pets = petsInfo.get("pets").getAsJsonArray();
@@ -478,7 +838,7 @@ public class ProfileViewer {
networth += bankBalance + purseBalance;
- this.networth.put(profileId, networth);
+ this.networth.put(profileName, networth);
return networth;
}
@@ -486,33 +846,33 @@ public class ProfileViewer {
return latestProfile;
}
- public JsonArray getPlayerInformation(Runnable runnable) {
- if (playerInformation != null) return playerInformation;
+ public JsonArray getSkyblockProfiles(Runnable runnable) {
+ if (skyblockProfiles != null) return skyblockProfiles;
long currentTime = System.currentTimeMillis();
- if (currentTime - lastPlayerInfoState < 15 * 1000 && updatingPlayerInfoState.get()) return null;
-
+ if (currentTime - lastPlayerInfoState < 15 * 1000 && updatingSkyblockProfilesState.get()) return null;
lastPlayerInfoState = currentTime;
- updatingPlayerInfoState.set(true);
+ updatingSkyblockProfilesState.set(true);
- HashMap<String, String> args = new HashMap<>();
- args.put("uuid", "" + uuid);
- manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, "skyblock/profiles",
- args, jsonObject -> {
- updatingPlayerInfoState.set(false);
+ manager.apiUtils
+ .newHypixelApiRequest("skyblock/profiles")
+ .queryArgument("uuid", "" + uuid)
+ .requestJson()
+ .handle((jsonObject, throwable) -> {
+ updatingSkyblockProfilesState.set(false);
+
+ if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ if (!jsonObject.has("profiles")) return null;
+ skyblockProfiles = jsonObject.get("profiles").getAsJsonArray();
- if (jsonObject == null) return;
- if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
- playerInformation = jsonObject.get("profiles").getAsJsonArray();
- if (playerInformation == null) return;
- String backup = null;
- long backupLastSave = 0;
+ String lastCuteName = null;
+ long lastLastSave = 0;
- profileIds.clear();
+ profileNames.clear();
- for (int i = 0; i < playerInformation.size(); i++) {
- JsonObject profile = playerInformation.get(i).getAsJsonObject();
+ for (JsonElement profileEle : skyblockProfiles) {
+ JsonObject profile = profileEle.getAsJsonObject();
if (!profile.has("members")) continue;
JsonObject members = profile.get("members").getAsJsonObject();
@@ -521,80 +881,81 @@ public class ProfileViewer {
JsonObject member = members.get(uuid).getAsJsonObject();
if (member.has("coop_invitation")) {
- JsonObject coop_invitation = member.get("coop_invitation").getAsJsonObject();
- if (!coop_invitation.get("confirmed").getAsBoolean()) {
+ if (!member.get("coop_invitation").getAsJsonObject().get("confirmed").getAsBoolean()) {
continue;
}
}
- String cute_name = profile.get("cute_name").getAsString();
- if (backup == null) backup = cute_name;
- profileIds.add(cute_name);
+ String cuteName = profile.get("cute_name").getAsString();
+ profileNames.add(cuteName);
+ if (profile.has("selected") && profile.get("selected").getAsBoolean()) {
+ lastCuteName = cuteName;
+ break;
+ }
+ if (lastCuteName == null) lastCuteName = cuteName;
if (member.has("last_save")) {
- long last_save = member.get("last_save").getAsLong();
- if (last_save > backupLastSave) {
- backupLastSave = last_save;
- backup = cute_name;
+ long lastSave = member.get("last_save").getAsLong();
+ if (lastSave > lastLastSave) {
+ lastLastSave = lastSave;
+ lastCuteName = cuteName;
}
}
-
}
}
- latestProfile = backup;
+ latestProfile = lastCuteName;
+
if (runnable != null) runnable.run();
}
- }, () -> updatingPlayerInfoState.set(false)
- );
-
+ return null;
+ });
return null;
}
- public JsonObject getGuildInfo(Runnable runnable) {
+ public JsonObject getGuildInformation(Runnable runnable) {
if (guildInformation != null) return guildInformation;
long currentTime = System.currentTimeMillis();
if (currentTime - lastGuildInfoState < 15 * 1000 && updatingGuildInfoState.get()) return null;
-
lastGuildInfoState = currentTime;
updatingGuildInfoState.set(true);
- HashMap<String, String> args = new HashMap<>();
- args.put("player", "" + uuid);
- manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, "guild",
- args, jsonObject -> {
+ manager.apiUtils
+ .newHypixelApiRequest("guild")
+ .queryArgument("player", "" + uuid)
+ .requestJson()
+ .handle((jsonObject, ex) -> {
updatingGuildInfoState.set(false);
- if (jsonObject == null) return;
- if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ if (!jsonObject.has("guild")) return null;
+
guildInformation = jsonObject.get("guild").getAsJsonObject();
- if (guildInformation == null) return;
+
if (runnable != null) runnable.run();
}
- }, () -> updatingGuildInfoState.set(false)
- );
-
+ return null;
+ });
return null;
}
- public List<String> getProfileIds() {
- return profileIds;
+ public List<String> getProfileNames() {
+ return profileNames;
}
- public JsonObject getProfileInformation(String profileId) {
- JsonArray playerInfo = getPlayerInformation(() -> {
- });
+ public JsonObject getProfileInformation(String profileName) {
+ JsonArray playerInfo = getSkyblockProfiles(() -> {});
if (playerInfo == null) return null;
- if (profileId == null) profileId = latestProfile;
- if (profileMap.containsKey(profileId)) return profileMap.get(profileId);
+ if (profileName == null) profileName = latestProfile;
+ if (profileMap.containsKey(profileName)) return profileMap.get(profileName);
- for (int i = 0; i < playerInformation.size(); i++) {
- if (!playerInformation.get(i).isJsonObject()) {
- playerInformation = null;
+ for (int i = 0; i < skyblockProfiles.size(); i++) {
+ if (!skyblockProfiles.get(i).isJsonObject()) {
+ skyblockProfiles = null;
return null;
}
- JsonObject profile = playerInformation.get(i).getAsJsonObject();
- if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) {
+ JsonObject profile = skyblockProfiles.get(i).getAsJsonObject();
+ if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) {
if (!profile.has("members")) return null;
JsonObject members = profile.get("members").getAsJsonObject();
if (!members.has(uuid)) continue;
@@ -605,7 +966,7 @@ public class ProfileViewer {
if (profile.has("game_mode")) {
profileInfo.add("game_mode", profile.get("game_mode"));
}
- profileMap.put(profileId, profileInfo);
+ profileMap.put(profileName, profileInfo);
return profileInfo;
}
}
@@ -613,20 +974,19 @@ public class ProfileViewer {
return null;
}
- public List<JsonObject> getCoopProfileInformation(String profileId) {
- JsonArray playerInfo = getPlayerInformation(() -> {
- });
+ public List<JsonObject> getCoopProfileInformation(String profileName) {
+ JsonArray playerInfo = getSkyblockProfiles(() -> {});
if (playerInfo == null) return null;
- if (profileId == null) profileId = latestProfile;
- if (coopProfileMap.containsKey(profileId)) return coopProfileMap.get(profileId);
+ if (profileName == null) profileName = latestProfile;
+ if (coopProfileMap.containsKey(profileName)) return coopProfileMap.get(profileName);
- for (int i = 0; i < playerInformation.size(); i++) {
- if (!playerInformation.get(i).isJsonObject()) {
- playerInformation = null;
+ for (int i = 0; i < skyblockProfiles.size(); i++) {
+ if (!skyblockProfiles.get(i).isJsonObject()) {
+ skyblockProfiles = null;
return null;
}
- JsonObject profile = playerInformation.get(i).getAsJsonObject();
- if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) {
+ JsonObject profile = skyblockProfiles.get(i).getAsJsonObject();
+ if (profile.get("cute_name").getAsString().equalsIgnoreCase(profileName)) {
if (!profile.has("members")) return null;
JsonObject members = profile.get("members").getAsJsonObject();
if (!members.has(uuid)) return null;
@@ -637,7 +997,7 @@ public class ProfileViewer {
coopList.add(coopProfileInfo);
}
}
- coopProfileMap.put(profileId, coopList);
+ coopProfileMap.put(profileName, coopList);
return coopList;
}
}
@@ -646,203 +1006,145 @@ public class ProfileViewer {
}
public void resetCache() {
- playerInformation = null;
+ skyblockProfiles = null;
guildInformation = null;
- basicInfo = null;
playerStatus = null;
stats.clear();
passiveStats.clear();
- profileIds.clear();
+ profileNames.clear();
profileMap.clear();
coopProfileMap.clear();
petsInfoMap.clear();
- skillInfoMap.clear();
- inventoryInfoMap.clear();
+ skyblockInfoCache.clear();
+ inventoryCacheMap.clear();
collectionInfoMap.clear();
networth.clear();
}
public int getCap(JsonObject leveling, String skillName) {
JsonElement capsElement = Utils.getElement(leveling, "leveling_caps");
- if (capsElement == null || !capsElement.isJsonObject()) {
- return 50;
- }
- JsonObject caps = capsElement.getAsJsonObject();
- if (caps.has(skillName)) {
- return caps.get(skillName).getAsInt();
- }
- return 50;
+ return capsElement != null && capsElement.isJsonObject() && capsElement.getAsJsonObject().has(skillName)
+ ? capsElement.getAsJsonObject().get(skillName).getAsInt()
+ : 50;
}
- public JsonObject getSkillInfo(String profileId) {
- JsonObject profileInfo = getProfileInformation(profileId);
+ public Map<String, Level> getSkyblockInfo(String profileName) {
+ JsonObject profileInfo = getProfileInformation(profileName);
+
if (profileInfo == null) return null;
- if (profileId == null) profileId = latestProfile;
- if (skillInfoMap.containsKey(profileId)) return skillInfoMap.get(profileId);
+ if (profileName == null) profileName = latestProfile;
+ if (skyblockInfoCache.containsKey(profileName)) return skyblockInfoCache.get(profileName);
+
JsonObject leveling = Constants.LEVELING;
- if (leveling == null) return null;
-
- float experience_skill_taming =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_taming"), 0);
- float experience_skill_mining =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_mining"), 0);
- float experience_skill_foraging =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_foraging"), 0);
- float experience_skill_enchanting =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_enchanting"), 0);
- float experience_skill_carpentry =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_carpentry"), 0);
- float experience_skill_farming =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_farming"), 0);
- float experience_skill_combat =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_combat"), 0);
- float experience_skill_fishing =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_fishing"), 0);
- float experience_skill_alchemy =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_alchemy"), 0);
- float experience_skill_runecrafting =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_runecrafting"), 0);
- float experience_skill_hotm = Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0);
-
- float experience_skill_catacombs =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0);
-
- float experience_slayer_zombie =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.zombie.xp"), 0);
- float experience_slayer_spider =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.spider.xp"), 0);
- float experience_slayer_wolf = Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.wolf.xp"), 0);
- float experience_slayer_enderman =
- Utils.getElementAsFloat(Utils.getElement(profileInfo, "slayer_bosses.enderman.xp"), 0);
-
- float totalSkillXP = experience_skill_taming + experience_skill_mining + experience_skill_foraging
- + experience_skill_enchanting + experience_skill_carpentry + experience_skill_farming
- + experience_skill_combat + experience_skill_fishing + experience_skill_alchemy
- + experience_skill_runecrafting;
+ if (leveling == null || !leveling.has("social")) {
+ Utils.showOutdatedRepoNotification();
+ return null;
+ }
+
+ Map<String, Level> out = new HashMap<>();
+
+ List<String> skills = Arrays.asList(
+ "taming",
+ "mining",
+ "foraging",
+ "enchanting",
+ "carpentry",
+ "farming",
+ "combat",
+ "fishing",
+ "alchemy",
+ "runecrafting",
+ "social"
+ );
+ float totalSkillXP = 0;
+ for (String skillName : skills) {
+ float skillExperience = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "experience_skill_" + (skillName.equals("social") ? "social2" : skillName)),
+ 0
+ );
+ totalSkillXP += skillExperience;
+ JsonArray levelingArray = Utils.getElement(leveling, "leveling_xp").getAsJsonArray();
+ if (skillName.equals("runecrafting")) {
+ levelingArray = Utils.getElement(leveling, "runecrafting_xp").getAsJsonArray();
+ } else if (skillName.equals("social")) {
+ levelingArray = Utils.getElement(leveling, "social").getAsJsonArray();
+ }
+
+ int maxLevel =
+ getCap(leveling, skillName) +
+ (
+ skillName.equals("farming")
+ ? Utils.getElementAsInt(Utils.getElement(profileInfo, "jacob2.perks.farming_level_cap"), 0)
+ : 0
+ );
+ out.put(skillName, getLevel(levelingArray, skillExperience, maxLevel, false));
+ }
+
+ // Skills API disabled?
if (totalSkillXP <= 0) {
return null;
}
- JsonObject skillInfo = new JsonObject();
-
- skillInfo.addProperty("experience_skill_taming", experience_skill_taming);
- skillInfo.addProperty("experience_skill_mining", experience_skill_mining);
- skillInfo.addProperty("experience_skill_foraging", experience_skill_foraging);
- skillInfo.addProperty("experience_skill_enchanting", experience_skill_enchanting);
- skillInfo.addProperty("experience_skill_carpentry", experience_skill_carpentry);
- skillInfo.addProperty("experience_skill_farming", experience_skill_farming);
- skillInfo.addProperty("experience_skill_combat", experience_skill_combat);
- skillInfo.addProperty("experience_skill_fishing", experience_skill_fishing);
- skillInfo.addProperty("experience_skill_alchemy", experience_skill_alchemy);
- skillInfo.addProperty("experience_skill_runecrafting", experience_skill_runecrafting);
- skillInfo.addProperty("experience_skill_hotm", experience_skill_hotm);
-
- skillInfo.addProperty("experience_skill_catacombs", experience_skill_catacombs);
-
- skillInfo.addProperty("experience_slayer_zombie", experience_slayer_zombie);
- skillInfo.addProperty("experience_slayer_spider", experience_slayer_spider);
- skillInfo.addProperty("experience_slayer_wolf", experience_slayer_wolf);
- skillInfo.addProperty("experience_slayer_enderman", experience_slayer_enderman);
-
- JsonArray levelingArray = Utils.getElement(leveling, "leveling_xp").getAsJsonArray();
- int farmingCap = getCap(leveling, "farming") + (int) Utils.getElementAsFloat(
- Utils.getElement(profileInfo, "jacob2.perks.farming_level_cap"), 0);
- Level level_skill_taming = getLevel(levelingArray, experience_skill_taming, getCap(leveling, "taming"), false);
- Level level_skill_mining = getLevel(levelingArray, experience_skill_mining, getCap(leveling, "mining"), false);
- Level level_skill_foraging =
- getLevel(levelingArray, experience_skill_foraging, getCap(leveling, "foraging"), false);
- Level level_skill_enchanting =
- getLevel(levelingArray, experience_skill_enchanting, getCap(leveling, "enchanting"), false);
- Level level_skill_carpentry =
- getLevel(levelingArray, experience_skill_carpentry, getCap(leveling, "carpentry"), false);
- Level level_skill_farming = getLevel(levelingArray, experience_skill_farming, farmingCap, false);
- Level level_skill_combat = getLevel(levelingArray, experience_skill_combat, getCap(leveling, "combat"), false);
- Level level_skill_fishing = getLevel(levelingArray, experience_skill_fishing, getCap(leveling, "fishing"), false);
- Level level_skill_alchemy = getLevel(levelingArray, experience_skill_alchemy, getCap(leveling, "alchemy"), false);
- Level level_skill_hotm = getLevel(levelingArray, experience_skill_hotm, getCap(leveling, "HOTM"), false);
- Level level_skill_runecrafting = getLevel(Utils.getElement(leveling, "runecrafting_xp").getAsJsonArray(),
- experience_skill_runecrafting, getCap(leveling, "runecrafting"), false
- );
- Level level_skill_catacombs = getLevel(Utils.getElement(leveling, "catacombs").getAsJsonArray(),
- experience_skill_catacombs, getCap(leveling, "catacombs"), false
+ out.put(
+ "hotm",
+ getLevel(
+ Utils.getElement(leveling, "leveling_xp").getAsJsonArray(),
+ Utils.getElementAsFloat(Utils.getElement(profileInfo, "mining_core.experience"), 0),
+ getCap(leveling, "HOTM"),
+ false
+ )
);
- Level level_slayer_zombie = getLevel(Utils.getElement(leveling, "slayer_xp.zombie").getAsJsonArray(),
- experience_slayer_zombie, 9, true
- );
- Level level_slayer_spider = getLevel(Utils.getElement(leveling, "slayer_xp.spider").getAsJsonArray(),
- experience_slayer_spider, 9, true
- );
- Level level_slayer_wolf = getLevel(Utils.getElement(leveling, "slayer_xp.wolf").getAsJsonArray(),
- experience_slayer_wolf, 9, true
- );
- Level level_slayer_enderman = getLevel(Utils.getElement(leveling, "slayer_xp.enderman").getAsJsonArray(),
- experience_slayer_enderman, 9, true
+ out.put(
+ "catacombs",
+ getLevel(
+ Utils.getElement(leveling, "catacombs").getAsJsonArray(),
+ Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0),
+ getCap(leveling, "catacombs"),
+ false
+ )
);
- skillInfo.addProperty("level_skill_taming", level_skill_taming.level);
- skillInfo.addProperty("level_skill_mining", level_skill_mining.level);
- skillInfo.addProperty("level_skill_foraging", level_skill_foraging.level);
- skillInfo.addProperty("level_skill_enchanting", level_skill_enchanting.level);
- skillInfo.addProperty("level_skill_carpentry", level_skill_carpentry.level);
- skillInfo.addProperty("level_skill_farming", level_skill_farming.level);
- skillInfo.addProperty("level_skill_combat", level_skill_combat.level);
- skillInfo.addProperty("level_skill_fishing", level_skill_fishing.level);
- skillInfo.addProperty("level_skill_alchemy", level_skill_alchemy.level);
- skillInfo.addProperty("level_skill_runecrafting", level_skill_runecrafting.level);
-
- skillInfo.addProperty("level_skill_catacombs", level_skill_catacombs.level);
-
- skillInfo.addProperty("level_slayer_zombie", level_slayer_zombie.level);
- skillInfo.addProperty("level_slayer_spider", level_slayer_spider.level);
- skillInfo.addProperty("level_slayer_wolf", level_slayer_wolf.level);
- skillInfo.addProperty("level_slayer_enderman", level_slayer_enderman.level);
-
- skillInfo.addProperty("maxed_skill_taming", level_skill_taming.maxed);
- skillInfo.addProperty("maxed_skill_mining", level_skill_mining.maxed);
- skillInfo.addProperty("maxed_skill_foraging", level_skill_foraging.maxed);
- skillInfo.addProperty("maxed_skill_enchanting", level_skill_enchanting.maxed);
- skillInfo.addProperty("maxed_skill_carpentry", level_skill_carpentry.maxed);
- skillInfo.addProperty("maxed_skill_farming", level_skill_farming.maxed);
- skillInfo.addProperty("maxed_skill_combat", level_skill_combat.maxed);
- skillInfo.addProperty("maxed_skill_fishing", level_skill_fishing.maxed);
- skillInfo.addProperty("maxed_skill_alchemy", level_skill_alchemy.maxed);
- skillInfo.addProperty("maxed_skill_runecrafting", level_skill_runecrafting.maxed);
-
- skillInfo.addProperty("maxed_skill_catacombs", level_skill_catacombs.maxed);
-
- skillInfo.addProperty("maxed_slayer_zombie", level_slayer_zombie.maxed);
- skillInfo.addProperty("maxed_slayer_spider", level_slayer_spider.maxed);
- skillInfo.addProperty("maxed_slayer_wolf", level_slayer_wolf.maxed);
- skillInfo.addProperty("maxed_slayer_enderman", level_slayer_enderman.maxed);
-
- skillInfo.addProperty("maxxp_skill_taming", level_skill_taming.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_mining", level_skill_mining.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_foraging", level_skill_foraging.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_enchanting", level_skill_enchanting.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_carpentry", level_skill_carpentry.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_farming", level_skill_farming.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_combat", level_skill_combat.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_fishing", level_skill_fishing.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_alchemy", level_skill_alchemy.maxXpForLevel);
- skillInfo.addProperty("maxxp_skill_runecrafting", level_skill_runecrafting.maxXpForLevel);
-
- skillInfo.addProperty("maxxp_skill_catacombs", level_skill_catacombs.maxXpForLevel);
-
- skillInfo.addProperty("maxxp_slayer_zombie", level_slayer_zombie.maxXpForLevel);
- skillInfo.addProperty("maxxp_slayer_spider", level_slayer_spider.maxXpForLevel);
- skillInfo.addProperty("maxxp_slayer_wolf", level_slayer_wolf.maxXpForLevel);
- skillInfo.addProperty("maxxp_slayer_enderman", level_slayer_enderman.maxXpForLevel);
-
- return skillInfo;
+ List<String> dungeonClasses = Arrays.asList("healer", "tank", "mage", "archer", "berserk");
+ for (String className : dungeonClasses) {
+ float classExperience = Utils.getElementAsFloat(
+ Utils.getElement(profileInfo, "dungeons.player_classes." + className + ".experience"),
+ 0
+ );
+ out.put(
+ className,
+ getLevel(
+ Utils.getElement(leveling, "catacombs").getAsJsonArray(),
+ classExperience,
+ getCap(leveling, "catacombs"),
+ false
+ )
+ );
+ }
+
+ List<String> slayers = Arrays.asList("zombie", "spider", "wolf", "enderman", "blaze");
+ for (String slayerName : slayers) {
+ float slayerExperience = Utils.getElementAsFloat(Utils.getElement(
+ profileInfo,
+ "slayer_bosses." + slayerName + ".xp"
+ ), 0);
+ out.put(
+ slayerName,
+ getLevel(Utils.getElement(leveling, "slayer_xp." + slayerName).getAsJsonArray(), slayerExperience, 9, true)
+ );
+ }
+
+ skyblockInfoCache.put(profileName, out);
+
+ return out;
}
- public JsonObject getInventoryInfo(String profileId) {
- JsonObject profileInfo = getProfileInformation(profileId);
+ public JsonObject getInventoryInfo(String profileName) {
+ JsonObject profileInfo = getProfileInformation(profileName);
if (profileInfo == null) return null;
- if (profileId == null) profileId = latestProfile;
- if (inventoryInfoMap.containsKey(profileId)) return inventoryInfoMap.get(profileId);
+ if (profileName == null) profileName = latestProfile;
+ if (inventoryCacheMap.containsKey(profileName)) return inventoryCacheMap.get(profileName);
String inv_armor_bytes = Utils.getElementAsString(
Utils.getElement(profileInfo, "inv_armor.data"),
@@ -889,6 +1191,10 @@ public class ProfileViewer {
Utils.getElement(profileInfo, "candy_inventory_contents.data"),
"Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="
);
+ String equipment_contents_bytes = Utils.getElementAsString(
+ Utils.getElement(profileInfo, "equippment_contents.data"),
+ "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA="
+ );
JsonObject inventoryInfo = new JsonObject();
@@ -903,7 +1209,8 @@ public class ProfileViewer {
"potion_bag",
"inv_contents",
"talisman_bag",
- "candy_inventory_contents"
+ "candy_inventory_contents",
+ "equippment_contents",
};
String[] inv_bytes = new String[]{
inv_armor_bytes,
@@ -916,7 +1223,8 @@ public class ProfileViewer {
potion_bag_bytes,
inv_contents_bytes,
talisman_bag_bytes,
- candy_inventory_contents_bytes
+ candy_inventory_contents_bytes,
+ equipment_contents_bytes,
};
for (int i = 0; i < inv_bytes.length; i++) {
try {
@@ -928,11 +1236,10 @@ public class ProfileViewer {
JsonObject temp = getBackpackData(backpack_contents_json, backpack_icons);
contents = (JsonArray) temp.get("contents");
inventoryInfo.add("backpack_sizes", temp.get("backpack_sizes"));
-
} else {
-
- NBTTagCompound inv_contents_nbt =
- CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(bytes)));
+ NBTTagCompound inv_contents_nbt = CompressedStreamTools.readCompressed(
+ new ByteArrayInputStream(Base64.getDecoder().decode(bytes))
+ );
NBTTagList items = inv_contents_nbt.getTagList("i", 10);
for (int j = 0; j < items.tagCount(); j++) {
JsonObject item = manager.getJsonFromNBTEntry(items.getCompoundTagAt(j));
@@ -945,19 +1252,13 @@ public class ProfileViewer {
}
}
- inventoryInfoMap.put(profileId, inventoryInfo);
+ inventoryCacheMap.put(profileName, inventoryInfo);
return inventoryInfo;
}
- public boolean checkIfValidJson(JsonElement element) {
- return element != null;
- }
-
- public JsonObject getBackpackData(JsonObject backpack_contents_json, JsonObject backpack_icons) {
-
- JsonArray contents = new JsonArray();
- if (!(checkIfValidJson(backpack_contents_json) && checkIfValidJson(backpack_icons))) {
+ public JsonObject getBackpackData(JsonObject backpackContentsJson, JsonObject backpackIcons) {
+ if (backpackContentsJson == null || backpackIcons == null) {
JsonObject bundledReturn = new JsonObject();
bundledReturn.add("contents", new JsonArray());
bundledReturn.add("backpack_sizes", new JsonArray());
@@ -968,9 +1269,9 @@ public class ProfileViewer {
String[] backpackArray = new String[0];
//Create backpack array which sizes up
- for (Map.Entry<String, JsonElement> backpackIcon : backpack_icons.entrySet()) {
+ for (Map.Entry<String, JsonElement> backpackIcon : backpackIcons.entrySet()) {
if (backpackIcon.getValue() instanceof JsonObject) {
- JsonObject backpackData = (JsonObject) backpack_contents_json.get(backpackIcon.getKey());
+ JsonObject backpackData = (JsonObject) backpackContentsJson.get(backpackIcon.getKey());
String bytes = Utils.getElementAsString(backpackData.get("data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
backpackArray = growArray(bytes, Integer.parseInt(backpackIcon.getKey()), backpackArray);
}
@@ -978,11 +1279,9 @@ public class ProfileViewer {
//reduce backpack array to filter out not existent backpacks
{
- int backpackCount = 0;
String[] tempBackpackArray = new String[0];
for (String s : backpackArray) {
if (s != null) {
- backpackCount++;
String[] veryTempBackpackArray = new String[tempBackpackArray.length + 1];
System.arraycopy(tempBackpackArray, 0, veryTempBackpackArray, 0, tempBackpackArray.length);
@@ -994,11 +1293,13 @@ public class ProfileViewer {
}
JsonArray backpackSizes = new JsonArray();
+ JsonArray contents = new JsonArray();
for (String backpack : backpackArray) {
try {
- NBTTagCompound inv_contents_nbt =
- CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(backpack)));
+ NBTTagCompound inv_contents_nbt = CompressedStreamTools.readCompressed(
+ new ByteArrayInputStream(Base64.getDecoder().decode(backpack))
+ );
NBTTagList items = inv_contents_nbt.getTagList("i", 10);
backpackSizes.add(new JsonPrimitive(items.tagCount()));
@@ -1021,18 +1322,16 @@ public class ProfileViewer {
int newSize = Math.max(index + 1, oldArray.length);
String[] newArray = new String[newSize];
- for (int i = 0; i < oldArray.length; i++) {
- newArray[i] = oldArray[i];
- }
+ System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
newArray[index] = bytes;
return newArray;
}
- public JsonObject getPetsInfo(String profileId) {
- JsonObject profileInfo = getProfileInformation(profileId);
+ public JsonObject getPetsInfo(String profileName) {
+ JsonObject profileInfo = getProfileInformation(profileName);
if (profileInfo == null) return null;
- if (petsInfoMap.containsKey(profileId)) return petsInfoMap.get(profileId);
+ if (petsInfoMap.containsKey(profileName)) return petsInfoMap.get(profileName);
JsonObject petsInfo = new JsonObject();
JsonElement petsElement = profileInfo.get("pets");
@@ -1041,31 +1340,33 @@ public class ProfileViewer {
JsonArray pets = petsElement.getAsJsonArray();
for (int i = 0; i < pets.size(); i++) {
JsonObject pet = pets.get(i).getAsJsonObject();
- if (pet.has("active") && pet.get("active").getAsJsonPrimitive().getAsBoolean()) {
+ if (pet.has("active") && pet.get("active").getAsBoolean()) {
activePet = pet;
break;
}
}
petsInfo.add("active_pet", activePet);
petsInfo.add("pets", pets);
- petsInfoMap.put(profileId, petsInfo);
+ petsInfoMap.put(profileName, petsInfo);
return petsInfo;
}
return null;
}
- private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?[0-9]+)");
-
- public JsonObject getCollectionInfo(String profileId) {
- JsonObject profileInfo = getProfileInformation(profileId);
+ public JsonObject getCollectionInfo(String profileName) {
+ JsonObject profileInfo = getProfileInformation(profileName);
if (profileInfo == null) return null;
JsonObject resourceCollectionInfo = getResourceCollectionInformation();
if (resourceCollectionInfo == null) return null;
- if (profileId == null) profileId = latestProfile;
- if (collectionInfoMap.containsKey(profileId)) return collectionInfoMap.get(profileId);
+ if (profileName == null) profileName = latestProfile;
+ if (collectionInfoMap.containsKey(profileName)) return collectionInfoMap.get(profileName);
+ List<JsonObject> coopMembers = getCoopProfileInformation(profileName);
JsonElement unlocked_coll_tiers_element = Utils.getElement(profileInfo, "unlocked_coll_tiers");
JsonElement crafted_generators_element = Utils.getElement(profileInfo, "crafted_generators");
+ JsonObject fakeMember = new JsonObject();
+ fakeMember.add("crafted_generators", crafted_generators_element);
+ coopMembers.add(coopMembers.size(), fakeMember);
JsonElement collectionInfoElement = Utils.getElement(profileInfo, "collection");
if (unlocked_coll_tiers_element == null || collectionInfoElement == null) {
@@ -1083,17 +1384,17 @@ public class ProfileViewer {
}
for (Map.Entry<String, JsonElement> entry : personalAmounts.entrySet()) {
- totalAmounts.addProperty(entry.getKey(), entry.getValue().getAsInt());
+ totalAmounts.addProperty(entry.getKey(), entry.getValue().getAsLong());
}
- List<JsonObject> coopProfiles = getCoopProfileInformation(profileId);
+ List<JsonObject> coopProfiles = getCoopProfileInformation(profileName);
if (coopProfiles != null) {
for (JsonObject coopProfile : coopProfiles) {
JsonElement coopCollectionInfoElement = Utils.getElement(coopProfile, "collection");
if (coopCollectionInfoElement != null && coopCollectionInfoElement.isJsonObject()) {
for (Map.Entry<String, JsonElement> entry : coopCollectionInfoElement.getAsJsonObject().entrySet()) {
float existing = Utils.getElementAsFloat(totalAmounts.get(entry.getKey()), 0);
- totalAmounts.addProperty(entry.getKey(), existing + entry.getValue().getAsInt());
+ totalAmounts.addProperty(entry.getKey(), existing + entry.getValue().getAsLong());
}
}
}
@@ -1116,17 +1417,17 @@ public class ProfileViewer {
}
}
}
-
- if (crafted_generators_element != null && crafted_generators_element.isJsonArray()) {
- JsonArray crafted_generators = crafted_generators_element.getAsJsonArray();
- for (int i = 0; i < crafted_generators.size(); i++) {
- String unlocked = crafted_generators.get(i).getAsString();
-
+ for (JsonObject current_member_info : coopMembers) {
+ if (
+ !current_member_info.has("crafted_generators") || !current_member_info.get("crafted_generators").isJsonArray()
+ ) continue;
+ JsonArray crafted_generators = Utils.getElement(current_member_info, "crafted_generators").getAsJsonArray();
+ for (int j = 0; j < crafted_generators.size(); j++) {
+ String unlocked = crafted_generators.get(j).getAsString();
Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked);
-
if (matcher.find()) {
- String tier_str = matcher.group(1);
- int tier = Integer.parseInt(tier_str);
+ String tierString = matcher.group(1);
+ int tier = Integer.parseInt(tierString);
String coll = unlocked.substring(0, unlocked.length() - (matcher.group().length()));
if (!minionTiers.has(coll) || minionTiers.get(coll).getAsInt() < tier) {
minionTiers.addProperty(coll, tier);
@@ -1177,37 +1478,43 @@ public class ProfileViewer {
collectionInfo.add("total_amounts", totalAmounts);
collectionInfo.add("collection_tiers", collectionTiers);
+ collectionInfoMap.put(profileName, collectionInfo);
+
return collectionInfo;
}
- public PlayerStats.Stats getPassiveStats(String profileId) {
- if (passiveStats.get(profileId) != null) return passiveStats.get(profileId);
- JsonObject profileInfo = getProfileInformation(profileId);
+ public PlayerStats.Stats getPassiveStats(String profileName) {
+ if (passiveStats.get(profileName) != null) return passiveStats.get(profileName);
+ JsonObject profileInfo = getProfileInformation(profileName);
if (profileInfo == null) return null;
- PlayerStats.Stats passiveStats = PlayerStats.getPassiveBonuses(getSkillInfo(profileId), profileInfo);
+ PlayerStats.Stats passiveStats = PlayerStats.getPassiveBonuses(getSkyblockInfo(profileName), profileInfo);
if (passiveStats != null) {
passiveStats.add(PlayerStats.getBaseStats());
}
- this.passiveStats.put(profileId, passiveStats);
+ this.passiveStats.put(profileName, passiveStats);
return passiveStats;
}
- public PlayerStats.Stats getStats(String profileId) {
- //if(stats.get(profileId) != null) return stats.get(profileId);
- JsonObject profileInfo = getProfileInformation(profileId);
+ public PlayerStats.Stats getStats(String profileName) {
+ if (stats.get(profileName) != null) return stats.get(profileName);
+ JsonObject profileInfo = getProfileInformation(profileName);
if (profileInfo == null) {
return null;
}
- PlayerStats.Stats stats =
- PlayerStats.getStats(getSkillInfo(profileId), getInventoryInfo(profileId), getCollectionInfo(profileId),
- getPetsInfo(profileId), profileInfo
- );
- this.stats.put(profileId, stats);
+ PlayerStats.Stats stats = PlayerStats.getStats(
+ getSkyblockInfo(profileName),
+ getInventoryInfo(profileName),
+ getCollectionInfo(profileName),
+ getPetsInfo(profileName),
+ profileInfo
+ );
+ if (stats == null) return null;
+ this.stats.put(profileName, stats);
return stats;
}
@@ -1215,139 +1522,8 @@ public class ProfileViewer {
return uuid;
}
- public @Nullable
- JsonObject getHypixelProfile() {
- if (uuidToHypixelProfile.containsKey(uuid)) return uuidToHypixelProfile.get(uuid);
- return null;
- }
- }
-
- private final HashMap<String, JsonObject> nameToHypixelProfile = new HashMap<>();
- private final HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>();
- private final HashMap<String, Profile> uuidToProfileMap = new HashMap<>();
-
- public void getHypixelProfile(String name, Consumer<JsonObject> callback) {
- String nameF = name.toLowerCase();
- HashMap<String, String> args = new HashMap<>();
- args.put("name", "" + nameF);
- manager.hypixelApi.getHypixelApiAsync(NotEnoughUpdates.INSTANCE.config.apiKey.apiKey, "player",
- args, jsonObject -> {
- if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()
- && jsonObject.get("player").isJsonObject()) {
- nameToUuid.put(nameF, jsonObject.get("player").getAsJsonObject().get("uuid").getAsString());
- uuidToHypixelProfile.put(
- jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(),
- jsonObject.get("player").getAsJsonObject()
- );
- if (callback != null) callback.accept(jsonObject);
- } else {
- if (callback != null) callback.accept(null);
- }
- }
- );
- }
-
- private final HashMap<String, String> nameToUuid = new HashMap<>();
-
- public void putNameUuid(String name, String uuid) {
- nameToUuid.put(name, uuid);
- }
-
- public void getPlayerUUID(String name, Consumer<String> uuidCallback) {
- String nameF = name.toLowerCase();
- if (nameToUuid.containsKey(nameF)) {
- uuidCallback.accept(nameToUuid.get(nameF));
- return;
+ public @Nullable JsonObject getHypixelProfile() {
+ return uuidToHypixelProfile.getOrDefault(uuid, null);
}
-
- manager.hypixelApi.getApiAsync("https://api.mojang.com/users/profiles/minecraft/" + nameF,
- (jsonObject) -> {
- if (jsonObject.has("id") && jsonObject.get("id").isJsonPrimitive() &&
- ((JsonPrimitive) jsonObject.get("id")).isString()) {
- String uuid = jsonObject.get("id").getAsString();
- nameToUuid.put(nameF, uuid);
- uuidCallback.accept(uuid);
- return;
- }
- uuidCallback.accept(null);
- }, () -> uuidCallback.accept(null)
- );
- }
-
- public void getProfileByName(String name, Consumer<Profile> callback) {
- String nameF = name.toLowerCase();
-
- if (nameToUuid.containsKey(nameF) && nameToUuid.get(nameF) == null) {
- callback.accept(null);
- return;
- }
-
- getPlayerUUID(nameF, (uuid) -> {
- if (uuid == null) {
- getHypixelProfile(nameF, jsonObject -> {
- if (jsonObject != null) {
- callback.accept(getProfileReset(nameToUuid.get(nameF), ignored -> {
- }));
- } else {
- callback.accept(null);
- nameToUuid.put(nameF, null);
- }
- });
- } else {
- if (!uuidToHypixelProfile.containsKey(uuid)) {
- getHypixelProfile(nameF, jsonObject -> {
- });
- }
- callback.accept(getProfileReset(uuid, ignored -> {
- }));
- }
- });
-
- return;
- }
-
- public Profile getProfileRaw(String uuid) {
- return uuidToProfileMap.get(uuid);
- }
-
- public Profile getProfile(String uuid, Consumer<Profile> callback) {
- Profile profile = uuidToProfileMap.computeIfAbsent(uuid, k -> new Profile(uuid));
- if (profile.playerInformation != null) {
- callback.accept(profile);
- } else {
- profile.getPlayerInformation(() -> callback.accept(profile));
- }
- return profile;
- }
-
- public Profile getProfileReset(String uuid, Consumer<Profile> callback) {
- if (uuidToProfileMap.containsKey(uuid)) uuidToProfileMap.get(uuid).resetCache();
- return getProfile(uuid, callback);
- }
-
- private static JsonObject resourceCollection = null;
- private static final AtomicBoolean updatingResourceCollection = new AtomicBoolean(false);
-
- public static JsonObject getResourceCollectionInformation() {
- if (resourceCollection != null) return resourceCollection;
- if (updatingResourceCollection.get()) return null;
-
- updatingResourceCollection.set(true);
-
- HashMap<String, String> args = new HashMap<>();
- NotEnoughUpdates.INSTANCE.manager.hypixelApi.getHypixelApiAsync(
- NotEnoughUpdates.INSTANCE.config.apiKey.apiKey,
- "resources/skyblock/collections",
- args,
- jsonObject -> {
- updatingResourceCollection.set(false);
- if (jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
- resourceCollection = jsonObject.get("collections").getAsJsonObject();
- }
- },
- () -> updatingResourceCollection.set(false)
- );
-
- return null;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java
new file mode 100644
index 00000000..7df88964
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryData.java
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.bestiary;
+
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.LinkedHashMap;
+import java.util.List;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+
+public class BestiaryData {
+
+ private static final LinkedHashMap<ItemStack, List<String>> bestiaryLocations = new LinkedHashMap<ItemStack, List<String>>() {
+ {
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Private Island",
+ "bdee7687-9c85-4e7a-b789-b55e90d21d68",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NiJ9fX0="
+ ),
+ Utils.createList(
+ "family_cave_spider",
+ "family_enderman_private",
+ "family_skeleton",
+ "family_slime",
+ "family_spider",
+ "family_witch",
+ "family_zombie"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Hub",
+ "88208736-41cd-4ed8-8ed7-53179140a7fa",
+ "eyJ0aW1lc3RhbXAiOjE1NTkyMTU0MTY5MDksInByb2ZpbGVJZCI6IjQxZDNhYmMyZDc0OTQwMGM5MDkwZDU0MzRkMDM4MzFiIiwicHJvZmlsZU5hbWUiOiJNZWdha2xvb24iLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Q3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjgifX19"
+ ),
+ Utils.createList("family_unburried_zombie", "family_old_wolf", "family_ruin_wolf", "family_zombie_villager")
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Spiders Den",
+ "acbeaf98-2081-40c5-b5a3-221a2957d532",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzc1NDMxOGEzMzc2ZjQ3MGU0ODFkZmNkNmM4M2E1OWFhNjkwYWQ0YjRkZDc1NzdmZGFkMWMyZWYwOGQ4YWVlNiJ9fX0"
+ ),
+ Utils.createList(
+ "family_arachne",
+ "family_arachne_brood",
+ "family_arachne_keeper",
+ "family_brood_mother_spider",
+ "family_dasher_spider",
+ "family_respawning_skeleton",
+ "family_random_slime",
+ "family_spider_jockey",
+ "family_splitter_spider",
+ "family_voracious_spider",
+ "family_weaver_spider"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "The End",
+ "e39ea8b1-a267-48a9-907a-1b97b85342bc",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1In19fQ"
+ ),
+ Utils.createList(
+ "family_dragon",
+ "family_enderman",
+ "family_endermite",
+ "family_corrupted_protector",
+ "family_obsidian_wither",
+ "family_voidling_extremist",
+ "family_voidling_fanatic",
+ "family_watcher",
+ "family_zealot_enderman"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Crimson Isles",
+ "d8489bfe-dcd7-41f0-bfbd-fb482bf61ecb",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzM2ODdlMjVjNjMyYmNlOGFhNjFlMGQ2NGMyNGU2OTRjM2VlYTYyOWVhOTQ0ZjRjZjMwZGNmYjRmYmNlMDcxIn19fQ"
+ ),
+ Utils.createList(
+ "family_ashfang",
+ "family_barbarian_duke_x",
+ "family_bladesoul",
+ "family_blaze",
+ "family_flaming_spider",
+ "family_ghast",
+ "family_mage_outlaw",
+ "family_magma_cube",
+ "family_magma_cube_boss",
+ "family_matcho",
+ "family_charging_mushroom_cow",
+ "family_pigman",
+ "family_wither_skeleton",
+ "family_wither_spectre"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Deep Caverns",
+ "896b5137-a2dd-4de2-8c63-d5a5649bfc70",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTY5YTFmMTE0MTUxYjQ1MjEzNzNmMzRiYzE0YzI5NjNhNTAxMWNkYzI1YTY1NTRjNDhjNzA4Y2Q5NmViZmMifX19"
+ ),
+ Utils.createList(
+ "family_automaton",
+ "family_butterfly",
+ "family_emerald_slime",
+ "family_caverns_ghost",
+ "family_goblin",
+ "family_team_treasurite",
+ "family_ice_walker",
+ "family_lapis_zombie",
+ "family_diamond_skeleton",
+ "family_diamond_zombie",
+ "family_redstone_pigman",
+ "family_sludge",
+ "family_invisible_creeper",
+ "family_thyst",
+ "family_treasure_hoarder",
+ "family_worms",
+ "family_yog"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "The Park",
+ "6473b2ff-0575-4aec-811f-5f0dca2131b6",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWIifX19"
+ ),
+ Utils.createList("family_howling_spirit", "family_pack_spirit", "family_soul_of_the_alpha")
+ );
+ put(
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.lit_pumpkin), EnumChatFormatting.AQUA + "Spooky"),
+ Utils.createList(
+ "family_batty_witch",
+ "family_headless_horseman",
+ "family_phantom_spirit",
+ "family_scary_jerry",
+ "family_trick_or_treater",
+ "family_wither_gourd",
+ "family_wraith"
+ )
+ );
+ put(
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "Catacombs",
+ "00b3837d-9275-304c-8bf9-656659087e6b",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTY0ZTFjM2UzMTVjOGQ4ZmZmYzM3OTg1YjY2ODFjNWJkMTZhNmY5N2ZmZDA3MTk5ZThhMDVlZmJlZjEwMzc5MyJ9fX0"
+ ),
+ Utils.createList(
+ "family_diamond_guy",
+ "family_cellar_spider",
+ "family_crypt_dreadlord",
+ "family_crypt_lurker",
+ "family_crypt_souleater",
+ "family_king_midas",
+ "family_lonely_spider",
+ "family_lost_adventurer",
+ "family_scared_skeleton",
+ "family_shadow_assassin",
+ "family_skeleton_grunt",
+ "family_skeleton_master",
+ "family_skeleton_soldier",
+ "family_skeletor",
+ "family_sniper_skeleton",
+ "family_super_archer",
+ "family_super_tank_zombie",
+ "family_crypt_tank_zombie",
+ "family_watcher_summon_undead",
+ "family_dungeon_respawning_skeleton",
+ "family_crypt_witherskeleton",
+ "family_zombie_commander",
+ "family_zombie_grunt",
+ "family_zombie_knight",
+ "family_zombie_soldier"
+ )
+ );
+ }
+ };
+ private static final LinkedHashMap<String, ItemStack> bestiaryMobs = new LinkedHashMap<String, ItemStack>() {
+ {
+ // Private Island
+ put(
+ "family_cave_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aCave Spider",
+ "a8aee72d-0d1d-3db7-8cf8-be1ce6ec2dc4",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDE2NDVkZmQ3N2QwOTkyMzEwN2IzNDk2ZTk0ZWViNWMzMDMyOWY5N2VmYzk2ZWQ3NmUyMjZlOTgyMjQifX19"
+ )
+ );
+ put(
+ "family_enderman_private",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aEnderman",
+ "2005daad-730b-363c-abae-e6f3830816fb",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0="
+ )
+ );
+ put(
+ "family_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSkeleton",
+ "53924f1a-87e6-4709-8e53-f1c7d13dc239",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
+ )
+ );
+ put(
+ "family_slime",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSlime",
+ "3b70a2f3-319c-38d5-b7d1-5b2425770184",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
+ )
+ );
+ put(
+ "family_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSpider",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_witch",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWitch",
+ "cf4f97d7-2e1f-3678-9ca3-4a7b9666cc28",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmNlNjYwNDE1N2ZjNGFiNTU5MWU0YmNmNTA3YTc0OTkxOGVlOWM0MWUzNTdkNDczNzZlMGVlNzM0MjA3NGM5MCJ9fX0="
+ )
+ );
+ put(
+ "family_zombie",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+
+ // Hub
+ put("family_unburried_zombie", Utils.createItemStack(Items.golden_sword, EnumChatFormatting.AQUA + "§aCrypt Ghoul"));
+ put(
+ "family_old_wolf",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aOld Wolf",
+ "26e6f2d9-8a27-3a77-965c-5bd2b5d2dc93",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDM1OTUzN2MxNTUzNGY2MWMxY2Q4ODZiYzExODc3NGVkMjIyODBlN2NkYWI2NjEzODcwMTYwYWFkNGNhMzkifX19"
+ )
+ );
+ put(
+ "family_ruin_wolf",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWolf",
+ "7e9af289-f295-3f8c-bd54-58b7667d5759",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjlkMWQzMTEzZWM0M2FjMjk2MWRkNTlmMjgxNzVmYjQ3MTg4NzNjNmM0NDhkZmNhODcyMjMxN2Q2NyJ9fX0="
+ )
+ );
+ put(
+ "family_zombie_villager",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie Villager",
+ "3acb9940-fc42-328e-91e8-c9a9a57e8698",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTVlMDhhODc3NmMxNzY0YzNmZTZhNmRkZDQxMmRmY2I4N2Y0MTMzMWRhZDQ3OWFjOTZjMjFkZjRiZjNhYzg5YyJ9fX0="
+ )
+ );
+
+ // Spiders Den
+ put(
+ "family_arachne",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aArachne",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_arachne_brood",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aArachne's Brood",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_arachne_keeper",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aArachne's Keeper",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_brood_mother_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aBrood Mother",
+ "d7390e70-1e99-3c24-9b1c-bb098e0bbef1",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2YwNjIyYjM5OThkNDJiMzRkNWJjNzYwYmIyYzgzZmRiYzZlNjhmYWIwNWI3ZWExN2IzNTA5N2VkODExOTBkNiJ9fX0="
+ )
+ );
+ put(
+ "family_dasher_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aDasher Spider",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_respawning_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aGravel Skeleton",
+ "53924f1a-87e6-4709-8e53-f1c7d13dc239",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
+ )
+ );
+ put(
+ "family_random_slime",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aRain Slime",
+ "3b70a2f3-319c-38d5-b7d1-5b2425770184",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
+ )
+ );
+ put(
+ "family_spider_jockey",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSpider Jockey",
+ "4eb8745c-80d2-356b-b4fa-f3ffa74082e7",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzA5MzkzNzNjYWZlNGIxZjUzOTdhYWZkMDlmM2JiMTY2M2U3YjYyOWE0MWE3NWZiZGMxODYwYjZiZjhiNDc1ZiJ9fX0="
+ )
+ );
+ put(
+ "family_splitter_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSplitter Spider",
+ "50010472-fa22-3519-b941-2d6d22f47bf1",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMmFjZjY5ZmM3YWY1NDk3YTE3NDE4OTFkMWU1YmYzMmI5NmFlMGQ2YzBiYmQzYzE0NzU4ZWE0NGEwM2M1NzI4MyJ9fX0="
+ )
+ );
+ put(
+ "family_voracious_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aVoracious Spider",
+ "3e5474d4-4365-3ea7-b4bc-b4edc54da341",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODMwMDk4NmVkMGEwNGVhNzk5MDRmNmFlNTNmNDllZDNhMGZmNWIxZGY2MmJiYTYyMmVjYmQzNzc3ZjE1NmRmOCJ9fX0="
+ )
+ );
+ put(
+ "family_weaver_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWeaver Spider",
+ "97414c0c-623b-3df3-b1f6-bbcaddafc7fc",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTIxNDM4ZjY0NmRjMDQ1MTU5NjdlODE5NWNjYzNkMzFlMjNiMDJmOWFhMGFjOTE0ZWRjMjgyMmY5ODM5NGI4NiJ9fX0="
+ )
+ );
+
+ // The End
+ put("family_dragon", Utils.createItemStack(Item.getItemFromBlock(Blocks.dragon_egg), EnumChatFormatting.AQUA + "§aDragon"));
+ put(
+ "family_enderman",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aEnderman",
+ "2005daad-730b-363c-abae-e6f3830816fb",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0="
+ )
+ );
+ put(
+ "family_endermite",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aEndermite",
+ "b3224e56-73d2-32f9-9081-a23b7512035b",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWJjN2I5ZDM2ZmI5MmI2YmYyOTJiZTczZDMyYzZjNWIwZWNjMjViNDQzMjNhNTQxZmFlMWYxZTY3ZTM5M2EzZSJ9fX0="
+ )
+ );
+ put(
+ "family_corrupted_protector",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aEndstone Protector",
+ "a46a9adf-60a3-38f2-a3dd-335d85f1cc10",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJiY2FjZWViNDE2MmY0MDBkNDQ3NDMzMTU5MzJhYzgyMGQzMTE5YWM4OTg2YTAxNjFhNzI2MTYxY2NjOTNmYyJ9fX0="
+ )
+ );
+ put(
+ "family_obsidian_wither",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aObsidian Defender",
+ "d0e05de7-6067-454d-beae-c6d19d886191",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMjg1MTE1NCwKICAicHJvZmlsZUlkIiA6ICJkMGUwNWRlNzYwNjc0NTRkYmVhZWM2ZDE5ZDg4NjE5MSIsCiAgInByb2ZpbGVOYW1lIiA6ICJNb3VsYmVycnkiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmNlMTU1MjI0ZWE0YmM0OWE4ZTkxOTA3MzdjYjA0MTdkOGE3YzM4YTAzN2Q4ZDAzODJkZGU0ODI5YzEwMzU5MCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9"
+ )
+ );
+ put(
+ "family_voidling_extremist",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§dVoidling Extremist",
+ "159dcb01-74e3-382c-87d6-3afa022fb379",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWIwNzU5NGUyZGYyNzM5MjFhNzdjMTAxZDBiZmRmYTExMTVhYmVkNWI5YjIwMjllYjQ5NmNlYmE5YmRiYjRiMyJ9fX0="
+ )
+ );
+ put(
+ "family_voidling_fanatic",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aVoidling Fanatic",
+ "e86aab24-6245-3967-bf3d-07e31999b602",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTUzYjdiY2Q1NmYwYjk1Zjg3ZGQ3OWVkMTc2MzZiZWI5ZDgzNDY3NDQwMTQyMjhlYTJmNmIxMTBiMTQ4YzEifX19"
+ )
+ );
+ put(
+ "family_watcher",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWatcher",
+ "00a702b9-7bad-3205-a04b-52478d8c0e7f",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGFhOGZjOGRlNjQxN2I0OGQ0OGM4MGI0NDNjZjUzMjZlM2Q5ZGE0ZGJlOWIyNWZjZDQ5NTQ5ZDk2MTY4ZmMwIn19fQ=="
+ )
+ );
+ put(
+ "family_zealot_enderman",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.AQUA + "§aZealot")
+ );
+
+ // Crimson Isle
+ put(
+ "family_ashfang",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aAshfang",
+ "1bc8810e-2b57-3a89-8e00-a47a057d6ecc",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2QyYTViNGIxMDliZDc4OGVkYmEwMTcxZDBhYWI4YTU1MzA1YWMyZjU2MTg0ZGY3MGEzMTljZDQ4OGEzNmMzZSJ9fX0="
+ )
+ );
+ put(
+ "family_barbarian_duke_x",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aBarbarian Duke X",
+ "6ddece1d-8227-35f3-b9ca-476a9f6cd8c5",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0MTI0OTYyNTU3NSwKICAicHJvZmlsZUlkIiA6ICIyNzZlMDQ2YjI0MDM0M2VkOTk2NmU0OTRlN2U2Y2IzNCIsCiAgInByb2ZpbGVOYW1lIiA6ICJBRFJBTlM3MTAiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmVlOWZjN2MxODFlMmY2MzBmNmIxYWY4NWQ0OTUxMzU5Y2FmY2ZhODJmZjVlYTNiYzI4M2UwZTYwODhjNmU1NCIKICAgIH0KICB9Cn0"
+ )
+ );
+ put(
+ "family_bladesoul",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aBladesoul",
+ "9a1699a4-9b61-37a5-be7a-ca23a1f092a1",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg1NzcxMCwKICAicHJvZmlsZUlkIiA6ICIwNTVhOTk2NTk2M2E0YjRmOGMwMjRmMTJmNDFkMmNmMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGVWb3hlbGxlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdmNWYzMzg0Mzg0ZDdmMDNiZjk3YTczMDk5YjBiYWZiNzJjNTM4ZmMwNDE1YWM4NjEzYjY2NGY4NzU3OWEzNzkiCiAgICB9CiAgfQp9"
+ )
+ );
+ put(
+ "family_blaze",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aBlaze",
+ "118fe834-28aa-3b0d-afe6-f0c52d01afe8",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjc4ZWYyZTRjZjJjNDFhMmQxNGJmZGU5Y2FmZjEwMjE5ZjViMWJmNWIzNWE0OWViNTFjNjQ2Nzg4MmNiNWYwIn19fQ=="
+ )
+ );
+ put(
+ "family_flaming_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aFlaming Spider",
+ "d27e14a2-f35e-3c7b-8062-089fa201a533",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0NDQ5OTUzOTQ2NywKICAicHJvZmlsZUlkIiA6ICJhYTZhNzUwNWVkYmU0NjNiYjk1NWYyMWY0MjNiYTM1NCIsCiAgInByb2ZpbGVOYW1lIiA6ICJub3RhbmR5d2FyaG9sIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzVhNjVlZjIzZWEzNTA0NzE1MGQzMzg4MDQ3M2E0N2ZlNjM1ZjBjMGUzYzgyM2JkNzZkYzg0OWNiMDI0NDE2NTUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="
+ )
+ );
+ put(
+ "family_ghast",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aGhast",
+ "69725d7d-1933-3dea-87bd-a3052482ab2c",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGU4YTM4ZTlhZmJkM2RhMTBkMTliNTc3YzU1YzdiZmQ2YjRmMmU0MDdlNDRkNDAxN2IyM2JlOTE2N2FiZmYwMiJ9fX0="
+ )
+ );
+ put(
+ "family_mage_outlaw",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMage Outlaw",
+ "1d16c26c-d937-336f-821a-371968d050c2",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg3Mzk2NywKICAicHJvZmlsZUlkIiA6ICJiNzQ3OWJhZTI5YzQ0YjIzYmE1NjI4MzM3OGYwZTNjNiIsCiAgInByb2ZpbGVOYW1lIiA6ICJTeWxlZXgiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWJlYzk5YjNhMDUwZmQyNzc1Mjg0MDc2NzYzNjZlMjBiOTIwMDZhZDg4ZDE0NzI3YTRkOTllYjhjYjI3M2I2MiIKICAgIH0KICB9Cn0"
+ )
+ );
+ put(
+ "family_magma_cube",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMagma Cube",
+ "35f02923-7bec-3869-9ef5-b42a4794cac8",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
+ )
+ );
+ put(
+ "family_magma_cube_boss",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§6§lMagma Cube Boss",
+ "35f02923-7bec-3869-9ef5-b42a4794cac8",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
+ )
+ );
+ put(
+ "family_matcho",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMatcho",
+ "61db73be-677f-554a-9450-e306a7ff0449",
+ "e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWYyZGFhYmI3OGExZjdhYTEyZDE0NWQ4OGMwY2E0NmI5ZTg1NmY1NTM0ZTkyODZlNTU1ZmFmMGMyOTFmNGZkNSJ9fX0="
+ )
+ );
+ put(
+ "family_charging_mushroom_cow",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMushroom Bull",
+ "2b9eb675-2097-4b51-8fec-c1a51562f19c",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE2M2JjNDE2YjhlNjA1OGY5MmIyMzFlOWE1MjRiN2ZlMTE4ZWI2ZTdlZWFiNGFkMTZkMWI1MmEzZWMwNGZjZCJ9fX0="
+ )
+ );
+ put(
+ "family_pigman",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aPigman",
+ "3fc29372-e78e-3ad6-b0b0-05ca0a84babd",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOWM2ZTk4NTgyZmZkOGZmOGZlYjMzMjJjZDE4NDljNDNmYjE2YjE1OGFiYjExY2E3YjQyZWRhNzc0M2ViIn19fQ=="
+ )
+ );
+ put(
+ "family_wither_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWither Skeleton",
+ "2141b934-c877-3db1-bc6c-7c9a347ffa95",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzk1M2I2YzY4NDQ4ZTdlNmI2YmY4ZmIyNzNkNzIwM2FjZDhlMWJlMTllODE0ODFlYWQ1MWY0NWRlNTlhOCJ9fX0="
+ )
+ );
+ put(
+ "family_wither_spectre",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWither Spectre",
+ "9a1699a4-9b61-37a5-be7a-ca23a1f092a1",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0NDA4Mjg1NzcxMCwKICAicHJvZmlsZUlkIiA6ICIwNTVhOTk2NTk2M2E0YjRmOGMwMjRmMTJmNDFkMmNmMiIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaGVWb3hlbGxlIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdmNWYzMzg0Mzg0ZDdmMDNiZjk3YTczMDk5YjBiYWZiNzJjNTM4ZmMwNDE1YWM4NjEzYjY2NGY4NzU3OWEzNzkiCiAgICB9CiAgfQp9"
+ )
+ );
+
+ // Deep Caverns
+ put(
+ "family_automaton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aAutomaton",
+ "a46a9adf-60a3-38f2-a3dd-335d85f1cc10",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJiY2FjZWViNDE2MmY0MDBkNDQ3NDMzMTU5MzJhYzgyMGQzMTE5YWM4OTg2YTAxNjFhNzI2MTYxY2NjOTNmYyJ9fX0="
+ )
+ );
+ put(
+ "family_butterfly",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§eButterfly",
+ "9dd11ec6-cfea-34df-9336-416c946567bc",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYyNTUxMjE4ODY3NCwKICAicHJvZmlsZUlkIiA6ICI3MzgyZGRmYmU0ODU0NTVjODI1ZjkwMGY4OGZkMzJmOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJJb3lhbCIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS85ZmQ4MDZkZWZkZmRmNTliMWYyNjA5YzhlZTM2NDY2NmRlNjYxMjdhNjIzNDE1YjU0MzBjOTM1OGM2MDFlZjdjIgogICAgfQogIH0KfQ=="
+ )
+ );
+ put(
+ "family_emerald_slime",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aEmerald Slime",
+ "cb762e0d-a1e6-3888-8c05-eddabbbe49a2",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTc3NGU4NmFhNGNmZjc5MjM5NWI3N2FkZDU3YjAwYmIxYTEwMmY4ZjBmMDk4MGY0ZDU1YjNkN2FmZjFlNmRhOSJ9fX0="
+ )
+ );
+ put(
+ "family_caverns_ghost",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aGhost",
+ "c5752211-7503-3e77-9890-d1cf6ba1d0e7",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTgxOTc3OTE4YTExODBlMGRlYzg3OWU2YmNkMWFhMzk0OTQ5NzdiYjkxM2JlMmFiMDFhZmYxZGIxZmE0In19fQ=="
+ )
+ );
+ put(
+ "family_goblin",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aGoblin",
+ "7c7d07db-4911-31f1-9a19-1589899cfe25",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjZiOTcyZTMyZDc2MWIxOTI2MjZlNWQ2ZDAxZWRjMDk0OTQwOTEwMTAzY2VhNWUyZTJkMWYyMzFhZGI3NTVkNSJ9fX0="
+ )
+ );
+ put(
+ "family_team_treasurite",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aGrunt",
+ "a64ccd19-2a64-39a4-b2f5-cb6799c12a99",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYxODE5NTA2MDUwMCwKICAicHJvZmlsZUlkIiA6ICI0ZTMwZjUwZTdiYWU0M2YzYWZkMmE3NDUyY2ViZTI5YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJfdG9tYXRvel8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY1ZTAzYjhkZTExOWY4NTg5YTgwODIyNGNiZWE3MzdmNWRjZjI0MjM1Nzk5YjczNzhhYzViZjA2YWJmNmRkNCIKICAgIH0KICB9Cn0="
+ )
+ );
+ put(
+ "family_ice_walker",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.packed_ice), EnumChatFormatting.AQUA + "§aIce Walker")
+ );
+ put("family_lapis_zombie", Utils.createItemStack(Items.dye, EnumChatFormatting.AQUA + "§aLapis Zombie", 4));
+ put(
+ "family_diamond_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMiner Skeleton",
+ "39c843e6-237b-36b2-8a7b-c5ff5d3ebf99",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODM2YmJjNDIxNWNlYTFiNmE0ODRlODkzYjExNmU3MzQ1OWVmMzZiZmZjNjIyNzQxZTU3N2U5NDkzYTQxZTZlIn19fQ=="
+ )
+ );
+ put(
+ "family_diamond_zombie",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aMiner Zombie",
+ "468210c9-f4bd-34c7-aa8d-2c3d0d5e05c1",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDI4ZDlmZjU0MTg4YTFhZmVlNjViOTRmM2JmY2NlMzIxYzY0M2EzNDU5MGMxNGIxOTJiMmUzZWMyZjUyNWQzIn19fQ=="
+ )
+ );
+ put("family_redstone_pigman", Utils.createItemStack(Items.redstone, EnumChatFormatting.AQUA + "§aRedstone Pigman"));
+ put(
+ "family_sludge",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSludge",
+ "3b70a2f3-319c-38d5-b7d1-5b2425770184",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODk1YWVlYzZiODQyYWRhODY2OWY4NDZkNjViYzQ5NzYyNTk3ODI0YWI5NDRmMjJmNDViZjNiYmI5NDFhYmU2YyJ9fX0="
+ )
+ );
+ put(
+ "family_invisible_creeper",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSneaky Creeper",
+ "81fb1385-b2fc-4d4f-b5bb-0fe9b1d37d60",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYxOTE5MjI5MzI5OCwKICAicHJvZmlsZUlkIiA6ICI0ZjU2ZTg2ODk2OGU0ZWEwYmNjM2M2NzRlNzQ3ODdjOCIsCiAgInByb2ZpbGVOYW1lIiA6ICJDVUNGTDE1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2E2ODIyNGNmOGVkNGMwM2I0NTdiZjQ5YmViNmY1NDQxOTM2NzkyNjhiODQyMWIwMWZmY2U2ZDI3YjI1YWMzMmQiCiAgICB9CiAgfQp9"
+ )
+ );
+ put(
+ "family_thyst",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aThyst",
+ "b3224e56-73d2-32f9-9081-a23b7512035b",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWJjN2I5ZDM2ZmI5MmI2YmYyOTJiZTczZDMyYzZjNWIwZWNjMjViNDQzMjNhNTQxZmFlMWYxZTY3ZTM5M2EzZSJ9fX0="
+ )
+ );
+ put(
+ "family_treasure_hoarder",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aTreasure Hoarder",
+ "b0f13fc2-07a5-3964-8303-784f802e5f0f",
+ "ewogICJ0aW1lc3RhbXAiIDogMTU5MDE1NjYzNDYzOCwKICAicHJvZmlsZUlkIiA6ICI5MWZlMTk2ODdjOTA0NjU2YWExZmMwNTk4NmRkM2ZlNyIsCiAgInByb2ZpbGVOYW1lIiA6ICJoaGphYnJpcyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iMmIxMmE4MTRjZWQ4YWYwMmNkZGYyOWEzN2U3ZjMwMTFlNDMwZThhMThiMzhiNzA2ZjI3YzZiZDMxNjUwYjY1IgogICAgfQogIH0KfQ=="
+ )
+ );
+ put(
+ "family_worms",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWorm",
+ "29f95759-1a6f-3e85-9941-91a7a2275274",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYyMDQ0NTc2NDQ1MSwKICAicHJvZmlsZUlkIiA6ICJmNDY0NTcxNDNkMTU0ZmEwOTkxNjBlNGJmNzI3ZGNiOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJSZWxhcGFnbzA1IiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RmMDNhZDk2MDkyZjNmNzg5OTAyNDM2NzA5Y2RmNjlkZTZiNzI3YzEyMWIzYzJkYWVmOWZmYTFjY2FlZDE4NmMiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ=="
+ )
+ );
+ put(
+ "family_yog",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aYog",
+ "35f02923-7bec-3869-9ef5-b42a4794cac8",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzg5NTdkNTAyM2M5MzdjNGM0MWFhMjQxMmQ0MzQxMGJkYTIzY2Y3OWE5ZjZhYjM2Yjc2ZmVmMmQ3YzQyOSJ9fX0="
+ )
+ );
+
+ // The Park
+ put(
+ "family_howling_spirit",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§bHowling Spirit",
+ "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
+ )
+ );
+ put(
+ "family_pack_spirit",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§bPack Spirit",
+ "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
+ )
+ );
+ put(
+ "family_soul_of_the_alpha",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§3Soul of the Alpha",
+ "802a167c-cbcd-3a1f-becd-5b1a25a4cf15",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjdjOGJlZjZiZWI3N2UyOWFmODYyN2VjZGMzOGQ4NmFhMmZlYTdjY2QxNjNkYzczYzAwZjlmMjU4ZjlhMTQ1NyJ9fX0="
+ )
+ );
+
+ // Spooky
+ put(
+ "family_batty_witch",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§8Crazy Witch",
+ "cf4f97d7-2e1f-3678-9ca3-4a7b9666cc28",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmNlNjYwNDE1N2ZjNGFiNTU5MWU0YmNmNTA3YTc0OTkxOGVlOWM0MWUzNTdkNDczNzZlMGVlNzM0MjA3NGM5MCJ9fX0="
+ )
+ );
+ put(
+ "family_headless_horseman",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§6Headless Horseman",
+ "2594a979-1302-3d6e-a1da-c9dbf0959539",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGM2NTcwZjEyNDI5OTJmNmViYTIzZWU1ODI1OThjMzllM2U3NDUzODMyNzNkZWVmOGIzOTc3NTgzZmUzY2Y1In19fQ=="
+ )
+ );
+ put(
+ "family_phantom_spirit",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§cPhantom Spirit",
+ "805d7035-5f25-37ea-8530-7c0d09156c8e",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYwMzcyMjc5NzYzNywKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjUzYjJmN2M1ZTE3N2JkNjdjZWFkMzBkMGVlNTM0MjVjNzY4NGM5NzVjOGMyYTUyNzNhMDljYTQ5YTFmNmNkZCIKICAgIH0KICB9Cn0="
+ )
+ );
+ put(
+ "family_scary_jerry",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§6Scary Jerry",
+ "127e3dec-4ab7-3798-9410-5fce3f227632",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYwMzczMzU4OTcxOSwKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGYyMDJkYzI0ZDE1ZjdjZTM2ZTAyZmI0YjNlODE1M2IxNDZhYjljMTcyNGFhYTVkNDg0Yzc0MWRhMGVlYjZmZCIKICAgIH0KICB9Cn0="
+ )
+ );
+ put(
+ "family_trick_or_treater",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§eTrick or Treater",
+ "79dd9434-1fde-3aac-87a7-bb09d91eba77",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDdjYmUwNjFiNDQ1Yjg4Y2IyZGY1OWFjY2M4ZDJjMWMxMjExOGZlMGIyMTI3ZTZlNzU4MTM1NTBhZGFjNjdjZiJ9fX0="
+ )
+ );
+ put(
+ "family_wither_gourd",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§6Wither Gourd",
+ "3263c14e-c555-365e-a244-0ee97a8b2056",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjhmMmZmYzZmYjRlOTk1OWI5YTdhMzE3ZjUxYTY3NzVhMTU5ZGRjMjI0MWRiZDZjNzc0ZDNhYzA4YjYifX19"
+ )
+ );
+ put(
+ "family_wraith",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§8Wraith",
+ "bca22b11-8e4c-386a-8824-7b2bd6364cde",
+ "ewogICJ0aW1lc3RhbXAiIDogMTYwMzczMzcxNjI0MiwKICAicHJvZmlsZUlkIiA6ICJhMmY4MzQ1OTVjODk0YTI3YWRkMzA0OTcxNmNhOTEwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJiUHVuY2giLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWVhYmMzMDc1Y2Y0MWYzOGU2ZGYxMjM2Yjk1Y2FhZmNiYTFiZWUyMmM0OWQ4MDRiOTQyNzQ4OGMyZjZlMGVmYyIKICAgIH0KICB9Cn0="
+ )
+ );
+
+ // Dungeons
+ put(
+ "family_diamond_guy",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§d§lAngry Archeologist",
+ "db784d7a-fae1-3d60-9a5a-42a1814037f8",
+ "eyJ0aW1lc3RhbXAiOjE1NzU0NzAzOTQwMzEsInByb2ZpbGVJZCI6IjdkYTJhYjNhOTNjYTQ4ZWU4MzA0OGFmYzNiODBlNjhlIiwicHJvZmlsZU5hbWUiOiJHb2xkYXBmZWwiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M0OGM3ODM0NThlNGNmODUxOGU4YWI1ODYzZmJjNGNiOTQ4ZjkwNTY4ZWViOWE2MGQxNmM0ZmRlMmI5NmMwMzMifX19"
+ )
+ );
+ put(
+ "family_cellar_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aCellar Spider",
+ "a8aee72d-0d1d-3db7-8cf8-be1ce6ec2dc4",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDE2NDVkZmQ3N2QwOTkyMzEwN2IzNDk2ZTk0ZWViNWMzMDMyOWY5N2VmYzk2ZWQ3NmUyMjZlOTgyMjQifX19"
+ )
+ );
+ put(
+ "family_crypt_dreadlord",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aCrypt Dreadlord",
+ "68b4c885-7447-3382-b86b-b661b464d76e",
+ "eyJ0aW1lc3RhbXAiOjE1NjI0Mjc0MTA5MTQsInByb2ZpbGVJZCI6ImIwZDczMmZlMDBmNzQwN2U5ZTdmNzQ2MzAxY2Q5OGNhIiwicHJvZmlsZU5hbWUiOiJPUHBscyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjZmMzQ5MjcwYTNiODUxODk2Y2RhZDg0MmY1ZWVjNmUxNDBiZDkxMTliNzVjMDc0OTU1YzNiZTc4NjVlMjdjNyJ9fX0="
+ )
+ );
+ put(
+ "family_crypt_lurker",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aCrypt Lurker",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ put(
+ "family_crypt_souleater",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aCrypt Souleater",
+ "68b4c885-7447-3382-b86b-b661b464d76e",
+ "eyJ0aW1lc3RhbXAiOjE1NjI0Mjc0MTA5MTQsInByb2ZpbGVJZCI6ImIwZDczMmZlMDBmNzQwN2U5ZTdmNzQ2MzAxY2Q5OGNhIiwicHJvZmlsZU5hbWUiOiJPUHBscyIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjZmMzQ5MjcwYTNiODUxODk2Y2RhZDg0MmY1ZWVjNmUxNDBiZDkxMTliNzVjMDc0OTU1YzNiZTc4NjVlMjdjNyJ9fX0="
+ )
+ );
+ put(
+ "family_king_midas",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§d§lKing Midas",
+ "1a85d923-f8dd-35b8-899a-8f13b9469b0c",
+ "ewogICJ0aW1lc3RhbXAiIDogMTU5MTU3NjA3MDMwMCwKICAicHJvZmlsZUlkIiA6ICJkYTQ5OGFjNGU5Mzc0ZTVjYjYxMjdiMzgwODU1Nzk4MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOaXRyb2hvbGljXzIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiY2EwODU3NTAwNDM1MDNmNWRmOWY3ZGVmODI0YTJlM2FjZmMyNzg0MmJjZDA5ZDJiNjY5NTg4MWU4MzJmNSIKICAgIH0KICB9Cn0="
+ )
+ );
+ put(
+ "family_lonely_spider",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aLonely Spider",
+ "7c63f3cf-a963-311a-aeca-3a075b417806",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2Q1NDE1NDFkYWFmZjUwODk2Y2QyNThiZGJkZDRjZjgwYzNiYTgxNjczNTcyNjA3OGJmZTM5MzkyN2U1N2YxIn19fQ=="
+ )
+ );
+ put(
+ "family_lost_adventurer",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§d§lLost Adventurer",
+ "f69ba621-a8b6-31a7-8de1-dc7ade140e1d",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzFlMDMyOWY0MjE5MmVlN2MxYTBjNzA0ZjgyZGJiYmU3YzAwZmJmYTNmMDIwYzEwNjdhMjA4NjMwYjk5MWI5ODgifX19"
+ )
+ );
+ put(
+ "family_scared_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aScared Skeleton",
+ "53924f1a-87e6-4709-8e53-f1c7d13dc239",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
+ )
+ );
+ put(
+ "family_shadow_assassin",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§d§lShadow Assassin",
+ "ef18719c-db6a-3ffb-97ca-4ed764ce9464",
+ "ewogICJ0aW1lc3RhbXAiIDogMTU5MjI2ODE3MDkxMSwKICAicHJvZmlsZUlkIiA6ICJkYTQ5OGFjNGU5Mzc0ZTVjYjYxMjdiMzgwODU1Nzk4MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJOaXRyb2hvbGljXzIiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM5OWUwMGY0MDQ0MTFlNDY1ZDc0Mzg4ZGYxMzJkNTFmZTg2OGVjZjg2ZjFjMDczZmFmZmExZDkxNzJlYzBmMyIKICAgIH0KICB9Cn0="
+ )
+ );
+ put(
+ "family_skeleton_grunt",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSkeleton Grunt",
+ "dfed3415-919e-3358-b563-0abd0513f74c",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzA0NzE2NzdiMzdhZTg0MmMyYmQyMzJlMTZlZWI4NGQ1YTQ5MzIzMWVlY2VjMDcyZGEzOGJlMzEyN2RkNWM4In19fQ=="
+ )
+ );
+ put(
+ "family_skeleton_master",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSkeleton Master",
+ "ce22e0d7-c78e-3c8d-907a-2368c927808c",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzRlOTVlMWI3ZGM4MmJhNzg0NWE2OGZjNmEzMTJmNGNkOTBlZTJmNmNjZTI2YTY4Yzg4YjA0YjEwNzJkODc5In19fQ=="
+ )
+ );
+ put(
+ "family_skeleton_soldier",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSkeleton Soldier",
+ "cab75065-c896-338e-a399-c4a6da16d678",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjE5Njg4ZTBjMmYwNWFlYjk3OWQ2YTFiOGM5MTE5NTdiN2QzNjU3ZTE0YjU3YWY5M2M1ZWY2ZjZhNTk1NjlkZCJ9fX0="
+ )
+ );
+ put(
+ "family_skeletor",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSkeletor",
+ "49fcfb3e-da7e-3fda-b4f9-37df5ac8fbd3",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODlkMDc0YWQ5Yjk5NzE4NzllYjMyNWJkZGZmMzY3NWY3MjI0ODU2YmQ2ZDU2OWZjOGQ0ODNjMTMzZDczMDA1ZCJ9fX0K"
+ )
+ );
+ put(
+ "family_sniper_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSniper",
+ "848130dc-9c46-3818-a099-b429cb2f1d75",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjE4YzA3MWYwODBkYmE1MGE2MmE2MjYzZmY3MjRlZGMxNTdjZTRmYjQ4ODNjY2VmZjI0OTFkNWJiZGU4MzBjMSJ9fX0K"
+ )
+ );
+ put(
+ "family_super_archer",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSuper Archer",
+ "8ebf155b-7b8f-386f-91f1-2e425db4230f",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGNhZTZkYjBiNTlhNjQzMDUwNzZkOTY2ZDhlN2I5YTk3YmU0NmRhZTNhODA3NzE0ZmE4NmQzNzg0OGY2In19fQ=="
+ )
+ );
+ put(
+ "family_super_tank_zombie",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aSuper Tank Zombie",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ put(
+ "family_crypt_tank_zombie",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aTank Zombie",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ put(
+ "family_watcher_summon_undead",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§a§4§lUndead",
+ "0ac53e90-4e60-388c-a754-092dd4578592",
+ "eyJ0aW1lc3RhbXAiOjE1ODYwNDAyMDM1NzMsInByb2ZpbGVJZCI6ImRhNDk4YWM0ZTkzNzRlNWNiNjEyN2IzODA4NTU3OTgzIiwicHJvZmlsZU5hbWUiOiJOaXRyb2hvbGljXzIiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Y0NjI0YTlhOGM2OWNhMjA0NTA0YWJiMDQzZDQ3NDU2Y2Q5YjA5NzQ5YTM2MzU3NDYyMzAzZjI3NmEyMjlkNCJ9fX0="
+ )
+ );
+ put(
+ "family_dungeon_respawning_skeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aUndead Skeleton",
+ "53924f1a-87e6-4709-8e53-f1c7d13dc239",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMTgzNjcwNCwKICAicHJvZmlsZUlkIiA6ICI1MzkyNGYxYTg3ZTY0NzA5OGU1M2YxYzdkMTNkYzIzOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJUaHJvd3BvIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg4ZWI2OGE0ZDM4ZTlmNDQ2YjhlOTkyNzVmMTYwMzAyZjM2NmVmMTAyMTZhYmY5NDg0ODdlNTgyNTEyYmQwZjMiCiAgICB9CiAgfQp9="
+ )
+ );
+ put(
+ "family_crypt_witherskeleton",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aWithermancer",
+ "d0e05de7-6067-454d-beae-c6d19d886191",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY1NTYzMjg1MTE1NCwKICAicHJvZmlsZUlkIiA6ICJkMGUwNWRlNzYwNjc0NTRkYmVhZWM2ZDE5ZDg4NjE5MSIsCiAgInByb2ZpbGVOYW1lIiA6ICJNb3VsYmVycnkiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmNlMTU1MjI0ZWE0YmM0OWE4ZTkxOTA3MzdjYjA0MTdkOGE3YzM4YTAzN2Q4ZDAzODJkZGU0ODI5YzEwMzU5MCIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9"
+ )
+ );
+ put(
+ "family_zombie_commander",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie Commander",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ put(
+ "family_zombie_grunt",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie Grunt",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ put(
+ "family_zombie_knight",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie Knight",
+ "34af9e21-dff4-3b94-9fb5-07816e41af75",
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjVkMmYzMWJhMTYyZmU2MjcyZTgzMWFlZDE3ZjUzMjEzZGI2ZmExYzRjYmU0ZmM4MjdmMzk2M2NjOThiOSJ9fX0="
+ )
+ );
+ put(
+ "family_zombie_soldier",
+ Utils.createSkull(
+ EnumChatFormatting.AQUA + "§aZombie Soldier",
+ "9673d491-d589-44cb-b63e-5f8b3148b3df",
+ "ewogICJ0aW1lc3RhbXAiIDogMTY0Njc1NjU2MzM1MiwKICAicHJvZmlsZUlkIiA6ICJkYmQ4MDQ2M2EwMzY0Y2FjYjI3OGNhODBhMDBkZGIxMyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ4bG9nMjEiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjM2NjZkMWJkZjQ1NThiMGQxNjk5MGIyNDFlODE4NWNiZjU4YzNlMDNjMjRkOTA0NTQ0ZThjYzY1YjFjMzhkMSIKICAgIH0KICB9Cn0=\", \"n8vct7fj3NdiODy/h6PJhjxSR2U7d8gQxHjdVq553HqG60SSczt1Tl9XhvQbZP14ZrJGWxCziauuYb/HjZza0ugNAhfwh9z8hqR1PjBJGdvp+wpxoWpP2wd5RT9i5/GYEqpiAIAt9vHY1YeyejFqKZhXaGgp7gZZNjOQWQqB0SZzTUTAPzRW9FiY8x2re7H7Y1POThRXOvvkeQ6qWdPV6Hk5hTumV0rfEGm971jQRIbfdzBZDJRcro+8y+dlje/NpF5qf0JLy78Xr4hc2cwbT9+wqOeoUTcM/r9mwL15OKgFLjB44jszauKRHNfoqb6B3+1fNQEJrJK/7hIyvswpde7C5uOxkE7oMFib6X68VVEhb6PGC1+HWNaMaGjI0wWEkCahp48ihN9+sBEBFXOxIAhXG/pvJcbEi742/cBS1CTtOI8qui6JSL9MKX5jmyhtjjibOYRZbacosqayCnwsJAdMmwS7zIxc8jGhpfKECiSni/baS4zRla0bns4hfEM0l7ASv0Dh99WQD0We2ZMqltmix8lMEaAILXJVBln3CFrjYvncfku2hrSaqu1lNAtfMYYSITEUCBJ7McVAVmUHOrER0XGoVs9L237H0BQNSLqlGGEQ7OM8HV6G0YfXGlbNgNBx6O9k8ZijuK60JeEoJapcmbNj/LVHEU+dsgcFAbo="
+ )
+ );
+ }
+ };
+ private static final LinkedHashMap<String, String> mobTypeMap = new LinkedHashMap<String, String>() {
+ {
+ // Island
+ put("family_cave_spider", "ISLAND");
+ put("family_enderman_private", "ISLAND");
+ put("family_skeleton", "ISLAND");
+ put("family_slime", "ISLAND");
+ put("family_spider", "ISLAND");
+ put("family_witch", "ISLAND");
+ put("family_zombie", "ISLAND");
+
+ // Hub
+ put("family_unburried_zombie", "MOB");
+ put("family_old_wolf", "MOB");
+ put("family_ruin_wolf", "MOB");
+ put("family_zombie_villager", "MOB");
+
+ // Spiders Den
+ put("family_arachne", "BOSS");
+ put("family_arachne_brood", "MOB");
+ put("family_arachne_keeper", "MOB");
+ put("family_brood_mother_spider", "BOSS");
+ put("family_dasher_spider", "MOB");
+ put("family_respawning_skeleton", "MOB");
+ put("family_random_slime", "MOB");
+ put("family_spider_jockey", "MOB");
+ put("family_splitter_spider", "MOB");
+ put("family_voracious_spider", "MOB");
+ put("family_weaver_spider", "MOB");
+
+ // The End
+ put("family_dragon", "BOSS");
+ put("family_enderman", "MOB");
+ put("family_endermite", "MOB");
+ put("family_corrupted_protector", "BOSS");
+ put("family_obsidian_wither", "MOB");
+ put("family_voidling_extremist", "MOB");
+ put("family_voidling_fanatic", "MOB");
+ put("family_watcher", "MOB");
+ put("family_zealot_enderman", "MOB");
+
+ // Crimson Isles
+ put("family_ashfang", "BOSS");
+ put("family_barbarian_duke_x", "BOSS");
+ put("family_bladesoul", "BOSS");
+ put("family_blaze", "MOB");
+ put("family_flaming_spider", "MOB");
+ put("family_ghast", "MOB");
+ put("family_mage_outlaw", "BOSS");
+ put("family_magma_cube", "MOB");
+ put("family_magma_cube_boss", "BOSS");
+ put("family_matcho", "MOB");
+ put("family_charging_mushroom_cow", "MOB");
+ put("family_pigman", "MOB");
+ put("family_wither_skeleton", "MOB");
+ put("family_wither_spectre", "MOB");
+
+ // Deep Caverns
+ put("family_automaton", "MOB");
+ put("family_butterfly", "MOB");
+ put("family_emerald_slime", "MOB");
+ put("family_caverns_ghost", "MOB");
+ put("family_goblin", "MOB");
+ put("family_team_treasurite", "MOB");
+ put("family_ice_walker", "MOB");
+ put("family_lapis_zombie", "MOB");
+ put("family_diamond_skeleton", "MOB");
+ put("family_diamond_zombie", "MOB");
+ put("family_redstone_pigman", "MOB");
+ put("family_sludge", "MOB");
+ put("family_invisible_creeper", "MOB");
+ put("family_thyst", "MOB");
+ put("family_treasure_hoarder", "MOB");
+ put("family_worms", "MOB");
+ put("family_yog", "MOB");
+
+ // The Park
+ put("family_howling_spirit", "MOB");
+ put("family_pack_spirit", "MOB");
+ put("family_soul_of_the_alpha", "MOB");
+
+ // Spooky
+ put("family_batty_witch", "MOB");
+ put("family_headless_horseman", "BOSS");
+ put("family_phantom_spirit", "MOB");
+ put("family_scary_jerry", "MOB");
+ put("family_trick_or_treater", "MOB");
+ put("family_wither_gourd", "MOB");
+ put("family_wraith", "MOB");
+
+ // Catacombs
+ put("family_diamond_guy", "MOB");
+ put("family_cellar_spider", "MOB");
+ put("family_crypt_dreadlord", "MOB");
+ put("family_crypt_lurker", "MOB");
+ put("family_crypt_souleater", "MOB");
+ put("family_king_midas", "MOB");
+ put("family_lonely_spider", "MOB");
+ put("family_lost_adventurer", "MOB");
+ put("family_scared_skeleton", "MOB");
+ put("family_shadow_assassin", "MOB");
+ put("family_skeleton_grunt", "MOB");
+ put("family_skeleton_master", "MOB");
+ put("family_skeleton_soldier", "MOB");
+ put("family_skeletor", "MOB");
+ put("family_sniper_skeleton", "MOB");
+ put("family_super_archer", "MOB");
+ put("family_super_tank_zombie", "MOB");
+ put("family_crypt_tank_zombie", "MOB");
+ put("family_watcher_summon_undead", "MOB");
+ put("family_dungeon_respawning_skeleton", "MOB");
+ put("family_crypt_witherskeleton", "MOB");
+ put("family_zombie_commander", "MOB");
+ put("family_zombie_grunt", "MOB");
+ put("family_zombie_knight", "MOB");
+ put("family_zombie_soldier", "MOB");
+ }
+ };
+
+ public static LinkedHashMap<ItemStack, List<String>> getBestiaryLocations() {
+ return bestiaryLocations;
+ }
+
+ public static LinkedHashMap<String, ItemStack> getBestiaryMobs() {
+ return bestiaryMobs;
+ }
+
+ public static LinkedHashMap<String, String> getMobType() {
+ return mobTypeMap;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java
new file mode 100644
index 00000000..70ea051a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/bestiary/BestiaryPage.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.bestiary;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+public class BestiaryPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
+ private static final ResourceLocation BESTIARY_TEXTURE = new ResourceLocation("notenoughupdates:pv_bestiary_tab.png");
+ private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
+ private static final int XCOUNT = 7;
+ private static final int YCOUNT = 5;
+ private static final float XPADDING = (190 - XCOUNT * 20) / (float) (XCOUNT + 1);
+ private static final float YPADDING = (202 - YCOUNT * 20) / (float) (YCOUNT + 1);
+ private ItemStack selectedBestiaryLocation = null;
+ private List<String> tooltipToDisplay = null;
+
+ public BestiaryPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+ JsonObject profileInfo = GuiProfileViewer.getProfile().getProfileInformation(GuiProfileViewer.getProfileId());
+
+ int bestiarySize = BestiaryData.getBestiaryLocations().size();
+ int bestiaryXSize = (int) (350f / (bestiarySize - 1 + 0.0000001f));
+
+ {
+ int yIndex = 0;
+ for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ if (mouseX > guiLeft + 30 + bestiaryXSize * yIndex && mouseX < guiLeft + 30 + bestiaryXSize * yIndex + 20) {
+ if (mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20) {
+ tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ }
+ }
+ if (stack == selectedBestiaryLocation) {
+ Utils.drawTexturedRect(
+ guiLeft + 30 + bestiaryXSize * yIndex,
+ guiTop + 10,
+ 20,
+ 20,
+ 20 / 256f,
+ 0,
+ 20 / 256f,
+ 0,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12);
+ } else {
+ Utils.drawTexturedRect(
+ guiLeft + 30 + bestiaryXSize * yIndex,
+ guiTop + 10,
+ 20,
+ 20,
+ 0,
+ 20 / 256f,
+ 0,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStack(stack, guiLeft + 32 + bestiaryXSize * yIndex, guiTop + 12);
+ }
+ yIndex++;
+ }
+ }
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BESTIARY_TEXTURE);
+ Utils.drawTexturedRect(guiLeft, guiTop, 431, 202, GL11.GL_NEAREST);
+
+ GlStateManager.color(1, 1, 1, 1);
+ Color color = new Color(128, 128, 128, 255);
+ Utils.renderAlignedString(
+ EnumChatFormatting.RED + "Bestiary Level: ",
+ EnumChatFormatting.GRAY + "" + (float) getBestiaryTiers(profileInfo) / 10,
+ guiLeft + 220,
+ guiTop + 50,
+ 110
+ );
+
+ GlStateManager.disableLighting();
+ RenderHelper.enableGUIStandardItemLighting();
+ List<String> mobs = BestiaryData.getBestiaryLocations().get(selectedBestiaryLocation);
+ if (mobs != null) {
+ for (int i = 0; i < mobs.size(); i++) {
+ String mob = mobs.get(i);
+ if (mob != null) {
+ ItemStack mobItem = BestiaryData.getBestiaryMobs().get(mob);
+ if (mobItem != null) {
+ int xIndex = i % XCOUNT;
+ int yIndex = i / XCOUNT;
+
+ float x = 23 + XPADDING + (XPADDING + 20) * xIndex;
+ float y = 30 + YPADDING + (YPADDING + 20) * yIndex;
+
+ float completedness = 0;
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y,
+ 20,
+ 20 * (1 - completedness),
+ 0,
+ 20 / 256f,
+ 0,
+ 20 * (1 - completedness) / 256f,
+ GL11.GL_NEAREST
+ );
+ //GlStateManager.color(1, 185 / 255f, 0, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(
+ guiLeft + x,
+ guiTop + y + 20 * (1 - completedness),
+ 20,
+ 20 * (completedness),
+ 0,
+ 20 / 256f,
+ 20 * (1 - completedness) / 256f,
+ 20 / 256f,
+ GL11.GL_NEAREST
+ );
+ Utils.drawItemStack(mobItem, guiLeft + (int) x + 2, guiTop + (int) y + 2);
+ float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0);
+ float deaths = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.deaths_" + mob), 0);
+
+ String type;
+ if (BestiaryData.getMobType().get(mob) != null) {
+ type = BestiaryData.getMobType().get(mob);
+ } else {
+ type = "MOB";
+ }
+ JsonObject leveling = Constants.LEVELING;
+ ProfileViewer.Level level = null;
+ if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) {
+ JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray();
+ int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0);
+ level = ProfileViewer.getLevel(levelingArray, kills, levelCap, false);
+ } else {
+ Utils.showOutdatedRepoNotification();
+ }
+
+ float levelNum = -1;
+ if (level != null) {
+ levelNum = level.level;
+ }
+ if (mouseX > guiLeft + (int) x + 2 && mouseX < guiLeft + (int) x + 18) {
+ if (mouseY > guiTop + (int) y + 2 && mouseY < guiTop + (int) y + 18) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(
+ mobItem.getDisplayName() + " " + ((levelNum == -1) ? "?" : (int) Math.floor(levelNum))
+ );
+ tooltipToDisplay.add(
+ EnumChatFormatting.GRAY + "Kills: " + EnumChatFormatting.GREEN + numberFormat.format(kills)
+ );
+ tooltipToDisplay.add(
+ EnumChatFormatting.GRAY + "Deaths: " + EnumChatFormatting.GREEN + numberFormat.format(deaths)
+ );
+ if (level != null) {
+ String progressStr;
+ if (level.maxed) {
+ progressStr = EnumChatFormatting.GOLD + "MAXED!";
+ } else {
+ progressStr = EnumChatFormatting.AQUA +
+ StringUtils.shortNumberFormat(Math.round((levelNum % 1) * level.maxXpForLevel)) +
+ "/" +
+ StringUtils.shortNumberFormat(level.maxXpForLevel);
+ }
+ tooltipToDisplay.add(EnumChatFormatting.GRAY + "Progress: " + progressStr);
+ }
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ // if (tier >= 0) {
+ // Utils.drawStringCentered(tierString, Minecraft.getMinecraft().fontRendererObj,
+ // guiLeft + x + 10, guiTop + y - 4, true,
+ // tierStringColour
+ // );
+ // }
+ Utils.drawStringCentered(
+ (int) Math.floor(levelNum) + "",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + x + 10,
+ guiTop + y + 26,
+ true,
+ color.getRGB()
+ );
+ }
+ }
+ }
+ }
+ if (tooltipToDisplay != null) {
+ List<String> grayTooltip = new ArrayList<>(tooltipToDisplay.size());
+ for (String line : tooltipToDisplay) {
+ grayTooltip.add(EnumChatFormatting.GRAY + line);
+ }
+ Utils.drawHoveringText(grayTooltip, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
+ tooltipToDisplay = null;
+ }
+ }
+
+ @Override
+ public void mouseReleased(int mouseX, int mouseY, int mouseButton) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ int bestiarySize = BestiaryData.getBestiaryLocations().size();
+ int bestiaryYSize = (int) (350f / (bestiarySize - 1 + 0.0000001f));
+ int yIndex = 0;
+ for (ItemStack stack : BestiaryData.getBestiaryLocations().keySet()) {
+ if (mouseX > guiLeft + 30 + bestiaryYSize * yIndex && mouseX < guiLeft + 30 + bestiaryYSize * yIndex + 20) {
+ if (mouseY > guiTop + 10 && mouseY < guiTop + 10 + 20) {
+ selectedBestiaryLocation = stack;
+ Utils.playPressSound();
+ return;
+ }
+ }
+ yIndex++;
+ }
+ }
+
+ private int getBestiaryTiers(JsonObject profileInfo) {
+ int beLevel = 0;
+ for (ItemStack items : BestiaryData.getBestiaryLocations().keySet()) {
+ List<String> mobs = BestiaryData.getBestiaryLocations().get(items);
+ if (mobs != null) {
+ for (String mob : mobs) {
+ if (mob != null) {
+ float kills = Utils.getElementAsFloat(Utils.getElement(profileInfo, "bestiary.kills_" + mob), 0);
+ String type;
+ if (BestiaryData.getMobType().get(mob) != null) {
+ type = BestiaryData.getMobType().get(mob);
+ } else {
+ type = "MOB";
+ }
+ JsonObject leveling = Constants.LEVELING;
+ ProfileViewer.Level level = null;
+ if (leveling != null && Utils.getElement(leveling, "bestiary." + type) != null) {
+ JsonArray levelingArray = Utils.getElement(leveling, "bestiary." + type).getAsJsonArray();
+ int levelCap = Utils.getElementAsInt(Utils.getElement(leveling, "bestiary.caps." + type), 0);
+ level = ProfileViewer.getLevel(levelingArray, kills, levelCap, false);
+ }
+
+ float levelNum = 0;
+ if (level != null) {
+ levelNum = level.level;
+ }
+ beLevel += (int) Math.floor(levelNum);
+ }
+ }
+ }
+ }
+ return beLevel;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java
new file mode 100644
index 00000000..b4d92325
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/info/QuiverInfo.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.info;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class QuiverInfo {
+ public String selectedArrow;
+ public Map<String, Integer> arrows;
+
+ public List<String> generateProfileViewerTooltip() {
+ List<String> list = new ArrayList<>();
+ int totalCount = 0;
+ list.add(EnumChatFormatting.AQUA + "Quiver:");
+ for (Map.Entry<String, Integer> arrow : arrows.entrySet()) {
+ JsonObject repoInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(arrow.getKey());
+ if (repoInfo == null || repoInfo.isJsonNull()) {
+ continue;
+ }
+ list.add(
+ " " + repoInfo.get("displayname").getAsString() + EnumChatFormatting.RESET + ": " + EnumChatFormatting.GREEN +
+ EnumChatFormatting.BOLD + arrow.getValue());
+ totalCount += arrow.getValue();
+ }
+
+ list.add("");
+ list.add(EnumChatFormatting.AQUA + "Total: " + EnumChatFormatting.GREEN + EnumChatFormatting.BOLD + totalCount);
+ if (selectedArrow != null) {
+ JsonObject repoInfo = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(selectedArrow);
+ if (repoInfo == null) {
+ list.add(EnumChatFormatting.AQUA + "Selected Arrow: " + EnumChatFormatting.RED + "ERROR");
+ } else {
+ list.add(EnumChatFormatting.AQUA + "Selected Arrow: " + repoInfo.get("displayname").getAsString());
+ }
+ }
+
+ return list;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java
new file mode 100644
index 00000000..5a3027c3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFish.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.trophy;
+
+import java.util.Map;
+
+public class TrophyFish {
+
+ public final Map<TrophyFishRarity, Integer> trophyFishRarityIntegerMap;
+ private final String name;
+ private int total = 0;
+
+ public TrophyFish(String name, Map<TrophyFishRarity, Integer> trophyFishRarityIntegerMap) {
+ this.name = name;
+ this.trophyFishRarityIntegerMap = trophyFishRarityIntegerMap;
+ }
+
+ public void addTotal(int n) {
+ total += n;
+ }
+
+ public int getTotal() {
+ return total;
+ }
+
+ public void removeTotal(int n) {
+ total -= n;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Map<TrophyFishRarity, Integer> getTrophyFishRarityIntegerMap() {
+ return trophyFishRarityIntegerMap;
+ }
+
+ public void add(TrophyFishRarity rarity, int value) {
+ if (!trophyFishRarityIntegerMap.containsKey(rarity)) {
+ trophyFishRarityIntegerMap.put(rarity, value);
+ }
+ }
+
+ public String getInternalName() {
+ return name.toLowerCase().replace(" ", "_");
+ }
+
+ public enum TrophyFishRarity {
+ BRONZE,
+ SILVER,
+ GOLD,
+ DIAMOND,
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java
new file mode 100644
index 00000000..cda47ffd
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/trophy/TrophyFishPage.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.trophy;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewerPage;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderHelper;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.apache.commons.lang3.text.WordUtils;
+import org.apache.commons.lang3.tuple.Pair;
+import org.lwjgl.opengl.GL11;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class TrophyFishPage extends GuiProfileViewerPage {
+
+ public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
+ private static final Map<String, EnumChatFormatting> internalTrophyFish = new HashMap<String, EnumChatFormatting>() {
+ {
+ put("gusher", EnumChatFormatting.WHITE);
+ put("flyfish", EnumChatFormatting.GREEN);
+ put("moldfin", EnumChatFormatting.DARK_PURPLE);
+ put("vanille", EnumChatFormatting.BLUE);
+ put("blobfish", EnumChatFormatting.WHITE);
+ put("mana_ray", EnumChatFormatting.BLUE);
+ put("slugfish", EnumChatFormatting.GREEN);
+ put("soul_fish", EnumChatFormatting.DARK_PURPLE);
+ put("lava_horse", EnumChatFormatting.BLUE);
+ put("golden_fish", EnumChatFormatting.GOLD);
+ put("karate_fish", EnumChatFormatting.DARK_PURPLE);
+ put("skeleton_fish", EnumChatFormatting.DARK_PURPLE);
+ put("sulphur_skitter", EnumChatFormatting.WHITE);
+ put("obfuscated_fish_1", EnumChatFormatting.WHITE);
+ put("obfuscated_fish_2", EnumChatFormatting.GREEN);
+ put("obfuscated_fish_3", EnumChatFormatting.BLUE);
+ put("volcanic_stonefish", EnumChatFormatting.BLUE);
+ put("steaming_hot_flounder", EnumChatFormatting.WHITE);
+ }
+ };
+ private static final LinkedHashMap<ItemStack, Pair<String, Integer>> armorHelmets = new LinkedHashMap<ItemStack, Pair<String, Integer>>() {
+ {
+ put(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("BRONZE_HUNTER_HELMET")
+ ),
+ Pair.of(EnumChatFormatting.GREEN + "Novice Fisher", 1)
+ );
+ put(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("SILVER_HUNTER_HELMET")
+ ),
+ Pair.of(EnumChatFormatting.BLUE + "Adept Fisher", 2)
+ );
+ put(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("GOLD_HUNTER_HELMET")
+ ),
+ Pair.of(EnumChatFormatting.DARK_PURPLE + "Expert Fisher", 3)
+ );
+ put(
+ NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("DIAMOND_HUNTER_HELMET")
+ ),
+ Pair.of(EnumChatFormatting.GOLD + "Master Fisher", 4)
+ );
+ }
+ };
+ private static final Map<Integer, Pair<Integer, Integer>> slotLocations = new HashMap<Integer, Pair<Integer, Integer>>() {
+ {
+ put(0, Pair.of(277, 46));
+ put(1, Pair.of(253, 58));
+ put(2, Pair.of(301, 58));
+ put(3, Pair.of(229, 70));
+ put(4, Pair.of(325, 70));
+ put(5, Pair.of(277, 70));
+ put(6, Pair.of(253, 82));
+ put(7, Pair.of(301, 82));
+ put(8, Pair.of(229, 94));
+ put(9, Pair.of(325, 94));
+ put(10, Pair.of(253, 106));
+ put(11, Pair.of(301, 106));
+ put(12, Pair.of(277, 118));
+ put(13, Pair.of(229, 118));
+ put(14, Pair.of(325, 118));
+ put(15, Pair.of(253, 130));
+ put(16, Pair.of(301, 130));
+ put(17, Pair.of(277, 142));
+ }
+ };
+ private static final ResourceLocation TROPHY_FISH_TEXTURE = new ResourceLocation("notenoughupdates:pv_trophy_fish_tab.png");
+ private static final String checkX = "§c✖";
+ private static final String check = "§a✔";
+ private final Map<String, Integer> total = new HashMap<>();
+ private final Map<String, TrophyFish> trophyFishList = new HashMap<>();
+ private long totalCount = 0;
+
+ public TrophyFishPage(GuiProfileViewer instance) {
+ super(instance);
+ }
+
+ @Override
+ public void drawPage(int mouseX, int mouseY, float partialTicks) {
+ int guiLeft = GuiProfileViewer.getGuiLeft();
+ int guiTop = GuiProfileViewer.getGuiTop();
+
+ trophyFishList.clear();
+
+ JsonObject profileInformation = GuiProfileViewer.getProfile().getProfileInformation(GuiProfileViewer.getProfileId());
+ if (profileInformation == null || !profileInformation.has("trophy_fish")) {
+ Utils.drawStringCentered(
+ EnumChatFormatting.RED + "No data found",
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 431 / 2f,
+ guiTop + 101,
+ true,
+ 0
+ );
+ return;
+ }
+ JsonObject trophyObject = profileInformation.get("trophy_fish").getAsJsonObject();
+
+ loadTrophyInformation(trophyObject);
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TROPHY_FISH_TEXTURE);
+ Utils.drawTexturedRect(guiLeft, guiTop, 431, 202, GL11.GL_NEAREST);
+
+ GlStateManager.color(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+ RenderHelper.enableGUIStandardItemLighting();
+
+ JsonObject stats = profileInformation.get("stats").getAsJsonObject();
+
+ int thunderKills = 0;
+ if (stats.has("kills_thunder")) {
+ thunderKills = stats.getAsJsonObject().get("kills_thunder").getAsInt();
+ }
+ ItemStack thunder_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("THUNDER_SC")
+ );
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(thunder_sc, guiLeft + 16, guiTop + 108);
+
+ Utils.drawStringF(
+ EnumChatFormatting.AQUA + "Thunder Kills: §f" + thunderKills,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 36,
+ guiTop + 112,
+ true,
+ 0
+ );
+
+ ItemStack lord_jawbus_sc = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("LORD_JAWBUS_SC")
+ );
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(lord_jawbus_sc, guiLeft + 16, guiTop + 120);
+ int jawbusKills = 0;
+ if (stats.has("kills_lord_jawbus")) {
+ jawbusKills = stats.getAsJsonObject().get("kills_lord_jawbus").getAsInt();
+ }
+
+ Utils.drawStringF(
+ EnumChatFormatting.AQUA + "Lord Jawbus Kills: §f" + jawbusKills,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 36,
+ guiTop + 124,
+ true,
+ 0
+ );
+
+ ItemStack fishing_rod = NotEnoughUpdates.INSTANCE.manager.jsonToStack(
+ NotEnoughUpdates.INSTANCE.manager.getItemInformation().get("FISHING_ROD")
+ );
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(fishing_rod, guiLeft + 20, guiTop + 21);
+
+ Utils.drawStringF(
+ EnumChatFormatting.AQUA + "Total Caught: §f" + totalCount,
+ Minecraft.getMinecraft().fontRendererObj,
+ guiLeft + 38,
+ guiTop + 25,
+ true,
+ 0
+ );
+
+ ArrayList<TrophyFish> arrayList = new ArrayList<>(trophyFishList.values());
+ arrayList.sort((c1, c2) -> Integer.compare(c2.getTotal(), c1.getTotal()));
+
+ int x;
+ int y;
+ for (TrophyFish value : arrayList) {
+ x = guiLeft + slotLocations.get(arrayList.indexOf(value)).getLeft();
+ y = guiTop + slotLocations.get(arrayList.indexOf(value)).getRight();
+ RenderHelper.enableGUIStandardItemLighting();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap = value.getTrophyFishRarityIntegerMap();
+ if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.BRONZE)) {
+ GlStateManager.color(255 / 255f, 130 / 255f, 0 / 255f, 1);
+ }
+ if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.SILVER)) {
+ GlStateManager.color(192 / 255f, 192 / 255f, 192 / 255f, 1);
+ }
+ if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.GOLD)) {
+ GlStateManager.color(1, 0.82F, 0, 1);
+ }
+ if (trophyFishRarityIntegerMap.containsKey(TrophyFish.TrophyFishRarity.DIAMOND)) {
+ GlStateManager.color(31 / 255f, 216 / 255f, 241 / 255f, 1);
+ }
+ Utils.drawTexturedRect(x - 2, y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(getItem(value.getName()), x, y);
+
+ if (mouseX >= x && mouseX < x + 24) {
+ if (mouseY >= y && mouseY <= y + 24) {
+ Utils.drawHoveringText(
+ getTooltip(value.getName(), value.getTrophyFishRarityIntegerMap()),
+ mouseX,
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+ }
+
+ if (arrayList.size() != internalTrophyFish.size()) {
+ List<String> clonedList = new ArrayList<>(internalTrophyFish.size());
+ clonedList.addAll(internalTrophyFish.keySet());
+ clonedList.removeAll(fixStringName(new ArrayList<>(trophyFishList.keySet())));
+ for (String difference : clonedList) {
+ RenderHelper.enableGUIStandardItemLighting();
+ x = guiLeft + slotLocations.get(clonedList.indexOf(difference) + (trophyFishList.keySet().size())).getLeft();
+ y = guiTop + slotLocations.get(clonedList.indexOf(difference) + (trophyFishList.keySet().size())).getRight();
+ ItemStack itemStack = new ItemStack(Items.dye, 1, 8);
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y);
+ if (mouseX >= x && mouseX < x + 24) {
+ if (mouseY >= y && mouseY <= y + 24) {
+ Utils.drawHoveringText(
+ getTooltip(difference, null),
+ mouseX,
+ mouseY,
+ width,
+ height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ GlStateManager.color(1, 1, 1, 1);
+ }
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(x - 2, y - 2, 20, 20, 0, 20 / 256f, 0, 20 / 256f, GL11.GL_NEAREST);
+ }
+ }
+
+ if (!trophyObject.has("rewards")) return;
+
+ int[] trophiesPerTier = getTrophiesPerTier(trophyObject);
+ JsonArray rewards = trophyObject.get("rewards").getAsJsonArray();
+ int i = 0;
+ for (ItemStack itemStack : armorHelmets.keySet()) {
+ RenderHelper.enableGUIStandardItemLighting();
+ int integer = armorHelmets.get(itemStack).getRight();
+ x = guiLeft + 15;
+ y = guiTop + 50 + i;
+
+ Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(itemStack, x, y);
+ Utils.drawStringF(armorHelmets.get(itemStack).getLeft(), Minecraft.getMinecraft().fontRendererObj, x + 20, y + 4, true, 0);
+
+ int hasValue = trophiesPerTier[integer - 1];
+ int neededValue = integer == 1 ? 15 : 18;
+ String neededText = "§c" + hasValue + "/" + neededValue;
+
+ try {
+ JsonElement jsonElement = rewards.get(integer - 1);
+ if (!jsonElement.isJsonNull()) {
+ Utils.drawStringF(check, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 2, true, 0);
+ } else {
+ Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 4, true, 0);
+ }
+ } catch (IndexOutOfBoundsException exception) {
+ Utils.drawStringF(neededText, Minecraft.getMinecraft().fontRendererObj, x + 100, y + 4, true, 0);
+ }
+ i += 10;
+ }
+
+ GlStateManager.enableLighting();
+ }
+
+ private int[] getTrophiesPerTier(JsonObject trophyFish) {
+ int[] trophiesPerTier = new int[] { 0, 0, 0, 0 };
+ for (String fishType : internalTrophyFish.keySet()) {
+ int highestTier = 0;
+ if (trophyFish.has((fishType + "_bronze"))) highestTier = 1;
+ if (trophyFish.has((fishType + "_silver"))) highestTier = 2;
+ if (trophyFish.has((fishType + "_gold"))) highestTier = 3;
+ if (trophyFish.has((fishType + "_diamond"))) highestTier = 4;
+
+ if (highestTier >= 1) trophiesPerTier[0]++;
+ if (highestTier >= 2) trophiesPerTier[1]++;
+ if (highestTier >= 3) trophiesPerTier[2]++;
+ if (highestTier >= 4) trophiesPerTier[3]++;
+ }
+ return trophiesPerTier;
+ }
+
+ private List<String> getTooltip(String name, Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap) {
+ List<String> tooltip = new ArrayList<>();
+ tooltip.add(internalTrophyFish.get(name.toLowerCase(Locale.US).replace(" ", "_")) + WordUtils.capitalize(name.replace("_", " ")));
+
+ List<String> lore = readLoreFromRepo(name.toUpperCase(Locale.US));
+ List<String> description = readDescriptionFromLore(lore);
+ tooltip.addAll(description);
+ tooltip.add(" ");
+
+ if (trophyFishRarityIntegerMap == null) {
+ tooltip.add(EnumChatFormatting.RED + checkX + " Not Discovered");
+ tooltip.add(" ");
+ }
+
+ tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.DIAMOND, EnumChatFormatting.AQUA));
+ tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.GOLD, EnumChatFormatting.GOLD));
+ tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.SILVER, EnumChatFormatting.GRAY));
+ tooltip.add(display(trophyFishRarityIntegerMap, TrophyFish.TrophyFishRarity.BRONZE, EnumChatFormatting.DARK_GRAY));
+ return tooltip;
+ }
+
+ private String display(
+ Map<TrophyFish.TrophyFishRarity, Integer> trophyFishRarityIntegerMap,
+ TrophyFish.TrophyFishRarity rarity,
+ EnumChatFormatting color
+ ) {
+ String name = WordUtils.capitalize(rarity.name().toLowerCase(Locale.US));
+ if (trophyFishRarityIntegerMap == null) {
+ return color + name + ": " + checkX;
+ }
+
+ if (trophyFishRarityIntegerMap.containsKey(rarity)) {
+ return color + name + ": " + EnumChatFormatting.GOLD + trophyFishRarityIntegerMap.get(rarity);
+ } else {
+ return color + name + ": " + checkX;
+ }
+ }
+
+ private ItemStack getItem(String name) {
+ String repoName = name.toUpperCase(Locale.US).replace(" ", "_") + "_BRONZE";
+ JsonObject jsonItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(repoName);
+ return NotEnoughUpdates.INSTANCE.manager.jsonToStack(jsonItem);
+ }
+
+ private void loadTrophyInformation(JsonObject trophyObject) {
+ Map<String, List<Pair<TrophyFish.TrophyFishRarity, Integer>>> trophyFishRarityIntegerMap = new HashMap<>();
+ totalCount = 0;
+ for (Map.Entry<String, JsonElement> stringJsonElementEntry : trophyObject.entrySet()) {
+ String key = stringJsonElementEntry.getKey();
+ if (key.equalsIgnoreCase("rewards") || key.equalsIgnoreCase("total_caught")) {
+ if (key.equalsIgnoreCase("total_caught")) {
+ totalCount = stringJsonElementEntry.getValue().getAsInt();
+ }
+ continue;
+ }
+
+ String[] s = key.split("_");
+ String type = s[s.length - 1];
+ TrophyFish.TrophyFishRarity trophyFishRarity;
+ int value = stringJsonElementEntry.getValue().getAsInt();
+
+ if (key.startsWith("golden_fish_")) {
+ type = s[2];
+ }
+ try {
+ trophyFishRarity = TrophyFish.TrophyFishRarity.valueOf(type.toUpperCase(Locale.US));
+ } catch (IllegalArgumentException ignored) {
+ total.put(WordUtils.capitalize(key), value);
+ continue;
+ }
+
+ String replace = key.replace("_" + type, "");
+ String name = WordUtils.capitalize(replace);
+ List<Pair<TrophyFish.TrophyFishRarity, Integer>> pairs;
+
+ if (trophyFishRarityIntegerMap.containsKey(name)) {
+ pairs = trophyFishRarityIntegerMap.get(name);
+ } else {
+ pairs = new ArrayList<>();
+ }
+ pairs.add(Pair.of(trophyFishRarity, value));
+ trophyFishRarityIntegerMap.put(name, pairs);
+ }
+
+ trophyFishRarityIntegerMap.forEach((name, pair) -> {
+ if (!trophyFishList.containsKey(name)) {
+ TrophyFish trophyFish = new TrophyFish(name, new HashMap<>());
+ trophyFish.addTotal(total.get(name));
+ for (Pair<TrophyFish.TrophyFishRarity, Integer> pair1 : pair) {
+ trophyFish.add(pair1.getKey(), pair1.getValue());
+ }
+ trophyFishList.put(name, trophyFish);
+ } else {
+ TrophyFish trophyFish = trophyFishList.get(name);
+ for (Pair<TrophyFish.TrophyFishRarity, Integer> pair1 : pair) {
+ trophyFish.add(pair1.getKey(), pair1.getValue());
+ }
+ }
+ });
+ }
+
+ private List<String> fixStringName(List<String> list) {
+ List<String> fixedList = new ArrayList<>();
+ for (String s : list) {
+ fixedList.add(s.toLowerCase(Locale.US).replace(" ", "_"));
+ }
+ return fixedList;
+ }
+
+ private List<String> readDescriptionFromLore(List<String> lore) {
+ List<String> description = new ArrayList<>();
+ boolean found = false;
+
+ for (String line : lore) {
+ if (!found && line.startsWith("§7")) found = true;
+ if (found && line.isEmpty()) break;
+
+ if (found) {
+ description.add(line);
+ }
+ }
+
+ return description;
+ }
+
+ private List<String> readLoreFromRepo(String name) {
+ String repoName = name.toUpperCase(Locale.US).replace(" ", "_") + "_BRONZE";
+ JsonObject jsonItem = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(repoName);
+
+ List<String> list = new ArrayList<>();
+ if (jsonItem != null && jsonItem.has("lore")) {
+ for (JsonElement line : jsonItem.getAsJsonArray("lore")) {
+ list.add(line.getAsString());
+ }
+ }
+
+ return list;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java
new file mode 100644
index 00000000..3ceabaf5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyDungeonsWeight.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.lily;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.DungeonsWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class LilyDungeonsWeight extends DungeonsWeight {
+
+ private final JsonObject profileJson;
+
+ public LilyDungeonsWeight(Map<String, ProfileViewer.Level> player, JsonObject profileJson) {
+ super(player);
+ this.profileJson = profileJson;
+ }
+
+ @Override
+ public void getDungeonWeight() {
+ ProfileViewer.Level catacombs = player.get("catacombs");
+
+ double extra = 0;
+ double n = 0;
+ if (catacombs.totalXp < CATACOMBS_LEVEL_50_XP) {
+ n = 0.2 * Math.pow(catacombs.level / 50, 1.538679118869934);
+ } else {
+ extra = 500.0 * Math.pow((catacombs.totalXp - CATACOMBS_LEVEL_50_XP) / 142452410.0, 1.0 / 1.781925776625157);
+ }
+
+ if (catacombs.level != 0) {
+ if (catacombs.totalXp < CATACOMBS_LEVEL_50_XP) {
+ weightStruct.add(
+ new WeightStruct(
+ Utils.getElement(Constants.WEIGHT, "lily.dungeons.overall").getAsDouble() *
+ ((Math.pow(1.18340401286164044, (catacombs.level + 1)) - 1.05994990217254) * (1 + n))
+ )
+ );
+ } else {
+ weightStruct.add(new WeightStruct((4100 + extra) * 2));
+ }
+ }
+ }
+
+ public void getDungeonCompletionWeight(String cataMode) {
+ double max1000 = 0;
+ double mMax1000 = 0;
+ JsonObject dungeonsCompletionWorth = Utils.getElement(Constants.WEIGHT, "lily.dungeons.completion_worth").getAsJsonObject();
+ for (Map.Entry<String, JsonElement> dcwEntry : dungeonsCompletionWorth.entrySet()) {
+ if (dcwEntry.getKey().startsWith("catacombs_")) {
+ max1000 += dcwEntry.getValue().getAsDouble();
+ } else {
+ mMax1000 += dcwEntry.getValue().getAsDouble();
+ }
+ }
+ max1000 *= 1000;
+ mMax1000 *= 1000;
+ double upperBound = 1500;
+ if (cataMode.equals("normal")) {
+ if (Utils.getElement(profileJson, "dungeons.dungeon_types.catacombs.tier_completions") == null) {
+ return;
+ }
+
+ double score = 0;
+ for (Map.Entry<String, JsonElement> normalFloor : Utils
+ .getElement(profileJson, "dungeons.dungeon_types.catacombs.tier_completions")
+ .getAsJsonObject()
+ .entrySet()) {
+ int amount = normalFloor.getValue().getAsInt();
+ double excess = 0;
+ if (amount > 1000) {
+ excess = amount - 1000;
+ amount = 1000;
+ }
+
+ double floorScore = amount * dungeonsCompletionWorth.get("catacombs_" + normalFloor.getKey()).getAsDouble();
+ if (excess > 0) floorScore *= Math.log(excess / 1000 + 1) / Math.log(7.5) + 1;
+ score += floorScore;
+ }
+
+ weightStruct.add(new WeightStruct(score / max1000 * upperBound * 2));
+ } else {
+ JsonObject dungeonsCompletionBuffs = Utils.getElement(Constants.WEIGHT, "lily.dungeons.completion_buffs").getAsJsonObject();
+
+ if (Utils.getElement(profileJson, "dungeons.dungeon_types.master_catacombs.tier_completions") == null) {
+ return;
+ }
+
+ for (Map.Entry<String, JsonElement> masterFloor : Utils
+ .getElement(profileJson, "dungeons.dungeon_types.master_catacombs.tier_completions")
+ .getAsJsonObject()
+ .entrySet()) {
+ if (dungeonsCompletionBuffs.get(masterFloor.getKey()) != null) {
+ int amount = masterFloor.getValue().getAsInt();
+ double threshold = 20;
+ if (amount >= threshold) {
+ upperBound += dungeonsCompletionBuffs.get(masterFloor.getKey()).getAsInt();
+ } else {
+ upperBound +=
+ dungeonsCompletionBuffs.get(masterFloor.getKey()).getAsInt() * Math.pow((amount / threshold), 1.840896416);
+ }
+ }
+ }
+
+ double masterScore = 0;
+ for (Map.Entry<String, JsonElement> masterFloor : Utils
+ .getElement(profileJson, "dungeons.dungeon_types.master_catacombs.tier_completions")
+ .getAsJsonObject()
+ .entrySet()) {
+ int amount = masterFloor.getValue().getAsInt();
+ double excess = 0;
+ if (amount > 1000) {
+ excess = amount - 1000;
+ amount = 1000;
+ }
+
+ double floorScore = amount * dungeonsCompletionWorth.get("master_catacombs_" + masterFloor.getKey()).getAsDouble();
+ if (excess > 0) {
+ floorScore *= (Math.log((excess / 1000) + 1) / Math.log(6)) + 1;
+ }
+ masterScore += floorScore;
+ }
+
+ weightStruct.add(new WeightStruct((masterScore / mMax1000) * upperBound * 2));
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java
new file mode 100644
index 00000000..8ed43f6e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySkillsWeight.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.lily;
+
+import static io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight.SKILL_NAMES;
+
+import com.google.gson.JsonArray;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class LilySkillsWeight extends SkillsWeight {
+
+ public LilySkillsWeight(Map<String, ProfileViewer.Level> player) {
+ super(player);
+ }
+
+ @Override
+ public void getSkillsWeight(String skillName) {
+ double skillAverage = 0;
+ for (String skill : SKILL_NAMES) {
+ skillAverage +=
+ (int) ProfileViewer.getLevel(
+ Utils.getElement(Constants.LEVELING, "leveling_xp").getAsJsonArray(),
+ player.get(skill).totalXp,
+ 60,
+ false
+ )
+ .level;
+ }
+ skillAverage /= SKILL_NAMES.size();
+
+ float currentExp = player.get(skillName).totalXp;
+ int currentLevel = (int) ProfileViewer.getLevel(
+ Utils.getElement(Constants.LEVELING, "leveling_xp").getAsJsonArray(),
+ currentExp,
+ 60,
+ false
+ )
+ .level;
+
+ JsonArray srwTable = Utils.getElement(Constants.WEIGHT, "lily.skills.ratio_weight." + skillName).getAsJsonArray();
+ double base =
+ (
+ (12 * Math.pow((skillAverage / 60), 2.44780217148309)) *
+ srwTable.get(currentLevel).getAsDouble() *
+ srwTable.get(srwTable.size() - 1).getAsDouble()
+ ) +
+ (srwTable.get(srwTable.size() - 1).getAsDouble() * Math.pow(currentLevel / 60.0, Math.pow(2, 0.5)));
+ base *= Utils.getElement(Constants.WEIGHT, "lily.skills.overall").getAsDouble();
+ double overflow = 0;
+ if (currentExp > SKILLS_LEVEL_60) {
+ double factor = Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "lily.skills.factors." + skillName), 0);
+ double effectiveOver = effectiveXP(currentExp - SKILLS_LEVEL_60, factor);
+ double t =
+ (effectiveOver / SKILLS_LEVEL_60) *
+ Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "lily.skills.overflow_multipliers." + skillName), 0);
+ if (t > 0) {
+ overflow += Utils.getElement(Constants.WEIGHT, "lily.skills.overall").getAsDouble() * t;
+ }
+ }
+
+ weightStruct.add(new WeightStruct(base, overflow));
+ }
+
+ private double effectiveXP(double xp, double factor) {
+ return Math.pow(xp, factor);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java
new file mode 100644
index 00000000..d26597a1
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilySlayerWeight.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.lily;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class LilySlayerWeight extends SlayerWeight {
+
+ public LilySlayerWeight(Map<String, ProfileViewer.Level> player) {
+ super(player);
+ }
+
+ public void getSlayerWeight(String slayerName) {
+ int currentSlayerXp = (int) player.get(slayerName).totalXp;
+
+ double score;
+ double d = currentSlayerXp / 100000.0;
+ if (currentSlayerXp >= 6416) {
+ double D = (d - Math.pow(3, (-5.0 / 2))) * (d + Math.pow(3, -5.0 / 2));
+ double u = Math.cbrt(3 * (d + Math.sqrt(D)));
+ double v = Math.cbrt(3 * (d - Math.sqrt(D)));
+ score = u + v - 1;
+ } else {
+ score = Math.sqrt(4.0 / 3) * Math.cos(Math.acos(d * Math.pow(3, 5.0 / 2)) / 3) - 1;
+ }
+
+ double scaleFactor = Utils.getElementAsFloat(
+ Utils.getElement(Constants.WEIGHT, "lily.slayer.deprecation_scaling." + slayerName),
+ 0
+ );
+ int intScore = (int) score;
+ double distance = currentSlayerXp - actualInt(intScore);
+ double effectiveDistance = distance * Math.pow(scaleFactor, intScore);
+ double effectiveScore = effectiveInt(intScore, scaleFactor) + effectiveDistance;
+ double weight;
+ switch (slayerName) {
+ case "zombie":
+ weight = (effectiveScore / 9250) + (currentSlayerXp / 1000000.0);
+ break;
+ case "spider":
+ weight = (effectiveScore / 7019.57) + ((currentSlayerXp * 1.6) / 1000000);
+ break;
+ case "wolf":
+ weight = (effectiveScore / 2982.06) + ((currentSlayerXp * 3.6) / 1000000);
+ break;
+ case "enderman":
+ weight = (effectiveScore / 996.3003) + ((currentSlayerXp * 10.0) / 1000000);
+ break;
+ case "blaze":
+ weight = (effectiveScore / 935.0455) + ((currentSlayerXp * 10.0) / 1000000);
+ break;
+ default:
+ return;
+ }
+
+ weightStruct.add(new WeightStruct(2 * weight));
+ }
+
+ private double actualInt(int intScore) {
+ return (((Math.pow(intScore, 3) / 6) + (Math.pow(intScore, 2) / 2) + (intScore / 3.0)) * 100000);
+ }
+
+ private double effectiveInt(int intScore, double scaleFactor) {
+ double total = 0;
+ for (int k = 0; k < intScore; k++) {
+ total += (Math.pow((k + 1), 2) + (k + 1)) * Math.pow(scaleFactor, (k + 1));
+ }
+ return 1000000 * total * (0.05 / scaleFactor);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java
new file mode 100644
index 00000000..4ffc9fdd
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/lily/LilyWeight.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.lily;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight;
+import java.util.Map;
+
+public class LilyWeight extends Weight {
+
+ public LilyWeight(Map<String, ProfileViewer.Level> player, JsonObject profileJson) {
+ super(new LilySlayerWeight(player), new LilySkillsWeight(player), new LilyDungeonsWeight(player, profileJson));
+ }
+
+ @Override
+ public void calculateWeight() {
+ slayerWeight.getWeightStruct().reset();
+ skillsWeight.getWeightStruct().reset();
+ dungeonsWeight.getWeightStruct().reset();
+
+ for (String slayerName : SLAYER_NAMES) {
+ slayerWeight.getSlayerWeight(slayerName);
+ }
+ for (String skillName : SKILL_NAMES) {
+ skillsWeight.getSkillsWeight(skillName);
+ }
+
+ dungeonsWeight.getDungeonWeight();
+ ((LilyDungeonsWeight) dungeonsWeight).getDungeonCompletionWeight("normal");
+ ((LilyDungeonsWeight) dungeonsWeight).getDungeonCompletionWeight("master");
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java
new file mode 100644
index 00000000..3b5adae5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherDungeonsWeight.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.senither;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.DungeonsWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class SenitherDungeonsWeight extends DungeonsWeight {
+
+ public SenitherDungeonsWeight(Map<String, ProfileViewer.Level> player) {
+ super(player);
+ }
+
+ public void getClassWeight(String className) {
+ ProfileViewer.Level currentClass = player.get(className);
+ double base =
+ Math.pow(currentClass.level, 4.5) *
+ Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "senither.dungeons.classes." + className), 0);
+
+ if (currentClass.totalXp <= CATACOMBS_LEVEL_50_XP) {
+ weightStruct.add(new WeightStruct(base));
+ return;
+ }
+
+ double remaining = currentClass.totalXp - CATACOMBS_LEVEL_50_XP;
+ double splitter = (4 * CATACOMBS_LEVEL_50_XP) / base;
+ weightStruct.add(new WeightStruct(Math.floor(base), Math.pow(remaining / splitter, 0.968)));
+ }
+
+ @Override
+ public void getDungeonWeight() {
+ ProfileViewer.Level catacombs = player.get("catacombs");
+ double base =
+ Math.pow(catacombs.level, 4.5) * Utils.getElementAsFloat(Utils.getElement(Constants.WEIGHT, "senither.dungeons.catacombs"), 0);
+
+ if (catacombs.totalXp <= CATACOMBS_LEVEL_50_XP) {
+ weightStruct.add(new WeightStruct(base));
+ return;
+ }
+
+ double remaining = catacombs.totalXp - CATACOMBS_LEVEL_50_XP;
+ double splitter = (4 * CATACOMBS_LEVEL_50_XP) / base;
+ weightStruct.add(new WeightStruct(Math.floor(base), Math.pow(remaining / splitter, 0.968)));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java
new file mode 100644
index 00000000..2a4ee48c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSkillsWeight.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.senither;
+
+import com.google.gson.JsonArray;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SkillsWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class SenitherSkillsWeight extends SkillsWeight {
+
+ public SenitherSkillsWeight(Map<String, ProfileViewer.Level> player) {
+ super(player);
+ }
+
+ @Override
+ public void getSkillsWeight(String skillName) {
+ JsonArray curWeights = Utils.getElement(Constants.WEIGHT, "senither.skills." + skillName).getAsJsonArray();
+ double exponent = curWeights.get(0).getAsDouble();
+ double divider = curWeights.get(1).getAsDouble();
+
+ float currentSkillXp = player.get(skillName).totalXp;
+
+ if (currentSkillXp > 0) {
+ int maxLevel = skillName.equals("farming")
+ ? 60
+ : Utils.getElementAsInt(Utils.getElement(Constants.LEVELING, "leveling_caps." + skillName), 50);
+ double level = ProfileViewer.getLevel(
+ Utils.getElement(Constants.LEVELING, "leveling_xp").getAsJsonArray(),
+ currentSkillXp,
+ maxLevel,
+ false
+ )
+ .level;
+
+ double maxLevelExp = maxLevel == 50 ? SKILLS_LEVEL_50 : SKILLS_LEVEL_60;
+ double base = Math.pow(level * 10, 0.5 + exponent + (level / 100)) / 1250;
+ if (currentSkillXp <= maxLevelExp) {
+ weightStruct.add(new WeightStruct(base));
+ return;
+ }
+
+ weightStruct.add(new WeightStruct(Math.round(base), Math.pow((currentSkillXp - maxLevelExp) / divider, 0.968)));
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java
new file mode 100644
index 00000000..80853853
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherSlayerWeight.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.senither;
+
+import com.google.gson.JsonArray;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.SlayerWeight;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.WeightStruct;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import java.util.Map;
+
+public class SenitherSlayerWeight extends SlayerWeight {
+
+ public SenitherSlayerWeight(Map<String, ProfileViewer.Level> player) {
+ super(player);
+ }
+
+ public void getSlayerWeight(String slayerName) {
+ if (slayerName.equals("blaze")) {
+ return;
+ }
+
+ JsonArray curWeights = Utils.getElement(Constants.WEIGHT, "senither.slayer." + slayerName).getAsJsonArray();
+ double divider = curWeights.get(0).getAsDouble();
+ double modifier = curWeights.get(1).getAsDouble();
+
+ int currentSlayerXp = (int) player.get(slayerName).totalXp;
+
+ if (currentSlayerXp <= 1000000) {
+ weightStruct.add(new WeightStruct(currentSlayerXp == 0 ? 0 : currentSlayerXp / divider));
+ return;
+ }
+
+ double base = 1000000 / divider;
+ double remaining = currentSlayerXp - 1000000;
+ double overflow = 0;
+ double initialModifier = modifier;
+
+ while (remaining > 0) {
+ double left = Math.min(remaining, 1000000);
+
+ overflow += Math.pow(left / (divider * (1.5 + modifier)), 0.942);
+ modifier += initialModifier;
+ remaining -= left;
+ }
+
+ weightStruct.add(new WeightStruct(base, overflow));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java
new file mode 100644
index 00000000..2f813576
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/senither/SenitherWeight.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.senither;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.weight.weight.Weight;
+import java.util.Map;
+
+public class SenitherWeight extends Weight {
+
+ public SenitherWeight(Map<String, ProfileViewer.Level> player) {
+ super(new SenitherSlayerWeight(player), new SenitherSkillsWeight(player), new SenitherDungeonsWeight(player));
+ }
+
+ @Override
+ public void calculateWeight() {
+ slayerWeight.getWeightStruct().reset();
+ skillsWeight.getWeightStruct().reset();
+ dungeonsWeight.getWeightStruct().reset();
+
+ for (String slayerName : SLAYER_NAMES) {
+ slayerWeight.getSlayerWeight(slayerName);
+ }
+
+ for (String skillName : SKILL_NAMES) {
+ skillsWeight.getSkillsWeight(skillName);
+ }
+
+ dungeonsWeight.getDungeonWeight();
+ for (String dungeonClassName : DUNGEON_CLASS_NAMES) {
+ ((SenitherDungeonsWeight) dungeonsWeight).getClassWeight(dungeonClassName);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java
new file mode 100644
index 00000000..39e743aa
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/DungeonsWeight.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.weight;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import java.util.Map;
+
+public abstract class DungeonsWeight {
+
+ protected static final long CATACOMBS_LEVEL_50_XP = 569809640;
+
+ protected final Map<String, ProfileViewer.Level> player;
+ protected final WeightStruct weightStruct;
+
+ public DungeonsWeight(Map<String, ProfileViewer.Level> player) {
+ this.player = player;
+ this.weightStruct = new WeightStruct();
+ }
+
+ public WeightStruct getWeightStruct() {
+ return weightStruct;
+ }
+
+ public abstract void getDungeonWeight();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java
new file mode 100644
index 00000000..55669f7b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SkillsWeight.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.weight;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import java.util.Map;
+
+public abstract class SkillsWeight {
+
+ protected static final long SKILLS_LEVEL_50 = 55172425;
+ protected static final long SKILLS_LEVEL_60 = 111672425;
+ protected final Map<String, ProfileViewer.Level> player;
+ protected final WeightStruct weightStruct;
+
+ public SkillsWeight(Map<String, ProfileViewer.Level> player) {
+ this.player = player;
+ this.weightStruct = new WeightStruct();
+ }
+
+ public WeightStruct getWeightStruct() {
+ return weightStruct;
+ }
+
+ public abstract void getSkillsWeight(String skillName);
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java
new file mode 100644
index 00000000..20b2762d
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/SlayerWeight.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.weight;
+
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import java.util.Map;
+
+public abstract class SlayerWeight {
+
+ protected final Map<String, ProfileViewer.Level> player;
+ protected final WeightStruct weightStruct;
+
+ public SlayerWeight(Map<String, ProfileViewer.Level> player) {
+ this.player = player;
+ this.weightStruct = new WeightStruct();
+ }
+
+ public WeightStruct getWeightStruct() {
+ return weightStruct;
+ }
+
+ public abstract void getSlayerWeight(String slayerName);
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java
new file mode 100644
index 00000000..129f53fc
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/Weight.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.weight;
+
+import java.util.Arrays;
+import java.util.List;
+
+public abstract class Weight {
+
+ public static final List<String> SKILL_NAMES = Arrays.asList(
+ "taming",
+ "mining",
+ "foraging",
+ "enchanting",
+ "farming",
+ "combat",
+ "fishing",
+ "alchemy"
+ );
+ protected static final List<String> SLAYER_NAMES = Arrays.asList("wolf", "zombie", "spider", "enderman", "blaze");
+ protected static final List<String> DUNGEON_CLASS_NAMES = Arrays.asList("healer", "mage", "berserk", "archer", "tank");
+ protected final SlayerWeight slayerWeight;
+ protected final SkillsWeight skillsWeight;
+ protected final DungeonsWeight dungeonsWeight;
+
+ public Weight(SlayerWeight slayerWeight, SkillsWeight skillsWeight, DungeonsWeight dungeonsWeight) {
+ this.slayerWeight = slayerWeight;
+ this.skillsWeight = skillsWeight;
+ this.dungeonsWeight = dungeonsWeight;
+ this.calculateWeight();
+ }
+
+ public WeightStruct getTotalWeight() {
+ return new WeightStruct()
+ .add(slayerWeight.getWeightStruct())
+ .add(skillsWeight.getWeightStruct())
+ .add(dungeonsWeight.getWeightStruct());
+ }
+
+ public SlayerWeight getSlayerWeight() {
+ return slayerWeight;
+ }
+
+ public SkillsWeight getSkillsWeight() {
+ return skillsWeight;
+ }
+
+ public DungeonsWeight getDungeonsWeight() {
+ return dungeonsWeight;
+ }
+
+ protected abstract void calculateWeight();
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/WeightStruct.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/WeightStruct.java
new file mode 100644
index 00000000..924dcb40
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/weight/weight/WeightStruct.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.profileviewer.weight.weight;
+
+public class WeightStruct {
+
+ private double base;
+ private double overflow;
+
+ public WeightStruct() {
+ this(0, 0);
+ }
+
+ public WeightStruct(double base) {
+ this(base, 0);
+ }
+
+ public WeightStruct(double base, double overflow) {
+ this.base = base;
+ this.overflow = overflow;
+ }
+
+ public WeightStruct add(WeightStruct o) {
+ this.base += o.base;
+ this.overflow += o.overflow;
+ return this;
+ }
+
+ public double getRaw() {
+ return base + overflow;
+ }
+
+ public void reset() {
+ this.base = 0;
+ this.overflow = 0;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java
index d0b464f6..004ea372 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingOverlay.java
@@ -1,6 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
@@ -50,8 +70,8 @@ public class CraftingOverlay {
forEachSlot(chest, (recipeIngredient, slot) -> {
if (Utils.isWithinRect(
mouseX, mouseY,
- slot.xDisplayPosition + gui.guiLeft,
- slot.yDisplayPosition + gui.guiTop,
+ slot.xDisplayPosition + ((AccessorGuiContainer) gui).getGuiLeft(),
+ slot.yDisplayPosition + ((AccessorGuiContainer) gui).getGuiTop(),
16, 16
))
block.accept(recipeIngredient, slot);
@@ -82,7 +102,7 @@ public class CraftingOverlay {
fontRenderer.drawStringWithShadow(
currentRecipe.getCraftText(),
Utils.peekGuiScale().getScaledWidth() / 2f - fontRenderer.getStringWidth(currentRecipe.getCraftText()) / 2f,
- guiChest.guiTop - 15f, 0x808080
+ ((AccessorGuiContainer) guiChest).getGuiTop() - 15f, 0x808080
);
}
renderTooltip(guiChest, chest);
@@ -103,7 +123,7 @@ public class CraftingOverlay {
if (Keyboard.getEventKey() == Keyboard.KEY_R)
manager.showRecipe(recipeIngredient.getInternalItemId());
if (Keyboard.getEventKey() == Keyboard.KEY_U)
- manager.displayGuiItemRecipe(recipeIngredient.getInternalItemId(), null);
+ manager.displayGuiItemRecipe(recipeIngredient.getInternalItemId());
}
});
});
@@ -140,8 +160,8 @@ public class CraftingOverlay {
}
private void drawItemStack(GuiChest gui, Slot slot, ItemStack item) {
- int slotX = slot.xDisplayPosition + gui.guiLeft;
- int slotY = slot.yDisplayPosition + gui.guiTop;
+ int slotX = slot.xDisplayPosition + ((AccessorGuiContainer) gui).getGuiLeft();
+ int slotY = slot.yDisplayPosition + ((AccessorGuiContainer) gui).getGuiTop();
Gui.drawRect(slotX, slotY, slotX + 16, slotY + 16, 0x64ff0000);
if (item != null)
Utils.drawItemStack(item, slotX, slotY);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
index 576cbbd4..a642187b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.common.collect.Sets;
@@ -17,10 +36,11 @@ import java.util.Set;
public class CraftingRecipe implements NeuRecipe {
- public static final ResourceLocation BACKGROUND = new ResourceLocation("textures/gui/container/crafting_table.png");
+ public static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates",
+ "textures/gui/crafting_table_tall.png");
private static final int EXTRA_STRING_X = 132;
- private static final int EXTRA_STRING_Y = 25;
+ private static final int EXTRA_STRING_Y = 50;
private final NEUManager manager;
private final Ingredient[] inputs;
@@ -45,6 +65,11 @@ public class CraftingRecipe implements NeuRecipe {
}
@Override
+ public RecipeType getType() {
+ return RecipeType.CRAFTING;
+ }
+
+ @Override
public boolean hasVariableCost() {
return false;
}
@@ -72,10 +97,10 @@ public class CraftingRecipe implements NeuRecipe {
if (input == null) continue;
ItemStack item = input.getItemStack();
if (item == null) continue;
- slots.add(new RecipeSlot(30 + x * GuiItemRecipe.SLOT_SPACING, 17 + y * GuiItemRecipe.SLOT_SPACING, item));
+ slots.add(new RecipeSlot(30 + x * GuiItemRecipe.SLOT_SPACING, 48 + y * GuiItemRecipe.SLOT_SPACING, item));
}
}
- slots.add(new RecipeSlot(124, 35, outputIngredient.getItemStack()));
+ slots.add(new RecipeSlot(124, 66, outputIngredient.getItemStack()));
return slots;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
index c971d82a..47eb0d11 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.common.collect.Sets;
@@ -15,12 +34,18 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
public class ForgeRecipe implements NeuRecipe {
- private static final ResourceLocation BACKGROUND =
- new ResourceLocation("notenoughupdates", "textures/gui/forge_recipe.png");
+ private static final ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/forge_recipe_tall.png"
+ );
private static final int SLOT_IMAGE_U = 176;
private static final int SLOT_IMAGE_V = 0;
@@ -28,7 +53,7 @@ public class ForgeRecipe implements NeuRecipe {
private static final int SLOT_PADDING = 1;
private static final int EXTRA_INFO_MAX_WIDTH = 75;
public static final int EXTRA_INFO_X = 132;
- public static final int EXTRA_INFO_Y = 25;
+ public static final int EXTRA_INFO_Y = 55;
public enum ForgeType {
REFINING, ITEM_FORGING
@@ -77,6 +102,11 @@ public class ForgeRecipe implements NeuRecipe {
}
@Override
+ public RecipeType getType() {
+ return RecipeType.FORGE;
+ }
+
+ @Override
public Set<Ingredient> getIngredients() {
return Sets.newHashSet(inputs);
}
@@ -102,7 +132,7 @@ public class ForgeRecipe implements NeuRecipe {
int[] slotCoordinates = getSlotCoordinates(i, inputs.size());
slots.add(new RecipeSlot(slotCoordinates[0], slotCoordinates[1], itemStack));
}
- slots.add(new RecipeSlot(124, 35, output.getItemStack()));
+ slots.add(new RecipeSlot(124, 66, output.getItemStack()));
return slots;
}
@@ -214,14 +244,14 @@ public class ForgeRecipe implements NeuRecipe {
);
}
- private static final int RECIPE_CENTER_X = 40;
- private static final int RECIPE_CENTER_Y = 34;
- private static final int SLOT_DISTANCE_FROM_CENTER = 22;
+ private static final int RECIPE_CENTER_X = 49;
+ private static final int RECIPE_CENTER_Y = 74;
+ private static final int SLOT_DISTANCE_FROM_CENTER = 30;
private static final int RECIPE_FALLBACK_X = 20;
private static final int RECIPE_FALLBACK_Y = 15;
static int[] getSlotCoordinates(int slotNumber, int totalSlotCount) {
- if (totalSlotCount > 6) {
+ if (totalSlotCount > 8) {
return new int[]{
RECIPE_FALLBACK_X + (slotNumber % 4) * GuiItemRecipe.SLOT_SPACING,
RECIPE_FALLBACK_Y + (slotNumber / 4) * GuiItemRecipe.SLOT_SPACING,
@@ -236,7 +266,10 @@ public class ForgeRecipe implements NeuRecipe {
double rad = Math.PI * 2 * slotNumber / totalSlotCount;
int x = (int) (Math.cos(rad) * SLOT_DISTANCE_FROM_CENTER);
int y = (int) (Math.sin(rad) * SLOT_DISTANCE_FROM_CENTER);
- return new int[]{RECIPE_CENTER_X + x, RECIPE_CENTER_Y + y};
+ return new int[]{
+ RECIPE_CENTER_X + x - GuiItemRecipe.SLOT_SIZE / 2,
+ RECIPE_CENTER_Y + y - GuiItemRecipe.SLOT_SIZE / 2
+ };
}
static String formatDuration(int seconds) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/Ingredient.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/Ingredient.java
index 79b548da..c973f8c0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/Ingredient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/Ingredient.java
@@ -1,9 +1,27 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.init.Items;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
import net.minecraft.item.ItemStack;
import java.util.HashMap;
@@ -75,9 +93,7 @@ public class Ingredient {
public ItemStack getItemStack() {
if (itemStack != null) return itemStack;
if (isCoins()) {
- itemStack = new ItemStack(Items.gold_nugget);
- itemStack.setStackDisplayName("\u00A7r\u00A76" + Utils.formatNumberWithDots(getCount()) + " Coins");
- return itemStack;
+ return ItemUtils.getCoinItemStack(count);
}
JsonObject itemInfo = manager.getItemInformation().get(internalItemId);
itemStack = manager.jsonToStack(itemInfo);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java
new file mode 100644
index 00000000..235ba3ce
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ItemShopRecipe.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.recipes;
+
+import com.google.common.collect.Sets;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import io.github.moulberry.notenoughupdates.miscgui.GuiNavigation;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class ItemShopRecipe implements NeuRecipe {
+ public static ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/item_shop_recipe.png"
+ );
+
+ private static final int SLOT_IMAGE_U = 176;
+ private static final int SLOT_IMAGE_V = 0;
+
+ private static final int SLOT_IMAGE_SIZE = 18;
+ public static final int RESULT_SLOT_Y = 66;
+ public static final int RESULT_SLOT_X = 124;
+
+ public static final int BUTTON_X = 130;
+ public static final int BUTTON_Y = 16;
+
+ private static final int COST_SLOT_X = 30;
+ private static final int COST_SLOT_SPACING = 6;
+ private static final int ROW_SPACING = 18;
+ private final List<Ingredient> cost;
+ private final Ingredient result;
+ private boolean selected;
+
+ private final Ingredient npcIngredient;
+ private final boolean hasWaypoint;
+ private final JsonObject npcObject;
+
+ public ItemShopRecipe(Ingredient npcIngredient, List<Ingredient> cost, Ingredient result, JsonObject npcObject) {
+ this.npcIngredient = npcIngredient;
+ this.cost = cost;
+ this.result = result;
+ this.npcObject = npcObject;
+ hasWaypoint = NotEnoughUpdates.INSTANCE.navigation.isValidWaypoint(npcObject);
+ }
+
+ @Override
+ public Set<Ingredient> getCatalystItems() {
+ return Sets.newHashSet(npcIngredient);
+ }
+
+ @Override
+ public Set<Ingredient> getIngredients() {
+ return new HashSet<>(cost);
+ }
+
+ @Override
+ public Set<Ingredient> getOutputs() {
+ return Sets.newHashSet(result);
+ }
+
+ @Override
+ public List<RecipeSlot> getSlots() {
+ List<RecipeSlot> slots = new ArrayList<>();
+
+ int i = 0;
+ int colCount = cost.size() / 4;
+ int startX = COST_SLOT_X - 8 * (colCount - 1);
+ int rowSize = cost.size();
+ if (rowSize > 4) rowSize = 4;
+ int startY = RESULT_SLOT_Y + 8 - (SLOT_IMAGE_SIZE * rowSize + COST_SLOT_SPACING * (rowSize - 1)) / 2;
+ for (Ingredient ingredient : cost) {
+ slots.add(new RecipeSlot(
+ startX + (i / 4) * ROW_SPACING + 1,
+ startY + (i % 4) * (SLOT_IMAGE_SIZE + COST_SLOT_SPACING) + 1,
+ ingredient.getItemStack()
+ ));
+ i++;
+ }
+ slots.add(new RecipeSlot(RESULT_SLOT_X, RESULT_SLOT_Y, result.getItemStack()));
+ return slots;
+ }
+
+ @Override
+ public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ int colCount = cost.size() / 4;
+ int startX = COST_SLOT_X - 8 * (colCount - 1);
+ int rowSize = cost.size();
+ if (rowSize > 4) rowSize = 4;
+ int startY = RESULT_SLOT_Y + 8 - (SLOT_IMAGE_SIZE * rowSize + COST_SLOT_SPACING * (rowSize - 1)) / 2;
+ for (int i = 0; i < cost.size(); i++) {
+ gui.drawTexturedModalRect(
+ gui.guiLeft + startX + (i / 4) * ROW_SPACING,
+ gui.guiTop + startY + (i % 4) * (SLOT_IMAGE_SIZE + COST_SLOT_SPACING),
+ SLOT_IMAGE_U, SLOT_IMAGE_V,
+ SLOT_IMAGE_SIZE, SLOT_IMAGE_SIZE
+ );
+ }
+ if (!hasWaypoint) return;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(GuiNavigation.BACKGROUND);
+ selected = npcIngredient.getInternalItemId().equals(NotEnoughUpdates.INSTANCE.navigation.getInternalname());
+ gui.drawTexturedModalRect(
+ gui.guiLeft + BUTTON_X,
+ gui.guiTop + BUTTON_Y,
+ selected ? GuiNavigation.TICK_POSITION_U : GuiNavigation.PIN_POSITION_U,
+ selected ? GuiNavigation.TICK_POSITION_V : GuiNavigation.PIN_POSITION_V,
+ GuiNavigation.ICON_SIZE,
+ GuiNavigation.ICON_SIZE
+ );
+ }
+
+ @Override
+ public void mouseClicked(GuiItemRecipe gui, int mouseX, int mouseY, int mouseButton) {
+ if (hasWaypoint && Utils.isWithinRect(
+ mouseX - gui.guiLeft,
+ mouseY - gui.guiTop,
+ BUTTON_X,
+ BUTTON_Y,
+ GuiNavigation.ICON_SIZE,
+ GuiNavigation.ICON_SIZE
+ )) {
+ boolean shiftPressed = Keyboard.isKeyDown(Keyboard.KEY_RSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
+ if (selected && !shiftPressed) {
+ NotEnoughUpdates.INSTANCE.navigation.untrackWaypoint();
+ } else {
+ NotEnoughUpdates.INSTANCE.navigation.trackWaypoint(npcIngredient.getInternalItemId());
+ if (shiftPressed) {
+ NotEnoughUpdates.INSTANCE.navigation.useWarpCommand();
+ }
+ }
+ Utils.playPressSound();
+ selected = !selected;
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return npcObject.get("displayname").getAsString();
+ }
+
+ @Override
+ public RecipeType getType() {
+ return RecipeType.NPC_SHOP;
+ }
+
+ @Override
+ public boolean hasVariableCost() {
+ return false;
+ }
+
+ @Override
+ public JsonObject serialize() {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("type", "npc_shop");
+ jsonObject.addProperty("result", result.serialize());
+ jsonObject.add(
+ "cost",
+ JsonUtils.transformListToJsonArray(cost, costItem -> new JsonPrimitive(costItem.serialize()))
+ );
+ return jsonObject;
+ }
+
+ @Override
+ public ResourceLocation getBackground() {
+ return BACKGROUND;
+ }
+
+ public static NeuRecipe parseItemRecipe(NEUManager neuManager, JsonObject recipe, JsonObject outputItemJson) {
+ return new ItemShopRecipe(
+ new Ingredient(neuManager, outputItemJson.get("internalname").getAsString()),
+ JsonUtils.transformJsonArrayToList(
+ recipe.getAsJsonArray("cost"),
+ it -> new Ingredient(neuManager, it.getAsString())
+ ),
+ new Ingredient(neuManager, recipe.get("result").getAsString()),
+ outputItemJson
+ );
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java
new file mode 100644
index 00000000..61749593
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/MobLootRecipe.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.recipes;
+
+import com.google.common.collect.Sets;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.miscfeatures.entityviewer.EntityViewer;
+import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.Panorama;
+import io.github.moulberry.notenoughupdates.util.ItemUtils;
+import io.github.moulberry.notenoughupdates.util.JsonUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+public class MobLootRecipe implements NeuRecipe {
+
+ private static final int MOB_POS_X = 38, MOB_POS_Y = 100;
+ private static final int SLOT_POS_X = 82, SLOT_POS_Y = 24;
+
+ public static class MobDrop {
+ public final Ingredient drop;
+ public final String chance;
+ public final List<String> extra;
+
+ private ItemStack itemStack;
+
+ public MobDrop(Ingredient drop, String chance, List<String> extra) {
+ this.drop = drop;
+ this.chance = chance;
+ this.extra = extra;
+ }
+
+ public ItemStack getItemStack() {
+ if (itemStack == null) {
+ itemStack = drop.getItemStack().copy();
+ List<String> arrayList = new ArrayList<>(extra);
+ arrayList.add("§r§e§lDrop Chance: §6" + formatDropChance());
+ ItemUtils.appendLore(itemStack, arrayList);
+ }
+ return itemStack;
+ }
+
+ private String formatDropChance() {
+ if (chance == null) {
+ return "";
+ }
+
+ if (!chance.endsWith("%")) {
+ return chance;
+ }
+
+ String chanceText = chance.substring(0, chance.length() - 1);
+ int chanceIn;
+ try {
+ chanceIn = (int) (100.0 / Double.parseDouble(chanceText));
+ } catch (NumberFormatException e) {
+ return chance;
+ }
+
+ String format = GuiProfileViewer.numberFormat.format(chanceIn);
+ return "1/" + format + " (" + chance + ")";
+ }
+ }
+
+ public static ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/mob_loot_tall.png"
+ );
+ private final Ingredient mobIngredient;
+ private final List<MobDrop> drops;
+ private final int coins;
+ private final int combatXp;
+ private final int xp;
+ private final String name;
+ private final String render;
+ private final int level;
+ private final List<String> extra;
+ private EntityLivingBase entityLivingBase;
+
+ private final String panoName;
+
+ private ResourceLocation[] panos = null;
+
+ public MobLootRecipe(
+ Ingredient mobIngredient,
+ List<MobDrop> drops,
+ int level,
+ int coins,
+ int xp,
+ int combatXp,
+ String name,
+ String render,
+ List<String> extra,
+ String panoName
+ ) {
+ this.mobIngredient = mobIngredient;
+ this.drops = drops;
+ this.level = level;
+ this.coins = coins;
+ this.xp = xp;
+ this.extra = extra;
+ this.combatXp = combatXp;
+ this.name = name;
+ this.render = render;
+ this.panoName = panoName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public List<MobDrop> getDrops() {
+ return drops;
+ }
+
+ public int getCoins() {
+ return coins;
+ }
+
+ public int getCombatXp() {
+ return combatXp;
+ }
+
+ public Ingredient getMob() {
+ return mobIngredient;
+ }
+
+ public int getXp() {
+ return xp;
+ }
+
+ public String getRender() {
+ return render;
+ }
+
+ public synchronized EntityLivingBase getRenderEntity() {
+ if (entityLivingBase == null) {
+ if (render == null) return null;
+ if (render.startsWith("@")) {
+ entityLivingBase = EntityViewer.constructEntity(new ResourceLocation(render.substring(1)));
+ } else {
+ entityLivingBase = EntityViewer.constructEntity(render, Collections.emptyList());
+ }
+ }
+ return entityLivingBase;
+ }
+
+ @Override
+ public Set<Ingredient> getIngredients() {
+ return Sets.newHashSet(mobIngredient);
+ }
+
+ @Override
+ public Set<Ingredient> getCatalystItems() {
+ return Sets.newHashSet(mobIngredient);
+ }
+
+ @Override
+ public Set<Ingredient> getOutputs() {
+ return drops.stream().map(it -> it.drop).collect(Collectors.toSet());
+ }
+
+ @Override
+ public String getTitle() {
+ return getFullMobName();
+ }
+
+ public String getFullMobName() {
+ return (level > 0 ? "§8[§7Lv " + level + "§8] §c" : "§c") + name;
+ }
+
+ @Override
+ public List<RecipeSlot> getSlots() {
+ List<RecipeSlot> slots = new ArrayList<>();
+ BiConsumer<Integer, ItemStack> addSlot = (sl, is) -> slots.add(
+ new RecipeSlot(
+ SLOT_POS_X + (sl % 5) * 16,
+ SLOT_POS_Y + (sl / 5) * 16,
+ is
+ ));
+ int i = 0;
+ for (; i < drops.size(); i++) {
+ MobDrop mobDrop = drops.get(i);
+ addSlot.accept(i, mobDrop.getItemStack());
+ }
+ return slots;
+ }
+
+ @Override
+ public RecipeType getType() {
+ return RecipeType.MOB_LOOT;
+ }
+
+ @Override
+ public boolean shouldUseForCraftCost() {
+ return false;
+ }
+
+ @Override
+ public boolean hasVariableCost() {
+ return true;
+ }
+
+ public static final int PANORAMA_POS_X = 13;
+ public static final int PANORAMA_POS_Y = 23;
+ public static final int PANORAMA_WIDTH = 50;
+ public static final int PANORAMA_HEIGHT = 80;
+
+ @Override
+ public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
+ if (panos == null) {
+ panos = Panorama.getPanoramasForLocation(panoName, "day");
+ }
+ Panorama.drawPanorama(
+ ((System.nanoTime() / 20000000000F) % 1) * 360,
+ gui.guiLeft + PANORAMA_POS_X,
+ gui.guiTop + PANORAMA_POS_Y,
+ PANORAMA_WIDTH,
+ PANORAMA_HEIGHT,
+ 0F,
+ 0F,
+ panos
+ );
+ if (getRenderEntity() != null)
+ EntityViewer.renderEntity(entityLivingBase, gui.guiLeft + MOB_POS_X, gui.guiTop + MOB_POS_Y, mouseX, mouseY);
+ }
+
+ @Override
+ public void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
+ if (gui.isWithinRect(
+ mouseX,
+ mouseY,
+ gui.guiLeft + PANORAMA_POS_X,
+ gui.guiTop + PANORAMA_POS_Y,
+ PANORAMA_WIDTH,
+ PANORAMA_HEIGHT
+ )) {
+ List<String> stuff = new ArrayList<>();
+ stuff.add(getFullMobName());
+ stuff.add("");
+ if (coins > 0)
+ stuff.add("§r§6Coins: " + coins);
+ if (xp > 0)
+ stuff.add("§r§aExperience: " + xp);
+ if (combatXp > 0)
+ stuff.add("§r§bCombat Experience: " + combatXp);
+ stuff.addAll(extra);
+ Utils.drawHoveringText(
+ stuff,
+ mouseX,
+ mouseY,
+ gui.width,
+ gui.height,
+ -1,
+ Minecraft.getMinecraft().fontRendererObj
+ );
+ }
+ }
+
+ @Override
+ public int[] getPageFlipPositionLeftTopCorner() {
+ return new int[]{14, 118};
+ }
+
+ @Override
+ public JsonObject serialize() {
+ JsonObject recipe = new JsonObject();
+ recipe.addProperty("level", level);
+ recipe.addProperty("coins", coins);
+ recipe.addProperty("xp", xp);
+ recipe.addProperty("combat_xp", combatXp);
+ recipe.addProperty("name", name);
+ recipe.addProperty("render", render);
+ recipe.addProperty("type", getType().getId());
+ recipe.addProperty("panorama", "unknown");
+ recipe.add("extra", JsonUtils.transformListToJsonArray(extra, JsonPrimitive::new));
+ recipe.add("drops", JsonUtils.transformListToJsonArray(drops, drop -> {
+ JsonObject dropObject = new JsonObject();
+ dropObject.addProperty("id", drop.drop.serialize());
+ dropObject.add("extra", JsonUtils.transformListToJsonArray(drop.extra, JsonPrimitive::new));
+ dropObject.addProperty("chance", drop.chance);
+ return dropObject;
+ }));
+ return recipe;
+ }
+
+ @Override
+ public ResourceLocation getBackground() {
+ return BACKGROUND;
+ }
+
+ public static MobLootRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject outputItemJson) {
+ List<MobDrop> drops = new ArrayList<>();
+ for (JsonElement jsonElement : recipe.getAsJsonArray("drops")) {
+ if (jsonElement.isJsonPrimitive()) {
+ drops.add(new MobDrop(new Ingredient(manager, jsonElement.getAsString()), null, Collections.emptyList()));
+ } else {
+ JsonObject jsonObject = jsonElement.getAsJsonObject();
+ drops.add(
+ new MobDrop(
+ new Ingredient(manager, jsonObject.get("id").getAsString()),
+ jsonObject.has("chance") ? jsonObject.get("chance").getAsString() : null,
+ JsonUtils.getJsonArrayOrEmpty(jsonObject, "extra", JsonElement::getAsString)
+ ));
+ }
+ }
+
+ return new MobLootRecipe(
+ new Ingredient(manager, outputItemJson.get("internalname").getAsString(), 1),
+ drops,
+ recipe.has("level") ? recipe.get("level").getAsInt() : 0,
+ recipe.has("coins") ? recipe.get("coins").getAsInt() : 0,
+ recipe.has("xp") ? recipe.get("xp").getAsInt() : 0,
+ recipe.has("combat_xp") ? recipe.get("combat_xp").getAsInt() : 0,
+ recipe.get("name").getAsString(),
+ recipe.has("render") && !recipe.get("render").isJsonNull() ? recipe.get("render").getAsString() : null,
+ JsonUtils.getJsonArrayOrEmpty(recipe, "extra", JsonElement::getAsString),
+ recipe.has("panorama") ? recipe.get("panorama").getAsString() : "unknown"
+ );
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
index 3516f707..a0090050 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
@@ -1,10 +1,32 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import net.minecraft.client.gui.GuiButton;
import net.minecraft.util.ResourceLocation;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -15,6 +37,12 @@ public interface NeuRecipe {
List<RecipeSlot> getSlots();
+ RecipeType getType();
+
+ default String getTitle() {
+ return getType().getLabel();
+ }
+
default void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
}
@@ -24,22 +52,31 @@ public interface NeuRecipe {
default void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
}
+ default void mouseClicked(GuiItemRecipe gui, int mouseX, int mouseY, int mouseButton) {}
+
+ default void handleKeyboardInput() {}
+
+ default Set<Ingredient> getCatalystItems() {
+ return Collections.emptySet();
+ }
+
boolean hasVariableCost();
JsonObject serialize();
+ default List<GuiButton> getExtraButtons(GuiItemRecipe guiItemRecipe) {
+ return new ArrayList<>();
+ }
+
ResourceLocation getBackground();
static NeuRecipe parseRecipe(NEUManager manager, JsonObject recipe, JsonObject output) {
+ RecipeType recipeType = RecipeType.CRAFTING;
if (recipe.has("type")) {
- switch (recipe.get("type").getAsString().intern()) {
- case "forge":
- return ForgeRecipe.parseForgeRecipe(manager, recipe, output);
- case "trade":
- return VillagerTradeRecipe.parseStaticRecipe(manager, recipe);
- }
+ recipeType = RecipeType.getRecipeTypeForId(recipe.get("type").getAsString());
}
- return CraftingRecipe.parseCraftingRecipe(manager, recipe, output);
+ if (recipeType == null) return null;
+ return recipeType.createRecipe(manager, recipe, output);
}
default boolean shouldUseForCraftCost() {
@@ -49,4 +86,13 @@ public interface NeuRecipe {
default boolean isAvailable() {
return true;
}
+
+ /**
+ * @return an array of length two in the format [leftmost x, topmost y] of the page buttons
+ */
+ default int[] getPageFlipPositionLeftTopCorner() {
+ return new int[]{110, 90};
+ }
+
+ default void actionPerformed(GuiButton button) {}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
index 46aff6c4..d63ea42c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeGenerator.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.gson.JsonArray;
@@ -9,9 +28,11 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.init.Items;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
@@ -20,9 +41,14 @@ import org.lwjgl.input.Keyboard;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
public class RecipeGenerator {
public static final String DURATION = "Duration: ";
@@ -41,7 +67,7 @@ public class RecipeGenerator {
@SubscribeEvent
public void onTick(TickEvent event) {
- if (!neu.config.hidden.enableItemEditing) return;
+ if (!neu.config.apiData.repositoryEditing) return;
GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
if (currentScreen == null) return;
if (!(currentScreen instanceof GuiChest)) return;
@@ -81,7 +107,7 @@ public class RecipeGenerator {
" seconds (no QF) ."));
boolean saved = false;
try {
- saved = saveRecipe(recipe);
+ saved = saveRecipes(recipe.getOutput().getInternalItemId(), Collections.singletonList(recipe));
} catch (IOException e) {
}
if (!saved)
@@ -93,21 +119,153 @@ public class RecipeGenerator {
" Failed to save recipe. Does the item already exist?"));
}
}
+ if (saveRecipe) attemptToSaveBestiary(menu);
+ }
+
+ private List<String> getLore(ItemStack item) {
+ NBTTagList loreTag = item.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+ List<String> loreList = new ArrayList<>();
+ for (int i = 0; i < loreTag.tagCount(); i++) {
+ loreList.add(loreTag.getStringTagAt(i));
+ }
+ return loreList;
+ }
+
+ // §8[§7Lv1§8] §fZombie Villager
+ private static final Pattern MOB_DISPLAY_NAME_PATTERN = Pattern.compile("^§8\\[§7Lv(?<level>\\d+)§8] (?<name>.*)$");
+ // §7Coins per Kill: §61
+ // §7Combat Exp: §3120
+ // §8 ■ §7§5Skeleton Grunt Helmet §8(§a5%§8)
+ // §8 ■ §7§fRotten Flesh
+ // §8 ■ Dragon Essence §8x3-5
+ private static final Pattern LORE_PATTERN = Pattern.compile("^(?:" +
+ "§7Coins per Kill: §6(?<coins>[,\\d]+)|" +
+ "§7Combat Exp: §3(?<combatxp>[,\\d]+)|" +
+ "§7XP Orbs: §3(?<xp>[,\\d]+)|" +
+ "§8 ■ (?:§7)?(?<dropName>(?:§.)?.+?)(?: §8\\(§a(?<dropChances>[\\d.<]+%)§8\\)| §8(?<dropCount>x.*))?|" +
+ "§7Kills: §a[,\\d]+|" +
+ "§.[a-zA-Z]+ Loot|" +
+ "§7Deaths: §a[,\\d]+|" +
+ " §8■ (?<missing>§c\\?\\?\\?)|" +
+ "" +
+ ")$");
+
+ private void attemptToSaveBestiary(IInventory menu) {
+ if (!menu.getDisplayName().getUnformattedText().contains("➜")) return;
+ ItemStack backArrow = menu.getStackInSlot(48);
+ if (backArrow == null || backArrow.getItem() != Items.arrow) return;
+ if (!getLore(backArrow).stream().anyMatch(it -> it.startsWith("§7To Bestiary ➜"))) return;
+ List<NeuRecipe> recipes = new ArrayList<>();
+ String internalMobName =
+ menu.getDisplayName().getUnformattedText().split("➜")[1].toUpperCase(Locale.ROOT).trim() + "_MONSTER";
+ for (int i = 9; i < 44; i++) {
+ ItemStack mobStack = menu.getStackInSlot(i);
+ if (mobStack == null || mobStack.getItem() != Items.skull) continue;
+ Matcher matcher = MOB_DISPLAY_NAME_PATTERN.matcher(mobStack.getDisplayName());
+ if (!matcher.matches()) continue;
+ String name = matcher.group("name");
+ int level = parseIntIgnoringCommas(matcher.group("level"));
+ List<String> mobLore = getLore(mobStack);
+ int coins = 0, xp = 0, combatXp = 0;
+ List<MobLootRecipe.MobDrop> drops = new ArrayList<>();
+ for (String loreLine : mobLore) {
+ Matcher loreMatcher = LORE_PATTERN.matcher(loreLine);
+ if (!loreMatcher.matches()) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "[WARNING] Unknown lore line: " + loreLine));
+ continue;
+ }
+ if (loreMatcher.group("coins") != null)
+ coins = parseIntIgnoringCommas(loreMatcher.group("coins"));
+ if (loreMatcher.group("combatxp") != null)
+ combatXp = parseIntIgnoringCommas(loreMatcher.group("combatxp"));
+ if (loreMatcher.group("xp") != null)
+ xp = parseIntIgnoringCommas(loreMatcher.group("xp"));
+ if (loreMatcher.group("dropName") != null) {
+ String dropName = loreMatcher.group("dropName");
+ List<JsonObject> possibleItems = neu.manager.getItemInformation().values().stream().filter(it -> it.get(
+ "displayname").getAsString().equals(dropName)).collect(Collectors.toList());
+ if (possibleItems.size() != 1) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "[WARNING] Could not parse drop, ambiguous or missing item information: " + loreLine));
+ continue;
+ }
+ Ingredient item = new Ingredient(neu.manager, possibleItems.get(0).get("internalname").getAsString());
+ String chance = loreMatcher.group("dropChances") != null
+ ? loreMatcher.group("dropChances")
+ : loreMatcher.group("dropCount");
+ drops.add(new MobLootRecipe.MobDrop(item, chance, new ArrayList<>()));
+ }
+ if (loreMatcher.group("missing") != null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ "[WARNING] You are missing Bestiary levels for drop: " + loreLine));
+
+ }
+ }
+ recipes.add(new MobLootRecipe(
+ new Ingredient(neu.manager, internalMobName, 1),
+ drops,
+ level,
+ coins,
+ xp,
+ combatXp,
+ name,
+ null,
+ new ArrayList<>(),
+ "unknown"
+ ));
+ }
+ boolean saved = false;
+ try {
+ saved = saveRecipes(internalMobName, recipes);
+ } catch (IOException e) {
+ }
+ if (!saved)
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("" +
+ EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" +
+ EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + " ERROR " +
+ EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD + EnumChatFormatting.OBFUSCATED + "#" +
+ EnumChatFormatting.RESET + EnumChatFormatting.DARK_RED + EnumChatFormatting.BOLD +
+ " Failed to save recipe. Does the item already exist?")); // TODO: MERGE CODE OVER
+ }
+
+ private int parseIntIgnoringCommas(String text) {
+ return Integer.parseInt(text.replace(",", ""));
}
- public boolean saveRecipe(NeuRecipe recipe) throws IOException {
- JsonObject recipeJson = recipe.serialize();
- for (Ingredient i : recipe.getOutputs()) {
- if (i.isCoins()) continue;
- JsonObject outputJson = neu.manager.readJsonDefaultDir(i.getInternalItemId() + ".json");
- if (outputJson == null) return false;
- outputJson.addProperty("clickcommand", "viewrecipe");
- JsonArray array = new JsonArray();
- array.add(recipeJson);
- outputJson.add("recipes", array);
- neu.manager.writeJsonDefaultDir(outputJson, i.getInternalItemId() + ".json");
- neu.manager.loadItem(i.getInternalItemId());
+ /*{
+ id: "minecraft:skull",
+ Count: 1b,
+ tag: {
+ overrideMeta: 1b,
+ SkullOwner: {
+ Id: "2005daad-730b-363c-abae-e6f3830816fb",
+ Properties: {
+ textures: [{
+ Value: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTZjMGIzNmQ1M2ZmZjY5YTQ5YzdkNmYzOTMyZjJiMGZlOTQ4ZTAzMjIyNmQ1ZTgwNDVlYzU4NDA4YTM2ZTk1MSJ9fX0="
+ }]
+ }
+ },
+ display: {
+ Lore: ["§7Coins per Kill: §610", "§7Combat Exp: §340", "§7XP Orbs: §312", "", "§7Kills: §a990", "§7Deaths: §a2", "", "§fCommon Loot", "§8 ■ §7§fEnder Pearl §8x1-3", "", "§9Rare Loot", "§8 ■ §7§aEnchanted Ender Pearl §8(§a1%§8)", "", "§6Legendary Loot", "§8 ■ §7§7[Lvl 1] §aEnderman §8(§a0.02%§8)", "§8 ■ §7§7[Lvl 1] §fEnderman §8(§a0.05%§8)", "§8 ■ §7§5Ender Helmet §8(§a0.1%§8)", "§8 ■ §7§5Ender Boots §8(§a0.1%§8)", "§8 ■ §7§5Ender Leggings §8(§a0.1%§8)", "§8 ■ §7§5Ender Chestplate §8(§a0.1%§8)", "", "§dRNGesus Loot", " §8■ §c???"],
+ Name: "§8[§7Lv42§8] §fEnderman"
+ },
+ AttributeModifiers: []
+ },
+ Damage: 3s
+}*/
+ public boolean saveRecipes(String relevantItem, List<NeuRecipe> recipes) throws IOException {
+ relevantItem = relevantItem.replace(" ", "_");
+ JsonObject outputJson = neu.manager.readJsonDefaultDir(relevantItem + ".json");
+ if (outputJson == null) return false;
+ outputJson.addProperty("clickcommand", "viewrecipe");
+ JsonArray array = new JsonArray();
+ for (NeuRecipe recipe : recipes) {
+ array.add(recipe.serialize());
}
+ outputJson.add("recipes", array);
+ neu.manager.writeJsonDefaultDir(outputJson, relevantItem + ".json");
+ neu.manager.loadItem(relevantItem);
return true;
}
@@ -149,7 +307,7 @@ public class RecipeGenerator {
);
}
- private static final Map<Character, Integer> durationSuffixLengthMap = new HashMap<Character, Integer>() {{
+ private static Map<Character, Integer> durationSuffixLengthMap = new HashMap<Character, Integer>() {{
put('d', 60 * 60 * 24);
put('h', 60 * 60);
put('m', 60);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeSlot.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeSlot.java
index 61f8ef27..489485e4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeSlot.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeSlot.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java
new file mode 100644
index 00000000..de9c869f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/RecipeType.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.recipes;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+
+public enum RecipeType {
+ CRAFTING("crafting", "Crafting", CraftingRecipe::parseCraftingRecipe, new ItemStack(Blocks.crafting_table)),
+ FORGE("forge", "Forging", ForgeRecipe::parseForgeRecipe, new ItemStack(Blocks.anvil)),
+ TRADE("trade", "Trading", VillagerTradeRecipe::parseStaticRecipe, new ItemStack(Items.emerald)),
+ MOB_LOOT("drops", "Mob Loot", MobLootRecipe::parseRecipe, new ItemStack(Items.diamond_sword)),
+ NPC_SHOP("npc_shop", "NPC Item Shop", ItemShopRecipe::parseItemRecipe, new ItemStack(Items.wheat_seeds));
+
+ private final String id;
+ private final String label;
+ private final RecipeFactory recipeFactory;
+ private final ItemStack icon;
+
+ RecipeType(String id, String label, RecipeFactory recipeFactory, ItemStack icon) {
+ this.id = id;
+ this.label = label;
+ this.recipeFactory = recipeFactory;
+ this.icon = icon;
+ icon.setStackDisplayName("neurecipe-" + id);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public RecipeFactory getRecipeFactory() {
+ return recipeFactory;
+ }
+
+ public ItemStack getIcon() {
+ return icon;
+ }
+
+ public NeuRecipe createRecipe(NEUManager manager, JsonObject recipe, JsonObject outputItemJson) {
+ return recipeFactory.createRecipe(manager, recipe, outputItemJson);
+ }
+
+ public static RecipeType getRecipeTypeForId(String id) {
+ for (RecipeType value : values()) {
+ if (value.id.equals(id)) return value;
+ }
+ return null;
+ }
+
+ @FunctionalInterface
+ interface RecipeFactory {
+ NeuRecipe createRecipe(NEUManager manager, JsonObject recipe, JsonObject outputItemJson);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java
index 371d4f3c..9bb79604 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.recipes;
import com.google.common.collect.Sets;
@@ -17,18 +36,22 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.util.ResourceLocation;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
public class VillagerTradeRecipe implements NeuRecipe {
- public static final int COST_SLOT_X = 51;
- public static final int COST_SLOT_Y = 34;
- public static final int RESULT_SLOT_Y = 35;
+ public static final int COST_SLOT_X = 52;
+ public static final int COST_SLOT_Y = 66;
+ public static final int RESULT_SLOT_Y = 66;
public static final int RESULT_SLOT_X = 124;
private static class Holder { // This holder object exists to defer initialization to first access
- private static final GameProfile DREAM_PROFILE =
- new GameProfile(UUID.fromString("ec70bcaf-702f-4bb8-b48d-276fa52a780c"), "Dream");
+ private static final GameProfile DREAM_PROFILE = new GameProfile(UUID.fromString(
+ "ec70bcaf-702f-4bb8-b48d-276fa52a780c"), "Dream");
private static final EntityLivingBase DEMO_DREAM = new AbstractClientPlayer(null, DREAM_PROFILE) {
@Override
protected NetworkPlayerInfo getPlayerInfo() {
@@ -51,8 +74,10 @@ public class VillagerTradeRecipe implements NeuRecipe {
}
- private final static ResourceLocation BACKGROUND =
- new ResourceLocation("notenoughupdates", "textures/gui/villager_recipe.png");
+ private final static ResourceLocation BACKGROUND = new ResourceLocation(
+ "notenoughupdates",
+ "textures/gui/villager_recipe_tall.png"
+ );
private final Ingredient result;
private final Ingredient cost;
@@ -74,6 +99,11 @@ public class VillagerTradeRecipe implements NeuRecipe {
}
@Override
+ public RecipeType getType() {
+ return RecipeType.TRADE;
+ }
+
+ @Override
public Set<Ingredient> getIngredients() {
return Sets.newHashSet(cost);
}
@@ -108,7 +138,7 @@ public class VillagerTradeRecipe implements NeuRecipe {
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
Utils.drawStringCenteredScaledMaxWidth(
minCost + " - " + maxCost, fontRenderer,
- gui.guiLeft + 50, gui.guiTop + 60, false, 75, 0xff00ff
+ gui.guiLeft + 50, gui.guiTop + 90, false, 75, 0xff00ff
);
}
@@ -118,9 +148,9 @@ public class VillagerTradeRecipe implements NeuRecipe {
public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
GuiInventory.drawEntityOnScreen(
gui.guiLeft + 90,
- gui.guiTop + 75,
+ gui.guiTop + 100,
30,
- gui.guiLeft - mouseX + 80,
+ gui.guiLeft - mouseX + 110,
gui.guiTop + 60 - mouseY,
Holder.DEMO_ENTITY
);
@@ -131,7 +161,7 @@ public class VillagerTradeRecipe implements NeuRecipe {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("type", "trade");
jsonObject.addProperty("result", result.serialize());
- jsonObject.addProperty("cost", cost.getInternalItemId());
+ jsonObject.addProperty("cost", cost.serialize());
if (minCost > 0)
jsonObject.addProperty("min", minCost);
if (maxCost > 0)
@@ -144,7 +174,7 @@ public class VillagerTradeRecipe implements NeuRecipe {
return BACKGROUND;
}
- public static VillagerTradeRecipe parseStaticRecipe(NEUManager manager, JsonObject recipe) {
+ public static VillagerTradeRecipe parseStaticRecipe(NEUManager manager, JsonObject recipe, JsonObject result) {
return new VillagerTradeRecipe(
new Ingredient(manager, recipe.get("result").getAsString()),
new Ingredient(manager, recipe.get("cost").getAsString()),
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/AllowEmptyHTMLTag.java b/src/main/java/io/github/moulberry/notenoughupdates/util/AllowEmptyHTMLTag.java
index b7fc55e4..5c223605 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/AllowEmptyHTMLTag.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/AllowEmptyHTMLTag.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import info.bliki.htmlcleaner.TagNode;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
new file mode 100644
index 00000000..8c594911
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ApiUtil.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.message.BasicNameValuePair;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.zip.GZIPInputStream;
+
+public class ApiUtil {
+ private static final Gson gson = new Gson();
+ private static final ExecutorService executorService = Executors.newFixedThreadPool(3);
+ private static final String USER_AGENT = "NotEnoughUpdates/" + NotEnoughUpdates.VERSION;
+ private static SSLContext ctx;
+
+ static {
+ try {
+ KeyStore letsEncryptStore = KeyStore.getInstance("JKS");
+ letsEncryptStore.load(ApiUtil.class.getResourceAsStream("/neukeystore.jks"), "neuneu".toCharArray());
+ ctx = SSLContext.getInstance("TLS");
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ kmf.init(letsEncryptStore, null);
+ tmf.init(letsEncryptStore);
+ ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ } catch (KeyStoreException | NoSuchAlgorithmException | KeyManagementException | UnrecoverableKeyException |
+ IOException | CertificateException e) {
+ System.out.println("Failed to load NEU keystore. A lot of API requests won't work");
+ e.printStackTrace();
+ }
+ }
+
+ public static class Request {
+
+ private final List<NameValuePair> queryArguments = new ArrayList<>();
+ private String baseUrl = null;
+ private boolean shouldGunzip = false;
+ private String method = "GET";
+
+ public Request method(String method) {
+ this.method = method;
+ return this;
+ }
+
+ public Request url(String baseUrl) {
+ this.baseUrl = baseUrl;
+ return this;
+ }
+
+ public Request queryArgument(String key, String value) {
+ queryArguments.add(new BasicNameValuePair(key, value));
+ return this;
+ }
+
+ public Request queryArguments(Collection<NameValuePair> queryArguments) {
+ this.queryArguments.addAll(queryArguments);
+ return this;
+ }
+
+ public Request gunzip() {
+ shouldGunzip = true;
+ return this;
+ }
+
+ private CompletableFuture<URL> buildUrl() {
+ CompletableFuture<URL> fut = new CompletableFuture<>();
+ try {
+ fut.complete(new URIBuilder(baseUrl)
+ .addParameters(queryArguments)
+ .build()
+ .toURL());
+ } catch (URISyntaxException |
+ MalformedURLException |
+ NullPointerException e) { // Using CompletableFuture as an exception monad, isn't that exiting?
+ fut.completeExceptionally(e);
+ }
+ return fut;
+ }
+
+ public CompletableFuture<String> requestString() {
+ return buildUrl().thenApplyAsync(url -> {
+ try {
+ InputStream inputStream = null;
+ URLConnection conn = null;
+ try {
+ conn = url.openConnection();
+ if (conn instanceof HttpsURLConnection && ctx != null) {
+ HttpsURLConnection sslConn = (HttpsURLConnection) conn;
+ sslConn.setSSLSocketFactory(ctx.getSocketFactory());
+ }
+ if (conn instanceof HttpURLConnection) {
+ ((HttpURLConnection) conn).setRequestMethod(method);
+ }
+ conn.setConnectTimeout(10000);
+ conn.setReadTimeout(10000);
+ conn.setRequestProperty("User-Agent", USER_AGENT);
+
+ inputStream = conn.getInputStream();
+
+ if (shouldGunzip) {
+ inputStream = new GZIPInputStream(inputStream);
+ }
+
+ // While the assumption of UTF8 isn't always true; it *should* always be true.
+ // Not in the sense that this will hold in most cases (although that as well),
+ // but in the sense that any violation of this better have a good reason.
+ return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
+ } finally {
+ try {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ } finally {
+ if (conn instanceof HttpURLConnection) {
+ ((HttpURLConnection) conn).disconnect();
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e); // We can rethrow, since supplyAsync catches exceptions.
+ }
+ }, executorService);
+ }
+
+ public CompletableFuture<JsonObject> requestJson() {
+ return requestJson(JsonObject.class);
+ }
+
+ public <T> CompletableFuture<T> requestJson(Class<? extends T> clazz) {
+ return requestString().thenApply(str -> gson.fromJson(str, clazz));
+ }
+
+ }
+
+ public Request request() {
+ return new Request();
+ }
+
+ public Request newHypixelApiRequest(String apiPath) {
+ return newAnonymousHypixelApiRequest(apiPath)
+ .queryArgument("key", NotEnoughUpdates.INSTANCE.config.apiData.apiKey);
+ }
+
+ public Request newAnonymousHypixelApiRequest(String apiPath) {
+ return new Request()
+ .url("https://api.hypixel.net/" + apiPath);
+ }
+
+ public Request newMoulberryRequest(String path) {
+ return new Request()
+ .url(getMyApiURL() + path);
+ }
+
+ private String getMyApiURL() {
+ return String.format("https://%s/", NotEnoughUpdates.INSTANCE.config.apiData.moulberryCodesApi);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java
new file mode 100644
index 00000000..37b0a187
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoader.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.common.base.Objects;
+
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public interface AsyncDependencyLoader<T> {
+
+ Optional<T> peekValue();
+
+ public static <R, T> AsyncDependencyLoader<T> withObjectIdentity(
+ Supplier<R> supplier,
+ Function<R, CompletableFuture<T>> generator
+ ) {
+ return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> a != b);
+ }
+
+ public static <R, T> AsyncDependencyLoader<T> withEqualsInvocation(
+ Supplier<R> supplier,
+ Function<R, CompletableFuture<T>> generator
+ ) {
+ return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> !Objects.equal(a, b));
+ }
+
+ public static <R, T> AsyncDependencyLoader<T> withEqualityFunction(
+ Supplier<R> supplier,
+ Function<R, CompletableFuture<T>> generator,
+ BiFunction<R, R, Boolean> isEqual
+ ) {
+ return new AsyncDependencyLoaderImpl<>(supplier, generator, (a, b) -> !isEqual.apply(a, b));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java
new file mode 100644
index 00000000..4b7f2fb8
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/AsyncDependencyLoaderImpl.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+class AsyncDependencyLoaderImpl<R, T> implements AsyncDependencyLoader<T> {
+
+ private final Supplier<R> supplyDependency;
+ private final Function<R, CompletableFuture<T>> generator;
+ private final BiFunction<R, R, Boolean> isDifferent;
+ private volatile CompletableFuture<T> lastValue;
+ private volatile R lastDependency;
+ private volatile boolean isFirstFire = true;
+
+ @Override
+ public synchronized Optional<T> peekValue() {
+ R nextDependency = supplyDependency.get();
+ if (isFirstFire || isDifferent.apply(nextDependency, lastDependency)) {
+ isFirstFire = false;
+ if (lastValue != null)
+ lastValue.cancel(true);
+ lastValue = generator.apply(nextDependency);
+ }
+ lastDependency = nextDependency;
+ return Optional.ofNullable(lastValue.getNow(null));
+ }
+
+ AsyncDependencyLoaderImpl(
+ Supplier<R> supplyDependency,
+ Function<R, CompletableFuture<T>> generator,
+ BiFunction<R, R, Boolean> isDifferent
+ ) {
+ this.supplyDependency = supplyDependency;
+ this.generator = generator;
+ this.isDifferent = isDifferent;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
new file mode 100644
index 00000000..10bfa6a9
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Calculator.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.List;
+import java.util.Locale;
+import java.util.NoSuchElementException;
+
+public class Calculator {
+ public static BigDecimal calculate(String source) throws CalculatorException {
+ source = source.toLowerCase(Locale.ROOT);
+ return evaluate(shuntingYard(lex(source)));
+ }
+
+ ///<editor-fold desc="Lexing Time">
+ public enum TokenType {
+ NUMBER, BINOP, LPAREN, RPAREN, POSTOP
+ }
+
+ public static class Token {
+ public TokenType type;
+ String operatorValue;
+ long numericValue;
+ int exponent;
+ int tokenStart;
+ int tokenLength;
+ }
+
+ static String binops = "+-*/x";
+ static String postops = "mkbts";
+ static String digits = "0123456789";
+
+ static void readDigitsInto(Token token, String source, boolean decimals) {
+ int startIndex = token.tokenStart + token.tokenLength;
+ for (int j = 0; j + startIndex < source.length(); j++) {
+ char d = source.charAt(j + startIndex);
+ int d0 = digits.indexOf(d);
+ if (d0 != -1) {
+ if (decimals)
+ token.exponent--;
+ token.numericValue *= 10;
+ token.numericValue += d0;
+ token.tokenLength += 1;
+ } else {
+ return;
+ }
+ }
+ }
+
+ public static class CalculatorException extends Exception {
+ int offset, length;
+
+ public CalculatorException(String message, int offset, int length) {
+ super(message);
+ this.offset = offset;
+ this.length = length;
+ }
+
+ public int getLength() {
+ return length;
+ }
+
+ public int getOffset() {
+ return offset;
+ }
+ }
+
+ public static List<Token> lex(String source) throws CalculatorException {
+ List<Token> tokens = new ArrayList<>();
+ for (int i = 0; i < source.length(); ) {
+ char c = source.charAt(i);
+ if (Character.isWhitespace(c)) {
+ i++;
+ continue;
+ }
+ Token token = new Token();
+ token.tokenStart = i;
+ if (binops.indexOf(c) != -1) {
+ token.tokenLength = 1;
+ token.type = TokenType.BINOP;
+ token.operatorValue = c + "";
+ } else if (postops.indexOf(c) != -1) {
+ token.tokenLength = 1;
+ token.type = TokenType.POSTOP;
+ token.operatorValue = c + "";
+ } else if (c == ')') {
+ token.tokenLength = 1;
+ token.type = TokenType.RPAREN;
+ token.operatorValue = ")";
+ } else if (c == '(') {
+ token.tokenLength = 1;
+ token.type = TokenType.LPAREN;
+ token.operatorValue = "(";
+ } else if ('.' == c) {
+ token.tokenLength = 1;
+ token.type = TokenType.NUMBER;
+ readDigitsInto(token, source, true);
+ if (token.tokenLength == 1) {
+ throw new CalculatorException("Invalid number literal", i, 1);
+ }
+ } else if (digits.indexOf(c) != -1) {
+ token.type = TokenType.NUMBER;
+ readDigitsInto(token, source, false);
+ if (i + token.tokenLength < source.length()) {
+ char p = source.charAt(i + token.tokenLength);
+ if ('.' == p) {
+ token.tokenLength++;
+ readDigitsInto(token, source, true);
+ }
+ }
+ } else {
+ throw new CalculatorException("Unknown thing " + c, i, 1);
+ }
+ tokens.add(token);
+ i += token.tokenLength;
+ }
+ return tokens;
+ }
+ ///</editor-fold>
+
+ ///<editor-fold desc="Shunting Time">
+ static int getPrecedence(Token token) throws CalculatorException {
+ switch (token.operatorValue.intern()) {
+ case "+":
+ case "-":
+ return 0;
+ case "*":
+ case "/":
+ case "x":
+ return 1;
+ }
+ throw new CalculatorException("Unknown operator " + token.operatorValue, token.tokenStart, token.tokenLength);
+ }
+
+ public static List<Token> shuntingYard(List<Token> toShunt) throws CalculatorException {
+ // IT'S SHUNTING TIME
+ // This is an implementation of the shunting yard algorithm
+
+ Deque<Token> op = new ArrayDeque<>();
+ List<Token> out = new ArrayList<>();
+
+ for (Token currentlyShunting : toShunt) {
+ switch (currentlyShunting.type) {
+ case NUMBER:
+ out.add(currentlyShunting);
+ break;
+ case BINOP:
+ int p = getPrecedence(currentlyShunting);
+ while (!op.isEmpty()) {
+ Token l = op.peek();
+ if (l.type == TokenType.LPAREN)
+ break;
+ assert (l.type == TokenType.BINOP);
+ int pl = getPrecedence(l);
+ if (pl >= p) { // Association order
+ out.add(op.pop());
+ } else {
+ break;
+ }
+ }
+ op.push(currentlyShunting);
+ break;
+ case LPAREN:
+ op.push(currentlyShunting);
+ break;
+ case RPAREN:
+ while (1 > 0) {
+ if (op.isEmpty())
+ throw new CalculatorException(
+ "Unbalanced right parenthesis",
+ currentlyShunting.tokenStart,
+ currentlyShunting.tokenLength
+ );
+ Token l = op.pop();
+ if (l.type == TokenType.LPAREN) {
+ break;
+ }
+ out.add(l);
+ }
+ break;
+ case POSTOP:
+ out.add(currentlyShunting);
+ break;
+ }
+ }
+ while (!op.isEmpty()) {
+ Token l = op.pop();
+ if (l.type == TokenType.LPAREN)
+ throw new CalculatorException("Unbalanced left parenthesis", l.tokenStart, l.tokenLength);
+ out.add(l);
+ }
+ return out;
+ }
+
+ /// </editor-fold>
+
+ ///<editor-fold desc="Evaluating Time">
+
+ public static BigDecimal evaluate(List<Token> rpnTokens) throws CalculatorException {
+ Deque<BigDecimal> values = new ArrayDeque<>();
+ try {
+ for (Token command : rpnTokens) {
+ switch (command.type) {
+ case NUMBER:
+ values.push(new BigDecimal(command.numericValue).scaleByPowerOfTen(command.exponent));
+ break;
+ case BINOP:
+ BigDecimal right = values.pop().setScale(2, RoundingMode.HALF_UP);
+ BigDecimal left = values.pop().setScale(2, RoundingMode.HALF_UP);
+ switch (command.operatorValue.intern()) {
+ case "x":
+ case "*":
+ values.push(left.multiply(right).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "/":
+ try {
+ values.push(left.divide(right, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP));
+ } catch (ArithmeticException e) {
+ throw new CalculatorException("Encountered division by 0", command.tokenStart, command.tokenLength);
+ }
+ break;
+ case "+":
+ values.push(left.add(right).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "-":
+ values.push(left.subtract(right).setScale(2, RoundingMode.HALF_UP));
+ break;
+ default:
+ throw new CalculatorException(
+ "Unknown operation " + command.operatorValue,
+ command.tokenStart,
+ command.tokenLength
+ );
+ }
+ break;
+ case LPAREN:
+ case RPAREN:
+ throw new CalculatorException(
+ "Did not expect unshunted token in RPN",
+ command.tokenStart,
+ command.tokenLength
+ );
+ case POSTOP:
+ BigDecimal p = values.pop();
+ switch (command.operatorValue.intern()) {
+ case "s":
+ values.push(p.multiply(new BigDecimal(64)).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "k":
+ values.push(p.multiply(new BigDecimal(1_000)).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "m":
+ values.push(p.multiply(new BigDecimal(1_000_000)).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "b":
+ values.push(p.multiply(new BigDecimal(1_000_000_000)).setScale(2, RoundingMode.HALF_UP));
+ break;
+ case "t":
+ values.push(p.multiply(new BigDecimal("1000000000000")).setScale(2, RoundingMode.HALF_UP));
+ break;
+ default:
+ throw new CalculatorException(
+ "Unknown operation " + command.operatorValue,
+ command.tokenStart,
+ command.tokenLength
+ );
+ }
+ break;
+ }
+ }
+ BigDecimal peek = values.pop();
+ return peek.stripTrailingZeros();
+ } catch (NoSuchElementException e) {
+ throw new CalculatorException("Unfinished expression", 0, 0);
+ }
+ }
+
+ ///</editor-fold>
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
index bb3b3425..ef030367 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
@@ -1,7 +1,36 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
-import com.google.gson.*;
-import io.github.moulberry.notenoughupdates.collectionlog.CollectionConstant;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import io.github.moulberry.notenoughupdates.events.RepositoryReloadEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.lang.reflect.Type;
import java.util.concurrent.locks.ReentrantLock;
@@ -40,11 +69,14 @@ public class Constants {
public static JsonObject ESSENCECOSTS;
public static JsonObject FAIRYSOULS;
public static JsonObject REFORGESTONES;
- public static CollectionConstant COLLECTIONLOG;
+ public static JsonObject TROPHYFISH;
+ public static JsonObject WEIGHT;
+ public static JsonObject RNGSCORE;
private static final ReentrantLock lock = new ReentrantLock();
- public static void reload() {
+ @SubscribeEvent
+ public void reload(RepositoryReloadEvent event) {
try {
lock.lock();
@@ -59,7 +91,11 @@ public class Constants {
ESSENCECOSTS = Utils.getConstant("essencecosts", gson);
FAIRYSOULS = Utils.getConstant("fairy_souls", gson);
REFORGESTONES = Utils.getConstant("reforgestones", gson);
- //COLLECTIONLOG = Utils.getConstant("collectionlog", gson, CollectionConstant.class);
+ TROPHYFISH = Utils.getConstant("trophyfish", gson);
+ WEIGHT = Utils.getConstant("weight", gson);
+ RNGSCORE = Utils.getConstant("rngscore", gson);
+ } catch (Exception ex) {
+ ex.printStackTrace();
} finally {
lock.unlock();
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Debouncer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Debouncer.java
index 15808a29..ec076a77 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Debouncer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Debouncer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
/**
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java b/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java
index 1c78f924..3c6c5f3d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/DiscordMarkdownBuilder.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
public class DiscordMarkdownBuilder {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/GuiTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/util/GuiTextures.java
index 48a6915b..3ead5a56 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/GuiTextures.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/GuiTextures.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import net.minecraft.util.ResourceLocation;
@@ -8,8 +27,6 @@ public class GuiTextures {
public static final ResourceLocation itemPaneTabArrow =
new ResourceLocation("notenoughupdates:item_pane_tab_arrow.png");
- //public static final ResourceLocation prev = new ResourceLocation("notenoughupdates:prev.png");
- //public static final ResourceLocation next = new ResourceLocation("notenoughupdates:next.png");
public static final ResourceLocation rightarrow_overlay =
new ResourceLocation("notenoughupdates:rightarrow_overlay.png");
public static final ResourceLocation rightarrow = new ResourceLocation("notenoughupdates:rightarrow.png");
@@ -19,8 +36,6 @@ public class GuiTextures {
public static final ResourceLocation off = new ResourceLocation("notenoughupdates:off.png");
public static final ResourceLocation on = new ResourceLocation("notenoughupdates:on.png");
public static final ResourceLocation help = new ResourceLocation("notenoughupdates:help.png");
- public static final ResourceLocation slider_off = new ResourceLocation("notenoughupdates:slider_off.png");
- public static final ResourceLocation slider_on = new ResourceLocation("notenoughupdates:slider_on.png");
public static final ResourceLocation slider_off_large = new ResourceLocation("notenoughupdates:slider_off_large.png");
public static final ResourceLocation slider_on_large = new ResourceLocation("notenoughupdates:slider_on_large.png");
public static final ResourceLocation slider_button = new ResourceLocation("notenoughupdates:slider_button.png");
@@ -34,36 +49,17 @@ public class GuiTextures {
public static final ResourceLocation item_mask = new ResourceLocation("notenoughupdates:item_mask.png");
public static final ResourceLocation item_haschild = new ResourceLocation("notenoughupdates:item_haschild.png");
+ public static final ResourceLocation button_white = new ResourceLocation("notenoughupdates:button_white.png");
public static final ResourceLocation button_tex = new ResourceLocation("notenoughupdates:button.png");
public static final ResourceLocation button_fsr =
new ResourceLocation("notenoughupdates:FSR_do_not_texture_this_please.png");
- public static final ResourceLocation setting_border = new ResourceLocation("notenoughupdates:setting_border.png");
-
- public static final ResourceLocation button_white = new ResourceLocation("notenoughupdates:button_white.png");
- public static final ResourceLocation colour_selector_dot =
- new ResourceLocation("notenoughupdates:colour_selector_dot.png");
- public static final ResourceLocation colour_selector_bar =
- new ResourceLocation("notenoughupdates:colour_selector_bar.png");
- public static final ResourceLocation colour_selector_bar_alpha =
- new ResourceLocation("notenoughupdates:colour_selector_bar_alpha.png");
- public static final ResourceLocation colour_selector_chroma =
- new ResourceLocation("notenoughupdates:colour_selector_chroma.png");
-
public static final ResourceLocation accessory_bag_overlay =
new ResourceLocation("notenoughupdates:accessory_bag_overlay.png");
public static final ResourceLocation quickcommand_background =
new ResourceLocation("notenoughupdates:quickcommand_background.png");
- public static final ResourceLocation gamemodes = new ResourceLocation("notenoughupdates:gamemodes.png");
- public static final ResourceLocation radial_square_off =
- new ResourceLocation("notenoughupdates:radial_square_off.png");
- public static final ResourceLocation radial_square_on = new ResourceLocation("notenoughupdates:radial_square_on.png");
- public static final ResourceLocation radial_circle_off =
- new ResourceLocation("notenoughupdates:radial_circle_off.png");
- public static final ResourceLocation radial_circle_on = new ResourceLocation("notenoughupdates:radial_circle_on.png");
-
public static final ResourceLocation dungeon_chest_worth =
new ResourceLocation("notenoughupdates:dungeon_chest_worth.png");
@@ -73,10 +69,6 @@ public class GuiTextures {
public static final ResourceLocation auction_view_buttons =
new ResourceLocation("notenoughupdates:auction_view_buttons.png");
- public static final ResourceLocation logo = new ResourceLocation("notenoughupdates:logo.png");
- public static final ResourceLocation logo_fg = new ResourceLocation("notenoughupdates:logo_fg.png");
- public static final ResourceLocation logo_bg = new ResourceLocation("notenoughupdates:logo_bg.png");
-
public static final ResourceLocation sort_all = new ResourceLocation("notenoughupdates:sort_all.png");
public static final ResourceLocation sort_mob = new ResourceLocation("notenoughupdates:sort_mob.png");
public static final ResourceLocation sort_pet = new ResourceLocation("notenoughupdates:sort_pet.png");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java
index 9cbad402..27993510 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HastebinUploader.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.gson.Gson;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java
index 7258fe9f..1968b51e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HotmInformation.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.gson.JsonArray;
@@ -140,13 +159,11 @@ public class HotmInformation {
public synchronized void requestUpdate(boolean force) {
if (updateTask.isDone() || force) {
- updateTask = neu.manager.hypixelApi.getHypixelApiAsync(
- neu.config.apiKey.apiKey,
- "skyblock/profiles",
- new HashMap<String, String>() {{
- put("uuid", Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""));
- }}
- ).thenAccept(this::updateInformation);
+ updateTask = neu.manager.apiUtils
+ .newHypixelApiRequest("skyblock/profiles")
+ .queryArgument("uuid", Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""))
+ .requestJson()
+ .thenAccept(this::updateInformation);
}
}
@@ -176,7 +193,10 @@ public class HotmInformation {
Tree tree = new Tree();
JsonObject nodes = miningCore.getAsJsonObject("nodes");
for (Map.Entry<String, JsonElement> node : nodes.entrySet()) {
- tree.levels.put(node.getKey(), node.getValue().getAsInt());
+ String key = node.getKey();
+ if (!key.startsWith("toggle_")) {
+ tree.levels.put(key, node.getValue().getAsInt());
+ }
}
if (miningCore.has("powder_mithril_total")) {
tree.totalMithrilPowder = miningCore.get("powder_mithril_total").getAsInt();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
deleted file mode 100644
index 2628eb7d..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package io.github.moulberry.notenoughupdates.util;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import org.apache.commons.io.IOUtils;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.net.ConnectException;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLEncoder;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.function.Consumer;
-import java.util.zip.GZIPInputStream;
-
-public class HypixelApi {
- private final Gson gson = new Gson();
- private final ExecutorService es = Executors.newFixedThreadPool(3);
-
- private static final int FAILS_BEFORE_SWITCH = 3;
- private int currentUrl = 0;
- private long lastPrimaryUrl = 0;
- private final String[] myApiURLs = {"https://moulberry.codes/"};
- //, "http://moulberry.codes/", "http://51.79.51.21/"};//, "http://51.75.78.252/" };
- private final Integer[] myApiSuccesses = {0, 0, 0, 0};
-
- public CompletableFuture<JsonObject> getHypixelApiAsync(String apiKey, String method, HashMap<String, String> args) {
- return getApiAsync(generateApiUrl(apiKey, method, args));
- }
-
- public void getHypixelApiAsync(
- String apiKey,
- String method,
- HashMap<String, String> args,
- Consumer<JsonObject> consumer
- ) {
- getHypixelApiAsync(apiKey, method, args, consumer, () -> {
- });
- }
-
- public void getHypixelApiAsync(
- String apiKey,
- String method,
- HashMap<String, String> args,
- Consumer<JsonObject> consumer,
- Runnable error
- ) {
- getApiAsync(generateApiUrl(apiKey, method, args), consumer, error);
- }
-
- private String getMyApiURL() {
- if (currentUrl == 0) {
- lastPrimaryUrl = System.currentTimeMillis();
- } else if (System.currentTimeMillis() - lastPrimaryUrl > 1000 * 60 * 30) { //Try switch back to main url after 30m
- currentUrl = 0;
- }
-
- myApiSuccesses[currentUrl] = Math.min(FAILS_BEFORE_SWITCH, myApiSuccesses[currentUrl] + 1);
- return myApiURLs[currentUrl];
- }
-
- private void myApiError(int index) {
- myApiSuccesses[index] = myApiSuccesses[index] - 2;
-
- if (myApiSuccesses[index] < 0) {
- myApiSuccesses[index] = 0;
-
- if (index == currentUrl) {
- currentUrl++;
- if (currentUrl >= myApiURLs.length) {
- currentUrl = 0;
- }
- }
- }
- }
-
- public CompletableFuture<JsonObject> getApiAsync(String urlS) {
- CompletableFuture<JsonObject> result = new CompletableFuture<>();
- es.submit(() -> {
- try {
- result.complete(getApiSync(urlS));
- } catch (Exception e) {
- result.completeExceptionally(e);
- }
- });
- return result;
- }
-
- public void getApiAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
- es.submit(() -> {
- try {
- consumer.accept(getApiSync(urlS));
- } catch (Exception e) {
- error.run();
- }
- });
- }
-
- public void getMyApiAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
- es.submit(() -> {
- int current = currentUrl;
- try {
- consumer.accept(getApiSync(getMyApiURL() + urlS));
- } catch (Exception e) {
- if (NotEnoughUpdates.INSTANCE.config.hidden.dev) {
- e.printStackTrace();
- }
- myApiError(current);
- error.run();
- }
- });
- }
-
- public void getMyApiGZIPAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
- es.submit(() -> {
- int current = currentUrl;
- try {
- consumer.accept(getApiGZIPSync(getMyApiURL() + urlS));
- } catch (Exception e) {
- myApiError(current);
- error.run();
- }
- });
- }
-
- public void getApiGZIPAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
- es.submit(() -> {
- try {
- consumer.accept(getApiGZIPSync(urlS));
- } catch (Exception e) {
- error.run();
- }
- });
- }
-
- public JsonObject getApiSync(String urlS) throws IOException {
- URL url = new URL(urlS);
- URLConnection connection = url.openConnection();
- connection.setConnectTimeout(10000);
- connection.setReadTimeout(10000);
-
- String response = IOUtils.toString(connection.getInputStream(), StandardCharsets.UTF_8);
-
- JsonObject json = gson.fromJson(response, JsonObject.class);
- if (json == null) throw new ConnectException("Invalid JSON");
- return json;
- }
-
- public JsonObject getApiGZIPSync(String urlS) throws IOException {
- URL url = new URL(urlS);
- URLConnection connection = url.openConnection();
- connection.setConnectTimeout(10000);
- connection.setReadTimeout(10000);
-
- String response = IOUtils.toString(new GZIPInputStream(connection.getInputStream()), StandardCharsets.UTF_8);
-
- JsonObject json = gson.fromJson(response, JsonObject.class);
- return json;
- }
-
- public String generateApiUrl(String apiKey, String method, HashMap<String, String> args) {
- if (apiKey != null)
- args.put("key", apiKey.trim().replace("-", ""));
- StringBuilder url = new StringBuilder("https://api.hypixel.net/" + method);
- boolean first = true;
- for (Map.Entry<String, String> entry : args.entrySet()) {
- if (first) {
- url.append("?");
- first = false;
- } else {
- url.append("&");
- }
- try {
- url.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8.name())).append("=")
- .append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()));
- } catch (UnsupportedEncodingException e) {
- }
- }
- return url.toString();
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java
new file mode 100644
index 00000000..3692602a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemResolutionQuery.java
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParseException;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+
+import javax.annotation.Nullable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class ItemResolutionQuery {
+
+ private static final Pattern ENCHANTED_BOOK_NAME_PATTERN = Pattern.compile("^((?:§.)+)([^§]+) ([IVXL]+)$");
+ private static final String EXTRA_ATTRIBUTES = "ExtraAttributes";
+ private static final List<String> PET_RARITIES = Arrays.asList(
+ "COMMON",
+ "UNCOMMON",
+ "RARE",
+ "EPIC",
+ "LEGENDARY",
+ "MYTHIC"
+ );
+ private final NEUManager manager;
+ private NBTTagCompound compound;
+ private Item itemType;
+ private int stackSize = -1;
+ private Gui guiContext;
+ private String knownInternalName;
+
+ public ItemResolutionQuery(NEUManager manager) {
+ this.manager = manager;
+ }
+
+ public ItemResolutionQuery withItemNBT(NBTTagCompound compound) {
+ this.compound = compound;
+ return this;
+ }
+
+ public ItemResolutionQuery withItemStack(ItemStack stack) {
+ if (stack == null) return this;
+ this.itemType = stack.getItem();
+ this.compound = stack.getTagCompound();
+ this.stackSize = stack.stackSize;
+ return this;
+ }
+
+ public ItemResolutionQuery withGuiContext(Gui gui) {
+ this.guiContext = gui;
+ return this;
+ }
+
+ public ItemResolutionQuery withCurrentGuiContext() {
+ this.guiContext = Minecraft.getMinecraft().currentScreen;
+ return this;
+ }
+
+ public ItemResolutionQuery withKnownInternalName(String knownInternalName) {
+ this.knownInternalName = knownInternalName;
+ return this;
+ }
+
+ @Nullable
+ public String resolveInternalName() {
+ if (knownInternalName != null) {
+ return knownInternalName;
+ }
+ String resolvedName = resolveFromSkyblock();
+ if (resolvedName == null) {
+ resolvedName = resolveContextualName();
+ } else {
+ switch (resolvedName.intern()) {
+ case "PET":
+ resolvedName = resolvePetName();
+ break;
+ case "RUNE":
+ resolvedName = resolveRuneName();
+ break;
+ case "ENCHANTED_BOOK":
+ resolvedName = resolveEnchantedBookNameFromNBT();
+ break;
+ case "PARTY_HAT_CRAB":
+ case "PARTY_HAT_CRAB_ANIMATED":
+ resolvedName = resolveCrabHatName();
+ break;
+ }
+ }
+
+ return resolvedName;
+ }
+
+ @Nullable
+ public JsonObject resolveToItemListJson() {
+ String internalName = resolveInternalName();
+ if (internalName == null) {
+ return null;
+ }
+ return manager.getItemInformation().get(internalName);
+ }
+
+ @Nullable
+ public ItemStack resolveToItemStack() {
+ JsonObject jsonObject = resolveToItemListJson();
+ if (jsonObject == null) return null;
+ return manager.jsonToStack(jsonObject);
+ }
+
+ @Nullable
+ public ItemStack resolveToItemStack(boolean useReplacements) {
+ JsonObject jsonObject = resolveToItemListJson();
+ if (jsonObject == null) return null;
+ return manager.jsonToStack(jsonObject, false, useReplacements);
+ }
+
+ // <editor-fold desc="Resolution Helpers">
+ private boolean isBazaar(IInventory chest) {
+ if (chest.getDisplayName().getFormattedText().startsWith("Bazaar ➜ ")) {
+ return true;
+ }
+ int bazaarSlot = chest.getSizeInventory() - 5;
+ if (bazaarSlot < 0) return false;
+ ItemStack stackInSlot = chest.getStackInSlot(bazaarSlot);
+ if (stackInSlot == null || stackInSlot.stackSize == 0) return false;
+ // NBT lore, we do not care about rendered lore
+ List<String> lore = ItemUtils.getLore(stackInSlot);
+ return lore.contains("§7To Bazaar");
+ }
+
+ private String resolveContextualName() {
+ if (!(guiContext instanceof GuiChest)) {
+ return null;
+ }
+ GuiChest chest = (GuiChest) guiContext;
+ ContainerChest inventorySlots = (ContainerChest) chest.inventorySlots;
+ String guiName = inventorySlots.getLowerChestInventory().getDisplayName().getUnformattedText();
+ boolean isOnBazaar = isBazaar(inventorySlots.getLowerChestInventory());
+ String displayName = ItemUtils.getDisplayName(compound);
+ if (displayName == null) return null;
+ if (itemType == Items.enchanted_book && isOnBazaar && compound != null) {
+ return resolveEnchantmentByName(displayName);
+ }
+ if (displayName.endsWith("Enchanted Book") && guiName.startsWith("Superpairs")) {
+ for (String loreLine : ItemUtils.getLore(compound)) {
+ String enchantmentIdCandidate = resolveEnchantmentByName(loreLine);
+ if (enchantmentIdCandidate != null) return enchantmentIdCandidate;
+ }
+ return null;
+ }
+ if (guiName.equals("Catacombs RNG Meter")) {
+ return resolveItemInCatacombsRngMeter();
+ }
+ return null;
+ }
+
+ private String resolveItemInCatacombsRngMeter() {
+ List<String> lore = ItemUtils.getLore(compound);
+ if (lore.size() > 16) {
+ String s = lore.get(15);
+ if (s.equals("§7Selected Drop")) {
+ String displayName = lore.get(16);
+ return getInternalNameByDisplayName(displayName);
+ }
+ }
+
+ return null;
+ }
+
+ private String getInternalNameByDisplayName(String displayName) {
+ String cleanDisplayName = StringUtils.cleanColour(displayName);
+ for (Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager
+ .getItemInformation()
+ .entrySet()) {
+
+ JsonObject object = entry.getValue();
+ if (object.has("displayname")) {
+ String name = object.get("displayname").getAsString();
+ if (StringUtils.cleanColour(name).equals(cleanDisplayName)) {
+ return entry.getKey();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ private String resolveEnchantmentByName(String name) {
+ Matcher matcher = ENCHANTED_BOOK_NAME_PATTERN.matcher(name);
+ if (!matcher.matches()) return null;
+ String format = matcher.group(1).toLowerCase(Locale.ROOT);
+ String enchantmentName = matcher.group(2).trim();
+ String romanLevel = matcher.group(3);
+ boolean ultimate = (format.contains("§l"));
+
+ return (ultimate ? "ULTIMATE_" : "")
+ + enchantmentName.replace(" ", "_").toUpperCase(Locale.ROOT)
+ + ";" + Utils.parseRomanNumeral(romanLevel);
+ }
+
+ private String resolveCrabHatName() {
+ int crabHatYear = getExtraAttributes().getInteger("party_hat_year");
+ String color = getExtraAttributes().getString("party_hat_color");
+ return "PARTY_HAT_CRAB_" + color.toUpperCase(Locale.ROOT) + (crabHatYear == 2022 ? "_ANIMATED" : "");
+ }
+
+ private String resolveEnchantedBookNameFromNBT() {
+ NBTTagCompound enchantments = getExtraAttributes().getCompoundTag("enchantments");
+ String enchantName = IteratorUtils.getOnlyElement(enchantments.getKeySet(), null);
+ if (enchantName == null || enchantName.isEmpty()) return null;
+ return enchantName.toUpperCase(Locale.ROOT) + ";" + enchantments.getInteger(enchantName);
+ }
+
+ private String resolveRuneName() {
+ NBTTagCompound runes = getExtraAttributes().getCompoundTag("runes");
+ String runeName = IteratorUtils.getOnlyElement(runes.getKeySet(), null);
+ if (runeName == null || runeName.isEmpty()) return null;
+ return runeName.toUpperCase(Locale.ROOT) + "_RUNE;" + runes.getInteger(runeName);
+ }
+
+ private String resolvePetName() {
+ String petInfo = getExtraAttributes().getString("petInfo");
+ if (petInfo == null || petInfo.isEmpty()) return null;
+ try {
+ JsonObject petInfoObject = manager.gson.fromJson(petInfo, JsonObject.class);
+ String petId = petInfoObject.get("type").getAsString();
+ String petTier = petInfoObject.get("tier").getAsString();
+ int rarityIndex = PET_RARITIES.indexOf(petTier);
+ return petId.toUpperCase(Locale.ROOT) + ";" + rarityIndex;
+ } catch (JsonParseException | ClassCastException ex) {
+ /* This happens if Hypixel changed the pet json format;
+ I still log this exception, since this case *is* exceptional and cannot easily be recovered from */
+ ex.printStackTrace();
+ return null;
+ }
+ }
+
+ private NBTTagCompound getExtraAttributes() {
+ if (compound == null) return new NBTTagCompound();
+ return compound.getCompoundTag(EXTRA_ATTRIBUTES);
+ }
+
+ private String resolveFromSkyblock() {
+ String internalName = getExtraAttributes().getString("id");
+ if (internalName == null || internalName.isEmpty()) return null;
+ return internalName.toUpperCase(Locale.ROOT).replace(':', '-');
+ }
+
+ // </editor-fold>
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java
new file mode 100644
index 00000000..8b81d1b4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ItemUtils.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.listener.ItemTooltipListener;
+import io.github.moulberry.notenoughupdates.miscfeatures.PetInfoOverlay;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.JsonToNBT;
+import net.minecraft.nbt.NBTException;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
+
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+public class ItemUtils {
+
+ public static ItemStack getCoinItemStack(long coinAmount) {
+ String uuid = "2070f6cb-f5db-367a-acd0-64d39a7e5d1b";
+ String texture =
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM4MDcxNzIxY2M1YjRjZDQwNmNlNDMxYTEzZjg2MDgzYTg5NzNlMTA2NGQyZjg4OTc4Njk5MzBlZTZlNTIzNyJ9fX0=";
+ if (coinAmount >= 100000) {
+ uuid = "94fa2455-2881-31fe-bb4e-e3e24d58dbe3";
+ texture =
+ "eyJ0aW1lc3RhbXAiOjE2MzU5NTczOTM4MDMsInByb2ZpbGVJZCI6ImJiN2NjYTcxMDQzNDQ0MTI4ZDMwODllMTNiZGZhYjU5IiwicHJvZmlsZU5hbWUiOiJsYXVyZW5jaW8zMDMiLCJzaWduYXR1cmVSZXF1aXJlZCI6dHJ1ZSwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2M5Yjc3OTk5ZmVkM2EyNzU4YmZlYWYwNzkzZTUyMjgzODE3YmVhNjQwNDRiZjQzZWYyOTQzM2Y5NTRiYjUyZjYiLCJtZXRhZGF0YSI6eyJtb2RlbCI6InNsaW0ifX19fQo=";
+ }
+ if (coinAmount >= 10000000) {
+ uuid = "0af8df1f-098c-3b72-ac6b-65d65fd0b668";
+ texture =
+ "ewogICJ0aW1lc3RhbXAiIDogMTYzNTk1NzQ4ODQxNywKICAicHJvZmlsZUlkIiA6ICJmNThkZWJkNTlmNTA0MjIyOGY2MDIyMjExZDRjMTQwYyIsCiAgInByb2ZpbGVOYW1lIiA6ICJ1bnZlbnRpdmV0YWxlbnQiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvN2I5NTFmZWQ2YTdiMmNiYzIwMzY5MTZkZWM3YTQ2YzRhNTY0ODE1NjRkMTRmOTQ1YjZlYmMwMzM4Mjc2NmQzYiIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9";
+ }
+ ItemStack skull = Utils.createSkull(
+ "\u00A7r\u00A76" + NumberFormat.getInstance(Locale.US).format(coinAmount) + " Coins",
+ uuid,
+ texture
+ );
+ NBTTagCompound extraAttributes = skull.getTagCompound().getCompoundTag("ExtraAttributes");
+ extraAttributes.setString("id", "SKYBLOCK_COIN");
+ skull.getTagCompound().setTag("ExtraAttributes", extraAttributes);
+ return skull;
+ }
+
+ public static ItemStack createQuestionMarkSkull(String label) {
+ return Utils.createSkull(
+ label,
+ "00000000-0000-0000-0000-000000000000",
+ "bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40"
+ );
+ }
+
+ public static NBTTagCompound getOrCreateTag(ItemStack is) {
+ if (is.hasTagCompound()) return is.getTagCompound();
+ NBTTagCompound nbtTagCompound = new NBTTagCompound();
+ is.setTagCompound(nbtTagCompound);
+ return nbtTagCompound;
+ }
+
+ public static void appendLore(ItemStack is, List<String> moreLore) {
+ NBTTagCompound tagCompound = is.getTagCompound();
+ if (tagCompound == null) {
+ tagCompound = new NBTTagCompound();
+ }
+ NBTTagCompound display = tagCompound.getCompoundTag("display");
+ NBTTagList lore = display.getTagList("Lore", 8);
+ for (String s : moreLore) {
+ lore.appendTag(new NBTTagString(s));
+ }
+ display.setTag("Lore", lore);
+ tagCompound.setTag("display", display);
+ is.setTagCompound(tagCompound);
+ }
+
+ public static List<String> getLore(ItemStack is) {
+ return getLore(is.getTagCompound());
+ }
+
+ public static List<String> getLore(NBTTagCompound tagCompound) {
+ if (tagCompound == null) {
+ return Collections.emptyList();
+ }
+ NBTTagList tagList = tagCompound.getCompoundTag("display").getTagList("Lore", 8);
+ List<String> list = new ArrayList<>();
+ for (int i = 0; i < tagList.tagCount(); i++) {
+ list.add(tagList.getStringTagAt(i));
+ }
+ return list;
+ }
+
+ public static String getDisplayName(NBTTagCompound compound) {
+ if (compound == null) return null;
+ String string = compound.getCompoundTag("display").getString("Name");
+ if (string == null || string.isEmpty())
+ return null;
+ return string;
+ }
+
+ public static String fixEnchantId(String enchId, boolean useId) {
+ if (Constants.ENCHANTS != null && Constants.ENCHANTS.has("enchant_mapping_id") &&
+ Constants.ENCHANTS.has("enchant_mapping_item")) {
+ JsonArray mappingFrom = Constants.ENCHANTS.getAsJsonArray("enchant_mapping_" + (useId ? "id" : "item"));
+ JsonArray mappingTo = Constants.ENCHANTS.getAsJsonArray("enchant_mapping_" + (useId ? "item" : "id"));
+
+ for (int i = 0; i < mappingFrom.size(); i++) {
+ if (mappingFrom.get(i).getAsString().equals(enchId)) {
+ return mappingTo.get(i).getAsString();
+ }
+ }
+
+ }
+ return enchId;
+ }
+
+ /**
+ * Mutates baseValues
+ */
+ public static <T> void modifyReplacement(
+ Map<String, String> baseValues,
+ Map<String, T> modifiers,
+ BiFunction<String, T, String> mapper
+ ) {
+ if (modifiers == null || baseValues == null) return;
+ for (Map.Entry<String, T> modifier : modifiers.entrySet()) {
+ String baseValue = baseValues.get(modifier.getKey());
+ if (baseValue == null) continue;
+ try {
+ baseValues.put(modifier.getKey(), mapper.apply(baseValue, modifier.getValue()));
+ } catch (Exception e) {
+ System.out.println("Exception during replacement mapping: ");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static String applyReplacements(Map<String, String> replacements, String text) {
+ for (Map.Entry<String, String> replacement : replacements.entrySet()) {
+ String search = "{" + replacement.getKey() + "}";
+ text = text.replace(search, replacement.getValue());
+ }
+ return text;
+ }
+
+ public static ItemStack createPetItemstackFromPetInfo(PetInfoOverlay.Pet currentPet) {
+ String petname = currentPet.petType;
+ String tier = Utils.getRarityFromInt(currentPet.rarity.petId).toUpperCase();
+ String heldItem = currentPet.petItem;
+ String skin = currentPet.skin;
+ JsonObject heldItemJson = heldItem == null ? null : NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(
+ heldItem);
+ String petId = currentPet.getPetId(false);
+ float exp = currentPet.petLevel.totalXp;
+
+ GuiProfileViewer.PetLevel levelObj = GuiProfileViewer.getPetLevel(petname, tier, exp);
+
+ float level = levelObj.level;
+
+ ItemStack petItemstack = NotEnoughUpdates.INSTANCE.manager
+ .createItemResolutionQuery()
+ .withKnownInternalName(petId)
+ .resolveToItemStack(false);
+ if (petItemstack == null) {
+ petItemstack = ItemUtils.createQuestionMarkSkull(EnumChatFormatting.RED + "Unknown Pet");
+ appendLore(petItemstack, Arrays.asList(
+ "§cThis pet is not saved in the repository",
+ "",
+ "§cIf you expected it to be there please send a message in",
+ "§c§l#neu-support §r§con §ldiscord.gg/moulberry"
+ ));
+ }
+ Map<String, String> replacements = NotEnoughUpdates.INSTANCE.manager.getPetLoreReplacements(
+ petname,
+ tier,
+ MathHelper.floor_float(level)
+ );
+
+ if (heldItem != null) {
+ modifyReplacement(replacements, GuiProfileViewer.PET_STAT_BOOSTS.get(heldItem), (original, modifier) ->
+ "" + MathHelper.floor_float(Float.parseFloat(original) + modifier));
+ modifyReplacement(replacements, GuiProfileViewer.PET_STAT_BOOSTS_MULT.get(heldItem), (original, modifier) ->
+ "" + MathHelper.floor_float(Float.parseFloat(original) * modifier));
+ }
+
+ NBTTagCompound tag = getOrCreateTag(petItemstack);
+ if (tag.hasKey("display", 10)) {
+ NBTTagCompound displayTag = tag.getCompoundTag("display");
+ if (displayTag.hasKey("Lore", 9)) {
+ List<String> newLore = new ArrayList<>();
+ NBTTagList lore = displayTag.getTagList("Lore", 8);
+ int secondLastBlankLine = -1, lastBlankLine = -1;
+ for (int j = 0; j < lore.tagCount(); j++) {
+ String line = lore.getStringTagAt(j);
+ if (line.trim().isEmpty()) {
+ secondLastBlankLine = lastBlankLine;
+ lastBlankLine = j;
+ }
+ line = applyReplacements(replacements, line);
+ newLore.add(line);
+ }
+ if (skin != null) {
+ JsonObject petSkin = NotEnoughUpdates.INSTANCE.manager
+ .createItemResolutionQuery()
+ .withKnownInternalName("PET_SKIN_" + skin)
+ .resolveToItemListJson();
+ if (petSkin != null) {
+ try {
+ NBTTagCompound nbt = JsonToNBT.getTagFromJson(petSkin.get("nbttag").getAsString());
+ tag.setTag("SkullOwner", nbt.getTag("SkullOwner"));
+ String name = petSkin.get("displayname").getAsString();
+ if (name != null) {
+ name = Utils.cleanColour(name);
+ newLore.set(0, newLore.get(0) + ", " + name);
+ }
+ } catch (NBTException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ for (int i = 0; i < newLore.size(); i++) {
+ String cleaned = Utils.cleanColour(newLore.get(i));
+ if (cleaned.equals("Right-click to add this pet to")) {
+ newLore.remove(i + 1);
+ newLore.remove(i);
+ secondLastBlankLine = i - 1;
+ break;
+ }
+ }
+ if (secondLastBlankLine != -1) {
+ List<String> petItemLore = new ArrayList<>();
+ if (heldItem != null) {
+ petItemLore.add(EnumChatFormatting.GOLD + "Held Item: " + heldItemJson.get("displayname").getAsString());
+ List<String> heldItemLore = JsonUtils.getJsonArrayOrEmpty(heldItemJson, "lore", JsonElement::getAsString);
+ int blanks = 0;
+ for (String heldItemLoreLine : heldItemLore) {
+ if (heldItemLoreLine.trim().isEmpty()) {
+ blanks++;
+ } else if (blanks == 2) {
+ petItemLore.add(heldItemLoreLine);
+ } else if (blanks > 2) {
+ break;
+ }
+ }
+ }
+ if (currentPet.candyUsed > 0) {
+ if (petItemLore.size() > 0) {
+ petItemLore.add("");
+ }
+ petItemLore.add("§a(" + currentPet.candyUsed + "/10) Pet Candy Used");
+ }
+ newLore.addAll(secondLastBlankLine + 1, petItemLore);
+ }
+ NBTTagList temp = new NBTTagList();
+ for (String loreLine : newLore) {
+ temp.appendTag(new NBTTagString(loreLine));
+ }
+ displayTag.setTag("Lore", temp);
+ }
+
+ if (displayTag.hasKey("Name", 8)) {
+ String displayName = displayTag.getString("Name");
+ displayName = applyReplacements(replacements, displayName);
+ displayTag.setTag("Name", new NBTTagString(displayName));
+ }
+ tag.setTag("display", displayTag);
+ }
+
+ // Adds the missing pet fields to the tag
+ NBTTagCompound extraAttributes = new NBTTagCompound();
+ JsonObject petInfo = new JsonObject();
+ if (tag.hasKey("ExtraAttributes", 10)) {
+ extraAttributes = tag.getCompoundTag("ExtraAttributes");
+ if (extraAttributes.hasKey("petInfo", 8)) {
+ petInfo = new JsonParser().parse(extraAttributes.getString("petInfo")).getAsJsonObject();
+ }
+ }
+ petInfo.addProperty("exp", exp);
+ petInfo.addProperty("tier", tier);
+ petInfo.addProperty("type", petname);
+ if (heldItem != null) {
+ petInfo.addProperty("heldItem", heldItem);
+ }
+ if (skin != null) {
+ petInfo.addProperty("skin", skin);
+ }
+ extraAttributes.setString("petInfo", petInfo.toString());
+ tag.setTag("ExtraAttributes", extraAttributes);
+ petItemstack.setTagCompound(tag);
+ return petItemstack;
+ }
+
+ private static final DecimalFormat decimalFormatter = new DecimalFormat("#,###,###.###");
+
+ public static ItemStack petToolTipXPExtendPetOverlay(ItemStack stack) {
+ NBTTagCompound tag = stack.getTagCompound() == null ? new NBTTagCompound() : stack.getTagCompound();
+ if (tag.hasKey("display", 10)) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList lore = display.getTagList("Lore", 8);
+ if (Utils.cleanColour(lore.getStringTagAt(0)).matches(ItemTooltipListener.petToolTipRegex) &&
+ lore.tagCount() > 7) {
+
+ GuiProfileViewer.PetLevel petLevel;
+
+ PetInfoOverlay.Pet pet = PetInfoOverlay.getPetFromStack(
+ stack.getTagCompound()
+ );
+ if (pet == null) return stack;
+ petLevel = pet.petLevel;
+ if (petLevel == null) return stack;
+
+ NBTTagList newLore = new NBTTagList();
+ int maxLvl = 100;
+ if (Constants.PETS != null && Constants.PETS.has("custom_pet_leveling") &&
+ Constants.PETS.getAsJsonObject("custom_pet_leveling").has(pet.petType.toUpperCase()) &&
+ Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(pet.petType.toUpperCase()).has(
+ "max_level")) {
+ maxLvl =
+ Constants.PETS
+ .getAsJsonObject("custom_pet_leveling")
+ .getAsJsonObject(pet.petType.toUpperCase())
+ .get("max_level")
+ .getAsInt();
+ }
+ for (int i = 0; i < lore.tagCount(); i++) {
+ if (i == lore.tagCount() - 2) {
+ newLore.appendTag(new NBTTagString(""));
+ if (petLevel.level >= maxLvl) {
+ newLore.appendTag(new NBTTagString(
+ EnumChatFormatting.AQUA + "" + EnumChatFormatting.BOLD + "MAX LEVEL"));
+ } else {
+ double levelPercent = (Math.round(petLevel.levelPercentage * 1000) / 10.0);
+ newLore.appendTag(new NBTTagString(
+ EnumChatFormatting.GRAY + "Progress to Level " + (int) (petLevel.level + 1) + ": " +
+ EnumChatFormatting.YELLOW + levelPercent + "%"));
+ StringBuilder sb = new StringBuilder();
+
+ for (int j = 0; j < 20; j++) {
+ if (j < (levelPercent / 5)) {
+ sb.append(EnumChatFormatting.DARK_GREEN);
+ } else {
+ sb.append(EnumChatFormatting.WHITE);
+ }
+ sb.append(EnumChatFormatting.BOLD + "" + EnumChatFormatting.STRIKETHROUGH + " ");
+ }
+ newLore.appendTag(new NBTTagString(sb.toString()));
+ newLore.appendTag(new NBTTagString(
+ EnumChatFormatting.GRAY + "EXP: " + EnumChatFormatting.YELLOW +
+ decimalFormatter.format(petLevel.levelXp) +
+ EnumChatFormatting.GOLD + "/" + EnumChatFormatting.YELLOW +
+ decimalFormatter.format(petLevel.currentLevelRequirement)
+ ));
+ }
+ }
+ newLore.appendTag(lore.get(i));
+ }
+ display.setTag("Lore", newLore);
+ tag.setTag("display", display);
+ }
+ }
+ }
+ stack.setTagCompound(tag);
+ return stack;
+ }
+
+ public static boolean isSoulbound(ItemStack item) {
+ return ItemUtils.getLore(item).stream()
+ .anyMatch(line -> line.equals("§8§l* §8Co-op Soulbound §8§l*") ||
+ line.equals("§8§l* Soulbound §8§l*"));
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/IteratorUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/IteratorUtils.java
new file mode 100644
index 00000000..32cd5fad
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/IteratorUtils.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import java.util.Iterator;
+
+public class IteratorUtils {
+
+ public static <T> T getOnlyElement(Iterator<T> it, T defaultValue) {
+ if (!it.hasNext()) return defaultValue;
+ T ret = it.next();
+ if (it.hasNext()) return defaultValue;
+ return ret;
+ }
+
+ public static <T> T getOnlyElement(Iterable<T> it, T defaultValue) {
+ return getOnlyElement(it.iterator(), defaultValue);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java
new file mode 100644
index 00000000..2e2977cc
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/JsonUtils.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+public class JsonUtils {
+ public static Stream<JsonElement> getJsonArrayAsStream(JsonArray array) {
+ return StreamSupport.stream(array.spliterator(), false);
+ }
+
+ public static <T> List<T> transformJsonArrayToList(
+ JsonArray array,
+ Function<? super JsonElement, ? extends T> mapper
+ ) {
+ return getJsonArrayAsStream(array).map(mapper).collect(Collectors.toList());
+ }
+
+ public static <T> List<T> getJsonArrayOrEmpty(
+ JsonObject rootObject,
+ String name,
+ Function<? super JsonElement, ? extends T> mapper
+ ) {
+ if (rootObject == null || !rootObject.has(name)) {
+ return Collections.emptyList();
+ }
+ JsonElement jsonElement = rootObject.get(name);
+ if (jsonElement.isJsonArray()) {
+ return transformJsonArrayToList(jsonElement.getAsJsonArray(), mapper);
+ }
+ return Collections.emptyList();
+ }
+
+ public static <T> JsonArray transformListToJsonArray(
+ List<T> things,
+ Function<? super T, ? extends JsonElement> mapper
+ ) {
+ JsonArray array = new JsonArray();
+ for (T t : things) {
+ array.add(mapper.apply(t));
+ }
+ return array;
+ }
+
+ public static <T> Map<String, T> transformJsonObjectToMap(
+ JsonObject object,
+ Function<? super JsonElement, ? extends T> mapper
+ ) {
+ Map<String, T> map = new HashMap<>();
+ for (Map.Entry<String, JsonElement> entry : object.entrySet()) {
+ map.put(entry.getKey(), mapper.apply(entry.getValue()));
+ }
+ return map;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/LerpingFloat.java b/src/main/java/io/github/moulberry/notenoughupdates/util/LerpingFloat.java
index a034fa8d..e2bfa711 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/LerpingFloat.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/LerpingFloat.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
public class LerpingFloat {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java b/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java
new file mode 100644
index 00000000..bf973b76
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/MinecraftExecutor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import net.minecraft.client.Minecraft;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.Executor;
+
+public class MinecraftExecutor implements Executor {
+
+ public static MinecraftExecutor INSTANCE = new MinecraftExecutor();
+
+ private MinecraftExecutor() {}
+
+ @Override
+ public void execute(@NotNull Runnable runnable) {
+ Minecraft.getMinecraft().addScheduledTask(runnable);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java b/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java
new file mode 100644
index 00000000..6510bc20
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/MoulSigner.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.X509EncodedKeySpec;
+
+public class MoulSigner {
+ private MoulSigner() {}
+
+ static PublicKey publicKey;
+
+ static {
+ try (InputStream is = MoulSigner.class.getResourceAsStream("/moulberry.key")) {
+ byte[] publicKeyBytes = IOUtils.toByteArray(is);
+ X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(publicKeyBytes);
+ publicKey = KeyFactory.getInstance("RSA").generatePublic(x509EncodedKeySpec);
+ } catch (IOException | NullPointerException | NoSuchAlgorithmException | InvalidKeySpecException e) {
+ NotEnoughUpdates.LOGGER.error("Cannot initialize MoulSigner", e);
+ }
+ }
+
+ public static boolean verifySignature(byte[] data, byte[] signatureBytes) {
+ if (Boolean.getBoolean("neu.noverifysignature")) return true;
+ if (publicKey == null) {
+ NotEnoughUpdates.LOGGER.warn("MoulSigner could not be initialized, will fail this request");
+ return false;
+ }
+ try {
+ Signature signature = Signature.getInstance("SHA256withRSA");
+ signature.initVerify(publicKey);
+ signature.update(data);
+ return signature.verify(signatureBytes);
+ } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
+ NotEnoughUpdates.LOGGER.error("Error while verifying signature. Considering this as invalid signature", e);
+ return false;
+ }
+ }
+
+ public static boolean verifySignature(File file) {
+ try {
+ return verifySignature(
+ IOUtils.toByteArray(file.toURI()),
+ IOUtils.toByteArray(new File(file.getParentFile(), file.getName() + ".asc").toURI())
+ );
+ } catch (IOException e) {
+ NotEnoughUpdates.LOGGER.error("Ran into an IOException while verifying a signature", e);
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java
new file mode 100644
index 00000000..230b8ae5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUDebugLogger.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.options.customtypes.NEUDebugFlag;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.util.function.Consumer;
+
+public class NEUDebugLogger {
+ private static final Minecraft mc = Minecraft.getMinecraft();
+ public static Consumer<String> logMethod = NEUDebugLogger::chatLogger;
+ // Used to prevent accessing NEUConfig in unit tests
+ public static boolean allFlagsEnabled = false;
+
+ private static void chatLogger(String message) {
+ mc.thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU DEBUG] " + message));
+ }
+
+ public static boolean isFlagEnabled(NEUDebugFlag flag) {
+ return NotEnoughUpdates.INSTANCE.config.hidden.debugFlags.contains(flag);
+ }
+
+ public static void log(NEUDebugFlag flag, String message) {
+ if (logMethod != null && (allFlagsEnabled || isFlagEnabled(flag))) {
+ logAlways(message);
+ }
+ }
+
+ public static void logAlways(String message) {
+ if (logMethod != null) {
+ logMethod.accept(message);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUResourceManager.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUResourceManager.java
index 3ef40567..af681f2d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/NEUResourceManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NEUResourceManager.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import net.minecraft.client.resources.IResource;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java
new file mode 100644
index 00000000..b09dd839
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NetUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import org.apache.commons.io.IOUtils;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+
+public class NetUtils {
+
+ public static CompletableFuture<File> downloadAsync(URL httpURL, File outputFile) {
+ return CompletableFuture.supplyAsync(() -> {
+ try {
+ try (
+ InputStream from = httpURL.openStream();
+ OutputStream to = Files.newOutputStream(outputFile.toPath());
+ ) {
+ IOUtils.copyLarge(from, to);
+ }
+ return outputFile;
+ } catch (IOException e) {
+ throw new CompletionException(e);
+ }
+ });
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java b/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java
new file mode 100644
index 00000000..d373ef2c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/NotificationHandler.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.inventory.ContainerChest;
+
+import java.util.List;
+
+public class NotificationHandler {
+ public static List<String> notificationLines = null;
+ public static boolean showNotificationOverInv = false;
+ public static long notificationDisplayMillis = 0;
+
+ public static void displayNotification(List<String> lines, boolean showForever) {
+ displayNotification(lines, showForever, false);
+ }
+
+ public static void displayNotification(List<String> lines, boolean showForever, boolean overInventory) {
+ if (showForever) {
+ notificationDisplayMillis = -420;
+ } else {
+ notificationDisplayMillis = System.currentTimeMillis();
+ }
+ notificationLines = lines;
+ showNotificationOverInv = overInventory;
+ }
+
+ /**
+ * Stops rendering the notification, if one is displayed
+ */
+ public static void cancelNotification() {
+ notificationDisplayMillis = 0;
+ }
+
+ public static void renderNotification() {
+ long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis);
+ boolean display = timeRemaining > 0 || notificationDisplayMillis == -420;
+ if (display && notificationLines != null && notificationLines.size() > 0) {
+ int width = 0;
+ int height = notificationLines.size() * 10 + 10;
+
+ for (String line : notificationLines) {
+ int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8;
+ if (len > width) {
+ width = len;
+ }
+ }
+
+ ScaledResolution sr = Utils.pushGuiScale(2);
+
+ int midX = sr.getScaledWidth() / 2;
+ int topY = sr.getScaledHeight() * 3 / 4 - height / 2;
+ RenderUtils.drawFloatingRectDark(midX - width / 2, sr.getScaledHeight() * 3 / 4 - height / 2, width, height);
+ /*Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2,
+ midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C);
+ Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2,
+ midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);*/
+
+ int xLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth("[X] Close");
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ "[X] Close",
+ midX + width / 2f - 3 - xLen,
+ topY + 3,
+ 0xFFFF5555,
+ false
+ );
+
+ if (notificationDisplayMillis > 0) {
+ Minecraft.getMinecraft().fontRendererObj.drawString(
+ (timeRemaining / 1000) + "s",
+ midX - width / 2f + 3,
+ topY + 3,
+ 0xFFaaaaaa,
+ false
+ );
+ }
+
+ Utils.drawStringCentered(
+ notificationLines.get(0),
+ Minecraft.getMinecraft().fontRendererObj,
+ midX,
+ topY + 4 + 5,
+ false,
+ -1
+ );
+ for (int i = 1; i < notificationLines.size(); i++) {
+ String line = notificationLines.get(i);
+ Utils.drawStringCentered(
+ line,
+ Minecraft.getMinecraft().fontRendererObj,
+ midX,
+ topY + 4 + 5 + 2 + i * 10,
+ false,
+ -1
+ );
+ }
+
+ Utils.pushGuiScale(-1);
+ }
+ }
+
+ public static boolean shouldRenderOverlay(Gui gui) {
+ boolean validGui = gui instanceof GuiContainer || gui instanceof GuiItemRecipe;
+ if (gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if (containerName.trim().equals("Fast Travel")) {
+ validGui = false;
+ }
+ }
+ return validGui;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
index 439ad571..b90e8087 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ProfileApiSyncer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java b/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java
new file mode 100644
index 00000000..4c0b73eb
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/PronounDB.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+public class PronounDB {
+
+ private static boolean isDisabled() {
+ JsonObject disabled = Constants.DISABLE;
+ return disabled != null && disabled.has("pronoundb");
+ }
+
+ /**
+ * Returns an Optional, since JVMs can be *very* funky with KeyStore loading
+ */
+ public static CompletableFuture<Optional<JsonObject>> performPronouning(String platform, String id) {
+ if (isDisabled()) return CompletableFuture.completedFuture(Optional.empty());
+ return NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .request()
+ .url("https://pronoundb.org/api/v1/lookup")
+ .queryArgument("platform", platform)
+ .queryArgument("id", id)
+ .requestJson()
+ .handle((result, ex) -> Optional.ofNullable(result));
+ }
+
+ public enum Pronoun {
+ HE("he", "him", "his"),
+ IT("it", "it", "its"),
+ SHE("she", "her", "hers"),
+ THEY("they", "them", "theirs");
+
+ private final String subject;
+ private final String object;
+ private final String possessive;
+
+ Pronoun(String subject, String object, String possessive) {
+ this.subject = subject;
+ this.object = object;
+ this.possessive = possessive;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public String getObject() {
+ return object;
+ }
+
+ public String getPossessive() {
+ return possessive;
+ }
+ }
+
+ public enum PronounChoice {
+ UNSPECIFIED("unspecified", "Unspecified"),
+ HE("hh", Pronoun.HE),
+ HEIT("hi", Pronoun.HE, Pronoun.IT),
+ HESHE("hs", Pronoun.HE, Pronoun.SHE),
+ HETHEY("ht", Pronoun.HE, Pronoun.THEY),
+ ITHE("ih", Pronoun.IT, Pronoun.HE),
+ IT("ii", Pronoun.IT),
+ ITSHE("is", Pronoun.IT, Pronoun.SHE),
+ ITTHEY("it", Pronoun.IT, Pronoun.THEY),
+ SHEHE("shh", Pronoun.SHE, Pronoun.HE),
+ SHE("sh", Pronoun.SHE),
+ SHEIT("si", Pronoun.SHE, Pronoun.IT),
+ SHETHEY("st", Pronoun.SHE, Pronoun.THEY),
+ THEYHE("th", Pronoun.THEY, Pronoun.HE),
+ THEYIT("ti", Pronoun.THEY, Pronoun.IT),
+ THEYSHE("ts", Pronoun.THEY, Pronoun.SHE),
+ THEY("tt", Pronoun.THEY),
+ ANY("any", "Any pronouns"),
+ OTHER("other", "Other pronouns"),
+ ASK("ask", "Ask me my pronouns"),
+ AVOID("avoid", "Avoid pronouns, use my name");
+ private final String id;
+ private List<Pronoun> pronouns = null;
+ private String override = null;
+
+ PronounChoice(String id, String override) {
+ this.override = override;
+ this.id = id;
+ }
+
+ PronounChoice(String id, Pronoun... pronouns) {
+ this.id = id;
+ this.pronouns = Arrays.asList(pronouns);
+ }
+
+ public static Optional<PronounChoice> findPronounsForId(String id) {
+ for (PronounChoice value : values()) {
+ if (value.id.equals(id)) return Optional.of(value);
+ }
+ return Optional.empty();
+ }
+
+ public String getOverride() {
+ return override;
+ }
+
+ public List<Pronoun> getPronounsInPreferredOrder() {
+ return pronouns;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public List<String> render() {
+ if (override != null)
+ return Arrays.asList(override);
+ return pronouns
+ .stream()
+ .map(pronoun -> pronoun.getSubject() + "/" + pronoun.getObject())
+ .collect(Collectors.toList());
+ }
+
+ public boolean isConsciousChoice() {
+ return this != UNSPECIFIED;
+ }
+
+ }
+
+ public static Optional<PronounChoice> parsePronouns(JsonObject pronounObject) {
+ if (pronounObject.has("pronouns")) {
+ JsonElement pronouns = pronounObject.get("pronouns");
+ if (pronouns.isJsonPrimitive() && pronouns.getAsJsonPrimitive().isString())
+ return PronounChoice.findPronounsForId(pronouns.getAsString());
+ }
+ return Optional.empty();
+ }
+
+ public static CompletableFuture<Optional<PronounChoice>> getPronounsFor(String platform, String name) {
+ return performPronouning(platform, name).thenApply(it -> it.flatMap(PronounDB::parsePronouns));
+ }
+
+ public static CompletableFuture<Optional<PronounChoice>> getPronounsFor(UUID minecraftPlayer) {
+ return getPronounsFor("minecraft", minecraftPlayer.toString() /* dashed UUID */);
+ }
+
+ public static void test() {
+ System.out.println("Pronouning...");
+ getPronounsFor(UUID.fromString("842204e6-6880-487b-ae5a-0595394f9948")).thenAccept(it -> {
+ PronounChoice pronounsFor = it.get();
+ pronounsFor.render().forEach(System.out::println);
+ });
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/RequestFocusListener.java b/src/main/java/io/github/moulberry/notenoughupdates/util/RequestFocusListener.java
index 3df5d9f1..092c8564 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/RequestFocusListener.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/RequestFocusListener.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import javax.swing.*;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java
index c517bd08..634c94b6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.common.primitives.Floats;
@@ -9,10 +28,13 @@ import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.apache.logging.log4j.LogManager;
-import java.nio.*;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
import java.util.Arrays;
import java.util.BitSet;
-import java.util.Comparator;
@SideOnly(Side.CLIENT)
public class ReverseWorldRenderer {
@@ -564,4 +586,4 @@ public class ReverseWorldRenderer {
return this.stateVertexFormat;
}
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
index 4bf1d6aa..f3a09fcc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
@@ -1,12 +1,31 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.common.reflect.TypeToken;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.listener.ScoreboardLocationChangeListener;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.init.Blocks;
@@ -18,6 +37,8 @@ import net.minecraft.scoreboard.Score;
import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.ScorePlayerTeam;
import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.GuiOpenEvent;
@@ -34,7 +55,12 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -57,15 +83,23 @@ public class SBInfo {
public String slayer = "";
public boolean stranded = false;
- public String mode = "";
+ public String mode = null;
public Date currentTimeDate = null;
- public String lastOpenContainerName = "";
+ private JsonObject mayorJson = new JsonObject();
+
+ /**
+ * Use Utils.getOpenChestName() instead
+ */
+ @Deprecated
+ public String currentlyOpenChestName = "";
+ public String lastOpenChestName = "";
private long lastManualLocRaw = -1;
private long lastLocRaw = -1;
public long joinedWorld = -1;
+ private long lastMayorUpdate;
public long unloadedWorld = -1;
private JsonObject locraw = null;
public boolean isInDungeon = false;
@@ -96,7 +130,8 @@ public class SBInfo {
private int tickCount = 0;
public String currentProfile = null;
- @SubscribeEvent
+ //Set the priority HIGH to allow other GuiOpenEvent's to use the new currentlyOpenChestName data
+ @SubscribeEvent(priority = EventPriority.HIGH)
public void onGuiOpen(GuiOpenEvent event) {
if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
@@ -104,22 +139,32 @@ public class SBInfo {
GuiChest chest = (GuiChest) event.gui;
ContainerChest container = (ContainerChest) chest.inventorySlots;
- lastOpenContainerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
+ currentlyOpenChestName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
+ lastOpenChestName = currentlyOpenChestName;
+ } else {
+ currentlyOpenChestName = "";
}
}
@SubscribeEvent
public void onGuiTick(TickEvent event) {
if (tickCount++ % 10 != 0) return;
- GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
- if (currentScreen instanceof GuiChest) {
- ContainerChest container = (ContainerChest) ((GuiChest) currentScreen).inventorySlots;
- if ("Profile Management".equals(container.getLowerChestInventory().getDisplayName().getUnformattedText())) {
- updateProfileInformation(container);
- }
+ if (Utils.getOpenChestName().equals("Profile Management")) {
+ ContainerChest container = (ContainerChest) ((GuiChest) Minecraft.getMinecraft().currentScreen).inventorySlots;
+ updateProfileInformation(container);
}
}
+ public boolean checkForSkyblockLocation() {
+ if (!NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() || getLocation() == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "[NEU] This command is not available outside SkyBlock"));
+ return false;
+ }
+
+ return true;
+ }
+
private static final Pattern PROFILE_PATTERN =
Pattern.compile("(?<type>(♲ Ironman)|(☀ Stranded)|()) *Profile: (?<name>[^ ]+)");
@@ -189,7 +234,8 @@ public class SBInfo {
locraw = null;
this.setLocation(null);
joinedWorld = System.currentTimeMillis();
- lastOpenContainerName = "";
+ currentlyOpenChestName = "";
+ lastOpenChestName = "";
hasNewTab = false;
}
@@ -254,7 +300,10 @@ public class SBInfo {
lastLocRaw = System.currentTimeMillis();
NotEnoughUpdates.INSTANCE.sendChatMessage("/locraw");
}
-
+ if (currentTime - lastMayorUpdate > 300 * 1000) {
+ updateMayor();
+ lastMayorUpdate = currentTime;
+ }
try {
for (NetworkPlayerInfo info : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) {
String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info);
@@ -293,7 +342,7 @@ public class SBInfo {
String cleanLine = Utils.cleanColour(line);
- if (cleanLine.contains("Dungeon") && cleanLine.contains("Cleared:") && cleanLine.contains("%")) {
+ if (cleanLine.contains("Cleared:") && cleanLine.contains("%")) {
tempIsInDungeon = true;
}
@@ -311,6 +360,8 @@ public class SBInfo {
slayer = "Sven";
} else if (line.contains("Voidgloom Seraph")) {
slayer = "Enderman";
+ } else if (line.contains("Inferno Demonlord")) {
+ slayer = "Blaze";
}
if (lines.contains("Slayer Quest") && SlayerOverlay.unloadOverlayTimer == -1 ||
lines.contains("Slayer Quest") && System.currentTimeMillis() - SlayerOverlay.unloadOverlayTimer > 500) {
@@ -353,7 +404,11 @@ public class SBInfo {
//Replaced with for loop because in crystal hollows with events the line it's on can shift.
for (String line : lines) {
if (line.contains("⏣")) {
- location = Utils.cleanColour(line).replaceAll("[^A-Za-z0-9() ]", "").trim();
+ String l = Utils.cleanColour(line).replaceAll("[^A-Za-z0-9() ]", "").trim();
+ if (!l.equals(location)) {
+ new ScoreboardLocationChangeListener(location, l);
+ }
+ location = l;
break;
}
}
@@ -372,4 +427,16 @@ public class SBInfo {
e.printStackTrace();
}
}
+
+ public void updateMayor() {
+ NotEnoughUpdates.INSTANCE.manager.apiUtils
+ .newHypixelApiRequest("resources/skyblock/election")
+ .requestJson()
+ .thenAccept(newJson -> mayorJson = newJson);
+ }
+
+
+ public JsonObject getMayorJson() {
+ return mayorJson;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SkytilsCompat.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SkytilsCompat.java
new file mode 100644
index 00000000..f0cb5732
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SkytilsCompat.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.util;
+
+import net.minecraft.item.ItemStack;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+public class SkytilsCompat {
+ // Defer static initialization
+ private static class Holder {
+ // Skytils is present in some capacity
+ static boolean isSkytilsPresent = false;
+ // All classes successfully loaded
+ static boolean isSkytilsFullyPresent = false;
+
+ static Class<?> skytilsClass = null;
+ static Method renderRarityMethod = null;
+ static Class<?> renderUtilClass = null;
+
+ static Object skytilsCompanionObject = null;
+
+ static Class<?> skytilsConfigClass = null;
+
+ static Object skytilsConfigObject = null;
+ static Method skytilsGetShowItemRarity = null;
+
+ static {
+ Exception exception = null;
+ for (String packageStart : Arrays.asList("gg.skytils", "skytils")) {
+ isSkytilsPresent = false;
+ try {
+ skytilsClass = Class.forName(packageStart + ".skytilsmod.Skytils");
+ isSkytilsPresent = true;
+ } catch (ClassNotFoundException ignored) {
+ }
+
+ if (isSkytilsPresent) {
+ try {
+ Class<?> skytilsCompanionClass = Class.forName(packageStart + ".skytilsmod.Skytils$Companion");
+ skytilsConfigClass = Class.forName(packageStart + ".skytilsmod.core.Config");
+ Field skytilsCompanionField = skytilsClass.getField("Companion");
+ skytilsCompanionObject = skytilsCompanionField.get(null);
+ Method skytilsGetConfigMethod = skytilsCompanionClass.getMethod("getConfig");
+ skytilsConfigObject = skytilsGetConfigMethod.invoke(skytilsCompanionObject);
+ skytilsGetShowItemRarity = skytilsConfigClass.getMethod("getShowItemRarity");
+ renderUtilClass = Class.forName(packageStart + ".skytilsmod.utils.RenderUtil");
+ renderRarityMethod = renderUtilClass.getDeclaredMethod(
+ "renderRarity",
+ ItemStack.class,
+ Integer.TYPE,
+ Integer.TYPE
+ );
+ isSkytilsFullyPresent = true;
+ break;
+ } catch (ClassNotFoundException | NoSuchMethodException | NoSuchFieldException | IllegalAccessException |
+ InvocationTargetException e) {
+ exception = e;
+ }
+ }
+ }
+
+ if (!isSkytilsFullyPresent) {
+ if (exception != null) {
+ System.err.println("Failed to get Skytils class even tho Skytils mod is present. This is (probably) a NEU bug");
+ exception.printStackTrace();
+ }
+ }
+ }
+ }
+
+ public static boolean isSkytilsFullyLoaded() {
+ return Holder.isSkytilsFullyPresent;
+ }
+
+ public static boolean isSkytilsPresent() {
+ return Holder.isSkytilsPresent;
+ }
+
+ public static void renderSkytilsRarity(ItemStack stack, int x, int y) {
+ renderSkytilsRarity(stack, x, y, false);
+ }
+
+ public static void renderSkytilsRarity(ItemStack stack, int x, int y, boolean force) {
+ if (Holder.isSkytilsFullyPresent) {
+ try {
+ if (force || (boolean) Holder.skytilsGetShowItemRarity.invoke(Holder.skytilsConfigObject))
+ Holder.renderRarityMethod.invoke(null, stack, x, y);
+ } catch (IllegalAccessException | InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java
index 27a40565..e3318e3c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import java.awt.*;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
index b38db88f..bcce86bb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
@@ -1,3 +1,22 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import org.lwjgl.input.Keyboard;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
index 9b5f62e3..2267cbea 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
@@ -1,10 +1,34 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
-import com.google.gson.*;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonPrimitive;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking;
+import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.entity.EntityPlayerSP;
@@ -30,35 +54,98 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
import net.minecraft.network.play.client.C0DPacketCloseWindow;
-import net.minecraft.util.*;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatStyle;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.Matrix4f;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.StatCollector;
import net.minecraftforge.fml.common.Loader;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
-import java.awt.Color;
+import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
+import java.math.BigInteger;
import java.nio.FloatBuffer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
- public static boolean hasEffectOverride = false;
- public static boolean disableCustomDungColours = false;
private static final LinkedList<Integer> guiScales = new LinkedList<>();
- private static ScaledResolution lastScale = new ScaledResolution(Minecraft.getMinecraft());
//Labymod compatibility
private static final FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16);
private static final FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16);
+ private static final EnumChatFormatting[] rainbow = new EnumChatFormatting[]{
+ EnumChatFormatting.RED,
+ EnumChatFormatting.GOLD,
+ EnumChatFormatting.YELLOW,
+ EnumChatFormatting.GREEN,
+ EnumChatFormatting.AQUA,
+ EnumChatFormatting.LIGHT_PURPLE,
+ EnumChatFormatting.DARK_PURPLE
+ };
+ private static final Pattern CHROMA_REPLACE_PATTERN = Pattern.compile("\u00a7z(.+?)(?=\u00a7|$)");
+ private static final char[] c = new char[]{'k', 'm', 'b', 't'};
+ private static final LerpingFloat scrollY = new LerpingFloat(0, 100);
+ public static boolean hasEffectOverride = false;
+ public static boolean disableCustomDungColours = false;
+ public static String[] rarityArr = new String[]{
+ "COMMON",
+ "UNCOMMON",
+ "RARE",
+ "EPIC",
+ "LEGENDARY",
+ "MYTHIC",
+ "SPECIAL",
+ "VERY SPECIAL",
+ "SUPREME",
+ "^^ THAT ONE IS DIVINE ^^"
+//, "DIVINE"
+ };
+ public static String[] rarityArrC = new String[]{
+ EnumChatFormatting.WHITE + EnumChatFormatting.BOLD.toString() + "COMMON",
+ EnumChatFormatting.GREEN + EnumChatFormatting.BOLD.toString() + "UNCOMMON",
+ EnumChatFormatting.BLUE + EnumChatFormatting.BOLD.toString() + "RARE",
+ EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD.toString() + "EPIC",
+ EnumChatFormatting.GOLD + EnumChatFormatting.BOLD.toString() + "LEGENDARY",
+ EnumChatFormatting.LIGHT_PURPLE + EnumChatFormatting.BOLD.toString() + "MYTHIC",
+ EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "SPECIAL",
+ EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "VERY SPECIAL",
+ EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE",
+ EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE",
+ //EnumChatFormatting.AQUA+EnumChatFormatting.BOLD.toString()+"DIVINE",
+ };
+ public static final HashMap<String, String> rarityArrMap = new HashMap<String, String>() {{
+ put("COMMON", rarityArrC[0]);
+ put("UNCOMMON", rarityArrC[1]);
+ put("RARE", rarityArrC[2]);
+ put("EPIC", rarityArrC[3]);
+ put("LEGENDARY", rarityArrC[4]);
+ put("MYTHIC", rarityArrC[5]);
+ put("SPECIAL", rarityArrC[6]);
+ put("VERY SPECIAL", rarityArrC[7]);
+ put("DIVINE", rarityArrC[8]);
+ // put("DIVINE", rarityArrC[9]);
+ }};
+ public static Splitter PATH_SPLITTER = Splitter.on(".").omitEmptyStrings().limit(2);
+ private static ScaledResolution lastScale = new ScaledResolution(Minecraft.getMinecraft());
+ private static long startTime = 0;
public static <T> ArrayList<T> createList(T... values) {
ArrayList<T> list = new ArrayList<>();
@@ -162,8 +249,13 @@ public class Utils {
}
public static void drawItemStackWithText(ItemStack stack, int x, int y, String text) {
- if (stack == null) return;
+ drawItemStackWithText(stack, x, y, text, false);
+ }
+ public static void drawItemStackWithText(ItemStack stack, int x, int y, String text, boolean skytilsRarity) {
+ if (stack == null) return;
+ if (skytilsRarity)
+ SkytilsCompat.renderSkytilsRarity(stack, x, y);
RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
disableCustomDungColours = true;
@@ -177,27 +269,17 @@ public class Utils {
}
public static void drawItemStack(ItemStack stack, int x, int y) {
- if (stack == null) return;
-
drawItemStackWithText(stack, x, y, null);
}
- private static final EnumChatFormatting[] rainbow = new EnumChatFormatting[]{
- EnumChatFormatting.RED,
- EnumChatFormatting.GOLD,
- EnumChatFormatting.YELLOW,
- EnumChatFormatting.GREEN,
- EnumChatFormatting.AQUA,
- EnumChatFormatting.LIGHT_PURPLE,
- EnumChatFormatting.DARK_PURPLE
- };
+ public static void drawItemStack(ItemStack stack, int x, int y, boolean skytilsRarity) {
+ drawItemStackWithText(stack, x, y, null, skytilsRarity);
+ }
public static String chromaString(String str) {
return chromaString(str, 0, false);
}
- private static final Pattern CHROMA_REPLACE_PATTERN = Pattern.compile("\u00a7z(.+?)(?=\u00a7|$)");
-
public static String chromaStringByColourCode(String str) {
if (str.contains("\u00a7z")) {
Matcher matcher = CHROMA_REPLACE_PATTERN.matcher(str);
@@ -219,8 +301,6 @@ public class Utils {
return str;
}
- private static long startTime = 0;
-
public static String chromaString(String str, float offset, boolean bold) {
str = cleanColour(str);
@@ -247,8 +327,6 @@ public class Utils {
return rainbowText.toString();
}
- private static final char[] c = new char[]{'k', 'm', 'b', 't'};
-
public static String shortNumberFormat(double n, int iteration) {
double d = ((long) n / 100) / 10.0;
boolean isRound = (d * 10) % 10 == 0;
@@ -301,6 +379,40 @@ public class Utils {
return "";
}
+ public static String trimWhitespaceAndFormatCodes(String str) {
+ int startIndex = indexOfFirstNonWhitespaceNonFormatCode(str);
+ int endIndex = lastIndexOfNonWhitespaceNonFormatCode(str);
+ if (startIndex == -1 || endIndex == -1) return "";
+ return str.substring(startIndex, endIndex + 1);
+ }
+
+ private static int indexOfFirstNonWhitespaceNonFormatCode(String str) {
+ int len = str.length();
+ for (int i = 0; i < len; i++) {
+ char ch = str.charAt(i);
+ if (Character.isWhitespace(ch)) {
+ continue;
+ } else if (ch == '\u00a7') {
+ i++;
+ continue;
+ }
+ return i;
+ }
+ return -1;
+ }
+
+ private static int lastIndexOfNonWhitespaceNonFormatCode(String str) {
+ for (int i = str.length() - 1; i >= 0; i--) {
+ char ch = str.charAt(i);
+ if (Character.isWhitespace(ch) || ch == '\u00a7' || (i > 0 && str.charAt(i - 1) == '\u00a7')) {
+ continue;
+ }
+ return i;
+ }
+
+ return -1;
+ }
+
public static List<String> getRawTooltip(ItemStack stack) {
List<String> list = Lists.newArrayList();
String s = stack.getDisplayName();
@@ -477,46 +589,6 @@ public class Utils {
return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
}
- public static String[] rarityArr = new String[]{
- "COMMON",
- "UNCOMMON",
- "RARE",
- "EPIC",
- "LEGENDARY",
- "MYTHIC",
- "SPECIAL",
- "VERY SPECIAL",
- "SUPREME",
- "^^ THAT ONE IS DIVINE ^^"
-//, "DIVINE"
- };
-
- public static String[] rarityArrC = new String[]{
- EnumChatFormatting.WHITE + EnumChatFormatting.BOLD.toString() + "COMMON",
- EnumChatFormatting.GREEN + EnumChatFormatting.BOLD.toString() + "UNCOMMON",
- EnumChatFormatting.BLUE + EnumChatFormatting.BOLD.toString() + "RARE",
- EnumChatFormatting.DARK_PURPLE + EnumChatFormatting.BOLD.toString() + "EPIC",
- EnumChatFormatting.GOLD + EnumChatFormatting.BOLD.toString() + "LEGENDARY",
- EnumChatFormatting.LIGHT_PURPLE + EnumChatFormatting.BOLD.toString() + "MYTHIC",
- EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "SPECIAL",
- EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "VERY SPECIAL",
- EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE",
- EnumChatFormatting.AQUA + EnumChatFormatting.BOLD.toString() + "DIVINE",
- //EnumChatFormatting.AQUA+EnumChatFormatting.BOLD.toString()+"DIVINE",
- };
- public static final HashMap<String, String> rarityArrMap = new HashMap<String, String>() {{
- put("COMMON", rarityArrC[0]);
- put("UNCOMMON", rarityArrC[1]);
- put("RARE", rarityArrC[2]);
- put("EPIC", rarityArrC[3]);
- put("LEGENDARY", rarityArrC[4]);
- put("MYTHIC", rarityArrC[5]);
- put("SPECIAL", rarityArrC[6]);
- put("VERY SPECIAL", rarityArrC[7]);
- put("DIVINE", rarityArrC[8]);
- // put("DIVINE", rarityArrC[9]);
- }};
-
public static String getRarityFromInt(int rarity) {
if (rarity < 0 || rarity >= rarityArr.length) {
return rarityArr[0];
@@ -598,6 +670,60 @@ public class Utils {
return (float) Math.round(value * scale) / scale;
}
+ public static int roundToNearestInt(double value) {
+ return (int) Math.round(value);
+ }
+
+ // Parses Roman numerals, allowing for single character irregular subtractive notation (e.g. IL is 49, IIL is invalid)
+ public static int parseRomanNumeral(String input) {
+ int prevVal = 0;
+ int total = 0;
+ for (int i = input.length() - 1; i >= 0; i--) {
+ int val;
+ char ch = input.charAt(i);
+ switch (ch) {
+ case 'I':
+ val = 1;
+ break;
+ case 'V':
+ val = 5;
+ break;
+ case 'X':
+ val = 10;
+ break;
+ case 'L':
+ val = 50;
+ break;
+ case 'C':
+ val = 100;
+ break;
+ case 'D':
+ val = 500;
+ break;
+ case 'M':
+ val = 1000;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid Roman Numeral Character: " + ch);
+ }
+ if (val < prevVal) val = -val;
+ total += val;
+ prevVal = val;
+ }
+
+ return total;
+ }
+
+ public static int parseIntOrRomanNumeral(String input) {
+ // 0 through 9, '-', and '+' come before 'A' in ANSI, UTF8, and UTF16 character sets
+ //
+ if (input.charAt(0) < 'A') {
+ return Integer.parseInt(input);
+ }
+
+ return parseRomanNumeral(input);
+ }
+
public static void playPressSound() {
playSound(new ResourceLocation("gui.button.press"), true);
}
@@ -717,11 +843,15 @@ public class Utils {
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
}
- public static ItemStack createItemStack(Item item, String displayname, String... lore) {
- return createItemStack(item, displayname, 0, lore);
+ public static ItemStack createItemStack(Item item, String displayName, String... lore) {
+ return createItemStack(item, displayName, 0, lore);
+ }
+
+ public static ItemStack createItemStack(Block item, String displayName, String... lore) {
+ return createItemStack(Item.getItemFromBlock(item), displayName, lore);
}
- public static ItemStack createItemStack(Item item, String displayname, int damage, String... lore) {
+ public static ItemStack createItemStack(Item item, String displayName, int damage, String... lore) {
ItemStack stack = new ItemStack(item, 1, damage);
NBTTagCompound tag = new NBTTagCompound();
NBTTagCompound display = new NBTTagCompound();
@@ -731,7 +861,7 @@ public class Utils {
Lore.appendTag(new NBTTagString(line));
}
- display.setString("Name", displayname);
+ display.setString("Name", displayName);
display.setTag("Lore", Lore);
tag.setTag("display", display);
@@ -749,6 +879,8 @@ public class Utils {
String... lore
) {
NBTTagCompound tag = itemStack.getTagCompound();
+ if (tag == null)
+ tag = new NBTTagCompound();
NBTTagCompound display = tag.getCompoundTag("display");
NBTTagList Lore = new NBTTagList();
@@ -1253,8 +1385,6 @@ public class Utils {
return prim.getAsString();
}
- public static Splitter PATH_SPLITTER = Splitter.on(".").omitEmptyStrings().limit(2);
-
public static JsonElement getElement(JsonElement element, String path) {
List<String> path_split = PATH_SPLITTER.splitToList(path);
if (element instanceof JsonObject) {
@@ -1269,6 +1399,11 @@ public class Utils {
}
}
+ public static JsonElement getElementOrDefault(JsonElement element, String path, JsonElement def) {
+ JsonElement result = getElement(element, path);
+ return result != null ? result : def;
+ }
+
public static ChatStyle createClickStyle(ClickEvent.Action action, String value) {
ChatStyle style = new ChatStyle();
style.setChatClickEvent(new ClickEvent(action, value));
@@ -1294,12 +1429,12 @@ public class Utils {
file.delete();
}
- public static char getPrimaryColourCode(String displayname) {
+ public static char getPrimaryColourCode(String displayName) {
int lastColourCode = -99;
int currentColour = 0;
int[] mostCommon = new int[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- for (int i = 0; i < displayname.length(); i++) {
- char c = displayname.charAt(i);
+ for (int i = 0; i < displayName.length(); i++) {
+ char c = displayName.charAt(i);
if (c == '\u00A7') {
lastColourCode = i;
} else if (lastColourCode == i - 1) {
@@ -1326,8 +1461,8 @@ public class Utils {
return "0123456789abcdef".charAt(currentColour);
}
- public static Color getPrimaryColour(String displayname) {
- int colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(getPrimaryColourCode(displayname));
+ public static Color getPrimaryColour(String displayName) {
+ int colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode(getPrimaryColourCode(displayName));
return new Color(colourInt).darker();
}
@@ -1336,8 +1471,6 @@ public class Utils {
scrollY.resetTimer();
}
- private static final LerpingFloat scrollY = new LerpingFloat(0, 100);
-
public static void drawHoveringText(
List<String> textLines,
final int mouseX,
@@ -1761,7 +1894,109 @@ public class Utils {
}
public static boolean isWithinRect(int x, int y, int left, int top, int width, int height) {
- return left <= x && x <= left + width &&
- top <= y && y <= top + height;
+ return left <= x && x < left + width &&
+ top <= y && y < top + height;
+ }
+
+ public static int getNumberOfStars(ItemStack stack) {
+ if (stack != null && stack.hasTagCompound()) {
+ NBTTagCompound tag = stack.getTagCompound();
+
+ if (tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if (ea.hasKey("upgrade_level", 99)) {
+ return ea.getInteger("upgrade_level");
+ } else if (ea.hasKey("dungeon_item_level")) {
+ return ea.getInteger("dungeon_item_level");
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static String getStarsString(int stars) {
+ EnumChatFormatting colorCode = null;
+ EnumChatFormatting defaultColorCode = EnumChatFormatting.GOLD;
+ int amount = 0;
+ if (stars > 5 && stars < 11) {
+ colorCode = EnumChatFormatting.LIGHT_PURPLE;
+ amount = stars - 5;
+ stars = 5;
+ }
+ if (stars > 10) {
+ colorCode = EnumChatFormatting.AQUA;
+ defaultColorCode = EnumChatFormatting.LIGHT_PURPLE;
+ amount = stars - 10;
+ stars = 5;
+ }
+
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0; i < stars; i++) {
+ if (i < amount) {
+ stringBuilder.append(colorCode).append('\u272A');
+ } else {
+ stringBuilder.append(defaultColorCode).append('\u272A');
+ }
+ }
+ return stringBuilder.toString();
+ }
+
+ public static void showOutdatedRepoNotification() {
+ if (NotEnoughUpdates.INSTANCE.config.notifications.outdatedRepo) {
+ NotificationHandler.displayNotification(Lists.newArrayList(
+ EnumChatFormatting.RED + EnumChatFormatting.BOLD.toString() + "Missing repo data",
+ EnumChatFormatting.RED +
+ "Data used for many NEU features is not up to date, this should normally not be the case.",
+ EnumChatFormatting.RED + "You can try " + EnumChatFormatting.BOLD + "/neuresetrepo" + EnumChatFormatting.RESET +
+ EnumChatFormatting.RED + " and restart your game" +
+ " to see if that fixes the issue.",
+ EnumChatFormatting.RED + "If the problem persists please join " + EnumChatFormatting.BOLD +
+ "discord.gg/moulberry" +
+ EnumChatFormatting.RESET + EnumChatFormatting.RED + " and message in " + EnumChatFormatting.BOLD +
+ "#neu-support" + EnumChatFormatting.RESET + EnumChatFormatting.RED + " to get support"
+ ),
+ true, true
+ );
+ }
+ }
+
+ /**
+ * Finds the rarity from the lore of an item.
+ * -1 = UNKNOWN
+ * 0 = COMMON
+ * 1 = UNCOMMON
+ * 2 = RARE
+ * 3 = EPIC
+ * 4 = LEGENDARY
+ * 5 = MYTHIC
+ * 6 = SPECIAL
+ * 7 = VERY SPECIAL
+ */
+ public static int getRarityFromLore(JsonArray lore) {
+ for (int i = lore.size() - 1; i >= 0; i--) {
+ String line = lore.get(i).getAsString();
+
+ for (int j = 0; j < rarityArrC.length; j++) {
+ if (line.startsWith(rarityArrC[j])) {
+ return j;
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static UUID parseDashlessUUID(String dashlessUuid) {
+ // From: https://stackoverflow.com/a/30760478/
+ BigInteger most = new BigInteger(dashlessUuid.substring(0, 16), 16);
+ BigInteger least = new BigInteger(dashlessUuid.substring(16, 32), 16);
+ return new UUID(most.longValue(), least.longValue());
+ }
+
+ public static String getOpenChestName() {
+ return SBInfo.getInstance().currentlyOpenChestName;
+ }
+
+ public static String getLastOpenChestName() {
+ return SBInfo.getInstance().lastOpenChestName;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
index aef2490e..81eea343 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/XPInformation.java
@@ -1,8 +1,26 @@
+/*
+ * Copyright (C) 2022 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
package io.github.moulberry.notenoughupdates.util;
import com.google.common.base.Splitter;
import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
@@ -12,11 +30,9 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import java.util.stream.StreamSupport;
public class XPInformation {
private static final XPInformation INSTANCE = new XPInformation();
@@ -171,6 +187,7 @@ public class XPInformation {
skillInfo.currentXp += updateWithPercentage.get(skill) / 100f * cap;
skillInfo.totalXp += skillInfo.currentXp;
skillInfo.currentXpMax = cap;
+ break;
} else {
skillInfo.totalXp += cap;
}
@@ -212,15 +229,16 @@ public class XPInformation {
};
private void onApiUpdated(ProfileViewer.Profile profile) {
- JsonObject skillInfo = profile.getSkillInfo(null);
+ Map<String, ProfileViewer.Level> skyblockInfo = profile.getSkyblockInfo(null);
for (String skill : skills) {
SkillInfo info = new SkillInfo();
- float level = skillInfo.get("level_skill_" + skill).getAsFloat();
+ ProfileViewer.Level levelInfo = skyblockInfo.get(skill);
+ float level = levelInfo.level;
- info.totalXp = skillInfo.get("experience_skill_" + skill).getAsFloat();
- info.currentXpMax = skillInfo.get("maxxp_skill_" + skill).getAsFloat();
+ info.totalXp = levelInfo.totalXp;
+ info.currentXpMax = levelInfo.maxXpForLevel;
info.level = (int) level;
info.currentXp = (level % 1) * info.currentXpMax;
info.fromApi = true;
@@ -228,29 +246,4 @@ public class XPInformation {
skillInfoMap.put(skill.toLowerCase(), info);
}
}
-
- public double getPetLevel(String petId, double exp, String rarity) {
- Stream<JsonElement> pet_levels =
- StreamSupport.stream(Constants.PETS.get("pet_levels").getAsJsonArray().spliterator(), false);
- int pet_rarity_offset = Constants.PETS.getAsJsonObject("pet_rarity_offset").get(rarity).getAsInt();
- JsonObject custom_pet_leveling = Constants.PETS.getAsJsonObject("custom_pet_leveling").getAsJsonObject(petId);
- List<Integer> xpLevelsRequired =
- pet_levels.skip(pet_rarity_offset).limit(100).map(JsonElement::getAsInt).collect(Collectors.toList());
- if (custom_pet_leveling != null && custom_pet_leveling.get("type").getAsInt() == 1)
- xpLevelsRequired.addAll(StreamSupport
- .stream(custom_pet_leveling.getAsJsonArray("pet_levels").spliterator(), false)
- .map(JsonElement::getAsInt)
- .collect(Collectors.toList()));
- double remainingExp = exp;
- for (int i = 0; i < xpLevelsRequired.size(); i++) {
- int xpForCurrentLevel = xpLevelsRequired.get(i);
- if (remainingExp >= xpForCurrentLevel) {
- remainingExp -= xpForCurrentLevel;
- } else {
- return i + 1 + remainingExp / xpForCurrentLevel;
- }
- }
- return xpLevelsRequired.size();
- }
-
}