summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/NotSkyblockAddonsInstallerFrame.java667
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java224
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java10
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/HelpGUI.java189
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/ItemRarityHalo.java251
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java419
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java35
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java621
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java196
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java533
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java205
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java210
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java49
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java58
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/Options.java83
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java2473
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java146
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java505
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java890
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java67
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/SBScoreboardData.java76
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java78
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java262
-rw-r--r--src/main/resources/assets/notenoughupdates/button20x.pngbin0 -> 170 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/custom_ench_colour.pngbin0 -> 4530 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/folder.pngbin0 -> 454 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_0.jpgbin0 -> 21394 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_1.jpgbin0 -> 20539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_2.jpgbin0 -> 18095 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_3.jpgbin0 -> 21069 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_4.jpgbin0 -> 17245 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_5.jpgbin0 -> 13035 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_0.jpgbin0 -> 15969 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_1.jpgbin0 -> 14301 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_2.jpgbin0 -> 12769 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_3.jpgbin0 -> 12440 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_4.jpgbin0 -> 11408 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_5.jpgbin0 -> 16017 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_0.jpgbin0 -> 30425 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_1.jpgbin0 -> 18248 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_2.jpgbin0 -> 14289 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_3.jpgbin0 -> 19871 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_4.jpgbin0 -> 18328 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_5.jpgbin0 -> 8718 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_0.jpgbin0 -> 14773 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_1.jpgbin0 -> 11063 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_2.jpgbin0 -> 5580 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_3.jpgbin0 -> 17256 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_4.jpgbin0 -> 12133 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_5.jpgbin0 -> 4516 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_0.jpgbin0 -> 34048 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_1.jpgbin0 -> 28471 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_2.jpgbin0 -> 22159 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_3.jpgbin0 -> 27487 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_4.jpgbin0 -> 19750 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_5.jpgbin0 -> 21597 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_0.jpgbin0 -> 18255 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_1.jpgbin0 -> 11295 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_2.jpgbin0 -> 13877 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_3.jpgbin0 -> 18438 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_4.jpgbin0 -> 10785 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_5.jpgbin0 -> 12742 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_0.jpgbin0 -> 19008 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_1.jpgbin0 -> 19414 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_2.jpgbin0 -> 19388 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_3.jpgbin0 -> 19497 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_4.jpgbin0 -> 18727 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_5.jpgbin0 -> 18871 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_0.jpgbin0 -> 16337 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_1.jpgbin0 -> 19376 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_2.jpgbin0 -> 17633 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_3.jpgbin0 -> 18424 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_4.jpgbin0 -> 18780 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_5.jpgbin0 -> 18041 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_0.jpgbin0 -> 16337 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_1.jpgbin0 -> 19376 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_2.jpgbin0 -> 17633 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_3.jpgbin0 -> 18424 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_4.jpgbin0 -> 18780 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_5.jpgbin0 -> 18041 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_0.jpgbin0 -> 35131 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_1.jpgbin0 -> 32356 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_2.jpgbin0 -> 34147 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_3.jpgbin0 -> 42291 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_4.jpgbin0 -> 25831 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_5.jpgbin0 -> 20933 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_0.jpgbin0 -> 28070 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_1.jpgbin0 -> 30401 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_2.jpgbin0 -> 29899 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_3.jpgbin0 -> 30543 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_4.jpgbin0 -> 27401 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_5.jpgbin0 -> 21828 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_0.jpgbin0 -> 34294 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_1.jpgbin0 -> 47518 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_2.jpgbin0 -> 46569 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_3.jpgbin0 -> 36648 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_4.jpgbin0 -> 15788 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_5.jpgbin0 -> 47536 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_0.jpgbin0 -> 20273 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_1.jpgbin0 -> 23666 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_2.jpgbin0 -> 26548 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_3.jpgbin0 -> 22310 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_4.jpgbin0 -> 9398 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_5.jpgbin0 -> 29882 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_0.jpgbin0 -> 30779 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_1.jpgbin0 -> 29586 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_2.jpgbin0 -> 30070 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_3.jpgbin0 -> 30822 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_4.jpgbin0 -> 11867 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_5.jpgbin0 -> 24780 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_0.jpgbin0 -> 19525 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_1.jpgbin0 -> 14742 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_2.jpgbin0 -> 16263 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_3.jpgbin0 -> 17533 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_4.jpgbin0 -> 6528 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_5.jpgbin0 -> 17504 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_0.jpgbin0 -> 42789 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_1.jpgbin0 -> 32963 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_2.jpgbin0 -> 36208 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_3.jpgbin0 -> 34657 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_4.jpgbin0 -> 25234 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_5.jpgbin0 -> 29243 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_0.jpgbin0 -> 16958 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_1.jpgbin0 -> 16735 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_2.jpgbin0 -> 15980 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_3.jpgbin0 -> 17531 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_4.jpgbin0 -> 11656 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_5.jpgbin0 -> 17297 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_0.jpgbin0 -> 20453 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_1.jpgbin0 -> 20509 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_2.jpgbin0 -> 23845 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_3.jpgbin0 -> 24436 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_4.jpgbin0 -> 10145 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_5.jpgbin0 -> 16562 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_0.jpgbin0 -> 17155 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_1.jpgbin0 -> 17538 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_2.jpgbin0 -> 15950 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_3.jpgbin0 -> 17928 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_4.jpgbin0 -> 5091 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_5.jpgbin0 -> 15786 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_0.jpgbin0 -> 37877 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_1.jpgbin0 -> 33985 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_2.jpgbin0 -> 29885 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_3.jpgbin0 -> 29426 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_4.jpgbin0 -> 17061 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_5.jpgbin0 -> 24623 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_0.jpgbin0 -> 25721 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_1.jpgbin0 -> 22713 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_2.jpgbin0 -> 17499 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_3.jpgbin0 -> 19113 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_4.jpgbin0 -> 11604 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_5.jpgbin0 -> 17142 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_0.jpgbin0 -> 19309 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_1.jpgbin0 -> 11211 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_2.jpgbin0 -> 13231 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_3.jpgbin0 -> 13388 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_4.jpgbin0 -> 10314 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_5.jpgbin0 -> 11803 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_0.jpgbin0 -> 26015 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_1.jpgbin0 -> 26016 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_2.jpgbin0 -> 24769 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_3.jpgbin0 -> 24854 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_4.jpgbin0 -> 26123 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_5.jpgbin0 -> 24894 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/patreon1.pngbin0 -> 46767 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/patreon2.pngbin0 -> 45479 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_basic.pngbin0 -> 5173 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_bg.pngbin0 -> 2016 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_cols.pngbin0 -> 1843 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_dropdown.pngbin0 -> 2386 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_elements.pngbin0 -> 2567 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_extra.pngbin0 -> 5665 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_invs.pngbin0 -> 4446 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/pv_pets.pngbin0 -> 4370 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/cape.frag4
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/fade_cape.frag8
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/make_gold.frag38
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/make_gold.vert13
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/blur.json21
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/blur2.fsh34
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.fsh11
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.json17
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/sobel.vsh20
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_border.jpgbin0 -> 14021 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss1-0.jpgbin0 -> 148110 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss10-0.jpgbin0 -> 57284 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss11-0.jpgbin0 -> 56257 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss12-0.jpgbin0 -> 57416 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss13-0.jpgbin0 -> 83136 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss14-0.jpgbin0 -> 74904 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss15-0.jpgbin0 -> 66785 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss16-0.jpgbin0 -> 72065 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss17-0.jpgbin0 -> 62715 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss18-0.jpgbin0 -> 30420 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss2-0.jpgbin0 -> 94161 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss3-0.jpgbin0 -> 96250 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss4-0.jpgbin0 -> 93772 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss5-0.jpgbin0 -> 95859 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss6-0.jpgbin0 -> 106602 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss7-0.jpgbin0 -> 127654 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss8-0.jpgbin0 -> 86011 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/ss_small/ss9-0.jpgbin0 -> 69263 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/wkhtmltox.zipbin31902481 -> 16009138 bytes
-rw-r--r--src/main/resources/mixins.notenoughupdates.json3
217 files changed, 7666 insertions, 953 deletions
diff --git a/src/main/java/NotSkyblockAddonsInstallerFrame.java b/src/main/java/NotSkyblockAddonsInstallerFrame.java
new file mode 100644
index 00000000..7c5a1638
--- /dev/null
+++ b/src/main/java/NotSkyblockAddonsInstallerFrame.java
@@ -0,0 +1,667 @@
+import javax.imageio.ImageIO;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+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.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.util.Locale;
+import java.util.jar.JarFile;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+
+public class NotSkyblockAddonsInstallerFrame extends JFrame implements ActionListener, MouseListener {
+
+ private static final Pattern IN_MODS_SUBFOLDER = Pattern.compile("1\\.8\\.9[/\\\\]?$");
+
+ private JLabel logo = null;
+ private JLabel versionInfo = null;
+ private JLabel labelFolder = null;
+
+ private JPanel panelCenter = null;
+ private JPanel panelBottom = null;
+ private JPanel totalContentPane = null;
+
+ private JTextArea descriptionText = null;
+ private JTextArea forgeDescriptionText = null;
+
+ private JTextField textFieldFolderLocation = null;
+ private JButton buttonChooseFolder = null;
+
+ private JButton buttonInstall = null;
+ private JButton buttonOpenFolder = null;
+ private JButton buttonClose = null;
+
+ private static final int TOTAL_HEIGHT = 435;
+ private static final int TOTAL_WIDTH = 404;
+
+ private int x = 0;
+ private int y = 0;
+
+ private int w = TOTAL_WIDTH;
+ private int h;
+ private int margin;
+
+ public NotSkyblockAddonsInstallerFrame() {
+ try {
+ setName("NotEnoughUpdatesInstallerFrame");
+ setTitle("NotEnoughUpdates Installer");
+ setResizable(false);
+ setSize(TOTAL_WIDTH, TOTAL_HEIGHT);
+ setContentPane(getPanelContentPane());
+
+ getButtonFolder().addActionListener(this);
+ getButtonInstall().addActionListener(this);
+ getButtonOpenFolder().addActionListener(this);
+ getButtonClose().addActionListener(this);
+ getForgeTextArea().addMouseListener(this);
+
+ pack();
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+
+ getFieldFolder().setText(getModsFolder().getPath());
+ getButtonInstall().setEnabled(true);
+ getButtonInstall().requestFocus();
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ }
+ }
+
+ public static void main(String[] args) {
+ try {
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ NotSkyblockAddonsInstallerFrame frame = new NotSkyblockAddonsInstallerFrame();
+ frame.centerFrame(frame);
+ frame.show();
+
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ }
+ }
+
+ private JPanel getPanelContentPane() {
+ if (totalContentPane == null) {
+ try {
+ totalContentPane = new JPanel();
+ totalContentPane.setName("PanelContentPane");
+ totalContentPane.setLayout(new BorderLayout(5, 5));
+ totalContentPane.setPreferredSize(new Dimension(TOTAL_WIDTH, TOTAL_HEIGHT));
+ totalContentPane.add(getPanelCenter(), "Center");
+ totalContentPane.add(getPanelBottom(), "South");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return totalContentPane;
+ }
+
+ private JPanel getPanelCenter() {
+ if (panelCenter == null) {
+ try {
+ (panelCenter = new JPanel()).setName("PanelCenter");
+ panelCenter.setLayout(null);
+ panelCenter.add(getPictureLabel(), getPictureLabel().getName());
+ panelCenter.add(getVersionInfo(), getVersionInfo().getName());
+ panelCenter.add(getTextArea(), getTextArea().getName());
+ panelCenter.add(getForgeTextArea(), getForgeTextArea().getName());
+ panelCenter.add(getLabelFolder(), getLabelFolder().getName());
+ panelCenter.add(getFieldFolder(), getFieldFolder().getName());
+ panelCenter.add(getButtonFolder(), getButtonFolder().getName());
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return panelCenter;
+ }
+
+ private JLabel getPictureLabel() {
+ if (logo == null) {
+ try {
+ h = w/2;
+ margin = 5;
+
+ BufferedImage myPicture = ImageIO.read(getClass().getClassLoader().getResourceAsStream("assets/notenoughupdates/logo.png"));
+ Image scaled = myPicture.getScaledInstance(w-margin*2, h-margin, Image.SCALE_SMOOTH);
+ logo = new JLabel(new ImageIcon(scaled));
+ logo.setName("Logo");
+ logo.setBounds(x+margin, y+margin, w-margin*2, h-margin);
+ logo.setFont(new Font(Font.DIALOG, Font.BOLD, 18));
+ logo.setHorizontalAlignment(SwingConstants.CENTER);
+ logo.setPreferredSize(new Dimension(h*742/537, h));
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return logo;
+ }
+
+ private JLabel getVersionInfo() {
+ if (versionInfo == null) {
+ try {
+ h = 25;
+
+ versionInfo = new JLabel();
+ versionInfo.setName("LabelMcVersion");
+ versionInfo.setBounds(x, y, w, h);
+ versionInfo.setFont(new Font(Font.DIALOG, Font.BOLD, 14));
+ versionInfo.setHorizontalAlignment(SwingConstants.CENTER);
+ versionInfo.setPreferredSize(new Dimension(w, h));
+ versionInfo.setText("NEU by Moulberry, Installer by Biscuit - for Minecraft 1.8.9");
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return versionInfo;
+ }
+
+ private JTextArea getTextArea() {
+ if (descriptionText == null) {
+ try {
+ h = 60;
+ margin = 10;
+
+ descriptionText = new JTextArea();
+ descriptionText.setName("TextArea");
+ descriptionText.setBounds(x+margin, y+margin, w-margin*2, h-margin);
+ descriptionText.setEditable(false);
+ descriptionText.setHighlighter(null);
+ descriptionText.setEnabled(true);
+ descriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12));
+ descriptionText.setLineWrap(true);
+ descriptionText.setOpaque(false);
+ descriptionText.setPreferredSize(new Dimension(w-margin*2, h-margin));
+ descriptionText.setText("This installer will copy NotEnoughUpdates into your forge mods folder for you, and replace any old versions that already exist. " +
+ "Close this if you prefer to do this yourself!");
+ descriptionText.setWrapStyleWord(true);
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return descriptionText;
+ }
+
+ private JTextArea getForgeTextArea() {
+ if (forgeDescriptionText == null) {
+ try {
+ h = 55;
+ margin = 10;
+
+ forgeDescriptionText = new JTextArea();
+ forgeDescriptionText.setName("TextAreaForge");
+ forgeDescriptionText.setBounds(x+margin, y+margin, w-margin*2, h-margin);
+ forgeDescriptionText.setEditable(false);
+ forgeDescriptionText.setHighlighter(null);
+ forgeDescriptionText.setEnabled(true);
+ forgeDescriptionText.setFont(new Font(Font.DIALOG, Font.PLAIN, 12));
+ forgeDescriptionText.setLineWrap(true);
+ forgeDescriptionText.setOpaque(false);
+ forgeDescriptionText.setPreferredSize(new Dimension(w-margin*2, h-margin));
+ forgeDescriptionText.setText("However, you still need to install Forge client in order to be able to run this mod. Click here to visit the download page for Forge 1.8.9!");
+ forgeDescriptionText.setForeground(Color.BLUE.darker());
+ forgeDescriptionText.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ forgeDescriptionText.setWrapStyleWord(true);
+
+ y += h;
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return forgeDescriptionText;
+ }
+
+ private JLabel getLabelFolder() {
+ if (labelFolder == null) {
+ h = 16;
+ w = 65;
+
+ x += 10; // Padding
+
+ try {
+ labelFolder = new JLabel();
+ labelFolder.setName("LabelFolder");
+ labelFolder.setBounds(x, y+2, w, h);
+ labelFolder.setPreferredSize(new Dimension(w, h));
+ labelFolder.setText("Mods Folder");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+
+ x += w;
+ }
+ return labelFolder;
+ }
+
+ private JTextField getFieldFolder() {
+ if (textFieldFolderLocation == null) {
+ h = 20;
+ w = 287;
+
+ try {
+ textFieldFolderLocation = new JTextField();
+ textFieldFolderLocation.setName("FieldFolder");
+ textFieldFolderLocation.setBounds(x, y, w, h);
+ textFieldFolderLocation.setEditable(false);
+ textFieldFolderLocation.setPreferredSize(new Dimension(w, h));
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+
+ x += w;
+ }
+ return textFieldFolderLocation;
+ }
+
+ private JButton getButtonFolder() {
+ if (buttonChooseFolder == null) {
+ h = 20;
+ w = 25;
+
+ x += 10; // Padding
+
+ try {
+ BufferedImage myPicture = ImageIO.read(getClass().getClassLoader().getResourceAsStream("assets/notenoughupdates/folder.png"));
+ Image scaled = myPicture.getScaledInstance(w-8, h-6, Image.SCALE_SMOOTH);
+ buttonChooseFolder = new JButton(new ImageIcon(scaled));
+ buttonChooseFolder.setName("ButtonFolder");
+ buttonChooseFolder.setBounds(x, y, w, h);
+ buttonChooseFolder.setPreferredSize(new Dimension(w, h));
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonChooseFolder;
+ }
+
+ private JPanel getPanelBottom() {
+ if (panelBottom == null) {
+ try {
+ panelBottom = new JPanel();
+ panelBottom.setName("PanelBottom");
+ panelBottom.setLayout(new FlowLayout(FlowLayout.CENTER, 15, 10));
+ panelBottom.setPreferredSize(new Dimension(390, 55));
+ panelBottom.add(getButtonInstall(), getButtonInstall().getName());
+ panelBottom.add(getButtonOpenFolder(), getButtonOpenFolder().getName());
+ panelBottom.add(getButtonClose(), getButtonClose().getName());
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return panelBottom;
+ }
+
+ private JButton getButtonInstall() {
+ if (buttonInstall == null) {
+ w = 100;
+ h = 26;
+
+ try {
+ buttonInstall = new JButton();
+ buttonInstall.setName("ButtonInstall");
+ buttonInstall.setPreferredSize(new Dimension(w, h));
+ buttonInstall.setText("Install");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonInstall;
+ }
+
+ private JButton getButtonOpenFolder() {
+ if (buttonOpenFolder == null) {
+ w = 130;
+ h = 26;
+
+ try {
+ buttonOpenFolder = new JButton();
+ buttonOpenFolder.setName("ButtonOpenFolder");
+ buttonOpenFolder.setPreferredSize(new Dimension(w, h));
+ buttonOpenFolder.setText("Open Mods Folder");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonOpenFolder;
+ }
+
+ private JButton getButtonClose() {
+ if (buttonClose == null) {
+ w = 100;
+ h = 26;
+
+ try {
+ (buttonClose = new JButton()).setName("ButtonClose");
+ buttonClose.setPreferredSize(new Dimension(w, h));
+ buttonClose.setText("Cancel");
+ } catch (Throwable ivjExc) {
+ showErrorPopup(ivjExc);
+ }
+ }
+ return buttonClose;
+ }
+
+ public void onFolderSelect() {
+ File currentDirectory = new File(getFieldFolder().getText());
+
+ JFileChooser jFileChooser = new JFileChooser(currentDirectory);
+ jFileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ jFileChooser.setAcceptAllFileFilterUsed(false);
+ if (jFileChooser.showOpenDialog(this) == 0) {
+ File newDirectory = jFileChooser.getSelectedFile();
+ getFieldFolder().setText(newDirectory.getPath());
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() == getButtonClose()) {
+ dispose();
+ System.exit(0);
+ }
+ if (e.getSource() == getButtonFolder()) {
+ onFolderSelect();
+ }
+ if (e.getSource() == getButtonInstall()) {
+ onInstall();
+ }
+ if (e.getSource() == getButtonOpenFolder()) {
+ onOpenFolder();
+ }
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getSource() == getForgeTextArea()) {
+ try {
+ Desktop.getDesktop().browse(new URI("http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html"));
+ } catch (IOException | URISyntaxException ex) {
+ showErrorPopup(ex);
+ }
+ }
+ }
+
+ public void onInstall() {
+ try {
+ File modsFolder = new File(getFieldFolder().getText());
+ if (!modsFolder.exists()) {
+ showErrorMessage("Folder not found: " + modsFolder.getPath());
+ return;
+ }
+ if (!modsFolder.isDirectory()) {
+ showErrorMessage("Not a folder: " + modsFolder.getPath());
+ return;
+ }
+ tryInstall(modsFolder);
+ } catch (Exception e) {
+ showErrorPopup(e);
+ }
+ }
+
+ private void tryInstall(File modsFolder) {
+ File thisFile = getThisFile();
+
+ if (thisFile != null) {
+ boolean inSubFolder = false;
+ if (IN_MODS_SUBFOLDER.matcher(modsFolder.getPath()).find()) {
+ inSubFolder = true;
+ }
+
+ boolean deletingFailure = false;
+ if (modsFolder.isDirectory()) { // Delete in this current folder.
+ boolean failed = findSkyblockAddonsAndDelete(modsFolder.listFiles());
+ if (failed) deletingFailure = true;
+ }
+ if (inSubFolder) { // We are in the 1.8.9 folder, delete in the parent folder as well.
+ if (modsFolder.getParentFile().isDirectory()) {
+ boolean failed = findSkyblockAddonsAndDelete(modsFolder.getParentFile().listFiles());
+ if (failed) deletingFailure = true;
+ }
+ } else { // We are in the main mods folder, but the 1.8.9 subfolder exists... delete in there too.
+ File subFolder = new File(modsFolder, "1.8.9");
+ if (subFolder.exists() && subFolder.isDirectory()) {
+ boolean failed = findSkyblockAddonsAndDelete(subFolder.listFiles());
+ if (failed) deletingFailure = true;
+ }
+ }
+
+ if (deletingFailure) return;
+
+ if (thisFile.isDirectory()) {
+ showErrorMessage("This file is a directory... Are we in a development environment?");
+ return;
+ }
+
+ try {
+ Files.copy(thisFile.toPath(), new File(modsFolder, thisFile.getName()).toPath());
+ } catch (Exception ex) {
+ showErrorPopup(ex);
+ return;
+ }
+
+ showMessage("NotEnoughUpdates has been successfully installed into your mods folder.");
+ dispose();
+ System.exit(0);
+ }
+ }
+
+ private boolean findSkyblockAddonsAndDelete(File[] files) {
+ if (files == null) return false;
+
+ for (File file : files) {
+ if (!file.isDirectory() && file.getPath().endsWith(".jar")) {
+ try {
+ JarFile jarFile = new JarFile(file);
+ ZipEntry mcModInfo = jarFile.getEntry("mcmod.info");
+ if (mcModInfo != null) {
+ InputStream inputStream = jarFile.getInputStream(mcModInfo);
+ String modID = getModIDFromInputStream(inputStream);
+ if (modID.equals("notenoughupdates")) {
+ jarFile.close();
+ try {
+ boolean deleted = file.delete();
+ if (!deleted) {
+ throw new Exception();
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ showErrorMessage("Was not able to delete the other NotEnoughUpdates files found in your mods folder!" + System.lineSeparator() +
+ "Please make sure that your minecraft is currently closed and try again, or feel" + System.lineSeparator() +
+ "free to open your mods folder and delete those files manually.");
+ return true;
+ }
+ continue;
+ }
+ }
+ jarFile.close();
+ } catch (Exception ex) {
+ // Just don't check the file I guess, move on to the next...
+ }
+ }
+ }
+ return false;
+ }
+
+ public void onOpenFolder() {
+ try {
+ Desktop.getDesktop().open(getModsFolder());
+ } catch (Exception e) {
+ showErrorPopup(e);
+ }
+ }
+
+ public File getModsFolder() {
+ String userHome = System.getProperty("user.home", ".");
+
+ File modsFolder = getFile(userHome, "minecraft/mods/1.8.9");
+ if (!modsFolder.exists()) {
+ modsFolder = getFile(userHome, "minecraft/mods");
+ }
+
+ if (!modsFolder.exists() && !modsFolder.mkdirs()) {
+ throw new RuntimeException("The working directory could not be created: " + modsFolder);
+ }
+ return modsFolder;
+ }
+
+ public File getFile(String userHome, String minecraftPath) {
+ File workingDirectory;
+ switch (getOperatingSystem()) {
+ case LINUX:
+ case SOLARIS: {
+ workingDirectory = new File(userHome, '.' + minecraftPath + '/');
+ break;
+ }
+ case WINDOWS: {
+ String applicationData = System.getenv("APPDATA");
+ if (applicationData != null) {
+ workingDirectory = new File(applicationData, "." + minecraftPath + '/');
+ break;
+ }
+ workingDirectory = new File(userHome, '.' + minecraftPath + '/');
+ break;
+ }
+ case MACOS: {
+ workingDirectory = new File(userHome, "Library/Application Support/" + minecraftPath);
+ break;
+ }
+ default: {
+ workingDirectory = new File(userHome, minecraftPath + '/');
+ break;
+ }
+ }
+ return workingDirectory;
+ }
+
+ public OperatingSystem getOperatingSystem() {
+ String osName = System.getProperty("os.name").toLowerCase(Locale.US);
+ if (osName.contains("win")) {
+ return OperatingSystem.WINDOWS;
+
+ } else if (osName.contains("mac")) {
+ return OperatingSystem.MACOS;
+
+ } else if (osName.contains("solaris") || osName.contains("sunos")) {
+
+ return OperatingSystem.SOLARIS;
+ } else if (osName.contains("linux") || osName.contains("unix")) {
+
+ return OperatingSystem.LINUX;
+ }
+ return OperatingSystem.UNKNOWN;
+ }
+
+ public void centerFrame(JFrame frame) {
+ Rectangle rectangle = frame.getBounds();
+ Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+ Rectangle screenRectangle = new Rectangle(0, 0, screenSize.width, screenSize.height);
+
+ int newX = screenRectangle.x + (screenRectangle.width - rectangle.width) / 2;
+ int newY = screenRectangle.y + (screenRectangle.height - rectangle.height) / 2;
+
+ if (newX < 0) newX = 0;
+ if (newY < 0) newY = 0;
+
+ frame.setBounds(newX, newY, rectangle.width, rectangle.height);
+ }
+
+ public void showMessage(String message) {
+ JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates", JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ public void showErrorMessage(String message) {
+ JOptionPane.showMessageDialog(null, message, "NotEnoughUpdates - Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ public enum OperatingSystem {
+ LINUX,
+ SOLARIS,
+ WINDOWS,
+ MACOS,
+ UNKNOWN
+ }
+
+ private static String getStacktraceText(Throwable ex) {
+ StringWriter stringWriter = new StringWriter();
+ ex.printStackTrace(new PrintWriter(stringWriter));
+ return stringWriter.toString().replace("\t", " ");
+ }
+
+ private static void showErrorPopup(Throwable ex) {
+ ex.printStackTrace();
+
+ JTextArea textArea = new JTextArea(getStacktraceText(ex));
+ textArea.setEditable(false);
+ Font currentFont = textArea.getFont();
+ Font newFont = new Font(Font.MONOSPACED, currentFont.getStyle(), currentFont.getSize());
+ textArea.setFont(newFont);
+
+ JScrollPane errorScrollPane = new JScrollPane(textArea);
+ errorScrollPane.setPreferredSize(new Dimension(600, 400));
+ JOptionPane.showMessageDialog(null, errorScrollPane, "Error", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private String getVersionFromMcmodInfo() {
+ String version = "";
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getClass().getClassLoader().getResourceAsStream("mcmod.info")));
+ while ((version = bufferedReader.readLine()) != null) {
+ if (version.contains("\"version\": \"")) {
+ version = version.split(Pattern.quote("\"version\": \""))[1];
+ version = version.substring(0, version.length() - 2);
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ // It's okay, I guess just don't use the version lol.
+ }
+ return version;
+ }
+
+ private String getModIDFromInputStream(InputStream inputStream) {
+ String version = "";
+ try {
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
+ while ((version = bufferedReader.readLine()) != null) {
+ if (version.contains("\"modid\": \"")) {
+ version = version.split(Pattern.quote("\"modid\": \""))[1];
+ version = version.substring(0, version.length() - 2);
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ // RIP, couldn't find the modid...
+ }
+ return version;
+ }
+
+ private File getThisFile() {
+ try {
+ return new File(NotSkyblockAddonsInstallerFrame.class.getProtectionDomain().getCodeSource().getLocation().toURI());
+ } catch (URISyntaxException ex) {
+ showErrorPopup(ex);
+ }
+ return null;
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {}
+
+ @Override
+ public void mouseReleased(MouseEvent e) {}
+
+ @Override
+ public void mouseEntered(MouseEvent e) {}
+
+ @Override
+ public void mouseExited(MouseEvent e) {}
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
index 4328eaf4..dcd8cfb2 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java
@@ -35,6 +35,11 @@ public class CustomItems {
"your buried duct tape problems are a thing of the past,",
"all for the low price of $7.99 or a subscription",
"to the Ducttapedigger youtube channel!");
+ public static JsonObject SPINAXX = create(
+ "SPINAXX",
+ "emerald",
+ "Spinaxx",
+ "Famous streamer btw :)");
public static JsonObject RUNE = create("RUNE", "paper", "No.", "I hate runes.");
public static JsonObject TWOBEETWOTEE = create("2B2T", "bedrock", "Minecraft's oldest anarchy Minecraft server in Minecraft.",
"This Minecraft anarchy server is the oldest server,",
@@ -48,6 +53,14 @@ public class CustomItems {
"incursions on the server, some of which I, a player on this Minecraft",
"anarchy server in Minecraft, have participated in. One of this server's",
"most infamous Minecraft players on the oldest Minecraft");
+ public static JsonObject LEOCTHL = create("LEOCTHL", "dragon_egg", "--- Stats below may not be entirely accurate ---",
+ "17 legendary dragon pets",
+ "24 epic dragon pets",
+ "18 epic golem pets",
+ "12 legendary golem pets",
+ "39 legendary phoenix pets",
+ "",
+ "get flexed");
/**
* SHAAAAAAAAAAAAAAAAAAME
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java
new file mode 100644
index 00000000..8e14598f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java
@@ -0,0 +1,224 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.common.base.Splitter;
+import io.github.moulberry.notenoughupdates.itemeditor.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.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class GuiEnchantColour extends GuiScreen {
+
+ public static final ResourceLocation custom_ench_colour = new ResourceLocation("notenoughupdates:custom_ench_colour.png");
+
+ private int guiLeft;
+ private int guiTop;
+ private final int xSize = 176;
+ private int ySize = 0;
+
+ private List<String> getEnchantColours() {
+ return NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value;
+ }
+
+ public static final Splitter splitter = Splitter.on(":").limit(4);
+
+ private HashMap<Integer, String> comparators = new HashMap<>();
+ private List<GuiElementTextField[]> guiElementTextFields = new ArrayList<>();
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ drawDefaultBackground();
+
+ List<String> enchantColours = getEnchantColours();
+
+ ySize = 53+25*enchantColours.size();
+ guiLeft = (width-xSize)/2;
+ guiTop = (height-ySize)/2;
+
+ NotEnoughUpdates.INSTANCE.manager.loadConfig();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(custom_ench_colour);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, 21, 0, 1, 0, 21/78f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(guiLeft, guiTop+ySize-32, xSize, 32, 0, 1, 46/78f, 1, GL11.GL_NEAREST);
+
+ fontRendererObj.drawString("Ench Name", guiLeft+10, guiTop+7, 4210752);
+ fontRendererObj.drawString("CMP", guiLeft+71, guiTop+7, 4210752);
+ fontRendererObj.drawString("LVL", guiLeft+96, guiTop+7, 4210752);
+ fontRendererObj.drawString("COL", guiLeft+121, guiTop+7, 4210752);
+ fontRendererObj.drawString("DEL", guiLeft+146, guiTop+7, 4210752);
+
+ Utils.drawStringCentered("Add Ench Colour", fontRendererObj, guiLeft+xSize/2, guiTop+ySize-20, false, 4210752);
+
+ int yIndex = 0;
+ for(String str : enchantColours) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(custom_ench_colour);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft, guiTop+21+yIndex*25, xSize, 25, 0, 1, 21/78f, 46/78f, GL11.GL_NEAREST);
+
+ List<String> colourOps = splitter.splitToList(str);
+ String enchantName = getColourOpIndex(colourOps, 0);
+ String comparator = getColourOpIndex(colourOps, 1);
+ String comparison = getColourOpIndex(colourOps, 2);
+ String colourCode = getColourOpIndex(colourOps, 3);
+
+ if(colourCode.length() > 1) colourCode = String.valueOf(colourCode.toLowerCase().charAt(0));
+ if(comparator.length() > 1) comparator = String.valueOf(comparator.toLowerCase().charAt(0));
+
+ Utils.drawStringCentered(comparator, fontRendererObj, guiLeft+81, guiTop+33+25*yIndex, false, 4210752);
+
+ if(guiElementTextFields.size() <= yIndex) {
+ guiElementTextFields.add(new GuiElementTextField[3]);
+ }
+ if(guiElementTextFields.get(yIndex)[0] == null) {
+ guiElementTextFields.get(yIndex)[0] = new GuiElementTextField(enchantName, GuiElementTextField.SCALE_TEXT);
+ guiElementTextFields.get(yIndex)[0].setSize(56, 20);
+ }
+ if(guiElementTextFields.get(yIndex)[1] == null) {
+ guiElementTextFields.get(yIndex)[1] = new GuiElementTextField(comparison,
+ GuiElementTextField.SCALE_TEXT|GuiElementTextField.NUM_ONLY|GuiElementTextField.NO_SPACE);
+ guiElementTextFields.get(yIndex)[1].setSize(20, 20);
+ }
+ if(guiElementTextFields.get(yIndex)[2] == null) {
+ guiElementTextFields.get(yIndex)[2] = new GuiElementTextField(colourCode, GuiElementTextField.SCALE_TEXT);
+ guiElementTextFields.get(yIndex)[2].setSize(20, 20);
+ }
+ guiElementTextFields.get(yIndex)[0].setText(enchantName);
+ guiElementTextFields.get(yIndex)[1].setText(comparison);
+ comparators.put(yIndex, comparator);
+ guiElementTextFields.get(yIndex)[2].setText(colourCode);
+
+ guiElementTextFields.get(yIndex)[0].render(guiLeft+10, guiTop+23+25*yIndex);
+ guiElementTextFields.get(yIndex)[1].render(guiLeft+96, guiTop+23+25*yIndex);
+ guiElementTextFields.get(yIndex)[2].render(guiLeft+121, guiTop+23+25*yIndex);
+
+ yIndex++;
+ }
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ super.keyTyped(typedChar, keyCode);
+ for(int yIndex=0; yIndex<guiElementTextFields.size(); yIndex++) {
+ for(int i=0; i<3; i++) {
+ guiElementTextFields.get(yIndex)[i].keyTyped(typedChar, keyCode);
+ if(guiElementTextFields.get(yIndex)[i].getFocus()) {
+ int addOffset = 0;
+ if(keyCode == Keyboard.KEY_UP) {
+ addOffset -= 1;
+ } else if(keyCode == Keyboard.KEY_DOWN) {
+ addOffset += 1;
+ }
+
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.remove(yIndex);
+ if(yIndex+addOffset < 0) {
+ addOffset = -yIndex;
+ } else if(yIndex+addOffset > NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.size()) {
+ addOffset = NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.size()-yIndex;
+ }
+ System.out.println(addOffset);
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.add(yIndex+addOffset,
+ getEnchantOpString(guiElementTextFields.get(yIndex), comparators.get(yIndex)));
+ NotEnoughUpdates.INSTANCE.manager.saveConfig();
+ if(addOffset != 0) {
+ GuiElementTextField[] guiElementTextFieldArray = guiElementTextFields.remove(yIndex);
+ guiElementTextFields.add(yIndex+addOffset, guiElementTextFieldArray);
+ }
+ return;
+ }
+ }
+ }
+ }
+
+ public String getEnchantOpString(GuiElementTextField[] tfs, String comparator) {
+ StringBuilder enchantOp = new StringBuilder();
+ enchantOp.append(tfs[0].getText());
+ enchantOp.append(":");
+ enchantOp.append(comparator);
+ enchantOp.append(":");
+ enchantOp.append(tfs[1].getText());
+ enchantOp.append(":");
+ enchantOp.append(tfs[2].getText());
+ return enchantOp.toString();
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+ for(int yIndex=0; yIndex<guiElementTextFields.size(); yIndex++) {
+ for(int i=0; i<3; i++) {
+ int x = guiLeft+10;
+ if(i == 1) x+=86;
+ else if(i == 2) x+=111;
+
+ if(mouseX > x && mouseX < x+guiElementTextFields.get(yIndex)[i].getWidth()) {
+ if(mouseY > guiTop+23+25*yIndex && mouseY < guiTop+23+25*yIndex+20) {
+ guiElementTextFields.get(yIndex)[i].mouseClicked(mouseX, mouseY, mouseButton);
+ if(mouseButton == 1) {
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.remove(yIndex);
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.add(yIndex,
+ getEnchantOpString(guiElementTextFields.get(yIndex), comparators.get(yIndex)));
+ NotEnoughUpdates.INSTANCE.manager.saveConfig();
+ }
+ continue;
+ }
+ }
+ guiElementTextFields.get(yIndex)[i].otherComponentClick();
+ }
+ comparators.computeIfAbsent(yIndex, k->">");
+ if(mouseY > guiTop+23+25*yIndex && mouseY < guiTop+23+25*yIndex+20) {
+ if(mouseX > guiLeft+71 && mouseX < guiLeft+71+20) {
+ switch (comparators.get(yIndex)) {
+ case ">":
+ comparators.put(yIndex, "="); break;
+ case "=":
+ comparators.put(yIndex, "<"); break;
+ default:
+ comparators.put(yIndex, ">"); break;
+ }
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.remove(yIndex);
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.add(yIndex,
+ getEnchantOpString(guiElementTextFields.get(yIndex), comparators.get(yIndex)));
+ NotEnoughUpdates.INSTANCE.manager.saveConfig();
+ } else if(mouseX > guiLeft+146 && mouseX < guiLeft+146+20) {
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.remove(yIndex);
+ guiElementTextFields.remove(yIndex);
+ comparators.remove(yIndex);
+ NotEnoughUpdates.INSTANCE.manager.saveConfig();
+ }
+ }
+ }
+ if(mouseX >= guiLeft+42 && mouseX <= guiLeft+42+88) {
+ if(mouseY >= guiTop+ySize-30 && mouseY <= guiTop+ySize-10) {
+ NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value.add("[a-zA-Z ]+:>:5:9");
+ NotEnoughUpdates.INSTANCE.manager.saveConfig();
+ }
+ }
+ }
+
+ public static String getColourOpIndex(List<String> colourOps, int index) {
+ if(colourOps.size() > index) {
+ return colourOps.get(index);
+ } else {
+ switch(index) {
+ case 0:
+ return "[a-zA-Z ]+";
+ case 1:
+ return ">";
+ case 2:
+ return "5";
+ case 3:
+ return "9";
+ }
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java
index 200569df..c4040f60 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java
@@ -37,10 +37,10 @@ public class GuiItemRecipe extends GuiScreen {
private String title;
private NEUManager manager;
- private int guiLeft = 0;
- private int guiTop = 0;
- private int xSize = 176;
- private int ySize = 166;
+ public int guiLeft = 0;
+ public int guiTop = 0;
+ public int xSize = 176;
+ public int ySize = 166;
public GuiItemRecipe(String title, List<ItemStack[]> craftMatrices, List<JsonObject> results, NEUManager manager) {
this.craftMatrices = craftMatrices;
@@ -170,7 +170,7 @@ public class GuiItemRecipe extends GuiScreen {
@Override
public void handleKeyboardInput() throws IOException {
- super.handleKeyboardInput(); //TODO: r and u
+ super.handleKeyboardInput();
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/HelpGUI.java b/src/main/java/io/github/moulberry/notenoughupdates/HelpGUI.java
new file mode 100644
index 00000000..1049dc55
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/HelpGUI.java
@@ -0,0 +1,189 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+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.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.util.vector.Vector2f;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class HelpGUI extends GuiScreen {
+
+ private int guiLeft = 0;
+ private int guiTop = 0;
+ private int sizeX = 0;
+ private int sizeY = 0;
+
+ private int page = 0;
+ private ResourceLocation screenshotBorder = new ResourceLocation("notenoughupdates:ss_border.jpg");
+ private ResourceLocation[] screenshots = null;
+
+ int scaleFactor = 0;
+
+ @Override
+ public void setWorldAndResolution(Minecraft mc, int width, int height) {
+ super.setWorldAndResolution(mc, width, height);
+
+ screenshots = new ResourceLocation[18];
+ for(int i=0; i<=17; i++) {
+ screenshots[i] = new ResourceLocation("notenoughupdates:ss_small/ss"+(i+1)+"-0.jpg");
+ }
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ Keyboard.enableRepeatEvents(true);
+ super.keyTyped(typedChar, keyCode);
+ if(keyCode == Keyboard.KEY_LEFT) {
+ page--;
+ } else if(keyCode == Keyboard.KEY_RIGHT) {
+ page++;
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ super.drawScreen(mouseX, mouseY, partialTicks);
+
+ drawDefaultBackground();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ scaleFactor = scaledResolution.getScaleFactor();
+
+ sizeX = width/2+40/scaleFactor;
+ sizeY = height/2+40/scaleFactor;
+ guiLeft = width/4-20/scaleFactor;
+ guiTop = height/4-20/scaleFactor;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(screenshotBorder);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY);
+
+ page = Math.max(0, Math.min(17, page));
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(screenshots[page]);
+ Utils.drawTexturedRect(guiLeft+20f/scaleFactor, guiTop+20f/scaleFactor, sizeX-40f/scaleFactor, sizeY-40f/scaleFactor);
+
+ Utils.drawStringCentered(EnumChatFormatting.GOLD+"NEU Tutorial - Page "+(page+1)+"/18 - Use arrow keys", Minecraft.getMinecraft().fontRendererObj,
+ width/2, guiTop+8, true, 0);
+ if(scaleFactor != 2) Utils.drawStringCentered(EnumChatFormatting.GOLD+"Use GUI Scale normal for better reading experience", Minecraft.getMinecraft().fontRendererObj,
+ width/2, guiTop+18, true, 0);
+
+ for(Map.Entry<Vector2f, List<String>> entry : texts[page].entrySet()) {
+ Vector2f location = entry.getKey();
+ List<String> text = entry.getValue();
+
+ float x = guiLeft+20f/scaleFactor+(sizeX-40f/scaleFactor)*location.x;
+ float y = guiTop+20f/scaleFactor+(sizeY-40f/scaleFactor)*location.y;
+
+ Utils.drawHoveringText(text, (int)x, (int)y+12, 100000, 100000, 200, Minecraft.getMinecraft().fontRendererObj);
+ }
+ }
+
+
+ private static HashMap<Vector2f, List<String>>[] texts = new HashMap[18];
+ static {
+ for(int i=0; i<18; i++) {
+ texts[i] = new HashMap<>();
+ }
+ texts[0].put(new Vector2f(0.73f, 0.60f), Utils.createList(
+ EnumChatFormatting.GOLD+"Itemlist",
+ EnumChatFormatting.GRAY+"Here you will find a list of (most) skyblock items",
+ EnumChatFormatting.GRAY+"The itemlist can be accessed by opening your inventory or most menus while on skyblock"));
+ texts[1].put(new Vector2f(0.73f, 0.16f), Utils.createList(
+ EnumChatFormatting.GOLD+"Itemlist",
+ EnumChatFormatting.GRAY+"These are the page controls for the itemlist",
+ EnumChatFormatting.GRAY+"Clicking these controls will bring you to other pages of the itemlist"));
+ texts[2].put(new Vector2f(0.73f, 1.05f), Utils.createList(
+ EnumChatFormatting.GOLD+"Itemlist",
+ EnumChatFormatting.GRAY+"These are the sorting controls for the itemlist",
+ EnumChatFormatting.GRAY+"The buttons on the left control the ordering of the items",
+ EnumChatFormatting.GRAY+"The buttons on the right can be used to filter a certain type of item"));
+ texts[3].put(new Vector2f(0.39f, 1.04f), Utils.createList(
+ EnumChatFormatting.GOLD+"Itemlist",
+ EnumChatFormatting.GRAY+"This is the search bar for the itemlist",
+ EnumChatFormatting.GRAY+"Double-click the bar to enable inventory search mode",
+ EnumChatFormatting.GRAY+"The button on the left opens up the mod settings",
+ EnumChatFormatting.GRAY+"The button on the right displays this tutorial"));
+ texts[4].put(new Vector2f(0.39f, 0.99f), Utils.createList(
+ EnumChatFormatting.GOLD+"QuickCommands",
+ EnumChatFormatting.GRAY+"These are the QuickCommands",
+ EnumChatFormatting.GRAY+"They let you warp around or access certain menus more easily"));
+ texts[5].put(new Vector2f(0.7f, 0.71f), Utils.createList(
+ EnumChatFormatting.GOLD+"Itemlist",
+ EnumChatFormatting.GRAY+"Hover over an item in the list to display it's lore",
+ EnumChatFormatting.GRAY+"Left clicking some items will display the recipe for that item",
+ EnumChatFormatting.GRAY+"Right clicking some items will display a wiki page for that item",
+ EnumChatFormatting.GRAY+"'F' will favourite an item, putting it to the top of the itemlist"));
+ texts[6].put(new Vector2f(0.17f, 0.21f), Utils.createList(
+ EnumChatFormatting.GOLD+"Collection Log",
+ EnumChatFormatting.GRAY+"This is the collection log. It can be accessed using the /neucl command, or via the QuickCommand",
+ EnumChatFormatting.GRAY+"The collection log keeps track of all items that enter your inventory while you are playing skyblock",
+ EnumChatFormatting.GRAY+"If you are a completionist, this feature is for you"));
+ texts[7].put(new Vector2f(0.05f, 0.13f), Utils.createList(
+ EnumChatFormatting.GOLD+"Collection Log",
+ EnumChatFormatting.GRAY+"Clicking on 'Filter' will change the items that",
+ EnumChatFormatting.GRAY+"appear in the list"));
+ texts[8].put(new Vector2f(0.35f, 0.74f), Utils.createList(
+ EnumChatFormatting.GOLD+"NeuAH",
+ EnumChatFormatting.GRAY+"This is the NEU Auction House (NeuAH)",
+ EnumChatFormatting.GRAY+"This AH can be accessed from anywhere using the /neuah command, or via the QuickCommand",
+ EnumChatFormatting.GRAY+"The items here refresh automatically, so there is no need to close the GUI to see the latest auctions",
+ EnumChatFormatting.GRAY+"Sometimes, you might have to wait until the list is populated with items from the API"));
+ texts[9].put(new Vector2f(0.41f, 0.40f), Utils.createList(
+ EnumChatFormatting.GOLD+"NeuAH",
+ EnumChatFormatting.GRAY+"These tabs control the items that appear in NeuAH",
+ EnumChatFormatting.GRAY+"You can find the main categories on the top of the GUI and subcategories appear on the side of the GUI once a main category is selected"));
+ texts[10].put(new Vector2f(0.57f, 0.38f), Utils.createList(
+ EnumChatFormatting.GOLD+"NeuAH",
+ EnumChatFormatting.GRAY+"Search for items using the search bar at the top",
+ EnumChatFormatting.GRAY+"Boolean operators such as &, | or ! work here."));
+ texts[10].put(new Vector2f(0.40f, 0.72f), Utils.createList(
+ EnumChatFormatting.GOLD+"NeuAH",
+ EnumChatFormatting.GRAY+"This toolbar contains many useful features",
+ EnumChatFormatting.GRAY+"which control the sorting and ordering of",
+ EnumChatFormatting.GRAY+"the auction house, similar to the normal AH"));
+ texts[11].put(new Vector2f(0.55f, 0.72f), Utils.createList(
+ EnumChatFormatting.GOLD+"NeuAH",
+ EnumChatFormatting.GRAY+"Clicking on an item will bring up the auction view",
+ EnumChatFormatting.GRAY+"Here you can viewer the buyer/seller and place bids or make purchases",
+ EnumChatFormatting.GRAY+"Trying to purchase an item will result in a confirmation GUI similar to the normal AH"));
+ texts[12].put(new Vector2f(0.28f, 0.82f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"Access the profile viewer using /neuprofile (ign) or /pv (ign)",
+ EnumChatFormatting.GRAY+"This is the main page of the profile viewer",
+ EnumChatFormatting.GRAY+"This page contains basic information like stats and skill levels"));
+ texts[12].put(new Vector2f(0.72f, 0.55f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"Click the button on the left to switch profiles and use the bar on the right to switch players"));
+ texts[13].put(new Vector2f(0.28f, 0.82f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"This is the extra info page of the profile viewer",
+ EnumChatFormatting.GRAY+"This page contains all the small bits of information about a player that don't fit anywhere else"));
+ texts[14].put(new Vector2f(0.28f, 0.82f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"This is the inventories page of the profile viewer",
+ EnumChatFormatting.GRAY+"Click on the inventory icons in the top-left or use your keyboard to switch the inventory type",
+ EnumChatFormatting.GRAY+"The bar on the bottom-left searches the current inventory for matching items"));
+ texts[15].put(new Vector2f(0.28f, 0.82f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"This is the collections page of the profile viewer",
+ EnumChatFormatting.GRAY+"Click on the icons on the left or use the keyboard shortcut to switch collection type"));
+ texts[16].put(new Vector2f(0.28f, 0.82f), Utils.createList(
+ EnumChatFormatting.GOLD+"Profile Viewer",
+ EnumChatFormatting.GRAY+"This is the pets page of the profile viewer",
+ EnumChatFormatting.GRAY+"Click to select the pet on the left",
+ EnumChatFormatting.GRAY+"The selected pet's stats will display on the right"));
+ texts[17].put(new Vector2f(0.27f, 0.40f), Utils.createList(
+ EnumChatFormatting.GOLD+"Overlay",
+ EnumChatFormatting.GRAY+"Rearrange certain GUI elements of the main overlay using /neuoverlay",
+ EnumChatFormatting.GRAY+"If you accidentally move them off screen, use the button in the top left to reset the GUI"));
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/ItemRarityHalo.java b/src/main/java/io/github/moulberry/notenoughupdates/ItemRarityHalo.java
new file mode 100644
index 00000000..2c70ec1e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/ItemRarityHalo.java
@@ -0,0 +1,251 @@
+package io.github.moulberry.notenoughupdates;
+
+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.entity.RenderItem;
+import net.minecraft.client.renderer.texture.TextureUtil;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.Matrix4f;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.opengl.GL45;
+
+import java.awt.*;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+
+public class ItemRarityHalo {
+
+ public static Framebuffer itemFramebuffer1 = null;
+ public static Framebuffer itemFramebuffer2 = null;
+ public static HashMap<ItemStack, Integer> itemHaloTexMap = new HashMap<>();
+ public static Matrix4f projectionMatrix = null;
+
+ public static Shader colourShader = null;
+ public static Shader blurShaderHorz = null;
+ public static Shader blurShaderVert = null;
+
+ private static int oldScaledResolution = 0;
+
+ public static void onItemRender(ItemStack stack, int x, int y) {
+ if(x == 0 && y == 0) return;
+
+ if(!OpenGlHelper.isFramebufferEnabled() || !OpenGlHelper.areShadersSupported()) return;
+ NotEnoughUpdates neu = NotEnoughUpdates.INSTANCE;
+ if(!neu.isOnSkyblock()) return;
+ if(neu.manager.config.itemHighlightOpacity.value <= 1) return;
+ if(neu.manager.getInternalNameForItem(stack) == null) return;
+
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int size = 16*scaledresolution.getScaleFactor();
+
+ if(projectionMatrix == null) {
+ projectionMatrix = Utils.createProjectionMatrix(size, size);
+ }
+
+ itemFramebuffer1 = checkFramebufferSizes(itemFramebuffer1, size, size);
+ itemFramebuffer2 = checkFramebufferSizes(itemFramebuffer2, size, size);
+
+ try {
+ if(colourShader == null) {
+ colourShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
+ "setrgbtoalpha", itemFramebuffer1, itemFramebuffer2);
+ upload(colourShader, size, size);
+ }
+
+ if(blurShaderHorz == null) {
+ blurShaderHorz = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
+ "blur", itemFramebuffer2, itemFramebuffer1);
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.getShaderManager().getShaderUniform("Radius").set(5f);
+ blurShaderHorz.getShaderManager().getShaderUniform("AlphaMult").set(2f);
+ upload(blurShaderHorz, size, size);
+ }
+
+ if(blurShaderVert == null) {
+ blurShaderVert = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
+ "blur", itemFramebuffer1, itemFramebuffer2);
+ blurShaderVert.getShaderManager().getShaderUniform("BlurDir").set(0, 1);
+ blurShaderVert.getShaderManager().getShaderUniform("Radius").set(5f);
+ blurShaderVert.getShaderManager().getShaderUniform("AlphaMult").set(2f);
+ upload(blurShaderVert, size, size);
+ }
+ } catch(Exception e) { return; }
+
+ if(oldScaledResolution != scaledresolution.getScaleFactor()) {
+ resetItemHaloCache();
+ oldScaledResolution = scaledresolution.getScaleFactor();
+ }
+
+ int currentBuffer = GL11.glGetInteger(GL30.GL_FRAMEBUFFER_BINDING);
+ IntBuffer currentViewport = BufferUtils.createIntBuffer(16);
+ GL11.glGetInteger(GL11.GL_VIEWPORT, currentViewport);
+ try {
+ if(!itemHaloTexMap.containsKey(stack)) {
+ int texture1 = TextureUtil.glGenTextures();
+ int texture2 = TextureUtil.glGenTextures();
+
+ GlStateManager.bindTexture(texture1);
+ GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, ((ByteBuffer)null));
+ itemFramebuffer1.bindFramebuffer(false);
+ OpenGlHelper.glFramebufferTexture2D(OpenGlHelper.GL_FRAMEBUFFER, OpenGlHelper.GL_COLOR_ATTACHMENT0, 3553, texture1, 0);
+
+ GlStateManager.bindTexture(texture2);
+ GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, size, size, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, ((ByteBuffer)null));
+ itemFramebuffer2.bindFramebuffer(false);
+ OpenGlHelper.glFramebufferTexture2D(OpenGlHelper.GL_FRAMEBUFFER, OpenGlHelper.GL_COLOR_ATTACHMENT0, 3553, texture2, 0);
+
+ itemFramebuffer1.framebufferClear();
+ itemFramebuffer2.framebufferClear();
+
+ GlStateManager.pushMatrix(); {
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, size, size, 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ GL11.glScalef(scaledresolution.getScaleFactor(), scaledresolution.getScaleFactor(), 1);
+
+ itemFramebuffer1.bindFramebuffer(true);
+
+ RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
+ RenderHelper.enableGUIStandardItemLighting();
+ float zLevel = itemRender.zLevel;
+ itemRender.zLevel = -145; //Negates the z-offset of the below method.
+ itemRender.renderItemAndEffectIntoGUI(stack, 0, 0);
+ itemRender.zLevel = zLevel;
+ RenderHelper.disableStandardItemLighting();
+ } GlStateManager.popMatrix();
+
+ GlStateManager.pushMatrix(); {
+ GL45.glTextureBarrier(); GL11.glFlush(); GL11.glFinish();
+ executeShader(colourShader);
+ //GL45.glTextureBarrier(); GL11.glFlush(); GL11.glFinish();
+ //executeShader(blurShaderHorz);
+ //GL45.glTextureBarrier(); GL11.glFlush(); GL11.glFinish();
+ //executeShader(blurShaderVert);
+ //GL45.glTextureBarrier(); GL11.glFlush(); GL11.glFinish();
+ } GlStateManager.popMatrix();
+
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, scaledresolution.getScaledWidth_double(), scaledresolution.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(5888);
+
+ OpenGlHelper.glBindFramebuffer(OpenGlHelper.GL_FRAMEBUFFER, currentBuffer);
+ GlStateManager.viewport(currentViewport.get(), currentViewport.get(), currentViewport.get(), currentViewport.get());
+
+ //TextureUtil.deleteTexture(texture1);
+ itemHaloTexMap.put(stack, texture2);
+ }
+
+ OpenGlHelper.glBindFramebuffer(OpenGlHelper.GL_FRAMEBUFFER, currentBuffer);
+ GlStateManager.viewport(currentViewport.get(), currentViewport.get(), currentViewport.get(), currentViewport.get());
+
+ GlStateManager.bindTexture(itemHaloTexMap.get(stack));
+ Color color = Utils.getPrimaryColour(stack.getDisplayName());
+ GlStateManager.color(color.getRed()/255f, color.getGreen()/255f, color.getBlue()/255f,
+ NotEnoughUpdates.INSTANCE.manager.config.itemHighlightOpacity.value.floatValue()/255f);
+ Utils.drawTexturedRect(x, y, 16, 16,
+ 0, 1, 1, 0, GL11.GL_NEAREST);
+ GlStateManager.bindTexture(0);
+ } catch(Exception e) {
+ e.printStackTrace();
+ OpenGlHelper.glBindFramebuffer(OpenGlHelper.GL_FRAMEBUFFER, currentBuffer);
+ GlStateManager.viewport(currentViewport.get(), currentViewport.get(), currentViewport.get(), currentViewport.get());
+ }
+ }
+
+ private static Framebuffer checkFramebufferSizes(Framebuffer framebuffer, int width, int height) {
+ if(framebuffer == null || framebuffer.framebufferWidth != width || framebuffer.framebufferHeight != height) {
+ if(framebuffer == null) {
+ framebuffer = new Framebuffer(width, height, true);
+ } else {
+ framebuffer.createBindFramebuffer(width, height);
+ }
+ framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ return framebuffer;
+ }
+
+ public static void resetItemHaloCache() {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int size = 16*scaledresolution.getScaleFactor();
+
+ for(int tex : itemHaloTexMap.values()) {
+ TextureUtil.deleteTexture(tex);
+ }
+ itemHaloTexMap.clear();
+
+ if(NotEnoughUpdates.INSTANCE.isOnSkyblock()) {
+ projectionMatrix = Utils.createProjectionMatrix(size, size);
+ upload(colourShader, size, size);
+ upload(blurShaderHorz, size, size);
+ upload(blurShaderVert, size, size);
+ }
+ }
+
+ private static void upload(Shader shader, int width, int height) {
+ if(shader == null) return;
+ shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix);
+ shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width, height);
+ shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height);
+ shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float)width, (float)height);
+ }
+
+ private static void executeShader(Shader shader) {
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.disableBlend();
+ GlStateManager.disableDepth();
+ GlStateManager.disableAlpha();
+ GlStateManager.disableFog();
+ GlStateManager.disableLighting();
+ GlStateManager.disableColorMaterial();
+ GlStateManager.enableTexture2D();
+ GlStateManager.bindTexture(0);
+
+ float f = (float)shader.framebufferOut.framebufferTextureWidth;
+ float f1 = (float)shader.framebufferOut.framebufferTextureHeight;
+ GlStateManager.viewport(0, 0, (int)f, (int)f1);
+
+ shader.getShaderManager().useShader();
+ shader.getShaderManager().addSamplerTexture("DiffuseSampler", shader.framebufferIn);
+
+ shader.framebufferOut.framebufferClear();
+ shader.framebufferOut.bindFramebuffer(false);
+
+ GlStateManager.depthMask(false);
+
+ GlStateManager.enableAlpha();
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+ worldrenderer.pos(0.0D, (double)f1, 500.0D).color(255, 255, 255, 255).endVertex();
+ worldrenderer.pos((double)f, (double)f1, 500.0D).color(255, 255, 255, 255).endVertex();
+ worldrenderer.pos((double)f, 0.0D, 500.0D).color(255, 255, 255, 255).endVertex();
+ worldrenderer.pos(0.0D, 0.0D, 500.0D).color(255, 255, 255, 255).endVertex();
+ tessellator.draw();
+
+ GlStateManager.depthMask(true);
+
+ shader.getShaderManager().endShader();
+
+ shader.framebufferOut.unbindFramebuffer();
+ shader.framebufferIn.unbindFramebufferTexture();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
index b9f086a4..f272ee29 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
@@ -63,6 +63,19 @@ public class NEUIO {
}
}
+ public String getLatestCommit() {
+ try {
+ GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
+ GHRepository repo = github.getRepositoryById("247692460");
+ for(GHCommit commit : repo.listCommits()) {
+ return commit.getSHA1();
+ }
+ } catch(IOException e) {
+ return null;
+ }
+ return "";
+ }
+
/**
* @param oldShas Map from filename (eg. BOW.json) to the sha in the local repository
* @return Map from filename to the new shas
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 8d625c14..3a84dc5c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -10,6 +10,7 @@ import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.*;
@@ -21,8 +22,11 @@ import org.lwjgl.opengl.Display;
import javax.swing.*;
import java.io.*;
import java.net.URL;
+import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -224,24 +228,29 @@ public class NEUManager {
/**
* Downloads and sets auctionPricesJson from the URL specified by AUCTIONS_PRICE_URL.
*/
+ private ExecutorService es = Executors.newCachedThreadPool();
public void updatePrices() {
if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*120) { //2 hours
craftCost.clear();
- System.out.println("UPDATING PRICE INFORMATION");
+ System.out.println("[NEU] UPDATING PRICE INFORMATION");
auctionLastUpdate = System.currentTimeMillis();
- try(Reader inReader = new InputStreamReader(new GZIPInputStream(new URL(AUCTIONS_PRICE_URL).openStream()))) {
- auctionPricesJson = gson.fromJson(inReader, JsonObject.class);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ es.submit(() -> {
+ try(Reader inReader = new InputStreamReader(new GZIPInputStream(new URL(AUCTIONS_PRICE_URL).openStream()))) {
+ auctionPricesJson = gson.fromJson(inReader, JsonObject.class);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
}
}
public boolean hasAuctionInfo(String internalname) {
+ if(auctionPricesJson == null) return false;
return auctionPricesJson.has("item_data") && auctionPricesJson.get("item_data").getAsJsonObject().has(internalname);
}
public boolean hasBazaarInfo(String internalname) {
+ if(auctionPricesJson == null) return false;
return auctionPricesJson.has("bazaar") && auctionPricesJson.get("bazaar").getAsJsonObject().has(internalname);
}
@@ -274,7 +283,7 @@ public class NEUManager {
if(info == null || !info.has("price")) {
return 0;
}
- if(!auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) {
+ if(auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) {
return 0;
}
JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices");
@@ -349,7 +358,7 @@ public class NEUManager {
BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
JsonObject json = gson.fromJson(reader, JsonObject.class);
return json;
- } catch(Exception e) { return null; }
+ } catch(Exception e) { e.printStackTrace(); return null; }
}
/**
@@ -358,121 +367,168 @@ public class NEUManager {
* repository.
*/
public void loadItemInformation() {
- try {
- if(config.autoupdate.value) {
- JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
- JDialog dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
- dialog.setModal(false);
- //dialog.setVisible(true);
-
- if (Display.isActive()) dialog.toFront();
-
- HashMap<String, String> oldShas = new HashMap<>();
- for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) {
- if (new File(repoLocation, entry.getKey() + ".json").exists()) {
- oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString());
- }
- }
- Map<String, String> changedFiles = neuio.getChangedItems(oldShas);
+ Thread thread = new Thread(() -> {
+ JDialog dialog = null;
+ try {
+ if(config.autoupdate.value) {
+ JOptionPane pane = new JOptionPane("Getting items to download from remote repository.");
+ dialog = pane.createDialog("NotEnoughUpdates Remote Sync");
+ dialog.setModal(false);
+ if(config.dev.value) dialog.setVisible(true);
- if (changedFiles != null) {
- for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) {
- itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5),
- changedFile.getValue());
+ if (Display.isActive()) dialog.toFront();
+
+ String latestCommit = neuio.getLatestCommit();
+ if(latestCommit == null || latestCommit.isEmpty()) return;
+
+ JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json"));
+ if(currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestCommit)) {
+ JsonObject newCurrentCommitJSON = new JsonObject();
+ newCurrentCommitJSON.addProperty("sha", latestCommit);
+ try {
+ writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json"));
+ } catch (IOException e) {
+ }
+ } else {
+ dialog.setVisible(false);
+ return;
}
- try {
- writeJson(itemShaConfig, itemShaLocation);
- } catch (IOException e) {
+
+ HashMap<String, String> oldShas = new HashMap<>();
+ for (Map.Entry<String, JsonElement> entry : itemShaConfig.entrySet()) {
+ if (new File(repoLocation, entry.getKey() + ".json").exists()) {
+ oldShas.put(entry.getKey() + ".json", entry.getValue().getAsString());
+ }
}
- }
+ Map<String, String> changedFiles = neuio.getChangedItems(oldShas);
- if (Display.isActive()) dialog.toFront();
+ if (Display.isActive()) dialog.toFront();
- if (changedFiles != null && changedFiles.size() <= 20) {
+ if (changedFiles != null && changedFiles.size() <= 20) {
+ String startMessage = "NotEnoughUpdates: Syncing with remote repository (";
+ int downloaded = 0;
- String startMessage = "NotEnoughUpdates: Syncing with remote repository (";
- int downloaded = 0;
+ String dlUrl = "https://raw.githubusercontent.com/Moulberry/NotEnoughUpdates-REPO/master/";
+
+ for (String name : changedFiles.keySet()) {
+ pane.setMessage(startMessage + (++downloaded) + "/" + changedFiles.size() + ")\nCurrent: " + name);
+ dialog.pack();
+ if(config.dev.value) dialog.setVisible(true);
+ if (Display.isActive()) dialog.toFront();
+
+ File item = new File(repoLocation, name);
+ try {
+ item.getParentFile().mkdirs();
+ item.createNewFile();
+ } catch (IOException e) {
+ continue;
+ }
+ URL url = new URL(dlUrl+name);
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setConnectTimeout(3000);
+ urlConnection.setReadTimeout(3000);
+ try (BufferedInputStream inStream = new BufferedInputStream(urlConnection.getInputStream());
+ FileOutputStream fileOutputStream = new FileOutputStream(item)) {
+ byte dataBuffer[] = new byte[1024];
+ int bytesRead;
+ while ((bytesRead = inStream.read(dataBuffer, 0, 1024)) != -1) {
+ fileOutputStream.write(dataBuffer, 0, bytesRead);
+ }
+ itemShaConfig.addProperty(name.substring(0, name.length() - 5),
+ changedFiles.get(name));
+ } catch (IOException e) {
+ }
+ }
+ try {
+ writeJson(itemShaConfig, itemShaLocation);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ } else {
+ Utils.recursiveDelete(repoLocation);
+ repoLocation.mkdirs();
- String dlUrl = "https://raw.githubusercontent.com/Moulberry/NotEnoughUpdates-REPO/master/";
+ //TODO: Store hard-coded value somewhere else
+ String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
- for (String name : changedFiles.keySet()) {
- pane.setMessage(startMessage + (++downloaded) + "/" + changedFiles.size() + ")\nCurrent: " + name);
+ pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
dialog.pack();
- dialog.setVisible(true);
+ if(config.dev.value) dialog.setVisible(true);
if (Display.isActive()) dialog.toFront();
- File item = new File(repoLocation, name);
+ File itemsZip = new File(repoLocation, "neu-items-master.zip");
try {
- item.createNewFile();
+ itemsZip.createNewFile();
} catch (IOException e) {
+ return;
}
- try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl+name).openStream());
- FileOutputStream fileOutputStream = new FileOutputStream(item)) {
+ URL url = new URL(dlUrl);
+ URLConnection urlConnection = url.openConnection();
+ urlConnection.setConnectTimeout(3000);
+ urlConnection.setReadTimeout(3000);
+ 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;
}
- }
- } else {
- Utils.recursiveDelete(repoLocation);
- repoLocation.mkdirs();
- //TODO: Store hard-coded value somewhere else
- String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
+ pane.setMessage("Unzipping NEU Master Archive.");
+ dialog.pack();
+ //dialog.setVisible(true);
+ if (Display.isActive()) dialog.toFront();
- pane.setMessage("Downloading NEU Master Archive. (DL# >20)");
- dialog.pack();
- dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
+ unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath());
- File itemsZip = new File(repoLocation, "neu-items-master.zip");
- try {
- itemsZip.createNewFile();
- } catch (IOException e) {
- }
- try (BufferedInputStream inStream = new BufferedInputStream(new URL(dlUrl).openStream());
- 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);
+ if (changedFiles != null) {
+ for (Map.Entry<String, String> changedFile : changedFiles.entrySet()) {
+ itemShaConfig.addProperty(changedFile.getKey().substring(0, changedFile.getKey().length() - 5),
+ changedFile.getValue());
+ }
+ try {
+ writeJson(itemShaConfig, itemShaLocation);
+ } catch (IOException e) {
+ }
}
- } catch (IOException e) {
- e.printStackTrace();
}
-
- pane.setMessage("Unzipping NEU Master Archive.");
- dialog.pack();
- dialog.setVisible(true);
- if (Display.isActive()) dialog.toFront();
-
- unzipIgnoreFirstFolder(itemsZip.getAbsolutePath(), repoLocation.getAbsolutePath());
}
-
- dialog.dispose();
+ } catch(Exception e) {
+ e.printStackTrace();
+ } finally {
+ if(dialog != null) dialog.dispose();
}
- } catch(Exception e) {}
-
- Set<String> currentlyInstalledItems = new HashSet<>();
- for(File f : new File(repoLocation, "items").listFiles()) {
- currentlyInstalledItems.add(f.getName().substring(0, f.getName().length()-5));
- }
- Set<String> removedItems;
- if(config.autoupdate.value) {
- removedItems = neuio.getRemovedItems(currentlyInstalledItems);
- } else {
- removedItems = new HashSet<>();
- }
- for(File f : new File(repoLocation, "items").listFiles()) {
- String internalname = f.getName().substring(0, f.getName().length()-5);
- if(!removedItems.contains(internalname)) {
- loadItem(internalname);
+ File items = new File(repoLocation, "items");
+ if(items.exists()) {
+ File[] itemFiles = new File(repoLocation, "items").listFiles();
+ if(itemFiles != null) {
+ for(File f : itemFiles) {
+ String internalname = f.getName().substring(0, f.getName().length()-5);
+ if(!getItemInformation().keySet().contains(internalname)) {
+ loadItem(internalname);
+ }
+ }
+ }
+ }
+ });
+
+ File items = new File(repoLocation, "items");
+ if(items.exists()) {
+ 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);
+ }
}
}
+
+ thread.start();
}
/**
@@ -810,6 +866,7 @@ public class NEUManager {
public JsonObject getJsonFromItemBytes(String item_bytes) {
try {
NBTTagCompound tag = CompressedStreamTools.readCompressed(new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes)));
+ //System.out.println(tag.toString());
return getJsonFromNBT(tag);
} catch(IOException e) {
return null;
@@ -873,7 +930,12 @@ public class NEUManager {
}
public JsonObject getJsonFromNBT(NBTTagCompound tag) {
- tag = tag.getTagList("i", 10).getCompoundTagAt(0);
+ return getJsonFromNBTEntry(tag.getTagList("i", 10).getCompoundTagAt(0));
+ }
+
+ public JsonObject getJsonFromNBTEntry(NBTTagCompound tag) {
+ if(tag.getKeySet().size() == 0) return null;
+
int id = tag.getShort("id");
int damage = tag.getShort("Damage");
int count = tag.getShort("Count");
@@ -882,6 +944,7 @@ public class NEUManager {
if(id == 141) id = 391; //for some reason hypixel thinks carrots have id 141
String internalname = getInternalnameFromNBT(tag);
+ if(internalname == null) return null;
NBTTagCompound display = tag.getCompoundTag("display");
String[] lore = getLoreFromNBT(tag);
@@ -896,15 +959,31 @@ public class NEUManager {
String clickcommand = "";
- //public JsonObject createItemJson(String internalname, String itemid, String displayname, String[] lore,
- // String crafttext, String infoType, String[] info,
- // String clickcommand, int damage, NBTTagCompound nbttag) {
JsonObject item = new JsonObject();
item.addProperty("internalname", internalname);
item.addProperty("itemid", itemid);
item.addProperty("displayname", displayname);
+ if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ byte[] bytes = null;
+ for(String key : ea.getKeySet()) {
+ if(key.endsWith("backpack_data") || key.equals("new_year_cake_bag_data")) {
+ bytes = ea.getByteArray(key);
+ break;
+ }
+ }
+ if(bytes != null) {
+ JsonArray bytesArr = new JsonArray();
+ for(byte b : bytes) {
+ bytesArr.add(new JsonPrimitive(b));
+ }
+ item.add("item_contents", bytesArr);
+ }
+ }
+
if(lore != null && lore.length > 0) {
JsonArray jsonLore = new JsonArray();
for (String line : lore) {
@@ -1060,8 +1139,6 @@ public class NEUManager {
}
if(craftMatrices.size() > 0) {
- Minecraft.getMinecraft().thePlayer.sendQueue.addToSendQueue(new C0DPacketCloseWindow(
- Minecraft.getMinecraft().thePlayer.openContainer.windowId));
Minecraft.getMinecraft().displayGuiScreen(new GuiItemRecipe("Item Usages", craftMatrices, results, this));
return true;
}
@@ -1335,11 +1412,134 @@ public class NEUManager {
return itemMap;
}
+ public String removeUnusedDecimal(double num) {
+ if(num % 1 == 0) {
+ return String.valueOf((int)num);
+ } else {
+ return String.valueOf(num);
+ }
+ }
+
+ public HashMap<String, String> getLoreReplacements(String petname, String tier, int level) {
+ JsonObject petnums = null;
+ if(petname != null && tier != null) {
+ petnums = Utils.getConstant("petnums");
+ }
+
+ HashMap<String, String> replacements = new HashMap<>();
+ if(level < 1) {
+ replacements.put("LVL", "1\u27A1100");
+ } else {
+ replacements.put("LVL", ""+level);
+ }
+ if(petnums != null) {
+ if(petnums.has(petname)) {
+ JsonObject petInfo = petnums.get(petname).getAsJsonObject();
+ if(petInfo.has(tier)) {
+ JsonObject petInfoTier = petInfo.get(tier).getAsJsonObject();
+ if(petInfoTier == null || !petInfoTier.has("1") || !petInfoTier.has("100")) {
+ return replacements;
+ }
+
+ JsonObject min = petInfoTier.get("1").getAsJsonObject();
+ JsonObject max = petInfoTier.get("100").getAsJsonObject();
+
+ if(level < 1) {
+ JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray();
+ JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray();
+ for(int i=0; i<otherNumsMax.size(); i++) {
+ replacements.put(""+i, removeUnusedDecimal(Math.floor(otherNumsMin.get(i).getAsFloat()*10)/10f)+
+ "\u27A1"+removeUnusedDecimal(Math.floor(otherNumsMax.get(i).getAsFloat()*10)/10f));
+ }
+
+ for(Map.Entry<String, JsonElement> entry : max.get("statNums").getAsJsonObject().entrySet()) {
+ int statMax = (int)Math.floor(entry.getValue().getAsFloat());
+ int statMin = (int)Math.floor(min.get("statNums").getAsJsonObject().get(entry.getKey()).getAsFloat());
+ String statStr = (statMin>0?"+":"")+statMin+"\u27A1"+statMax;
+ replacements.put(entry.getKey(), statStr);
+ }
+ } else {
+ float minMix = (100-level)/99f;
+ float maxMix = (level-1)/99f;
+
+ JsonArray otherNumsMin = min.get("otherNums").getAsJsonArray();
+ JsonArray otherNumsMax = max.get("otherNums").getAsJsonArray();
+ for(int i=0; i<otherNumsMax.size(); i++) {
+ float val = otherNumsMin.get(i).getAsFloat()*minMix + otherNumsMax.get(i).getAsFloat()*maxMix;
+ replacements.put(""+i, removeUnusedDecimal(Math.floor(val*10)/10f));
+ }
+
+ for(Map.Entry<String, JsonElement> entry : max.get("statNums").getAsJsonObject().entrySet()) {
+ 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);
+ replacements.put(entry.getKey(), statStr);
+ }
+ }
+ }
+ }
+ }
+
+ return replacements;
+ }
+
+ public HashMap<String, String> getLoreReplacements(NBTTagCompound tag, int level) {
+ String petname = null;
+ String tier = null;
+ if(tag != null && tag.hasKey("ExtraAttributes")) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if(ea.hasKey("petInfo")) {
+ String petInfoStr = ea.getString("petInfo");
+ JsonObject petInfo = gson.fromJson(petInfoStr, JsonObject.class);
+ petname = petInfo.get("type").getAsString();
+ tier = petInfo.get("tier").getAsString();
+ if(petInfo.has("heldItem")) {
+ String heldItem = petInfo.get("heldItem").getAsString();
+ if(heldItem.equals("PET_ITEM_TIER_BOOST")) {
+ switch(tier) {
+ case "COMMON":
+ tier = "UNCOMMON"; break;
+ case "UNCOMMON":
+ tier = "RARE"; break;
+ case "RARE":
+ tier = "EPIC"; break;
+ case "EPIC":
+ tier = "LEGENDARY"; break;
+ }
+ }
+ }
+ }
+ }
+ return getLoreReplacements(petname, tier, level);
+ }
+
+ public NBTTagList processLore(JsonArray lore, HashMap<String, String> replacements) {
+ NBTTagList nbtLore = new NBTTagList();
+ for(JsonElement line : lore) {
+ String lineStr = line.getAsString();
+ if(!lineStr.contains("Click to view recipes!") &&
+ !lineStr.contains("Click to view recipe!")) {
+ for(Map.Entry<String, String> entry : replacements.entrySet()) {
+ lineStr = lineStr.replace("{"+entry.getKey()+"}", entry.getValue());
+ }
+ nbtLore.appendTag(new NBTTagString(lineStr));
+ }
+ }
+ return nbtLore;
+ }
+
public ItemStack jsonToStack(JsonObject json) {
return jsonToStack(json, true);
}
public ItemStack jsonToStack(JsonObject json, boolean useCache) {
+ return jsonToStack(json, useCache, true);
+ }
+
+ public ItemStack jsonToStack(JsonObject json, boolean useCache, boolean useReplacements) {
+ if(json == null) return new ItemStack(Items.painting, 1, 10);
+
if(useCache && itemstackCache.containsKey(json.get("internalname").getAsString())) {
return itemstackCache.get(json.get("internalname").getAsString()).copy();
}
@@ -1363,24 +1563,27 @@ public class NEUManager {
NBTTagCompound tag = JsonToNBT.getTagFromJson(json.get("nbttag").getAsString());
stack.setTagCompound(tag);
} catch(NBTException e) {
- if(json.get("internalname").getAsString().equalsIgnoreCase("ROCK;0")) e.printStackTrace();
}
}
+ HashMap<String, String> replacements = new HashMap<>();
+
+ if(useReplacements) {
+ replacements = getLoreReplacements(stack.getTagCompound(), -1);
+
+ String displayname = json.get("displayname").getAsString();
+ for(Map.Entry<String, String> entry : replacements.entrySet()) {
+ displayname = displayname.replace("{"+entry.getKey()+"}", entry.getValue());
+ }
+ stack.setStackDisplayName(displayname);
+ }
+
if(json.has("lore")) {
NBTTagCompound display = new NBTTagCompound();
if(stack.getTagCompound() != null && stack.getTagCompound().hasKey("display")) {
display = stack.getTagCompound().getCompoundTag("display");
}
- NBTTagList lore = new NBTTagList();
- for(JsonElement line : json.get("lore").getAsJsonArray()) {
- String lineStr = line.getAsString();
- if(!lineStr.contains("Click to view recipes!") &&
- !lineStr.contains("Click to view recipe!")) {
- lore.appendTag(new NBTTagString(lineStr));
- }
- }
- display.setTag("Lore", lore);
+ display.setTag("Lore", processLore(json.get("lore").getAsJsonArray(), replacements));
NBTTagCompound tag = stack.getTagCompound() != null ? stack.getTagCompound() : new NBTTagCompound();
tag.setTag("display", display);
stack.setTagCompound(tag);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
index 23def271..0cb7a548 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -96,7 +96,6 @@ public class NEUOverlay extends Gui {
private JsonObject[] searchedItemsArr = null;
private boolean itemPaneOpen = false;
- private boolean hoveringItemPaneToggle = false;
private int page = 0;
@@ -310,8 +309,9 @@ public class NEUOverlay extends Gui {
@Override
public void mouseClick(float x, float y, int mouseX, int mouseY) {
if(Mouse.getEventButtonState()) {
- displayInformationPane(HTMLInfoPane.createFromWikiUrl(overlay, manager, "Help",
- "https://moulberry.github.io/files/neu_help.html"));
+ //displayInformationPane(HTMLInfoPane.createFromWikiUrl(overlay, manager, "Help",
+ // "https://moulberry.github.io/files/neu_help.html"));
+ Minecraft.getMinecraft().displayGuiScreen(new HelpGUI());
Utils.playPressSound();
}
}
@@ -1054,7 +1054,7 @@ public class NEUOverlay extends Gui {
} else if(getSortMode() == SORT_MODE_MOB) {
return internalname.matches(mobRegex);
} else if(getSortMode() == SORT_MODE_PET) {
- return internalname.matches(petRegex);
+ return internalname.matches(petRegex) && item.get("displayname").getAsString().contains("[");
} else if(getSortMode() == SORT_MODE_TOOL) {
return checkItemType(item.get("lore").getAsJsonArray(),
"SWORD", "BOW", "AXE", "PICKAXE", "FISHING ROD", "WAND", "SHOVEL", "HOE") >= 0;
@@ -1097,6 +1097,15 @@ public class NEUOverlay extends Gui {
case "ducttapedigger":
searchedItems.add(CustomItems.DUCTTAPE);
break;
+ case "thirtyvirus":
+ searchedItems.add(manager.getItemInformation().get("SPIKED_BAIT"));
+ break;
+ case "leocthl":
+ searchedItems.add(CustomItems.LEOCTHL);
+ break;
+ case "spinaxx":
+ searchedItems.add(CustomItems.SPINAXX);
+ break;
}
}
@@ -1480,16 +1489,16 @@ public class NEUOverlay extends Gui {
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 e) { }
}
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));
} catch(Exception e) { }
@@ -1633,21 +1642,16 @@ public class NEUOverlay extends Gui {
int rightSide = leftSide+paneWidth-getBoxPadding()-getItemBoxXPadding();
//Tab
- Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow);
- GlStateManager.color(1f, 1f, 1f, 0.3f);
- Utils.drawTexturedRect(width-itemPaneTabOffset.getValue(), height/2 - 50, 20, 100);
- GlStateManager.bindTexture(0);
+ if(!manager.config.disableItemTabOpen.value) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(itemPaneTabArrow);
+ GlStateManager.color(1f, 1f, 1f, 0.3f);
+ Utils.drawTexturedRect(width-itemPaneTabOffset.getValue(), height/2 - 50, 20, 100);
+ GlStateManager.bindTexture(0);
- if(mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 50
- && mouseY < height/2 + 50) {
- if(!hoveringItemPaneToggle) {
- if(!manager.config.disableItemTabOpen.value) {
- itemPaneOpen = !itemPaneOpen;
- }
- hoveringItemPaneToggle = true;
+ if(!itemPaneOpen && mouseX > width-itemPaneTabOffset.getValue() && mouseY > height/2 - 50
+ && mouseY < height/2 + 50) {
+ itemPaneOpen = true;
}
- } else {
- hoveringItemPaneToggle = false;
}
//Atomic reference used so that below lambda doesn't complain about non-effectively-final variable
@@ -1803,12 +1807,7 @@ public class NEUOverlay extends Gui {
//Render tooltip
JsonObject json = tooltipToDisplay.get();
if(json != null) {
- List<String> text = new ArrayList<>();
- text.add(json.get("displayname").getAsString());
- JsonArray lore = json.get("lore").getAsJsonArray();
- for(int i=0; i<lore.size(); i++) {
- text.add(lore.get(i).getAsString());
- }
+ List<String> text = manager.jsonToStack(json).getTooltip(Minecraft.getMinecraft().thePlayer, false);
String internalname = json.get("internalname").getAsString();
JsonObject auctionInfo = manager.getItemAuctionInfo(internalname);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
index 28ecbc8e..eb6357ae 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
@@ -4,9 +4,11 @@ import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroup;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating;
+import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector2f;
@@ -27,6 +29,14 @@ public class NEUOverlayPlacements extends GuiScreen {
super.drawScreen(mouseX, mouseY, partialTicks);
drawDefaultBackground();
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(icons);
+ GlStateManager.enableBlend();
+
+ GlStateManager.tryBlendFuncSeparate(775, 769, 1, 0);
+ GlStateManager.enableAlpha();
+ this.drawTexturedModalRect(width / 2 - 7, height / 2 - 7, 0, 0, 16, 16);
+
if(mouseX < 300 && mouseY < 300 && clickedElement != null) {
guiButton.yPosition = height - 5 - guiButton.height;
} else {
@@ -73,9 +83,14 @@ public class NEUOverlayPlacements extends GuiScreen {
new Color(200, 200, 200, 100).getRGB());
break;
case BOTMID:
+ case INV_BOTMID:
drawRect((int)position.x, (int)(position.y+element.getHeight()*0.9f),
(int)position.x+element.getWidth(), (int)position.y+element.getHeight(),
new Color(200, 200, 200, 100).getRGB());
+ if(anchorPoint.anchorPoint == MBAnchorPoint.AnchorPoint.INV_BOTMID) {
+ Utils.drawStringCentered("Inv-Relative", Minecraft.getMinecraft().fontRendererObj,
+ position.x+element.getWidth()*0.5f, position.y+element.getHeight()*0.5f, false, 0);
+ }
break;
case MIDMID:
drawRect((int)(position.x+element.getWidth()*0.45f), (int)(position.y+element.getHeight()*0.45f),
@@ -91,6 +106,7 @@ public class NEUOverlayPlacements extends GuiScreen {
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
MBGuiGroupFloating mainGroup = NotEnoughUpdates.INSTANCE.overlay.guiGroup;
+ int index=0;
for(MBGuiElement element : mainGroup.getChildren()) {
MBAnchorPoint anchorPoint = mainGroup.getChildrenMap().get(element);
Vector2f position = mainGroup.getChildrenPosition().get(element);
@@ -104,22 +120,27 @@ public class NEUOverlayPlacements extends GuiScreen {
clickedAnchorX = (int)anchorPoint.offset.x;
clickedAnchorY = (int)anchorPoint.offset.y;
} else {
- float anchorX = (width-element.getWidth()) * anchorPoint.anchorPoint.x + anchorPoint.offset.x;
- float anchorY = (height-element.getHeight()) * anchorPoint.anchorPoint.y + anchorPoint.offset.y;
-
MBAnchorPoint.AnchorPoint[] vals = MBAnchorPoint.AnchorPoint.values();
anchorPoint.anchorPoint = vals[(anchorPoint.anchorPoint.ordinal()+1)%vals.length];
- float screenX = (width-element.getWidth()) * anchorPoint.anchorPoint.x;
- float screenY = (height-element.getHeight()) * anchorPoint.anchorPoint.y;
- anchorPoint.offset.x = anchorX - screenX;
- anchorPoint.offset.y = anchorY - screenY;
+ mainGroup.recalculate();
+
+ anchorPoint.offset.x += position.x - mainGroup.getChildrenPosition().get(element).x;
+ anchorPoint.offset.y += position.y - mainGroup.getChildrenPosition().get(element).y;
mainGroup.recalculate();
+
+ if(index == 0) {
+ NotEnoughUpdates.INSTANCE.manager.config.overlaySearchBar.value = anchorPoint.toString();
+ } else if(index == 1) {
+ NotEnoughUpdates.INSTANCE.manager.config.overlayQuickCommand.value = anchorPoint.toString();
+ }
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
}
return;
}
}
+ index++;
}
if(guiButton.mousePressed(Minecraft.getMinecraft(), mouseX, mouseY)) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index a589fe2b..fbcd3de3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -11,18 +11,25 @@ import io.github.moulberry.notenoughupdates.commands.SimpleCommand;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane;
import io.github.moulberry.notenoughupdates.infopanes.CosmeticsInfoPane;
+import io.github.moulberry.notenoughupdates.mixins.MixinRenderItem;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
import io.github.moulberry.notenoughupdates.questing.GuiQuestLine;
-import io.github.moulberry.notenoughupdates.questing.NEUQuesting;
+import io.github.moulberry.notenoughupdates.questing.SBScoreboardData;
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.ScaledResolution;
import net.minecraft.client.gui.inventory.*;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.settings.KeyBinding;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
import net.minecraft.command.ICommandSender;
+import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.event.ClickEvent;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.ContainerChest;
@@ -33,15 +40,9 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.Scoreboard;
-import net.minecraft.util.ChatComponentText;
-import net.minecraft.util.ChatStyle;
-import net.minecraft.util.EnumChatFormatting;
-import net.minecraft.util.Session;
+import net.minecraft.util.*;
import net.minecraftforge.client.ClientCommandHandler;
-import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.client.event.GuiOpenEvent;
-import net.minecraftforge.client.event.GuiScreenEvent;
-import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.*;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
@@ -51,6 +52,7 @@ import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
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.StringUtils;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
@@ -63,17 +65,20 @@ import java.lang.reflect.Modifier;
import java.net.Proxy;
import java.text.NumberFormat;
import java.util.*;
+import java.util.List;
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.GuiTextures.*;
@Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION)
public class NotEnoughUpdates {
public static final String MODID = "notenoughupdates";
- public static final String VERSION = "REL-1.0.0";
+ public static final String VERSION = "1.1-REL";
public static NotEnoughUpdates INSTANCE = null;
@@ -129,12 +134,134 @@ public class NotEnoughUpdates {
}
});
+ SimpleCommand enchantColourCommand = new SimpleCommand("neuec", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ openGui = new GuiEnchantColour();
+ }
+ });
+
+ public static ProfileViewer profileViewer;
+
+ SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if (manager.config.apiKey.value == null || manager.config.apiKey.value.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) {
+ profileViewer.getProfileByName(Minecraft.getMinecraft().thePlayer.getName(), profile -> {
+ if (profile != null) profile.resetCache();
+ openGui = new GuiProfileViewer(profile);
+ });
+ } else if (args.length > 1) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "Too many arguments. Usage: /neuprofile [name]"));
+ } else {
+ profileViewer.getProfileByName(args[0], profile -> {
+ if (profile != null) profile.resetCache();
+ openGui = new GuiProfileViewer(profile);
+ });
+ }
+ }
+ };
+
+ SimpleCommand viewProfileCommand = new SimpleCommand("neuprofile", viewProfileRunnable, new SimpleCommand.TabCompleteRunnable() {
+ @Override
+ public List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos) {
+ if(args.length != 1) return null;
+
+ String lastArg = args[args.length-1];
+ List<String> playerMatches = new ArrayList<>();
+ for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
+ String playerName = player.getName();
+ if(playerName.toLowerCase().startsWith(lastArg.toLowerCase())) {
+ playerMatches.add(playerName);
+ }
+ }
+ return playerMatches;
+ }
+ });
+
+ SimpleCommand viewProfileShortCommand = new SimpleCommand("pv", new SimpleCommand.ProcessCommandRunnable() {
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(!hasSkyblockScoreboard()) {
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/pv " + StringUtils.join(args, " "));
+ } else {
+ viewProfileRunnable.processCommand(sender, args);
+ }
+ }
+ }, new SimpleCommand.TabCompleteRunnable() {
+ @Override
+ public List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos) {
+ if (args.length != 1) return null;
+
+ String lastArg = args[args.length - 1];
+ List<String> playerMatches = new ArrayList<>();
+ for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
+ String playerName = player.getName();
+ if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) {
+ playerMatches.add(playerName);
+ }
+ }
+ return playerMatches;
+ }
+ });
+
+ SimpleCommand viewProfileShort2Command = new SimpleCommand("vp", new SimpleCommand.ProcessCommandRunnable() {
+ @Override
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(!hasSkyblockScoreboard()) {
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/vp " + StringUtils.join(args, " "));
+ } else {
+ viewProfileRunnable.processCommand(sender, args);
+ }
+ }
+ }, new SimpleCommand.TabCompleteRunnable() {
+ @Override
+ public List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos) {
+ if (args.length != 1) return null;
+
+ String lastArg = args[args.length - 1];
+ List<String> playerMatches = new ArrayList<>();
+ for (EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
+ String playerName = player.getName();
+ if (playerName.toLowerCase().startsWith(lastArg.toLowerCase())) {
+ playerMatches.add(playerName);
+ }
+ }
+ return playerMatches;
+ }
+ });
+
+ SimpleCommand linksCommand = new SimpleCommand("neulinks", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ File repo = manager.repoLocation;
+ if(repo.exists()) {
+ File updateJson = new File(repo, "update.json");
+ try {
+ JsonObject update = manager.getJsonFromFile(updateJson);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ displayLinks(update);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ } catch (Exception ignored) {
+ }
+ }
+ }
+ });
+
SimpleCommand overlayPlacementsCommand = new SimpleCommand("neuoverlay", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
openGui = new NEUOverlayPlacements();
}
});
+ SimpleCommand tutorialCommand = new SimpleCommand("neututorial", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ openGui = new HelpGUI();
+ }
+ });
+
SimpleCommand cosmeticsCommand = new SimpleCommand("neucosmetics", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {
@@ -151,7 +278,7 @@ public class NotEnoughUpdates {
"You must be on Skyblock to use this feature."));
} else if(manager.config.apiKey.value == null || manager.config.apiKey.value.trim().isEmpty()) {
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+
- "Can't open NeuAH, Api Key is not set. Run /api new and put the result in settings."));
+ "Can't open NeuAH, apikey is not set. Run /api new and put the result in settings."));
} else {
openGui = new CustomAHGui();
manager.auctionManager.customAH.lastOpen = System.currentTimeMillis();
@@ -175,14 +302,20 @@ public class NotEnoughUpdates {
f.mkdirs();
ClientCommandHandler.instance.registerCommand(collectionLogCommand);
ClientCommandHandler.instance.registerCommand(cosmeticsCommand);
+ ClientCommandHandler.instance.registerCommand(linksCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileShortCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileShort2Command);
+ ClientCommandHandler.instance.registerCommand(tutorialCommand);
ClientCommandHandler.instance.registerCommand(overlayPlacementsCommand);
- //ClientCommandHandler.instance.registerCommand(questingCommand);
+ ClientCommandHandler.instance.registerCommand(enchantColourCommand);
ClientCommandHandler.instance.registerCommand(neuAhCommand);
neuio = new NEUIO(getAccessToken());
manager = new NEUManager(this, neuio, f);
manager.loadItemInformation();
overlay = new NEUOverlay(manager);
+ profileViewer = new ProfileViewer(manager);
for(KeyBinding kb : manager.keybinds) {
ClientRegistry.registerKeyBinding(kb);
@@ -203,7 +336,7 @@ public class NotEnoughUpdates {
}));
//TODO: login code. Ignore this, used for testing.
- /*try {
+ try {
Field field = Minecraft.class.getDeclaredField("session");
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication)
new YggdrasilAuthenticationService(Proxy.NO_PROXY, UUID.randomUUID().toString())
@@ -232,7 +365,7 @@ public class NotEnoughUpdates {
field.setAccessible(true);
field.set(Minecraft.getMinecraft(), session);
} catch (NoSuchFieldException | AuthenticationException | IllegalAccessException e) {
- }*/
+ }
}
/**
@@ -250,149 +383,208 @@ public class NotEnoughUpdates {
}
}
+ private void displayLinks(JsonObject update) {
+ String discord_link = update.get("discord_link").getAsString();
+ String youtube_link = update.get("youtube_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();
+
+ ChatComponentText other = null;
+ if(other_text.length() > 0) {
+ other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]");
+ other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link));
+ }
+ ChatComponentText links = new ChatComponentText("");
+ ChatComponentText separator = new ChatComponentText(
+ EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"---":"--"));
+ ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]");
+ discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link));
+ ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]");
+ youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_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));
+
+
+ links.appendSibling(separator);
+ links.appendSibling(discord);
+ links.appendSibling(separator);
+ links.appendSibling(youtube);
+ 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);
+ }
+
+ private void displayUpdateMessageIfOutOfDate() {
+ File repo = manager.repoLocation;
+ if(repo.exists()) {
+ File updateJson = new File(repo, "update.json");
+ try {
+ JsonObject o = manager.getJsonFromFile(updateJson);
+
+ String version = o.get("version").getAsString();
+
+ if(!VERSION.equalsIgnoreCase(version)) {
+ String update_msg = o.get("update_msg").getAsString();
+ String discord_link = o.get("discord_link").getAsString();
+ String youtube_link = o.get("youtube_link").getAsString();
+ String update_link = o.get("update_link").getAsString();
+ String github_link = o.get("github_link").getAsString();
+ String other_text = o.get("other_text").getAsString();
+ String other_link = o.get("other_link").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));
+ }
+
+ displayLinks(o);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+
+ }
+ } catch(Exception ignored) {}
+ }
+ }
+
/**
* 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 HashMap<String, Long> newItemAddMap = new HashMap<>();
+ private long lastLongUpdate = 0;
+ private long lastSkyblockScoreboard = 0;
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
+ if(event.phase != TickEvent.Phase.START) return;
+
+ boolean longUpdate = false;
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastLongUpdate > 1000) {
+ longUpdate = true;
+ lastLongUpdate = currentTime;
+ }
if(openGui != null) {
Minecraft.getMinecraft().displayGuiScreen(openGui);
openGui = null;
}
- if(hasSkyblockScoreboard()) {
- manager.auctionManager.tick();
- if(!joinedSB && manager.config.showUpdateMsg.value) {
- File repo = manager.repoLocation;
- if(repo.exists()) {
- File updateJson = new File(repo, "update.json");
- try {
- JsonObject o = manager.getJsonFromFile(updateJson);
-
- String version = o.get("version").getAsString();
-
- if(!VERSION.equalsIgnoreCase(version)) {
- String update_msg = o.get("update_msg").getAsString();
- String discord_link = o.get("discord_link").getAsString();
- String youtube_link = o.get("youtube_link").getAsString();
- String update_link = o.get("update_link").getAsString();
- String github_link = o.get("github_link").getAsString();
- String other_text = o.get("other_text").getAsString();
- String other_link = o.get("other_link").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));
- }
- ChatComponentText other = null;
- if(other_text.length() > 0) {
- other = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+other_text+EnumChatFormatting.GRAY+"]");
- other.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, other_link));
- }
- ChatComponentText links = new ChatComponentText("");
- ChatComponentText separator = new ChatComponentText(
- EnumChatFormatting.GRAY+EnumChatFormatting.BOLD.toString()+EnumChatFormatting.STRIKETHROUGH+(other==null?"---":"--"));
- ChatComponentText discord = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.BLUE+"Discord"+EnumChatFormatting.GRAY+"]");
- discord.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, discord_link));
- ChatComponentText youtube = new ChatComponentText(EnumChatFormatting.GRAY+"["+EnumChatFormatting.RED+"YouTube"+EnumChatFormatting.GRAY+"]");
- youtube.setChatStyle(Utils.createClickStyle(ClickEvent.Action.OPEN_URL, youtube_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));
-
-
- links.appendSibling(separator);
- links.appendSibling(discord);
- links.appendSibling(separator);
- links.appendSibling(youtube);
- 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);
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
-
- }
-
- joinedSB = true;
- } catch(Exception ignored) {}
+ if(longUpdate) {
+ updateSkyblockScoreboard();
+ if(hasSkyblockScoreboard()) {
+ lastSkyblockScoreboard = currentTime;
+ if(!joinedSB && manager.config.showUpdateMsg.value) {
+ joinedSB = true;
+ displayUpdateMessageIfOutOfDate();
+ if(!manager.config.loadedModBefore.value) {
+ manager.config.loadedModBefore.value = true;
+ try { manager.saveConfig(); } catch(IOException e) {}
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.BLUE+"It seems this is your first time using NotEnoughUpdates."));
+ ChatComponentText clickText = new ChatComponentText(
+ EnumChatFormatting.YELLOW+"Click this message if you would like to view a short tutorial.");
+ clickText.setChatStyle(Utils.createClickStyle(ClickEvent.Action.RUN_COMMAND, "/neututorial"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(clickText);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ }
}
+ SBScoreboardData.getInstance().tick();
+ //GuiQuestLine.questLine.tick();
}
- //NEUQuesting.getInstance().tick();
- //GuiQuestLine.questLine.tick();
+ if(currentTime - lastSkyblockScoreboard < 5*60*1000) { //5 minutes
+ manager.auctionManager.tick();
+ } else {
+ manager.auctionManager.markNeedsUpdate();
+ }
+ //ItemRarityHalo.resetItemHaloCache();
}
- if(currChatMessage != null && System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
- lastChatMessage = System.currentTimeMillis();
+ if(currChatMessage != null && currentTime - lastChatMessage > CHAT_MSG_COOLDOWN) {
+ lastChatMessage = currentTime;
Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage);
currChatMessage = null;
}
- if(hasSkyblockScoreboard() && manager.getCurrentProfile() != null && 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(longUpdate && hasSkyblockScoreboard()) {
+ if(manager.getCurrentProfile() == null || manager.getCurrentProfile().length() == 0) {
+ ProfileViewer.Profile profile = profileViewer.getProfile(
+ Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""), (json) -> {});
+ if(profile != null) {
+ String latest = profile.getLatestProfile();
+ if(latest != null) {
+ manager.setCurrentProfileBackup(profile.getLatestProfile());
}
- if(stack.hasTagCompound()) {
- NBTTagCompound tag = stack.getTagCompound();
- if(tag.hasKey("ExtraAttributes", 10)) {
+ }
+ }
+ if(manager.getCurrentProfile() != null && 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;
}
- 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")) {
- usableContainer = true;
+ 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.openContainer.getInventory()) {
- processUniqueStack(stack, newItem);
+ 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);
}
}
- } else {
-
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
- processUniqueStack(stack, newItem);
- }
+ newItemAddMap.keySet().retainAll(newItem);
}
- newItemAddMap.keySet().retainAll(newItem);
}
}
@@ -407,6 +599,7 @@ public class NotEnoughUpdates {
if(newItemAddMap.containsKey(internalname)) {
if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) {
log.add(internalname);
+ try { manager.saveConfig(); } catch(IOException ignored) {}
}
} else {
newItemAddMap.put(internalname, System.currentTimeMillis());
@@ -416,6 +609,15 @@ public class NotEnoughUpdates {
}
}
+ @SubscribeEvent(priority=EventPriority.HIGHEST)
+ public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) {
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) {
+ if(((GuiProfileViewer)Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) {
+ event.setCanceled(true);
+ }
+ }
+ }
+
@SubscribeEvent
public void onRenderGameOverlay(RenderGameOverlayEvent event) {
if(event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) &&
@@ -448,7 +650,8 @@ public class NotEnoughUpdates {
String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") ||
- containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid"));
+ containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid") ||
+ containerName.trim().equals("Confirm Purchase"));
}
//OPEN
@@ -596,7 +799,8 @@ public class NotEnoughUpdates {
missingRecipe.set(true);
}
//System.out.println(e.message);
- if(isOnSkyblock() && manager.config.streamerMode.value && e.message instanceof ChatComponentText) {
+ if(unformatted.startsWith("Sending to server") &&
+ isOnSkyblock() && manager.config.streamerMode.value && e.message instanceof ChatComponentText) {
String m = e.message.getFormattedText();
String m2 = StreamerMode.filterChat(e.message.getFormattedText());
if(!m.equals(m2)) {
@@ -618,7 +822,7 @@ public class NotEnoughUpdates {
*/
@SubscribeEvent
public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
- if((event.gui instanceof GuiContainer || event.gui instanceof CustomAHGui) && isOnSkyblock()) {
+ if((shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && isOnSkyblock()) {
ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledresolution.getScaledWidth();
@@ -644,13 +848,24 @@ public class NotEnoughUpdates {
npe.printStackTrace();
focusInv = !hoverPane;
}
- if(focusInv) {
- try {
- overlay.render(event.getMouseX(), event.getMouseY(), hoverInv && focusInv);
- } catch(ConcurrentModificationException e) {e.printStackTrace();}
- GL11.glTranslatef(0, 0, 10);
+ }
+ 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 {
+ overlay.render(event.getMouseX(), event.getMouseY(), hoverInv && focusInv);
+ } catch(ConcurrentModificationException e) {e.printStackTrace();}
+ GL11.glTranslatef(0, 0, 10);
+ }
}
}
@@ -677,6 +892,19 @@ public class NotEnoughUpdates {
}
}
+ 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;
+ }
+
/**
* 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))
@@ -685,8 +913,7 @@ public class NotEnoughUpdates {
@SubscribeEvent
public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
if(!(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView())) {
- if(event.gui instanceof GuiContainer && isOnSkyblock()) {
-
+ if(shouldRenderOverlay(event.gui) && isOnSkyblock()) {
renderDungeonChestOverlay(event.gui);
if(!focusInv) {
@@ -732,7 +959,10 @@ public class NotEnoughUpdates {
ItemStack item = lower.getStackInSlot(11+i);
String internal = manager.getInternalNameForItem(item);
if(internal != null) {
- int worth = manager.auctionManager.getLowestBin(internal);
+ float worth = manager.auctionManager.getLowestBin(internal);
+
+ if(worth == -1) worth = manager.getCraftCost(internal).craftCost;
+
if(worth > 0) {
totalValue += worth;
} else {
@@ -771,7 +1001,6 @@ public class NotEnoughUpdates {
guiTop+14, true, 170, Color.BLACK.getRGB());
Utils.drawStringCenteredScaledMaxWidth(plString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90,
guiTop+28, true, 170, Color.BLACK.getRGB());
-
}
} catch(Exception e) {
e.printStackTrace();
@@ -792,7 +1021,7 @@ public class NotEnoughUpdates {
overlay.mouseInput();
return;
}
- if(event.gui instanceof GuiContainer && !(hoverInv && focusInv) && isOnSkyblock()) {
+ if(shouldRenderOverlay(event.gui) && !(hoverInv && focusInv) && isOnSkyblock()) {
if(overlay.mouseInput()) {
event.setCanceled(true);
}
@@ -817,7 +1046,7 @@ public class NotEnoughUpdates {
return;
}
- if(event.gui instanceof GuiContainer && isOnSkyblock()) {
+ if(shouldRenderOverlay(event.gui) && isOnSkyblock()) {
if(overlay.keyboardInput(focusInv)) {
event.setCanceled(true);
}
@@ -936,6 +1165,103 @@ public class NotEnoughUpdates {
}*/
}
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onItemTooltipLow(ItemTooltipEvent event) {
+ //NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value
+ int index = 0;
+ List<String> newTooltip = new ArrayList<>();
+ for(String line : event.toolTip) {
+ for(String op : NotEnoughUpdates.INSTANCE.manager.config.enchantColours.value) {
+ 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);
+
+ if(enchantName.length() == 0) continue;
+ if(comparator.length() == 0) continue;
+ if(comparison.length() == 0) continue;
+ if(colourCode.length() == 0) continue;
+
+ if(enchantName.contains("(") || enchantName.contains(")")) continue;
+
+ int comparatorI = ">=<".indexOf(comparator.charAt(0));
+
+ int levelToFind = -1;
+ try {
+ levelToFind = Integer.parseInt(comparison);
+ } catch(Exception e) { continue; }
+
+ if(comparatorI < 0) continue;
+ if("0123456789abcdefz".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 {
+ String prefix = "\u00A79";
+ if(enchantName.startsWith("ULT_")) prefix = "\u00A7l\u00A7d";
+ pattern = Pattern.compile(prefix+"("+enchantName+") ([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X))(,|$)");
+ } catch(Exception e) {continue;} //malformed regex
+ Matcher matcher = pattern.matcher(line);
+ int matchCount = 0;
+ while(matcher.find() && matchCount < 5) {
+ matchCount++;
+ int level = -1;
+ String levelStr = matcher.group(2);
+ 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;
+ }
+ }
+ 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) {
+ if(!colourCode.equals("z")) {
+ line = line.replaceAll("\\u00A79"+matcher.group(1), "\u00A7"+colourCode+matcher.group(1));
+ } else {
+ line = line.replaceAll("\\u00A79"+matcher.group(1), Utils.chromaString(matcher.group(1)));
+ }
+ }
+ }
+ }
+ newTooltip.add(line);
+ }
+ event.toolTip.clear();
+ event.toolTip.addAll(newTooltip);
+ }
+
/**
* This makes it so that holding LCONTROL while hovering over an item with NBT will show the NBT of the item.
* @param event
@@ -1036,13 +1362,19 @@ public class NotEnoughUpdates {
}
}
- //Stolen from Biscut's SkyblockAddons
public boolean isOnSkyblock() {
if(!manager.config.onlyShowOnSkyblock.value) return true;
return hasSkyblockScoreboard();
}
+ private boolean hasSkyblockScoreboard;
+
public boolean hasSkyblockScoreboard() {
+ return hasSkyblockScoreboard;
+ }
+
+ //Stolen from Biscut's SkyblockAddons
+ private void updateSkyblockScoreboard() {
Minecraft mc = Minecraft.getMinecraft();
if (mc != null && mc.theWorld != null) {
@@ -1052,12 +1384,13 @@ public class NotEnoughUpdates {
String objectiveName = sidebarObjective.getDisplayName().replaceAll("(?i)\\u00A7.", "");
for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) {
if (objectiveName.startsWith(skyblock)) {
- return true;
+ hasSkyblockScoreboard = true;
+ return;
}
}
}
}
- return false;
+ hasSkyblockScoreboard = false;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java b/src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java
new file mode 100644
index 00000000..502792df
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java
@@ -0,0 +1,196 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.settings.KeyBinding;
+import net.minecraft.item.ItemStack;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class SBAIntegration {
+
+ private static boolean hasSBA = true;
+ private static Class<?> skyblockAddonsClass = null;
+ private static Method skyblockAddons_getInstance = null;
+ private static Method skyblockAddons_getUtils = null;
+ private static Class<?> backpackManagerClass = null;
+ private static Method backpackManager_getFromItem = null;
+ private static Class<?> backpackClass = null;
+ private static Method backpackClass_setX= null;
+ private static Method backpackClass_setY = null;
+ private static Class<?> utilsClass = null;
+ private static Method utils_setBackpackToPreview = null;
+ public static boolean setActiveBackpack(ItemStack stack, int mouseX, int mouseY) {
+ if(!hasSBA) return false;
+ try {
+ if(skyblockAddonsClass == null) {
+ skyblockAddonsClass = Class.forName("codes.biscuit.skyblockaddons.SkyblockAddons");
+ }
+ if(skyblockAddons_getInstance == null) {
+ skyblockAddons_getInstance = skyblockAddonsClass.getDeclaredMethod("getInstance");
+ }
+ if(skyblockAddons_getUtils == null) {
+ skyblockAddons_getUtils = skyblockAddonsClass.getDeclaredMethod("getUtils");
+ }
+ if(backpackManagerClass == null) {
+ backpackManagerClass = Class.forName("codes.biscuit.skyblockaddons.utils.BackpackManager");
+ }
+ if(backpackManager_getFromItem == null) {
+ backpackManager_getFromItem = backpackManagerClass.getDeclaredMethod("getFromItem", ItemStack.class);
+ }
+ if(backpackClass == null) {
+ backpackClass = Class.forName("codes.biscuit.skyblockaddons.utils.Backpack");
+ }
+ if(backpackClass_setX == null) {
+ backpackClass_setX = backpackClass.getDeclaredMethod("setX", int.class);
+ }
+ if(backpackClass_setY == null) {
+ backpackClass_setY = backpackClass.getDeclaredMethod("setY", int.class);
+ }
+ if(utilsClass == null) {
+ utilsClass = Class.forName("codes.biscuit.skyblockaddons.utils.Utils");
+ }
+ if(utils_setBackpackToPreview == null) {
+ utils_setBackpackToPreview = utilsClass.getDeclaredMethod("setBackpackToPreview", backpackClass);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ hasSBA = false;
+ return false;
+ }
+ try {
+ Object skyblockAddons = skyblockAddons_getInstance.invoke(null);
+ Object utils = skyblockAddons_getUtils.invoke(skyblockAddons);
+ if(stack == null) {
+ utils_setBackpackToPreview.invoke(utils, (Object) null);
+ } else {
+ Object backpack = backpackManager_getFromItem.invoke(null, stack);
+ backpackClass_setX.invoke(backpack, mouseX);
+ backpackClass_setY.invoke(backpack, mouseY);
+ utils_setBackpackToPreview.invoke(utils, backpack);
+ }
+ } catch(Exception e) { return false; }
+ return true;
+ }
+
+ private static Field guiContainerHook_freezeBackpack = null;
+ public static boolean isFreezeBackpack() {
+ if(!hasSBA) return false;
+ try {
+ if(guiContainerHookClass == null) {
+ guiContainerHookClass = Class.forName("codes.biscuit.skyblockaddons.asm.hooks.GuiContainerHook");
+ }
+ if(guiContainerHook_freezeBackpack == null) {
+ guiContainerHook_freezeBackpack = guiContainerHookClass.getDeclaredField("freezeBackpack");
+ guiContainerHook_freezeBackpack.setAccessible(true);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ hasSBA = false;
+ return false;
+ }
+ try {
+ return (boolean) guiContainerHook_freezeBackpack.get(null);
+ } catch(Exception e) {
+ return false;
+ }
+ }
+
+ public static boolean setFreezeBackpack(boolean freezeBackpack) {
+ if(!hasSBA) return false;
+ try {
+ if(guiContainerHookClass == null) {
+ guiContainerHookClass = Class.forName("codes.biscuit.skyblockaddons.asm.hooks.GuiContainerHook");
+ }
+ if(guiContainerHook_freezeBackpack == null) {
+ guiContainerHook_freezeBackpack = guiContainerHookClass.getDeclaredField("freezeBackpack");
+ guiContainerHook_freezeBackpack.setAccessible(true);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ hasSBA = false;
+ return false;
+ }
+ try {
+ guiContainerHook_freezeBackpack.set(null, freezeBackpack);
+ return true;
+ } catch(Exception e) {
+ return false;
+ }
+ }
+
+ private static Method guiContainerHook_keyTyped = null;
+ private static Method skyblockAddons_getFreezeBackpackKey = null;
+ public static boolean keyTyped(int keyCode) {
+ if(!hasSBA) return false;
+ try {
+ if(skyblockAddonsClass == null) {
+ skyblockAddonsClass = Class.forName("codes.biscuit.skyblockaddons.SkyblockAddons");
+ }
+ if(skyblockAddons_getInstance == null) {
+ skyblockAddons_getInstance = skyblockAddonsClass.getDeclaredMethod("getInstance");
+ }
+ if(skyblockAddons_getFreezeBackpackKey == null) {
+ skyblockAddons_getFreezeBackpackKey = skyblockAddonsClass.getDeclaredMethod("getFreezeBackpackKey");
+ }
+ if(guiContainerHookClass == null) {
+ guiContainerHookClass = Class.forName("codes.biscuit.skyblockaddons.asm.hooks.GuiContainerHook");
+ }
+ if(guiContainerHook_keyTyped == null) {
+ guiContainerHook_keyTyped = guiContainerHookClass.getDeclaredMethod("keyTyped", int.class);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ hasSBA = false;
+ return false;
+ }
+ try {
+ Object skyblockAddons = skyblockAddons_getInstance.invoke(null);
+ if(!isFreezeBackpack() && ((KeyBinding)skyblockAddons_getFreezeBackpackKey.invoke(skyblockAddons)).getKeyCode() == keyCode) {
+ setFreezeBackpack(true);
+ } else {
+ guiContainerHook_keyTyped.invoke(null, keyCode);
+ }
+ } catch(Exception e) { return false; }
+ return true;
+ }
+
+ private static Class<?> guiContainerHookClass = null;
+ private static Method guiContainerHook_drawBackpacks = null;
+ public static boolean renderActiveBackpack(int mouseX, int mouseY, FontRenderer fontRendererObj) {
+ if(!hasSBA) return false;
+ try {
+ if(guiContainerHookClass == null) {
+ guiContainerHookClass = Class.forName("codes.biscuit.skyblockaddons.asm.hooks.GuiContainerHook");
+ }
+ if(guiContainerHook_drawBackpacks == null) {
+ guiContainerHook_drawBackpacks = guiContainerHookClass.getDeclaredMethod("drawBackpacks",
+ GuiContainer.class, int.class, int.class, FontRenderer.class);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ hasSBA = false;
+ return false;
+ }
+ try {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ GuiContainer container = new GuiContainer(null) {
+ protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
+ }
+ };
+ container.setWorldAndResolution(Minecraft.getMinecraft(), width, height);
+
+ guiContainerHook_drawBackpacks.invoke(null, container, mouseX, mouseY, fontRendererObj);
+ } catch(Exception e) { return false; }
+ return true;
+ }
+
+}
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 20ac86ba..33012194 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -1,6 +1,7 @@
package io.github.moulberry.notenoughupdates.auction;
import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.util.Utils;
@@ -19,16 +20,15 @@ import net.minecraft.util.EnumChatFormatting;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
public class APIManager {
private NEUManager manager;
public final CustomAH customAH;
- private int totalPages = 0;
- private int lastApiUpdate;
- private LinkedList<Integer> needUpdate = new LinkedList<>();
-
private TreeMap<String, Auction> auctionMap = new TreeMap<>();
public HashMap<String, HashSet<String>> internalnameToAucIdMap = new HashMap<>();
private HashSet<String> playerBids = new HashSet<>();
@@ -37,15 +37,18 @@ public class APIManager {
private HashMap<String, TreeMap<Integer, String>> internalnameToLowestBIN = new HashMap<>();
- private JsonArray playerInformation = null;
+ private LinkedList<Integer> pagesToDownload = null;
public TreeMap<String, HashMap<Integer, HashSet<String>>> extrasToAucIdMap = new TreeMap<>();
- private long lastPageUpdate = 0;
- private long lastProfileUpdate = 0;
+ private long lastAuctionUpdate = 0;
+ private long lastShortAuctionUpdate = 0;
private long lastCustomAHSearch = 0;
private long lastCleanup = 0;
+ private long lastApiUpdate = 0;
+ private long firstHypixelApiUpdate = 0;
+
public int activeAuctions = 0;
public int uniqueItems = 0;
public int totalTags = 0;
@@ -53,28 +56,11 @@ public class APIManager {
public int taggedAuctions = 0;
public int processMillis = 0;
- private boolean doFullUpdate = false;
-
public APIManager(NEUManager manager) {
this.manager = manager;
customAH = new CustomAH(manager);
}
- public JsonObject getPlayerInformation() {
- if(playerInformation == null) return null;
- for(int i=0; i<playerInformation.size(); i++) {
- JsonObject profile = playerInformation.get(i).getAsJsonObject();
- if(profile.get("cute_name").getAsString().equalsIgnoreCase(manager.getCurrentProfile())) {
- if(!profile.has("members")) return null;
- JsonObject members = profile.get("members").getAsJsonObject();
- String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
- if(!members.has(uuid)) return null;
- return members.get(uuid).getAsJsonObject();
- }
- }
- return null;
- }
-
public TreeMap<String, Auction> getAuctionItems() {
return auctionMap;
}
@@ -128,23 +114,36 @@ public class APIManager {
}
}
+ public void markNeedsUpdate() {
+ firstHypixelApiUpdate = 0;
+ pagesToDownload = null;
+ }
+
public void tick() {
+ if(manager.config.apiKey.value == null || manager.config.apiKey.value.isEmpty()) return;
+
customAH.tick();
- if(System.currentTimeMillis() - lastPageUpdate > 5*1000) {
- lastPageUpdate = System.currentTimeMillis();
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastAuctionUpdate > 60*1000) {
+ lastAuctionUpdate = currentTime;
updatePageTick();
+ }
+
+ if(currentTime - lastShortAuctionUpdate > 10*1000) {
+ lastShortAuctionUpdate = currentTime;
+ updatePageTickShort();
ahNotification();
}
- if(System.currentTimeMillis() - lastProfileUpdate > 10*1000) {
+ /*if(currentTime - lastProfileUpdate > 10*1000) {
lastProfileUpdate = System.currentTimeMillis();
updateProfiles(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""));
- }
- if(System.currentTimeMillis() - lastCleanup > 120*1000) {
- lastCleanup = System.currentTimeMillis();
+ }*/
+ if(currentTime - lastCleanup > 120*1000) {
+ lastCleanup = currentTime;
cleanup();
}
- if(System.currentTimeMillis() - lastCustomAHSearch > 60*1000) {
- lastCustomAHSearch = System.currentTimeMillis();
+ if(currentTime - lastCustomAHSearch > 60*1000) {
+ lastCustomAHSearch = currentTime;
if(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView()) {
customAH.updateSearch();
calculateStats();
@@ -152,41 +151,6 @@ public class APIManager {
}
}
- public void updateProfiles(String uuid) {
- HashMap<String, String> args = new HashMap<>();
- args.put("uuid", ""+uuid);
- manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles",
- args, jsonObject -> {
- if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
- playerInformation = jsonObject.get("profiles").getAsJsonArray();
- if(playerInformation == null) return;
- String backup = null;
- long backupLastSave = 0;
- for(int i=0; i<playerInformation.size(); i++) {
- JsonObject profile = playerInformation.get(i).getAsJsonObject();
- String cute_name = profile.get("cute_name").getAsString();
-
- if(backup == null) backup = cute_name;
-
- if(!profile.has("members")) continue;
- JsonObject members = profile.get("members").getAsJsonObject();
-
- if(members.has(uuid)) {
- JsonObject member = members.get(uuid).getAsJsonObject();
- long last_save = member.get("last_save").getAsLong();
- if(last_save > backupLastSave) {
- backupLastSave = last_save;
- backup = cute_name;
- }
- }
- }
-
- manager.setCurrentProfileBackup(backup);
- }
- }
- );
- }
-
private String niceAucId(String aucId) {
if(aucId.length()!=32) return aucId;
@@ -246,58 +210,109 @@ public class APIManager {
}
}
+ private ExecutorService es = Executors.newSingleThreadExecutor();
private void cleanup() {
- try {
- long currTime = System.currentTimeMillis();
- Set<String> toRemove = new HashSet<>();
- for(Map.Entry<String, Auction> entry : auctionMap.entrySet()) {
- long timeToEnd = entry.getValue().end - currTime;
- if(timeToEnd < -60) {
- toRemove.add(entry.getKey());
- } else if(currTime - entry.getValue().lastUpdate > 5*60*1000) {
- toRemove.add(entry.getKey());
- }
- }
- toRemove.removeAll(playerBids);
- for(String aucid : toRemove) {
- auctionMap.remove(aucid);
- }
- for(HashMap<Integer, HashSet<String>> extrasMap : extrasToAucIdMap.values()) {
- for(HashSet<String> aucids : extrasMap.values()) {
- for(String aucid : toRemove) {
- aucids.remove(aucid);
+ es.submit(() -> {
+ try {
+ long currTime = System.currentTimeMillis();
+ Set<String> toRemove = new HashSet<>();
+ for(Map.Entry<String, Auction> entry : auctionMap.entrySet()) {
+ long timeToEnd = entry.getValue().end - currTime;
+ if(timeToEnd < -120*1000) { //2 minutes
+ toRemove.add(entry.getKey());
}
}
+ toRemove.removeAll(playerBids);
+ remove(toRemove);
+ } catch(ConcurrentModificationException e) {
+ lastCleanup = System.currentTimeMillis() - 110*1000;
}
- for(HashSet<String> aucids : internalnameToAucIdMap.values()) {
- aucids.removeAll(toRemove);
- }
- for(TreeMap<Integer, String> lowestBINs : internalnameToLowestBIN.values()) {
- lowestBINs.values().removeAll(toRemove);
+ });
+ }
+
+ private void remove(Set<String> toRemove) {
+ for(String aucid : toRemove) {
+ auctionMap.remove(aucid);
+ }
+ for(HashMap<Integer, HashSet<String>> extrasMap : extrasToAucIdMap.values()) {
+ for(HashSet<String> aucids : extrasMap.values()) {
+ for(String aucid : toRemove) {
+ aucids.remove(aucid);
+ }
}
- } catch(ConcurrentModificationException e) {
- cleanup();
+ }
+ for(HashSet<String> aucids : internalnameToAucIdMap.values()) {
+ aucids.removeAll(toRemove);
+ }
+ for(TreeMap<Integer, String> lowestBINs : internalnameToLowestBIN.values()) {
+ lowestBINs.values().removeAll(toRemove);
+ }
+ }
+
+ private void updatePageTickShort() {
+ if(pagesToDownload == null || pagesToDownload.isEmpty()) return;
+
+ if(firstHypixelApiUpdate == 0 || (System.currentTimeMillis() - firstHypixelApiUpdate)%(60*1000) > 15*1000) return;
+
+ JsonObject disable = Utils.getConstant("disable");
+ if(disable != null && disable.get("auctions").getAsBoolean()) return;
+
+ while(!pagesToDownload.isEmpty()) {
+ int page = pagesToDownload.pop();
+ getPageFromAPI(page);
}
}
private void updatePageTick() {
- if(totalPages == 0) {
+ JsonObject disable = Utils.getConstant("disable");
+ if(disable != null && disable.get("auctions").getAsBoolean()) return;
+
+ if(pagesToDownload == null) {
getPageFromAPI(0);
- } else if(doFullUpdate) {
- doFullUpdate = false;
- for(int i=0; i<totalPages; i++) {
- getPageFromAPI(i);
- }
- } else {
- if(needUpdate.isEmpty()) resetNeedUpdate();
+ }
- int pageToUpdate = needUpdate.pop();
- while (pageToUpdate >= totalPages && !needUpdate.isEmpty()) {
- pageToUpdate = needUpdate.pop();
- }
+ manager.hypixelApi.getApiGZIPAsync("http://moulberry.codes/auction.json.gz", jsonObject -> {
+ if(jsonObject.get("success").getAsBoolean()) {
+ long apiUpdate = (long)jsonObject.get("time").getAsFloat();
+ if(lastApiUpdate == apiUpdate) {
+ lastAuctionUpdate -= 30*1000;
+ }
+ lastApiUpdate = apiUpdate;
- getPageFromAPI(pageToUpdate);
- }
+ JsonArray new_auctions = jsonObject.get("new_auctions").getAsJsonArray();
+ for(JsonElement auctionElement : new_auctions) {
+ JsonObject auction = auctionElement.getAsJsonObject();
+ //System.out.println("New auction " + auction);
+ processAuction(auction);
+ }
+ JsonArray new_bids = jsonObject.get("new_bids").getAsJsonArray();
+ for(JsonElement newBidElement : new_bids) {
+ JsonObject newBid = newBidElement.getAsJsonObject();
+ String newBidUUID = newBid.get("uuid").getAsString();
+ //System.out.println("new bid" + newBidUUID);
+ int newBidAmount = newBid.get("highest_bid_amount").getAsInt();
+ int end = newBid.get("end").getAsInt();
+ int bid_count = newBid.get("bid_count").getAsInt();
+
+ Auction auc = auctionMap.get(newBidUUID);
+ if(auc != null) {
+ //System.out.println("Setting auction " + newBidUUID + " price to " + newBidAmount);
+ auc.highest_bid_amount = newBidAmount;
+ auc.end = end;
+ auc.bid_count = bid_count;
+ }
+ }
+ Set<String> toRemove = new HashSet<>();
+ JsonArray removed_auctions = jsonObject.get("removed_auctions").getAsJsonArray();
+ for(JsonElement removedAuctionsElement : removed_auctions) {
+ String removed = removedAuctionsElement.getAsString();
+ toRemove.add(removed);
+ }
+ remove(toRemove);
+ }
+ }, () -> {
+ System.out.println("Error downloading auction from Moulberry's jank API. :(");
+ });
}
public void calculateStats() {
@@ -332,6 +347,8 @@ public class APIManager {
if(contains) {
if(line.trim().contains(rarity + " " + typeMatches[j])) {
return j;
+ } else if(line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) {
+ return j;
}
} else {
if(line.trim().endsWith(rarity + " " + typeMatches[j])) {
@@ -346,171 +363,181 @@ public class APIManager {
return -1;
}
- private void getPageFromAPI(int page) {
- //System.out.println("Trying to update page: " + page);
- HashMap<String, String> args = new HashMap<>();
- args.put("page", ""+page);
- manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/auctions",
- args, jsonObject -> {
- if (jsonObject.get("success").getAsBoolean()) {
- totalPages = jsonObject.get("totalPages").getAsInt();
- activeAuctions = jsonObject.get("totalAuctions").getAsInt();
-
- int lastUpdated = jsonObject.get("lastUpdated").getAsInt();
+ private String[] romans = new String[]{"I","II","III","IV","V","VI","VII","VIII","IX","X","XI",
+ "XII","XIII","XIV","XV","XVI","XVII","XIX","XX"};
+
+
+ String[] categoryItemType = new String[]{"sword","fishingrod","pickaxe","axe",
+ "shovel","petitem","travelscroll","reforgestone","bow"};
+ String playerUUID = null;
+ private void processAuction(JsonObject auction) {
+ if(playerUUID == null) playerUUID = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replaceAll("-","");
+
+ 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();
+ int highest_bid_amount = auction.get("highest_bid_amount").getAsInt();
+ int bid_count = auction.get("bids").getAsJsonArray().size();
+ boolean bin = false;
+ if(auction.has("bin")) {
+ bin = auction.get("bin").getAsBoolean();
+ }
+ String sbCategory = auction.get("category").getAsString();
+ String extras = auction.get("extra").getAsString().toLowerCase();
+ String item_name = auction.get("item_name").getAsString();
+ String item_lore = Utils.fixBrokenAPIColour(auction.get("item_lore").getAsString());
+ String item_bytes = auction.get("item_bytes").getAsString();
+ String rarity = auction.get("tier").getAsString();
+ JsonArray bids = auction.get("bids").getAsJsonArray();
- if(lastApiUpdate != lastUpdated) {
- if(manager.config.quickAHUpdate.value &&
- (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView())) {
- doFullUpdate = true;
+ try {
+ NBTTagCompound item_tag;
+ try {
+ item_tag = CompressedStreamTools.readCompressed(
+ new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes)));
+ } catch(IOException e) { return; }
+
+ NBTTagCompound tag = item_tag.getTagList("i", 10).getCompoundTagAt(0).getCompoundTag("tag");
+ String internalname = manager.getInternalnameFromNBT(tag);
+
+ String[] lore = new String[0];
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if(display.hasKey("Lore", 9)) {
+ NBTTagList loreList = new NBTTagList();
+ for(String line : item_lore.split("\n")) {
+ loreList.appendTag(new NBTTagString(line));
+ }
+ display.setTag("Lore", loreList);
+ }
+ tag.setTag("display", display);
+ item_tag.getTagList("i", 10).getCompoundTagAt(0).setTag("tag", tag);
+
+ if(tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ if(ea.hasKey("enchantments", 10)) {
+ NBTTagCompound enchantments = ea.getCompoundTag("enchantments");
+ for(String key : enchantments.getKeySet()) {
+ String enchantname = key.toLowerCase().replace("_", " ");
+ int enchantlevel = enchantments.getInteger(key);
+ String enchantLevelStr;
+ if(enchantlevel >= 1 && enchantlevel <= 20) {
+ enchantLevelStr = romans[enchantlevel-1];
+ } else {
+ enchantLevelStr = String.valueOf(enchantlevel);
}
- resetNeedUpdate();
+ extras = extras.replace(enchantname, enchantname + " " + enchantLevelStr);
}
+ }
+ }
- lastApiUpdate = lastUpdated;
-
- String[] lvl4Maxes = {"Experience", "Life Steal", "Scavenger", "Looting"};
-
- String[] categoryItemType = new String[]{"sword","fishingrod","pickaxe","axe",
- "shovel","petitem","travelscroll","reforgestone","bow"};
- String playerUUID = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replaceAll("-","");
+ int index=0;
+ for(String str : extras.split(" ")) {
+ str = Utils.cleanColour(str).toLowerCase();
+ if(str.length() > 0) {
+ HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent(str, k -> new HashMap<>());
+ HashSet<String> aucids = extrasMap.computeIfAbsent(index, k -> new HashSet<>());
+ aucids.add(auctionUuid);
+ }
+ index++;
+ }
- long startProcess = System.currentTimeMillis();
- JsonArray auctions = jsonObject.get("auctions").getAsJsonArray();
- for (int i = 0; i < auctions.size(); i++) {
- JsonObject auction = auctions.get(i).getAsJsonObject();
+ if(bin) {
+ TreeMap<Integer, String> lowestBINs = internalnameToLowestBIN.computeIfAbsent(internalname, k -> new TreeMap<>());
+ int count = item_tag.getInteger("Count");
+ lowestBINs.put(starting_bid/(count>0?count:1), auctionUuid);
+ if(lowestBINs.size() > 5) {
+ lowestBINs.keySet().remove(lowestBINs.lastKey());
+ }
+ }
- 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();
- int highest_bid_amount = auction.get("highest_bid_amount").getAsInt();
- int bid_count = auction.get("bids").getAsJsonArray().size();
- boolean bin = false;
- if(auction.has("bin")) {
- bin = auction.get("bin").getAsBoolean();
- }
- String sbCategory = auction.get("category").getAsString();
- String extras = auction.get("extra").getAsString();
- String item_name = auction.get("item_name").getAsString();
- String item_lore = Utils.fixBrokenAPIColour(auction.get("item_lore").getAsString());
- String item_bytes = auction.get("item_bytes").getAsString();
- String rarity = auction.get("tier").getAsString();
- JsonArray bids = auction.get("bids").getAsJsonArray();
-
- for(String lvl4Max : lvl4Maxes) {
- item_lore = item_lore.replaceAll("\\u00A79("+lvl4Max+" IV)", EnumChatFormatting.DARK_PURPLE+"$1");
- }
- item_lore = item_lore.replaceAll("\\u00A79([A-Za-z ]+ VI)", EnumChatFormatting.DARK_PURPLE+"$1");
- item_lore = item_lore.replaceAll("\\u00A79([A-Za-z ]+ VII)", EnumChatFormatting.RED+"$1");
-
- try {
- NBTTagCompound item_tag;
- try {
- item_tag = CompressedStreamTools.readCompressed(
- new ByteArrayInputStream(Base64.getDecoder().decode(item_bytes)));
- } catch(IOException e) { continue; }
-
- NBTTagCompound tag = item_tag.getTagList("i", 10).getCompoundTagAt(0).getCompoundTag("tag");
- String internalname = manager.getInternalnameFromNBT(tag);
- String displayNormal = "";
- if(manager.getItemInformation().containsKey(internalname)) {
- displayNormal = Utils.cleanColour(manager.getItemInformation().get(internalname).get("displayname").getAsString());
- }
+ for(int j=0; j<bids.size(); j++) {
+ JsonObject bid = bids.get(j).getAsJsonObject();
+ if(bid.get("bidder").getAsString().equalsIgnoreCase(playerUUID)) {
+ playerBids.add(auctionUuid);
+ }
+ }
- String[] lore = new String[0];
- NBTTagCompound display = tag.getCompoundTag("display");
- if(display.hasKey("Lore", 9)) {
- NBTTagList loreList = new NBTTagList();
- for(String line : item_lore.split("\n")) {
- loreList.appendTag(new NBTTagString(line));
- }
- display.setTag("Lore", loreList);
- }
- tag.setTag("display", display);
- item_tag.getTagList("i", 10).getCompoundTagAt(0).setTag("tag", tag);
-
- int index=0;
- for(String str : extras.split(" ")) {
- str = Utils.cleanColour(str).toLowerCase();
- if(str.length() > 0) {
- HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent(str, k -> new HashMap<>());
- HashSet<String> aucids = extrasMap.computeIfAbsent(index, k -> new HashSet<>());
- aucids.add(auctionUuid);
- }
- index++;
- }
+ if(checkItemType(item_lore, true, "DUNGEON") >= 0) {
+ HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent("dungeon", k -> new HashMap<>());
+ HashSet<String> aucids = extrasMap.computeIfAbsent(0, k -> new HashSet<>());
+ aucids.add(auctionUuid);
+ }
- if(bin) {
- TreeMap<Integer, String> lowestBINs = internalnameToLowestBIN.computeIfAbsent(internalname, k -> new TreeMap<>());
- int count = item_tag.getInteger("Count");
- lowestBINs.put(starting_bid/(count>0?count:1), auctionUuid);
- if(lowestBINs.size() > 5) {
- lowestBINs.keySet().remove(lowestBINs.lastKey());
- }
- }
+ //Categories
+ String category = sbCategory;
+ int itemType = checkItemType(item_lore, true,"SWORD", "FISHING ROD", "PICKAXE",
+ "AXE", "SHOVEL", "PET ITEM", "TRAVEL SCROLL", "REFORGE STONE", "BOW");
+ if(itemType >= 0 && itemType < categoryItemType.length) {
+ category = categoryItemType[itemType];
+ }
+ if(category.equals("consumables") && extras.contains("enchanted book")) category = "ebook";
+ if(category.equals("consumables") && extras.endsWith("potion")) category = "potion";
+ if(category.equals("misc") && extras.contains("rune")) category = "rune";
+ if(category.equals("misc") && item_lore.split("\n")[0].endsWith("Furniture")) category = "furniture";
+ if(item_lore.split("\n")[0].endsWith("Pet") ||
+ item_lore.split("\n")[0].endsWith("Mount")) category = "pet";
+
+ Auction auction1 = new Auction(auctioneerUuid, end, starting_bid, highest_bid_amount,
+ bid_count, bin, category, rarity, item_tag);
+
+ if(tag.hasKey("ench")) {
+ auction1.enchLevel = 1;
+ if(tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ int hotpotatocount = ea.getInteger("hot_potato_count");
+ if(hotpotatocount == 10) {
+ auction1.enchLevel = 2;
+ }
+ }
+ }
- for(int j=0; j<bids.size(); j++) {
- JsonObject bid = bids.get(j).getAsJsonObject();
- if(bid.get("bidder").getAsString().equalsIgnoreCase(playerUUID)) {
- playerBids.add(auctionUuid);
- }
- }
+ auctionMap.put(auctionUuid, auction1);
+ internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid);
+ } catch(Exception e) {e.printStackTrace();}
+ }
- if(checkItemType(item_lore, true, "DUNGEON") >= 0) {
- HashMap<Integer, HashSet<String>> extrasMap = extrasToAucIdMap.computeIfAbsent("dungeon", k -> new HashMap<>());
- HashSet<String> aucids = extrasMap.computeIfAbsent(0, k -> new HashSet<>());
- aucids.add(auctionUuid);
- }
+ private void getPageFromAPI(int page) {
+ System.out.println("downloading page:"+page);
+ //System.out.println("Trying to update page: " + page);
+ HashMap<String, String> args = new HashMap<>();
+ args.put("page", ""+page);
+ manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/auctions",
+ args, jsonObject -> {
+ if(jsonObject == null) return;
- //Categories
- String category = sbCategory;
- int itemType = checkItemType(item_lore, false,"SWORD", "FISHING ROD", "PICKAXE",
- "AXE", "SHOVEL", "PET ITEM", "TRAVEL SCROLL", "REFORGE STONE", "BOW");
- if(itemType >= 0 && itemType < categoryItemType.length) {
- category = categoryItemType[itemType];
- }
- if(extras.startsWith("Enchanted Book")) category = "ebook";
- if(extras.endsWith("Potion")) category = "potion";
- if(extras.contains("Rune")) category = "rune";
- if(item_lore.split("\n")[0].endsWith("Furniture")) category = "furniture";
- if(item_lore.split("\n")[0].endsWith("Pet") ||
- item_lore.split("\n")[0].endsWith("Mount")) category = "pet";
-
- Auction auction1 = new Auction(auctioneerUuid, end, starting_bid, highest_bid_amount,
- bid_count, bin, category, rarity, item_tag);
-
- if(tag.hasKey("ench")) {
- auction1.enchLevel = 1;
- if(tag.hasKey("ExtraAttributes", 10)) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
-
- int hotpotatocount = ea.getInteger("hot_potato_count");
- if(hotpotatocount == 10) {
- auction1.enchLevel = 2;
- }
- }
+ if (jsonObject.get("success").getAsBoolean()) {
+ if(pagesToDownload == null) {
+ int totalPages = jsonObject.get("totalPages").getAsInt();
+ pagesToDownload = new LinkedList<>();
+ for(int i=0; i<totalPages; i++) {
+ pagesToDownload.add(i);
}
+ }
+ if(firstHypixelApiUpdate == 0) {
+ firstHypixelApiUpdate = jsonObject.get("lastUpdated").getAsLong();
+ }
+ activeAuctions = jsonObject.get("totalAuctions").getAsInt();
- auction1.lastUpdate = System.currentTimeMillis();
+ long startProcess = System.currentTimeMillis();
+ JsonArray auctions = jsonObject.get("auctions").getAsJsonArray();
+ for (int i = 0; i < auctions.size(); i++) {
+ JsonObject auction = auctions.get(i).getAsJsonObject();
- auctionMap.put(auctionUuid, auction1);
- internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid);
- } catch(Exception e) {e.printStackTrace();}
+ processAuction(auction);
+ }
+ processMillis = (int)(System.currentTimeMillis() - startProcess);
+ } else {
+ pagesToDownload.addLast(page);
}
- processMillis = (int)(System.currentTimeMillis() - startProcess);
+ }, () -> {
+ pagesToDownload.addLast(page);
}
- }
);
}
- private void resetNeedUpdate() {
- for(Integer page=0; page<totalPages; page++) {
- if(!needUpdate.contains(page)) {
- needUpdate.addLast(page);
- }
- }
- }
-
/*ScheduledExecutorService auctionUpdateSES = Executors.newSingleThreadScheduledExecutor();
private AtomicInteger auctionUpdateId = new AtomicInteger(0);
public void updateAuctions() {
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 17ce216e..6fdb2924 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
@@ -34,6 +34,8 @@ import java.awt.datatransfer.StringSelection;
import java.text.NumberFormat;
import java.util.*;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -103,7 +105,7 @@ public class CustomAH extends Gui {
private Category CATEGORY_TRAVEL_SCROLLS = new Category("travelscroll", "Travel Scrolls", "map");
private Category CATEGORY_REFORGE_STONES = new Category("reforgestone", "Reforge Stones", "anvil");
- private Category CATEGORY_RUNES = new Category("rune", "Runes", "end_portal_frame");
+ private Category CATEGORY_RUNES = new Category("rune", "Runes", "magma_cream");
private Category CATEGORY_FURNITURE = new Category("furniture", "Furniture", "armor_stand");
private Category CATEGORY_COMBAT = new Category("weapon", "Combat", "golden_sword", CATEGORY_SWORD,
@@ -182,10 +184,12 @@ public class CustomAH extends Gui {
}
public void tick() {
- if(shouldUpdateSearch) updateSearch();
- if(shouldSortItems) {
- sortItems();
- shouldSortItems = false;
+ if(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || renderOverAuctionView) {
+ if(shouldUpdateSearch) updateSearch();
+ if(shouldSortItems) {
+ sortItems();
+ shouldSortItems = false;
+ }
}
}
@@ -530,8 +534,7 @@ public class CustomAH extends Gui {
} catch(NullPointerException e) { //i cant be bothered
}
}
- } else if(containerName.trim().equals("Confirm Bid")) {
-
+ } else if(containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) {
Minecraft.getMinecraft().getTextureManager().bindTexture(auction_accept);
this.drawTexturedModalRect(auctionViewLeft, guiTop, 0, 0, 78, 172);
@@ -867,6 +870,12 @@ public class CustomAH extends Gui {
case 8:
lore.add("");
lore.add("Current aucid: " + currentAucId);
+ if(currentAucId != null) {
+ APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId);
+ if(auc != null) {
+ lore.add("Current auc category: " + auc.category);
+ }
+ }
lore.add(" --- Processing");
lore.add("Page Process Millis: " + manager.auctionManager.processMillis);
lore.add(" --- Auction Stats");
@@ -1032,116 +1041,117 @@ public class CustomAH extends Gui {
return matches;
}
+ private ExecutorService es = Executors.newSingleThreadExecutor();
public void updateSearch() {
if(searchField == null || priceField == null) init();
+ long currentTime = System.currentTimeMillis();
- /*if(searchField.getText().length() > 0 && searchField.getText().length() <= 2 &&
- System.currentTimeMillis() - lastSearchFieldUpdate < 200) {
- shouldUpdateSearch = true;
- return;
- }*/
-
- if(System.currentTimeMillis() - lastUpdateSearch < 500) {
- shouldUpdateSearch = true;
- return;
- }
+ es.submit(() -> {
+ if(currentTime - lastUpdateSearch < 500) {
+ shouldUpdateSearch = true;
+ return;
+ }
- lastUpdateSearch = System.currentTimeMillis();
- shouldUpdateSearch = false;
+ lastUpdateSearch = currentTime;
+ shouldUpdateSearch = false;
- scrollAmount = 0;
- try {
- auctionIds.clear();
- if(filterMyAuctions) {
- for(String aucid : manager.auctionManager.getPlayerBids()) {
- APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid);
- if(doesAucMatch(auc)) {
- auctionIds.add(aucid);
- }
- }
- } else if(searchField.getText().length() == 0) {
- for(Map.Entry<String, APIManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) {
- if(doesAucMatch(entry.getValue())) {
- auctionIds.add(entry.getKey());
+ scrollAmount = 0;
+ try {
+ HashSet<String> auctionIdsNew = new HashSet<>();
+ auctionIdsNew.clear();
+ if(filterMyAuctions) {
+ for(String aucid : manager.auctionManager.getPlayerBids()) {
+ APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid);
+ if(doesAucMatch(auc)) {
+ auctionIdsNew.add(aucid);
+ }
}
- }
- } else {
- String query = searchField.getText();
- Set<String> dontMatch = new HashSet<>();
-
- HashSet<String> allMatch = new HashSet<>();
- if(query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query
+ } else if(searchField.getText().length() == 0) {
for(Map.Entry<String, APIManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) {
if(doesAucMatch(entry.getValue())) {
- allMatch.add(entry.getKey());
- } else {
- dontMatch.add(entry.getKey());
+ auctionIdsNew.add(entry.getKey());
}
}
- }
-
- boolean invert = false;
-
- StringBuilder query2 = new StringBuilder();
- char lastOp = '|';
- for(char c : query.toCharArray()) {
- if(query2.toString().trim().isEmpty() && c == '!') {
- invert = true;
- } else if(c == '|' || c == '&') {
- if(lastOp == '|') {
- HashSet<String> result = search(query2.toString(), dontMatch);
- if(!invert) {
- auctionIds.addAll(result);
- } else {
- HashSet<String> allClone = (HashSet<String>) allMatch.clone();
- allClone.removeAll(result);
- auctionIds.addAll(allClone);
- }
- } else if(lastOp == '&') {
- HashSet<String> result = search(query2.toString(), dontMatch);
- if(!invert) {
- auctionIds.retainAll(result);
+ } else {
+ String query = searchField.getText();
+ Set<String> dontMatch = new HashSet<>();
+
+ HashSet<String> allMatch = new HashSet<>();
+ if(query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query
+ for(Map.Entry<String, APIManager.Auction> entry : manager.auctionManager.getAuctionItems().entrySet()) {
+ if(doesAucMatch(entry.getValue())) {
+ allMatch.add(entry.getKey());
} else {
- auctionIds.removeAll(result);
+ dontMatch.add(entry.getKey());
}
}
-
- query2 = new StringBuilder();
- invert = false;
- lastOp = c;
- } else {
- query2.append(c);
}
- }
- if(lastOp == '|') {
- HashSet<String> result = search(query2.toString(), dontMatch);
- if(!invert) {
- auctionIds.addAll(result);
- } else {
- HashSet<String> allClone = (HashSet<String>) allMatch.clone();
- allClone.removeAll(result);
- auctionIds.addAll(allClone);
+
+ boolean invert = false;
+
+ StringBuilder query2 = new StringBuilder();
+ char lastOp = '|';
+ for(char c : query.toCharArray()) {
+ if(query2.toString().trim().isEmpty() && c == '!') {
+ invert = true;
+ } else if(c == '|' || c == '&') {
+ if(lastOp == '|') {
+ HashSet<String> result = search(query2.toString(), dontMatch);
+ if(!invert) {
+ auctionIdsNew.addAll(result);
+ } else {
+ HashSet<String> allClone = (HashSet<String>) allMatch.clone();
+ allClone.removeAll(result);
+ auctionIdsNew.addAll(allClone);
+ }
+ } else if(lastOp == '&') {
+ HashSet<String> result = search(query2.toString(), dontMatch);
+ if(!invert) {
+ auctionIdsNew.retainAll(result);
+ } else {
+ auctionIdsNew.removeAll(result);
+ }
+ }
+
+ query2 = new StringBuilder();
+ invert = false;
+ lastOp = c;
+ } else {
+ query2.append(c);
+ }
}
- } else if(lastOp == '&') {
- HashSet<String> result = search(query2.toString(), dontMatch);
- if(!invert) {
- auctionIds.retainAll(result);
- } else {
- auctionIds.removeAll(result);
+ if(lastOp == '|') {
+ HashSet<String> result = search(query2.toString(), dontMatch);
+ if(!invert) {
+ auctionIdsNew.addAll(result);
+ } else {
+ HashSet<String> allClone = (HashSet<String>) allMatch.clone();
+ allClone.removeAll(result);
+ auctionIdsNew.addAll(allClone);
+ }
+ } else if(lastOp == '&') {
+ HashSet<String> result = search(query2.toString(), dontMatch);
+ if(!invert) {
+ auctionIdsNew.retainAll(result);
+ } else {
+ auctionIdsNew.removeAll(result);
+ }
}
}
+ auctionIds = auctionIdsNew;
+ sortItems();
+ } catch(Exception e) {
+ shouldUpdateSearch = true;
}
- sortItems();
- } catch(Exception e) {
- shouldUpdateSearch = true;
- }
+ });
}
public void sortItems() throws ConcurrentModificationException {
try {
- sortedAuctionIds.clear();
- sortedAuctionIds.addAll(auctionIds);
- sortedAuctionIds.sort((o1, o2) -> {
+ List<String> sortedAuctionIdsNew = new ArrayList<>();
+
+ sortedAuctionIdsNew.addAll(auctionIds);
+ sortedAuctionIdsNew.sort((o1, o2) -> {
APIManager.Auction auc1 = manager.auctionManager.getAuctionItems().get(o1);
APIManager.Auction auc2 = manager.auctionManager.getAuctionItems().get(o2);
@@ -1176,6 +1186,8 @@ public class CustomAH extends Gui {
}
return o1.compareTo(o2);
});
+
+ sortedAuctionIds = sortedAuctionIdsNew;
} catch(Exception e) {
shouldSortItems = true;
}
@@ -1371,7 +1383,7 @@ public class CustomAH extends Gui {
Utils.playPressSound();
}
}
- } else if(containerName.trim().equals("Confirm Bid")) {
+ } else if(containerName.trim().equals("Confirm Bid") || containerName.trim().equals("Confirm Purchase")) {
if(mouseX > guiLeft+getXSize()+4+31 && mouseX < guiLeft+getXSize()+4+31+16) {
if(mouseY > guiTop+31 && mouseY < guiTop+31+16) {
if(currentAucId != null) {
@@ -1444,6 +1456,7 @@ public class CustomAH extends Gui {
aucid = sortedAuctionIds.get(id);
} catch (IndexOutOfBoundsException e) { break out; }
+ if(aucid == null) continue;
APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(aucid);
if(auc != null) {
if(mouseX > itemX && mouseX < itemX+16) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java
index ae27be46..029e24db 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/SimpleCommand.java
@@ -3,21 +3,36 @@ package io.github.moulberry.notenoughupdates.commands;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
+import net.minecraft.util.BlockPos;
+
+import java.util.ArrayList;
+import java.util.List;
public class SimpleCommand extends CommandBase {
private String commandName;
private ProcessCommandRunnable runnable;
+ private TabCompleteRunnable tabRunnable;
public SimpleCommand(String commandName, ProcessCommandRunnable runnable) {
this.commandName = commandName;
this.runnable = runnable;
}
+ public SimpleCommand(String commandName, ProcessCommandRunnable runnable, TabCompleteRunnable tabRunnable) {
+ this.commandName = commandName;
+ this.runnable = runnable;
+ this.tabRunnable = tabRunnable;
+ }
+
public abstract static class ProcessCommandRunnable {
public abstract void processCommand(ICommandSender sender, String[] args);
}
+ public abstract static class TabCompleteRunnable {
+ public abstract List<String> tabComplete(ICommandSender sender, String[] args, BlockPos pos);
+ }
+
public boolean canCommandSenderUseCommand(ICommandSender sender) {
return true;
}
@@ -33,4 +48,9 @@ public class SimpleCommand extends CommandBase {
public void processCommand(ICommandSender sender, String[] args) throws CommandException {
runnable.processCommand(sender, args);
}
+
+ public List<String> addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) {
+ if(tabRunnable != null) return tabRunnable.tabComplete(sender, args, pos);
+ return null;
+ }
}
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 331ba8b1..9b42f5a6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -20,7 +20,7 @@ public class CapeManager {
public static final CapeManager INSTANCE = new CapeManager();
private HashMap<String, Pair<NEUCape, String>> capeMap = new HashMap<>();
- private String[] capes = new String[]{"testcape", "nullzee", "gravy", "fade", "contrib"};
+ private String[] capes = new String[]{"patreon1", "patreon2", "gravy", "fade", "contrib"};
public static CapeManager getInstance() {
return INSTANCE;
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 1ec2dee3..bcd5e26e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
@@ -110,14 +110,14 @@ public class CapeNode {
velocity.y -= gravity * (resistance)/(1-resistance);
float actualResistance = resistance;
- BlockPos pos = new BlockPos(
+ /*BlockPos pos = new BlockPos(
MathHelper.floor_double(position.x),
MathHelper.floor_double(position.y),
MathHelper.floor_double(position.z));
Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock();
if(block.getMaterial().isLiquid()) {
actualResistance = 0.8f;
- }
+ }*/
velocity.scale(1-actualResistance);
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 08d91057..9fc2a5ee 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
@@ -10,6 +10,7 @@ import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.potion.Potion;
import net.minecraft.util.BlockPos;
import net.minecraft.util.MathHelper;
import net.minecraft.util.ResourceLocation;
@@ -27,6 +28,7 @@ import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.security.Key;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -45,6 +47,8 @@ public class NEUCape {
public static float targetDist = 1/20f;
+ private EntityPlayer currentPlayer;
+
private String shaderName = "cape";
public NEUCape(String capeName) {
@@ -223,6 +227,10 @@ public class NEUCape {
public void onRenderPlayer(RenderPlayerEvent.Post e) {
EntityPlayer player = e.entityPlayer;
+ if(currentPlayer != null && currentPlayer != player) return;
+
+ if(player.getActivePotionEffect(Potion.invisibility) != null) return;
+
ensureCapeNodesCreated(player);
Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
@@ -258,9 +266,18 @@ public class NEUCape {
lastRender = System.currentTimeMillis();
}
+ private boolean notRendering = false;
public void onTick(TickEvent.ClientTickEvent event, EntityPlayer player) {
- if(player != null && System.currentTimeMillis() - lastRender < 100) {
- ensureCapeNodesCreated(Minecraft.getMinecraft().thePlayer);
+ if(player == null) return;
+
+ if(System.currentTimeMillis() - lastRender < 500) {
+ if(currentPlayer == null) {
+ currentPlayer = player;
+ } else if(currentPlayer != player) {
+ return;
+ }
+
+ ensureCapeNodesCreated(player);
for(int y=0; y<nodes.size(); y++) {
for(int x=0; x<nodes.get(y).size(); x++) {
@@ -271,6 +288,12 @@ public class NEUCape {
}
}
updateCape(player);
+
+ notRendering = false;
+ } else {
+ currentPlayer = null;
+
+ notRendering = true;
}
}
@@ -346,128 +369,129 @@ public class NEUCape {
private double oldPlayerAngle;
private int crouchTicks = 0;
long startTime = 0;
- long updateMillis = 0;
- long renderMillis = 0;
private void updateCape(EntityPlayer player) {
Vector3f capeTranslation = updateFixedCapeNodes(player);
- if(System.currentTimeMillis() - lastRender > 100) {
+ if(notRendering) {
for (int y = 0; y < nodes.size(); y++) {
for (int x = 0; x < nodes.get(y).size(); x++) {
- Vector3f.add(nodes.get(y).get(x).position, capeTranslation, nodes.get(y).get(x).position);
- nodes.get(y).get(x).lastPosition.set(nodes.get(y).get(x).position);
- nodes.get(y).get(x).renderPosition.set(nodes.get(y).get(x).position);
+ CapeNode node = nodes.get(y).get(x);
+ if(!node.fixed) {
+ Vector3f.add(node.position, capeTranslation, node.position);
+ node.lastPosition.set(node.position);
+ node.renderPosition.set(node.position);
+ }
}
}
- } else {
- double playerAngle = Math.toRadians(player.renderYawOffset);
- double deltaAngle = playerAngle - oldPlayerAngle;
- if(deltaAngle > Math.PI) {
- deltaAngle = 2*Math.PI - deltaAngle;
- }
- if(deltaAngle < -Math.PI) {
- deltaAngle = 2*Math.PI + deltaAngle;
- }
- deltaAngleAccum *= 0.5f;
- deltaAngleAccum += deltaAngle;
+ }
- float dX = (float)Math.cos(playerAngle+Math.PI/2f);
- float dZ = (float)Math.sin(playerAngle+Math.PI/2f);
+ double playerAngle = Math.toRadians(player.renderYawOffset);
+ double deltaAngle = playerAngle - oldPlayerAngle;
+ if(deltaAngle > Math.PI) {
+ deltaAngle = 2*Math.PI - deltaAngle;
+ }
+ if(deltaAngle < -Math.PI) {
+ deltaAngle = 2*Math.PI + deltaAngle;
+ }
+ deltaAngleAccum *= 0.5f;
+ deltaAngleAccum += deltaAngle;
- float factor = (float)(deltaAngleAccum*deltaAngleAccum);
+ float dX = (float)Math.cos(playerAngle+Math.PI/2f);
+ float dZ = (float)Math.sin(playerAngle+Math.PI/2f);
- tl.handleKeyboardInput();
+ float factor = (float)(deltaAngleAccum*deltaAngleAccum);
- float capeTransLength = capeTranslation.length();
+ tl.handleKeyboardInput();
- float capeTranslationFactor = 0f;
- if(capeTransLength > 0.5f) {
- capeTranslationFactor = (capeTransLength-0.5f)/capeTransLength;
- }
- Vector3f lookDir = new Vector3f(dX, 0, dZ);
- Vector3f lookDirNorm = lookDir.normalise(null);
- float dot = Vector3f.dot(capeTranslation, lookDirNorm);
- if(dot < 0) { //Moving backwards
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
- if(!node.fixed) {
- node.position.x += lookDirNorm.x*dot;
- node.position.y += lookDirNorm.y*dot;
- node.position.z += lookDirNorm.z*dot;
- }
- }
- }
- //Apply small backwards force
- factor = 0.05f;
- }
+ float capeTransLength = capeTranslation.length();
- if(factor > 0) {
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-dX*factor, 0, -dZ*factor);
+ float capeTranslationFactor = 0f;
+ if(capeTransLength > 0.5f) {
+ capeTranslationFactor = (capeTransLength-0.5f)/capeTransLength;
+ }
+ Vector3f lookDir = new Vector3f(dX, 0, dZ);
+ Vector3f lookDirNorm = lookDir.normalise(null);
+ float dot = Vector3f.dot(capeTranslation, lookDirNorm);
+ if(dot < 0) { //Moving backwards
+ for(int y=0; y<nodes.size(); y++) {
+ for(int x=0; x<nodes.get(y).size(); x++) {
+ CapeNode node = nodes.get(y).get(x);
+ if(!node.fixed) {
+ node.position.x += lookDirNorm.x*dot;
+ node.position.y += lookDirNorm.y*dot;
+ node.position.z += lookDirNorm.z*dot;
}
}
}
+ //Apply small backwards force
+ factor = 0.05f;
+ }
- if(capeTranslationFactor > 0f) {
- float capeDX = capeTranslation.x*capeTranslationFactor;
- float capeDY = capeTranslation.y*capeTranslationFactor;
- float capeDZ = capeTranslation.z*capeTranslationFactor;
-
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- CapeNode node = nodes.get(y).get(x);
- if(!node.fixed) {
- node.position.x += capeDX;
- node.position.y += capeDY;
- node.position.z += capeDZ;
- }
- }
+ if(factor > 0) {
+ for(int y=0; y<nodes.size(); y++) {
+ for(int x=0; x<nodes.get(y).size(); x++) {
+ nodes.get(y).get(x).applyForce(-dX*factor, 0, -dZ*factor);
}
}
+ }
- //Wind
- float currTime = (System.currentTimeMillis()-startTime)/1000f;
- float windRandom = Math.abs((float)(0.5f*Math.sin(0.22f*currTime)+Math.sin(0.44f*currTime)*Math.sin(0.47f*currTime)));
- double windDir = playerAngle+Math.PI/4f*Math.sin(0.2f*currTime);
+ if(capeTranslationFactor > 0f) {
+ float capeDX = capeTranslation.x*capeTranslationFactor;
+ float capeDY = capeTranslation.y*capeTranslationFactor;
+ float capeDZ = capeTranslation.z*capeTranslationFactor;
- float windDX = (float)Math.cos(windDir+Math.PI/2f);
- float windDZ = (float)Math.sin(windDir+Math.PI/2f);
for(int y=0; y<nodes.size(); y++) {
for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-windDX*windRandom*0.01f, 0, -windDZ*windRandom*0.01f);
+ CapeNode node = nodes.get(y).get(x);
+ if(!node.fixed) {
+ node.position.x += capeDX;
+ node.position.y += capeDY;
+ node.position.z += capeDZ;
+ }
}
}
+ }
- if(player.isSneaking()) {
- crouchTicks++;
- float mult = 0.5f;
- if(crouchTicks < 5) {
- mult = 2f;
- }
- for(int y=0; y<8; y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).applyForce(-dX*mult, 0, -dZ*mult);
- }
+ //Wind
+ float currTime = (System.currentTimeMillis()-startTime)/1000f;
+ float windRandom = Math.abs((float)(0.5f*Math.sin(0.22f*currTime)+Math.sin(0.44f*currTime)*Math.sin(0.47f*currTime)));
+ double windDir = playerAngle+Math.PI/4f*Math.sin(0.2f*currTime);
+
+ float windDX = (float)Math.cos(windDir+Math.PI/2f);
+ float windDZ = (float)Math.sin(windDir+Math.PI/2f);
+ for(int y=0; y<nodes.size(); y++) {
+ for(int x=0; x<nodes.get(y).size(); x++) {
+ nodes.get(y).get(x).applyForce(-windDX*windRandom*0.01f, 0, -windDZ*windRandom*0.01f);
+ }
+ }
+
+ if(player.isSneaking()) {
+ crouchTicks++;
+ float mult = 0.5f;
+ if(crouchTicks < 5) {
+ mult = 2f;
+ }
+ for(int y=0; y<8; y++) {
+ for(int x=0; x<nodes.get(y).size(); x++) {
+ nodes.get(y).get(x).applyForce(-dX*mult, 0, -dZ*mult);
}
- } else {
- crouchTicks = 0;
}
+ } else {
+ crouchTicks = 0;
+ }
- oldPlayerAngle = playerAngle;
+ oldPlayerAngle = playerAngle;
+ for(int y=0; y<nodes.size(); y++) {
+ for(int x=0; x<nodes.get(y).size(); x++) {
+ nodes.get(y).get(x).update();
+ }
+ }
+ int updates = player == Minecraft.getMinecraft().thePlayer ? 50 : 25;
+ for(int i=0; i<updates; i++) {
for(int y=0; y<nodes.size(); y++) {
for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).update();
- }
- }
- int updates = player == Minecraft.getMinecraft().thePlayer ? 50 : 25;
- for(int i=0; i<updates; i++) {
- for(int y=0; y<nodes.size(); y++) {
- for(int x=0; x<nodes.get(y).size(); x++) {
- nodes.get(y).get(x).resolveAll(2+1f*y/nodes.size(), false);
- }
+ nodes.get(y).get(x).resolveAll(2+1f*y/nodes.size(), false);
}
}
}
@@ -549,7 +573,7 @@ public class NEUCape {
private void renderCape(EntityPlayer player, float partialRenderTick) {
ensureCapeNodesCreated(player);
- if(System.currentTimeMillis() - lastRender > 100) {
+ if(System.currentTimeMillis() - lastRender > 500) {
updateCape(player);
}
updateFixedCapeNodesPartial(player, partialRenderTick);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
index 5f9e6af1..1516aae1 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
@@ -47,13 +47,13 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
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_TOOL = 5;
+ 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 String[] filterPrettyNames = new String[]{"ALL","WEAPON","ARMOR",
- "ACCESSORY","PET","TOOL","ZOMBIE SLAYER","WOLF SLAYER","SPIDER SLAYER"};
+ "ACCESSORY","PET","DUNGEON","ZOMBIE SLAYER","WOLF SLAYER","SPIDER SLAYER"};
private Framebuffer itemFramebuffer = null;
private Framebuffer itemBGFramebuffer = null;
@@ -94,8 +94,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
case FILTER_PET:
if(!internalname.matches(petRegex) || !item.get("displayname").getAsString().contains("[")) continue;
break;
- case FILTER_TOOL:
- if(overlay.checkItemType(lore, "AXE", "PICKAXE", "FISHING ROD", "SHOVEL", "HOE") < 0) continue;
+ 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;
@@ -241,19 +241,6 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
}
}
- 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;
- }
-
public int getCurrentAcquiredCount() {
if(getAcquiredItems() == null) return 0;
if(!getAcquiredItems().containsKey(manager.getCurrentProfile())) return 0;
@@ -268,7 +255,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
if(itemFramebuffer != null && grayscaleShader != null &&
(itemFramebuffer.framebufferWidth != width || itemFramebuffer.framebufferHeight != height)) {
- grayscaleShader.setProjectionMatrix(createProjectionMatrix(
+ grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix(
width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor()));
}
@@ -300,7 +287,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
grayscaleShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
"grayscale",
itemFramebuffer, itemFramebufferGrayscale);
- grayscaleShader.setProjectionMatrix(createProjectionMatrix(
+ grayscaleShader.setProjectionMatrix(Utils.createProjectionMatrix(
width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor()));
} catch(Exception e) {
return;
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 3c939589..23f4ad0b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
@@ -54,7 +54,9 @@ public class GuiElementTextField extends GuiElement {
}
public void setText(String text) {
- textField.setText(text);
+ if(textField.getText() == null || !textField.getText().equals(text)) {
+ textField.setText(text);
+ }
}
public void setSize(int searchBarXSize, int searchBarYSize) {
@@ -300,6 +302,7 @@ public class GuiElementTextField extends GuiElement {
if((options & FORCE_CAPS) != 0) typedChar = Character.toUpperCase(typedChar);
if((options & NO_SPACE) != 0 && typedChar == ' ') return;
+ textField.setFocused(true);
textField.textboxKeyTyped(typedChar, keyCode);
if((options & COLOUR) != 0) {
@@ -378,11 +381,18 @@ public class GuiElementTextField extends GuiElement {
textNoColor = matcher.replaceFirst("\u00B6"+code);
}
+ int xStartOffset = 5;
+ float scale = 1;
String[] texts = text.split("\n");
for(int yOffI = 0; yOffI < texts.length; yOffI++) {
int yOff = yOffI*extraSize;
if(isScaling() && Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])>searchBarXSize-10) {
+ scale = (searchBarXSize-2)/(float)Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI]);
+ if(scale > 1) scale=1;
+ float newLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])*scale;
+ xStartOffset = (int)((searchBarXSize-newLen)/2f);
+
Utils.drawStringCenteredScaledMaxWidth(texts[yOffI], Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f,
y+searchBarYSize/2f+yOff, false,
searchBarXSize-2, Color.WHITE.getRGB());
@@ -390,7 +400,6 @@ public class GuiElementTextField extends GuiElement {
Minecraft.getMinecraft().fontRendererObj.drawString(Utils.trimToWidth(texts[yOffI], searchBarXSize-10), x + 5,
y+(searchBarYSize-8)/2+yOff, Color.WHITE.getRGB());
}
-
}
if(focus && System.currentTimeMillis()%1000>500) {
@@ -406,22 +415,20 @@ public class GuiElementTextField extends GuiElement {
if(split.length <= numLinesBeforeCursor || split.length == 0) {
textBeforeCursorWidth = 0;
} else {
- textBeforeCursorWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length-1]);
+ textBeforeCursorWidth = (int)(Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length-1])*scale);
}
- drawRect(x + 5 + textBeforeCursorWidth,
+ drawRect(x + xStartOffset + textBeforeCursorWidth,
y+(searchBarYSize-8)/2-1 + yOff,
- x + 5 + textBeforeCursorWidth+1,
+ x + xStartOffset + textBeforeCursorWidth+1,
y+(searchBarYSize-8)/2+9 + yOff, Color.WHITE.getRGB());
}
String selectedText = textField.getSelectedText();
if(!selectedText.isEmpty()) {
- int leftIndex = textField.getCursorPosition() < textField.getSelectionEnd() ?
- textField.getCursorPosition() : textField.getSelectionEnd();
- int rightIndex = textField.getCursorPosition() > textField.getSelectionEnd() ?
- textField.getCursorPosition() : textField.getSelectionEnd();
+ int leftIndex = Math.min(textField.getCursorPosition(), textField.getSelectionEnd());
+ int rightIndex = Math.max(textField.getCursorPosition(), textField.getSelectionEnd());
- int texX = 0;
+ float texX = 0;
int texY = 0;
boolean sectionSignPrev = false;
boolean bold = false;
@@ -440,9 +447,9 @@ public class GuiElementTextField extends GuiElement {
if(c == '\n') {
if(i >= leftIndex && i < rightIndex) {
- drawRect(x + 5 + texX,
+ drawRect(x + xStartOffset + (int)texX,
y+(searchBarYSize-8)/2-1 + texY,
- x + 5 + texX + 3,
+ x + xStartOffset + (int)texX + 3,
y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB());
}
@@ -456,22 +463,22 @@ public class GuiElementTextField extends GuiElement {
int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c));
if(bold) len++;
if(i >= leftIndex && i < rightIndex) {
- drawRect(x + 5 + texX,
+ drawRect(x + xStartOffset + (int)texX,
y+(searchBarYSize-8)/2-1 + texY,
- x + 5 + texX + len,
+ x + xStartOffset + (int)(texX + len*scale),
y+(searchBarYSize-8)/2+9 + texY, Color.LIGHT_GRAY.getRGB());
- Minecraft.getMinecraft().fontRendererObj.drawString(String.valueOf(c),
- x + 5 + texX,
- y+(searchBarYSize-8)/2 + texY, Color.BLACK.getRGB());
+ Utils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj,
+ x + xStartOffset + texX,
+ y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale);
if(bold) {
- Minecraft.getMinecraft().fontRendererObj.drawString(String.valueOf(c),
- x + 5 + texX +1,
- y+(searchBarYSize-8)/2 + texY, Color.BLACK.getRGB());
+ Utils.drawStringScaled(String.valueOf(c), Minecraft.getMinecraft().fontRendererObj,
+ x + xStartOffset + texX + 1,
+ y+searchBarYSize/2f-scale*8/2f + texY, false, Color.BLACK.getRGB(), scale);
}
}
- texX += len;
+ texX += len*scale;
}
}
}
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 7f0eb46f..06dfd246 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
@@ -9,7 +9,9 @@ public class MBAnchorPoint implements Serializable {
public enum AnchorPoint {
TOPLEFT(0, 0), TOPMID(0.5f, 0), TOPRIGHT(1, 0),
MIDRIGHT(1, 0.5f), BOTRIGHT(1, 1), BOTMID(0.5f, 1),
- BOTLEFT(0, 1), MIDLEFT(0, 0.5f), MIDMID(0.5f, 0.5f);
+ BOTLEFT(0, 1), MIDLEFT(0, 0.5f), MIDMID(0.5f, 0.5f),
+
+ INV_BOTMID(0.5f, 1f);
public final float x;
public final float y;
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 4759d99b..aba1d743 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
@@ -54,8 +54,10 @@ public abstract class MBGuiGroup extends MBGuiElement {
@Override
public void render(float x, float y) {
+ Map<MBGuiElement, Vector2f> childrenPos = getChildrenPosition();
+
for(MBGuiElement child : getChildren()) {
- Vector2f childPos = childrenPosition.get(child);
+ Vector2f childPos = childrenPos.get(child);
child.render(x+childPos.x, y+childPos.y);
}
}
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 91cca2d7..6bdd25fd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
@@ -1,5 +1,9 @@
package io.github.moulberry.notenoughupdates.mbgui;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiContainer;
import org.lwjgl.util.vector.Vector2f;
import java.util.*;
@@ -7,6 +11,8 @@ import java.util.*;
public class MBGuiGroupFloating extends MBGuiGroup {
private LinkedHashMap<MBGuiElement, MBAnchorPoint> children;
+ private GuiContainer lastContainer = null;
+ private HashMap<MBGuiElement, Vector2f> childrenPositionOffset = new HashMap<>();
public MBGuiGroupFloating(int width, int height, LinkedHashMap<MBGuiElement, MBAnchorPoint> children) {
this.width = width;
@@ -20,7 +26,53 @@ public class MBGuiGroupFloating extends MBGuiGroup {
}
@Override
+ public Map<MBGuiElement, Vector2f> getChildrenPosition() {
+ GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
+
+ if(currentScreen instanceof GuiContainer) {
+ GuiContainer currentContainer = (GuiContainer) currentScreen;
+ if(lastContainer != currentContainer) {
+ lastContainer = currentContainer;
+ for(Map.Entry<MBGuiElement, MBAnchorPoint> entry : children.entrySet()) {
+ MBGuiElement child = entry.getKey();
+ MBAnchorPoint anchorPoint = entry.getValue();
+
+ Vector2f childPos;
+ if(childrenPosition.containsKey(child)) {
+ childPos = new Vector2f(childrenPosition.get(child));
+ } else {
+ childPos = new Vector2f();
+ }
+
+ if(anchorPoint.anchorPoint == MBAnchorPoint.AnchorPoint.INV_BOTMID) {
+ try {
+ int xSize = (int) Utils.getField(GuiContainer.class, currentContainer, "xSize", "field_146999_f");
+ int ySize = (int) Utils.getField(GuiContainer.class, currentContainer, "ySize", "field_147000_g");
+ int guiLeft = (int) Utils.getField(GuiContainer.class, currentContainer, "guiLeft", "field_147003_i");
+ int guiTop = (int) Utils.getField(GuiContainer.class, currentContainer, "guiTop", "field_147009_r");
+
+ int defGuiLeft = (this.width - xSize) / 2;
+ int defGuiTop = (this.height - ySize) / 2;
+
+ childPos.x += guiLeft-defGuiLeft + (anchorPoint.anchorPoint.x-0.5f)*xSize;
+ childPos.y += guiTop-defGuiTop + (anchorPoint.anchorPoint.y-0.5f)*ySize;
+ } catch(Exception ignored) {
+ }
+ }
+
+ childrenPositionOffset.put(child, childPos);
+ }
+ }
+ return Collections.unmodifiableMap(childrenPositionOffset);
+ } else {
+ return Collections.unmodifiableMap(childrenPosition);
+ }
+ }
+
+ @Override
public void recalculate() {
+ lastContainer = null;
+
for(MBGuiElement child : children.keySet()) {
child.recalculate();
}
@@ -30,6 +82,12 @@ public class MBGuiGroupFloating extends MBGuiGroup {
MBAnchorPoint anchorPoint = entry.getValue();
float x = anchorPoint.anchorPoint.x * width - anchorPoint.anchorPoint.x * child.getWidth() + anchorPoint.offset.x;
float y = anchorPoint.anchorPoint.y * height - anchorPoint.anchorPoint.y * child.getHeight() + anchorPoint.offset.y;
+
+ if(anchorPoint.anchorPoint == MBAnchorPoint.AnchorPoint.INV_BOTMID) {
+ x = width*0.5f + anchorPoint.offset.x;
+ y = height*0.5f + anchorPoint.offset.y;
+ }
+
childrenPosition.put(child, new Vector2f(x, y));
}
}
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 51c85b19..00fdc873 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java
@@ -4,6 +4,7 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import net.minecraft.client.renderer.InventoryEffectRenderer;
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.ModifyVariable;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
new file mode 100644
index 00000000..67f0f7dc
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
@@ -0,0 +1,53 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.ItemRarityHalo;
+import io.github.moulberry.notenoughupdates.NEUResourceManager;
+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.OpenGlHelper;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.model.IBakedModel;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.Matrix4f;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL30;
+import org.lwjgl.util.vector.Vector4f;
+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.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+import javax.vecmath.Vector3f;
+import java.awt.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+
+@Mixin({RenderItem.class})
+public abstract class MixinRenderItem {
+
+ //Lnet/minecraft/client/renderer/entity/RenderItem;renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/resources/model/IBakedModel;)V
+ @Inject(method="Lnet/minecraft/client/renderer/entity/RenderItem;renderItemIntoGUI(Lnet/minecraft/item/ItemStack;II)V",
+ at=@At("HEAD"), cancellable = true)
+ public void renderItemIntoGUI(ItemStack stack, int x, int y, CallbackInfo ci) {
+ if(x == 0 && y == 0 || true) return;
+ ItemRarityHalo.onItemRender(stack, x, y);
+
+ if(Keyboard.isKeyDown(Keyboard.KEY_H)) ci.cancel();
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
index 1c8a6e07..88165d08 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
@@ -1,6 +1,7 @@
package io.github.moulberry.notenoughupdates.options;
import com.google.gson.*;
+import io.github.moulberry.notenoughupdates.GuiEnchantColour;
import io.github.moulberry.notenoughupdates.NEUOverlayPlacements;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint;
@@ -77,11 +78,6 @@ public class Options {
"Hide Apikey Setting",
false,
"Hides the Apikey setting (please try not to leak Apikey if you're recording)");
- public Option<Boolean> quickAHUpdate = new Option(
- false,
- "NeuAH Quick Update",
- false,
- "Will instantly update the whole AH when an api update is detected (aka as fast as possible). Warning: Uses lots of data.");
public Option<Double> bgBlurFactor = new Option(
5.0,
"Background Blur",
@@ -137,6 +133,11 @@ public class Options {
"Item Background Opacity",
false,
"Changes the opacity of item background. Value between 0-255.", 0, 255);
+ public Option<Double> itemHighlightOpacity = new Option(
+ 178.0,
+ "Item Highlight Opacity",
+ false,
+ "Changes the opacity of item highlights. Value between 0-255.", 0, 255);
public Option<Double> panePadding = new Option(
10.0,
"Pane Padding",
@@ -161,6 +162,11 @@ public class Options {
"Show Dev Options",
true,
"Dev Feature. Please don't use.");
+ public Option<Boolean> loadedModBefore = new Option(
+ false,
+ "loadedModBefore",
+ true,
+ "loadedModBefore");
public Option<String> selectedCape = new Option(
"",
"Selected Cape",
@@ -206,6 +212,17 @@ public class Options {
"OverlaySearchBar",
false,
"OverlaySearchBar");
+ public Option<List<String>> enchantColours = new Option(
+ Utils.createList("[a-zA-Z ]+:\u003e:9:6",
+ "[a-zA-Z ]+:\u003e:6:c",
+ "[a-zA-Z ]+:\u003e:5:5",
+ "Experience:\u003e:3:5",
+ "Life Steal:\u003e:3:5",
+ "Scavenger:\u003e:3:5",
+ "Looting:\u003e:3:5"),
+ "enchantColours",
+ false,
+ "enchantColours");
private ArrayList<String> createDefaultQuickCommands() {
ArrayList<String> arr = new ArrayList<>();
@@ -233,14 +250,16 @@ public class Options {
}
private transient List<Button> buttons = new ArrayList<>();
+
{
buttons.add(new Button("Open Config Folder", "Opens the config folder. Be careful.", () -> {
- if(Desktop.isDesktopSupported()) {
+ if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
- if(NotEnoughUpdates.INSTANCE.manager.configFile.getParentFile().exists()) {
+ if (NotEnoughUpdates.INSTANCE.manager.configFile.getParentFile().exists()) {
try {
desktop.open(NotEnoughUpdates.INSTANCE.manager.configFile.getParentFile());
- } catch(IOException ignored) {}
+ } catch (IOException ignored) {
+ }
}
}
}));
@@ -248,6 +267,11 @@ public class Options {
buttons.add(new Button("Edit Gui Positions", "Allows you to change the position of the search bar, etc.", () -> {
Minecraft.getMinecraft().displayGuiScreen(new NEUOverlayPlacements());
}));
+
+
+ buttons.add(new Button("Edit Enchant Colours", "Allows you to change the colour of any enchant at any level.", () -> {
+ Minecraft.getMinecraft().displayGuiScreen(new GuiEnchantColour());
+ }));
}
public List<Button> getButtons() {
@@ -257,6 +281,8 @@ public class Options {
public List<Option> getOptions() {
List<Option> options = new ArrayList<>();
+ //Pane width near top so less scuffed
+ tryAddOption(paneWidthMult, options);
//Buttons
tryAddOption(enableItemEditing, options);
tryAddOption(onlyShowOnSkyblock, options);
@@ -268,7 +294,6 @@ public class Options {
tryAddOption(tooltipBorderColours, options);
tryAddOption(hideApiKey, options);
tryAddOption(streamerMode, options);
- tryAddOption(quickAHUpdate, options);
tryAddOption(autoupdate, options);
tryAddOption(cacheRenderedItempane, options);
tryAddOption(itemStyle, options);
@@ -276,10 +301,10 @@ public class Options {
tryAddOption(disableItemTabOpen, options);
//Sliders
tryAddOption(bgBlurFactor, options);
- tryAddOption(paneWidthMult, options);
tryAddOption(ahNotification, options);
tryAddOption(bgOpacity, options);
tryAddOption(fgOpacity, options);
+ tryAddOption(itemHighlightOpacity, options);
tryAddOption(panePadding, options);
tryAddOption(tooltipBorderOpacity, options);
//Text
@@ -289,7 +314,7 @@ public class Options {
}
private void tryAddOption(Option<?> option, List<Option> list) {
- if(!option.secret) {// || dev.value) {
+ if (!option.secret) {// || dev.value) {
list.add(option);
}
}
@@ -318,19 +343,19 @@ public class Options {
}
public void setValue(String value) {
- if(this.value instanceof Boolean) {
+ if (this.value instanceof Boolean) {
((Option<Boolean>) this).value = Boolean.valueOf(value);
- } else if(this.value instanceof Double) {
- ((Option<Double>)this).value = Double.valueOf(value);
- } else if(this.value instanceof String) {
- ((Option<String>)this).value = value;
+ } else if (this.value instanceof Double) {
+ ((Option<Double>) this).value = Double.valueOf(value);
+ } else if (this.value instanceof String) {
+ ((Option<String>) this).value = value;
}
}
}
public static JsonSerializer<Option<?>> createSerializer() {
return (src, typeOfSrc, context) -> {
- if(src.secret && src.defaultValue.equals(src.value)) {
+ if (src.secret && src.defaultValue.equals(src.value)) {
return null;
}
return context.serialize(src.value);
@@ -341,7 +366,7 @@ public class Options {
return (json, typeOfT, context) -> {
try {
return new Option(context.deserialize(json, Object.class), "unknown", false, "unknown");
- } catch(Exception e) {
+ } catch (Exception e) {
return null;
}
};
@@ -353,22 +378,24 @@ public class Options {
Options oLoad = gson.fromJson(reader, Options.class);
Options oDefault = new Options();
- if(oLoad == null) return oDefault;
+ if (oLoad == null) return oDefault;
- for(Field f : Options.class.getDeclaredFields()) {
+ for (Field f : Options.class.getDeclaredFields()) {
try {
- if(((Option)f.get(oDefault)).value instanceof List) {
+ if (((Option) f.get(oDefault)).value instanceof List) {
//If the default size of the list is greater than the loaded size, use the default value.
- if(((List<?>)((Option)f.get(oDefault)).value).size() > ((List<?>)((Option)f.get(oLoad)).value).size()) {
- continue;
- }
+ //if(((List<?>)((Option)f.get(oDefault)).value).size() > ((List<?>)((Option)f.get(oLoad)).value).size()) {
+ // continue;
+ //}
}
- ((Option)f.get(oDefault)).value = ((Option)f.get(oLoad)).value;
- } catch (Exception e) { }
+ ((Option) f.get(oDefault)).value = ((Option) f.get(oLoad)).value;
+ } catch (Exception e) {
+ }
}
return oDefault;
}
+
public void saveToFile(Gson gson, File file) throws IOException {
file.createNewFile();
@@ -377,6 +404,4 @@ public class Options {
writer.write(gson.toJson(this));
}
}
-
-
-}
+} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
new file mode 100644
index 00000000..76da035a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
@@ -0,0 +1,2473 @@
+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.google.gson.JsonPrimitive;
+import com.mojang.authlib.GameProfile;
+import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import com.mojang.authlib.properties.Property;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.SBAIntegration;
+import io.github.moulberry.notenoughupdates.cosmetics.ShaderManager;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.questing.SBScoreboardData;
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityOtherPlayerMP;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.texture.TextureUtil;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.client.resources.IResourceManagerReloadListener;
+import net.minecraft.client.resources.SkinManager;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+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.util.*;
+import net.minecraft.world.World;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.Charsets;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.text.WordUtils;
+import org.luaj.vm2.ast.Str;
+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;
+
+import java.awt.*;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+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_extra = new ResourceLocation("notenoughupdates:pv_extra.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");
+ public static final ResourceLocation resource_packs = new ResourceLocation("minecraft:textures/gui/resource_packs.png");
+ private static final ResourceLocation creativeInventoryTabs =
+ new ResourceLocation("textures/gui/container/creative_inventory/tabs.png");
+
+ private static final NumberFormat numberFormat = NumberFormat.getInstance(Locale.US);
+
+ private final ProfileViewer.Profile profile;
+ private 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;
+ private boolean profileDropdownSelected = false;
+
+ public enum ProfileViewerPage {
+ LOADING(null),
+ INVALID_NAME(null),
+ BASIC(new ItemStack(Items.paper)),
+ EXTRA(new ItemStack(Items.book)),
+ INVS(new ItemStack(Item.getItemFromBlock(Blocks.ender_chest))),
+ COLS(new ItemStack(Items.painting)),
+ PETS(new ItemStack(Items.bone));
+
+ public final ItemStack stack;
+
+
+ ProfileViewerPage(ItemStack stack) {
+ this.stack = stack;
+ }
+ }
+
+ public GuiProfileViewer(ProfileViewer.Profile profile) {
+ this.profile = profile;
+ String name = "";
+ if(profile != null) {
+ name = profile.getHypixelProfile().get("displayname").getAsString();
+ }
+ playerNameTextField = new GuiElementTextField(name,
+ GuiElementTextField.SCALE_TEXT);
+ playerNameTextField.setSize(100, 20);
+ }
+
+ private GuiElementTextField playerNameTextField;
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ currentTime = System.currentTimeMillis();
+ if(startTime == 0) startTime = currentTime;
+
+ if(profile == null) {
+ currentPage = ProfileViewerPage.INVALID_NAME;
+ }
+ if(profileId == null && profile != null && profile.getLatestProfile() != null) {
+ profileId = profile.getLatestProfile();
+ }
+
+ this.sizeX = 431;
+ this.sizeY = 202;
+ 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);
+
+ GlStateManager.enableDepth();
+ GlStateManager.translate(0, 0, 5);
+ renderTabs(true);
+ GlStateManager.translate(0, 0, -3);
+
+ GlStateManager.disableDepth();
+ GlStateManager.translate(0, 0, -2);
+ renderTabs(false);
+ GlStateManager.translate(0, 0, 2);
+
+ GlStateManager.disableLighting();
+ GlStateManager.enableDepth();
+ 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_bg);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
+
+ if(!(currentPage == ProfileViewerPage.LOADING)) {
+ playerNameTextField.render(guiLeft+sizeX-100, guiTop+sizeY+5);
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ if(profile != null) {
+ 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());
+
+ if(profileDropdownSelected && !profile.getProfileIds().isEmpty() && scaledResolution.getScaleFactor() != 4) {
+ int dropdownOptionSize = scaledResolution.getScaleFactor()==3?10:20;
+
+ int numProfiles = profile.getProfileIds().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+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);
+
+ for(int yIndex=0; yIndex<profile.getProfileIds().size(); yIndex++) {
+ String otherProfileId = profile.getProfileIds().get(yIndex);
+ Utils.drawStringCenteredScaledMaxWidth(otherProfileId, Minecraft.getMinecraft().fontRendererObj, guiLeft+50,
+ guiTop+sizeY+23+dropdownOptionSize/2f+dropdownOptionSize*yIndex, true, 90, new Color(33, 112, 104, 255).getRGB());
+ }
+
+ }
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ switch (currentPage) {
+ case BASIC:
+ drawBasicPage(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 LOADING:
+ Utils.drawStringCentered(EnumChatFormatting.YELLOW+"Loading player profiles...", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+sizeX/2f, guiTop+101, true, 0);
+ 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;
+ }
+
+ lastTime = currentTime;
+
+ 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;
+ }
+ }
+
+ private boolean isLoadedProfile() {
+ return profile.getProfileInformation(profileId) != null;
+ }
+
+ 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) {
+ ignoredTabs++;
+ continue;
+ }
+ boolean pressed = page == currentPage;
+ if(pressed == renderPressed) {
+ renderTab(page.stack, i-ignoredTabs, pressed);
+ }
+ }
+ }
+
+ private void renderTab(ItemStack stack, int xIndex, 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+xIndex*28;
+ int y = guiTop-28;
+
+ float uMin = 0;
+ float uMax = 28/256f;
+ float vMin = 20/256f;
+ float vMax = 51/256f;
+ if(pressed) {
+ vMin = 52/256f;
+ vMax = 84/256f;
+
+ if(xIndex != 0) {
+ uMin = 28/256f;
+ uMax = 56/256f;
+ }
+
+ renderBlurredBackground(width, height, x+2, y+2, 28-4, 28-4);
+ } else {
+ renderBlurredBackground(width, height, x+2, y+4, 28-4, 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, 28, pressed?32:31, uMin, uMax, vMin, vMax, GL11.GL_NEAREST);
+
+ GlStateManager.enableDepth();
+ Utils.drawItemStack(stack, x+6, y+9);
+ }
+
+ @Override
+ 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) {
+ 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(currentPage != page) Utils.playPressSound();
+ currentPage = page;
+ inventoryTextField.otherComponentClick();
+ playerNameTextField.otherComponentClick();
+ return;
+ }
+ }
+ }
+ }
+ switch (currentPage) {
+ 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(mouseX > guiLeft+sizeX-100 && mouseX < guiLeft+sizeX) {
+ if(mouseY > guiTop+sizeY+5 && mouseY < guiTop+sizeY+25) {
+ playerNameTextField.mouseClicked(mouseX, mouseY, mouseButton);
+ inventoryTextField.otherComponentClick();
+ return;
+ }
+ }
+ if(mouseX > guiLeft && mouseX < guiLeft+100 && profile != null && !profile.getProfileIds().isEmpty()) {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ if(mouseY > guiTop+sizeY+3 && mouseY < guiTop+sizeY+23) {
+ 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)) {
+ profileNum = index;
+ break;
+ }
+ }
+ if(mouseButton == 0) {
+ profileNum++;
+ } else {
+ profileNum--;
+ }
+ if(profileNum >= profile.getProfileIds().size()) profileNum = 0;
+ if(profileNum < 0) profileNum = profile.getProfileIds().size()-1;
+
+ String newProfileId = profile.getProfileIds().get(profileNum);
+ if(profileId != null && !profileId.equals(newProfileId)) {
+ resetCache();
+ }
+ profileId = newProfileId;
+ } else {
+ profileDropdownSelected = !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(profileId != null && !profileId.equals(newProfileId)) {
+ resetCache();
+ }
+ profileId = newProfileId;
+ }
+ }
+ playerNameTextField.otherComponentClick();
+ inventoryTextField.otherComponentClick();
+ return;
+ }
+ profileDropdownSelected = false;
+ playerNameTextField.otherComponentClick();
+ inventoryTextField.otherComponentClick();
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ super.keyTyped(typedChar, keyCode);
+ SBAIntegration.keyTyped(keyCode);
+ switch (currentPage) {
+ case INVS:
+ keyTypedInvs(typedChar, keyCode);
+ inventoryTextField.keyTyped(typedChar, keyCode);
+ break;
+ case COLS:
+ keyTypedCols(typedChar, keyCode);
+ break;
+ }
+ if(playerNameTextField.getFocus() && !(currentPage == ProfileViewerPage.LOADING)) {
+ 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));
+ });
+ }
+ playerNameTextField.keyTyped(typedChar, keyCode);
+ }
+ }
+
+ @Override
+ 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 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 = "talisman_bag"; break;
+ case Keyboard.KEY_4:
+ case Keyboard.KEY_NUMPAD4:
+ selectedInventory = "wardrobe_contents"; break;
+ case Keyboard.KEY_5:
+ case Keyboard.KEY_NUMPAD5:
+ selectedInventory = "fishing_bag"; break;
+ case Keyboard.KEY_6:
+ case Keyboard.KEY_NUMPAD6:
+ 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;
+ JsonObject collectionInfo = profile.getCollectionInfo(profileId);
+ if(collectionInfo == null) return;
+
+ ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, collectionInfo, 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;
+
+ if(mouseY > y+invSizeY && mouseY < y+invSizeY+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 class Level {
+ float level;
+ float currentLevelRequirement;
+ float maxXP;
+ }
+
+ public Level getLevel(JsonArray levels, int offset, float exp) {
+ float xpTotal = 0;
+ float level = 1;
+ float currentLevelRequirement = 0;
+ float remainingToNextLevel = 0;
+
+ boolean addLevel = true;
+
+ for(int i=offset; i<offset+99; i++) {
+
+ if(addLevel) {
+ currentLevelRequirement = levels.get(i).getAsFloat();
+ xpTotal += currentLevelRequirement;
+ if(xpTotal > exp) {
+ remainingToNextLevel = (exp-(xpTotal-currentLevelRequirement))/currentLevelRequirement;
+ addLevel = false;
+ } else {
+ level += 1;
+ }
+ } else {
+ xpTotal += levels.get(i).getAsFloat();
+ }
+ }
+
+ level += remainingToNextLevel;
+ if(level <= 0) {
+ level = 1;
+ } else if(level > 100) {
+ level = 100;
+ }
+ Level levelObj = new Level();
+ levelObj.level = level;
+ levelObj.currentLevelRequirement = currentLevelRequirement;
+ levelObj.maxXP = xpTotal;
+ return levelObj;
+ }
+
+ private static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS = new HashMap<>();
+ static {
+ HashMap<String, Float> bigTeeth = new HashMap<>();
+ bigTeeth.put("CRIT_CHANCE", 5f);
+ PET_STAT_BOOSTS.put("PET_ITEM_BIG_TEETH_COMMON", bigTeeth);
+
+ HashMap<String, Float> hardenedScales = new HashMap<>();
+ hardenedScales.put("DEFENCE", 25f);
+ PET_STAT_BOOSTS.put("PET_ITEM_HARDENED_SCALES_UNCOMMON", hardenedScales);
+
+ HashMap<String, Float> luckyClover = new HashMap<>();
+ luckyClover.put("MAGIC_FIND", 7f);
+ PET_STAT_BOOSTS.put("PET_ITEM_LUCKY_CLOVER", luckyClover);
+
+ HashMap<String, Float> sharpenedClaws = new HashMap<>();
+ sharpenedClaws.put("CRIT_DAMAGE", 15f);
+ PET_STAT_BOOSTS.put("PET_ITEM_SHARPENED_CLAWS_UNCOMMON", sharpenedClaws);
+ }
+ private static final HashMap<String, HashMap<String, Float>> PET_STAT_BOOSTS_MULT = new HashMap<>();
+ static {
+ HashMap<String, Float> ironClaws = new HashMap<>();
+ ironClaws.put("CRIT_DAMAGE", 1.4f);
+ ironClaws.put("CRIT_CHANCE", 1.4f);
+ PET_STAT_BOOSTS_MULT.put("PET_ITEM_IRON_CLAWS_COMMON", ironClaws);
+
+ HashMap<String, Float> textbook = new HashMap<>();
+ textbook.put("INTELLIGENCE", 2f);
+ PET_STAT_BOOSTS_MULT.put("PET_ITEM_TEXTBOOK", textbook);
+ }
+
+ private int selectedPet = -1;
+ private int petsPage = 0;
+ private List<JsonObject> sortedPets = null;
+ private List<ItemStack> sortedPetsStack = null;
+ private static HashMap<String, String> minionRarityToNumMap = new HashMap<>();
+ static {
+ minionRarityToNumMap.put("COMMON", "0");
+ minionRarityToNumMap.put("UNCOMMON", "1");
+ minionRarityToNumMap.put("RARE", "2");
+ minionRarityToNumMap.put("EPIC", "3");
+ minionRarityToNumMap.put("LEGENDARY", "4");
+ }
+ private void drawPetsPage(int mouseX, int mouseY, float partialTicks) {
+ JsonObject petsInfo = profile.getPetsInfo(profileId);
+ if(petsInfo == null) return;
+ JsonObject petsJson = Utils.getConstant("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(SBScoreboardData.getInstance().currentTimeDate != null) {
+ if(SBScoreboardData.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBScoreboardData.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 = minionRarityToNumMap.get(tier1);
+ int tierNum1I = Integer.parseInt(tierNum1);
+ float exp1 = pet1.get("exp").getAsFloat();
+
+ String tier2 = pet2.get("tier").getAsString();
+ String tierNum2 = minionRarityToNumMap.get(tier2);
+ 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);
+ JsonObject heldItemJson = heldItem==null?null:NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(heldItem);
+ String tierNum = minionRarityToNumMap.get(tier);
+ float exp = pet.get("exp").getAsFloat();
+ if(tierNum == null) continue;
+
+ if(pet.has("heldItem") && pet.get("heldItem").getAsString().equals("PET_ITEM_TIER_BOOST")) {
+ tierNum = ""+(Integer.parseInt(tierNum)+1);
+ }
+
+ int petRarityOffset = petsJson.get("pet_rarity_offset").getAsJsonObject().get(tier).getAsInt();
+ JsonArray levelsArr = petsJson.get("pet_levels").getAsJsonArray();
+
+ Level levelObj = getLevel(levelsArr, petRarityOffset, 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 newNewLore = new NBTTagList();
+ 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(heldItemJson != null && secondLastBlank != null) {
+ for(int j=0; j<newLore.tagCount(); j++) {
+ String line = newLore.getStringTagAt(j);
+
+ if(j == secondLastBlank.intValue()) {
+ newNewLore.appendTag(new NBTTagString(""));
+ newNewLore.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) {
+ newNewLore.appendTag(new NBTTagString(heldItemLine));
+ } else if(blanks>2) {
+ break;
+ }
+ }
+ }
+
+ newNewLore.appendTag(new NBTTagString(line));
+ }
+ display.setTag("Lore", newNewLore);
+ } else {
+ 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, sortedPets.size()); i++) {
+ JsonObject pet = sortedPets.get(i);
+ ItemStack stack = sortedPetsStack.get(i);
+ if(pet != null) {
+ 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);
+ Utils.drawTexturedRect(guiLeft+x, guiTop+y, 20, 20,
+ 0, 20/256f, 0, 20/256f, GL11.GL_NEAREST);
+ } 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);
+ String type = pet.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+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.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);
+
+ ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(item);
+ GlStateManager.scale(-3.5f, 3.5f, 1);
+ GlStateManager.enableDepth();
+ Utils.drawItemStack(stack, 0, 0);
+ GlStateManager.scale(-1/3.5f, 1/3.5f, 1);
+ GlStateManager.translate(-x, -y, 0);
+ break;
+ }
+ }
+
+ 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];
+
+ 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);
+
+ 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);
+
+ 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);
+
+ renderAlignedString(EnumChatFormatting.YELLOW+"Total XP", EnumChatFormatting.WHITE.toString()+shortNumberFormat(exp, 0), guiLeft+319, guiTop+125, 98);
+ renderAlignedString(EnumChatFormatting.YELLOW+"Current LVL XP",
+ EnumChatFormatting.WHITE.toString()+shortNumberFormat((level%1)*currentLevelRequirement, 0), guiLeft+319, guiTop+143, 98);
+ renderAlignedString(EnumChatFormatting.YELLOW+"Required LVL XP", EnumChatFormatting.WHITE.toString()+shortNumberFormat(currentLevelRequirement, 0), guiLeft+319, guiTop+161, 98);
+ }
+ }
+
+ private 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);
+
+ float MAX_MINION_TIER = 11f;
+ 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 minionJson = NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(minion+"_GENERATOR_1");
+ 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;
+ int tier = (int)Utils.getElementAsFloat(minionTiers.get(minion), 0);
+ 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<>();
+ static {
+ invNameToDisplayMap.put("inv_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.chest), EnumChatFormatting.GRAY+"Inventory"));
+ invNameToDisplayMap.put("ender_chest_contents", Utils.createItemStack(Item.getItemFromBlock(Blocks.ender_chest), EnumChatFormatting.GRAY+"Ender Chest"));
+ invNameToDisplayMap.put("talisman_bag", Utils.createItemStack(Items.golden_apple, EnumChatFormatting.GRAY+"Accessory Bag"));
+ invNameToDisplayMap.put("wardrobe_contents", Utils.createItemStack(Items.leather_chestplate, EnumChatFormatting.GRAY+"Wardrobe"));
+ invNameToDisplayMap.put("fishing_bag", Utils.createItemStack(Items.fish, EnumChatFormatting.GRAY+"Fishing Bag"));
+ invNameToDisplayMap.put("potion_bag", Utils.createItemStack(Items.potionitem, EnumChatFormatting.GRAY+"Potion Bag"));
+ }
+
+ public int countItemsInInventory(String internalname, JsonObject inventoryInfo, 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(item.get("internalname").getAsString().equals(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;
+ }
+ return 6;
+ }
+
+ private int getIgnoredRowsForInventory(String invName) {
+ switch(invName) {
+ case "talisman_bag":
+ case "fishing_bag":
+ case "potion_bag":
+ return 1;
+ }
+ return 0;
+ }
+
+ private int getAvailableSlotsForInventory(JsonObject inventoryInfo, JsonObject collectionInfo, String invName) {
+ if(collectionInfo == null) return -1;
+ JsonObject misc = Utils.getConstant("misc");
+ if(misc == null) return -1;
+ JsonElement sizesElement = Utils.getElement(misc, "bag_size."+invName+".sizes");
+ JsonElement collectionElement = Utils.getElement(misc, "bag_size."+invName+".collection");
+
+ if(sizesElement == null || !sizesElement.isJsonArray()) return -1;
+ if(collectionElement == null || !collectionElement.isJsonPrimitive()) return -1;
+
+ JsonArray sizes = sizesElement.getAsJsonArray();
+ String collection = collectionElement.getAsString();
+
+ JsonElement tierElement = Utils.getElement(collectionInfo, "collection_tiers."+collection);
+
+ if(tierElement == null || !tierElement.isJsonPrimitive()) {
+ return 0;
+ }
+ int tier = tierElement.getAsInt();
+
+ int currentSlots = 0;
+ for(int i=0; i<sizes.size(); i++) {
+ JsonObject sizeInfo = sizes.get(i).getAsJsonObject();
+ if(sizeInfo.get("tier").getAsInt() <= tier) {
+ currentSlots = sizeInfo.get("slots").getAsInt();
+ }
+ }
+ return currentSlots;
+ }
+
+ private ItemStack fillerStack = new ItemStack(Item.getItemFromBlock(Blocks.stained_glass_pane), 1, 15);
+ public ItemStack[][][] getItemsForInventory(JsonObject inventoryInfo, JsonObject collectionInfo, String invName) {
+ if(inventoryItems.containsKey(invName)) return inventoryItems.get(invName);
+
+ JsonArray jsonInv = Utils.getElement(inventoryInfo, invName).getAsJsonArray();
+
+ int rowSize = 9;
+ int rows = jsonInv.size()/rowSize;
+ int maxRowsPerPage = getRowsForInventory(invName);
+ int ignoredRows = getIgnoredRowsForInventory(invName);
+ int maxInvSize = rowSize*maxRowsPerPage;
+
+ int numInventories = (jsonInv.size()-1)/maxInvSize+1;
+
+ ItemStack[][][] inventories = new ItemStack[numInventories][][];
+
+ int availableSlots = getAvailableSlotsForInventory(inventoryInfo, collectionInfo, invName);
+
+ for(int i=0; i<numInventories; i++) {
+ int thisRows = Math.min(maxRowsPerPage, rows-maxRowsPerPage*i)-ignoredRows;
+ if(thisRows <= 0) break;
+
+ ItemStack[][] items = new ItemStack[thisRows][rowSize];
+
+ int invSize = Math.min(jsonInv.size(), maxInvSize+maxInvSize*i);
+ for(int j=maxInvSize*i; 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(jsonInv.get(j) == null || !jsonInv.get(j).isJsonObject()) {
+ if(availableSlots >= 0) {
+ if(j >= availableSlots) {
+ items[yIndex][xIndex] = fillerStack;
+ }
+ }
+ 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;
+ }
+
+ 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 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;
+ JsonObject collectionInfo = profile.getCollectionInfo(profileId);
+
+ 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);
+
+ ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, collectionInfo, selectedInventory);
+ if(currentInventoryIndex >= inventories.length) currentInventoryIndex = inventories.length-1;
+ if(currentInventoryIndex < 0) currentInventoryIndex = 0;
+
+ ItemStack[][] inventory = inventories[currentInventoryIndex];
+ if(inventory == null) {
+ 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(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, false);
+ }
+ }
+ }
+ }
+ }
+
+ if(arrowCount == -1) {
+ arrowCount = countItemsInInventory("ARROW", inventoryInfo, "quiver");
+ }
+ if(greenCandyCount == -1) {
+ greenCandyCount = countItemsInInventory("GREEN_CANDY", inventoryInfo, "candy_inventory_contents");
+ }
+ if(purpleCandyCount == -1) {
+ purpleCandyCount = countItemsInInventory("PURPLE_CANDY", inventoryInfo, "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;
+
+ 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 > y+invSizeY && mouseY < y+invSizeY+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, y+invSizeY, 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, y+invSizeY, 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 && !SBAIntegration.isFreezeBackpack()) lastBackpack = null;
+ if(SBAIntegration.isFreezeBackpack()) {
+ if(lastBackpack != null) {
+ SBAIntegration.setActiveBackpack(lastBackpack, lastBackpackX, lastBackpackY);
+ GlStateManager.translate(0, 0, 100);
+ SBAIntegration.renderActiveBackpack(mouseX, mouseY, fontRendererObj);
+ GlStateManager.translate(0, 0, -100);
+ }
+ } else {
+ if(stackToRender != null) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stackToRender);
+ boolean renderedBackpack;
+ if(internalname != null && (internalname.endsWith("BACKPACK") || internalname.equals("NEW_YEAR_CAKE_BAG"))) {
+ lastBackpack = stackToRender;
+ lastBackpackX = mouseX;
+ lastBackpackY = mouseY;
+ renderedBackpack = SBAIntegration.setActiveBackpack(lastBackpack, lastBackpackX, lastBackpackY);
+ if(renderedBackpack) {
+ GlStateManager.translate(0, 0, 100);
+ renderedBackpack = SBAIntegration.renderActiveBackpack(mouseX, mouseY, fontRendererObj);
+ GlStateManager.translate(0, 0, -100);
+ }
+ } else {
+ renderedBackpack = false;
+ }
+ if(!renderedBackpack) {
+ lastBackpack = 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 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 = 109;
+ float yOffset = 10;
+
+ float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0);
+ float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
+
+ renderAlignedString(EnumChatFormatting.GOLD+"Bank Balance", EnumChatFormatting.WHITE.toString()+shortNumberFormat(bankBalance, 0),
+ guiLeft+xStart, guiTop+yStartTop, 76);
+ renderAlignedString(EnumChatFormatting.GOLD+"Purse", EnumChatFormatting.WHITE.toString()+shortNumberFormat(purseBalance, 0),
+ guiLeft+xStart, guiTop+yStartTop+yOffset, 76);
+
+
+ float fairySouls = Utils.getElementAsFloat(Utils.getElement(profileInfo, "fairy_souls_collected"), 0);
+ renderAlignedString(EnumChatFormatting.LIGHT_PURPLE+"Fairy Souls", EnumChatFormatting.WHITE.toString()+(int)fairySouls+"/209",
+ guiLeft+xStart, guiTop+yStartBottom, 76);
+ if(skillInfo != null) {
+ float totalSkillLVL = 0;
+ float totalSlayerLVL = 0;
+ float totalSkillCount = 0;
+ float totalSlayerCount = 0;
+
+ for(Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) {
+ if(entry.getKey().startsWith("level_skill")) {
+ if(entry.getKey().contains("runecrafting")) continue;
+ totalSkillLVL += entry.getValue().getAsFloat();
+ totalSkillCount++;
+ } else if(entry.getKey().startsWith("level_slayer")) {
+ totalSlayerLVL += entry.getValue().getAsFloat();
+ totalSlayerCount++;
+ }
+ }
+
+ float avgSkillLVL = totalSkillLVL/totalSkillCount;
+ float avgSlayerLVL = totalSlayerLVL/totalSlayerCount;
+
+ renderAlignedString(EnumChatFormatting.RED+"AVG Skill Level", EnumChatFormatting.WHITE.toString()+Math.floor(avgSkillLVL*10)/10,
+ guiLeft+xStart, guiTop+yStartBottom+yOffset, 76);
+ renderAlignedString(EnumChatFormatting.RED+"AVG Slayer Level", EnumChatFormatting.WHITE.toString()+Math.floor(avgSlayerLVL*10)/10,
+ guiLeft+xStart, guiTop+yStartBottom+yOffset*2, 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);
+
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Auction Bids", EnumChatFormatting.WHITE.toString()+(int)auctions_bids,
+ guiLeft+xStart+xOffset, guiTop+yStartTop, 76);
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Highest Bid", EnumChatFormatting.WHITE.toString()+shortNumberFormat(auctions_highest_bid, 0),
+ guiLeft+xStart+xOffset, guiTop+yStartTop+yOffset, 76);
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Auctions Won", EnumChatFormatting.WHITE.toString()+(int)auctions_won,
+ guiLeft+xStart+xOffset, guiTop+yStartTop+yOffset*2, 76);
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Auctions Created", EnumChatFormatting.WHITE.toString()+(int)auctions_created,
+ guiLeft+xStart+xOffset, guiTop+yStartTop+yOffset*3, 76);
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Gold Spent", EnumChatFormatting.WHITE.toString()+shortNumberFormat(auctions_gold_spent, 0),
+ guiLeft+xStart+xOffset, guiTop+yStartTop+yOffset*4, 76);
+ renderAlignedString(EnumChatFormatting.DARK_PURPLE+"Gold Earned", EnumChatFormatting.WHITE.toString()+shortNumberFormat(auctions_gold_earned, 0),
+ guiLeft+xStart+xOffset, guiTop+yStartTop+yOffset*5, 76);
+
+
+ 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 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 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);
+
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Revenant T3", EnumChatFormatting.WHITE.toString()+(int)zombie_boss_kills_tier_2,
+ guiLeft+xStart+xOffset, guiTop+yStartBottom, 76);
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Revenant T4", EnumChatFormatting.WHITE.toString()+(int)zombie_boss_kills_tier_3,
+ guiLeft+xStart+xOffset, guiTop+yStartBottom+yOffset, 76);
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Sven T3", EnumChatFormatting.WHITE.toString()+(int)wolf_boss_kills_tier_2,
+ guiLeft+xStart+xOffset, guiTop+yStartBottom+yOffset*2, 76);
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Sven T4", EnumChatFormatting.WHITE.toString()+(int)wolf_boss_kills_tier_3,
+ guiLeft+xStart+xOffset, guiTop+yStartBottom+yOffset*3, 76);
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Tarantula T3", EnumChatFormatting.WHITE.toString()+(int)spider_boss_kills_tier_2,
+ guiLeft+xStart+xOffset, guiTop+yStartBottom+yOffset*4, 76);
+ renderAlignedString(EnumChatFormatting.DARK_AQUA+"Tarantula T4", EnumChatFormatting.WHITE.toString()+(int)spider_boss_kills_tier_3,
+ guiLeft+xStart+xOffset, 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);
+
+ renderAlignedString(EnumChatFormatting.GREEN+"Ores Mined", EnumChatFormatting.WHITE.toString()+(int)pet_milestone_ores_mined,
+ guiLeft+xStart+xOffset*2, guiTop+yStartTop, 76);
+ renderAlignedString(EnumChatFormatting.GREEN+"Sea Creatures Killed", EnumChatFormatting.WHITE.toString()+(int)pet_milestone_sea_creatures_killed,
+ guiLeft+xStart+xOffset*2, guiTop+yStartTop+yOffset, 76);
+
+ renderAlignedString(EnumChatFormatting.GREEN+"Items Fished", EnumChatFormatting.WHITE.toString()+(int)items_fished,
+ guiLeft+xStart+xOffset*2, guiTop+yStartTop+yOffset*3, 76);
+ renderAlignedString(EnumChatFormatting.GREEN+"Treasures Fished", EnumChatFormatting.WHITE.toString()+(int)items_fished_treasure,
+ guiLeft+xStart+xOffset*2, guiTop+yStartTop+yOffset*4, 76);
+ 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;
+ 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;
+ renderAlignedString(EnumChatFormatting.YELLOW+"Deaths: "+ deathType, EnumChatFormatting.WHITE.toString()+deathCount,
+ guiLeft+xStart+xOffset*3, guiTop+yStartBottom+yOffset*index, 76);
+ index++;
+ }
+ }
+ }
+
+ private int backgroundClickedX = -1;
+
+ private static 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;
+ return (d < 1000?
+ ((d > 99.9 || isRound || (!isRound && d > 9.99)?
+ (int) d * 10 / 10 : d + ""
+ ) + "" + c[iteration])
+ : shortNumberFormat(d, iteration+1));
+ }
+
+ private void renderAlignedString(String first, String second, float x, float y, int length) {
+ if(fontRendererObj.getStringWidth(first + " " + second) >= length) {
+ 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(first + " " + second), Minecraft.getMinecraft().fontRendererObj,
+ x+length/2f+xOff/2f, y+4+yOff/2f, false, length,
+ new Color(0, 0, 0, 200/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB());
+ }
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawStringCenteredScaledMaxWidth(first + " " + second, Minecraft.getMinecraft().fontRendererObj,
+ x+length/2f, y+4, false, length, 4210752);
+ } else {
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ fontRendererObj.drawString(Utils.cleanColourNotModifiers(first),
+ x+xOff/2f, y+yOff/2f,
+ new Color(0, 0, 0, 200/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB(), false);
+ }
+ }
+ }
+
+ int secondLen = fontRendererObj.getStringWidth(second);
+ GlStateManager.color(1, 1, 1, 1);
+ fontRendererObj.drawString(first, x, y, 4210752, false);
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ fontRendererObj.drawString(Utils.cleanColourNotModifiers(second),
+ x+length-secondLen+xOff/2f, y+yOff/2f,
+ new Color(0, 0, 0, 200/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB(), false);
+ }
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ fontRendererObj.drawString(second, x+length-secondLen, y, 4210752, false);
+ }
+ }
+
+ 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(SBScoreboardData.getInstance().currentTimeDate != null) {
+ if(SBScoreboardData.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBScoreboardData.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;
+ String monthlyPackageRank = Utils.getElementAsString(profile.getHypixelProfile().get("monthlyPackageRank"), "NONE");
+ if(monthlyPackageRank.equals("NONE")) {
+ rank = Utils.getElementAsString(profile.getHypixelProfile().get("rank"),
+ Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE"));
+ } else {
+ rank = monthlyPackageRank;
+ }
+ EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName(Utils.getElementAsString(profile.getHypixelProfile().get("rankPlusColor"), "WHITE"));
+ String rankPlusColor = EnumChatFormatting.WHITE.toString();
+ if(rankPlusColorECF != null) {
+ rankPlusColor = rankPlusColorECF.toString();
+ }
+
+ JsonObject misc = Utils.getConstant("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.toString() + 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);
+ }
+ }
+
+ 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 = Utils.getConstant("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) {
+ UUID playerUUID = UUID.fromString(niceUuid(profile.getUuid()));
+ 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(backgroundClickedX != -1 && Mouse.isButtonDown(1)) {
+ for(int i=0; i<entityPlayer.inventory.armorInventory.length; i++) {
+ entityPlayer.inventory.armorInventory[i] = 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);
+ }
+ }
+ }
+ }
+ }
+
+ if(playerLocationSkin == null) {
+ try {
+ Minecraft.getMinecraft().getSkinManager().loadProfileTextures(entityPlayer.getGameProfile(), new SkinManager.SkinAvailableCallback() {
+ public void skinAvailable(MinecraftProfileTexture.Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) {
+ switch (type) {
+ case SKIN:
+ playerLocationSkin = location;
+ skinType = profileTexture.getMetadata("model");
+
+ if(skinType == null) {
+ skinType = "default";
+ }
+
+ break;
+ case CAPE:
+ playerLocationCape = location;
+ }
+ }
+ }, false);
+ } catch(Exception e){}
+ }
+
+ 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+50;
+ 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;
+ }
+ }
+ }
+ }
+ 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];
+ 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);
+ renderAlignedString(statNamePretty, EnumChatFormatting.WHITE.toString()+val, guiLeft+132, guiTop+32+12.5f*i, 80);
+
+ if(mouseX > guiLeft+132 && mouseX < guiLeft+212) {
+ if(mouseY > guiTop+32+12.5f*i && mouseY < guiTop+40+12.5f*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;
+
+ 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) {
+ String levelStr;
+ if(skillInfo.get("maxed_"+entry.getKey()).getAsBoolean()) {
+ levelStr = EnumChatFormatting.GOLD+"MAXED!";
+ } else {
+ int maxXp = (int)skillInfo.get("maxxp_"+entry.getKey()).getAsFloat();
+ levelStr = EnumChatFormatting.DARK_PURPLE.toString() + shortNumberFormat(Math.round((level%1)*maxXp), 0) + "/" + shortNumberFormat(maxXp, 0);
+ }
+
+ tooltipToDisplay = Utils.createList(levelStr);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ private void renderGoldBar(float x, float y, float xSize) {
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(Gui.icons);
+ ShaderManager shaderManager = ShaderManager.getInstance();
+ shaderManager.loadShader("make_gold");
+ shaderManager.loadData("make_gold", "amount", (startTime-System.currentTimeMillis())/10000f);
+
+ Utils.drawTexturedRect(x, y, xSize/2f, 5, 0/256f, (xSize/2f)/256f, 79/256f, 84/256f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(x+xSize/2f, y, xSize/2f, 5, (182-xSize/2f)/256f, 182/256f, 79/256f, 84/256f, GL11.GL_NEAREST);
+
+ GL20.glUseProgram(0);
+ }
+
+ private void renderBar(float x, float y, float xSize, float completed) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(Gui.icons);
+
+ completed = Math.round(completed/0.05f)*0.05f;
+
+ float notcompleted = 1-completed;
+
+ int displayNum = 0;//tl.x%5;
+
+ GlStateManager.color(1, 1, 1, 1);
+ float width = 0;
+
+ if(completed < 0.5f && (displayNum == 1 || displayNum == 0)) {
+ width = (0.5f - completed) * xSize;
+ Utils.drawTexturedRect(x+xSize*completed, y, width, 5, xSize*completed/256f, (xSize/2f)/256f, 74/256f, 79/256f, GL11.GL_NEAREST);
+ }
+ if(completed < 1f && (displayNum == 2 || displayNum == 0)) {
+ width = Math.min(xSize*notcompleted, xSize/2f);
+ Utils.drawTexturedRect(x+(xSize/2f)+Math.max(xSize*(completed-0.5f), 0), y, width, 5,
+ (182-(xSize/2f)+Math.max(xSize*(completed-0.5f), 0))/256f, 182/256f, 74/256f, 79/256f, GL11.GL_NEAREST);
+ }
+
+ if(completed > 0f && (displayNum == 3 || displayNum == 0)) {
+ width = Math.min(xSize*completed, xSize/2f);
+ 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)) {
+ 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);
+ }
+ }
+
+ 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((double)(mouseX / 40.0F)) * 20.0F;
+ ent.rotationYaw = (float)Math.atan((double)(mouseX / 40.0F)) * 40.0F;
+ ent.rotationPitch = -((float)Math.atan((double)(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;
+ }
+
+ 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).
+ *
+ * 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;
+ }
+
+ /**
+ * 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() {
+ 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 e) { }
+ }
+ 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 e) { }
+ }
+ 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) {
+ 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.setScreen(width*f, height*f, f);
+ Utils.drawTexturedRect(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax);
+ //Utils.setScreen(width, height, f);
+ blurOutputVert.unbindFramebufferTexture();
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
new file mode 100644
index 00000000..fa585f1e
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
@@ -0,0 +1,146 @@
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.Project;
+
+public class Panorama {
+
+ private static TexLoc tl = new TexLoc(97, 19, Keyboard.KEY_P);
+ private static TexLoc tl2 = new TexLoc(37, 80, Keyboard.KEY_L);
+
+ private static ResourceLocation backgroundTexture = null;
+
+ private static int lastWidth = 0;
+ private static int lastHeight = 0;
+
+ public static void drawPanorama(float angle, int x, int y, int width, int height, float yOffset, float zOffset, ResourceLocation[] panoramas) {
+ Minecraft.getMinecraft().getFramebuffer().unbindFramebuffer();
+
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ GL11.glViewport(0, 0, width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor());
+
+ float fov = 97;
+
+ {
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ GlStateManager.matrixMode(5889);
+ GlStateManager.pushMatrix();
+ GlStateManager.loadIdentity();
+ Project.gluPerspective(fov, (float)height/width, 0.05F, 10.0F);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.pushMatrix();
+ GlStateManager.loadIdentity();
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.rotate(180F, 1.0F, 0.0F, 0.0F);
+ GlStateManager.rotate(90, 0.0F, 0.0F, 1.0F);
+ GlStateManager.rotate(19, 1.0F, 0.0F, 0.0F);
+ //GlStateManager.rotate(tl.x, 0.0F, 0.0F, 1.0F);
+ GlStateManager.enableBlend();
+ GlStateManager.disableAlpha();
+ GlStateManager.disableCull();
+ GlStateManager.depthMask(false);
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+
+ GlStateManager.pushMatrix();
+
+ GlStateManager.translate(0, yOffset, zOffset);
+
+ GlStateManager.rotate(angle, 0.0F, 1.0F, 0.0F);
+
+ for (int k = 0; k < 6; ++k) {
+ GlStateManager.pushMatrix();
+
+ switch (k) {
+ 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 4:
+ GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); break;
+ case 5:
+ GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F); break;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(panoramas[k]);
+ float splits = 0.1f;
+ for(float x1=0; x1<1; x1+=splits) {
+ for(float y1=0; y1<1; y1+=splits) {
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
+
+ for(int i=0; i<4; i++) {
+ float x2 = (i == 0 || i == 3) ? x1 : x1+splits;
+ float y2 = (i >= 2) ? y1 : y1+splits;
+
+ float xr = x2*2-1;
+ float yr = y2*2-1;
+
+ float distSq = xr*xr+yr*yr+1;
+ 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();
+ }
+ }
+
+ GlStateManager.popMatrix();
+ }
+
+ GlStateManager.popMatrix();
+ GlStateManager.colorMask(true, true, true, false);
+
+ worldrenderer.setTranslation(0.0D, 0.0D, 0.0D);
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.matrixMode(5889);
+ GlStateManager.popMatrix();
+ GlStateManager.matrixMode(5888);
+ GlStateManager.popMatrix();
+ GlStateManager.depthMask(true);
+ GlStateManager.enableCull();
+ 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);
+ lastWidth = width*scaledresolution.getScaleFactor();
+ lastHeight = height*scaledresolution.getScaleFactor();
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(backgroundTexture);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
+ GL11.glCopyTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, 0, 0, 0, width*scaledresolution.getScaleFactor(), height*scaledresolution.getScaleFactor());
+
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+ 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();
+ tessellator.draw();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
new file mode 100644
index 00000000..dac93e6f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
@@ -0,0 +1,505 @@
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.*;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.nbt.*;
+import net.minecraft.util.EnumChatFormatting;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class PlayerStats {
+ public static final String HEALTH = "health";
+ public static final String DEFENCE = "defence";
+ public static final String STRENGTH = "strength";
+ public static final String SPEED = "speed";
+ public static final String CRIT_CHANCE = "crit_chance";
+ public static final String CRIT_DAMAGE = "crit_damage";
+ public static final String BONUS_ATTACK_SPEED = "bonus_attack_speed";
+ public static final String INTELLIGENCE = "intelligence";
+ 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[] defaultStatNames = new String[]{"health","defence","strength","speed","crit_chance",
+ "crit_damage","bonus_attack_speed","intelligence","sea_creature_chance","magic_find","pet_luck"};
+ public static final String[] defaultStatNamesPretty = new String[]{EnumChatFormatting.RED+"\u2764 Health",EnumChatFormatting.GREEN+"\u2748 Defence",
+ EnumChatFormatting.RED+"\u2741 Strength",EnumChatFormatting.WHITE+"\u2726 Speed",EnumChatFormatting.BLUE+"\u2623 Crit Chance",
+ EnumChatFormatting.BLUE+"\u2620 Crit Damage",EnumChatFormatting.YELLOW+"\u2694 Attack Speed",EnumChatFormatting.AQUA+"\u270e Intelligence",
+ EnumChatFormatting.DARK_AQUA+"\u03b1 SC Chance",EnumChatFormatting.AQUA+"\u272f Magic Find",EnumChatFormatting.LIGHT_PURPLE+"\u2663 Pet Luck"};
+
+ 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 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));
+ }
+ }
+ }
+
+ public static Stats getBaseStats() {
+ JsonObject misc = Utils.getConstant("misc");
+ if(misc == null) return null;
+
+ Stats stats = new Stats();
+ for(String statName : defaultStatNames) {
+ stats.addStat(statName, Utils.getElementAsFloat(Utils.getElement(misc, "base_stats."+statName), 0));
+ }
+ return stats;
+ }
+
+ private static Stats getFairyBonus(int fairyExchanges) {
+ Stats bonus = new Stats();
+
+ bonus.addStat(SPEED, fairyExchanges/10);
+
+ for(int i=0; i<fairyExchanges; i++) {
+ bonus.addStat(STRENGTH, (i + 1) % 5 == 0 ? 2 : 1);
+ bonus.addStat(DEFENCE, (i + 1) % 5 == 0 ? 2 : 1);
+ bonus.addStat(HEALTH, 3 + i / 2);
+ }
+
+ return bonus;
+ }
+
+ private static Stats getSkillBonus(JsonObject skillInfo) {
+ JsonObject bonuses = Utils.getConstant("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());
+ JsonObject skillStatMap = Utils.getElement(bonuses, "bonus_stats."+skill).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());
+ }
+ }
+ skillBonus.add(currentBonus);
+ }
+ }
+ }
+
+ return skillBonus;
+ }
+
+ private static Stats getPetBonus(JsonObject profile) {
+ JsonObject bonuses = Utils.getConstant("bonuses");
+ if(bonuses == null) return null;
+
+ JsonElement petsElement = Utils.getElement(profile, "pets");
+ if(petsElement == null) return new Stats();
+
+ JsonArray pets = petsElement.getAsJsonArray();
+
+ HashMap<String, String> highestRarityMap = new HashMap<>();
+
+ for(int i=0; i<pets.size(); i++) {
+ JsonObject pet = pets.get(i).getAsJsonObject();
+ highestRarityMap.put(pet.get("type").getAsString(), pet.get("tier").getAsString());
+ }
+
+ int petScore = 0;
+ for(String value : highestRarityMap.values()) {
+ petScore += Utils.getElementAsFloat(Utils.getElement(bonuses, "pet_value."+value.toUpperCase()), 0);
+ }
+
+ JsonElement petRewardsElement = Utils.getElement(bonuses, "pet_rewards");
+ if(petRewardsElement == null) return null;
+ JsonObject petRewards = petRewardsElement.getAsJsonObject();
+
+ Stats petBonus = new Stats();
+ for(int i=0; i<=petScore; i++) {
+ if(petRewards.has(""+i)) {
+ petBonus = new Stats();
+ for(Map.Entry<String, JsonElement> entry : petRewards.get(""+i).getAsJsonObject().entrySet()) {
+ petBonus.addStat(entry.getKey(), entry.getValue().getAsFloat());
+ }
+ }
+ }
+ return petBonus;
+ }
+
+ private static float harpBonus(JsonObject profile) {
+ String talk_to_melody = Utils.getElementAsString(Utils.getElement(profile, "objectives.talk_to_melody.status"), "INCOMPLETE");
+ if(talk_to_melody.equalsIgnoreCase("COMPLETE")) {
+ return 26;
+ } else {
+ return 0;
+ }
+ }
+
+
+ public static Stats getPassiveBonuses(JsonObject skillInfo, JsonObject profile) {
+ Stats passiveBonuses = new Stats();
+
+ Stats fairyBonus = getFairyBonus((int)Utils.getElementAsFloat(Utils.getElement(profile, "fairy_exchanges"), 0));
+ Stats skillBonus = getSkillBonus(skillInfo);
+ Stats petBonus = getPetBonus(profile);
+
+ if(fairyBonus == null || skillBonus == null || petBonus == null) return null;
+
+ passiveBonuses.add(fairyBonus);
+ passiveBonuses.add(skillBonus);
+ passiveBonuses.addStat(INTELLIGENCE, harpBonus(profile));
+ passiveBonuses.add(petBonus);
+
+ return passiveBonuses;
+ }
+
+ private static String getFullset(JsonArray armor, int ignore) {
+ String fullset = null;
+ for(int i=0; i<armor.size(); i++) {
+ if(i == ignore) continue;
+
+ JsonElement itemElement = armor.get(i);
+ if(itemElement == null || !itemElement.isJsonObject()) {
+ fullset = null;
+ break;
+ }
+ JsonObject item = itemElement.getAsJsonObject();
+ String internalname = item.get("internalname").getAsString();
+
+ String[] split = internalname.split("_");
+ split[split.length-1] = "";
+ String armorname = StringUtils.join(split, "_");
+
+ if(fullset == null) {
+ fullset = armorname;
+ } else if(!fullset.equalsIgnoreCase(armorname)){
+ fullset = null;
+ break;
+ }
+ }
+ return fullset;
+ }
+
+ private static Stats getSetBonuses(Stats stats, JsonObject inventoryInfo, JsonObject collectionInfo, JsonObject skillInfo, JsonObject profile) {
+ JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
+
+ Stats bonuses = new Stats();
+
+ String fullset = getFullset(armor, -1);
+
+ if(fullset != null) {
+ switch(fullset) {
+ case "LAPIS_ARMOR_":
+ bonuses.addStat(HEALTH, 60);
+ break;
+ case "EMERALD_ARMOR_":
+ {
+ int bonus = (int)Math.floor(Utils.getElementAsFloat(Utils.getElement(collectionInfo, "EMERALD"), 0)/3000);
+ bonuses.addStat(HEALTH, bonus);
+ bonuses.addStat(DEFENCE, bonus);
+ }
+ break;
+ case "FAIRY_":
+ bonuses.addStat(HEALTH, Utils.getElementAsFloat(Utils.getElement(profile, "fairy_souls_collected"), 0));
+ break;
+ case "SPEEDSTER_":
+ bonuses.addStat(SPEED, 20);
+ break;
+ case "YOUNG_DRAGON_":
+ bonuses.addStat(SPEED, 70);
+ break;
+ case "MASTIFF_":
+ 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(SEA_CREATURE_CHANCE, 4);
+ break;
+ case "ARMOR_OF_MAGMA_":
+ int bonus = (int)Math.min(200, Math.floor(Utils.getElementAsFloat(Utils.getElement(profile, "stats.kills_magma_cube"), 0)/10));
+ bonuses.addStat(HEALTH, bonus);
+ bonuses.addStat(INTELLIGENCE, bonus);
+ case "OLD_DRAGON_":
+ bonuses.addStat(HEALTH, 200);
+ bonuses.addStat(DEFENCE, 40);
+ break;
+ }
+ }
+
+ JsonElement chestplateElement = armor.get(2);
+ if(chestplateElement != null && chestplateElement.isJsonObject()) {
+ JsonObject chestplate = chestplateElement.getAsJsonObject();
+ if(chestplate.get("internalname").getAsString().equals("OBSIDIAN_CHESTPLATE")) {
+ JsonArray inventory = Utils.getElement(inventoryInfo, "inv_contents").getAsJsonArray();
+ for(int i=0; i<inventory.size(); i++) {
+ JsonElement itemElement = inventory.get(i);
+ if(itemElement != null && itemElement.isJsonObject()) {
+ JsonObject item = itemElement.getAsJsonObject();
+ if(item.get("internalname").getAsString().equals("OBSIDIAN")) {
+ int count = 1;
+ if(item.has("count")) {
+ count = item.get("count").getAsInt();
+ }
+ bonuses.addStat(SPEED, count/20);
+ }
+ }
+ }
+ }
+ }
+
+ return bonuses;
+ }
+
+ private static final Pattern HEALTH_PATTERN = Pattern.compile("^Health: ((?:\\+|-)[0-9]+)");
+ private static final Pattern DEFENCE_PATTERN = Pattern.compile("^Defense: ((?:\\+|-)[0-9]+)");
+ private static final Pattern STRENGTH_PATTERN = Pattern.compile("^Strength: ((?:\\+|-)[0-9]+)");
+ private static final Pattern SPEED_PATTERN = Pattern.compile("^Speed: ((?:\\+|-)[0-9]+)");
+ private static final Pattern CC_PATTERN = Pattern.compile("^Crit Chance: ((?:\\+|-)[0-9]+)");
+ private static final Pattern CD_PATTERN = Pattern.compile("^Crit Damage: ((?:\\+|-)[0-9]+)");
+ private static final Pattern ATKSPEED_PATTERN = Pattern.compile("^Bonus Attack Speed: ((?:\\+|-)[0-9]+)");
+ private static final Pattern INTELLIGENCE_PATTERN = Pattern.compile("^Intelligence: ((?:\\+|-)[0-9]+)");
+ private static final Pattern SCC_PATTERN = Pattern.compile("^Sea Creature Chance: ((?:\\+|-)[0-9]+)");
+ private static final HashMap<String, Pattern> STAT_PATTERN_MAP = new HashMap<>();
+ static {
+ STAT_PATTERN_MAP.put("health", HEALTH_PATTERN);
+ STAT_PATTERN_MAP.put("defence", DEFENCE_PATTERN);
+ STAT_PATTERN_MAP.put("strength", STRENGTH_PATTERN);
+ STAT_PATTERN_MAP.put("speed", SPEED_PATTERN);
+ STAT_PATTERN_MAP.put("crit_chance", CC_PATTERN);
+ STAT_PATTERN_MAP.put("crit_damage", CD_PATTERN);
+ STAT_PATTERN_MAP.put("bonus_attack_speed", ATKSPEED_PATTERN);
+ STAT_PATTERN_MAP.put("intelligence", INTELLIGENCE_PATTERN);
+ STAT_PATTERN_MAP.put("sea_creature_chance", SCC_PATTERN);
+ }
+ private static Stats getStatForItem(String internalname, JsonObject item, JsonArray lore) {
+ Stats stats = new Stats();
+ for(int i=0; i<lore.size(); i++) {
+ String line = lore.get(i).getAsString();
+ for(Map.Entry<String, Pattern> entry : STAT_PATTERN_MAP.entrySet()) {
+ Matcher matcher = entry.getValue().matcher(Utils.cleanColour(line));
+ if(matcher.find()) {
+ int bonus = Integer.parseInt(matcher.group(1));
+ stats.addStat(entry.getKey(), bonus);
+ }
+ }
+ }
+ if(internalname.equals("DAY_CRYSTAL") || internalname.equals("NIGHT_CRYSTAL")) {
+ stats.addStat(STRENGTH, 2.5f);
+ stats.addStat(DEFENCE, 2.5f);
+ }
+ if(internalname.equals("NEW_YEAR_CAKE_BAG") && item.has("item_contents")) {
+ JsonArray bytesArr = item.get("item_contents").getAsJsonArray();
+ byte[] bytes = new byte[bytesArr.size()];
+ for(int i=0; i<bytesArr.size(); i++) {
+ bytes[i] = bytesArr.get(i).getAsByte();
+ }
+ try {
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ HashSet<Integer> cakes = new HashSet<>();
+ for(int j=0; j<items.tagCount(); j++) {
+ if(items.getCompoundTagAt(j).getKeySet().size() > 0) {
+ NBTTagCompound nbt = items.getCompoundTagAt(j).getCompoundTag("tag");
+ if(nbt != null && nbt.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = nbt.getCompoundTag("ExtraAttributes");
+ if (ea.hasKey("new_years_cake")) {
+ cakes.add(ea.getInteger("new_years_cake"));
+ }
+ }
+ }
+ }
+ stats.addStat(HEALTH, cakes.size());
+ } catch(IOException e) {
+ e.printStackTrace();
+ return stats;
+ }
+ }
+ return stats;
+ }
+ private static Stats getItemBonuses(boolean talismanOnly, JsonArray... inventories) {
+ JsonObject misc = Utils.getConstant("misc");
+ if(misc == null) return null;
+ JsonElement talisman_upgrades_element = misc.get("talisman_upgrades");
+ if(talisman_upgrades_element == null) return null;
+ JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject();
+
+ HashMap<String, Stats> itemBonuses = new HashMap<>();
+ for(JsonArray inventory : inventories) {
+ for(int i=0; i<inventory.size(); i++) {
+ JsonElement itemElement = inventory.get(i);
+ if(itemElement != null && itemElement.isJsonObject()) {
+ JsonObject item = itemElement.getAsJsonObject();
+ String internalname = item.get("internalname").getAsString();
+ if(itemBonuses.containsKey(internalname)) {
+ continue;
+ }
+ 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);
+
+ for(Map.Entry<String, JsonElement> talisman_upgrades_item : talisman_upgrades.entrySet()) {
+ JsonArray upgrades = talisman_upgrades_item.getValue().getAsJsonArray();
+ for(int j=0; j<upgrades.size(); j++) {
+ String upgrade = upgrades.get(j).getAsString();
+ if(upgrade.equals(internalname)) {
+ itemBonuses.put(talisman_upgrades_item.getKey(), new Stats());
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ Stats itemBonusesStats = new Stats();
+ for(Stats stats : itemBonuses.values()) {
+ itemBonusesStats.add(stats);
+ }
+ return itemBonusesStats;
+ }
+
+ private static float getStatMult(JsonObject inventoryInfo) {
+ float mult = 1f;
+
+ JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
+
+ String fullset = getFullset(armor, -1);
+
+ if(fullset != null && fullset.equals("SUPERIOR_DRAGON_")) {
+ mult *= 1.05f;
+ }
+
+ for(int i=0; i<armor.size(); i++) {
+ JsonElement itemElement = armor.get(i);
+ if(itemElement == null || !itemElement.isJsonObject()) continue;
+
+ JsonObject item = itemElement.getAsJsonObject();
+ String internalname = item.get("internalname").getAsString();
+
+ String reforge = Utils.getElementAsString(Utils.getElement(item, "ExtraAttributes.modifier"), "");
+
+ if(reforge.equals("renowned")) {
+ mult *= 1.01f;
+ }
+ }
+
+ return mult;
+ }
+
+ private static void applyLimits(Stats stats, JsonObject inventoryInfo) {
+ //>0
+ JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
+
+ String fullset = getFullset(armor, 3);
+
+ if(fullset != null) {
+ switch(fullset) {
+ case "CHEAP_TUXEDO_":
+ stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(75, stats.get(HEALTH))));
+ case "FANCY_TUXEDO_":
+ stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(150, stats.get(HEALTH))));
+ case "ELEGANT_TUXEDO_":
+ stats.statsJson.add(HEALTH, new JsonPrimitive(Math.min(250, stats.get(HEALTH))));
+ }
+ }
+
+ 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;
+ stats.statsJson.add(statEntry.getKey(), new JsonPrimitive(Math.max(0, statEntry.getValue().getAsFloat())));
+ }
+ }
+
+ public static Stats getStats(JsonObject skillInfo, JsonObject inventoryInfo, JsonObject collectionInfo, JsonObject profile) {
+ if(skillInfo == 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 armorBonuses = getItemBonuses(false, armor);
+ Stats talismanBonuses = getItemBonuses(true, inventory, talisman_bag);
+
+ if(passiveBonuses == null || armorBonuses == null || talismanBonuses == null) return null;
+
+ Stats stats = getBaseStats().add(passiveBonuses).add(armorBonuses).add(talismanBonuses);
+
+ stats.add(getSetBonuses(stats, inventoryInfo, collectionInfo, skillInfo, profile));
+
+ stats.scaleAll(getStatMult(inventoryInfo));
+
+ applyLimits(stats, inventoryInfo);
+
+ return stats;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
new file mode 100644
index 00000000..d2b5ea23
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -0,0 +1,890 @@
+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.google.gson.JsonPrimitive;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+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 LinkedHashMap<String, ItemStack> skillToSkillDisplayMap = new LinkedHashMap<>();
+ static {
+ skillToSkillDisplayMap.put("skill_taming", Utils.createItemStack(Items.spawn_egg, EnumChatFormatting.LIGHT_PURPLE+"Taming"));
+ skillToSkillDisplayMap.put("skill_mining", Utils.createItemStack(Items.stone_pickaxe, EnumChatFormatting.GRAY+"Mining"));
+ skillToSkillDisplayMap.put("skill_foraging", Utils.createItemStack(Item.getItemFromBlock(Blocks.sapling), EnumChatFormatting.DARK_GREEN+"Foraging"));
+ skillToSkillDisplayMap.put("skill_enchanting", Utils.createItemStack(Item.getItemFromBlock(Blocks.enchanting_table), EnumChatFormatting.GREEN+"Enchanting"));
+ skillToSkillDisplayMap.put("skill_carpentry", Utils.createItemStack(Item.getItemFromBlock(Blocks.crafting_table), EnumChatFormatting.DARK_RED+"Carpentry"));
+ skillToSkillDisplayMap.put("skill_farming", Utils.createItemStack(Items.golden_hoe, EnumChatFormatting.YELLOW+"Farming"));
+ skillToSkillDisplayMap.put("skill_combat", Utils.createItemStack(Items.stone_sword, EnumChatFormatting.RED+"Combat"));
+ skillToSkillDisplayMap.put("skill_fishing", Utils.createItemStack(Items.fishing_rod, EnumChatFormatting.AQUA+"Fishing"));
+ skillToSkillDisplayMap.put("skill_alchemy", Utils.createItemStack(Items.brewing_stand, EnumChatFormatting.BLUE+"Alchemy"));
+ skillToSkillDisplayMap.put("skill_runecrafting", Utils.createItemStack(Items.magma_cream, EnumChatFormatting.DARK_PURPLE+"Runecrafting"));
+ skillToSkillDisplayMap.put(null, null);
+ skillToSkillDisplayMap.put("slayer_zombie", Utils.createItemStack(Items.rotten_flesh, EnumChatFormatting.GOLD+"Rev Slayer"));
+ skillToSkillDisplayMap.put("slayer_spider", Utils.createItemStack(Items.spider_eye, EnumChatFormatting.GOLD+"Tara Slayer"));
+ skillToSkillDisplayMap.put("slayer_wolf", Utils.createItemStack(Items.bone, EnumChatFormatting.GOLD+"Sven 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<>();
+ static {
+ collectionCatToCollectionMap.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"));
+ collectionCatToCollectionMap.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"));
+ collectionCatToCollectionMap.put(CAT_COMBAT,
+ Utils.createList("ROTTEN_FLESH", "BONE", "STRING", "SPIDER_EYE", "SULPHUR", "ENDER_PEARL",
+ "GHAST_TEAR", "SLIME_BALL", "BLAZE_ROD", "MAGMA_CREAM"));
+ collectionCatToCollectionMap.put(CAT_FORAGING,
+ Utils.createList("LOG", "LOG:1", "LOG:2", "LOG_2:1", "LOG_2", "LOG:3"));
+ collectionCatToCollectionMap.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"));
+ }
+
+ private static final LinkedHashMap<ItemStack, List<String>> collectionCatToMinionMap = new LinkedHashMap<>();
+ static {
+ collectionCatToMinionMap.put(CAT_FARMING,
+ Utils.createList("WHEAT", "CARROT", "POTATO", "PUMPKIN", "MELON", null, "MUSHROOM",
+ "COCOA", "CACTUS", "SUGAR_CANE", "CHICKEN", "COW", "PIG", null, "SHEEP",
+ "RABBIT", "NETHER_WARTS"));
+ collectionCatToMinionMap.put(CAT_MINING,
+ Utils.createList("COBBLESTONE", "COAL", "IRON", "GOLD", "DIAMOND", "LAPIS",
+ "EMERALD", "REDSTONE", "QUARTZ", "OBSIDIAN", "GLOWSTONE", "GRAVEL", "ICE", null,
+ "SAND", "ENDER_STONE"));
+ collectionCatToMinionMap.put(CAT_COMBAT,
+ Utils.createList("ZOMBIE", "SKELETON", "SPIDER", "CAVESPIDER", "CREEPER", "ENDERMAN",
+ "GHAST", "SLIME", "BLAZE", "MAGMA_CUBE"));
+ collectionCatToMinionMap.put(CAT_FORAGING,
+ Utils.createList("OAK", "SPRUCE", "BIRCH", "DARK_OAK", "ACACIA", "JUNGLE"));
+ collectionCatToMinionMap.put(CAT_FISHING,
+ Utils.createList("FISHING", null, null, null, null,
+ null, "CLAY", null, null, null));
+ }
+
+ private static final LinkedHashMap<String, ItemStack> collectionToCollectionDisplayMap = new LinkedHashMap<>();
+ static {
+ /** FARMING COLLECTIONS **/
+ collectionToCollectionDisplayMap.put("WHEAT", Utils.createItemStack(Items.wheat,
+ EnumChatFormatting.YELLOW+"Wheat"));
+ collectionToCollectionDisplayMap.put("CARROT_ITEM", Utils.createItemStack(Items.carrot,
+ EnumChatFormatting.YELLOW+"Carrot"));
+ collectionToCollectionDisplayMap.put("POTATO_ITEM", Utils.createItemStack(Items.potato,
+ EnumChatFormatting.YELLOW+"Potato"));
+ collectionToCollectionDisplayMap.put("PUMPKIN", Utils.createItemStack(Item.getItemFromBlock(Blocks.pumpkin),
+ EnumChatFormatting.YELLOW+"Pumpkin"));
+ collectionToCollectionDisplayMap.put("MELON", Utils.createItemStack(Items.melon,
+ EnumChatFormatting.YELLOW+"Melon"));
+ collectionToCollectionDisplayMap.put("SEEDS", Utils.createItemStack(Items.wheat_seeds,
+ EnumChatFormatting.YELLOW+"Seeds"));
+ collectionToCollectionDisplayMap.put("MUSHROOM_COLLECTION",
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.red_mushroom)
+ , EnumChatFormatting.YELLOW+"Mushroom"));
+ collectionToCollectionDisplayMap.put("INK_SACK:3", Utils.createItemStack(Items.dye,
+ EnumChatFormatting.YELLOW+"Cocoa Beans", 3));
+ collectionToCollectionDisplayMap.put("CACTUS", Utils.createItemStack(Item.getItemFromBlock(Blocks.cactus),
+ EnumChatFormatting.YELLOW+"Cactus"));
+ collectionToCollectionDisplayMap.put("SUGAR_CANE", Utils.createItemStack(Items.reeds,
+ EnumChatFormatting.YELLOW+"Sugar Cane"));
+ collectionToCollectionDisplayMap.put("FEATHER", Utils.createItemStack(Items.feather,
+ EnumChatFormatting.YELLOW+"Feather"));
+ collectionToCollectionDisplayMap.put("LEATHER", Utils.createItemStack(Items.leather,
+ EnumChatFormatting.YELLOW+"Leather"));
+ collectionToCollectionDisplayMap.put("PORK", Utils.createItemStack(Items.porkchop,
+ EnumChatFormatting.YELLOW+"Porkchop"));
+ collectionToCollectionDisplayMap.put("RAW_CHICKEN", Utils.createItemStack(Items.chicken,
+ EnumChatFormatting.YELLOW+"Chicken"));
+ collectionToCollectionDisplayMap.put("MUTTON", Utils.createItemStack(Items.mutton,
+ EnumChatFormatting.YELLOW+"Mutton"));
+ collectionToCollectionDisplayMap.put("RABBIT", Utils.createItemStack(Items.rabbit,
+ EnumChatFormatting.YELLOW+"Rabbit"));
+ collectionToCollectionDisplayMap.put("NETHER_STALK", Utils.createItemStack(Items.nether_wart,
+ EnumChatFormatting.YELLOW+"Nether Wart"));
+
+ /** MINING COLLECTIONS **/
+ collectionToCollectionDisplayMap.put("COBBLESTONE", Utils.createItemStack(Item.getItemFromBlock(Blocks.cobblestone),
+ EnumChatFormatting.GRAY+"Cobblestone"));
+ collectionToCollectionDisplayMap.put("COAL", Utils.createItemStack(Items.coal,
+ EnumChatFormatting.GRAY+"Coal"));
+ collectionToCollectionDisplayMap.put("IRON_INGOT", Utils.createItemStack(Items.iron_ingot,
+ EnumChatFormatting.GRAY+"Iron Ingot"));
+ collectionToCollectionDisplayMap.put("GOLD_INGOT", Utils.createItemStack(Items.gold_ingot,
+ EnumChatFormatting.GRAY+"Gold Ingot"));
+ collectionToCollectionDisplayMap.put("DIAMOND", Utils.createItemStack(Items.diamond,
+ EnumChatFormatting.GRAY+"Diamond"));
+ collectionToCollectionDisplayMap.put("INK_SACK:4", Utils.createItemStack(Items.dye,
+ EnumChatFormatting.GRAY+"Lapis Lazuli", 4));
+ collectionToCollectionDisplayMap.put("EMERALD", Utils.createItemStack(Items.emerald,
+ EnumChatFormatting.GRAY+"Emerald"));
+ collectionToCollectionDisplayMap.put("REDSTONE", Utils.createItemStack(Items.redstone,
+ EnumChatFormatting.GRAY+"Redstone"));
+ collectionToCollectionDisplayMap.put("QUARTZ", Utils.createItemStack(Items.quartz,
+ EnumChatFormatting.GRAY+"Nether Quartz"));
+ collectionToCollectionDisplayMap.put("OBSIDIAN", Utils.createItemStack(Item.getItemFromBlock(Blocks.obsidian),
+ EnumChatFormatting.GRAY+"Obsidian"));
+ collectionToCollectionDisplayMap.put("GLOWSTONE_DUST", Utils.createItemStack(Items.glowstone_dust,
+ EnumChatFormatting.GRAY+"Glowstone"));
+ collectionToCollectionDisplayMap.put("GRAVEL", Utils.createItemStack(Item.getItemFromBlock(Blocks.gravel),
+ EnumChatFormatting.GRAY+"Gravel"));
+ collectionToCollectionDisplayMap.put("ICE", Utils.createItemStack(Item.getItemFromBlock(Blocks.ice),
+ EnumChatFormatting.GRAY+"Ice"));
+ collectionToCollectionDisplayMap.put("NETHERRACK", Utils.createItemStack(Item.getItemFromBlock(Blocks.netherrack),
+ EnumChatFormatting.GRAY+"Netherrack"));
+ collectionToCollectionDisplayMap.put("SAND", Utils.createItemStack(Item.getItemFromBlock(Blocks.sand),
+ EnumChatFormatting.GRAY+"Sand"));
+ collectionToCollectionDisplayMap.put("ENDER_STONE", Utils.createItemStack(Item.getItemFromBlock(Blocks.end_stone),
+ EnumChatFormatting.GRAY+"End Stone"));
+
+ /** COMBAT COLLECTIONS **/
+ collectionToCollectionDisplayMap.put("ROTTEN_FLESH", Utils.createItemStack(Items.rotten_flesh,
+ EnumChatFormatting.RED+"Rotten Flesh"));
+ collectionToCollectionDisplayMap.put("BONE", Utils.createItemStack(Items.bone,
+ EnumChatFormatting.RED+"Bone"));
+ collectionToCollectionDisplayMap.put("STRING", Utils.createItemStack(Items.string,
+ EnumChatFormatting.RED+"String"));
+ collectionToCollectionDisplayMap.put("SPIDER_EYE", Utils.createItemStack(Items.spider_eye,
+ EnumChatFormatting.RED+"Spider Eye"));
+ collectionToCollectionDisplayMap.put("SULPHUR", Utils.createItemStack(Items.gunpowder,
+ EnumChatFormatting.RED+"Gunpowder"));
+ collectionToCollectionDisplayMap.put("ENDER_PEARL", Utils.createItemStack(Items.ender_pearl,
+ EnumChatFormatting.RED+"Ender Pearl"));
+ collectionToCollectionDisplayMap.put("GHAST_TEAR", Utils.createItemStack(Items.ghast_tear,
+ EnumChatFormatting.RED+"Ghast Tear"));
+ collectionToCollectionDisplayMap.put("SLIME_BALL", Utils.createItemStack(Items.slime_ball,
+ EnumChatFormatting.RED+"Slimeball"));
+ collectionToCollectionDisplayMap.put("BLAZE_ROD", Utils.createItemStack(Items.blaze_rod,
+ EnumChatFormatting.RED+"Blaze Rod"));
+ collectionToCollectionDisplayMap.put("MAGMA_CREAM", Utils.createItemStack(Items.magma_cream,
+ EnumChatFormatting.RED+"Magma Cream"));
+
+ /** FORAGING COLLECTIONS **/
+ collectionToCollectionDisplayMap.put("LOG", Utils.createItemStack(Item.getItemFromBlock(Blocks.log),
+ EnumChatFormatting.DARK_GREEN+"Oak"));
+ collectionToCollectionDisplayMap.put("LOG:1", Utils.createItemStack(Item.getItemFromBlock(Blocks.log),
+ EnumChatFormatting.DARK_GREEN+"Birch", 1));
+ collectionToCollectionDisplayMap.put("LOG:2", Utils.createItemStack(Item.getItemFromBlock(Blocks.log),
+ EnumChatFormatting.DARK_GREEN+"Spruce", 2));
+ collectionToCollectionDisplayMap.put("LOG_2:1", Utils.createItemStack(Item.getItemFromBlock(Blocks.log2),
+ EnumChatFormatting.DARK_GREEN+"Dark Oak", 1));
+ collectionToCollectionDisplayMap.put("LOG_2", Utils.createItemStack(Item.getItemFromBlock(Blocks.log2),
+ EnumChatFormatting.DARK_GREEN+"Acacia"));
+ collectionToCollectionDisplayMap.put("LOG:3", Utils.createItemStack(Item.getItemFromBlock(Blocks.log),
+ EnumChatFormatting.DARK_GREEN+"Jungle", 3));
+
+ /** FISHING COLLECTIONS **/
+ collectionToCollectionDisplayMap.put("RAW_FISH", Utils.createItemStack(Items.fish,
+ EnumChatFormatting.AQUA+"Fish"));
+ collectionToCollectionDisplayMap.put("RAW_FISH:1", Utils.createItemStack(Items.fish,
+ EnumChatFormatting.AQUA+"Salmon", 1));
+ collectionToCollectionDisplayMap.put("RAW_FISH:2", Utils.createItemStack(Items.fish,
+ EnumChatFormatting.AQUA+"Clownfish", 2));
+ collectionToCollectionDisplayMap.put("RAW_FISH:3", Utils.createItemStack(Items.fish,
+ EnumChatFormatting.AQUA+"Pufferfish", 3));
+ collectionToCollectionDisplayMap.put("PRISMARINE_SHARD", Utils.createItemStack(Items.prismarine_shard,
+ EnumChatFormatting.AQUA+"Prismarine Shard"));
+ collectionToCollectionDisplayMap.put("PRISMARINE_CRYSTALS", Utils.createItemStack(Items.prismarine_crystals,
+ EnumChatFormatting.AQUA+"Prismarine Crystals"));
+ collectionToCollectionDisplayMap.put("CLAY_BALL", Utils.createItemStack(Items.clay_ball,
+ EnumChatFormatting.AQUA+"Clay"));
+ collectionToCollectionDisplayMap.put("WATER_LILY", Utils.createItemStack(Item.getItemFromBlock(Blocks.waterlily),
+ EnumChatFormatting.AQUA+"Lilypad"));
+ collectionToCollectionDisplayMap.put("INK_SACK", Utils.createItemStack(Items.dye,
+ EnumChatFormatting.AQUA+"Ink Sack"));
+ collectionToCollectionDisplayMap.put("SPONGE", Utils.createItemStack(Item.getItemFromBlock(Blocks.sponge),
+ EnumChatFormatting.AQUA+"Sponge"));
+ }
+
+ public static LinkedHashMap<ItemStack, List<String>> getCollectionCatToMinionMap() {
+ return collectionCatToMinionMap;
+ }
+
+ public static LinkedHashMap<String, ItemStack> getCollectionToCollectionDisplayMap() {
+ return collectionToCollectionDisplayMap;
+ }
+
+ public static LinkedHashMap<ItemStack, List<String>> getCollectionCatToCollectionMap() {
+ return collectionCatToCollectionMap;
+ }
+
+ public static Map<String, ItemStack> getSkillToSkillDisplayMap() {
+ return Collections.unmodifiableMap(skillToSkillDisplayMap);
+ }
+
+ public class Profile {
+ private final String uuid;
+ private String latestProfile = null;
+
+ private JsonArray playerInformation = null;
+ private JsonObject basicInfo = null;
+
+ 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, JsonObject> collectionInfoMap = new HashMap<>();
+ private List<String> profileIds = new ArrayList<>();
+ private JsonObject playerStatus = null;
+ private HashMap<String, PlayerStats.Stats> stats = new HashMap<>();
+ private HashMap<String, PlayerStats.Stats> passiveStats = new HashMap<>();
+
+ public Profile(String uuid) {
+ this.uuid = uuid;
+ }
+
+ private AtomicBoolean updatingPlayerInfoState = new AtomicBoolean(false);
+ private AtomicBoolean updatingPlayerStatusState = new AtomicBoolean(false);
+
+ public JsonObject getPlayerStatus() {
+ if(playerStatus != null) return playerStatus;
+ if(updatingPlayerStatusState.get()) return null;
+
+ updatingPlayerStatusState.set(true);
+
+ HashMap<String, String> args = new HashMap<>();
+ args.put("uuid", ""+uuid);
+ manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "status",
+ args, jsonObject -> {
+ if(jsonObject == null) return;
+
+ updatingPlayerStatusState.set(false);
+ if(jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ playerStatus = jsonObject.get("session").getAsJsonObject();
+ }
+ }, () -> updatingPlayerStatusState.set(false)
+ );
+
+ return null;
+ }
+
+ public String getLatestProfile() {
+ return latestProfile;
+ }
+
+ public JsonArray getPlayerInformation(Runnable runnable) {
+ if (playerInformation != null) return playerInformation;
+ if (updatingPlayerInfoState.get()) return null;
+
+ updatingPlayerInfoState.set(true);
+
+ HashMap<String, String> args = new HashMap<>();
+ args.put("uuid", "" + uuid);
+ manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/profiles",
+ args, jsonObject -> {
+ if (jsonObject == null) return;
+
+ updatingPlayerInfoState.set(false);
+ if (jsonObject.has("success") && jsonObject.get("success").getAsBoolean()) {
+ playerInformation = jsonObject.get("profiles").getAsJsonArray();
+ if (playerInformation == null) return;
+ String backup = null;
+ long backupLastSave = 0;
+
+ profileIds.clear();
+
+ for (int i = 0; i < playerInformation.size(); i++) {
+ JsonObject profile = playerInformation.get(i).getAsJsonObject();
+
+ if (!profile.has("members")) continue;
+ JsonObject members = profile.get("members").getAsJsonObject();
+
+ if (members.has(uuid)) {
+ 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()) {
+ continue;
+ }
+ }
+
+ String cute_name = profile.get("cute_name").getAsString();
+ if (backup == null) backup = cute_name;
+ profileIds.add(cute_name);
+ if (member.has("last_save")) {
+ long last_save = member.get("last_save").getAsLong();
+ if (last_save > backupLastSave) {
+ backupLastSave = last_save;
+ backup = cute_name;
+ }
+ }
+
+ }
+ }
+ if (runnable != null) runnable.run();
+ latestProfile = backup;
+ }
+ }, () -> {
+ updatingPlayerInfoState.set(false);
+ }
+ );
+
+ return null;
+ }
+
+ public List<String> getProfileIds() {
+ return profileIds;
+ }
+
+ public JsonObject getProfileInformation(String profileId) {
+ JsonArray playerInfo = getPlayerInformation(() -> {});
+ if(playerInfo == null) return null;
+ if(profileId == null) profileId = latestProfile;
+ if(profileMap.containsKey(profileId)) return profileMap.get(profileId);
+
+ for(int i=0; i<playerInformation.size(); i++) {
+ if(!playerInformation.get(i).isJsonObject()) {
+ playerInformation = null;
+ return null;
+ }
+ JsonObject profile = playerInformation.get(i).getAsJsonObject();
+ if(profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) {
+ if(!profile.has("members")) return null;
+ JsonObject members = profile.get("members").getAsJsonObject();
+ if(!members.has(uuid)) continue;
+ JsonObject profileInfo = members.get(uuid).getAsJsonObject();
+ if(profile.has("banking")) {
+ profileInfo.add("banking", profile.get("banking").getAsJsonObject());
+ }
+ profileMap.put(profileId, profileInfo);
+ return profileInfo;
+ }
+ }
+
+ return null;
+ }
+
+ public List<JsonObject> getCoopProfileInformation(String profileId) {
+ JsonArray playerInfo = getPlayerInformation(() -> {});
+ if(playerInfo == null) return null;
+ if(profileId == null) profileId = latestProfile;
+ if(coopProfileMap.containsKey(profileId)) return coopProfileMap.get(profileId);
+
+ for(int i=0; i<playerInformation.size(); i++) {
+ if(!playerInformation.get(i).isJsonObject()) {
+ playerInformation = null;
+ return null;
+ }
+ JsonObject profile = playerInformation.get(i).getAsJsonObject();
+ if(profile.get("cute_name").getAsString().equalsIgnoreCase(profileId)) {
+ if(!profile.has("members")) return null;
+ JsonObject members = profile.get("members").getAsJsonObject();
+ if(!members.has(uuid)) return null;
+ List<JsonObject> coopList = new ArrayList<>();
+ for(Map.Entry<String, JsonElement> islandMember : members.entrySet()) {
+ if(!islandMember.getKey().equals(uuid)) {
+ JsonObject coopProfileInfo = islandMember.getValue().getAsJsonObject();
+ coopList.add(coopProfileInfo);
+ }
+ }
+ coopProfileMap.put(profileId, coopList);
+ return coopList;
+ }
+ }
+
+ return null;
+ }
+
+ public void resetCache() {
+ playerInformation = null;
+ basicInfo = null;
+ playerStatus = null;
+ stats.clear();
+ passiveStats.clear();
+ profileIds.clear();
+ profileMap.clear();
+ coopProfileMap.clear();
+ petsInfoMap.clear();
+ skillInfoMap.clear();
+ inventoryInfoMap.clear();
+ collectionInfoMap.clear();
+ }
+
+ private class Level {
+ private float level = 0;
+ private float maxXpForLevel = 0;
+ private boolean maxed = false;
+ }
+
+ public Level getLevel(JsonArray levelingArray, float xp, boolean cumulative) {
+ Level levelObj = new Level();
+ 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();
+ levelObj.maxXpForLevel = (levelXp-previous);
+ levelObj.level = 1 + level + (xp-levelXp)/levelObj.maxXpForLevel;
+ } else {
+ levelObj.maxXpForLevel = levelXp;
+ levelObj.level = level + xp/levelXp;
+ }
+ return levelObj;
+ } else {
+ if(!cumulative) xp -= levelXp;
+ }
+ }
+ levelObj.level = levelingArray.size();
+ levelObj.maxed = true;
+ return levelObj;
+ }
+
+ public JsonObject getSkillInfo(String profileId) {
+ JsonObject profileInfo = getProfileInformation(profileId);
+ if(profileInfo == null) return null;
+ if(profileId == null) profileId = latestProfile;
+ if(skillInfoMap.containsKey(profileId)) return skillInfoMap.get(profileId);
+ JsonObject leveling = Utils.getConstant("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_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 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(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_slayer_zombie", experience_slayer_zombie);
+ skillInfo.addProperty("experience_slayer_spider", experience_slayer_spider);
+ skillInfo.addProperty("experience_slayer_wolf", experience_slayer_wolf);
+
+ Level level_skill_taming = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_taming, false);
+ Level level_skill_mining = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_mining, false);
+ Level level_skill_foraging = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_foraging, false);
+ Level level_skill_enchanting = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_enchanting, false);
+ Level level_skill_carpentry = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_carpentry, false);
+ Level level_skill_farming = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_farming, false);
+ Level level_skill_combat = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_combat, false);
+ Level level_skill_fishing = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_fishing, false);
+ Level level_skill_alchemy = getLevel(Utils.getElement(leveling, "leveling_xp").getAsJsonArray(), experience_skill_alchemy, false);
+ Level level_skill_runecrafting = getLevel(Utils.getElement(leveling, "runecrafting_xp").getAsJsonArray(), experience_skill_runecrafting, false);
+
+ Level level_slayer_zombie = getLevel(Utils.getElement(leveling, "slayer_xp.zombie").getAsJsonArray(), experience_slayer_zombie, true);
+ Level level_slayer_spider = getLevel(Utils.getElement(leveling, "slayer_xp.spider").getAsJsonArray(), experience_slayer_spider, true);
+ Level level_slayer_wolf = getLevel(Utils.getElement(leveling, "slayer_xp.wolf").getAsJsonArray(), experience_slayer_wolf, true);
+
+ 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_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("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_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("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_slayer_zombie", level_slayer_zombie.maxXpForLevel);
+ skillInfo.addProperty("maxxp_slayer_spider", level_slayer_spider.maxXpForLevel);
+ skillInfo.addProperty("maxxp_slayer_wolf", level_slayer_wolf.maxXpForLevel);
+
+ return skillInfo;
+ }
+
+ public JsonObject getInventoryInfo(String profileId) {
+ JsonObject profileInfo = getProfileInformation(profileId);
+ if(profileInfo == null) return null;
+ if(profileId == null) profileId = latestProfile;
+ if(inventoryInfoMap.containsKey(profileId)) return inventoryInfoMap.get(profileId);
+
+ String inv_armor_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "inv_armor.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String fishing_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "fishing_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String quiver_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "quiver.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String ender_chest_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "ender_chest_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String wardrobe_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "wardrobe_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String potion_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "potion_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String inv_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "inv_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String talisman_bag_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "talisman_bag.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+ String candy_inventory_contents_bytes = Utils.getElementAsString(Utils.getElement(profileInfo, "candy_inventory_contents.data"), "Hz8IAAAAAAAAAD9iYD9kYD9kAAMAPwI/Gw0AAAA=");
+
+ JsonObject inventoryInfo = new JsonObject();
+
+ String[] inv_names = new String[]{"inv_armor", "fishing_bag", "quiver", "ender_chest_contents", "wardrobe_contents",
+ "potion_bag", "inv_contents", "talisman_bag", "candy_inventory_contents"};
+ String[] inv_bytes = new String[]{inv_armor_bytes, fishing_bag_bytes, quiver_bytes, ender_chest_contents_bytes, wardrobe_contents_bytes,
+ potion_bag_bytes, inv_contents_bytes, talisman_bag_bytes, candy_inventory_contents_bytes};
+ for(int i=0; i<inv_bytes.length; i++) {
+ try {
+ String bytes = inv_bytes[i];
+
+ JsonArray contents = new JsonArray();
+ 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));
+ contents.add(item);
+ }
+ inventoryInfo.add(inv_names[i], contents);
+ } catch(IOException e) {
+ inventoryInfo.add(inv_names[i], new JsonArray());
+ }
+ }
+
+ return inventoryInfo;
+ }
+
+ public JsonObject getPetsInfo(String profileId) {
+ JsonObject profileInfo = getProfileInformation(profileId);
+ if(profileInfo == null) return null;
+ if(petsInfoMap.containsKey(profileId)) return petsInfoMap.get(profileId);
+
+ JsonObject petsInfo = new JsonObject();
+ JsonElement petsElement = profileInfo.get("pets");
+ if(petsElement != null && petsElement.isJsonArray()) {
+ JsonObject activePet = null;
+ 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()) {
+ activePet = pet;
+ break;
+ }
+ }
+ petsInfo.add("active_pet", activePet);
+ petsInfo.add("pets", pets);
+ petsInfoMap.put(profileId, petsInfo);
+ return petsInfo;
+ }
+ return null;
+ }
+
+ private final Pattern COLL_TIER_PATTERN = Pattern.compile("_(-?[0-9]+)");
+ public JsonObject getCollectionInfo(String profileId) {
+ JsonObject profileInfo = getProfileInformation(profileId);
+ 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);
+
+ JsonElement unlocked_coll_tiers_element = Utils.getElement(profileInfo, "unlocked_coll_tiers");
+ JsonElement crafted_generators_element = Utils.getElement(profileInfo, "crafted_generators");
+ JsonElement collectionInfoElement = Utils.getElement(profileInfo, "collection");
+
+ if(unlocked_coll_tiers_element == null || crafted_generators_element == null || collectionInfoElement == null) {
+ return null;
+ }
+
+ JsonObject collectionInfo = new JsonObject();
+ JsonObject collectionTiers = new JsonObject();
+ JsonObject minionTiers = new JsonObject();
+ JsonObject personalAmounts = new JsonObject();
+ JsonObject totalAmounts = new JsonObject();
+
+ if(collectionInfoElement.isJsonObject()) {
+ personalAmounts = collectionInfoElement.getAsJsonObject();
+ }
+
+ for(Map.Entry<String, JsonElement> entry : personalAmounts.entrySet()) {
+ totalAmounts.addProperty(entry.getKey(), entry.getValue().getAsInt());
+ }
+
+ List<JsonObject> coopProfiles = getCoopProfileInformation(profileId);
+ 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());
+ }
+ }
+ }
+ }
+
+ if(unlocked_coll_tiers_element != null && unlocked_coll_tiers_element.isJsonArray()) {
+ JsonArray unlocked_coll_tiers = unlocked_coll_tiers_element.getAsJsonArray();
+ for(int i=0; i<unlocked_coll_tiers.size(); i++) {
+ String unlocked = unlocked_coll_tiers.get(i).getAsString();
+
+ Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked);
+
+ if(matcher.find()) {
+ String tier_str = matcher.group(1);
+ int tier = Integer.parseInt(tier_str);
+ String coll = unlocked.substring(0, unlocked.length()-(matcher.group().length()));
+ if(!collectionTiers.has(coll) || collectionTiers.get(coll).getAsInt() < tier) {
+ collectionTiers.addProperty(coll, tier);
+ }
+ }
+ }
+ }
+
+ 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();
+
+ Matcher matcher = COLL_TIER_PATTERN.matcher(unlocked);
+
+ if(matcher.find()) {
+ String tier_str = matcher.group(1);
+ int tier = Integer.parseInt(tier_str);
+ String coll = unlocked.substring(0, unlocked.length()-(matcher.group().length()));
+ if(!minionTiers.has(coll) || minionTiers.get(coll).getAsInt() < tier) {
+ minionTiers.addProperty(coll, tier);
+ }
+ }
+ }
+ }
+
+ JsonObject maxAmount = new JsonObject();
+ JsonObject updatedCollectionTiers = new JsonObject();
+ for(Map.Entry<String, JsonElement> totalAmountsEntry : totalAmounts.entrySet()) {
+ String collName = totalAmountsEntry.getKey();
+ int collTier = (int)Utils.getElementAsFloat(collectionTiers.get(collName), 0);
+
+ int currentAmount = (int)Utils.getElementAsFloat(totalAmounts.get(collName), 0);
+ if(currentAmount > 0) {
+ for(Map.Entry<String, JsonElement> resourceEntry : resourceCollectionInfo.entrySet()) {
+ JsonElement tiersElement = Utils.getElement(resourceEntry.getValue(), "items."+collName+".tiers");
+ if(tiersElement != null && tiersElement.isJsonArray()) {
+ JsonArray tiers = tiersElement.getAsJsonArray();
+ int maxTierAcquired = -1;
+ int maxAmountRequired = -1;
+ for(int i=0; i<tiers.size(); i++) {
+ JsonObject tierInfo = tiers.get(i).getAsJsonObject();
+ int tier = tierInfo.get("tier").getAsInt();
+ int amountRequired = tierInfo.get("amountRequired").getAsInt();
+ if(currentAmount >= amountRequired) {
+ maxTierAcquired = tier;
+ }
+ maxAmountRequired = amountRequired;
+ }
+ if(maxTierAcquired >= 0 && maxTierAcquired > collTier) {
+ updatedCollectionTiers.addProperty(collName, maxTierAcquired);
+ }
+ maxAmount.addProperty(collName, maxAmountRequired);
+ }
+ }
+ }
+ }
+
+ for(Map.Entry<String, JsonElement> collectionTiersEntry : updatedCollectionTiers.entrySet()) {
+ collectionTiers.add(collectionTiersEntry.getKey(), collectionTiersEntry.getValue());
+ }
+
+ collectionInfo.add("minion_tiers", minionTiers);
+ collectionInfo.add("max_amounts", maxAmount);
+ collectionInfo.add("personal_amounts", personalAmounts);
+ collectionInfo.add("total_amounts", totalAmounts);
+ collectionInfo.add("collection_tiers", collectionTiers);
+
+ return collectionInfo;
+ }
+
+ public PlayerStats.Stats getPassiveStats(String profileId) {
+ if(passiveStats.get(profileId) != null) return passiveStats.get(profileId);
+ JsonObject profileInfo = getProfileInformation(profileId);
+ if(profileInfo == null) return null;
+
+ PlayerStats.Stats passiveStats = PlayerStats.getPassiveBonuses(getSkillInfo(profileId), profileInfo);
+
+ if(passiveStats != null) {
+ passiveStats.add(PlayerStats.getBaseStats());
+ }
+
+ this.passiveStats.put(profileId, passiveStats);
+
+ return passiveStats;
+ }
+
+ public PlayerStats.Stats getStats(String profileId) {
+ if(stats.get(profileId) != null) return stats.get(profileId);
+ JsonObject profileInfo = getProfileInformation(profileId);
+ if(profileInfo == null) return null;
+
+ PlayerStats.Stats stats = PlayerStats.getStats(getSkillInfo(profileId), getInventoryInfo(profileId), getCollectionInfo(profileId), profileInfo);
+ this.stats.put(profileId, stats);
+ return stats;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public JsonObject getHypixelProfile() {
+ if(uuidToHypixelProfile.containsKey(uuid)) return uuidToHypixelProfile.get(uuid);
+ return null;
+ }
+ }
+
+ private HashMap<String, JsonObject> nameToHypixelProfile = new HashMap<>();
+ private HashMap<String, JsonObject> uuidToHypixelProfile = new HashMap<>();
+ private HashMap<String, Profile> uuidToProfileMap = new HashMap<>();
+
+ public void getHypixelProfile(String name, Consumer<JsonObject> callback) {
+ HashMap<String, String> args = new HashMap<>();
+ args.put("name", ""+name);
+ manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "player",
+ args, jsonObject -> {
+ if(jsonObject != null && jsonObject.has("success") && jsonObject.get("success").getAsBoolean()
+ && jsonObject.get("player").isJsonObject()) {
+ nameToHypixelProfile.put(name, jsonObject.get("player").getAsJsonObject());
+ 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);
+ return;
+ }
+ }
+ );
+ }
+
+ public Profile getProfileByName(String name, Consumer<Profile> callback) {
+ if(nameToHypixelProfile.containsKey(name)) {
+ Profile profile = getProfileReset(nameToHypixelProfile.get(name).get("uuid").getAsString(), ignored -> {});
+ callback.accept(profile);
+ return profile;
+ } else {
+ getHypixelProfile(name, jsonObject -> {
+ if(jsonObject == null) {
+ callback.accept(null);
+ } else {
+ callback.accept(getProfileReset(jsonObject.get("player").getAsJsonObject().get("uuid").getAsString(), ignored -> {}));
+ }
+
+ });
+ }
+ return null;
+ }
+
+ 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) {
+ Profile profile = getProfile(uuid, callback);
+ profile.resetCache();
+ return profile;
+ }
+
+ private static JsonObject resourceCollection = null;
+ private static 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.manager.config.apiKey.value, "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/questing/NEUQuesting.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java
deleted file mode 100644
index 8be12c95..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package io.github.moulberry.notenoughupdates.questing;
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.util.Utils;
-import net.minecraft.client.Minecraft;
-import net.minecraft.scoreboard.Score;
-import net.minecraft.scoreboard.ScoreObjective;
-import net.minecraft.scoreboard.ScorePlayerTeam;
-import net.minecraft.scoreboard.Scoreboard;
-import net.minecraft.util.EnumChatFormatting;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class NEUQuesting {
-
- private static final NEUQuesting INSTANCE = new NEUQuesting();
-
- private static final Pattern locationPattern = Pattern.compile("(\\u00a7)(?!.*\\u00a7).+");
- private static final Pattern timePattern = Pattern.compile(".+(am|pm)");
-
- public String location = "";
- public String date = "";
- public String time = "";
-
- public static NEUQuesting getInstance() {
- return INSTANCE;
- }
-
- public void tick() {
- Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard();
-
- ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); //§707/14/20
-
- List<Score> scores = new ArrayList<>();
- for(Score score : scoreboard.getSortedScores(sidebarObjective)) {
- scores.add(score);
- }
- List<String> lines = new ArrayList<>();
- for(int i=scores.size()-1; i>=0; i--) {
- Score score = scores.get(i);
- ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName());
- String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName());
- line = Utils.cleanDuplicateColourCodes(line);
- lines.add(line);
- }
- if(lines.size() >= 5) {
- date = Utils.cleanColour(lines.get(2)).trim();
- //§74:40am
- Matcher matcher = timePattern.matcher(lines.get(3));
- if(matcher.find()) {
- time = Utils.cleanColour(matcher.group()).trim();
- }
- matcher = locationPattern.matcher(lines.get(4));
- if(matcher.find()) {
- location = Utils.cleanColour(matcher.group()).trim();
- }
- }
- //System.out.println(date + ":" + time + ":" + location);
- }
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/SBScoreboardData.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/SBScoreboardData.java
new file mode 100644
index 00000000..4c19dd39
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/SBScoreboardData.java
@@ -0,0 +1,76 @@
+package io.github.moulberry.notenoughupdates.questing;
+
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.scoreboard.Score;
+import net.minecraft.scoreboard.ScoreObjective;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Scoreboard;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class SBScoreboardData {
+
+ private static final SBScoreboardData INSTANCE = new SBScoreboardData();
+
+ private static final Pattern locationPattern = Pattern.compile("(\\u00a7)(?!.*\\u00a7).+");
+ private static final Pattern timePattern = Pattern.compile(".+(am|pm)");
+
+ public String location = "";
+ public String date = "";
+ public String time = "";
+
+ public Date currentTimeDate = null;
+
+ public static SBScoreboardData getInstance() {
+ return INSTANCE;
+ }
+
+ public void tick() {
+ try {
+ Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard();
+
+ ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1); //§707/14/20
+
+ List<Score> scores = new ArrayList<>();
+ for(Score score : scoreboard.getSortedScores(sidebarObjective)) {
+ scores.add(score);
+ }
+ List<String> lines = new ArrayList<>();
+ for(int i=scores.size()-1; i>=0; i--) {
+ Score score = scores.get(i);
+ ScorePlayerTeam scoreplayerteam1 = scoreboard.getPlayersTeam(score.getPlayerName());
+ String line = ScorePlayerTeam.formatPlayerName(scoreplayerteam1, score.getPlayerName());
+ line = Utils.cleanDuplicateColourCodes(line);
+ lines.add(line);
+ }
+ if(lines.size() >= 5) {
+ date = Utils.cleanColour(lines.get(2)).trim();
+ //§74:40am
+ Matcher matcher = timePattern.matcher(lines.get(3));
+ if(matcher.find()) {
+ time = Utils.cleanColour(matcher.group()).trim();
+ try {
+ String timeSpace = time.replace("am", " am").replace("pm", " pm");
+ SimpleDateFormat parseFormat = new SimpleDateFormat("hh:mm a");
+ currentTimeDate = parseFormat.parse(timeSpace);
+ } catch (ParseException e) {}
+ }
+ matcher = locationPattern.matcher(lines.get(4));
+ if(matcher.find()) {
+ location = Utils.cleanColour(matcher.group()).trim();
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ //System.out.println(date + ":" + time + ":" + location);
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java
index 951cfa50..16da64fe 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementApi.java
@@ -3,10 +3,8 @@ package io.github.moulberry.notenoughupdates.questing.requirements;
import com.google.common.base.Splitter;
import com.google.gson.*;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
-import io.github.moulberry.notenoughupdates.questing.NEUQuesting;
import java.util.List;
-import java.util.Map;
public class RequirementApi extends Requirement {
@@ -40,7 +38,6 @@ public class RequirementApi extends Requirement {
private static JsonElement getElement(JsonElement element, String path) {
List<String> path_split = PATH_SPLITTER.splitToList(path);
if(element instanceof JsonObject) {
- System.out.println(path_split.get(0));
JsonElement e = element.getAsJsonObject().get(path_split.get(0));
if(path_split.size() > 1) {
return getElement(e, path_split.get(1));
@@ -100,12 +97,12 @@ public class RequirementApi extends Requirement {
@Override
public void updateRequirement() {
if(valid) {
- JsonObject profile = NotEnoughUpdates.INSTANCE.manager.auctionManager.getPlayerInformation();
+ /*JsonObject profile = NotEnoughUpdates.INSTANCE.manager.auctionManager.getPlayerInformation();
if(profile != null) {
System.out.println("-----------");
JsonElement element = getElement(profile, requirementLeft);
completed = checkElementSatisfiesComparison(element, op, requirementRight);
- }
+ }*/
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java
index 5ee005f5..319bc1b6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/requirements/RequirementIslandType.java
@@ -1,6 +1,6 @@
package io.github.moulberry.notenoughupdates.questing.requirements;
-import io.github.moulberry.notenoughupdates.questing.NEUQuesting;
+import io.github.moulberry.notenoughupdates.questing.SBScoreboardData;
public class RequirementIslandType extends Requirement {
@@ -14,6 +14,6 @@ public class RequirementIslandType extends Requirement {
@Override
public void updateRequirement() {
- completed = islandType.equalsIgnoreCase(NEUQuesting.getInstance().location);
+ completed = islandType.equalsIgnoreCase(SBScoreboardData.getInstance().location);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
index c271d63a..ca6c30af 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java
@@ -2,6 +2,7 @@ package io.github.moulberry.notenoughupdates.util;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
+import org.apache.commons.io.IOUtils;
import java.io.BufferedReader;
import java.io.IOException;
@@ -16,57 +17,68 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.function.Consumer;
+import java.util.zip.GZIPInputStream;
public class HypixelApi {
-
- /**
- * Not currently used as of BETA-1.6.
- */
-
private Gson gson = new Gson();
- private ExecutorService es = Executors.newCachedThreadPool();
+ private ExecutorService es = Executors.newFixedThreadPool(3);
public void getHypixelApiAsync(String apiKey, String method, HashMap<String, String> args, Consumer<JsonObject> consumer) {
- getHypixelApiAsync(generateApiUrl(apiKey.trim(), method, args), consumer);
+ getHypixelApiAsync(apiKey, method, args, consumer, () -> {});
}
- public void getHypixelApiAsync(String urlS, Consumer<JsonObject> consumer) {
+ public void getHypixelApiAsync(String apiKey, String method, HashMap<String, String> args, Consumer<JsonObject> consumer, Runnable error) {
+ getApiAsync(generateApiUrl(apiKey.trim(), method, args), consumer, error);
+ }
+
+ public void getApiAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
es.submit(() -> {
- consumer.accept(getHypixelApiSync(urlS));
+ try {
+ consumer.accept(getApiSync(urlS));
+ } catch(IOException e) {
+ error.run();
+ }
});
}
- public JsonObject getHypixelApiSync(String urlS) {
- URLConnection connection;
- try {
- URL url = new URL(urlS);
- connection = url.openConnection();
- connection.setConnectTimeout(3000);
- } catch(IOException e) {
- return null;
- }
-
- try(BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8))) {
- StringBuilder builder = new StringBuilder();
- int codePoint;
- while((codePoint = reader.read()) != -1) {
- builder.append(((char)codePoint));
+ public void getApiGZIPAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
+ es.submit(() -> {
+ try {
+ consumer.accept(getApiGZIPSync(urlS));
+ } catch(IOException e) {
+ error.run();
}
- String response = builder.toString();
+ });
+ }
- JsonObject json = gson.fromJson(response, JsonObject.class);
- return json;
- } catch(IOException e) {
- return null;
- }
+ public JsonObject getApiSync(String urlS) throws IOException {
+ URL url = new URL(urlS);
+ URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(3000);
+
+ String response = IOUtils.toString(connection.getInputStream(), StandardCharsets.UTF_8);
+
+ JsonObject json = gson.fromJson(response, JsonObject.class);
+ return json;
+ }
+
+ public JsonObject getApiGZIPSync(String urlS) throws IOException {
+ URL url = new URL(urlS);
+ URLConnection connection = url.openConnection();
+ connection.setConnectTimeout(3000);
+
+ 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) {
- String url = "https://api.hypixel.net/" + method + "?key=" + apiKey;
+ StringBuilder url = new StringBuilder("https://api.hypixel.net/" + method + "?key=" + apiKey);
for(Map.Entry<String, String> entry : args.entrySet()) {
- url += "&" + entry.getKey() + "=" + entry.getValue();
+ url.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
- return url;
+ return url.toString();
}
}
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 57b89a0a..144db9da 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
@@ -1,5 +1,10 @@
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 com.google.gson.JsonPrimitive;
import com.mojang.authlib.Agent;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
@@ -9,13 +14,18 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.client.audio.SoundHandler;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
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.ItemCameraTransforms;
import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.event.ClickEvent;
import net.minecraft.event.HoverEvent;
import net.minecraft.inventory.Slot;
@@ -29,6 +39,7 @@ import net.minecraft.util.*;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
+import org.lwjgl.util.glu.Project;
import javax.swing.*;
import java.awt.*;
@@ -72,7 +83,7 @@ public class Utils {
RenderHelper.disableStandardItemLighting();
}
- public static void drawItemStack(ItemStack stack, int x, int y) {
+ public static void drawItemStackWithText(ItemStack stack, int x, int y, String text) {
if(stack == null)return;
RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
@@ -80,11 +91,91 @@ public class Utils {
RenderHelper.enableGUIStandardItemLighting();
itemRender.zLevel = -145; //Negates the z-offset of the below method.
itemRender.renderItemAndEffectIntoGUI(stack, x, y);
+ itemRender.renderItemOverlayIntoGUI(Minecraft.getMinecraft().fontRendererObj, stack, x, y, text);
+ itemRender.zLevel = 0;
+ RenderHelper.disableStandardItemLighting();
+ }
+
+ 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 String chromaString(String str) {
+ long currentTimeMillis = System.currentTimeMillis();
+
+ StringBuilder rainbowText = new StringBuilder();
+ for(int i=0; i<str.length(); i++) {
+ char c = str.charAt(i);
+ int index = (int)(i-currentTimeMillis/100)%rainbow.length;
+ if(index < 0) index += rainbow.length;
+ rainbowText.append(rainbow[index]).append(c);
+ }
+ return rainbowText.toString();
+ }
+
+ public static void drawItemStackLinear(ItemStack stack, int x, int y) {
+ if(stack == null)return;
+
+ RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
+
+ RenderHelper.enableGUIStandardItemLighting();
+ itemRender.zLevel = -145; //Negates the z-offset of the below method.
+
+ IBakedModel ibakedmodel = itemRender.getItemModelMesher().getItemModel(stack);
+ GlStateManager.pushMatrix();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
+ Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture).setBlurMipmap(true, true);
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.enableAlpha();
+ GlStateManager.alphaFunc(516, 0.1F);
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ setupGuiTransform(x, y, ibakedmodel.isGui3d());
+ ibakedmodel = net.minecraftforge.client.ForgeHooksClient.handleCameraTransforms(ibakedmodel, ItemCameraTransforms.TransformType.GUI);
+ itemRender.renderItem(stack, ibakedmodel);
+ GlStateManager.disableAlpha();
+ GlStateManager.disableRescaleNormal();
+ GlStateManager.disableLighting();
+ GlStateManager.popMatrix();
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
+ Minecraft.getMinecraft().getTextureManager().getTexture(TextureMap.locationBlocksTexture).restoreLastBlurMipmap();
+
itemRender.renderItemOverlays(Minecraft.getMinecraft().fontRendererObj, stack, x, y);
itemRender.zLevel = 0;
RenderHelper.disableStandardItemLighting();
}
+ private static void setupGuiTransform(int xPosition, int yPosition, boolean isGui3d) {
+ GlStateManager.translate((float)xPosition, (float)yPosition, 5);
+ GlStateManager.translate(8.0F, 8.0F, 0.0F);
+ GlStateManager.scale(1.0F, 1.0F, -1.0F);
+ GlStateManager.scale(0.5F, 0.5F, 0.5F);
+
+ if (isGui3d) {
+ GlStateManager.scale(40.0F, 40.0F, 40.0F);
+ GlStateManager.rotate(210.0F, 1.0F, 0.0F, 0.0F);
+ GlStateManager.rotate(-135.0F, 0.0F, 1.0F, 0.0F);
+ GlStateManager.enableLighting();
+ } else {
+ GlStateManager.scale(64.0F, 64.0F, 64.0F);
+ GlStateManager.rotate(180.0F, 1.0F, 0.0F, 0.0F);
+ GlStateManager.disableLighting();
+ }
+ }
+
public static Method getMethod(Class<?> clazz, Class<?>[] params, String... methodNames) {
for(String methodName : methodNames) {
try {
@@ -144,6 +235,33 @@ public class Utils {
return str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();
}
+ private static String[] rarityArr = new String[] {
+ "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL",
+ };
+ public static int checkItemType(JsonArray lore, boolean contains, String... typeMatches) {
+ for(int i=lore.size()-1; i>=0; i--) {
+ String line = lore.get(i).getAsString();
+ for(String rarity : rarityArr) {
+ for(int j=0; j<typeMatches.length; j++) {
+ if(contains) {
+ if(line.trim().contains(rarity + " " + typeMatches[j])) {
+ return j;
+ } else if(line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) {
+ return j;
+ }
+ } else {
+ if(line.trim().endsWith(rarity + " " + typeMatches[j])) {
+ return j;
+ } else if(line.trim().endsWith(rarity + " DUNGEON " + typeMatches[j])) {
+ return j;
+ }
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
public static void playPressSound() {
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.create(
new ResourceLocation("gui.button.press"), 1.0F));
@@ -206,7 +324,11 @@ public class Utils {
}
public static ItemStack createItemStack(Item item, String displayname, String... lore) {
- ItemStack stack = new ItemStack(item);
+ return createItemStack(item, displayname, 0, 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();
NBTTagList Lore = new NBTTagList();
@@ -219,12 +341,18 @@ public class Utils {
display.setTag("Lore", Lore);
tag.setTag("display", display);
+ tag.setInteger("HideFlags", 254);
stack.setTagCompound(tag);
return stack;
}
+ public static void drawStringF(String str, FontRenderer fr, float x, float y, boolean shadow, int colour) {
+ GL11.glTranslatef(x, y, 0);
+ fr.drawString(str, x, y, colour, shadow);
+ }
+
public static void drawStringScaledMaxWidth(String str, FontRenderer fr, float x, float y, boolean shadow, int len, int colour) {
int strLen = fr.getStringWidth(str);
float factor = len/(float)strLen;
@@ -261,6 +389,19 @@ public class Utils {
drawStringScaled(str, fr, x-newLen/2, y-fontHeight/2, shadow, colour, factor);
}
+ public static 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;
+ }
+
public static void drawStringCenteredScaled(String str, FontRenderer fr, float x, float y, boolean shadow, int len, int colour) {
int strLen = fr.getStringWidth(str);
float factor = len/(float)strLen;
@@ -277,6 +418,15 @@ public class Utils {
drawStringScaled(str, fr, x, y-fontHeight/2, shadow, colour, factor);
}
+ public static void drawStringCenteredYScaledMaxWidth(String str, FontRenderer fr, float x, float y, boolean shadow, int len, int colour) {
+ int strLen = fr.getStringWidth(str);
+ float factor = len/(float)strLen;
+ factor = Math.min(1, factor);
+ float fontHeight = 8*factor;
+
+ drawStringScaled(str, fr, x, y-fontHeight/2, shadow, colour, factor);
+ }
+
public static int renderStringTrimWidth(String str, FontRenderer fr, boolean shadow, int x, int y, int len, int colour, int maxLines) {
return renderStringTrimWidth(str, fr, shadow, x, y, len, colour, maxLines, 1);
}
@@ -376,6 +526,50 @@ public class Utils {
drawHoveringText(textLines, mouseX, mouseY, screenWidth, screenHeight, maxTextWidth, font, true);
}
+ public static JsonObject getConstant(String constant) {
+ File repo = NotEnoughUpdates.INSTANCE.manager.repoLocation;
+ if(repo.exists()) {
+ File jsonFile = new File(repo, "constants/"+constant+".json");
+ try {
+ return NotEnoughUpdates.INSTANCE.manager.getJsonFromFile(jsonFile);
+ } catch (Exception ignored) {
+ }
+ }
+ System.out.println(constant + " = null");
+ return null;
+ }
+
+ public static float getElementAsFloat(JsonElement element, float def) {
+ if(element == null) return def;
+ if(!element.isJsonPrimitive()) return def;
+ JsonPrimitive prim = element.getAsJsonPrimitive();
+ if(!prim.isNumber()) return def;
+ return prim.getAsFloat();
+ }
+
+ public static String getElementAsString(JsonElement element, String def) {
+ if(element == null) return def;
+ if(!element.isJsonPrimitive()) return def;
+ JsonPrimitive prim = element.getAsJsonPrimitive();
+ if(!prim.isString()) return def;
+ 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) {
+ JsonElement e = element.getAsJsonObject().get(path_split.get(0));
+ if(path_split.size() > 1) {
+ return getElement(e, path_split.get(1));
+ } else {
+ return e;
+ }
+ } else {
+ return element;
+ }
+ }
+
public static ChatStyle createClickStyle(ClickEvent.Action action, String value) {
ChatStyle style = new ChatStyle();
style.setChatClickEvent(new ClickEvent(action, value));
@@ -392,6 +586,39 @@ public class Utils {
file.delete();
}
+ public static Color getPrimaryColour(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);
+ if(c == '\u00A7') {
+ lastColourCode = i;
+ } else if(lastColourCode == i-1) {
+ int colIndex = "0123456789abcdef".indexOf(c);
+ if(colIndex >= 0) {
+ currentColour = colIndex;
+ } else {
+ currentColour = 0;
+ }
+ } else if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(c) >= 0){
+ if(currentColour > 0) {
+ mostCommon[currentColour]++;
+ }
+ }
+ }
+ int mostCommonCount = 0;
+ for(int index=0; index<mostCommon.length; index++) {
+ if(mostCommon[index] > mostCommonCount) {
+ mostCommonCount = mostCommon[index];
+ currentColour = index;
+ }
+ }
+
+ int colourInt = Minecraft.getMinecraft().fontRendererObj.getColorCode("0123456789abcdef".charAt(currentColour));
+ return new Color(colourInt).darker();
+ }
+
public static void drawHoveringText(List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font, boolean coloured) {
if (!textLines.isEmpty())
{
@@ -502,36 +729,7 @@ public class Utils {
if(NotEnoughUpdates.INSTANCE.manager.config.tooltipBorderColours.value && coloured) {
if(textLines.size() > 0) {
String first = textLines.get(0);
- 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<first.length(); i++) {
- char c = first.charAt(i);
- if(c == '\u00A7') {
- lastColourCode = i;
- } else if(lastColourCode == i-1) {
- int colIndex = "0123456789abcdef".indexOf(c);
- if(colIndex >= 0) {
- currentColour = colIndex;
- } else {
- currentColour = 0;
- }
- } else if("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(c) >= 0){
- if(currentColour > 0) {
- mostCommon[currentColour]++;
- }
- }
- }
- int mostCommonCount = 0;
- for(int index=0; index<mostCommon.length; index++) {
- if(mostCommon[index] > mostCommonCount) {
- mostCommonCount = mostCommon[index];
- currentColour = index;
- }
- }
-
- int colourInt = font.getColorCode("0123456789abcdef".charAt(currentColour));
- borderColorStart = new Color(colourInt).darker().getRGB() & 0x00FFFFFF |
+ borderColorStart = getPrimaryColour(first).getRGB() & 0x00FFFFFF |
((NotEnoughUpdates.INSTANCE.manager.config.tooltipBorderOpacity.value.intValue()) << 24);
}
}
diff --git a/src/main/resources/assets/notenoughupdates/button20x.png b/src/main/resources/assets/notenoughupdates/button20x.png
new file mode 100644
index 00000000..8d723798
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/button20x.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/custom_ench_colour.png b/src/main/resources/assets/notenoughupdates/custom_ench_colour.png
new file mode 100644
index 00000000..2c1c717e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/custom_ench_colour.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/folder.png b/src/main/resources/assets/notenoughupdates/folder.png
new file mode 100644
index 00000000..f4af7353
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/folder.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_0.jpg
new file mode 100644
index 00000000..27531695
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_1.jpg
new file mode 100644
index 00000000..5586cf8a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_2.jpg
new file mode 100644
index 00000000..78540079
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_3.jpg
new file mode 100644
index 00000000..74bc8f23
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_4.jpg
new file mode 100644
index 00000000..cdf3fdde
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_5.jpg
new file mode 100644
index 00000000..63ce6702
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_0.jpg
new file mode 100644
index 00000000..93ee50d1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_1.jpg
new file mode 100644
index 00000000..9f100e8c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_2.jpg
new file mode 100644
index 00000000..7c1e9d5d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_3.jpg
new file mode 100644
index 00000000..133e3d4a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_4.jpg
new file mode 100644
index 00000000..c049a2fa
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_5.jpg
new file mode 100644
index 00000000..f9e5ed40
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_1_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_0.jpg
new file mode 100644
index 00000000..0bfb0d2e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_1.jpg
new file mode 100644
index 00000000..b4890bc5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_2.jpg
new file mode 100644
index 00000000..ea7da9aa
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_3.jpg
new file mode 100644
index 00000000..92013d1a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_4.jpg
new file mode 100644
index 00000000..2e3da992
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_5.jpg
new file mode 100644
index 00000000..95398c35
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_0.jpg
new file mode 100644
index 00000000..837a2928
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_1.jpg
new file mode 100644
index 00000000..6f988421
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_2.jpg
new file mode 100644
index 00000000..0c664062
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_3.jpg
new file mode 100644
index 00000000..278d92f1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_4.jpg
new file mode 100644
index 00000000..f9205c52
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_5.jpg
new file mode 100644
index 00000000..5ca08bf9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_2_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_0.jpg
new file mode 100644
index 00000000..f1f6a028
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_1.jpg
new file mode 100644
index 00000000..882e20a2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_2.jpg
new file mode 100644
index 00000000..3ec9391f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_3.jpg
new file mode 100644
index 00000000..0c99863b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_4.jpg
new file mode 100644
index 00000000..92b62ab3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_5.jpg
new file mode 100644
index 00000000..169c36be
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_0.jpg
new file mode 100644
index 00000000..cb60f6d3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_1.jpg
new file mode 100644
index 00000000..d538b920
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_2.jpg
new file mode 100644
index 00000000..27894a8a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_3.jpg
new file mode 100644
index 00000000..39a3b594
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_4.jpg
new file mode 100644
index 00000000..b172a40c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_5.jpg
new file mode 100644
index 00000000..3edaba89
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/combat_3_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_0.jpg
new file mode 100644
index 00000000..32f9f7bb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_1.jpg
new file mode 100644
index 00000000..ece00b29
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_2.jpg
new file mode 100644
index 00000000..298621e3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_3.jpg
new file mode 100644
index 00000000..ed4af05e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_4.jpg
new file mode 100644
index 00000000..aca79dcf
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_5.jpg
new file mode 100644
index 00000000..398e21c9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dark_auction/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_0.jpg
new file mode 100644
index 00000000..494c5fe0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_1.jpg
new file mode 100644
index 00000000..5da4d3e5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_2.jpg
new file mode 100644
index 00000000..445c31dc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_3.jpg
new file mode 100644
index 00000000..1de0182b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_4.jpg
new file mode 100644
index 00000000..75b6cd4e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_5.jpg
new file mode 100644
index 00000000..c5e99eac
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_0.jpg
new file mode 100644
index 00000000..494c5fe0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_1.jpg
new file mode 100644
index 00000000..5da4d3e5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_2.jpg
new file mode 100644
index 00000000..445c31dc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_3.jpg
new file mode 100644
index 00000000..1de0182b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_4.jpg
new file mode 100644
index 00000000..75b6cd4e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_5.jpg
new file mode 100644
index 00000000..c5e99eac
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dungeon_hub/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_0.jpg
new file mode 100644
index 00000000..f6231245
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_1.jpg
new file mode 100644
index 00000000..286b3a38
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_2.jpg
new file mode 100644
index 00000000..c6fca879
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_3.jpg
new file mode 100644
index 00000000..01b2f816
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_4.jpg
new file mode 100644
index 00000000..a5c810fe
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_5.jpg
new file mode 100644
index 00000000..30d32a08
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_0.jpg
new file mode 100644
index 00000000..b1fb3e84
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_1.jpg
new file mode 100644
index 00000000..f7642beb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_2.jpg
new file mode 100644
index 00000000..3cb3b42f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_3.jpg
new file mode 100644
index 00000000..a98d7672
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_4.jpg
new file mode 100644
index 00000000..ad2b8c70
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_5.jpg
new file mode 100644
index 00000000..f2e93cde
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/dynamic_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_0.jpg
new file mode 100644
index 00000000..c03b849d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_1.jpg
new file mode 100644
index 00000000..2286407b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_2.jpg
new file mode 100644
index 00000000..62127f51
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_3.jpg
new file mode 100644
index 00000000..fe631d89
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_4.jpg
new file mode 100644
index 00000000..cf835eea
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_5.jpg
new file mode 100644
index 00000000..879b5747
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_0.jpg
new file mode 100644
index 00000000..265515f6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_1.jpg
new file mode 100644
index 00000000..e774ca7a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_2.jpg
new file mode 100644
index 00000000..1e3c8a98
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_3.jpg
new file mode 100644
index 00000000..7833eb89
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_4.jpg
new file mode 100644
index 00000000..63fafd87
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_5.jpg
new file mode 100644
index 00000000..ae3bdbdf
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_1_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_0.jpg
new file mode 100644
index 00000000..e03657af
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_1.jpg
new file mode 100644
index 00000000..27db8499
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_2.jpg
new file mode 100644
index 00000000..c83f2c91
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_3.jpg
new file mode 100644
index 00000000..9b730712
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_4.jpg
new file mode 100644
index 00000000..e687ac9d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_5.jpg
new file mode 100644
index 00000000..a17337b9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_0.jpg
new file mode 100644
index 00000000..26909780
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_1.jpg
new file mode 100644
index 00000000..d1eb9e1b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_2.jpg
new file mode 100644
index 00000000..dafe1dd3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_3.jpg
new file mode 100644
index 00000000..0e870f38
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_4.jpg
new file mode 100644
index 00000000..51a760f5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_5.jpg
new file mode 100644
index 00000000..f40c330c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/farming_2_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_0.jpg
new file mode 100644
index 00000000..9a12896f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_1.jpg
new file mode 100644
index 00000000..c157ccdd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_2.jpg
new file mode 100644
index 00000000..ecee024b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_3.jpg
new file mode 100644
index 00000000..0dbef91f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_4.jpg
new file mode 100644
index 00000000..681aa33e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_5.jpg
new file mode 100644
index 00000000..6be866d2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_0.jpg
new file mode 100644
index 00000000..050e4f78
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_1.jpg
new file mode 100644
index 00000000..c3f012a2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_2.jpg
new file mode 100644
index 00000000..557d7396
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_3.jpg
new file mode 100644
index 00000000..3af3638e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_4.jpg
new file mode 100644
index 00000000..b5f913e6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_5.jpg
new file mode 100644
index 00000000..d3c13992
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/foraging_1_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_0.jpg
new file mode 100644
index 00000000..0d5f26dd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_1.jpg
new file mode 100644
index 00000000..820b92a4
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_2.jpg
new file mode 100644
index 00000000..14d01dd1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_3.jpg
new file mode 100644
index 00000000..bfc66ec9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_4.jpg
new file mode 100644
index 00000000..07f17d24
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_5.jpg
new file mode 100644
index 00000000..f3df82a5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_0.jpg
new file mode 100644
index 00000000..34bc84db
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_1.jpg
new file mode 100644
index 00000000..742d158b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_2.jpg
new file mode 100644
index 00000000..abf0a253
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_3.jpg
new file mode 100644
index 00000000..7efc75d6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_4.jpg
new file mode 100644
index 00000000..a7f7988b
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_5.jpg
new file mode 100644
index 00000000..e86e93c4
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/hub_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_0.jpg
new file mode 100644
index 00000000..e0c4288d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_1.jpg
new file mode 100644
index 00000000..e0cc8139
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_2.jpg
new file mode 100644
index 00000000..381912e1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_3.jpg
new file mode 100644
index 00000000..0beaf628
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_4.jpg
new file mode 100644
index 00000000..26417482
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_5.jpg
new file mode 100644
index 00000000..8571b288
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_day/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_0.jpg
new file mode 100644
index 00000000..e90efd5f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_1.jpg
new file mode 100644
index 00000000..603f9d04
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_2.jpg
new file mode 100644
index 00000000..b4d253f6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_3.jpg
new file mode 100644
index 00000000..abd201d1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_4.jpg
new file mode 100644
index 00000000..4c12b0b9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_5.jpg
new file mode 100644
index 00000000..93a5a26d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_1_night/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_0.jpg
new file mode 100644
index 00000000..7aced4cc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_1.jpg
new file mode 100644
index 00000000..852a1af2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_2.jpg
new file mode 100644
index 00000000..6710318f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_3.jpg
new file mode 100644
index 00000000..3d42e658
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_4.jpg
new file mode 100644
index 00000000..08abb255
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_5.jpg
new file mode 100644
index 00000000..3d4845d9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/mining_2/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_0.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_0.jpg
new file mode 100644
index 00000000..9482df80
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_1.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_1.jpg
new file mode 100644
index 00000000..1b4235dd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_1.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_2.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_2.jpg
new file mode 100644
index 00000000..2f1fcc06
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_2.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_3.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_3.jpg
new file mode 100644
index 00000000..ce20d9b5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_3.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_4.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_4.jpg
new file mode 100644
index 00000000..3dcdac57
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_4.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_5.jpg b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_5.jpg
new file mode 100644
index 00000000..45f65c7c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/panoramas/unknown/panorama_5.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/patreon1.png b/src/main/resources/assets/notenoughupdates/patreon1.png
new file mode 100644
index 00000000..aba027bc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/patreon1.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/patreon2.png b/src/main/resources/assets/notenoughupdates/patreon2.png
new file mode 100644
index 00000000..1c5a848a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/patreon2.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_basic.png b/src/main/resources/assets/notenoughupdates/pv_basic.png
new file mode 100644
index 00000000..227bad5a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_basic.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_bg.png b/src/main/resources/assets/notenoughupdates/pv_bg.png
new file mode 100644
index 00000000..6c09e78d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_bg.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_cols.png b/src/main/resources/assets/notenoughupdates/pv_cols.png
new file mode 100644
index 00000000..d0f2fa73
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_cols.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_dropdown.png b/src/main/resources/assets/notenoughupdates/pv_dropdown.png
new file mode 100644
index 00000000..af847f27
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_dropdown.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_elements.png b/src/main/resources/assets/notenoughupdates/pv_elements.png
new file mode 100644
index 00000000..0020478e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_elements.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_extra.png b/src/main/resources/assets/notenoughupdates/pv_extra.png
new file mode 100644
index 00000000..3203c85f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_extra.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_invs.png b/src/main/resources/assets/notenoughupdates/pv_invs.png
new file mode 100644
index 00000000..881078d2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_invs.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/pv_pets.png b/src/main/resources/assets/notenoughupdates/pv_pets.png
new file mode 100644
index 00000000..c953c313
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/pv_pets.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/shaders/cape.frag b/src/main/resources/assets/notenoughupdates/shaders/cape.frag
index cbe00c70..bfc089bb 100644
--- a/src/main/resources/assets/notenoughupdates/shaders/cape.frag
+++ b/src/main/resources/assets/notenoughupdates/shaders/cape.frag
@@ -8,9 +8,9 @@ void main() {
vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
gl_FragColor = texture * passColour;
- vec3 fakeSunNormal = normalize(vec3(0.2f,1f,-0.2f));
+ vec3 fakeSunNormal = normalize(vec3(0.2f,1.0f,-0.2f));
vec3 normNormal = normalize(passNormal);
float shading = max(0.6f, dot(fakeSunNormal, normNormal));
- gl_FragColor = vec4(gl_FragColor.rgb*shading, gl_FragColor.a);//gl_FragColor.rgb*shading
+ gl_FragColor = vec4(gl_FragColor.rgb*shading, gl_FragColor.a);
} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/fade_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/fade_cape.frag
index 76738c31..33d6b341 100644
--- a/src/main/resources/assets/notenoughupdates/shaders/fade_cape.frag
+++ b/src/main/resources/assets/notenoughupdates/shaders/fade_cape.frag
@@ -16,16 +16,16 @@ vec3 hsv2rgb(vec3 c) {
void main() {
vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
- float hue = mod(millis/10000f+gl_TexCoord[0].t, 1f);
+ float hue = mod(millis/10000.0f+gl_TexCoord[0].t, 1.0f);
float sat = 0.5f;
float val = 0.5f;
vec3 fade = hsv2rgb(vec3(hue, sat, val));
- gl_FragColor = vec4(texture.rgb*texture.a + fade*(1-texture.a), 1f) * passColour;
+ gl_FragColor = vec4(texture.rgb*texture.a + fade*(1.0f-texture.a), 1.0f) * passColour;
- vec3 fakeSunNormal = normalize(vec3(0.2f,1f,-0.2f));
+ vec3 fakeSunNormal = normalize(vec3(0.2f,1.0f,-0.2f));
vec3 normNormal = normalize(passNormal);
float shading = max(0.6f, dot(fakeSunNormal, normNormal));
gl_FragColor = vec4(gl_FragColor.rgb*shading, gl_FragColor.a);
-} \ No newline at end of file
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/make_gold.frag b/src/main/resources/assets/notenoughupdates/shaders/make_gold.frag
new file mode 100644
index 00000000..e771f2c2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/make_gold.frag
@@ -0,0 +1,38 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passPosition;
+uniform sampler2D textureIn;
+
+uniform float amount;
+
+//Algorithm by sam hocevar
+vec3 rgb2hsv(vec3 c) {
+ vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
+ vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));
+ vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));
+
+ float d = q.x - min(q.w, q.y);
+ float e = 1.0e-10;
+ return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
+}
+
+//Algorithm by hughsk
+vec3 hsv2rgb(vec3 c) {
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
+}
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ vec3 hsv = rgb2hsv(texture.rgb);
+
+ float hue = mod(hsv.x + amount + passPosition.x*4.0f, 1.0f);
+ float sat = hsv.y*0.7f;
+ float val = hsv.z;
+ vec3 fade = hsv2rgb(vec3(hue, sat, val));
+
+ gl_FragColor = vec4(fade.rgb, texture.a);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/make_gold.vert b/src/main/resources/assets/notenoughupdates/shaders/make_gold.vert
new file mode 100644
index 00000000..40a9d08a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/make_gold.vert
@@ -0,0 +1,13 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passPosition;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passPosition = gl_Position.xyz;
+
+ passColour = gl_Color;
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/blur.json b/src/main/resources/assets/notenoughupdates/shaders/program/blur.json
new file mode 100644
index 00000000..9da3c2e8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/blur.json
@@ -0,0 +1,21 @@
+{
+ "blend": {
+ "func": "add",
+ "srcrgb": "srcalpha",
+ "dstrgb": "1-srcalpha"
+ },
+ "vertex": "sobel",
+ "fragment": "blur2",
+ "attributes": [ "Position" ],
+ "samplers": [
+ { "name": "DiffuseSampler" }
+ ],
+ "uniforms": [
+ { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
+ { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
+ { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
+ { "name": "BlurDir", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
+ { "name": "Radius", "type": "float", "count": 1, "values": [ 5.0 ] },
+ { "name": "AlphaMult", "type": "float", "count": 1, "values": [ 1.0 ] }
+ ]
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/blur2.fsh b/src/main/resources/assets/notenoughupdates/shaders/program/blur2.fsh
new file mode 100644
index 00000000..ca64470a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/blur2.fsh
@@ -0,0 +1,34 @@
+#version 120
+
+uniform sampler2D DiffuseSampler;
+
+varying vec2 texCoord;
+varying vec2 oneTexel;
+
+uniform vec2 InSize;
+
+uniform vec2 BlurDir;
+uniform float Radius;
+uniform float AlphaMult;
+
+void main() {
+ vec4 blurred = vec4(0.0);
+ float totalStrength = 0.0;
+ float totalAlpha = 0.0;
+ float totalSamples = 0.0;
+ for(float r = -Radius; r <= Radius; r += 1.0) {
+ vec4 sample = texture2D(DiffuseSampler, texCoord + oneTexel * r * BlurDir);
+
+ // Accumulate average alpha
+ totalAlpha = totalAlpha + sample.a;
+ totalSamples = totalSamples + 1.0;
+
+ // Accumulate smoothed blur
+ //float strength = (2.0 - abs(r / Radius))*sample.a;
+ float strength = sample.a;
+ totalStrength = totalStrength + strength;
+ blurred = blurred + sample;
+ }
+ float alpha = totalAlpha/totalSamples*AlphaMult;
+ gl_FragColor = vec4(blurred.rgb / totalStrength, alpha);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.fsh b/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.fsh
new file mode 100644
index 00000000..324602fd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.fsh
@@ -0,0 +1,11 @@
+#version 120
+
+uniform sampler2D DiffuseSampler;
+
+varying vec2 texCoord;
+
+void main(){
+ vec4 diffuseColor = texture2D(DiffuseSampler, texCoord);
+
+ gl_FragColor = vec4(diffuseColor.a);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.json b/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.json
new file mode 100644
index 00000000..653764fb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/setrgbtoalpha.json
@@ -0,0 +1,17 @@
+{
+ "blend": {
+ "func": "add",
+ "srcrgb": "srcalpha",
+ "dstrgb": "1-srcalpha"
+ },
+ "vertex": "blit",
+ "fragment": "setrgbtoalpha",
+ "attributes": [ "Position" ],
+ "samplers": [
+ { "name": "DiffuseSampler" }
+ ],
+ "uniforms": [
+ { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
+ { "name": "OutSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }
+ ]
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/sobel.vsh b/src/main/resources/assets/notenoughupdates/shaders/program/sobel.vsh
new file mode 100644
index 00000000..21b17369
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/sobel.vsh
@@ -0,0 +1,20 @@
+#version 120
+
+attribute vec4 Position;
+
+uniform mat4 ProjMat;
+uniform vec2 InSize;
+uniform vec2 OutSize;
+
+varying vec2 texCoord;
+varying vec2 oneTexel;
+
+void main(){
+ vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0);
+ gl_Position = vec4(outPos.xy, 0.2, 1.0);
+
+ oneTexel = 1.0 / InSize;
+
+ texCoord = Position.xy / OutSize;
+ texCoord.y = 1.0 - texCoord.y;
+}
diff --git a/src/main/resources/assets/notenoughupdates/ss_border.jpg b/src/main/resources/assets/notenoughupdates/ss_border.jpg
new file mode 100644
index 00000000..28c1019f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_border.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss1-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss1-0.jpg
new file mode 100644
index 00000000..d05faab2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss1-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss10-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss10-0.jpg
new file mode 100644
index 00000000..a3bbae70
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss10-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss11-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss11-0.jpg
new file mode 100644
index 00000000..071a5df1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss11-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss12-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss12-0.jpg
new file mode 100644
index 00000000..447459cc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss12-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss13-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss13-0.jpg
new file mode 100644
index 00000000..88a89ae2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss13-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss14-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss14-0.jpg
new file mode 100644
index 00000000..a83e64fa
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss14-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss15-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss15-0.jpg
new file mode 100644
index 00000000..3d34bc43
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss15-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss16-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss16-0.jpg
new file mode 100644
index 00000000..9827eec2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss16-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss17-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss17-0.jpg
new file mode 100644
index 00000000..560b1d9a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss17-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss18-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss18-0.jpg
new file mode 100644
index 00000000..6322f89d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss18-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss2-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss2-0.jpg
new file mode 100644
index 00000000..ba71a84e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss2-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss3-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss3-0.jpg
new file mode 100644
index 00000000..7b179fcc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss3-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss4-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss4-0.jpg
new file mode 100644
index 00000000..c8ee048c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss4-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss5-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss5-0.jpg
new file mode 100644
index 00000000..4435fd97
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss5-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss6-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss6-0.jpg
new file mode 100644
index 00000000..c027edbc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss6-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss7-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss7-0.jpg
new file mode 100644
index 00000000..47dffef2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss7-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss8-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss8-0.jpg
new file mode 100644
index 00000000..fe4ae1bb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss8-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/ss_small/ss9-0.jpg b/src/main/resources/assets/notenoughupdates/ss_small/ss9-0.jpg
new file mode 100644
index 00000000..d06c092a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/ss_small/ss9-0.jpg
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/wkhtmltox.zip b/src/main/resources/assets/notenoughupdates/wkhtmltox.zip
index 5717aeaf..88e17154 100644
--- a/src/main/resources/assets/notenoughupdates/wkhtmltox.zip
+++ b/src/main/resources/assets/notenoughupdates/wkhtmltox.zip
Binary files differ
diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json
index 49e37916..8f07f5cc 100644
--- a/src/main/resources/mixins.notenoughupdates.json
+++ b/src/main/resources/mixins.notenoughupdates.json
@@ -5,6 +5,7 @@
"mixins": [
"MixinItemStack",
"MixinInventoryEffectRenderer",
- "MixinGuiIngame"
+ "MixinGuiIngame",
+ "MixinRenderItem"
]
} \ No newline at end of file