aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/NotSkyblockAddonsInstallerFrame.java667
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/AccessoryBagOverlay.java824
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/BetterContainers.java454
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/BetterPortals.java206
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java605
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/CustomItems.java13
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java257
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiItemRecipe.java10
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java19
-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/MorusIntegration.java60
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java607
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java1564
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java109
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java715
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java566
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java72
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java1653
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java211
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java1042
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java873
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java493
-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.java190
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java12
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java501
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java345
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java261
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java1559
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java406
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java845
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java303
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java349
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java54
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java83
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java862
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java583
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java118
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java14
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java20
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java8
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java67
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java95
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java47
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java25
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java72
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java52
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java118
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinInventoryEffectRenderer.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java37
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java29
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java31
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java139
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java69
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java53
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java24
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java35
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java24
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/Options.java562
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java2499
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java157
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java514
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java1017
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/NEUQuesting.java67
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/questing/SBInfo.java128
-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/Constants.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/HypixelApi.java107
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java95
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java8
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java486
-rw-r--r--src/main/resources/assets/notenoughupdates/accessory_bag_overlay.pngbin0 -> 973 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/button20x.pngbin0 -> 170 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/button_white.pngbin0 -> 6570 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/contrib.png (renamed from src/main/resources/assets/notenoughupdates/contrib.png)bin189394 -> 189394 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/fade.png (renamed from src/main/resources/assets/notenoughupdates/fade.png)bin18572 -> 18572 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/gravy.png (renamed from src/main/resources/assets/notenoughupdates/gravy.png)bin58330 -> 58330 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/lava.pngbin0 -> 169280 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/lightning.pngbin0 -> 6490 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/mbstaff.pngbin0 -> 470630 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/mcworld.pngbin0 -> 291014 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/nullzee.png (renamed from src/main/resources/assets/notenoughupdates/nullzee.png)bin108263 -> 108263 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/packshq.pngbin0 -> 22716 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/patreon1.pngbin0 -> 46767 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/patreon2.pngbin0 -> 45479 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/space.pngbin0 -> 866931 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/testcape.png (renamed from src/main/resources/assets/notenoughupdates/testcape.png)bin21571 -> 21571 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/colour_selector_bar.pngbin0 -> 245 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/colour_selector_bar_alpha.pngbin0 -> 240 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/colour_selector_chroma.pngbin0 -> 211 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/colour_selector_dot.pngbin0 -> 3677 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/cosmetics_fg.pngbin0 -> 1607 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/custom_ench_colour.pngbin0 -> 4530 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/custom_trade.pngbin0 -> 10346 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_chest_worth.pngbin1804 -> 1900 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/1.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.pngbin0 -> 7050 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.pngbin0 -> 16913 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.pngbin0 -> 1006 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.pngbin0 -> 6971 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.pngbin0 -> 10886 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.pngbin0 -> 13433 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.pngbin0 -> 10655 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.pngbin0 -> 4217 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.pngbin0 -> 6904 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.pngbin0 -> 6779 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/map_border_dragon_stone.pngbin0 -> 4952 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/1.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.pngbin0 -> 6703 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.pngbin0 -> 15370 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.pngbin0 -> 717 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.pngbin0 -> 6522 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.pngbin0 -> 7093 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.pngbin0 -> 7618 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.pngbin0 -> 7874 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.pngbin0 -> 4400 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.pngbin0 -> 6277 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.pngbin0 -> 6362 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/1.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.pngbin0 -> 7045 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.pngbin0 -> 12576 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.pngbin0 -> 1949 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.pngbin0 -> 6697 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.pngbin0 -> 5947 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.pngbin0 -> 8456 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.pngbin0 -> 6474 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.pngbin0 -> 4502 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.pngbin0 -> 6789 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.pngbin0 -> 5897 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/borders/steampunk.pngbin0 -> 10039 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corners_default/brown_corner.pngbin0 -> 971 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/brown_corridor.pngbin0 -> 1023 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/gray_corridor.pngbin0 -> 1055 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/green_corridor.pngbin0 -> 1107 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/orange_corridor.pngbin0 -> 1083 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/pink_corridor.pngbin0 -> 1032 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/purple_corridor.pngbin0 -> 1044 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/red_corridor.pngbin0 -> 1055 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/yellow_corridor.pngbin0 -> 1033 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/cross.pngbin0 -> 250 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/dividers_default/brown_divider.pngbin0 -> 964 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/editor/background.pngbin0 -> 2414 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/green_check.pngbin0 -> 166 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/question.pngbin0 -> 168 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/brown_room.pngbin0 -> 178 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/gray_room.pngbin0 -> 175 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/green_room.pngbin0 -> 177 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/orange_room.pngbin0 -> 979 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/pink_room.pngbin0 -> 176 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/purple_room.pngbin0 -> 176 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/red_room.pngbin0 -> 174 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/yellow_room.pngbin0 -> 177 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_map/white_check.pngbin0 -> 189 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/a.pngbin0 -> 569 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/b.pngbin0 -> 261 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/c.pngbin0 -> 330 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/confetti.pngbin0 -> 532 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/d.pngbin0 -> 277 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/s.pngbin0 -> 579 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dungeon_win/splus.pngbin0 -> 2296 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54.pngbin0 -> 4299 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_button_ctm.pngbin0 -> 4312 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_slot_ctm.pngbin0 -> 4721 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_config.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54.pngbin0 -> 4424 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_button_ctm.pngbin0 -> 4723 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_slot_ctm.pngbin0 -> 4721 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_config.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54.pngbin0 -> 2555 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_button_ctm.pngbin0 -> 4602 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_slot_ctm.pngbin0 -> 4602 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_config.json3
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54.pngbin0 -> 5234 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_button_ctm.pngbin0 -> 607 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_slot_ctm.pngbin0 -> 539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54.pngbin0 -> 5429 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_button_ctm.pngbin0 -> 543 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_slot_ctm.pngbin0 -> 539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54.pngbin0 -> 5519 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_button_ctm.pngbin0 -> 539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_slot_ctm.pngbin0 -> 539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54.pngbin0 -> 5234 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_button_ctm.pngbin0 -> 3437 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_slot_ctm.pngbin0 -> 539 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/toggle_off.pngbin0 -> 389 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/dynamic_54/toggle_on.pngbin0 -> 406 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/folder.pngbin0 -> 454 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/gamemodes.pngbin0 -> 663 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/item_haschild.pngbin0 -> 263 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.pngbin7532 -> 368 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/maps/F1Full.json16386
-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/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 -> 4636 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/quickcommand_background.pngbin0 -> 429 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/radial_circle_off.pngbin0 -> 322 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/radial_circle_on.pngbin0 -> 377 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/radial_square_off.pngbin0 -> 257 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/radial_square_on.pngbin0 -> 304 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/setting_border.pngbin0 -> 411 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/lava_cape.frag32
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/lava_cape.vert12
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/lightning_cape.frag13
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/lightning_cape.vert12
-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/mcworld_cape.frag129
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert12
-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/dungeonmap.fsh32
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.json19
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.vsh16
-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/shaders/space_cape.frag60
-rw-r--r--src/main/resources/assets/notenoughupdates/shaders/space_cape.vert12
-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/supersecretassets/bald.pngbin0 -> 19909 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/wkhtmltox.zipbin31902481 -> 16009138 bytes
-rw-r--r--src/main/resources/mixins.notenoughupdates.json14
420 files changed, 38465 insertions, 3154 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/AccessoryBagOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/AccessoryBagOverlay.java
new file mode 100644
index 00000000..5ca25082
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/AccessoryBagOverlay.java
@@ -0,0 +1,824 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.EnumChatFormatting;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static io.github.moulberry.notenoughupdates.GuiTextures.*;
+
+public class AccessoryBagOverlay {
+
+ private static final int TAB_BASIC = 0;
+ private static final int TAB_TOTAL = 1;
+ private static final int TAB_BONUS = 2;
+ private static final int TAB_DUP = 3;
+ private static final int TAB_MISSING = 4;
+ private static final int TAB_OPTIMIZER = 5;
+
+ private static final ItemStack[] TAB_STACKS = new ItemStack[] {
+ Utils.createItemStack(Items.dye, EnumChatFormatting.DARK_AQUA+"Basic Information",
+ 10, EnumChatFormatting.GREEN+"- Talis count by rarity"),
+ Utils.createItemStack(Items.diamond_sword, EnumChatFormatting.DARK_AQUA+"Total Stat Bonuses",
+ 0),
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.anvil), EnumChatFormatting.DARK_AQUA+"Total Stat Bonuses (from reforges)",
+ 0),
+ Utils.createItemStack(Items.dye, EnumChatFormatting.DARK_AQUA+"Duplicates",
+ 8),
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.barrier), EnumChatFormatting.DARK_AQUA+"Missing",
+ 0),
+ Utils.createItemStack(Item.getItemFromBlock(Blocks.redstone_block), EnumChatFormatting.DARK_AQUA+"Optimizer",
+ 0),
+ };
+
+ private static int currentTab = TAB_BASIC;
+
+ public static boolean mouseClick() {
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if(!containerName.trim().startsWith("Accessory Bag")) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+
+ if(!Mouse.getEventButtonState()) return false;
+ try {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ int mouseX = Mouse.getX() / scaledResolution.getScaleFactor();
+ int mouseY = height - Mouse.getY() / scaledResolution.getScaleFactor();
+
+ int xSize = (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "xSize", "field_146999_f");
+ int ySize = (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "ySize", "field_147000_g");
+ int guiLeft = (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiLeft", "field_147003_i");
+ int guiTop = (int) Utils.getField(GuiContainer.class, Minecraft.getMinecraft().currentScreen, "guiTop", "field_147009_r");
+
+ if(mouseX < guiLeft+xSize+3 || mouseX > guiLeft+xSize+80+28) return false;
+ if(mouseY < guiTop || mouseY > guiTop+166) return false;
+
+ if(mouseX > guiLeft+xSize+83 && mouseY < guiTop+20*TAB_MISSING+22) {
+ currentTab = (mouseY - guiTop)/20;
+ if(currentTab < 0) currentTab = 0;
+ if(currentTab > TAB_MISSING) currentTab = TAB_MISSING;
+ }
+
+ if(currentTab == TAB_OPTIMIZER) {
+ int x = guiLeft+xSize+3;
+ int y = guiTop;
+
+ if(mouseY > y+92 && mouseY < y+103) {
+ if(mouseX > x+5 && mouseX < x+75) {
+ mainWeapon = (int)Math.floor((mouseX-x-5)/70f*9);
+ if(mainWeapon < 1) {
+ mainWeapon = 1;
+ } else if(mainWeapon > 9) {
+ mainWeapon = 9;
+ }
+ }
+ }
+
+ if(mouseX > x+5 && mouseX < x+35 || mouseX > x+45 && mouseX < x+75) {
+ boolean set = mouseX > x+5 && mouseX < x+35;
+
+ if(mouseY > y+32 && mouseY < y+43) {
+ forceCC = set;
+ } else if(mouseY > y+52 && mouseY < y+63) {
+ forceAS = set;
+ } else if(mouseY > y+72 && mouseY < y+83) {
+ useGodPot = set;
+ } else if(mouseY > y+92 && mouseY < y+103) {
+ allowShaded = set;
+ }
+ }
+ }
+
+ return true;
+ } catch(Exception e) {
+ return false;
+ }
+ }
+
+ public static void resetCache() {
+ accessoryStacks = new HashSet<>();
+ pagesVisited = new HashSet<>();
+ talismanCountRarity = null;
+ totalStats = null;
+ reforgeStats = null;
+ duplicates = null;
+ missing = null;
+ }
+
+ private static Set<ItemStack> accessoryStacks = new HashSet<>();
+ private static Set<Integer> pagesVisited = new HashSet<>();
+
+ public static void renderVisitOverlay(int x, int y) {
+ Utils.drawStringCenteredScaledMaxWidth("Please visit all", Minecraft.getMinecraft().fontRendererObj, x+40, y+78, true, 70, -1);
+ Utils.drawStringCenteredScaledMaxWidth("pages of the bag", Minecraft.getMinecraft().fontRendererObj, x+40, y+86, true, 70, -1);
+ }
+
+ private static TreeMap<Integer, Integer> talismanCountRarity = null;
+ public static void renderBasicOverlay(int x, int y) {
+ if(talismanCountRarity == null) {
+ talismanCountRarity = new TreeMap<>();
+ for(ItemStack stack : accessoryStacks) {
+ int rarity = getRarity(stack);
+ if(rarity >= 0) {
+ talismanCountRarity.put(rarity, talismanCountRarity.getOrDefault(rarity, 0)+1);
+ }
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth("# By Rarity", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+
+ int yIndex = 0;
+ for(Map.Entry<Integer, Integer> entry : talismanCountRarity.descendingMap().entrySet()) {
+ String rarityName = rarityArrC[entry.getKey()];
+ renderAlignedString(rarityName, EnumChatFormatting.WHITE.toString()+entry.getValue(), x+5, y+20+11*yIndex, 70);
+ yIndex++;
+ }
+ }
+
+
+ private static PlayerStats.Stats totalStats = null;
+ public static void renderTotalStatsOverlay(int x, int y) {
+ if(totalStats == null) {
+ totalStats = new PlayerStats.Stats();
+ for(ItemStack stack : accessoryStacks) {
+ if(stack != null) totalStats.add(getStatForItem(stack, STAT_PATTERN_MAP, true));
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth("Total Stats", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ int yIndex = 0;
+ for(int i=0; i<PlayerStats.defaultStatNames.length; i++) {
+ String statName = PlayerStats.defaultStatNames[i];
+ String statNamePretty = PlayerStats.defaultStatNamesPretty[i];
+
+ int val = Math.round(totalStats.get(statName));
+
+ if(Math.abs(val) < 1E-5) continue;
+
+ 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, x+5, y+20+11*yIndex, 70);
+
+ yIndex++;
+ }
+ }
+
+ private static PlayerStats.Stats reforgeStats = null;
+ public static void renderReforgeStatsOverlay(int x, int y) {
+ if(reforgeStats == null) {
+ reforgeStats = new PlayerStats.Stats();
+ for(ItemStack stack : accessoryStacks) {
+ if(stack != null) reforgeStats.add(getStatForItem(stack, STAT_PATTERN_MAP_BONUS, false));
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth("Reforge Stats", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ int yIndex = 0;
+ for(int i=0; i<PlayerStats.defaultStatNames.length; i++) {
+ String statName = PlayerStats.defaultStatNames[i];
+ String statNamePretty = PlayerStats.defaultStatNamesPretty[i];
+
+ int val = Math.round(reforgeStats.get(statName));
+
+ if(Math.abs(val) < 1E-5) continue;
+
+ 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, x+5, y+20+11*yIndex, 70);
+
+ yIndex++;
+ }
+ }
+
+ private static Set<ItemStack> duplicates = null;
+ public static void renderDuplicatesOverlay(int x, int y) {
+ if(duplicates == null) {
+ JsonObject misc = Constants.MISC;
+ if(misc == null) {
+ Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ return;
+ }
+ JsonElement talisman_upgrades_element = misc.get("talisman_upgrades");
+ if(talisman_upgrades_element == null) {
+ Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ return;
+ }
+ JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject();
+
+ duplicates = new HashSet<>();
+
+ Set<String> prevInternalnames = new HashSet<>();
+ for(ItemStack stack : accessoryStacks) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+
+ if(prevInternalnames.contains(internalname)) {
+ duplicates.add(stack);
+ continue;
+ }
+ prevInternalnames.add(internalname);
+
+ if(talisman_upgrades.has(internalname)) {
+ JsonArray upgrades = talisman_upgrades.get(internalname).getAsJsonArray();
+ for(ItemStack stack2 : accessoryStacks) {
+ if(stack != stack2) {
+ String internalname2 = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack2);
+ for(int j=0; j<upgrades.size(); j++) {
+ String upgrade = upgrades.get(j).getAsString();
+ if(internalname2.equals(upgrade)) {
+ duplicates.add(stack);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ if(duplicates.isEmpty()) {
+ Utils.drawStringCenteredScaledMaxWidth("No Duplicates", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ } else {
+ Utils.drawStringCenteredScaledMaxWidth("Duplicates: " + duplicates.size(), Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+
+ int yIndex = 0;
+ for(ItemStack duplicate : duplicates) {
+ renderAlignedString(duplicate.getDisplayName(), "", x+5, y+20+11*yIndex, 70);
+ if(duplicates.size() > 11) {
+ if(++yIndex >= 10) break;
+ } else {
+ if(++yIndex >= 11) break;
+ }
+ }
+
+ if(duplicates.size() > 11) {
+ Utils.drawStringCenteredScaledMaxWidth("+" + (duplicates.size()-10) + " More",
+ Minecraft.getMinecraft().fontRendererObj, x+40, y+16+121, false, 70,
+ new Color(80, 80, 80).getRGB());
+ }
+ }
+ }
+
+ private static List<ItemStack> missing = null;
+ public static void renderMissingOverlay(int x, int y) {
+ if(missing == null) {
+ JsonObject misc = Constants.MISC;
+ if(misc == null) {
+ Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ return;
+ }
+ JsonElement talisman_upgrades_element = misc.get("talisman_upgrades");
+ if(talisman_upgrades_element == null) {
+ Utils.drawStringCenteredScaledMaxWidth("Duplicates: ERROR", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ return;
+ }
+ JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject();
+
+ missing = new ArrayList<>();
+
+ List<String> missingInternal = new ArrayList<>();
+ for(Map.Entry<String, JsonObject> entry : NotEnoughUpdates.INSTANCE.manager.getItemInformation().entrySet()) {
+ if(entry.getValue().has("lore")) {
+ if(checkItemType(entry.getValue().get("lore").getAsJsonArray(), "ACCESSORY", "HATCCESSORY") >= 0) {
+ missingInternal.add(entry.getKey());
+ }
+ }
+ }
+
+ for(ItemStack stack : accessoryStacks) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ missingInternal.remove(internalname);
+
+ for(Map.Entry<String, JsonElement> talisman_upgrade_element : talisman_upgrades.entrySet()) {
+ JsonArray upgrades = talisman_upgrade_element.getValue().getAsJsonArray();
+ for(int j=0; j<upgrades.size(); j++) {
+ String upgrade = upgrades.get(j).getAsString();
+ if(internalname.equals(upgrade)) {
+ missingInternal.remove(talisman_upgrade_element.getKey());
+ break;
+ }
+ }
+ }
+ }
+
+ missingInternal.sort(getItemComparator());
+
+ for(String internal : missingInternal) {
+ missing.add(NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager.getItemInformation().get(internal)));
+ }
+ }
+ if(missing.isEmpty()) {
+ Utils.drawStringCenteredScaledMaxWidth("No Missing", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+ } else {
+ Utils.drawStringCenteredScaledMaxWidth("Missing: " + missing.size(), Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+
+ int yIndex = 0;
+ for(ItemStack missingStack : missing) {
+ renderAlignedString(missingStack.getDisplayName(), "", x+5, y+20+11*yIndex, 70);
+ if(missing.size() > 11) {
+ if(++yIndex >= 10) break;
+ } else {
+ if(++yIndex >= 11) break;
+ }
+ }
+
+ if(missing.size() > 11) {
+ Utils.drawStringCenteredScaledMaxWidth("+" + (missing.size()-10) + " More",
+ Minecraft.getMinecraft().fontRendererObj, x+40, y+16+121, false, 70,
+ new Color(80, 80, 80).getRGB());
+ }
+ }
+ }
+
+ private static boolean forceCC = false;
+ private static boolean forceAS = false;
+ private static boolean useGodPot = true;
+ private static boolean allowShaded = true;
+ private static int mainWeapon = 1;
+
+ public static void renderOptimizerOverlay(int x, int y) {
+ Utils.drawStringCenteredScaledMaxWidth("Optimizer", Minecraft.getMinecraft().fontRendererObj, x+40, y+12, false, 70,
+ new Color(80, 80, 80).getRGB());
+
+ int light = new Color(220, 220, 220).getRGB();
+ int dark = new Color(170, 170, 170).getRGB();
+
+ Gui.drawRect(x+5, y+32, x+35, y+43, forceCC?dark:light);
+ Gui.drawRect(x+45, y+32, x+75, y+43, forceCC?light:dark);
+
+ Gui.drawRect(x+5, y+52, x+35, y+63, forceAS?dark:light);
+ Gui.drawRect(x+45, y+52, x+75, y+63, forceAS?light:dark);
+
+ Gui.drawRect(x+5, y+72, x+35, y+83, useGodPot?dark:light);
+ Gui.drawRect(x+45, y+72, x+75, y+83, useGodPot?light:dark);
+
+ Gui.drawRect(x+5, y+92, x+35, y+103, allowShaded?dark:light);
+ Gui.drawRect(x+45, y+92, x+75, y+103, allowShaded?light:dark);
+
+ Gui.drawRect(x+5, y+102, x+75, y+113, light);
+ Gui.drawRect(x+5+(int)((mainWeapon-1)/9f*70), y+102, x+5+(int)(mainWeapon/9f*70), y+113, dark);
+
+ Utils.drawStringCenteredScaledMaxWidth("Force 100% CC", Minecraft.getMinecraft().fontRendererObj, x+40, y+27, false, 70,
+ new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((forceCC?EnumChatFormatting.GREEN:EnumChatFormatting.GRAY)+"YES",
+ Minecraft.getMinecraft().fontRendererObj, x+20, y+37,
+ true, 30, new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((forceCC?EnumChatFormatting.GRAY:EnumChatFormatting.RED)+"NO", Minecraft.getMinecraft().fontRendererObj, x+60, y+37,
+ true, 30, new Color(80, 80, 80).getRGB());
+
+ Utils.drawStringCenteredScaledMaxWidth("Force 100% ATKSPEED", Minecraft.getMinecraft().fontRendererObj, x+40, y+47, false, 70,
+ new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((forceAS?EnumChatFormatting.GREEN:EnumChatFormatting.GRAY)+"YES", Minecraft.getMinecraft().fontRendererObj, x+20, y+57,
+ true, 30, new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((forceAS?EnumChatFormatting.GRAY:EnumChatFormatting.RED)+"NO", Minecraft.getMinecraft().fontRendererObj, x+60, y+57,
+ true, 30, new Color(80, 80, 80).getRGB());
+
+ Utils.drawStringCenteredScaledMaxWidth("Use God Potion", Minecraft.getMinecraft().fontRendererObj, x+40, y+67, false, 70,
+ new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((useGodPot?EnumChatFormatting.GREEN:EnumChatFormatting.GRAY)+"YES", Minecraft.getMinecraft().fontRendererObj, x+20, y+77,
+ true, 30, new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((useGodPot?EnumChatFormatting.GRAY:EnumChatFormatting.RED)+"NO", Minecraft.getMinecraft().fontRendererObj, x+60, y+77,
+ true, 30, new Color(80, 80, 80).getRGB());
+
+ Utils.drawStringCenteredScaledMaxWidth("Use God Potion", Minecraft.getMinecraft().fontRendererObj, x+40, y+87, false, 70,
+ new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((allowShaded?EnumChatFormatting.GREEN:EnumChatFormatting.GRAY)+"YES",
+ Minecraft.getMinecraft().fontRendererObj, x+20, y+97,
+ true, 30, new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaledMaxWidth((allowShaded?EnumChatFormatting.GRAY:EnumChatFormatting.RED)+"NO",
+ Minecraft.getMinecraft().fontRendererObj, x+60, y+97,
+ true, 30, new Color(80, 80, 80).getRGB());
+
+ Utils.drawStringCenteredScaledMaxWidth("Main Weapon", Minecraft.getMinecraft().fontRendererObj, x+40, y+107, false, 70,
+ new Color(80, 80, 80).getRGB());
+ Utils.drawStringCenteredScaled("1 2 3 4 5 6 7 8 9",
+ Minecraft.getMinecraft().fontRendererObj, x+40, y+117,
+ true, 70, new Color(80, 80, 80).getRGB());
+ }
+
+ private static Comparator<String> getItemComparator() {
+ return (o1, o2) -> {
+ float cost1;
+ JsonObject o1Auc = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(o1);
+ if(o1Auc != null && o1Auc.has("price")) {
+ cost1 = o1Auc.get("price").getAsFloat();
+ } else {
+ cost1 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(o1).craftCost;
+ }
+ float cost2;
+ JsonObject o2Auc = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(o2);
+ if(o2Auc != null && o2Auc.has("price")) {
+ cost2 = o2Auc.get("price").getAsFloat();
+ } else {
+ cost2 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(o2).craftCost;
+ }
+
+
+ if(cost1 < cost2) return -1;
+ if(cost1 > cost2) return 1;
+
+ return o1.compareTo(o2);
+ };
+ }
+
+ public static void renderOverlay() {
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if(containerName.trim().startsWith("Accessory Bag")) {
+ try {
+ int xSize = (int) Utils.getField(GuiContainer.class, eventGui, "xSize", "field_146999_f");
+ int ySize = (int) Utils.getField(GuiContainer.class, eventGui, "ySize", "field_147000_g");
+ int guiLeft = (int) Utils.getField(GuiContainer.class, eventGui, "guiLeft", "field_147003_i");
+ int guiTop = (int) Utils.getField(GuiContainer.class, eventGui, "guiTop", "field_147009_r");
+
+ if(accessoryStacks.isEmpty()) {
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ if(stack != null && isAccessory(stack)) {
+ accessoryStacks.add(stack);
+ }
+ }
+ }
+
+ if(containerName.trim().contains("(")) {
+ String first = containerName.trim().split("\\(")[1].split("/")[0];
+ Integer currentPageNumber = Integer.parseInt(first);
+ //System.out.println("current:"+currentPageNumber);
+ if(!pagesVisited.contains(currentPageNumber)) {
+ boolean hasStack = false;
+ if(Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
+ IInventory inv = ((ContainerChest)Minecraft.getMinecraft().thePlayer.openContainer).getLowerChestInventory();
+ for(int i=0; i<inv.getSizeInventory(); i++) {
+ ItemStack stack = inv.getStackInSlot(i);
+ if(stack != null) {
+ hasStack = true;
+ if(isAccessory(stack)) {
+ accessoryStacks.add(stack);
+ }
+ }
+ }
+ }
+
+ if(hasStack) pagesVisited.add(currentPageNumber);
+ }
+
+ String second = containerName.trim().split("/")[1].split("\\)")[0];
+ //System.out.println(second + ":" + pagesVisited.size());
+ if(Integer.parseInt(second) > pagesVisited.size()) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop, 80, 149, 0, 80/256f, 0, 149/256f, GL11.GL_NEAREST);
+
+ renderVisitOverlay(guiLeft+xSize+3, guiTop);
+ return;
+ }
+ } else if(pagesVisited.isEmpty()) {
+ boolean hasStack = false;
+ if(Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) {
+ IInventory inv = ((ContainerChest)Minecraft.getMinecraft().thePlayer.openContainer).getLowerChestInventory();
+ for(int i=0; i<inv.getSizeInventory(); i++) {
+ ItemStack stack = inv.getStackInSlot(i);
+ if(stack != null) {
+ hasStack = true;
+ if(isAccessory(stack)) {
+ accessoryStacks.add(stack);
+ }
+ }
+ }
+ }
+
+ if(hasStack) pagesVisited.add(1);
+ }
+
+ for(int i=0; i<=TAB_MISSING; i++) {
+ if(i != currentTab) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay);
+ Utils.drawTexturedRect(guiLeft+xSize+80, guiTop+20*i, 25, 22,
+ 80/256f, 105/256f, 0, 22/256f, GL11.GL_NEAREST);
+ Utils.drawItemStack(TAB_STACKS[i], guiLeft+xSize+80+5, guiTop+20*i+3);
+ }
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop, 80, 149, 0, 80/256f, 0, 149/256f, GL11.GL_NEAREST);
+
+ if(pagesVisited.size() < 1) {
+ renderVisitOverlay(guiLeft+xSize+3, guiTop);
+ return;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay);
+ Utils.drawTexturedRect(guiLeft+xSize+80, guiTop+20*currentTab, 28, 22,
+ 80/256f, 108/256f, 22/256f, 44/256f, GL11.GL_NEAREST);
+ Utils.drawItemStack(TAB_STACKS[currentTab], guiLeft+xSize+80+8, guiTop+20*currentTab+3);
+
+ switch (currentTab) {
+ case TAB_BASIC:
+ renderBasicOverlay(guiLeft+xSize+3, guiTop); return;
+ case TAB_TOTAL:
+ renderTotalStatsOverlay(guiLeft+xSize+3, guiTop); return;
+ case TAB_BONUS:
+ renderReforgeStatsOverlay(guiLeft+xSize+3, guiTop); return;
+ case TAB_DUP:
+ renderDuplicatesOverlay(guiLeft+xSize+3, guiTop); return;
+ case TAB_MISSING:
+ renderMissingOverlay(guiLeft+xSize+3, guiTop); return;
+ case TAB_OPTIMIZER:
+ renderOptimizerOverlay(guiLeft+xSize+3, guiTop); return;
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static void renderAlignedString(String first, String second, float x, float y, int length) {
+ FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
+
+ 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 static final Pattern HEALTH_PATTERN_BONUS = Pattern.compile("^Health: (?:\\+|-)[0-9]+ HP \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern DEFENCE_PATTERN_BONUS = Pattern.compile("^Defense: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern STRENGTH_PATTERN_BONUS = Pattern.compile("^Strength: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern SPEED_PATTERN_BONUS = Pattern.compile("^Speed: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern CC_PATTERN_BONUS = Pattern.compile("^Crit Chance: (?:\\+|-)[0-9]+% \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern CD_PATTERN_BONUS = Pattern.compile("^Crit Damage: (?:\\+|-)[0-9]+% \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern ATKSPEED_PATTERN_BONUS = Pattern.compile("^Bonus Attack Speed: (?:\\+|-)[0-9]+% \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern INTELLIGENCE_PATTERN_BONUS = Pattern.compile("^Intelligence: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final Pattern SCC_PATTERN_BONUS = Pattern.compile("^Sea Creature Chance: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
+ private static final HashMap<String, Pattern> STAT_PATTERN_MAP_BONUS = new HashMap<>();
+ static {
+ STAT_PATTERN_MAP_BONUS.put("health", HEALTH_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("defence", DEFENCE_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("strength", STRENGTH_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("speed", SPEED_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("crit_chance", CC_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("crit_damage", CD_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("bonus_attack_speed", ATKSPEED_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("intelligence", INTELLIGENCE_PATTERN_BONUS);
+ STAT_PATTERN_MAP_BONUS.put("sea_creature_chance", SCC_PATTERN_BONUS);
+ }
+
+ 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 PlayerStats.Stats getStatForItem(ItemStack stack, HashMap<String, Pattern> patternMap, boolean addExtras) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ NBTTagCompound tag = stack.getTagCompound();
+ PlayerStats.Stats stats = new PlayerStats.Stats();
+
+ if(internalname == null) {
+ return stats;
+ }
+
+ if(tag != null) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ for (int i = 0; i < list.tagCount(); i++) {
+ String line = list.getStringTagAt(i);
+ for(Map.Entry<String, Pattern> entry : patternMap.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(!addExtras) return stats;
+
+ if(internalname.equals("DAY_CRYSTAL") || internalname.equals("NIGHT_CRYSTAL")) {
+ stats.addStat(PlayerStats.STRENGTH, 2.5f);
+ stats.addStat(PlayerStats.DEFENCE, 2.5f);
+ }
+
+ if(internalname.equals("NEW_YEAR_CAKE_BAG") && 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);
+ 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 ea2 = nbt.getCompoundTag("ExtraAttributes");
+ if (ea2.hasKey("new_years_cake")) {
+ cakes.add(ea2.getInteger("new_years_cake"));
+ }
+ }
+ }
+ }
+ stats.addStat(PlayerStats.HEALTH, cakes.size());
+ } catch(IOException e) {
+ e.printStackTrace();
+ return stats;
+ }
+ break;
+ }
+ }
+ }
+ return stats;
+ }
+
+ private static String[] rarityArr = new String[] {
+ "COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL",
+ };
+ private static String[] rarityArrC = new String[] {
+ EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()+"COMMON",
+ EnumChatFormatting.GREEN+EnumChatFormatting.BOLD.toString()+"UNCOMMON",
+ EnumChatFormatting.BLUE+EnumChatFormatting.BOLD.toString()+"RARE",
+ EnumChatFormatting.DARK_PURPLE+EnumChatFormatting.BOLD.toString()+"EPIC",
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()+"LEGENDARY",
+ EnumChatFormatting.LIGHT_PURPLE+EnumChatFormatting.BOLD.toString()+"MYTHIC",
+ EnumChatFormatting.RED+EnumChatFormatting.BOLD.toString()+"SPECIAL",
+ EnumChatFormatting.RED+EnumChatFormatting.BOLD.toString()+"VERY SPECIAL",
+ EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD.toString()+"SUPREME",
+ };
+ public static int checkItemType(ItemStack stack, boolean contains, String... typeMatches) {
+ NBTTagCompound tag = stack.getTagCompound();
+ if(tag != null) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ for (int i = list.tagCount()-1; i >= 0; i--) {
+ String line = list.getStringTagAt(i);
+ 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;
+ }
+ private static int checkItemType(JsonArray lore, 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(line.trim().endsWith(rarity + " " + typeMatches[j])) {
+ return j;
+ }
+ }
+ }
+ }
+ return -1;
+ }
+
+ public static boolean isAccessory(ItemStack stack) {
+ return checkItemType(stack, true, "ACCESSORY", "HATCCESSORY") >= 0;
+ }
+
+ public static int getRarity(ItemStack stack) {
+ NBTTagCompound tag = stack.getTagCompound();
+ if(tag != null) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ for (int i = list.tagCount(); i >= 0; i--) {
+ String line = list.getStringTagAt(i);
+ for(int j=0; j<rarityArrC.length; j++) {
+ if(line.contains(rarityArrC[j])) {
+ return j;
+ }
+ }
+ }
+ }
+ }
+ return -1;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/BetterContainers.java b/src/main/java/io/github/moulberry/notenoughupdates/BetterContainers.java
new file mode 100644
index 00000000..fac3a8d1
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/BetterContainers.java
@@ -0,0 +1,454 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.init.Blocks;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Random;
+
+public class BetterContainers {
+
+ private static final ResourceLocation TOGGLE_OFF = new ResourceLocation("notenoughupdates:dynamic_54/toggle_off.png");
+ private static final ResourceLocation TOGGLE_ON = new ResourceLocation("notenoughupdates:dynamic_54/toggle_on.png");
+
+ private static final ResourceLocation DYNAMIC_54_BASE = new ResourceLocation("notenoughupdates:dynamic_54/style1/dynamic_54.png");
+ private static final ResourceLocation DYNAMIC_54_SLOT = new ResourceLocation("notenoughupdates:dynamic_54/style1/dynamic_54_slot_ctm.png");
+ private static final ResourceLocation DYNAMIC_54_BUTTON = new ResourceLocation("notenoughupdates:dynamic_54/style1/dynamic_54_button_ctm.png");
+ private static final ResourceLocation rl = new ResourceLocation("notenoughupdates:dynamic_chest_inventory.png");
+ private static boolean loaded = false;
+ private static DynamicTexture texture = null;
+ private static int textColour = 4210752;
+
+ private static int lastClickedSlot = 0;
+ private static int clickedSlot = 0;
+ private static long clickedSlotMillis = 0;
+ public static long lastRenderMillis = 0;
+
+ public static HashMap<Integer, ItemStack> itemCache = new HashMap<>();
+ public static boolean lastUsingCached = false;
+ public static boolean usingCached = false;
+
+ public static void clickSlot(int slot) {
+ clickedSlotMillis = System.currentTimeMillis();
+ clickedSlot = slot;
+ }
+
+ public static int getClickedSlot() {
+ if(System.currentTimeMillis() - clickedSlotMillis < 500) {
+ return clickedSlot;
+ }
+ return -1;
+ }
+
+ public static void bindHook(TextureManager textureManager, ResourceLocation location) {
+ if(isChestOpen()) {
+ Container container = ((GuiChest)Minecraft.getMinecraft().currentScreen).inventorySlots;
+ if(container instanceof ContainerChest) {
+ usingCached = true;
+ IInventory lower = ((ContainerChest)container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ for(int index=0; index<size; index++) {
+ if(lower.getStackInSlot(index) != null) {
+ for(int index2=0; index2<size; index2++) {
+ itemCache.put(index2, lower.getStackInSlot(index2));
+ }
+ usingCached = false;
+ break;
+ }
+ }
+ }
+
+ if((texture != null && loaded && lastClickedSlot != getClickedSlot()) ||
+ lastUsingCached != getUsingCache() ||
+ (texture == null && !loaded)) {
+ lastUsingCached = getUsingCache();
+ lastClickedSlot = getClickedSlot();
+ generateTex(location);
+ }
+ if(texture != null && loaded) {
+ if(!usingCached) lastRenderMillis = System.currentTimeMillis();
+ lastRenderMillis = System.currentTimeMillis();
+ textureManager.loadTexture(rl, texture);
+ textureManager.bindTexture(rl);
+ return;
+ }
+ }
+ textureManager.bindTexture(location);
+ }
+
+ public static boolean getUsingCache() {
+ return usingCached && System.currentTimeMillis() - lastRenderMillis < 300;
+ }
+
+ public static boolean isAh() {
+ if(!isChestOpen()) return false;
+
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ return containerName.trim().startsWith("Auctions Browser") || containerName.trim().startsWith("Wardrobe");
+ }
+
+ public static boolean isOverriding() {
+ return isChestOpen() && ((loaded && texture != null));
+ }
+
+ public static boolean isBlankStack(ItemStack stack) {
+ return stack != null && stack.getItem() == Item.getItemFromBlock(Blocks.stained_glass_pane) &&
+ stack.getDisplayName() != null && stack.getDisplayName().trim().isEmpty();
+ }
+
+ public static boolean shouldRenderStack(ItemStack stack) {
+ return !isBlankStack(stack) && !isToggleOff(stack) && !isToggleOn(stack);
+ }
+
+ public static boolean isButtonStack(ItemStack stack) {
+ return stack != null && stack.getItem() != Item.getItemFromBlock(Blocks.stained_glass_pane)
+ && NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack) == null && !isToggleOn(stack) && !isToggleOff(stack);
+ }
+
+ public static int getTextColour() {
+ return textColour;
+ }
+
+ public static boolean isToggleOn(ItemStack stack) {
+ if(stack != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("display", 10) &&
+ stack.getTagCompound().getCompoundTag("display").hasKey("Lore", 9)) {
+ NBTTagList lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+ if(lore.tagCount() == 1 && lore.getStringTagAt(0).equalsIgnoreCase(EnumChatFormatting.GRAY+"click to disable!")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean isToggleOff(ItemStack stack) {
+ if(stack != null && stack.getTagCompound() != null && stack.getTagCompound().hasKey("display", 10) &&
+ stack.getTagCompound().getCompoundTag("display").hasKey("Lore", 9)) {
+ NBTTagList lore = stack.getTagCompound().getCompoundTag("display").getTagList("Lore", 8);
+ if(lore.tagCount() == 1 && lore.getStringTagAt(0).equalsIgnoreCase(EnumChatFormatting.GRAY+"click to enable!")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static void generateTex(ResourceLocation location) {
+ if(!hasItem()) return;
+ texture = null;
+ loaded = true;
+ Container container = ((GuiChest)Minecraft.getMinecraft().currentScreen).inventorySlots;
+
+ if(hasNullPane() && container instanceof ContainerChest) {
+ int backgroundStyle = NotEnoughUpdates.INSTANCE.manager.config.dynamicMenuBackgroundStyle.value.intValue();
+ backgroundStyle = Math.max(1, Math.min(10, backgroundStyle));
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:dynamic_54/style"+ backgroundStyle+"/dynamic_config.json")).getInputStream(), StandardCharsets.UTF_8))) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class);
+ String textColourS = json.get("text-colour").getAsString();
+ textColour = (int)Long.parseLong(textColourS, 16);
+ } catch(Exception e) {
+ textColour = 4210752;
+ e.printStackTrace();
+ }
+
+ try {
+ BufferedImage bufferedImageOn = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(TOGGLE_ON).getInputStream());
+ BufferedImage bufferedImageOff = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(TOGGLE_OFF).getInputStream());
+
+ BufferedImage bufferedImageBase = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(DYNAMIC_54_BASE).getInputStream());
+ try {
+ bufferedImageBase = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:dynamic_54/style"+ backgroundStyle+"/dynamic_54.png")).getInputStream());
+ } catch(Exception e) {}
+ BufferedImage bufferedImageSlot = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(DYNAMIC_54_SLOT).getInputStream());
+ try {
+ int buttonStyle = NotEnoughUpdates.INSTANCE.manager.config.dynamicMenuButtonStyle.value.intValue();
+ buttonStyle = Math.max(1, Math.min(10, buttonStyle));
+ bufferedImageSlot = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:dynamic_54/style"+buttonStyle+"/dynamic_54_slot_ctm.png")).getInputStream());
+ } catch(Exception e) {}
+ BufferedImage bufferedImageButton = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(DYNAMIC_54_BUTTON).getInputStream());
+ try {
+ int buttonStyle = NotEnoughUpdates.INSTANCE.manager.config.dynamicMenuButtonStyle.value.intValue();
+ buttonStyle = Math.max(1, Math.min(10, buttonStyle));
+ bufferedImageButton = ImageIO.read(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:dynamic_54/style"+buttonStyle+"/dynamic_54_button_ctm.png")).getInputStream());
+ } catch(Exception e) {}
+
+ int horzTexMult = bufferedImageBase.getWidth()/256;
+ int vertTexMult = bufferedImageBase.getWidth()/256;
+ BufferedImage bufferedImageNew = new BufferedImage(
+ bufferedImageBase.getColorModel(),
+ bufferedImageBase.copyData(null),
+ bufferedImageBase.isAlphaPremultiplied(),
+ null);
+ IInventory lower = ((ContainerChest) container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ boolean[][] slots = new boolean[9][size/9];
+ boolean[][] buttons = new boolean[9][size/9];
+ for (int index = 0; index < size; index++) {
+ ItemStack stack = getStackCached(lower, index);
+ buttons[index%9][index/9] = isButtonStack(stack);
+
+ if(buttons[index%9][index/9] && lastClickedSlot == index) {
+ buttons[index%9][index/9] = false;
+ slots[index%9][index/9] = true;
+ } else {
+ slots[index%9][index/9] = !isBlankStack(stack) && !buttons[index%9][index/9];
+ }
+ }
+ for (int index = 0; index < size; index++) {
+ ItemStack stack = getStackCached(lower, index);
+ int xi = index%9;
+ int yi = index/9;
+ if(slots[xi][yi] || buttons[xi][yi]) {
+ int x = 7*horzTexMult + xi*18*horzTexMult;
+ int y = 17*vertTexMult + yi*18*vertTexMult;
+
+ boolean on = isToggleOn(stack);
+ boolean off = isToggleOff(stack);
+
+ if(on || off) {
+ for(int x2=0; x2<18; x2++) {
+ for(int y2=0; y2<18; y2++) {
+ BufferedImage toggle = on ? bufferedImageOn : bufferedImageOff;
+ Color c = new Color(toggle.getRGB(x2, y2), true);
+ if(c.getAlpha() < 10) {
+ continue;
+ }
+ bufferedImageNew.setRGB(x+x2, y+y2, c.getRGB());
+ }
+ }
+ continue;
+ }
+
+ if(buttons[xi][yi]) {
+ boolean up = yi > 0 && buttons[xi][yi-1];
+ boolean right = xi < buttons.length-1 && buttons[xi+1][yi];
+ boolean down = yi < buttons[xi].length-1 && buttons[xi][yi+1];
+ boolean left = xi > 0 && buttons[xi-1][yi];
+
+ boolean upleft = yi > 0 && xi > 0 && buttons[xi-1][yi-1];
+ boolean upright = yi > 0 && xi < buttons.length-1 && buttons[xi+1][yi-1];
+ boolean downright = xi < buttons.length-1 && yi < buttons[xi+1].length-1 && buttons[xi+1][yi+1];
+ boolean downleft = xi > 0 && yi < buttons[xi-1].length-1 && buttons[xi-1][yi+1];
+
+ int ctmIndex = getCTMIndex(up, right, down, left, upleft, upright, downright, downleft);
+ int[] rgbs = bufferedImageButton.getRGB((ctmIndex%12)*19*horzTexMult, (ctmIndex/12)*19*vertTexMult,
+ 18*horzTexMult, 18*vertTexMult, null, 0, 18*vertTexMult);
+ bufferedImageNew.setRGB(x, y, 18*horzTexMult, 18*vertTexMult, rgbs, 0, 18*vertTexMult);
+
+ } else {
+ boolean up = yi > 0 && slots[xi][yi-1];
+ boolean right = xi < slots.length-1 && slots[xi+1][yi];
+ boolean down = yi < slots[xi].length-1 && slots[xi][yi+1];
+ boolean left = xi > 0 && slots[xi-1][yi];
+
+ boolean upleft = yi > 0 && xi > 0 && slots[xi-1][yi-1];
+ boolean upright = yi > 0 && xi < slots.length-1 && slots[xi+1][yi-1];
+ boolean downright = xi < slots.length-1 && yi < slots[xi+1].length-1 && slots[xi+1][yi+1];
+ boolean downleft = xi > 0 && yi < slots[xi-1].length-1 && slots[xi-1][yi+1];
+
+ int ctmIndex = getCTMIndex(up, right, down, left, upleft, upright, downright, downleft);
+ int[] rgbs = bufferedImageSlot.getRGB((ctmIndex%12)*19*horzTexMult, (ctmIndex/12)*19*vertTexMult,
+ 18*horzTexMult, 18*vertTexMult, null, 0, 18*vertTexMult);
+ bufferedImageNew.setRGB(x, y, 18*horzTexMult, 18*vertTexMult, rgbs, 0, 18*vertTexMult);
+ }
+ }
+ }
+ texture = new DynamicTexture(bufferedImageNew);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static void reset() {
+ texture = null;
+ loaded = false;
+ clickedSlot = -1;
+ clickedSlotMillis = 0;
+ textColour = 4210752;
+ }
+
+ private static boolean isChestOpen() {
+ return Minecraft.getMinecraft().currentScreen instanceof GuiChest &&
+ NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard() &&
+ (NotEnoughUpdates.INSTANCE.manager.config.dynamicMenuBackgroundStyle.value >= 1 &&
+ NotEnoughUpdates.INSTANCE.manager.config.dynamicMenuButtonStyle.value >= 1);
+ }
+
+ private static boolean hasItem() {
+ if(!isChestOpen()) return false;
+ Container container = ((GuiChest)Minecraft.getMinecraft().currentScreen).inventorySlots;
+ if(container instanceof ContainerChest) {
+ IInventory lower = ((ContainerChest)container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ for(int index=0; index<size; index++) {
+ if(getStackCached(lower, index) != null) return true;
+ }
+ }
+ return false;
+ }
+
+ private static ItemStack getStackCached(IInventory lower, int index) {
+ if(getUsingCache()) {
+ return itemCache.get(index);
+ } else {
+ return lower.getStackInSlot(index);
+ }
+ }
+
+ private static boolean hasNullPane() {
+ if(!isChestOpen()) return false;
+ Container container = ((GuiChest)Minecraft.getMinecraft().currentScreen).inventorySlots;
+ if(container instanceof ContainerChest) {
+ IInventory lower = ((ContainerChest)container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ for(int index=0; index<size; index++) {
+ if(isBlankStack(getStackCached(lower, index))) return true;
+ }
+ }
+ return false;
+ }
+
+ private static int getCTMIndex(boolean up, boolean right, boolean down, boolean left, boolean upleft, boolean upright, boolean downright, boolean downleft) {
+ if(up && right && down && left) {
+ if(upleft && upright && downright && downleft) {
+ return 26;
+ } else if(upleft && upright && downright && !downleft) {
+ return 33;
+ } else if(upleft && upright && !downright && downleft) {
+ return 32;
+ } else if(upleft && upright && !downright && !downleft) {
+ return 11;
+ } else if(upleft && !upright && downright && downleft) {
+ return 44;
+ } else if(upleft && !upright && downright && !downleft) {
+ return 35;
+ } else if(upleft && !upright && !downright && downleft) {
+ return 10;
+ } else if(upleft && !upright && !downright && !downleft) {
+ return 20;
+ } else if(!upleft && upright && downright && downleft) {
+ return 45;
+ } else if(!upleft && upright && downright && !downleft) {
+ return 23;
+ } else if(!upleft && upright && !downright && downleft) {
+ return 34;
+ } else if(!upleft && upright && !downright && !downleft) {
+ return 8;
+ } else if(!upleft && !upright && downright && downleft) {
+ return 22;
+ } else if(!upleft && !upright && downright && !downleft) {
+ return 9;
+ } else if(!upleft && !upright && !downright && downleft) {
+ return 21;
+ } else {
+ return 46;
+ }
+ } else if(up && right && down && !left) {
+ if(!upright && !downright) {
+ return 6;
+ } else if(!upright) {
+ return 28;
+ } else if(!downright) {
+ return 30;
+ } else {
+ return 25;
+ }
+ } else if(up && right && !down && left) {
+ if(!upleft && !upright) {
+ return 18;
+ } else if(!upleft) {
+ return 40;
+ } else if(!upright) {
+ return 42;
+ } else {
+ return 38;
+ }
+ } else if(up && right && !down && !left) {
+ if(!upright) {
+ return 16;
+ } else {
+ return 37;
+ }
+ } else if(up && !right && down && left) {
+ if(!upleft && !downleft) {
+ return 19;
+ } else if(!upleft) {
+ return 43;
+ } else if(!downleft) {
+ return 41;
+ } else {
+ return 27;
+ }
+ } else if(up && !right && down && !left) {
+ return 24;
+ } else if(up && !right && !down && left) {
+ if(!upleft) {
+ return 17;
+ } else {
+ return 39;
+ }
+ } else if(up && !right && !down && !left) {
+ return 36;
+ } else if(!up && right && down && left) {
+ if(!downleft && !downright) {
+ return 7;
+ } else if(!downleft) {
+ return 31;
+ } else if(!downright) {
+ return 29;
+ } else {
+ return 14;
+ }
+ } else if(!up && right && down && !left) {
+ if(!downright) {
+ return 4;
+ } else {
+ return 13;
+ }
+ } else if(!up && right && !down && left) {
+ return 2;
+ } else if(!up && right && !down && !left) {
+ return 1;
+ } else if(!up && !right && down && left) {
+ if(!downleft) {
+ return 5;
+ } else {
+ return 15;
+ }
+ } else if(!up && !right && down && !left) {
+ return 12;
+ } else if(!up && !right && !down && left) {
+ return 3;
+ } else {
+ return 0;
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/BetterPortals.java b/src/main/java/io/github/moulberry/notenoughupdates/BetterPortals.java
new file mode 100644
index 00000000..8c512164
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/BetterPortals.java
@@ -0,0 +1,206 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.client.event.RenderWorldEvent;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.GLU;
+import org.lwjgl.util.vector.Vector3f;
+
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.*;
+
+public class BetterPortals extends Gui {
+
+ private Set<Vector3f> loadedPortals = new HashSet<>();
+ private HashMap<BlockPos, String> portalNameMap = new HashMap<>();
+
+ @SubscribeEvent
+ public void onWorldChange(WorldEvent.Load event) {
+ portalNameMap.clear();
+ loadedPortals.clear();
+ }
+
+ /** The current GL viewport */
+ private static final IntBuffer VIEWPORT = GLAllocation.createDirectIntBuffer(16);
+ /** The current GL modelview matrix */
+ private static final FloatBuffer MODELVIEW = GLAllocation.createDirectFloatBuffer(16);
+ /** The current GL projection matrix */
+ private static final FloatBuffer PROJECTION = GLAllocation.createDirectFloatBuffer(16);
+ private static final FloatBuffer WINCOORDS = GLAllocation.createDirectFloatBuffer(3);
+
+ private float getFOVModifier(float partialTicks) {
+ Entity entity = Minecraft.getMinecraft().getRenderViewEntity();
+
+ float f = Minecraft.getMinecraft().gameSettings.fovSetting;
+ //f = f * (this.fovModifierHandPrev + (this.fovModifierHand - this.fovModifierHandPrev) * partialTicks);
+
+ if (entity instanceof EntityLivingBase && ((EntityLivingBase)entity).getHealth() <= 0.0F) {
+ float f1 = (float)((EntityLivingBase)entity).deathTime + partialTicks;
+ f /= (1.0F - 500.0F / (f1 + 500.0F)) * 2.0F + 1.0F;
+ }
+
+ Block block = ActiveRenderInfo.getBlockAtEntityViewpoint(Minecraft.getMinecraft().theWorld, entity, partialTicks);
+
+ if (block.getMaterial() == Material.water) {
+ f = f * 60.0F / 70.0F;
+ }
+
+ return net.minecraftforge.client.ForgeHooksClient.getFOVModifier(Minecraft.getMinecraft().entityRenderer, entity, block, partialTicks, f);
+ }
+
+ TexLoc tl = new TexLoc(0, 1, Keyboard.KEY_M);
+
+ @SubscribeEvent
+ public void renderWorld(RenderGameOverlayEvent event) {
+
+ GlStateManager.getFloat(2982, MODELVIEW);
+ GlStateManager.getFloat(2983, PROJECTION);
+ GL11.glGetInteger(GL11.GL_VIEWPORT, VIEWPORT);
+
+ EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
+ GlStateManager.disableCull();
+
+ tl.handleKeyboardInput();
+
+ WINCOORDS.flip().limit(3);
+
+ /*float objx = -(float)(0-player.posX);
+ float objy = (float)(100-player.posY-player.eyeHeight);
+ float objz = (float)(0-player.posZ);*/
+
+ float dX = -(float)(0-player.posX);
+ float dY = (float)(100-player.posY-player.eyeHeight);
+ float dZ = (float)(0-player.posZ);
+
+ //GLU.gluProject(objx, objy, objz, MODELVIEW, PROJECTION, VIEWPORT, WINCOORDS);
+
+ double x = dX*Math.cos(Math.toRadians(player.rotationYawHead))-dZ*Math.sin(Math.toRadians(player.rotationYawHead));
+ double z = dX*Math.sin(Math.toRadians(player.rotationYawHead))+dZ*Math.cos(Math.toRadians(player.rotationYawHead));
+
+ float fov = getFOVModifier(event.partialTicks);
+ x = x / z * Math.toRadians(fov);
+ dY = (float)(dY / z * Math.toRadians(fov));
+
+ //System.out.println(z);
+
+ //GLU.gluProject((float)x, dY, (float)z, MODELVIEW, PROJECTION, VIEWPORT, WINCOORDS);
+ //x = x / z * 2;
+ //dY = (float)(dY / z * 2);
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+
+ GL11.glScissor((int)(x*Minecraft.getMinecraft().displayWidth*tl.x/tl.y)+Minecraft.getMinecraft().displayWidth/2,
+ (int)(dY+Minecraft.getMinecraft().displayHeight/2), 2, 2);
+
+ drawRect(0, 0, 2000, 2000, -1);
+
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+ /*for(BlockPos pos : portalNameMap.keySet()) {
+ WINCOORDS.flip().limit(3);
+
+ /*float objx = -(float)((pos.getX()-player.posX)*Math.cos(Math.toRadians(player.rotationYawHead))*Math.cos(Math.toRadians(player.rotationPitch)));
+ float objy = (float)((pos.getY()-player.posY)*Math.sin(Math.toRadians(player.rotationPitch)));
+ float objz = (float)((pos.getZ()-player.posZ)*Math.sin(Math.toRadians(player.rotationYawHead)));
+
+ float objx = -(float)(pos.getX()-player.posX);
+ float objy = (float)(pos.getY()-player.posY-player.eyeHeight);
+ float objz = (float)(pos.getZ()-player.posZ);
+
+ GLU.gluProject(objx, objy, objz, MODELVIEW, PROJECTION, VIEWPORT, WINCOORDS);
+ //GLU.glu
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+
+ //System.out.println(WINCOORDS.get(1));
+
+ GL11.glScissor((int)WINCOORDS.get(0)*2,
+ Minecraft.getMinecraft().displayHeight-(int)WINCOORDS.get(1), (int)50, (int)50);
+
+ //0-1
+ //-1 - 1
+ //0-1920
+
+ drawRect(0, 0, 2000, 2000, -1);
+
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }*/
+
+ GlStateManager.enableCull();
+ }
+
+ @SubscribeEvent
+ public void tick(TickEvent.ClientTickEvent event) {
+ if(Minecraft.getMinecraft().theWorld != null) {
+ List<Vector3f> travelToPositions = new ArrayList<>();
+ for(Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList) {
+ if(entity instanceof EntityArmorStand) {
+ EntityArmorStand armorStand = (EntityArmorStand) entity;
+ if(armorStand.isInvisible() && armorStand.hasCustomName()) {
+ String customName = armorStand.getCustomNameTag();
+ if(customName.equals(EnumChatFormatting.AQUA+"Travel to:")) {
+ travelToPositions.add(new Vector3f((float)armorStand.posX, (float)armorStand.posY, (float)armorStand.posZ));
+ }
+ }
+ }
+ }
+ travelToPositions.removeAll(loadedPortals);
+ for(Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList) {
+ if(entity instanceof EntityArmorStand) {
+ EntityArmorStand armorStand = (EntityArmorStand) entity;
+ if(armorStand.isInvisible() && armorStand.hasCustomName()) {
+ String customName = armorStand.getCustomNameTag();
+ for(Vector3f position : travelToPositions) {
+ if(position.x == (float)armorStand.posX && position.y-0.375 == (float)armorStand.posY && position.z == (float)armorStand.posZ) {
+ float smallestDist = 999;
+ BlockPos closestPortal = null;
+ for(int xOff=-3; xOff<=3; xOff++) {
+ for(int zOff=-3; zOff<=3; zOff++) {
+ if(xOff != 0 && zOff != 0) continue;
+ BlockPos pos = new BlockPos(armorStand.posX+xOff, armorStand.posY+2, armorStand.posZ+zOff);
+ if(Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock() == Blocks.portal) {
+ float dist = (float)(armorStand.posX-(pos.getX()+0.5) + armorStand.posZ-(pos.getZ()+0.5));
+ if(closestPortal == null || dist < smallestDist) {
+ smallestDist = dist;
+ closestPortal = pos;
+ }
+ }
+ }
+ }
+ if(closestPortal != null) {
+ portalNameMap.put(closestPortal, customName);
+ }
+ }
+ }
+ }
+ }
+ }
+ loadedPortals.addAll(travelToPositions);
+ }
+ }
+
+ public void tryRegisterPortal() {
+
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java
new file mode 100644
index 00000000..0fa4aa96
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/CustomItemEffects.java
@@ -0,0 +1,605 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.Block;
+import net.minecraft.block.material.Material;
+import net.minecraft.block.state.BlockState;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.block.model.BakedQuad;
+import net.minecraft.client.renderer.texture.TextureAtlasSprite;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.renderer.texture.TextureUtil;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.model.IBakedModel;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.CompressedStreamTools;
+import net.minecraft.nbt.NBTTagByteArray;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.*;
+import net.minecraftforge.client.event.DrawBlockHighlightEvent;
+import net.minecraftforge.client.event.EntityViewRenderEvent;
+import net.minecraftforge.client.event.RenderBlockOverlayEvent;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.vector.Vector3f;
+import scala.tools.cmd.Spec;
+
+import java.awt.*;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.List;
+
+public class CustomItemEffects {
+
+ public static final CustomItemEffects INSTANCE = new CustomItemEffects();
+
+ private static final int MAX_BUILDERS_BLOCKS = 164;
+
+ public long aoteUseMillis = 0;
+ public int aoteTeleportationMillis = 0;
+ public Vector3f aoteTeleportationCurr = null;
+
+ public long lastMillis = 0;
+
+ public Vector3f getCurrentPosition() {
+ if(aoteTeleportationMillis <= 0) return null;
+ return aoteTeleportationCurr;
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.RenderTickEvent event) {
+ //if(aoteTeleportationTicks > 7) aoteTeleportationTicks = 7;
+ long currentTime = System.currentTimeMillis();
+ int delta = (int)(currentTime - lastMillis);
+ lastMillis = currentTime;
+
+ if(delta <= 0) return;
+
+ if(aoteTeleportationMillis > NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value.intValue()*2) {
+ aoteTeleportationMillis = NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value.intValue()*2;
+ }
+ if(aoteTeleportationMillis < 0) aoteTeleportationMillis = 0;
+
+ if(currentTime - aoteUseMillis > 1000 && aoteTeleportationMillis <= 0) {
+ aoteTeleportationCurr = null;
+ }
+
+ if(aoteTeleportationCurr != null) {
+ if(aoteTeleportationMillis > 0) {
+ int deltaMin = Math.min(delta, aoteTeleportationMillis);
+
+ float factor = deltaMin/(float)aoteTeleportationMillis;
+
+ float dX = aoteTeleportationCurr.x - (float)Minecraft.getMinecraft().thePlayer.posX;
+ float dY = aoteTeleportationCurr.y - (float)Minecraft.getMinecraft().thePlayer.posY;
+ float dZ = aoteTeleportationCurr.z - (float)Minecraft.getMinecraft().thePlayer.posZ;
+
+ aoteTeleportationCurr.x -= dX*factor;
+ aoteTeleportationCurr.y -= dY*factor;
+ aoteTeleportationCurr.z -= dZ*factor;
+
+ if(Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(aoteTeleportationCurr.x,
+ aoteTeleportationCurr.y, aoteTeleportationCurr.z)).getBlock().getMaterial() != Material.air) {
+ aoteTeleportationCurr.y = (float)Math.ceil(aoteTeleportationCurr.y);
+ }
+
+ aoteTeleportationMillis -= deltaMin;
+ } else {
+ aoteTeleportationCurr.x = (float) Minecraft.getMinecraft().thePlayer.posX;
+ aoteTeleportationCurr.y = (float) Minecraft.getMinecraft().thePlayer.posY;
+ aoteTeleportationCurr.z = (float) Minecraft.getMinecraft().thePlayer.posZ;
+ }
+ } else {
+ aoteUseMillis = 0;
+ aoteTeleportationMillis = 0;
+ }
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value <= 0
+ || Minecraft.getMinecraft().gameSettings.thirdPersonView != 0) return;
+
+ if(event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR || event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
+ ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ if(held != null) {
+ String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+ if(internal != null && internal.equals("ASPECT_OF_THE_END")) {
+ aoteUseMillis = System.currentTimeMillis();
+ if(aoteTeleportationCurr == null) {
+ aoteTeleportationCurr = new Vector3f();
+ aoteTeleportationCurr.x = (float) Minecraft.getMinecraft().thePlayer.posX;
+ aoteTeleportationCurr.y = (float) Minecraft.getMinecraft().thePlayer.posY;
+ aoteTeleportationCurr.z = (float) Minecraft.getMinecraft().thePlayer.posZ;
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onOverlayDrawn(RenderGameOverlayEvent event) {
+ if(!NotEnoughUpdates.INSTANCE.manager.config.disableWandOverlay.value &&
+ Minecraft.getMinecraft().objectMouseOver != null &&
+ Minecraft.getMinecraft().objectMouseOver.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK &&
+ ((event.type == null && Loader.isModLoaded("labymod")) ||
+ event.type == RenderGameOverlayEvent.ElementType.CROSSHAIRS)) {
+
+ IBlockState hover = Minecraft.getMinecraft().theWorld.getBlockState(
+ Minecraft.getMinecraft().objectMouseOver.getBlockPos().offset(
+ Minecraft.getMinecraft().objectMouseOver.sideHit, 1));
+ if(hover.getBlock() == Blocks.air) {
+ ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+
+ if(heldInternal != null && heldInternal.equals("BUILDERS_WAND")) {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ HashSet<BlockPos> candidatesOld = new HashSet<>();
+ TreeMap<Float, Set<BlockPos>> candidatesOldSorted = new TreeMap<>();
+
+ IBlockState match = Minecraft.getMinecraft().theWorld.getBlockState(Minecraft.getMinecraft().objectMouseOver.getBlockPos());
+ Item matchItem = Item.getItemFromBlock(match.getBlock());
+ if(matchItem != null) {
+ ItemStack matchStack = new ItemStack(matchItem, 1,
+ match.getBlock().getDamageValue(Minecraft.getMinecraft().theWorld, Minecraft.getMinecraft().objectMouseOver.getBlockPos()));
+ int itemCount = countItemsInInventoryAndStorage(matchStack);
+
+ getBuildersWandCandidates(Minecraft.getMinecraft().thePlayer, Minecraft.getMinecraft().objectMouseOver, event.partialTicks,
+ candidatesOld, candidatesOldSorted, 999-MAX_BUILDERS_BLOCKS);
+
+ if(candidatesOld.size() > MAX_BUILDERS_BLOCKS) {
+ Utils.drawStringCentered(EnumChatFormatting.RED.toString()+candidatesOld.size()+"/"+MAX_BUILDERS_BLOCKS,
+ Minecraft.getMinecraft().fontRendererObj,
+ scaledResolution.getScaledWidth()/2f, scaledResolution.getScaledHeight()/2f+10, true, 0);
+ } else {
+ String pre = EnumChatFormatting.GREEN.toString();
+ if(itemCount < candidatesOld.size()) {
+ pre = EnumChatFormatting.RED.toString();
+ }
+ Utils.drawStringCentered(pre+Math.min(candidatesOld.size(), itemCount)+"/"+
+ Math.min(candidatesOld.size(), MAX_BUILDERS_BLOCKS),
+ Minecraft.getMinecraft().fontRendererObj,
+ scaledResolution.getScaledWidth()/2f, scaledResolution.getScaledHeight()/2f+10, true, 0);
+ }
+
+ String itemCountS = EnumChatFormatting.DARK_GRAY+"x"+EnumChatFormatting.RESET+countItemsInInventoryAndStorage(matchStack);
+ int itemCountLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(itemCountS);
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.wandBlockCount.value) {
+ Utils.drawItemStack(matchStack, scaledResolution.getScaledWidth()/2 - (itemCountLen+16)/2, scaledResolution.getScaledHeight()/2+10+4);
+ Minecraft.getMinecraft().fontRendererObj.drawString(itemCountS,
+ scaledResolution.getScaledWidth()/2f - (itemCountLen+16)/2f+16, scaledResolution.getScaledHeight()/2f+10+8,
+ -1,
+ true);
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ }
+
+ }
+ }
+ }
+ }
+
+ public int countItemsInInventoryAndStorage(ItemStack match) {
+ int count = 0;
+
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ if(match.isItemEqual(stack)) {
+ count += stack.stackSize;
+ }
+ }
+
+ ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+
+ if(heldInternal != null && heldInternal.equals("BUILDERS_WAND")) {
+ //System.out.println("1");
+ if(held.hasTagCompound() && held.getTagCompound().hasKey("ExtraAttributes", 10) &&
+ held.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("builder's_wand_data", 7)) {
+ //System.out.println("2");
+ byte[] bytes = held.getTagCompound().getCompoundTag("ExtraAttributes").getByteArray("builder's_wand_data");
+ try {
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ for(int j=0; j<items.tagCount(); j++) {
+ NBTTagCompound buildersItem = items.getCompoundTagAt(j);
+ if(buildersItem.getKeySet().size() > 0) {
+ if(buildersItem.getInteger("id") == Item.getIdFromItem(match.getItem())) {
+ count += items.getCompoundTagAt(j).getByte("Count");
+ }
+ }
+ }
+ } catch(Exception e) {
+ return count;
+ }
+ }
+ }
+
+ return count;
+ }
+
+ @SubscribeEvent
+ public void renderBlockOverlay(DrawBlockHighlightEvent event) {
+ if(aoteTeleportationCurr != null && aoteTeleportationMillis > 0) {
+ event.setCanceled(true);
+ }
+ ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ String heldInternal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+ if(heldInternal != null) {
+ if(!NotEnoughUpdates.INSTANCE.manager.config.disableTreecapOverlay.value &&
+ (heldInternal.equals("JUNGLE_AXE") || heldInternal.equals("TREECAPITATOR_AXE"))) {
+ int maxWood = 10;
+ if(heldInternal.equals("TREECAPITATOR_AXE")) maxWood = 35;
+
+ if (event.target.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.color(0.0F, 0.0F, 0.0F, 0.4F);
+ GlStateManager.disableTexture2D();
+ GlStateManager.depthMask(false);
+
+ if(Minecraft.getMinecraft().theWorld.getBlockState(event.target.getBlockPos()).getBlock() == Blocks.log ||
+ Minecraft.getMinecraft().theWorld.getBlockState(event.target.getBlockPos()).getBlock() == Blocks.log2) {
+ EntityPlayer player = event.player;
+
+ int woods = 0;
+
+ HashSet<BlockPos> candidatesOld = new HashSet<>();
+ LinkedList<BlockPos> candidates = new LinkedList<>();
+ LinkedList<BlockPos> candidatesNew = new LinkedList<>();
+
+ candidatesNew.add(event.target.getBlockPos());
+
+ while(woods < maxWood) {
+ if(candidatesNew.isEmpty()) {
+ break;
+ }
+
+ candidates.addAll(candidatesNew);
+ candidatesNew.clear();
+
+ woods += candidates.size();
+ boolean random = woods > maxWood;
+
+ while(!candidates.isEmpty()) {
+ BlockPos candidate = candidates.pop();
+ Block block = Minecraft.getMinecraft().theWorld.getBlockState(candidate).getBlock();
+
+ candidatesOld.add(candidate);
+
+ for(int x = -1; x <= 1; x++) {
+ for(int y = -1; y <= 1; y++) {
+ for(int z = -1; z <= 1; z++) {
+ if(x != 0 || y != 0 || z != 0) {
+ BlockPos posNew = candidate.add(x, y, z);
+ if(!candidatesOld.contains(posNew) && !candidates.contains(posNew) && !candidatesNew.contains(posNew)) {
+ Block blockNew = Minecraft.getMinecraft().theWorld.getBlockState(posNew).getBlock();
+ if(blockNew == Blocks.log || blockNew == Blocks.log2) {
+ candidatesNew.add(posNew);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, candidate);
+ double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)event.partialTicks;
+ double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)event.partialTicks;
+ double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)event.partialTicks;
+
+ drawFilledBoundingBox(block.getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, candidate)
+ .expand(0.001D, 0.001D, 0.001D).offset(-d0, -d1, -d2),
+ random ? 0.5f : 1f, NotEnoughUpdates.INSTANCE.manager.config.treecapOverlayColour.value);
+ }
+ }
+ }
+
+ GlStateManager.depthMask(true);
+ GlStateManager.enableTexture2D();
+ GlStateManager.disableBlend();
+ }
+ } else if(!NotEnoughUpdates.INSTANCE.manager.config.disableWandOverlay.value && heldInternal.equals("BUILDERS_WAND")) {
+ int maxBlocks = 164;
+ if (event.target.typeOfHit == MovingObjectPosition.MovingObjectType.BLOCK) {
+ IBlockState hover = Minecraft.getMinecraft().theWorld.getBlockState(event.target.getBlockPos().offset(event.target.sideHit, 1));
+ if(hover.getBlock() == Blocks.air) {
+ EntityPlayer player = event.player;
+
+ IBlockState match = Minecraft.getMinecraft().theWorld.getBlockState(event.target.getBlockPos());
+ Item matchItem = Item.getItemFromBlock(match.getBlock());
+ if(matchItem != null) {
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.disableTexture2D();
+ GlStateManager.depthMask(false);
+
+ ItemStack matchStack = new ItemStack(matchItem, 1, match.getBlock().getMetaFromState(match));
+ int itemCount = countItemsInInventoryAndStorage(matchStack);
+
+ HashSet<BlockPos> candidatesOld = new HashSet<>();
+ TreeMap<Float, Set<BlockPos>> candidatesOldSorted = new TreeMap<>();
+
+ getBuildersWandCandidates(player, event.target, event.partialTicks, candidatesOld, candidatesOldSorted, 10);
+
+ String special = (candidatesOld.size() <= itemCount) ? NotEnoughUpdates.INSTANCE.manager.config.wandOverlayColour.value :
+ "0:255:255:0:0";
+
+ if(candidatesOld.size() <= maxBlocks) {
+ double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)event.partialTicks;
+ double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)event.partialTicks;
+ double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)event.partialTicks;
+
+ for(Set<BlockPos> candidatesSorted : candidatesOldSorted.values()) {
+ for(BlockPos candidate : candidatesSorted) {
+ match.getBlock().setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, candidate);
+ AxisAlignedBB bb = match.getBlock().getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, candidate)
+ .offset(event.target.sideHit.getFrontOffsetX(), event.target.sideHit.getFrontOffsetY(),
+ event.target.sideHit.getFrontOffsetZ());
+
+ drawBlock((int)bb.minX, (int)bb.minY, (int)bb.minZ+1, match, event.partialTicks, 0.75f);
+ }
+ }
+
+ for(BlockPos candidate : candidatesOld) {
+ match.getBlock().setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, candidate);
+ AxisAlignedBB bb = match.getBlock().getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, candidate)
+ .expand(0.001D, 0.001D, 0.001D).offset(-d0, -d1, -d2)
+ .offset(event.target.sideHit.getFrontOffsetX(), event.target.sideHit.getFrontOffsetY(),
+ event.target.sideHit.getFrontOffsetZ());
+
+ drawOutlineBoundingBox(bb, 1f, special);
+ }
+ }
+
+ GlStateManager.depthMask(true);
+ GlStateManager.enableTexture2D();
+ GlStateManager.disableBlend();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void getBuildersWandCandidates(EntityPlayer player, MovingObjectPosition target, float partialTicks,
+ HashSet<BlockPos> candidatesOld, TreeMap<Float, Set<BlockPos>> candidatesOldSorted, int extraMax) {
+ IBlockState match = Minecraft.getMinecraft().theWorld.getBlockState(target.getBlockPos());
+
+ candidatesOld.clear();
+ candidatesOldSorted.clear();
+ LinkedList<BlockPos> candidates = new LinkedList<>();
+ LinkedList<BlockPos> candidatesNew = new LinkedList<>();
+
+ candidatesNew.add(target.getBlockPos());
+
+ double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
+ double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
+ double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
+
+ while(candidatesOld.size() <= MAX_BUILDERS_BLOCKS+extraMax) {
+ if(candidatesNew.isEmpty()) {
+ break;
+ }
+
+ candidates.addAll(candidatesNew);
+ candidatesNew.clear();
+
+ while(!candidates.isEmpty()) {
+ if(candidatesOld.size() > MAX_BUILDERS_BLOCKS+extraMax) break;
+
+ BlockPos candidate = candidates.pop();
+
+ float distSq = (float)((candidate.getX()+0.5f-d0)*(candidate.getX()+0.5f-d0) +
+ (candidate.getY()+0.5f-d1-player.getEyeHeight())*(candidate.getY()+0.5f-d1-player.getEyeHeight()) +
+ (candidate.getZ()+0.5f-d2)*(candidate.getZ()+0.5f-d2));
+ candidatesOldSorted.computeIfAbsent(distSq, k->new HashSet<>()).add(candidate);
+
+ candidatesOld.add(candidate);
+
+ for(int x = -1; x <= 1; x++) {
+ for(int y = -1; y <= 1; y++) {
+ for(int z = -1; z <= 1; z++) {
+ if(x*x+y*y+z*z == 1) {
+ if(((x == 0) && (target.sideHit.getAxis() == EnumFacing.Axis.X)) ||
+ ((y == 0) && (target.sideHit.getAxis() == EnumFacing.Axis.Y)) ||
+ ((z == 0) && (target.sideHit.getAxis() == EnumFacing.Axis.Z))) {
+ if(Minecraft.getMinecraft().theWorld.getBlockState(candidate.add(
+ x+target.sideHit.getFrontOffsetX(),
+ y+target.sideHit.getFrontOffsetY(),
+ z+target.sideHit.getFrontOffsetZ())).getBlock() == Blocks.air) {
+ BlockPos posNew = candidate.add(x, y, z);
+ if(!candidatesOld.contains(posNew) && !candidates.contains(posNew) && !candidatesNew.contains(posNew)) {
+ IBlockState blockNew = Minecraft.getMinecraft().theWorld.getBlockState(posNew);
+ if(blockNew == match) {
+ candidatesNew.add(posNew);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static void drawBlock(int x, int y, int z, IBlockState state, float partialTicks, float brightness) {
+ EntityPlayerSP player = Minecraft.getMinecraft().thePlayer;
+ double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double)partialTicks;
+ double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double)partialTicks;
+ double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)partialTicks;
+
+ BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
+
+ GlStateManager.enableTexture2D();
+ GlStateManager.disableLighting();
+ GlStateManager.enableBlend();
+ GlStateManager.blendFunc(770, 771);
+
+ GlStateManager.enableDepth();
+ GlStateManager.depthMask(true);
+ GlStateManager.enableCull();
+ GlStateManager.cullFace(GL11.GL_BACK);
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x-d0, y-d1, z-d2);
+
+ int i = state.getBlock().getRenderType();
+ if(i == 3) {
+ IBakedModel ibakedmodel = blockrendererdispatcher.getModelFromBlockState(state, Minecraft.getMinecraft().theWorld, null);
+
+ Block block = state.getBlock();
+ block.setBlockBoundsForItemRender();
+ GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F);
+ int colour = block.getRenderColor(block.getStateForEntityRender(state));
+
+ if (EntityRenderer.anaglyphEnable) {
+ colour = TextureUtil.anaglyphColor(i);
+ }
+
+ colour = (colour & 0x00FFFFFF) | (100 << 24); //Set alpha to 100
+
+ for (EnumFacing enumfacing : EnumFacing.values()) {
+ renderModelBrightnessColorQuads(colour, ibakedmodel.getFaceQuads(enumfacing));
+ }
+
+ renderModelBrightnessColorQuads(colour, ibakedmodel.getGeneralQuads());
+ }
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.translate(-x+d0, -y+d1, -z+d2);
+ GlStateManager.popMatrix();
+ }
+
+ private static void renderModelBrightnessColorQuads(int c, List<BakedQuad> listQuads) {
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+
+ for (BakedQuad bakedquad : listQuads) {
+ worldrenderer.begin(7, DefaultVertexFormats.ITEM);
+ worldrenderer.addVertexData(bakedquad.getVertexData());
+
+ worldrenderer.putColor4(c);
+
+ Vec3i vec3i = bakedquad.getFace().getDirectionVec();
+ worldrenderer.putNormal((float)vec3i.getX(), (float)vec3i.getY(), (float)vec3i.getZ());
+ tessellator.draw();
+ }
+ }
+
+ public static void drawFilledBoundingBox(AxisAlignedBB p_181561_0_, float alpha, String special) {
+ Color c = new Color(SpecialColour.specialToChromaRGB(special), true);
+ GlStateManager.color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha);
+
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.disableTexture2D();
+ GlStateManager.depthMask(false);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ //vertical
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+ //x
+
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+
+ //z
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ tessellator.draw();
+ worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+
+ }
+
+ public static void drawOutlineBoundingBox(AxisAlignedBB p_181561_0_, float alpha, String special) {
+ Color c = new Color(SpecialColour.specialToChromaRGB(special), true);
+ GlStateManager.color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha);
+
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.disableTexture2D();
+ GlStateManager.depthMask(false);
+
+ GL11.glLineWidth(3);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(3, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ tessellator.draw();
+ worldrenderer.begin(3, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ tessellator.draw();
+ worldrenderer.begin(1, DefaultVertexFormats.POSITION);
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ tessellator.draw();
+
+ GL11.glLineWidth(1);
+ }
+
+}
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..c450c6f4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiEnchantColour.java
@@ -0,0 +1,257 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.common.base.Splitter;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.util.LerpingInteger;
+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.input.Mouse;
+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<>();
+
+ private LerpingInteger scroll = new LerpingInteger(0, 100);
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ drawDefaultBackground();
+
+ List<String> enchantColours = getEnchantColours();
+
+ ySize = 53+25*enchantColours.size();
+ guiLeft = (width-xSize)/2;
+
+ if(ySize > height) {
+ if(scroll.getTarget() > 0) {
+ scroll.setTarget(0);
+ } else if(scroll.getTarget() < height-ySize) {
+ scroll.setTarget(height-ySize);
+ }
+ scroll.tick();
+ guiTop = scroll.getValue();
+ } else {
+ guiTop = (height-ySize)/2;
+ scroll.setValue(0);
+ scroll.resetTimer();
+ }
+
+
+ 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
+ public void handleMouseInput() throws IOException {
+ super.handleMouseInput();
+
+ int dWheel = Mouse.getEventDWheel();
+
+ if(dWheel < 0) {
+ scroll.setTarget(scroll.getTarget()-50);
+ scroll.resetTimer();
+ } else if(dWheel > 0) {
+ scroll.setTarget(scroll.getTarget()+50);
+ scroll.resetTimer();
+ }
+ }
+
+ @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/GuiTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java
index 1f87018b..05fb792a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/GuiTextures.java
@@ -22,8 +22,27 @@ public class GuiTextures {
public static final ResourceLocation slider_button = new ResourceLocation("notenoughupdates:slider_button.png");
public static final ResourceLocation item_mask = new ResourceLocation("notenoughupdates:item_mask.png");
+ public static final ResourceLocation item_haschild = new ResourceLocation("notenoughupdates:item_haschild.png");
public static final ResourceLocation button_tex = new ResourceLocation("notenoughupdates:button.png");
+ public static final ResourceLocation setting_border = new ResourceLocation("notenoughupdates:setting_border.png");
+
+ public static final ResourceLocation button_white = new ResourceLocation("notenoughupdates:button_white.png");
+ public static final ResourceLocation colour_selector_dot = new ResourceLocation("notenoughupdates:colour_selector_dot.png");
+ public static final ResourceLocation colour_selector_bar = new ResourceLocation("notenoughupdates:colour_selector_bar.png");
+ public static final ResourceLocation colour_selector_bar_alpha = new ResourceLocation("notenoughupdates:colour_selector_bar_alpha.png");
+ public static final ResourceLocation colour_selector_chroma = new ResourceLocation("notenoughupdates:colour_selector_chroma.png");
+
+ public static final ResourceLocation accessory_bag_overlay = new ResourceLocation("notenoughupdates:accessory_bag_overlay.png");
+
+ public static final ResourceLocation quickcommand_background = new ResourceLocation("notenoughupdates:quickcommand_background.png");
+
+ public static final ResourceLocation gamemodes = new ResourceLocation("notenoughupdates:gamemodes.png");
+ public static final ResourceLocation radial_square_off = new ResourceLocation("notenoughupdates:radial_square_off.png");
+ public static final ResourceLocation radial_square_on = new ResourceLocation("notenoughupdates:radial_square_on.png");
+ public static final ResourceLocation radial_circle_off = new ResourceLocation("notenoughupdates:radial_circle_off.png");
+ public static final ResourceLocation radial_circle_on = new ResourceLocation("notenoughupdates:radial_circle_on.png");
+
public static final ResourceLocation dungeon_chest_worth = new ResourceLocation("notenoughupdates:dungeon_chest_worth.png");
public static final ResourceLocation auction_view = new ResourceLocation("notenoughupdates:auction_view.png");
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/MorusIntegration.java b/src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java
new file mode 100644
index 00000000..8ec4263a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java
@@ -0,0 +1,60 @@
+package io.github.moulberry.notenoughupdates;
+
+import io.github.moulberry.morus.MorusSubstitutor;
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class MorusIntegration {
+
+ private static MorusIntegration INSTANCE = new MorusIntegration();
+
+ public static MorusIntegration getInstance() {
+ return INSTANCE;
+ }
+
+ private HashMap<String, Integer> itemDrops = null;
+ private HashMap<String, Integer> inventoryItems = null;
+
+ public void tick() {
+ if(itemDrops == null) {
+ itemDrops = new HashMap<>();
+ for(String item : NotEnoughUpdates.INSTANCE.manager.getItemInformation().keySet()) {
+ itemDrops.put(item, 0);
+ }
+ }
+
+ HashMap<String, Integer> newInventoryItems = getInventoryItems();
+ if(inventoryItems != null) {
+ for(String internal : newInventoryItems.keySet()) {
+ int newAmount = newInventoryItems.get(internal);
+ int oldAmount = inventoryItems.getOrDefault(internal, 0);
+ if(newAmount > oldAmount) {
+ itemDrops.put(internal, itemDrops.getOrDefault(internal, 0)+newAmount-oldAmount);
+ }
+ }
+ }
+ inventoryItems = newInventoryItems;
+
+ for(Map.Entry<String, Integer> entry : itemDrops.entrySet()) {
+ MorusSubstitutor.putSubstiution("notenoughupdates", "itemdrops."+entry.getKey().toLowerCase(), ""+entry.getValue());
+ }
+
+ }
+
+ public HashMap<String, Integer> getInventoryItems() {
+ HashMap<String, Integer> inventoryItems = new HashMap<>();
+ if(Minecraft.getMinecraft().thePlayer != null) {
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if(internalname != null) {
+ inventoryItems.put(internalname, inventoryItems.getOrDefault(internalname, 0)+stack.stackSize);
+ }
+ }
+ }
+ return inventoryItems;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java
deleted file mode 100644
index 996809da..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUCape2.java
+++ /dev/null
@@ -1,607 +0,0 @@
-package io.github.moulberry.notenoughupdates;
-
-import net.minecraft.block.Block;
-import net.minecraft.client.Minecraft;
-import net.minecraft.client.entity.EntityPlayerSP;
-import net.minecraft.client.renderer.GlStateManager;
-import net.minecraft.client.renderer.Tessellator;
-import net.minecraft.client.renderer.WorldRenderer;
-import net.minecraft.client.renderer.texture.SimpleTexture;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
-import net.minecraft.command.CommandBase;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.util.*;
-import net.minecraftforge.client.event.ClientChatReceivedEvent;
-import net.minecraftforge.client.event.RenderPlayerEvent;
-import net.minecraftforge.common.MinecraftForge;
-import net.minecraftforge.event.entity.EntityJoinWorldEvent;
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
-import net.minecraftforge.fml.common.gameevent.TickEvent;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL20;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-public class NEUCape2 {
-
- //private ResourceLocation capeImageLocation = new ResourceLocation(Morus.MODID, "cape.jpg");
- //private SimpleTexture capeTexture;
-
- private long millisLastRenderUpdate = 0;
-
- private int horzNodes = 20;
- private double targetDist = 1/30.0;
-
- private EntityPlayer player = null;
-
- private double vertOffset = 1.4;
- private double shoulderLength = 0.3;
- private double shoulderWidth = 0.13;
- private double crouchWidthOffset = -0.05;
- private double maxCrouchOffset = 0.35;
-
- private double resistance = 0.08;
- private double gravity = 0.04;
- private int steps = 10;
-
- private List<List<Node>> nodes = new ArrayList<>();
-
- /*private void reloadCapeImage() {
- if(capeTexture != null) {
- capeTexture.deleteGlTexture();
- }
- capeTexture = new SimpleTexture(capeImageLocation);
- try {
- capeTexture.loadTexture(Minecraft.getMinecraft().getResourceManager());
- } catch(IOException e) {
- e.printStackTrace();
- }
- }*/
-
- private void resetNodes(EntityPlayer player) {
- nodes.clear();
- for(int i=0; i<50; i++) {
- List<Node> list = new ArrayList<>();
- for(int j=0; j<horzNodes; j++) {
- if(horzNodes == 1) {
- list.add(new Node(player.posX-1, player.posY+2-i*targetDist, player.posZ, i, j));
- } else if(horzNodes > 1) {
- list.add(new Node(player.posX-1, player.posY+2-i*targetDist, player.posZ+((double)j)/(horzNodes-1), i, j));
- }
- }
-
- nodes.add(list);
- }
- }
-
- class Node {
- public int iIndex;
- public int jIndex;
-
- public boolean fixed = false;
-
- public double x;
- public double y;
- public double z;
- public double xOld;
- public double yOld;
- public double zOld;
- public double aX;
- public double aY;
- public double aZ;
-
- public double normalX;
- public double normalY;
- public double normalZ;
-
- public Node(double x, double y, double z, int iIndex, int jIndex) {
- this.x = xOld = x;
- this.y = xOld = y;
- this.z = xOld = z;
- this.iIndex = iIndex;
- this.jIndex = jIndex;
- }
-
- private void updateNormal(Node up, Node left, Node right, Node down, Node up2, Node left2, Node right2, Node down2) {
- Vec3 normal1 = normal(up, left);
- Vec3 normal2 = normal(right, up);
- Vec3 normal3 = normal(down, right);
- Vec3 normal4 = normal(left, down);
- Vec3 normal5 = normal(up2, left2);
- Vec3 normal6 = normal(right2, up2);
- Vec3 normal7 = normal(down2, right2);
- Vec3 normal8 = normal(left2, down2);
-
- Vec3 avgNormal = normal1.add(normal2).add(normal3).add(normal4)
- .add(normal5).add(normal6).add(normal7).add(normal8).normalize();
-
- normalX = avgNormal.xCoord;
- normalY = avgNormal.yCoord;
- normalZ = avgNormal.zCoord;
- }
-
- private Vec3 normal(Node node1, Node node2) {
- if(node1 == null || node2 == null) {
- return new Vec3(0,0,0);
- }
- Vec3 thisNode = node2vec(this);
- Vec3 node1Vec = node2vec(node1);
- Vec3 node2Vec = node2vec(node2);
-
- Vec3 thisTo1 = node1Vec.subtract(thisNode);
- Vec3 thisTo2 = node2Vec.subtract(thisNode);
-
- return thisTo1.crossProduct(thisTo2);
-
- }
-
- public void update(double pX, double pY, double pZ, EntityPlayer player) {
- if(fixed) {
- return;
- }
-
- double xTemp = x;
- double yTemp = y;
- double zTemp = z;
-
- double res = resistance;
-
- BlockPos pos = new BlockPos(
- MathHelper.floor_double(x),
- MathHelper.floor_double(y),
- MathHelper.floor_double(z));
- Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock();
- if(block.getMaterial().isLiquid()) {
- aX /= 5;
- aY /= 5;
- aZ /= 5;
-
- res = Math.sqrt(res);
- }
-
- double xDiff = x-xOld;
- double yDiff = y-yOld;
- double zDiff = z-zOld;
-
- xDiff = MathHelper.clamp_double(xDiff, -0.5, 0.5);
- yDiff = MathHelper.clamp_double(yDiff, -0.5, 0.5);
- zDiff = MathHelper.clamp_double(zDiff, -0.5, 0.5);
-
- x = x + xDiff*(1-res)+aX*0.2;
- y = y + yDiff*(1-res)+aY*0.2;
- z = z + zDiff*(1-res)+aZ*0.2;
-
- resolvePlayerCollision(pX, pY, pZ, player);
-
- if(!checkCollision(xTemp, yTemp, zTemp)) {
- xOld = xTemp;
- yOld = yTemp;
- zOld = zTemp;
- }
-
- if(checkCollision(x, y, z)) {
- updateFromBoundingBox();
- }
-
- aX = 0;
- aY = 0;
- aZ = 0;
- }
-
- public boolean resolvePlayerCollision(double pX, double pY, double pZ, EntityPlayer player) {
- double angle = Math.toRadians(player.renderYawOffset);
-
- double offset = 0;
-
- if(player.getCurrentArmor(1) != null) {
- if(player.isSneaking()) {
- offset += 0.15;
- } else {
- offset += 0.06;
- }
- }
-
- if(player.isSneaking()) {
- offset -= crouchWidthOffset;
-
- double dY = y - player.posY;
-
- if(dY < 0.65) {
- offset += maxCrouchOffset;
- } else if(dY < 1.2) {
- offset += maxCrouchOffset*(1.2-dY)/0.55;
- }
- }
-
- double x1 = pX+Math.cos(angle)*2-Math.cos(angle+Math.PI/2)*(shoulderWidth+offset);
- double z1 = pZ+Math.sin(angle)*2-Math.sin(angle+Math.PI/2)*(shoulderWidth+offset);
- double x2 = pX-Math.cos(angle)*2-Math.cos(angle+Math.PI/2)*(shoulderWidth+offset);
- double z2 = pZ-Math.sin(angle)*2-Math.sin(angle+Math.PI/2)*(shoulderWidth+offset);
-
- boolean crossed = ((x2 - x1)*(z - z1) < (z2 - z1)*(x - x1));
-
- if(crossed) {
- double dot1 = ((x-x2)*(x1-x2)+(z-z2)*(z1-z2));
- double dot2 = (x1-x2)*(x1-x2)+(z1-z2)*(z1-z2);
- double k = dot1/dot2;
-
- x = xOld = (x1-x2)*k+x2;
- z = zOld = (z1-z2)*k+z2;
-
- return true;
- }
- return false;
- }
-
- public void updateFromBoundingBox() {
- BlockPos pos = new BlockPos(
- MathHelper.floor_double(x),
- MathHelper.floor_double(y),
- MathHelper.floor_double(z));
- Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock();
- block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, pos);
- AxisAlignedBB bb = block.getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, pos);
-
- Vec3 center = new Vec3((bb.minX + bb.maxX) / 2, (bb.minY + bb.maxY) / 2, (bb.minZ + bb.maxZ) / 2);
- MovingObjectPosition mop = bb.calculateIntercept(center.add(new Vec3(x, y, z).subtract(center).normalize()), center);
-
- if(mop == null) {
- return;
- }
-
- Vec3 vec = mop.hitVec;
-
- if(vec == null) {
- return;
- }
-
- double dX = vec.xCoord - x;
- double dY = vec.yCoord - y;
- double dZ = vec.zCoord - z;
- double adX = Math.abs(dX);
- double adY = Math.abs(dY);
- double adZ = Math.abs(dZ);
-
- double tot = adX + adY + adZ;
-
- //Simulate a little bit of friction
- if(tot < 0.15 || checkCollision(vec.xCoord, vec.yCoord, vec.zCoord)) {
- x = xOld;
- y = yOld;
- z = zOld;
- return;
- }
-
- //>0.3 check reduces the movement at corners a little bit
- if(adX/tot > 0.3) x = xOld = vec.xCoord;
- if(adY/tot > 0.3) y = yOld = vec.yCoord;
- if(adZ/tot > 0.3) z = zOld = vec.zCoord;
- }
-
- public boolean checkCollision(double x, double y, double z) {
- BlockPos pos = new BlockPos(
- MathHelper.floor_double(x),
- MathHelper.floor_double(y),
- MathHelper.floor_double(z));
- Block block = Minecraft.getMinecraft().theWorld.getBlockState(pos).getBlock();
-
- if(block.getMaterial().isSolid()) {
- block.setBlockBoundsBasedOnState(Minecraft.getMinecraft().theWorld, pos);
- AxisAlignedBB bb = block.getSelectedBoundingBox(Minecraft.getMinecraft().theWorld, pos);
-
- return bb.isVecInside(new Vec3(x, y, z));
- } else {
- return false;
- }
- }
- }
-
- @SubscribeEvent
- public void onRenderTick(TickEvent.RenderTickEvent e) {
- if(Minecraft.getMinecraft().theWorld == null || player == null) {
- return;
- }
-
- long delta = System.currentTimeMillis() - millisLastRenderUpdate;
-
- double lagFactor = delta/(1000/60.0);
- if(lagFactor > 3) {
- lagFactor = 3;
- }
-
- double playerX = player.lastTickPosX + (player.posX - player.lastTickPosX) * e.renderTickTime;
- double playerY = player.lastTickPosY + (player.posY - player.lastTickPosY) * e.renderTickTime;
- double playerZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * e.renderTickTime;
-
- updateFixedNodes(playerX, playerY, playerZ, player);
-
- for(List<Node> nodes2 : nodes) {
- for(Node node : nodes2) {
- node.aY -= gravity*lagFactor;
- node.update(playerX, playerY, playerZ, player);
- }
- }
- for(int step=0; step<steps*lagFactor; step++) {
- for(int i=0; i<nodes.size(); i++) {
- for (int j = 0; j < horzNodes; j++) {
- Node node = nodes.get(i).get(j);
- List<Node> struct = new ArrayList<>();
- List<Node> shear = new ArrayList<>();
- List<Node> bend = new ArrayList<>();
-
- if(i+1 < nodes.size()) struct.add(nodes.get(i+1).get(j));
- if(j+1 < horzNodes) struct.add(nodes.get(i).get(j+1));
- if(i-1 >= 0) struct.add(nodes.get(i-1).get(j));
- if(j-1 >= 0) struct.add(nodes.get(i).get(j-1));
-
- if(i+1 < nodes.size() && j+1 < horzNodes) shear.add(nodes.get(i+1).get(j+1));
- if(i+1 < nodes.size() && j-1 >= 0) shear.add(nodes.get(i+1).get(j-1));
- if(i-1 >= 0 && j+1 < horzNodes) shear.add(nodes.get(i-1).get(j+1));
- if(i-1 >= 0 && j-1 >= 0) shear.add(nodes.get(i-1).get(j-1));
-
- if(i+2 < nodes.size()) bend.add(nodes.get(i+2).get(j));
- if(j+2 < horzNodes) bend.add(nodes.get(i).get(j+2));
- if(i-2 >= 0) bend.add(nodes.get(i-2).get(j));
- if(j-2 >= 0) bend.add(nodes.get(i).get(j-2));
-
- try {
- updateNode(node, struct, shear, bend);
- } catch(Exception ex) {
-
- }
- }
- }
- }
- for(int i=0; i<nodes.size(); i++) {
- for (int j = 0; j < horzNodes; j++) {
- Node up = null, down = null, left = null, right = null;
- Node up2 = null, down2 = null, left2 = null, right2 = null;
-
- if(i+1 < nodes.size()) down = nodes.get(i+1).get(j);
- if(j+1 < horzNodes) right = nodes.get(i).get(j+1);
- if(i-1 >= 0) up = nodes.get(i-1).get(j);
- if(j-1 >= 0) left = nodes.get(i).get(j-1);
-
- if(i+2 < nodes.size()) down2 = nodes.get(i+2).get(j);
- if(j+2 < horzNodes) right2 = nodes.get(i).get(j+2);
- if(i-2 >= 0) up2 = nodes.get(i-2).get(j);
- if(j-2 >= 0) left2 = nodes.get(i).get(j-2);
-
- nodes.get(i).get(j).updateNormal(up, left, right, down, up2, left2, right2, down2);
- }
- }
-
- millisLastRenderUpdate = System.currentTimeMillis();
- }
-
- @SubscribeEvent
- public void onRenderPlayer(RenderPlayerEvent.Post e) {
- EntityPlayer player = e.entityPlayer;
-
- if(!player.getName().equalsIgnoreCase("Moulberry")) {
- return;
- }
-
- if(nodes.size() == 0) {
- resetNodes(player);
- }
-
- this.player = player;
-
- Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
-
- double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * e.partialRenderTick;
- double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * e.partialRenderTick;
- double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * e.partialRenderTick;
-
- GlStateManager.pushMatrix();
- GlStateManager.enableBlend();
- GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA,
- GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
- GL11.glDisable(GL11.GL_CULL_FACE);
- GlStateManager.enableTexture2D();
- int currTex = GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D);
- //GL11.glBindTexture(GL11.GL_TEXTURE_2D, capeTexture.getGlTextureId());
-
- //ShaderManager shaderManager = ShaderManager.getInstance();
-
- //shaderManager.loadShader("cape");
-
- for(int i=0; i<nodes.size(); i++) {
- for(int j=0; j<horzNodes; j++) {
- Node node = nodes.get(i).get(j);
- if(i+1 < nodes.size() && j+1 < horzNodes) {
- GlStateManager.color(1F, 1F, 1F, 1F);
- renderNodeConnection(viewerX, viewerY, viewerZ, node,
- nodes.get(i+1).get(j), nodes.get(i).get(j+1),
- nodes.get(i+1).get(j+1), true);
- GlStateManager.color(0.1F, 0.1F, 0.1F, 1F);
- renderNodeConnection(viewerX, viewerY, viewerZ, node,
- nodes.get(i+1).get(j), nodes.get(i).get(j+1),
- nodes.get(i+1).get(j+1), false);
- }
- }
- }
-
- GlStateManager.color(0.1F, 0.1F, 0.1F, 1F);
- for(int i=0; i<nodes.size(); i++) {
- if(i+1 < nodes.size()) {
- renderSideConnection(viewerX, viewerY, viewerZ,
- nodes.get(i).get(0), nodes.get(i+1).get(0));
- renderSideConnection(viewerX, viewerY, viewerZ,
- nodes.get(i).get(horzNodes-1), nodes.get(i+1).get(horzNodes-1));
- }
- }
-
- for(int j=0; j<horzNodes; j++) {
- if(j+1 < horzNodes) {
- renderSideConnection(viewerX, viewerY, viewerZ,
- nodes.get(0).get(j), nodes.get(0).get(j+1));
- renderSideConnection(viewerX, viewerY, viewerZ,
- nodes.get(nodes.size()-1).get(j), nodes.get(nodes.size()-1).get(j+1));
- }
- }
-
- GL20.glUseProgram(0);
-
- GL11.glBindTexture(GL11.GL_TEXTURE_2D, currTex);
- GL11.glEnable(GL11.GL_CULL_FACE);
- GlStateManager.enableTexture2D();
- GlStateManager.disableBlend();
- GlStateManager.popMatrix();
- GlStateManager.color(1F, 1F, 1F, 1F);
- }
-
- private Vec3 node2vec(Node node) {
- return new Vec3(node.x, node.y, node.z);
- }
-
- private void renderSideConnection(double pX, double pY, double pZ, Node node1, Node node2) {
- Tessellator tessellator = Tessellator.getInstance();
- WorldRenderer worldrenderer = tessellator.getWorldRenderer();
-
- worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_NORMAL);
-
- worldrenderer.pos(node1.x-pX, node1.y-pY, node1.z-pZ)
- .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex();
- worldrenderer.pos(node2.x-pX, node2.y-pY, node2.z-pZ)
- .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex();
- worldrenderer.pos(node1.x-pX+node1.normalX/15, node1.y-pY+node1.normalY/15, node1.z-pZ+node1.normalZ/15)
- .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex();
- worldrenderer.pos(node2.x-pX+node2.normalX/15, node2.y-pY+node2.normalY/15, node2.z-pZ+node2.normalZ/15)
- .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex();
-
- tessellator.draw();
- }
-
- private void renderNodeConnection(double pX, double pY, double pZ, Node node1, Node node2,
- Node node3, Node node4, boolean offset) {
- Tessellator tessellator = Tessellator.getInstance();
- WorldRenderer worldrenderer = tessellator.getWorldRenderer();
-
- //Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(node1.normalY + " " + node2.normalY + " " + node3.normalY + " " + node4.normalY));
-
- if(offset) {
- worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX_NORMAL);
-
- worldrenderer.pos(node1.x-pX+node1.normalX/15, node1.y-pY+node1.normalY/15, node1.z-pZ+node1.normalZ/15)
- .tex(((double)node1.jIndex)/(horzNodes-1), ((double)node1.iIndex)/(nodes.size()-1))
- .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex();
- worldrenderer.pos(node2.x-pX+node2.normalX/15, node2.y-pY+node2.normalY/15, node2.z-pZ+node2.normalZ/15)
- .tex(((double)node2.jIndex)/(horzNodes-1), ((double)node2.iIndex)/(nodes.size()-1))
- .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex();
- worldrenderer.pos(node3.x-pX+node3.normalX/15, node3.y-pY+node3.normalY/15, node3.z-pZ+node3.normalZ/15)
- .tex(((double)node3.jIndex)/(horzNodes-1), ((double)node3.iIndex)/(nodes.size()-1))
- .normal((float)node3.normalX, (float)node3.normalY, (float)node3.normalZ).endVertex();
- worldrenderer.pos(node4.x-pX+node4.normalX/15, node4.y-pY+node4.normalY/15, node4.z-pZ+node4.normalZ/15)
- .tex(((double)node4.jIndex)/(horzNodes-1), ((double)node4.iIndex)/(nodes.size()-1))
- .normal((float)node4.normalX, (float)node4.normalY, (float)node4.normalZ).endVertex();
-
- } else {
- worldrenderer.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_NORMAL);
-
- worldrenderer.pos(node1.x-pX, node1.y-pY, node1.z-pZ)
- .normal((float)node1.normalX, (float)node1.normalY, (float)node1.normalZ).endVertex();
- worldrenderer.pos(node2.x-pX, node2.y-pY, node2.z-pZ)
- .normal((float)node2.normalX, (float)node2.normalY, (float)node2.normalZ).endVertex();
- worldrenderer.pos(node3.x-pX, node3.y-pY, node3.z-pZ)
- .normal((float)node3.normalX, (float)node3.normalY, (float)node3.normalZ).endVertex();
- worldrenderer.pos(node4.x-pX, node4.y-pY, node4.z-pZ)
- .normal((float)node4.normalX, (float)node4.normalY, (float)node4.normalZ).endVertex();
- }
-
- tessellator.draw();
- }
-
- private Vec3 scale(Vec3 vector, double amount) {
- return new Vec3(vector.xCoord * amount, vector.yCoord * amount, vector.zCoord * amount);
- }
-
- private void updateNode(Node node, List<Node> struct, List<Node> shear, List<Node> bend) {
- double shearDist = 1.414*targetDist;
- double bendDist = 2*targetDist; //Potentially differentiate between corners?
-
- for(Node bendNode : bend) {
- resolve(node, bendNode, bendDist);
- }
-
- for(Node shearNode : shear) {
- resolve(node, shearNode, shearDist);
- }
-
- for(Node structNode : struct) {
- resolve(node, structNode, targetDist);
- }
- }
-
- public void resolve(Node node1, Node node2, double targetDist) {
- double dX = node1.x - node2.x;
- double dY = node1.y - node2.y;
- double dZ = node1.z - node2.z;
-
- double distSq = dX*dX + dY*dY + dZ*dZ;
- double dist = Math.sqrt(distSq);
-
- dX *= (1 - targetDist/dist)*0.5;
- dY *= (1 - targetDist/dist)*0.5;
- dZ *= (1 - targetDist/dist)*0.5;
-
- if(node1.fixed || node2.fixed) {
- dX *= 2;
- dY *= 2;
- dZ *= 2;
- }
-
- if(!node1.fixed) {
- node1.x -= dX;
- node1.y -= dY;
- node1.z -= dZ;
- }
-
- if(!node2.fixed) {
- node2.x += dX;
- node2.y += dY;
- node2.z += dZ;
- }
- }
-
- private void updateFixedNodes(double pX, double pY, double pZ, EntityPlayer player) {
- double angle = Math.toRadians(player.renderYawOffset);
-
- double shoulderWidth2 = shoulderWidth + (player.isSneaking()?crouchWidthOffset:0);
- if(player.getCurrentArmor(1) != null || player.getCurrentArmor(2) != null) {
- if(player.isSneaking()) {
- shoulderWidth2 += 0.15;
- } else {
- shoulderWidth2 += 0.06;
- }
- }
-
- Node node = nodes.get(0).get(0);
- node.x = pX+Math.cos(angle)*shoulderLength-Math.cos(angle+Math.PI/2)*shoulderWidth2;
- node.y = pY+vertOffset-(player.isSneaking()?0.2:0);
- node.z = pZ+Math.sin(angle)*shoulderLength-Math.sin(angle+Math.PI/2)*shoulderWidth2;
- node.fixed = true;
-
- node = nodes.get(0).get(nodes.get(0).size()-1);
- node.x = pX-Math.cos(angle)*shoulderLength-Math.cos(angle+Math.PI/2)*shoulderWidth2;
- node.y = pY+vertOffset-(player.isSneaking()?0.2:0);
- node.z = pZ-Math.sin(angle)*shoulderLength-Math.sin(angle+Math.PI/2)*shoulderWidth2;
- node.fixed = true;
-
-
-
- /*for(int i=0; i<horzNodes; i++) {
- Node node = nodes.get(0).get(i);
-
- node.x = pX-1;
- node.y = pY+2;
- node.z = pZ+((double)i)/(horzNodes-1);
- }*/
- }
-
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
new file mode 100644
index 00000000..f67b09ed
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
@@ -0,0 +1,1564 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.auction.APIManager;
+import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
+import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
+import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer;
+import io.github.moulberry.notenoughupdates.questing.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiCrafting;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.event.ClickEvent;
+import net.minecraft.init.Blocks;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.client.event.*;
+import net.minecraftforge.event.entity.player.ItemTooltipEvent;
+import net.minecraftforge.fml.common.Loader;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.StringSelection;
+import java.io.File;
+import java.io.IOException;
+import java.text.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.dungeon_chest_worth;
+
+public class NEUEventListener {
+
+ private NotEnoughUpdates neu;
+
+ private boolean hoverInv = false;
+ private boolean focusInv = false;
+
+ private boolean joinedSB = false;
+
+ public NEUEventListener(NotEnoughUpdates neu) {
+ this.neu = neu;
+ }
+
+ private void displayUpdateMessageIfOutOfDate() {
+ File repo = neu.manager.repoLocation;
+ if(repo.exists()) {
+ File updateJson = new File(repo, "update.json");
+ try {
+ JsonObject o = neu.manager.getJsonFromFile(updateJson);
+
+ String version = o.get("version").getAsString();
+
+ if(!neu.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));
+ }
+
+ neu.displayLinks(o);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+
+ }
+ } catch(Exception ignored) {}
+ }
+ }
+
+ private long notificationDisplayMillis = 0;
+ private List<String> notificationLines = null;
+
+ /**
+ * 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 lastVeryLongUpdate = 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(!NotEnoughUpdates.INSTANCE.manager.config.slowDungeonBlocks.value) {
+ DungeonBlocks.tick();
+ }
+ DungeonWin.tick();
+ if(longUpdate) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.slowDungeonBlocks.value) {
+ DungeonBlocks.tick();
+ }
+
+ neu.updateSkyblockScoreboard();
+ CapeManager.getInstance().tick();
+
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if(!containerName.trim().startsWith("Accessory Bag")) {
+ AccessoryBagOverlay.resetCache();
+ }
+ } else {
+ AccessoryBagOverlay.resetCache();
+ }
+
+ if(neu.hasSkyblockScoreboard()) {
+ if(Loader.isModLoaded("morus")) {
+ MorusIntegration.getInstance().tick();
+ }
+ lastSkyblockScoreboard = currentTime;
+ if(!joinedSB) {
+ joinedSB = true;
+
+ SBGamemodes.loadFromFile();
+
+ if(neu.manager.config.showUpdateMsg.value) {
+ displayUpdateMessageIfOutOfDate();
+ }
+
+ long maxMemoryMB = Runtime.getRuntime().maxMemory()/1024L/1024L;
+ if(maxMemoryMB > 4100) {
+ notificationDisplayMillis = System.currentTimeMillis();
+ notificationLines = new ArrayList<>();
+ notificationLines.add(EnumChatFormatting.DARK_RED+"Too much memory allocated!");
+ notificationLines.add(String.format(EnumChatFormatting.DARK_GRAY+"NEU has detected %03dMB of memory allocated to Minecraft!", maxMemoryMB));
+ notificationLines.add(EnumChatFormatting.DARK_GRAY+"It is recommended to allocated between 2-4GB of memory");
+ notificationLines.add(EnumChatFormatting.DARK_GRAY+"More than 4GB WILL cause FPS issues, EVEN if you have 16GB+ available");
+ notificationLines.add("");
+ notificationLines.add(EnumChatFormatting.DARK_GRAY+"For more information, visit #ram-info in discord.gg/spr6ESn");
+ }
+
+ if(!neu.manager.config.loadedModBefore.value) {
+ neu.manager.config.loadedModBefore.value = true;
+ try { neu.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(""));
+ }
+ }
+ SBInfo.getInstance().tick();
+ //GuiQuestLine.questLine.tick();
+ }
+ if(currentTime - lastSkyblockScoreboard < 5*60*1000) { //5 minutes
+ neu.manager.auctionManager.tick();
+ } else {
+ neu.manager.auctionManager.markNeedsUpdate();
+ }
+ //ItemRarityHalo.resetItemHaloCache();
+ }
+ if(longUpdate && neu.hasSkyblockScoreboard()) {
+ if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) {
+ ProfileViewer.Profile profile = NotEnoughUpdates.profileViewer.getProfile(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
+ callback->{});
+ if(profile != null) {
+ String latest = profile.getLatestProfile();
+ if(latest != null) {
+ neu.manager.setCurrentProfileBackup(profile.getLatestProfile());
+ }
+ }
+ }
+ if(neu.manager.getCurrentProfile() != null && neu.manager.getCurrentProfile().length() > 0) {
+ HashSet<String> newItem = new HashSet<>();
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer &&
+ !(Minecraft.getMinecraft().currentScreen instanceof GuiCrafting)) {
+ boolean usableContainer = true;
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) {
+ if(stack == null) {
+ continue;
+ }
+ if(stack.hasTagCompound()) {
+ NBTTagCompound tag = stack.getTagCompound();
+ if(tag.hasKey("ExtraAttributes", 10)) {
+ continue;
+ }
+ }
+ usableContainer = false;
+ break;
+ }
+ if(!usableContainer) {
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ if(containerName.equals("Accessory Bag") || containerName.startsWith("Wardrobe")) {
+ usableContainer = true;
+ }
+ }
+ }
+ if(usableContainer) {
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ processUniqueStack(stack, newItem);
+ }
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) {
+ processUniqueStack(stack, newItem);
+ }
+ }
+ } else {
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ processUniqueStack(stack, newItem);
+ }
+ }
+ newItemAddMap.keySet().retainAll(newItem);
+ }
+ }
+ }
+
+ private void processUniqueStack(ItemStack stack, HashSet<String> newItem) {
+ if(stack != null && stack.hasTagCompound()) {
+ String internalname = neu.manager.getInternalNameForItem(stack);
+ if(internalname != null) {
+ ArrayList<String> log = neu.manager.config.collectionLog.value.computeIfAbsent(
+ neu.manager.getCurrentProfile(), k -> new ArrayList<>());
+ if(!log.contains(internalname)) {
+ newItem.add(internalname);
+ if(newItemAddMap.containsKey(internalname)) {
+ if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) {
+ log.add(internalname);
+ try { neu.manager.saveConfig(); } catch(IOException ignored) {}
+ }
+ } else {
+ newItemAddMap.put(internalname, System.currentTimeMillis());
+ }
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent(priority= EventPriority.HIGHEST)
+ public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre 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) &&
+ Minecraft.getMinecraft().currentScreen instanceof GuiContainer && neu.overlay.isUsingMobsFilter()) {
+ event.setCanceled(true);
+ }
+ long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis);
+ if(event.type == RenderGameOverlayEvent.ElementType.ALL) {
+ DungeonWin.render(event.partialTicks);
+ }
+ if(event.type == RenderGameOverlayEvent.ElementType.ALL &&
+ timeRemaining > 0 && notificationLines != null && notificationLines.size() > 0) {
+ int width = 0;
+ int height = notificationLines.size()*10+10;
+
+ for(String line : notificationLines) {
+ int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line) + 8;
+ if(len > width) {
+ width = len;
+ }
+ }
+
+ ScaledResolution sr = Utils.pushGuiScale(2);
+
+ int midX = sr.getScaledWidth()/2;
+ int topY = sr.getScaledHeight()*3/4-height/2;
+ Gui.drawRect(midX-width/2, sr.getScaledHeight()*3/4-height/2,
+ midX+width/2, sr.getScaledHeight()*3/4+height/2, 0xFF3C3C3C);
+ Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2,
+ midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);
+
+ Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining/1000)+"s", midX-width/2+3,
+ topY+3, 0xFF000000, false);
+
+ Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj,
+ midX, topY+4+5, false, -1);
+ for(int i=1; i<notificationLines.size(); i++) {
+ String line = notificationLines.get(i);
+ Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj,
+ midX, topY+4+5+2+i*10, false, -1);
+ }
+
+ Utils.pushGuiScale(-1);
+ }
+ }
+
+ /**
+ * When opening a GuiContainer, will reset the overlay and load the config.
+ * When closing a GuiContainer, will save the config.
+ * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI.
+ */
+ AtomicBoolean missingRecipe = new AtomicBoolean(false);
+ @SubscribeEvent
+ public void onGuiOpen(GuiOpenEvent event) {
+ neu.manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis();
+ BetterContainers.reset();
+
+ if(event.gui == null && neu.manager.auctionManager.customAH.isRenderOverAuctionView() &&
+ !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
+ event.gui = new CustomAHGui();
+ }
+
+ if(!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) {
+ neu.manager.auctionManager.customAH.setRenderOverAuctionView(false);
+ } else if(event.gui instanceof GuiChest && (neu.manager.auctionManager.customAH.isRenderOverAuctionView() ||
+ Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)){
+ GuiChest chest = (GuiChest) event.gui;
+ ContainerChest container = (ContainerChest) chest.inventorySlots;
+ String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ neu.manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") ||
+ containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid") ||
+ containerName.trim().equals("Confirm Purchase"));
+ }
+
+ //OPEN
+ if(Minecraft.getMinecraft().currentScreen == null
+ && event.gui instanceof GuiContainer) {
+ neu.overlay.reset();
+ neu.manager.loadConfig();
+ }
+ //CLOSE
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer
+ && event.gui == null) {
+ try {
+ neu.manager.saveConfig();
+ } catch(IOException e) {}
+ }
+ if(event.gui != null && neu.manager.config.dev.value) {
+ if(event.gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+ ses.schedule(() -> {
+ if(Minecraft.getMinecraft().currentScreen != event.gui) {
+ return;
+ }
+ if(lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ try {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = neu.manager.getInternalNameForItem(res);
+
+ if(lower.getStackInSlot(48) != null) {
+ String backName = null;
+ NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound();
+ if(tag.hasKey("display", 10)) {
+ NBTTagCompound nbttagcompound = tag.getCompoundTag("display");
+ if(nbttagcompound.getTagId("Lore") == 9){
+ NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8);
+ backName = nbttaglist1.getStringTagAt(0);
+ }
+ }
+
+ if(backName != null) {
+ String[] split = backName.split(" ");
+ if(split[split.length-1].contains("Rewards")) {
+ String col = backName.substring(split[0].length()+1,
+ backName.length()-split[split.length-1].length()-1);
+
+ JsonObject json = neu.manager.getItemInformation().get(resInternalname);
+ json.addProperty("crafttext", "Requires: " + col);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ neu.manager.writeJsonDefaultDir(json, resInternalname+".json");
+ neu.manager.loadItem(resInternalname);
+ }
+ }
+ }
+
+ /*JsonArray arr = null;
+ File f = new File(neu.manager.configLocation, "missing.json");
+ try(InputStream instream = new FileInputStream(f)) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
+ JsonObject json = neu.manager.gson.fromJson(reader, JsonObject.class);
+ arr = json.getAsJsonArray("missing");
+ } catch(IOException e) {}
+ try {
+ JsonObject json = new JsonObject();
+ JsonArray newArr = new JsonArray();
+ for(JsonElement e : arr) {
+ if(!e.getAsString().equals(resInternalname)) {
+ newArr.add(e);
+ }
+ }
+ json.add("missing", newArr);
+ neu.manager.writeJson(json, f);
+ } catch(IOException e) {}*/
+
+
+
+ /*JsonObject recipe = new JsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+
+ for(int i=0; i<=18; i+=9) {
+ for(int j=0; j<3; j++) {
+ ItemStack stack = lower.getStackInSlot(10+i+j);
+ String internalname = "";
+ if(stack != null) {
+ internalname = neu.manager.getInternalNameForItem(stack);
+ if(!neu.manager.getItemInformation().containsKey(internalname)) {
+ neu.manager.writeItemToFile(stack);
+ }
+ internalname += ":"+stack.stackSize;
+ }
+ recipe.addProperty(y[i/9]+x[j], internalname);
+ }
+ }
+
+ JsonObject json = neu.manager.getJsonForItem(res);
+ json.add("recipe", recipe);
+ json.addProperty("internalname", resInternalname);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ neu.manager.writeJsonDefaultDir(json, resInternalname+".json");
+ neu.manager.loadItem(resInternalname);*/
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }, 200, TimeUnit.MILLISECONDS);
+ return;
+ }
+ }
+ }
+
+ /**
+ * 1) When receiving "You are playing on profile" messages, will set the current profile.
+ * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI)
+ * 3) Replaces lobby join notifications when streamer mode is active
+ */
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onGuiChat(ClientChatReceivedEvent e) {
+ DungeonWin.onChatMessage(e);
+
+ String r = null;
+ String unformatted = Utils.cleanColour(e.message.getUnformattedText());
+ if(unformatted.startsWith("You are playing on profile: ")) {
+ neu.manager.setCurrentProfile(unformatted.substring("You are playing on profile: ".length()).split(" ")[0].trim());
+ } else if(unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to:
+ neu.manager.setCurrentProfile(unformatted.substring("Your profile was changed to: ".length()).split(" ")[0].trim());
+ } else if(unformatted.startsWith("Your new API key is ")) {
+ neu.manager.config.apiKey.value = unformatted.substring("Your new API key is ".length());
+ try { neu.manager.saveConfig(); } catch(IOException ioe) {}
+ }
+ if(e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString()+
+ EnumChatFormatting.RED+"You haven't unlocked this recipe!"+EnumChatFormatting.RESET)) {
+ r = EnumChatFormatting.RED+"You haven't unlocked this recipe!";
+ } else if(e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString()+
+ EnumChatFormatting.RED+"Invalid recipe ")) {
+ r = "";
+ }
+ if(e.message.getFormattedText().contains(EnumChatFormatting.YELLOW+"Visit the Auction House to collect your item!")) {
+ if(NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid != null &&
+ System.currentTimeMillis() - NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBidMillis < 5000) {
+ NotEnoughUpdates.INSTANCE.sendChatMessage("/viewauction " +
+ NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.niceAucId(
+ NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.latestBid));
+ }
+ }
+ if(r != null) {
+ if(neu.manager.failViewItem(r)) {
+ e.setCanceled(true);
+ }
+ missingRecipe.set(true);
+ }
+ //System.out.println(e.message);
+ if(unformatted.startsWith("Sending to server") &&
+ neu.isOnSkyblock() && neu.manager.config.streamerMode.value && e.message instanceof ChatComponentText) {
+ String m = e.message.getFormattedText();
+ String m2 = StreamerMode.filterChat(e.message.getFormattedText());
+ if(!m.equals(m2)) {
+ e.message = new ChatComponentText(m2);
+ }
+ }
+ }
+
+ /**
+ * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
+ * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
+ *
+ * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI)
+ * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv)
+ *
+ * All of this only matters if players are using gui scale auto which may result in the inventory being drawn
+ * over the various panes.
+ * @param event
+ */
+ @SubscribeEvent
+ public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
+ if((shouldRenderOverlay(event.gui) || event.gui instanceof CustomAHGui) && neu.isOnSkyblock()) {
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledresolution.getScaledWidth();
+
+ boolean hoverPane = event.getMouseX() < width*neu.overlay.getInfoPaneOffsetFactor() ||
+ event.getMouseX() > width*neu.overlay.getItemPaneOffsetFactor();
+
+ if(event.gui instanceof GuiContainer) {
+ try {
+ int xSize = (int) Utils.getField(GuiContainer.class, event.gui, "xSize", "field_146999_f");
+ int ySize = (int) Utils.getField(GuiContainer.class, event.gui, "ySize", "field_147000_g");
+ int guiLeft = (int) Utils.getField(GuiContainer.class, event.gui, "guiLeft", "field_147003_i");
+ int guiTop = (int) Utils.getField(GuiContainer.class, event.gui, "guiTop", "field_147009_r");
+
+ hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize &&
+ event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize;
+
+ if(hoverPane) {
+ if(!hoverInv) focusInv = false;
+ } else {
+ focusInv = true;
+ }
+ } catch(NullPointerException npe) {
+ npe.printStackTrace();
+ focusInv = !hoverPane;
+ }
+ }
+ if(event.gui instanceof GuiItemRecipe) {
+ GuiItemRecipe guiItemRecipe = ((GuiItemRecipe)event.gui);
+ hoverInv = event.getMouseX() > guiItemRecipe.guiLeft && event.getMouseX() < guiItemRecipe.guiLeft + guiItemRecipe.xSize &&
+ event.getMouseY() > guiItemRecipe.guiTop && event.getMouseY() < guiItemRecipe.guiTop + guiItemRecipe.ySize;
+
+ if(hoverPane) {
+ if(!hoverInv) focusInv = false;
+ } else {
+ focusInv = true;
+ }
+ }
+ if(focusInv) {
+ try {
+ neu.overlay.render(hoverInv && focusInv);
+ } catch(ConcurrentModificationException e) {e.printStackTrace();}
+ GL11.glTranslatef(0, 0, 10);
+ }
+ }
+
+ if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ renderDungeonChestOverlay(event.gui);
+ if(neu.manager.config.accessoryBagOverlay.value) {
+ AccessoryBagOverlay.renderOverlay();
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
+ if(TradeWindow.tradeWindowActive() ||
+ event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ event.setCanceled(true);
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ //Dark background
+ Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
+
+ if(event.mouseX < width*neu.overlay.getWidthMult()/3 || event.mouseX > width-width*neu.overlay.getWidthMult()/3) {
+ if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
+ neu.overlay.render(false);
+ } else {
+ neu.overlay.render(false);
+ if(event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
+ } else {
+ TradeWindow.render(event.mouseX, event.mouseY);
+ }
+ }
+ }
+ }
+
+ 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))
+ * @param event
+ */
+ @SubscribeEvent
+ public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
+ if(!(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView())) {
+ if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ if(!focusInv) {
+ GL11.glTranslatef(0, 0, 300);
+ neu.overlay.render(hoverInv && focusInv);
+ GL11.glTranslatef(0, 0, -300);
+ }
+ neu.overlay.renderOverlay();
+ }
+ }
+ }
+
+ private void renderDungeonChestOverlay(GuiScreen gui) {
+ if(gui instanceof GuiChest && !neu.manager.config.dungeonProfitLore.value) {
+ try {
+ int xSize = (int) Utils.getField(GuiContainer.class, gui, "xSize", "field_146999_f");
+ int ySize = (int) Utils.getField(GuiContainer.class, gui, "ySize", "field_147000_g");
+ int guiLeft = (int) Utils.getField(GuiContainer.class, gui, "guiLeft", "field_147003_i");
+ int guiTop = (int) Utils.getField(GuiContainer.class, gui, "guiTop", "field_147009_r");
+
+ GuiChest eventGui = (GuiChest) gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ ItemStack rewardChest = lower.getStackInSlot(31);
+ if (rewardChest != null && rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN+"Open Reward Chest")) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth);
+ GL11.glColor4f(1, 1, 1, 1);
+ GlStateManager.disableLighting();
+ Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 71, 0, 180/256f, 0, 71/256f, GL11.GL_NEAREST);
+
+ int chestCost = 0;
+ String line6 = Utils.cleanColour(neu.manager.getLoreFromNBT(rewardChest.getTagCompound())[6]);
+ StringBuilder cost = new StringBuilder();
+ for(int i=0; i<line6.length(); i++) {
+ char c = line6.charAt(i);
+ if("0123456789".indexOf(c) >= 0) {
+ cost.append(c);
+ }
+ }
+ if(cost.length() > 0) {
+ chestCost = Integer.parseInt(cost.toString());
+ }
+
+ boolean missing = false;
+ int totalValueBIN = 0;
+ int totalValueAUC = 0;
+ for(int i=0; i<5; i++) {
+ ItemStack item = lower.getStackInSlot(11+i);
+ String internal = neu.manager.getInternalNameForItem(item);
+ if(internal != null) {
+ float bazaarPrice = -1;
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internal);
+ if(bazaarInfo != null && bazaarInfo.has("avg_sell")) {
+ bazaarPrice = bazaarInfo.get("avg_sell").getAsFloat();
+ }
+
+ float worthBIN = -1;
+ float worthAUC = -1;
+
+ if(bazaarPrice > 0) {
+ worthBIN = bazaarPrice;
+ worthAUC = bazaarPrice;
+ } else {
+ worthBIN = neu.manager.auctionManager.getLowestBin(internal);
+ JsonObject aucInfo = neu.manager.auctionManager.getItemAuctionInfo(internal);
+ if(aucInfo != null) {
+ worthAUC = aucInfo.get("price").getAsFloat();
+ }
+ }
+
+ if(worthAUC <= 0 && worthBIN <= 0) {
+ missing = true;
+ break;
+ }
+
+ if(worthBIN > 0 && totalValueBIN >= 0) {
+ totalValueBIN += worthBIN;
+ } else {
+ totalValueBIN = -1;
+ }
+
+ if(worthAUC > 0 && totalValueAUC >= 0) {
+ totalValueAUC += worthAUC;
+ } else {
+ totalValueAUC = -1;
+ }
+ }
+ }
+ if(totalValueAUC <= 0 && totalValueBIN <= 0) {
+ missing = true;
+ }
+
+ if(missing) {
+ drawStringShadow(EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!",
+ guiLeft+xSize+4+90, guiTop+14, 170);
+ } else {
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+ String valueStringBIN = EnumChatFormatting.YELLOW+"Value (BIN): " + EnumChatFormatting.GOLD
+ + EnumChatFormatting.BOLD + format.format(totalValueBIN) + " coins";
+ String valueStringAUC = EnumChatFormatting.YELLOW+"Value (AUC): " + EnumChatFormatting.GOLD
+ + EnumChatFormatting.BOLD + format.format(totalValueAUC) + " coins";
+
+
+ int profitLossBIN = totalValueBIN - chestCost;
+ String plStringBIN;
+ if(profitLossBIN >= 0) {
+ plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN
+ + EnumChatFormatting.BOLD + "+" + format.format(profitLossBIN) + " coins";
+ } else {
+ plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED
+ + EnumChatFormatting.BOLD + "-" + format.format(-profitLossBIN) + " coins";
+ }
+
+ int profitLossAUC = totalValueAUC - chestCost;
+ String plStringAUC;
+ if(profitLossAUC >= 0) {
+ plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN
+ + EnumChatFormatting.BOLD + "+" + format.format(profitLossAUC) + " coins";
+ } else {
+ plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED
+ + EnumChatFormatting.BOLD + "-" + format.format(-profitLossAUC) + " coins";
+ }
+
+ drawStringShadow(valueStringBIN, guiLeft+xSize+4+90,
+ guiTop+14, 170);
+ drawStringShadow(plStringBIN, guiLeft+xSize+4+90,
+ guiTop+26, 170);
+
+ drawStringShadow(valueStringAUC, guiLeft+xSize+4+90,
+ guiTop+44, 170);
+ drawStringShadow(plStringAUC, guiLeft+xSize+4+90,
+ guiTop+56, 170);
+ }
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void drawStringShadow(String str, float x, float y, int len) {
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str),
+ Minecraft.getMinecraft().fontRendererObj,
+ x+xOff/2f, y+yOff/2f, false, len,
+ new Color(20, 20, 20, 100/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB());
+ }
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth(str,
+ Minecraft.getMinecraft().fontRendererObj,
+ x, y, false, len,
+ new Color(64, 64, 64, 255).getRGB());
+ }
+
+ /**
+ * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused.
+ * Will also cancel the event if if NEUOverlay#mouseInput returns true.
+ * @param event
+ */
+ @SubscribeEvent
+ public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
+ if(!event.isCanceled()) {
+ Utils.scrollTooltip(Mouse.getEventDWheel());
+ }
+ if(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ event.setCanceled(true);
+ if(event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ neu.manager.auctionManager.customAH.handleMouseInput();
+ } else {
+ TradeWindow.handleMouseInput();
+ }
+ neu.overlay.mouseInput();
+ return;
+ }
+ if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ if(!neu.manager.config.accessoryBagOverlay.value || !AccessoryBagOverlay.mouseClick()) {
+ if(!(hoverInv && focusInv)) {
+ if(neu.overlay.mouseInput()) {
+ event.setCanceled(true);
+ }
+ } else {
+ neu.overlay.mouseInputInv();
+ }
+ }
+ }
+ }
+
+ ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+
+ /**
+ * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true.
+ * Also includes a dev function used for creating custom named json files with recipes.
+ */
+ @SubscribeEvent
+ public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
+ if(TradeWindow.tradeWindowActive() || event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(event.gui instanceof CustomAHGui ||
+ neu.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ if(neu.manager.auctionManager.customAH.keyboardInput()) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ } else if(neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ } else {
+ TradeWindow.keyboardInput();
+ if(Keyboard.getEventKey() != Keyboard.KEY_ESCAPE) {
+ event.setCanceled(true);
+ Minecraft.getMinecraft().dispatchKeypresses();
+ neu.overlay.keyboardInput(focusInv);
+ }
+ }
+ return;
+ }
+
+ if(shouldRenderOverlay(event.gui) && neu.isOnSkyblock()) {
+ if(neu.overlay.keyboardInput(focusInv)) {
+ event.setCanceled(true);
+ }
+ }
+ if(neu.manager.config.dev.value && neu.manager.config.enableItemEditing.value && Minecraft.getMinecraft().theWorld != null &&
+ Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) {
+ GuiScreen gui = Minecraft.getMinecraft().currentScreen;
+ if(gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) event.gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ if(lower.getStackInSlot(23) != null &&
+ lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
+ ItemStack res = lower.getStackInSlot(25);
+ String resInternalname = neu.manager.getInternalNameForItem(res);
+ JTextField tf = new JTextField();
+ tf.setText(resInternalname);
+ tf.addAncestorListener(new RequestFocusListener());
+ JOptionPane.showOptionDialog(null,
+ tf,
+ "Enter Name:",
+ JOptionPane.NO_OPTION,
+ JOptionPane.PLAIN_MESSAGE,
+ null, new String[]{"Enter"}, "Enter");
+ resInternalname = tf.getText();
+ if(resInternalname.trim().length() == 0) {
+ return;
+ }
+
+ JsonObject recipe = new JsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+
+ for(int i=0; i<=18; i+=9) {
+ for(int j=0; j<3; j++) {
+ ItemStack stack = lower.getStackInSlot(10+i+j);
+ String internalname = "";
+ if(stack != null) {
+ internalname = neu.manager.getInternalNameForItem(stack);
+ if(!neu.manager.getItemInformation().containsKey(internalname)) {
+ neu.manager.writeItemToFile(stack);
+ }
+ internalname += ":"+stack.stackSize;
+ }
+ recipe.addProperty(y[i/9]+x[j], internalname);
+ }
+ }
+
+ JsonObject json = neu.manager.getJsonForItem(res);
+ json.add("recipe", recipe);
+ json.addProperty("internalname", resInternalname);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
+ neu.manager.writeJsonDefaultDir(json, resInternalname+".json");
+ neu.manager.loadItem(resInternalname);
+ } catch(IOException e) {}
+ }
+ }
+ }
+ /*if(Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_RBRACKET && Keyboard.getEventKeyState()) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ started = true;
+ final Object[] items = neu.manager.getItemInformation().values().toArray();
+ AtomicInteger i = new AtomicInteger(0);
+
+ Runnable checker = new Runnable() {
+ @Override
+ public void run() {
+ int in = i.getAndIncrement();
+ /*if(missingRecipe.get()) {
+ String internalname = ((JsonObject)items[in]).get("internalname").getAsString();
+
+ JsonArray arr = null;
+ File f = new File(neu.manager.configLocation, "missing.json");
+ try(InputStream instream = new FileInputStream(f)) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
+ JsonObject json = neu.manager.gson.fromJson(reader, JsonObject.class);
+ arr = json.getAsJsonArray("missing");
+ } catch(IOException e) {}
+
+ try {
+ JsonObject json = new JsonObject();
+ if(arr == null) arr = new JsonArray();
+ arr.add(new JsonPrimitive(internalname));
+ json.add("missing", arr);
+ neu.manager.writeJson(json, f);
+ } catch(IOException e) {}
+ }
+ missingRecipe.set(false);
+
+ ses.schedule(() -> {
+ int index = i.get();
+ JsonObject o = (JsonObject)items[index];
+ if(Minecraft.getMinecraft().currentScreen != null) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ }
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
+
+ ses.schedule(this, 1000, TimeUnit.MILLISECONDS);
+ }, 100, TimeUnit.MILLISECONDS);
+ }
+ };
+
+ int index = i.get();
+ JsonObject o = (JsonObject)items[index];
+ if(Minecraft.getMinecraft().currentScreen != null) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ }
+ Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
+
+ ses.schedule(checker, 1000, TimeUnit.MILLISECONDS);
+ }*/
+ }
+
+ private static String[] rarityArrC = new String[] {
+ EnumChatFormatting.WHITE+EnumChatFormatting.BOLD.toString()+"COMMON",
+ EnumChatFormatting.GREEN+EnumChatFormatting.BOLD.toString()+"UNCOMMON",
+ EnumChatFormatting.BLUE+EnumChatFormatting.BOLD.toString()+"RARE",
+ EnumChatFormatting.DARK_PURPLE+EnumChatFormatting.BOLD.toString()+"EPIC",
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD.toString()+"LEGENDARY",
+ EnumChatFormatting.LIGHT_PURPLE+EnumChatFormatting.BOLD.toString()+"MYTHIC",
+ EnumChatFormatting.RED+EnumChatFormatting.BOLD.toString()+"SPECIAL",
+ EnumChatFormatting.RED+EnumChatFormatting.BOLD.toString()+"VERY SPECIAL",
+ EnumChatFormatting.DARK_RED+EnumChatFormatting.BOLD.toString()+"SUPREME",
+ };
+ @SubscribeEvent(priority = EventPriority.LOW)
+ public void onItemTooltipLow(ItemTooltipEvent event) {
+ if(!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return;
+
+ boolean hasEnchantments = event.itemStack.hasTagCompound() && event.itemStack.getTagCompound().hasKey("ExtraAttributes", 10) &&
+ event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").hasKey("enchantments", 10);
+ Set<String> enchantIds = new HashSet<>();
+ if(hasEnchantments) enchantIds = event.itemStack.getTagCompound().getCompoundTag("ExtraAttributes").getCompoundTag("enchantments").getKeySet();
+
+ JsonObject enchantsConst = Constants.ENCHANTS;
+ JsonArray allItemEnchs = null;
+ Set<String> ignoreFromPool = new HashSet<>();
+ if(enchantsConst != null && hasEnchantments && NotEnoughUpdates.INSTANCE.manager.config.missingEnchantList.value) {
+ try {
+ JsonArray enchantPools = enchantsConst.get("enchant_pools").getAsJsonArray();
+ for(JsonElement element : enchantPools) {
+ Set<String> currentPool = new HashSet<>();
+ for(JsonElement poolElement : element.getAsJsonArray()) {
+ String poolS = poolElement.getAsString();
+ currentPool.add(poolS);
+ }
+ for(JsonElement poolElement : element.getAsJsonArray()) {
+ String poolS = poolElement.getAsString();
+ if(enchantIds.contains(poolS)) {
+ ignoreFromPool.addAll(currentPool);
+ break;
+ }
+ }
+ }
+
+ JsonObject enchantsObj = enchantsConst.get("enchants").getAsJsonObject();
+ NBTTagCompound tag = event.itemStack.getTagCompound();
+ if(tag != null) {
+ NBTTagCompound display = tag.getCompoundTag("display");
+ if (display.hasKey("Lore", 9)) {
+ NBTTagList list = display.getTagList("Lore", 8);
+ out:
+ for (int i = list.tagCount(); i >= 0; i--) {
+ String line = list.getStringTagAt(i);
+ for(int j=0; j<rarityArrC.length; j++) {
+ for(Map.Entry<String, JsonElement> entry : enchantsObj.entrySet()) {
+ if(line.contains(rarityArrC[j] + " " + entry.getKey()) || line.contains(rarityArrC[j] + " DUNGEON " + entry.getKey())) {
+ allItemEnchs = entry.getValue().getAsJsonArray();
+ break out;
+ }
+ }
+ }
+ }
+ }
+ }
+ } catch(Exception e) {}
+ }
+
+ boolean gotToEnchants = false;
+ boolean passedEnchants = false;
+
+ boolean dungeonProfit = false;
+ int index = 0;
+ List<String> newTooltip = new ArrayList<>();
+ for(String line : event.toolTip) {
+ if(line.contains("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune")) {
+ line = line.replace("\u00A7cR\u00A76a\u00A7ei\u00A7an\u00A7bb\u00A79o\u00A7dw\u00A79 Rune",
+ Utils.chromaString("Rainbow Rune", index, false)+EnumChatFormatting.BLUE);
+ } else if(hasEnchantments) {
+ if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && NotEnoughUpdates.INSTANCE.manager.config.missingEnchantList.value) {
+ boolean lineHasEnch = false;
+ for(String s : enchantIds) {
+ String enchantName = WordUtils.capitalizeFully(s.replace("_", " "));
+ if(line.contains(enchantName)) {
+ lineHasEnch = true;
+ break;
+ }
+ }
+ if(lineHasEnch) {
+ gotToEnchants = true;
+ } else {
+ if(gotToEnchants && !passedEnchants && Utils.cleanColour(line).trim().length() == 0) {
+ if(enchantsConst != null && allItemEnchs != null) {
+ List<String> missing = new ArrayList<>();
+ for(JsonElement enchIdElement : allItemEnchs) {
+ String enchId = enchIdElement.getAsString();
+ if(!enchId.startsWith("ultimate_") && !ignoreFromPool.contains(enchId) && !enchantIds.contains(enchId)) {
+ missing.add(enchId);
+ }
+ }
+ newTooltip.add("");
+ StringBuilder currentLine = new StringBuilder(EnumChatFormatting.RED+"Missing: "+EnumChatFormatting.GRAY);
+ for(int i=0; i<missing.size(); i++) {
+ String enchName = WordUtils.capitalizeFully(missing.get(i).replace("_", " "));
+ if(currentLine.length() != 0 && (Utils.cleanColour(currentLine.toString()).length() + enchName.length()) > 40) {
+ newTooltip.add(currentLine.toString());
+ currentLine = new StringBuilder();
+ }
+ if(currentLine.length() != 0 && i != 0) {
+ currentLine.append(", ").append(enchName);
+ } else {
+ currentLine.append(EnumChatFormatting.GRAY).append(enchName);
+ }
+ }
+ if(currentLine.length() != 0) {
+ newTooltip.add(currentLine.toString());
+ }
+ }
+ passedEnchants = true;
+ }
+ }
+ }
+ for(String op : neu.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;
+
+ 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 {
+ pattern = Pattern.compile("(\\u00A79|\\u00A79\\u00A7d\\u00A7l)("+enchantName+") " +
+ "([0-9]+|(I|II|III|IV|V|VI|VII|VIII|IX|X|XI|XII|XIII|XIV|XV|XVI|XVII|XVIII|XIX|XX))(,|$)");
+ } catch(Exception e) {continue;} //malformed regex
+ Matcher matcher = pattern.matcher(line);
+ int matchCount = 0;
+ while(matcher.find() && matchCount < 5) {
+ if(Utils.cleanColour(matcher.group(2)).startsWith(" ")) continue;
+
+ matchCount++;
+ int level = -1;
+ String levelStr = matcher.group(matcher.groupCount()-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;
+ case "XI":
+ level = 11; break;
+ case "XII":
+ level = 12; break;
+ case "XIII":
+ level = 13; break;
+ case "XIV":
+ level = 14; break;
+ case "XV":
+ level = 15; break;
+ case "XVI":
+ level = 16; break;
+ case "XVII":
+ level = 17; break;
+ case "XVIII":
+ level = 18; break;
+ case "XIX":
+ level = 19; break;
+ case "XX":
+ level = 20; break;
+ }
+ }
+ boolean matches = false;
+ if(level > 0) {
+ switch(comparator) {
+ case ">":
+ matches = level > levelToFind; break;
+ case "=":
+ matches = level == levelToFind; break;
+ case "<":
+ matches = level < levelToFind; break;
+ }
+ }
+ if(matches) {
+ if(!colourCode.equals("z")) {
+ line = line.replace("\u00A79"+matcher.group(2), "\u00A7"+colourCode+matcher.group(2));
+ line = line.replace("\u00A79\u00A7d\u00A7l"+matcher.group(2), "\u00A7"+colourCode+
+ EnumChatFormatting.BOLD+matcher.group(2));
+ } else {
+ int offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
+ "\\u00A79"+matcher.group(2)+".*", ""));
+ line = line.replace("\u00A79"+matcher.group(2), Utils.chromaString(matcher.group(2), offset/12f+index, false));
+
+ offset = Minecraft.getMinecraft().fontRendererObj.getStringWidth(line.replaceAll(
+ "\\u00A79\\u00A7d\\u00A7l"+matcher.group(2)+".*", ""));
+ line = line.replace("\u00A79\u00A7d\u00A7l"+matcher.group(2), Utils.chromaString(matcher.group(2),
+ offset/12f+index, true));
+ }
+ }
+ }
+ }
+ }
+
+ newTooltip.add(line);
+
+ if(neu.manager.config.auctionPriceInfo.value) {
+ if(line.contains(EnumChatFormatting.GRAY+"Buy it now: ") ||
+ line.contains(EnumChatFormatting.GRAY+"Bidder: ") ||
+ line.contains(EnumChatFormatting.GRAY+"Starting bid: ")) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
+ if(internalname != null) {
+ newTooltip.add("");
+ if(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ newTooltip.add(EnumChatFormatting.GRAY+"[SHIFT for Price Info]");
+ } else {
+ JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
+
+ boolean hasAuctionPrice = auctionInfo != null;
+
+ int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
+
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+ APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname);
+
+ if(lowestBin > 0) {
+ newTooltip.add(EnumChatFormatting.GRAY+"Lowest BIN: "+
+ EnumChatFormatting.GOLD+format.format(lowestBin)+" coins");
+ }
+ if(hasAuctionPrice) {
+ int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ newTooltip.add(EnumChatFormatting.GRAY+"AH Price: "+
+ EnumChatFormatting.GOLD+format.format(auctionPrice)+" coins");
+ newTooltip.add(EnumChatFormatting.GRAY+"AH Sales: "+
+ EnumChatFormatting.GOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day");
+ if(auctionInfo.has("clean_price")) {
+ newTooltip.add(EnumChatFormatting.GRAY+"AH Price (Clean): "+
+ EnumChatFormatting.GOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins");
+ newTooltip.add(EnumChatFormatting.GRAY+"AH Sales (Clean): "+
+ EnumChatFormatting.GOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day");
+ }
+
+ }
+ if(craftCost.fromRecipe) {
+ newTooltip.add(EnumChatFormatting.GRAY+"Raw Craft Cost: "+
+ EnumChatFormatting.GOLD+format.format((int)craftCost.craftCost)+" coins");
+ }
+ }
+ }
+ }
+ }
+
+ if(neu.manager.config.dungeonProfitLore.value && Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
+ if(line.contains(EnumChatFormatting.GREEN+"Open Reward Chest")) {
+ dungeonProfit = true;
+ } else if(index == 7 && dungeonProfit) {
+ GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ IInventory lower = cc.getLowerChestInventory();
+
+ int chestCost = 0;
+ String line6 = Utils.cleanColour(line);
+ StringBuilder cost = new StringBuilder();
+ for(int i=0; i<line6.length(); i++) {
+ char c = line6.charAt(i);
+ if("0123456789".indexOf(c) >= 0) {
+ cost.append(c);
+ }
+ }
+ if(cost.length() > 0) {
+ chestCost = Integer.parseInt(cost.toString());
+ }
+
+ boolean missing = false;
+ int totalValueBIN = 0;
+ int totalValueAUC = 0;
+ for(int i=0; i<5; i++) {
+ ItemStack item = lower.getStackInSlot(11+i);
+ String internal = neu.manager.getInternalNameForItem(item);
+ if(internal != null) {
+ float worthBIN = neu.manager.auctionManager.getLowestBin(internal);
+ float worthAUC = neu.manager.auctionManager.getLowestBin(internal);
+
+ if(worthAUC == -1) worthAUC = neu.manager.auctionManager.getCraftCost(internal).craftCost;
+
+ if(worthAUC <= 0 && worthBIN <= 0) {
+ missing = true;
+ break;
+ }
+
+ if(worthBIN > 0 && totalValueBIN >= 0) {
+ totalValueBIN += worthBIN;
+ } else {
+ totalValueBIN = -1;
+ }
+
+ if(worthAUC > 0 && totalValueAUC >= 0) {
+ totalValueAUC += worthAUC;
+ } else {
+ totalValueAUC = -1;
+ }
+ }
+ }
+ if(totalValueAUC <= 0 && totalValueBIN <= 0) {
+ missing = true;
+ }
+
+ String neu = EnumChatFormatting.YELLOW + "[NEU] ";
+ if(missing) {
+ newTooltip.add(neu + EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!");
+ } else {
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+ String valueStringBIN = EnumChatFormatting.YELLOW+"Value (BIN): " + EnumChatFormatting.GOLD
+ + EnumChatFormatting.BOLD + format.format(totalValueBIN) + " coins";
+ String valueStringAUC = EnumChatFormatting.YELLOW+"Value (AUC): " + EnumChatFormatting.GOLD
+ + EnumChatFormatting.BOLD + format.format(totalValueAUC) + " coins";
+
+
+ int profitLossBIN = totalValueBIN - chestCost;
+ String plStringBIN;
+ if(profitLossBIN >= 0) {
+ plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN
+ + EnumChatFormatting.BOLD + "+" + format.format(profitLossBIN) + " coins";
+ } else {
+ plStringBIN = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED
+ + EnumChatFormatting.BOLD + "-" + format.format(-profitLossBIN) + " coins";
+ }
+
+ int profitLossAUC = totalValueAUC - chestCost;
+ String plStringAUC;
+ if(profitLossAUC >= 0) {
+ plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.DARK_GREEN
+ + EnumChatFormatting.BOLD + "+" + format.format(profitLossAUC) + " coins";
+ } else {
+ plStringAUC = EnumChatFormatting.YELLOW+"Profit/Loss: " + EnumChatFormatting.RED
+ + EnumChatFormatting.BOLD + "-" + format.format(-profitLossAUC) + " coins";
+ }
+
+ newTooltip.add(neu + valueStringBIN);
+ newTooltip.add(neu + plStringBIN);
+ newTooltip.add(neu + valueStringAUC);
+ newTooltip.add(neu + plStringAUC);
+ }
+ }
+ }
+
+ index++;
+ }
+
+ event.toolTip.clear();
+ event.toolTip.addAll(newTooltip);
+
+ if(neu.manager.config.invAuctionPrice.value || neu.manager.config.invBazaarPrice.value) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(event.itemStack);
+
+ if(internalname != null) {
+ JsonObject auctionInfo = neu.manager.auctionManager.getItemAuctionInfo(internalname);
+ JsonObject bazaarInfo = neu.manager.auctionManager.getBazaarInfo(internalname);
+
+ int lowestBin = neu.manager.auctionManager.getLowestBin(internalname);
+ APIManager.CraftInfo craftCost = neu.manager.auctionManager.getCraftCost(internalname);
+
+ boolean hasAuctionPrice = neu.manager.config.invAuctionPrice.value && auctionInfo != null;
+ boolean hasBazaarPrice = neu.manager.config.invBazaarPrice.value && bazaarInfo != null;
+ boolean hasLowestBinPrice = neu.manager.config.invAuctionPrice.value && lowestBin > 0;
+
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+
+ if(hasAuctionPrice || hasBazaarPrice || hasLowestBinPrice) event.toolTip.add("");
+ if(hasLowestBinPrice) {
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins");
+ }
+ if(hasAuctionPrice) {
+ int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins");
+ if(neu.manager.config.advancedPriceInfo.value) {
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day");
+ }
+ if(auctionInfo.has("clean_price")) {
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins");
+ if(neu.manager.config.advancedPriceInfo.value) {
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day");
+ }
+ }
+ } else if(hasBazaarPrice) {
+ int stackMultiplier = 1;
+ int shiftStackMultiplier = event.itemStack.stackSize > 1 ? event.itemStack.stackSize : 64;
+ if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ stackMultiplier = shiftStackMultiplier;
+ } else {
+ event.toolTip.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]");
+ }
+ if(bazaarInfo.has("avg_buy")) {
+ int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat()*stackMultiplier;
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins");
+ }
+ if(bazaarInfo.has("avg_sell")) {
+ int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat()*stackMultiplier;
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins");
+ }
+ if(neu.manager.config.advancedPriceInfo.value) {
+ if(bazaarInfo.has("curr_buy")) {
+ int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat()*stackMultiplier;
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins");
+ }
+ if(bazaarInfo.has("curr_sell")) {
+ int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat()*stackMultiplier;
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins");
+ }
+ }
+ }
+ if((hasAuctionPrice || hasBazaarPrice) && craftCost.fromRecipe) {
+ event.toolTip.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins");
+ }
+ }
+ }
+ }
+
+ /**
+ * This makes it so that holding LCONTROL while hovering over an item with NBT will show the NBT of the item.
+ * @param event
+ */
+ @SubscribeEvent
+ public void onItemTooltip(ItemTooltipEvent event) {
+ if(!neu.isOnSkyblock()) return;
+ if(neu.manager.config.hideEmptyPanes.value &&
+ event.itemStack.getItem().equals(Item.getItemFromBlock(Blocks.stained_glass_pane))) {
+ String first = Utils.cleanColour(event.toolTip.get(0));
+ first = first.replaceAll("\\(.*\\)", "").trim();
+ if(first.length() == 0) {
+ event.toolTip.clear();
+ }
+ }
+ //AH prices
+ /*if(Minecraft.getMinecraft().currentScreen != null) {
+ 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.trim().equals("Auctions Browser")) {
+ String internalname = neu.manager.getInternalNameForItem(event.itemStack);
+ if(internalname != null) {
+ for(int i=0; i<event.toolTip.size(); i++) {
+ String line = event.toolTip.get(i);
+ if(line.contains(EnumChatFormatting.GRAY + "Bidder: ") ||
+ line.contains(EnumChatFormatting.GRAY + "Starting bid: ") ||
+ line.contains(EnumChatFormatting.GRAY + "Buy it now: ")) {
+ neu.manager.updatePrices();
+ JsonObject auctionInfo = neu.manager.getItemAuctionInfo(internalname);
+
+ if(auctionInfo != null) {
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+ int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ float costOfEnchants = neu.manager.getCostOfEnchants(internalname,
+ event.itemStack.getTagCompound());
+ int priceWithEnchants = auctionPrice+(int)costOfEnchants;
+
+ event.toolTip.add(++i, EnumChatFormatting.GRAY + "Average price: " +
+ EnumChatFormatting.GOLD + format.format(auctionPrice) + " coins");
+ if(costOfEnchants > 0) {
+ event.toolTip.add(++i, EnumChatFormatting.GRAY + "Average price (w/ enchants): " +
+ EnumChatFormatting.GOLD +
+ format.format(priceWithEnchants) + " coins");
+ }
+
+ if(neu.manager.config.advancedPriceInfo.value) {
+ int salesVolume = (int) auctionInfo.get("sales").getAsFloat();
+ int flipPrice = (int)(0.93*priceWithEnchants);
+
+ event.toolTip.add(++i, EnumChatFormatting.GRAY + "Flip Price (93%): " +
+ EnumChatFormatting.GOLD + format.format(flipPrice) + " coins");
+ event.toolTip.add(++i, EnumChatFormatting.GRAY + "Volume: " +
+ EnumChatFormatting.GOLD + format.format(salesVolume) + " sales/day");
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }*/
+ if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !neu.manager.config.dev.value) return;
+ if(event.toolTip.size()>0&&event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) {
+ event.toolTip.remove(event.toolTip.size()-1);
+
+ StringBuilder sb = new StringBuilder();
+ String nbt = event.itemStack.getTagCompound().toString();
+ int indent = 0;
+ for(char c : nbt.toCharArray()) {
+ boolean newline = false;
+ if(c == '{' || c == '[') {
+ indent++;
+ newline = true;
+ } else if(c == '}' || c == ']') {
+ indent--;
+ sb.append("\n");
+ for(int i=0; i<indent; i++) sb.append(" ");
+ } else if(c == ',') {
+ newline = true;
+ } else if(c == '\"') {
+ sb.append(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY);
+ }
+
+ sb.append(c);
+ if(newline) {
+ sb.append("\n");
+ for(int i=0; i<indent; i++) sb.append(" ");
+ }
+ }
+ event.toolTip.add(sb.toString());
+ if(Keyboard.isKeyDown(Keyboard.KEY_H)) {
+ StringSelection selection = new StringSelection(sb.toString());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
deleted file mode 100644
index b9f086a4..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUIO.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package io.github.moulberry.notenoughupdates;
-
-import org.kohsuke.github.*;
-
-import java.io.IOException;
-import java.util.*;
-
-public class NEUIO {
-
- private final String accessToken;
-
- /**
- * THIS CLASS PROVIDES METHODS FOR INTERFACING WITH THE GIT REPOSITORY NotEnoughUpdates-REPO. THIS REPOSITORY
- * CONTAINS ALL THE JSON ITEMS. THIS SHOULD NOT BE A PERMANENT SOLUTION AND I SHOULD LOOK AT USING SOME FORM OF
- * HOSTING SERVICE OTHER THAN A GIT REPOSITORY IF THE USERBASE OF THE MOD GROWS SIGNIFICANTLY. UNFORTUNATELY I
- * CANT AFFORD HOSTING RIGHT NOW SO THIS IS WHAT YOU GET AND GITHUB WILL PROBABLY THROW A FIT IF A LARGE NUMBER
- * OF USERS START DOWNLOADING FROM THE REPO ALL AT ONCE.
- */
-
- public NEUIO(String accessToken) {
- this.accessToken = accessToken;
- }
-
- /**
- * Creates a new branch, commits to it with a single file change and submits a pull request from the new branch
- * back to the master branch.
- */
- public boolean createNewRequest(String newBranchName, String prTitle, String prBody, String filename, String content) {
- try {
- GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
- System.out.println("Getting repo");
-
- //https://github.com/Moulberry/NotEnoughUpdates-REPO
- GHRepository repo = github.getRepositoryById("247692460");
-
- System.out.println("Getting last commit");
- String lastCommitSha = repo.getRef("heads/master").getObject().getSha();
- System.out.println("Last master commit sha: " + lastCommitSha);
-
- String lastTreeSha = repo.getCommit(lastCommitSha).getTree().getSha();
-
- GHTreeBuilder tb = repo.createTree();
- tb.baseTree(lastTreeSha);
- tb.add(filename, content, false);
- GHTree tree = tb.create();
- System.out.println("Created new tree: " + tree.getSha());
-
- GHCommitBuilder cb = repo.createCommit();
- cb.message(prTitle);
- cb.tree(tree.getSha());
- cb.parent(lastCommitSha);
- GHCommit commit = cb.create();
- System.out.println("Created commit: " + commit.getSHA1());
-
- repo.createRef("refs/heads/"+newBranchName, commit.getSHA1());
- System.out.println("Set new branch head to commit.");
-
- repo.createPullRequest(prTitle, newBranchName, "master", prBody);
- return true;
- } catch(IOException e) {
- e.printStackTrace();
- return false;
- }
- }
-
- /**
- * @param oldShas Map from filename (eg. BOW.json) to the sha in the local repository
- * @return Map from filename to the new shas
- */
- public Map<String, String> getChangedItems(Map<String, String> oldShas) {
- HashMap<String, String> changedFiles = new HashMap<>();
- try {
- GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
- GHRepository repo = github.getRepositoryById("247692460");
-
- for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) {
- if(treeEntry.getPath().contains(".")) {
- String oldSha = oldShas.get(treeEntry.getPath());
- if(!treeEntry.getSha().equals(oldSha)) {
- changedFiles.put(treeEntry.getPath(), treeEntry.getSha());
- }
- }
- }
- } catch(IOException e) {
- return null;
- }
- return changedFiles;
- }
-
- public Set<String> getRemovedItems(Set<String> currentlyInstalled) {
- Set<String> removedItems = new HashSet<>();
- Set<String> repoItems = new HashSet<>();
- try {
- GitHub github = new GitHubBuilder().withOAuthToken(accessToken).build();
- GHRepository repo = github.getRepositoryById("247692460");
-
- for(GHTreeEntry treeEntry : repo.getTreeRecursive("master", 1).getTree()) {
- String[] split = treeEntry.getPath().split("/");
- repoItems.add(split[split.length-1].split("\\.")[0]);
- }
- } catch(IOException e) {
- e.printStackTrace();
- return removedItems;
- }
- removedItems.addAll(currentlyInstalled);
- removedItems.removeAll(repoItems);
- return removedItems;
- }
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 8d625c14..8073227c 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -5,11 +5,13 @@ import com.google.gson.*;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
import io.github.moulberry.notenoughupdates.options.Options;
+import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.HypixelApi;
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 +23,13 @@ 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.nio.file.Path;
+import java.nio.file.Paths;
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;
@@ -30,7 +37,6 @@ import java.util.zip.ZipInputStream;
public class NEUManager {
private final NotEnoughUpdates neu;
- public final NEUIO neuio;
public final Gson gson;
public final APIManager auctionManager;
@@ -45,7 +51,9 @@ public class NEUManager {
public final KeyBinding keybindViewRecipe = new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates");
public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates");
public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates");
- public final KeyBinding[] keybinds = new KeyBinding[]{keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, keybindToggleDisplay, keybindClosePanes};
+ public final KeyBinding keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates");
+ public final KeyBinding[] keybinds = new KeyBinding[]{ keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe,
+ keybindToggleDisplay, keybindClosePanes, keybindItemSelect};
public String viewItemAttemptID = null;
public long viewItemAttemptTime = 0;
@@ -57,24 +65,23 @@ public class NEUManager {
private ResourceLocation wkZip = new ResourceLocation("notenoughupdates:wkhtmltox.zip");
private Map<String, ItemStack> itemstackCache = new HashMap<>();
- private static final String AUCTIONS_PRICE_URL = "https://moulberry.github.io/files/auc_avg_jsons/average_3day.json.gz";
- private JsonObject auctionPricesJson = null;
- private long auctionLastUpdate = 0;
+ //private static final String AUCTIONS_PRICE_URL = "https://moulberry.github.io/files/auc_avg_jsons/average_3day.json.gz";
+ private static final String GIT_COMMITS_URL = "https://api.github.com/repos/Moulberry/NotEnoughUpdates-REPO/commits/master";
- private HashMap<String, CraftInfo> craftCost = new HashMap<>();
private HashMap<String, Set<String>> usagesMap = new HashMap<>();
+ public String latestRepoCommit = null;
+
public File configLocation;
public File repoLocation;
- private File itemShaLocation;
- private JsonObject itemShaConfig;
public File configFile;
+ public File itemRenameFile;
+ public JsonObject itemRenameJson;
public Options config;
- public NEUManager(NotEnoughUpdates neu, NEUIO neuio, File configLocation) {
+ public NEUManager(NotEnoughUpdates neu, File configLocation) {
this.neu = neu;
this.configLocation = configLocation;
- this.neuio = neuio;
this.auctionManager = new APIManager(this);
GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting();
@@ -87,12 +94,11 @@ public class NEUManager {
this.repoLocation = new File(configLocation, "repo");
repoLocation.mkdir();
- this.itemShaLocation = new File(configLocation, "itemSha.json");
- try {
- itemShaLocation.createNewFile();
- itemShaConfig = getJsonFromFile(itemShaLocation);
- if(itemShaConfig == null) itemShaConfig = new JsonObject();
- } catch(IOException e) { }
+ this.itemRenameFile = new File(configLocation, "itemRename.json");
+ itemRenameJson = getJsonFromFile(itemRenameFile);
+ if(itemRenameJson == null) {
+ itemRenameJson = new JsonObject();
+ }
File wkShell = new File(configLocation, "wkhtmltox/bin/wkhtmltoimage");
if(!wkShell.exists()) {
@@ -104,12 +110,6 @@ public class NEUManager {
}
}
- public class CraftInfo {
- public boolean fromRecipe = false;
- public boolean vanillaItem = false;
- public float craftCost = -1;
- }
-
public void setCurrentProfile(String currentProfile) {
this.currentProfile = currentProfile;
}
@@ -126,85 +126,8 @@ public class NEUManager {
}
}
- public boolean isVanillaItem(String internalname) {
- //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES
- String vanillaName = internalname.split("-")[0];
- int sub = 0;
- for(int i=vanillaName.length()-1; i>1; i--) {
- char c = vanillaName.charAt(i);
- if((int)c >= 48 && (int)c <= 57) { //0-9
- sub++;
- } else if(c == '_') {
- sub++;
- break;
- } else {
- break;
- }
- }
- vanillaName = vanillaName.substring(0, vanillaName.length()-sub).toLowerCase();
- return Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null;
- }
-
- /**
- * Recursively calculates the cost of crafting an item from raw materials.
- */
- public CraftInfo getCraftCost(String internalname) {
- if(craftCost.containsKey(internalname)) {
- return craftCost.get(internalname);
- } else {
- CraftInfo ci = new CraftInfo();
-
- ci.vanillaItem = isVanillaItem(internalname);
-
- JsonObject auctionInfo = getItemAuctionInfo(internalname);
- JsonObject bazaarInfo = getBazaarInfo(internalname);
-
- if(bazaarInfo != null) {
- float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat();
- ci.craftCost = bazaarInstantBuyPrice;
- }
- if(auctionInfo != null && !ci.vanillaItem) { //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items.
- float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat();
- if(ci.craftCost < 0 || auctionPrice < ci.craftCost) {
- ci.craftCost = auctionPrice;
- }
- }
- JsonObject item = getItemInformation().get(internalname);
- if(item != null && item.has("recipe")) {
- float craftPrice = 0;
- JsonObject recipe = item.get("recipe").getAsJsonObject();
-
- String[] x = {"1","2","3"};
- String[] y = {"A","B","C"};
- for(int i=0; i<9; i++) {
- String name = y[i/3]+x[i%3];
- String itemS = recipe.get(name).getAsString();
- if(itemS.length() == 0) continue;
-
- int count = 1;
- if(itemS != null && itemS.split(":").length == 2) {
- count = Integer.valueOf(itemS.split(":")[1]);
- itemS = itemS.split(":")[0];
- }
- float compCost = getCraftCost(itemS).craftCost * count;
- if(compCost < 0) {
- if(!getCraftCost(itemS).vanillaItem) { //If it's a vanilla item without a cost attached to it, let compCost = 0.
- craftCost.put(internalname, ci);
- return ci;
- }
- } else {
- craftPrice += compCost;
- }
- }
-
- if(ci.craftCost < 0 || craftPrice < ci.craftCost) {
- ci.craftCost = craftPrice;
- ci.fromRecipe = true;
- }
- }
- craftCost.put(internalname, ci);
- return ci;
- }
+ public void saveItemRenameConfig() {
+ try { writeJson(itemRenameJson, itemRenameFile); } catch(IOException ignored) {}
}
public void saveConfig() throws IOException {
@@ -222,257 +145,233 @@ public class NEUManager {
}
/**
- * Downloads and sets auctionPricesJson from the URL specified by AUCTIONS_PRICE_URL.
+ * Parses a file in to a JsonObject.
*/
- public void updatePrices() {
- if(System.currentTimeMillis() - auctionLastUpdate > 1000*60*120) { //2 hours
- craftCost.clear();
- System.out.println("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();
- }
- }
- }
-
- public boolean hasAuctionInfo(String internalname) {
- return auctionPricesJson.has("item_data") && auctionPricesJson.get("item_data").getAsJsonObject().has(internalname);
- }
-
- public boolean hasBazaarInfo(String internalname) {
- return auctionPricesJson.has("bazaar") && auctionPricesJson.get("bazaar").getAsJsonObject().has(internalname);
- }
-
- public JsonObject getItemAuctionInfo(String internalname) {
- if(!hasAuctionInfo(internalname)) return null;
- JsonElement e = auctionPricesJson.get("item_data").getAsJsonObject().get(internalname);
- if(e == null) {
- return null;
- }
- return e.getAsJsonObject();
+ public JsonObject getJsonFromFile(File file) {
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
+ JsonObject json = gson.fromJson(reader, JsonObject.class);
+ return json;
+ } catch(Exception e) { return null; }
}
- public JsonObject getBazaarInfo(String internalname) {
- if(!hasBazaarInfo(internalname)) return null;
- JsonElement e = auctionPricesJson.get("bazaar").getAsJsonObject().get(internalname);
- if(e == null) {
- return null;
- }
- return e.getAsJsonObject();
+ public void resetRepo() {
+ try { Utils.recursiveDelete(new File(configLocation, "repo")); } catch(Exception e) {}
+ try { new File(configLocation, "currentCommit.json").delete(); } catch(Exception e) {}
}
/**
- * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc.
+ * Called when the game is first loaded. Compares the local repository to the github repository and handles
+ * the downloading of new/updated files. This then calls the "loadItem" method for every item in the local
+ * repository.
*/
- public float getCostOfEnchants(String internalname, NBTTagCompound tag) {
- float costOfEnchants = 0;
- if(true) return 0;
-
- JsonObject info = getItemAuctionInfo(internalname);
- if(info == null || !info.has("price")) {
- return 0;
- }
- if(!auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) {
- return 0;
- }
- JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices");
- JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums");
- if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) {
- return 0;
- }
- JsonObject iid_variables = ench_prices.getAsJsonObject(internalname);
- float ench_maximum = ench_maximums.get(internalname).getAsFloat();
+ public void loadItemInformation() {
+ /*File repoFile = new File(configLocation, "repo2");
+ repoFile.mkdirs();
+
+ try(Git git = Git.init().setDirectory(repoFile).call()) {
+ StoredConfig config = git.getRepository().getConfig();
+ config.setString("branch", "master", "merge", "refs/heads/master");
+ config.setString("branch", "master", "remote", "origin");
+ config.setString("remote", "origin", "fetch", "+refs/heads/*:refs/remotes/origin/*");
+ config.setString("remote", "origin", "url", "https://github.com/Moulberry/NotEnoughUpdates-REPO.git");
+ config.save();
+
+ git.remoteAdd().setName("origin").setUri(new URIish("https://github.com/Moulberry/NotEnoughUpdates-REPO.git")).call();
+ PullResult result = git.pull().setRemote("origin").setTimeout(30000).call();
+ System.out.println("successful pull: " + result.isSuccessful());
+ } catch(Exception e) {
+ e.printStackTrace();
+ }*/
- int enchants = 0;
- float price = getItemAuctionInfo(internalname).get("price").getAsFloat();
- if(tag.hasKey("ExtraAttributes")) {
- NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
- if(ea.hasKey("enchantments")) {
-
- NBTTagCompound enchs = ea.getCompoundTag("enchantments");
- for(String ench : enchs.getKeySet()) {
- enchants++;
- int level = enchs.getInteger(ench);
-
- for(Map.Entry<String, JsonElement> entry : iid_variables.entrySet()) {
- if(matchEnch(ench, level, entry.getKey())) {
- costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price +
- entry.getValue().getAsJsonObject().get("B").getAsFloat();
- break;
- }
- }
- }
+ /*if(repoFile.mkdirs()) {
+ try {
+ Git.cloneRepository()
+ .setURI("https://github.com/Moulberry/NotEnoughUpdates-REPO.git")
+ .setDirectory(repoFile)
+ .call();
+ } catch(Exception e) {
+ e.printStackTrace();
}
- }
- return costOfEnchants;
- }
-
- /**
- * Checks whether a certain enchant (ench name + lvl) matches an enchant id
- * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6
- */
- private boolean matchEnch(String ench, int level, String id) {
- if(!id.contains(":")) {
- return false;
- }
+ } else {
- String idEnch = id.split(":")[0];
- String idLevel = id.split(":")[1];
+ }*/
- if(!ench.equalsIgnoreCase(idEnch)) {
- return false;
- }
- if(String.valueOf(level).equalsIgnoreCase(idLevel)) {
- return true;
- }
- if(idLevel.startsWith("LE")) {
- int idLevelI = Integer.valueOf(idLevel.substring(2));
- return level <= idLevelI;
- } else if(idLevel.startsWith("GE")) {
- int idLevelI = Integer.valueOf(idLevel.substring(2));
- return level >= idLevelI;
- }
+ 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);
- return false;
- }
+ if (Display.isActive()) dialog.toFront();
- /**
- * Parses a file in to a JsonObject.
- */
- public JsonObject getJsonFromFile(File file) throws IOException {
- try {
- InputStream in = new FileInputStream(file);
- BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
- JsonObject json = gson.fromJson(reader, JsonObject.class);
- return json;
- } catch(Exception e) { return null; }
- }
+ JsonObject currentCommitJSON = getJsonFromFile(new File(configLocation, "currentCommit.json"));
- /**
- * Called when the game is first loaded. Compares the local repository to the github repository and handles
- * the downloading of new/updated files. This then calls the "loadItem" method for every item in the local
- * repository.
- */
- public void loadItemInformation() {
- 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());
+ latestRepoCommit = null;
+ try(Reader inReader = new InputStreamReader(new URL(GIT_COMMITS_URL).openStream())) {
+ JsonObject commits = gson.fromJson(inReader, JsonObject.class);
+ latestRepoCommit = commits.get("sha").getAsString();
+ } catch (Exception e) {
+ e.printStackTrace();
}
- }
- Map<String, String> changedFiles = neuio.getChangedItems(oldShas);
+ if(latestRepoCommit == null || latestRepoCommit.isEmpty()) return;
- 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) {
+ if(new File(configLocation, "repo").exists() && new File(configLocation, "repo/items").exists()) {
+
+ if(currentCommitJSON != null && currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
+ dialog.setVisible(false);
+ return;
+ }
+
+ /*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());
+ }
+ }
+ changedFiles = neuio.getChangedItems(oldShas);*/
}
- }
- if (Display.isActive()) dialog.toFront();
+ if (Display.isActive()) dialog.toFront();
- if (changedFiles != null && changedFiles.size() <= 20) {
+ if (false) {//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/";
- 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();
- for (String name : changedFiles.keySet()) {
- pane.setMessage(startMessage + (++downloaded) + "/" + changedFiles.size() + ")\nCurrent: " + name);
+ 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(5000);
+ urlConnection.setReadTimeout(5000);
+ 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();
+
+ //TODO: Store hard-coded value somewhere else
+ String dlUrl = "https://github.com/Moulberry/NotEnoughUpdates-REPO/archive/master.zip";
+
+ 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(15000);
+ urlConnection.setReadTimeout(20000);
+ 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) {
+ /*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) {
+ }
+ }*/
}
- 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(currentCommitJSON == null || !currentCommitJSON.get("sha").getAsString().equals(latestRepoCommit)) {
+ JsonObject newCurrentCommitJSON = new JsonObject();
+ newCurrentCommitJSON.addProperty("sha", latestRepoCommit);
+ try {
+ writeJson(newCurrentCommitJSON, new File(configLocation, "currentCommit.json"));
+ } catch (IOException 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();
}
/**
@@ -549,7 +448,7 @@ public class NEUManager {
}
}
}
- } catch(IOException e) {
+ } catch(Exception e) {
e.printStackTrace();
}
}
@@ -810,12 +709,25 @@ 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;
}
}
+ public String getUUIDFromNBT(NBTTagCompound tag) {
+ String uuid = null;
+ if (tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ if (ea.hasKey("uuid", 8)) {
+ uuid = ea.getString("uuid");
+ }
+ }
+ return uuid;
+ }
+
public String getInternalnameFromNBT(NBTTagCompound tag) {
String internalname = null;
if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
@@ -873,7 +785,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 +799,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);
@@ -895,16 +813,33 @@ public class NEUManager {
String[] info = new String[0];
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(ea.hasKey("dungeon_item_level")) {
+ item.addProperty("dungeon_item_level", ea.getInteger("dungeon_item_level"));
+ }
+ }
+
if(lore != null && lore.length > 0) {
JsonArray jsonLore = new JsonArray();
for (String line : lore) {
@@ -998,6 +933,12 @@ public class NEUManager {
return getInternalnameFromNBT(tag);
}
+ public String getUUIDForItem(ItemStack stack) {
+ if(stack == null) return null;
+ NBTTagCompound tag = stack.getTagCompound();
+ return getUUIDFromNBT(tag);
+ }
+
public void writeItemToFile(ItemStack stack) {
String internalname = getInternalNameForItem(stack);
@@ -1060,8 +1001,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;
}
@@ -1304,9 +1243,9 @@ public class NEUManager {
String prTitle = internalname + "-" + username;
String prBody = "Internal name: " + internalname + "\nSubmitted by: " + username;
String file = "items/"+internalname+".json";
- if(!neuio.createNewRequest(newBranchName, prTitle, prBody, file, gson.toJson(json))) {
+ /*if(!neuio.createNewRequest(newBranchName, prTitle, prBody, file, gson.toJson(json))) {
return false;
- }
+ }*/
try {
writeJsonDefaultDir(json, internalname+".json");
@@ -1335,11 +1274,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 = Constants.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 +1425,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..73381955 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -3,15 +3,14 @@ package io.github.moulberry.notenoughupdates;
import com.google.common.collect.Lists;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.infopanes.*;
import io.github.moulberry.notenoughupdates.itemeditor.NEUItemEditor;
import io.github.moulberry.notenoughupdates.mbgui.MBAnchorPoint;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiElement;
+import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupAligned;
import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupFloating;
-import io.github.moulberry.notenoughupdates.mbgui.MBGuiGroupHorz;
-import io.github.moulberry.notenoughupdates.util.LerpingFloat;
-import io.github.moulberry.notenoughupdates.util.LerpingInteger;
-import io.github.moulberry.notenoughupdates.util.Utils;
+import io.github.moulberry.notenoughupdates.util.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*;
import net.minecraft.client.gui.inventory.GuiContainer;
@@ -57,6 +56,8 @@ import static io.github.moulberry.notenoughupdates.GuiTextures.*;
public class NEUOverlay extends Gui {
+ private static final ResourceLocation SUPERGEHEIMNISVERMOGEN = new ResourceLocation("notenoughupdates:supersecretassets/bald.png");
+
private NEUManager manager;
private String mobRegex = ".*?((_MONSTER)|(_ANIMAL)|(_MINIBOSS)|(_BOSS)|(_SC))$";
@@ -95,8 +96,14 @@ public class NEUOverlay extends Gui {
private TreeSet<JsonObject> searchedItems = null;
private JsonObject[] searchedItemsArr = null;
+ private HashMap<String, Set<String>> searchedItemsSubgroup = new HashMap<>();
+
+ private long selectedItemMillis = 0;
+ private int selectedItemGroupX = -1;
+ private int selectedItemGroupY = -1;
+ private List<JsonObject> selectedItemGroup = null;
+
private boolean itemPaneOpen = false;
- private boolean hoveringItemPaneToggle = false;
private int page = 0;
@@ -128,8 +135,6 @@ public class NEUOverlay extends Gui {
private static final int SORT_MODE_ARMOR = 4;
private static final int SORT_MODE_ACCESSORY = 5;
- private ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
-
private boolean disabled = false;
private int lastScreenWidth;
@@ -272,20 +277,17 @@ public class NEUOverlay extends Gui {
@Override
public void render(float x, float y) {
int paddingUnscaled = getPaddingUnscaled();
+ int searchYSize = getSearchBarYSize();
- Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
- drawRect((int)x, (int)y,
- (int)x + getWidth(), (int)y + getHeight(),
- Color.WHITE.getRGB());
-
-
- drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled,
- (int)x + getWidth() - paddingUnscaled, (int)y + getHeight() - paddingUnscaled,
- Color.GRAY.getRGB());
+ Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(x, y,
+ searchYSize + paddingUnscaled*2, searchYSize + paddingUnscaled*2, GL11.GL_NEAREST);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(settings);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect((int)x + paddingUnscaled, (int)y + paddingUnscaled,
- getSearchBarYSize(), getSearchBarYSize());
+ searchYSize, searchYSize);
GlStateManager.bindTexture(0);
}
};
@@ -310,8 +312,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();
}
}
@@ -323,16 +326,14 @@ public class NEUOverlay extends Gui {
@Override
public void render(float x, float y) {
int paddingUnscaled = getPaddingUnscaled();
+ int searchYSize = getSearchBarYSize();
- Minecraft.getMinecraft().getTextureManager().bindTexture(help);
- drawRect((int)x, (int)y,
- (int)x + getWidth(), (int)y + getHeight(),
- Color.WHITE.getRGB());
-
- drawRect((int)x + paddingUnscaled, (int)y + paddingUnscaled,
- (int)x + getWidth() - paddingUnscaled, (int)y + getHeight() - paddingUnscaled,
- Color.GRAY.getRGB());
+ Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(x, y,
+ searchYSize + paddingUnscaled*2, searchYSize + paddingUnscaled*2, GL11.GL_NEAREST);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
GlStateManager.color(1f, 1f, 1f, 1f);
Utils.drawTexturedRect((int)x + paddingUnscaled, (int)y + paddingUnscaled,
getSearchBarYSize(), getSearchBarYSize());
@@ -401,7 +402,6 @@ public class NEUOverlay extends Gui {
NBTTagList textures = new NBTTagList();
NBTTagCompound textures_0 = new NBTTagCompound();
-
String uuid = UUID.nameUUIDFromBytes(display.getBytes()).toString();
skullOwner.setString("Id", uuid);
skullOwner.setString("Name", uuid);
@@ -424,16 +424,13 @@ public class NEUOverlay extends Gui {
}
}
if(render != null) {
- Minecraft.getMinecraft().getTextureManager().bindTexture(item_mask);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(quickcommand_background);
GlStateManager.color(1, 1, 1, 1);
Utils.drawTexturedRect(x, y,
- bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_LINEAR);
- GlStateManager.color(fg.getRed() / 255f,fg.getGreen() / 255f,
- fg.getBlue() / 255f, fg.getAlpha() / 255f);
- Utils.drawTexturedRect(x+paddingUnscaled, y+paddingUnscaled, bigItemSize, bigItemSize, GL11.GL_LINEAR);
+ bigItemSize + paddingUnscaled*2, bigItemSize + paddingUnscaled*2, GL11.GL_NEAREST);
- int mouseX = Mouse.getX() * scaledresolution.getScaledWidth() / Minecraft.getMinecraft().displayWidth;
- int mouseY = scaledresolution.getScaledHeight() - Mouse.getY() * scaledresolution.getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1;
+ int mouseX = Mouse.getX() * Utils.peekGuiScale().getScaledWidth() / Minecraft.getMinecraft().displayWidth;
+ int mouseY = Utils.peekGuiScale().getScaledHeight() - Mouse.getY() * Utils.peekGuiScale().getScaledHeight() / Minecraft.getMinecraft().displayHeight - 1;
if(mouseX > x && mouseX < x+bigItemSize) {
if(mouseY > y && mouseY < y+bigItemSize) {
@@ -454,21 +451,21 @@ public class NEUOverlay extends Gui {
};
}
- private MBGuiGroupHorz createQuickCommandGroup() {
+ private MBGuiGroupAligned createQuickCommandGroup() {
List<MBGuiElement> children = new ArrayList<>();
for(String quickCommand : manager.config.quickCommands.value) {
children.add(createQuickCommand(quickCommand));
}
- return new MBGuiGroupHorz(children) {
+ return new MBGuiGroupAligned(children, false) {
public int getPadding() {
return getPaddingUnscaled()*4;
}
};
}
- private MBGuiGroupHorz createSearchBarGroup() {
+ private MBGuiGroupAligned createSearchBarGroup() {
List<MBGuiElement> children = Lists.newArrayList(createSettingsButton(this), createSearchBar(), createHelpButton(this));
- return new MBGuiGroupHorz(children) {
+ return new MBGuiGroupAligned(children, false) {
public int getPadding() {
return getPaddingUnscaled()*4;
}
@@ -490,7 +487,7 @@ public class NEUOverlay extends Gui {
map.put(createSearchBarGroup(), searchBarAnchor);
map.put(createQuickCommandGroup(), quickCommandAnchor);
- return new MBGuiGroupFloating(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight(), map);
+ return new MBGuiGroupFloating(Utils.peekGuiScale().getScaledWidth(), Utils.peekGuiScale().getScaledHeight(), map);
}
public void resetAnchors(boolean onlyIfNull) {
@@ -541,6 +538,7 @@ public class NEUOverlay extends Gui {
itemPaneOffsetFactor.setValue(1);
itemPaneTabOffset.setValue(20);
}
+ if(activeInfoPane != null) activeInfoPane.reset();
}
/**
@@ -570,6 +568,22 @@ public class NEUOverlay extends Gui {
}
}
+ public void mouseInputInv() {
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
+ if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100) {
+ Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen);
+ if(slot != null) {
+ ItemStack hover = slot.getStack();
+ if(hover != null) {
+ textField.setText("id:"+manager.getInternalNameForItem(hover));
+ itemPaneOpen = true;
+ updateSearch();
+ }
+ }
+ }
+ }
+ }
+
/**
* Handles the mouse input, cancelling the forge event if a NEU gui element is clicked.
*/
@@ -578,11 +592,12 @@ public class NEUOverlay extends Gui {
return false;
}
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+ Utils.pushGuiScale(manager.config.paneGuiScale.value.intValue());
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
//if(lastMouseX != mouseX || lastMouseY != mouseY) {
// millisLastMouseMove = System.currentTimeMillis();
@@ -602,9 +617,36 @@ public class NEUOverlay extends Gui {
guiGroup.mouseClick(0, 0, mouseX, mouseY);
+ if(selectedItemGroup != null) {
+ int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size());
+ if(mouseY > selectedItemGroupY+17 && mouseY < selectedItemGroupY+35) {
+ for(int i=0; i<selectedItemGroup.size(); i++) {
+ if(mouseX >= selectedX-1+18*i && mouseX <= selectedX+17+18*i) {
+ JsonObject item = selectedItemGroup.get(i);
+ if (item != null) {
+ if(Mouse.getEventButton() == 0) {
+ manager.showRecipe(item);
+ } else if(Mouse.getEventButton() == 1) {
+ showInfo(item);
+ } else if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100) {
+ textField.setText("id:"+item.get("internalname").getAsString());
+ updateSearch();
+ searchMode = true;
+ }
+ }
+ Utils.pushGuiScale(-1);
+ return true;
+ }
+ }
+ }
+ }
+
//Item selection (right) gui
if(mouseX > width*getItemPaneOffsetFactor()) {
- if(!Mouse.getEventButtonState()) return true; //End early if the mouse isn't pressed, but still cancel event.
+ if(!Mouse.getEventButtonState()) {
+ Utils.pushGuiScale(-1);
+ return true; //End early if the mouse isn't pressed, but still cancel event.
+ }
AtomicBoolean clickedItem = new AtomicBoolean(false);
iterateItemSlots(new ItemSlotConsumer() {
@@ -619,7 +661,7 @@ public class NEUOverlay extends Gui {
manager.showRecipe(item);
} else if(Mouse.getEventButton() == 1) {
showInfo(item);
- } else if(Mouse.getEventButton() == 2) {
+ } else if(Mouse.getEventButton() == manager.keybindItemSelect.getKeyCode()+100) {
textField.setText("id:"+item.get("internalname").getAsString());
updateSearch();
searchMode = true;
@@ -637,7 +679,7 @@ public class NEUOverlay extends Gui {
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
int maxPages = getMaxPages();
- String name = scaledresolution.getScaleFactor()<4?"Page: ":"";
+ String name = Utils.peekGuiScale().getScaleFactor()<4?"Page: ":"";
float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD+name + maxPages + "/" + maxPages);
float maxButtonXSize = (rightSide-leftSide+2 - maxStrLen*0.5f - 10)/2f;
int buttonXSize = (int)Math.min(maxButtonXSize, getSearchBarYSize()*480/160f);
@@ -692,47 +734,60 @@ public class NEUOverlay extends Gui {
}
}
}
+ Utils.pushGuiScale(-1);
return true;
}
- if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
- if(Mouse.getEventButton() == 2) {
- Slot slot = Utils.getSlotUnderMouse((GuiContainer)Minecraft.getMinecraft().currentScreen);
- if(slot != null) {
- ItemStack hover = slot.getStack();
- if(hover != null) {
- textField.setText("id:"+manager.getInternalNameForItem(hover));
- updateSearch();
- searchMode = true;
+ //Clicking on "close info pane" button
+ if(activeInfoPane instanceof SettingsInfoPane) {
+ Utils.pushGuiScale(2);
+
+ int widthN = Utils.peekGuiScale().getScaledWidth();
+ int heightN = Utils.peekGuiScale().getScaledHeight();
+ int mouseXN = Mouse.getX() * widthN / Minecraft.getMinecraft().displayWidth;
+ int mouseYN = heightN - Mouse.getY() * heightN / Minecraft.getMinecraft().displayHeight - 1;
+
+ if(mouseXN > widthN*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseXN < widthN*getInfoPaneOffsetFactor()-getBoxPadding()+8) {
+ if(mouseYN > getBoxPadding()-8 && mouseYN < getBoxPadding()+8) {
+ if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up
+ displayInformationPane(null);
+
+ Utils.pushGuiScale(-1);
+ Utils.pushGuiScale(-1);
return true;
}
}
}
- }
- //Clicking on "close info pane" button
- if(mouseX > width*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseX < width*getInfoPaneOffsetFactor()-getBoxPadding()+8) {
- if(mouseY > getBoxPadding()-8 && mouseY < getBoxPadding()+8) {
- if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up
- displayInformationPane(null);
- return true;
+ Utils.pushGuiScale(-1);
+ } else {
+ if(mouseX > width*getInfoPaneOffsetFactor()-getBoxPadding()-8 && mouseX < width*getInfoPaneOffsetFactor()-getBoxPadding()+8) {
+ if(mouseY > getBoxPadding()-8 && mouseY < getBoxPadding()+8) {
+ if(Mouse.getEventButtonState() && Mouse.getEventButton() < 2) { //Left or right click up
+ displayInformationPane(null);
+ Utils.pushGuiScale(-1);
+ return true;
+ }
}
}
}
+
if(activeInfoPane != null) {
if(mouseX < width*getInfoPaneOffsetFactor()) {
activeInfoPane.mouseInput(width, height, mouseX, mouseY, mouseDown);
+ Utils.pushGuiScale(-1);
return true;
} else if(Mouse.getEventButton() <= 1 && Mouse.getEventButtonState()) { //Left or right click
activeInfoPane.mouseInputOutside();
}
}
+ Utils.pushGuiScale(-1);
return false;
}
public int getPaddingUnscaled() {
- int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
+ int paddingUnscaled = searchBarPadding/Utils.peekGuiScale().getScaleFactor();
if(paddingUnscaled < 1) paddingUnscaled = 1;
return paddingUnscaled;
@@ -742,7 +797,7 @@ public class NEUOverlay extends Gui {
* Returns searchBarXSize, scaled by 0.8 if gui scale == AUTO.
*/
public int getSearchBarXSize() {
- if(scaledresolution.getScaleFactor()==4) return (int)(searchBarXSize*0.8);
+ if(Utils.peekGuiScale().getScaleFactor()==4) return (int)(searchBarXSize*0.8);
return (int)(searchBarXSize);
}
@@ -767,8 +822,8 @@ public class NEUOverlay extends Gui {
* Finds the index of the character inside the search bar that was clicked, used to set the caret.
*/
public int getClickedIndex(int mouseX, int mouseY) {
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
int xComp = mouseX - (width/2 - getSearchBarXSize()/2 + 5);
@@ -852,21 +907,38 @@ public class NEUOverlay extends Gui {
itemstack.set(hover);
}
} else if(!hoverInv) {
- int height = scaledresolution.getScaledHeight();
+ Utils.pushGuiScale(manager.config.paneGuiScale.value.intValue());
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
- iterateItemSlots(new ItemSlotConsumer() {
- public void consume(int x, int y, int id) {
- if (mouseX >= x - 1 && mouseX <= x + ITEM_SIZE + 1) {
- if (mouseY >= y - 1 && mouseY <= y + ITEM_SIZE + 1) {
- JsonObject json = getSearchedItemPage(id);
- if (json != null) internalname.set(json.get("internalname").getAsString());
+ if (selectedItemGroup != null) {
+ int selectedX = Math.min(selectedItemGroupX, width - getBoxPadding() - 18 * selectedItemGroup.size());
+
+ if (mouseY > selectedItemGroupY + 17 && mouseY < selectedItemGroupY + 35) {
+ for (int i = 0; i < selectedItemGroup.size(); i++) {
+ if (mouseX >= selectedX - 1 + 18 * i && mouseX <= selectedX + 17 + 18 * i) {
+ internalname.set(selectedItemGroup.get(i).get("internalname").getAsString());
}
}
}
- });
+ } else {
+ iterateItemSlots(new ItemSlotConsumer() {
+ public void consume(int x, int y, int id) {
+ if (mouseX >= x - 1 && mouseX <= x + ITEM_SIZE + 1) {
+ if (mouseY >= y - 1 && mouseY <= y + ITEM_SIZE + 1) {
+ JsonObject json = getSearchedItemPage(id);
+ if (json != null) internalname.set(json.get("internalname").getAsString());
+ }
+ }
+ }
+ });
+ }
+
+
+ Utils.pushGuiScale(-1);
}
if(internalname.get() != null) {
if(itemstack.get() != null) {
@@ -988,8 +1060,8 @@ public class NEUOverlay extends Gui {
float cost1 = manager.auctionManager.getLowestBin(o1.get("internalname").getAsString());
float cost2 = manager.auctionManager.getLowestBin(o2.get("internalname").getAsString());
- if(cost1 == -1) cost1 = manager.getCraftCost(o1.get("internalname").getAsString()).craftCost;
- if(cost2 == -1) cost2 = manager.getCraftCost(o2.get("internalname").getAsString()).craftCost;
+ if(cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1.get("internalname").getAsString()).craftCost;
+ if(cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2.get("internalname").getAsString()).craftCost;
if(cost1 < cost2) return mult;
if(cost1 > cost2) return -mult;
@@ -1049,12 +1121,16 @@ public class NEUOverlay extends Gui {
* Checks whether an item matches the current sort mode.
*/
public boolean checkMatchesSort(String internalname, JsonObject item) {
+ if(!manager.config.showVanillaItems.value && item.has("vanilla") && item.get("vanilla").getAsBoolean()) {
+ return false;
+ }
+
if(getSortMode() == SORT_MODE_ALL) {
return !internalname.matches(mobRegex);
} 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;
@@ -1074,13 +1150,30 @@ public class NEUOverlay extends Gui {
public void updateSearch() {
if(searchedItems==null) searchedItems = new TreeSet<>(getItemComparator());
searchedItems.clear();
+ searchedItemsSubgroup.clear();
searchedItemsArr = null;
redrawItems = true;
Set<String> itemsMatch = manager.search(textField.getText(), true);
for(String itemname : itemsMatch) {
JsonObject item = manager.getItemInformation().get(itemname);
if(checkMatchesSort(itemname, item)) {
- searchedItems.add(item);
+ if(item.has("parent") && item.get("parent").isJsonPrimitive()) {
+ searchedItemsSubgroup
+ .computeIfAbsent(item.get("parent").getAsString(), k->new HashSet<>())
+ .add(item.get("internalname").getAsString());
+ } else {
+ searchedItems.add(item);
+ }
+ }
+ }
+ out:
+ for(Map.Entry<String, Set<String>> entry : searchedItemsSubgroup.entrySet()) {
+ if(searchedItems.contains(manager.getItemInformation().get(entry.getKey()))) {
+ continue;
+ }
+ for(String itemname : entry.getValue()) {
+ JsonObject item = manager.getItemInformation().get(itemname);
+ if(item != null) searchedItems.add(item);
}
}
switch(textField.getText().toLowerCase().trim()) {
@@ -1097,6 +1190,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;
}
}
@@ -1137,13 +1239,13 @@ public class NEUOverlay extends Gui {
}
public int getItemBoxXPadding() {
- int width = scaledresolution.getScaledWidth();
+ int width = Utils.peekGuiScale().getScaledWidth();
return (((int)(width/3*getWidthMult())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
}
public int getBoxPadding() {
double panePadding = Math.max(0, Math.min(20, manager.config.panePadding.value));
- return (int)(panePadding*2/scaledresolution.getScaleFactor()+5);
+ return (int)(panePadding*2/Utils.peekGuiScale().getScaleFactor()+5);
}
private abstract class ItemSlotConsumer {
@@ -1151,7 +1253,7 @@ public class NEUOverlay extends Gui {
}
public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer) {
- int width = scaledresolution.getScaledWidth();
+ int width = Utils.peekGuiScale().getScaledWidth();
int itemBoxXPadding = getItemBoxXPadding();
iterateItemSlots(itemSlotConsumer, (int)(width*getItemPaneOffsetFactor())+getBoxPadding()+itemBoxXPadding);
}
@@ -1162,8 +1264,8 @@ public class NEUOverlay extends Gui {
* code duplication issues.
*/
public void iterateItemSlots(ItemSlotConsumer itemSlotConsumer, int xStart) {
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
int paneWidth = (int)(width/3*getWidthMult());
int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
@@ -1184,7 +1286,7 @@ public class NEUOverlay extends Gui {
public float getWidthMult() {
float scaleFMult = 1;
- if(scaledresolution.getScaleFactor()==4) scaleFMult *= 0.9f;
+ if(Utils.peekGuiScale().getScaleFactor()==4) scaleFMult *= 0.9f;
if(manager.auctionManager.customAH.isRenderOverAuctionView()) scaleFMult *= 0.8f;
return (float)Math.max(0.5, Math.min(1.5, manager.config.paneWidthMult.value.floatValue()))*scaleFMult;
}
@@ -1193,7 +1295,7 @@ public class NEUOverlay extends Gui {
* Calculates the number of horizontal item slots.
*/
public int getSlotsXSize() {
- int width = scaledresolution.getScaledWidth();
+ int width = Utils.peekGuiScale().getScaledWidth();
int paneWidth = (int)(width/3*getWidthMult());
int itemBoxXPadding = (((int)(width-width*getItemPaneOffsetFactor())-2*getBoxPadding())%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
@@ -1207,7 +1309,7 @@ public class NEUOverlay extends Gui {
* Calculates the number of vertical item slots.
*/
public int getSlotsYSize() {
- int height = scaledresolution.getScaledHeight();
+ int height = Utils.peekGuiScale().getScaledHeight();
int itemBoxYPadding = ((height-getSearchBarYSize()-2*getBoxPadding()-ITEM_SIZE-2)%(ITEM_SIZE+ITEM_PADDING)+ITEM_PADDING)/2;
int yStart = getBoxPadding()+getSearchBarYSize()+itemBoxYPadding;
@@ -1222,7 +1324,7 @@ public class NEUOverlay extends Gui {
}
public int getSearchBarYSize() {
- return Math.max(searchBarYSize/scaledresolution.getScaleFactor(), ITEM_SIZE);
+ return Math.max(searchBarYSize/Utils.peekGuiScale().getScaleFactor(), ITEM_SIZE);
}
/**
@@ -1245,10 +1347,11 @@ public class NEUOverlay extends Gui {
int rightPressed = 0;
if(Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
- int height = scaledresolution.getScaledHeight();
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
- int mouseX = Mouse.getX() / scaledresolution.getScaleFactor();
- int mouseY = height - Mouse.getY() / scaledresolution.getScaleFactor();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
if(mouseY >= top && mouseY <= top+ySize) {
int leftPrev = leftSide-1;
@@ -1388,7 +1491,12 @@ public class NEUOverlay extends Gui {
* Renders black squares over the inventory to indicate items that do not match a specific search. (When searchMode
* is enabled)
*/
- public void renderOverlay(int mouseX, int mouseY) {
+ public void renderOverlay() {
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
if(searchMode && textField.getText().length() > 0) {
if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
GuiContainer inv = (GuiContainer) Minecraft.getMinecraft().currentScreen;
@@ -1480,16 +1588,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) { }
@@ -1517,7 +1625,6 @@ public class NEUOverlay extends Gui {
public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
if(manager.config.bgBlurFactor.value <= 0 || !OpenGlHelper.isFramebufferEnabled()) return;
- int f = scaledresolution.getScaleFactor();
float uMin = x/(float)width;
float uMax = (x+blurWidth)/(float)width;
float vMin = y/(float)height;
@@ -1532,11 +1639,11 @@ public class NEUOverlay extends Gui {
}
public void updateGuiGroupSize() {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+ Utils.pushGuiScale(manager.config.paneGuiScale.value.intValue());
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
- if(lastScreenWidth != width || lastScreenHeight != height || scaledresolution.getScaleFactor() != lastScale) {
+ if(lastScreenWidth != width || lastScreenHeight != height || Utils.peekGuiScale().getScaleFactor() != lastScale) {
guiGroup.width = width;
guiGroup.height = height;
@@ -1545,28 +1652,48 @@ public class NEUOverlay extends Gui {
lastScreenWidth = width;
lastScreenHeight = height;
- lastScale = scaledresolution.getScaleFactor();
+ lastScale = Utils.peekGuiScale().getScaleFactor();
}
+
+ Utils.pushGuiScale(-1);
}
int guiScaleLast = 0;
+ private boolean showVanillaLast = false;
/**
* Renders the search bar, quick commands, item selection (right) and item info (left) gui elements.
*/
- public void render(int mouseX, int mouseY, boolean hoverInv) {
+ public void render(boolean hoverInv) {
if(disabled) {
return;
}
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledresolution.getScaledWidth();
- int height = scaledresolution.getScaledHeight();
+
+ Utils.resetGuiScale();
+ Utils.pushGuiScale(manager.config.paneGuiScale.value.intValue());
+
+ int width = Utils.peekGuiScale().getScaledWidth();
+ int height = Utils.peekGuiScale().getScaledHeight();
+ int mouseX = Mouse.getX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ if(showVanillaLast != manager.config.showVanillaItems.value) {
+ showVanillaLast = manager.config.showVanillaItems.value;
+ updateSearch();
+ }
+
+ if(textField.getText().toLowerCase().contains("bald")) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(SUPERGEHEIMNISVERMOGEN);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect((width-64)/2f, (height-64)/2f-114, 64, 64, GL11.GL_LINEAR);
+ GlStateManager.bindTexture(0);
+ }
updateGuiGroupSize();
- if(guiScaleLast != scaledresolution.getScaleFactor()) {
- guiScaleLast = scaledresolution.getScaleFactor();
+ if(guiScaleLast != Utils.peekGuiScale().getScaleFactor()) {
+ guiScaleLast = Utils.peekGuiScale().getScaleFactor();
redrawItems = true;
}
@@ -1580,15 +1707,13 @@ public class NEUOverlay extends Gui {
yaw++;
yaw %= 360;
- manager.updatePrices();
-
- int opacity = Math.min(255, Math.max(0, manager.config.bgOpacity.value.intValue()));
- bg = new Color((bg.getRGB() & 0x00ffffff) | opacity << 24, true);
+ bg = new Color(SpecialColour.specialToChromaRGB(manager.config.paneBackgroundColour.value), true);
+ fg = new Color(SpecialColour.specialToChromaRGB(manager.config.itemBackgroundColour.value));
+ Color fgCustomOpacity = new Color(SpecialColour.specialToChromaRGB(manager.config.itemBackgroundColour.value), true);
- opacity = Math.min(255, Math.max(0, manager.config.fgOpacity.value.intValue()));
- Color fgCustomOpacity = new Color((fg.getRGB() & 0x00ffffff) | opacity << 24, true);
- Color fgFavourite = new Color(limCol(fg.getRed()+20), limCol(fg.getGreen()+10), limCol(fg.getBlue()-10), opacity);
- Color fgFavourite2 = new Color(limCol(fg.getRed()+100), limCol(fg.getGreen()+50), limCol(fg.getBlue()-50), opacity);
+ Color fgFavourite2 = new Color(SpecialColour.specialToChromaRGB(manager.config.itemFavouriteColour.value), true);
+ Color fgFavourite = new Color((int)(fgFavourite2.getRed()*0.8f), (int)(fgFavourite2.getGreen()*0.8f),
+ (int)(fgFavourite2.getBlue()*0.8f), fgFavourite2.getAlpha());
if(itemPaneOpen) {
if(itemPaneTabOffset.getValue() == 0) {
@@ -1633,21 +1758,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()*64/20f, height/2f - 32, 64, 64);
+ 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 - 32
+ && mouseY < height/2 + 32) {
+ itemPaneOpen = true;
}
- } else {
- hoveringItemPaneToggle = false;
}
//Atomic reference used so that below lambda doesn't complain about non-effectively-final variable
@@ -1661,7 +1781,7 @@ public class NEUOverlay extends Gui {
leftSide+paneWidth-getBoxPadding()+5, height-getBoxPadding()+5, bg.getRGB());
renderNavElement(leftSide+getBoxPadding()+getItemBoxXPadding(), rightSide, getMaxPages(), page+1,
- scaledresolution.getScaleFactor()<4?"Page: ":"");
+ Utils.peekGuiScale().getScaleFactor()<4?"Page: ":"");
//Sort bar
drawRect(leftSide+getBoxPadding()+getItemBoxXPadding()-1,
@@ -1736,6 +1856,18 @@ public class NEUOverlay extends Gui {
millisLastMouseMove = System.currentTimeMillis();
}
+ if(selectedItemGroup != null) {
+ if(mouseX < selectedItemGroupX-1 || mouseX > selectedItemGroupX+17 ||
+ mouseY < selectedItemGroupY-1 || mouseY > selectedItemGroupY+17) {
+ int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size());
+ if(mouseX < selectedX-1 || mouseX > selectedX-1+18*selectedItemGroup.size() ||
+ mouseY < selectedItemGroupY+17 || mouseY > selectedItemGroupY+35) {
+ selectedItemGroup = null;
+ selectedItemMillis = -1;
+ }
+ }
+ }
+
if(!hoverInv) {
iterateItemSlots(new ItemSlotConsumer() {
public void consume(int x, int y, int id) {
@@ -1745,7 +1877,25 @@ public class NEUOverlay extends Gui {
}
if (mouseX > x - 1 && mouseX < x + ITEM_SIZE + 1) {
if (mouseY > y - 1 && mouseY < y + ITEM_SIZE + 1) {
- tooltipToDisplay.set(json);
+ String internalname = json.get("internalname").getAsString();
+ if(searchedItemsSubgroup.containsKey(internalname)) {
+ if(selectedItemMillis == -1) selectedItemMillis = System.currentTimeMillis();
+ if(System.currentTimeMillis() - selectedItemMillis > 200 &&
+ (selectedItemGroup == null || selectedItemGroup.isEmpty())) {
+
+ ArrayList<JsonObject> children = new ArrayList<>();
+ children.add(json);
+ for(String itemname : searchedItemsSubgroup.get(internalname)) {
+ children.add(manager.getItemInformation().get(itemname));
+ }
+
+ selectedItemGroup = children;
+ selectedItemGroupX = x;
+ selectedItemGroupY = y;
+ }
+ } else {
+ tooltipToDisplay.set(json);
+ }
}
}
}
@@ -1770,6 +1920,38 @@ public class NEUOverlay extends Gui {
renderItems(xStart, true, true, true);
}
+ if(selectedItemGroup != null) {
+ GL11.glTranslatef(0, 0, 10);
+
+ int selectedX = Math.min(selectedItemGroupX, width-getBoxPadding()-18*selectedItemGroup.size());
+
+ GlStateManager.depthFunc(GL11.GL_LESS);
+ drawRect(selectedX, selectedItemGroupY+18,
+ selectedX-2+18*selectedItemGroup.size(), selectedItemGroupY+34, fgCustomOpacity.getRGB());
+ drawRect(selectedX, selectedItemGroupY+18,
+ selectedX-1+18*selectedItemGroup.size(), selectedItemGroupY+35, new Color(30, 30, 30).getRGB());
+ drawRect(selectedX-1, selectedItemGroupY+17,
+ selectedX-2+18*selectedItemGroup.size(), selectedItemGroupY+34, new Color(180, 180, 180).getRGB());
+ GlStateManager.depthFunc(GL11.GL_LEQUAL);
+
+ GL11.glTranslatef(0, 0, 10);
+
+ tooltipToDisplay.set(null);
+ if(mouseY > selectedItemGroupY+17 && mouseY < selectedItemGroupY+35) {
+ for(int i=0; i<selectedItemGroup.size(); i++) {
+ if(mouseX >= selectedX-1+18*i && mouseX <= selectedX+17+18*i) {
+ tooltipToDisplay.set(selectedItemGroup.get(i));
+ }
+ }
+ }
+ for(int i=0; i<selectedItemGroup.size(); i++) {
+ JsonObject item = selectedItemGroup.get(i);
+ Utils.drawItemStack(manager.jsonToStack(item), selectedX+18*i, selectedItemGroupY+18);
+ }
+
+ GL11.glTranslatef(0, 0, -20);
+ }
+
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();
@@ -1792,64 +1974,96 @@ public class NEUOverlay extends Gui {
if(activeInfoPane != null) {
activeInfoPane.tick();
- activeInfoPane.render(width, height, bg, fg, scaledresolution, mouseX, mouseY);
+ activeInfoPane.render(width, height, bg, fg, Utils.peekGuiScale(), mouseX, mouseY);
GlStateManager.color(1f, 1f, 1f, 1f);
Minecraft.getMinecraft().getTextureManager().bindTexture(close);
- Utils.drawTexturedRect(rightSide-getBoxPadding()-8, getBoxPadding()-8, 16, 16);
+ if(activeInfoPane instanceof SettingsInfoPane) {
+ Utils.pushGuiScale(2);
+
+ int widthN = Utils.peekGuiScale().getScaledWidth();
+ int rightSideN = (int)(widthN*getInfoPaneOffsetFactor());
+ Utils.drawTexturedRect(rightSideN-getBoxPadding()-8, getBoxPadding()-8, 16, 16);
+
+ Utils.pushGuiScale(-1);
+ } else {
+ Utils.drawTexturedRect(rightSide-getBoxPadding()-8, getBoxPadding()-8, 16, 16);
+ }
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
//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);
- JsonObject bazaarInfo = manager.getBazaarInfo(internalname);
-
- boolean hasAuctionPrice = auctionInfo != null;
- boolean hasBazaarPrice = bazaarInfo != null;
+ JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname);
+ JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname);
int lowestBin = manager.auctionManager.getLowestBin(internalname);
+ APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(json.get("internalname").getAsString());
- NumberFormat format = NumberFormat.getInstance(Locale.US);
+ boolean hasAuctionPrice = !manager.config.invAuctionPrice.value && auctionInfo != null;
+ boolean hasBazaarPrice = !manager.config.invBazaarPrice.value && bazaarInfo != null;
+ boolean hasLowestBinPrice = !manager.config.invAuctionPrice.value && lowestBin > 0;
- NEUManager.CraftInfo craftCost = manager.getCraftCost(json.get("internalname").getAsString());
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
- if(hasAuctionPrice || hasBazaarPrice || craftCost.fromRecipe || lowestBin > 0) text.add("");
- if(lowestBin > 0) {
+ if(hasAuctionPrice || hasBazaarPrice || hasLowestBinPrice) text.add("");
+ if(hasLowestBinPrice) {
text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: "+
EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins");
}
- if(hasBazaarPrice) {
- int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat();
- text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+
- EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins");
- int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat();
- text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+
- EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins");
- if(manager.config.advancedPriceInfo.value) {
- int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat();
- text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+
- EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins");
- int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat();
- text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+
- EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins");
- }
- }
if(hasAuctionPrice) {
int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+
EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins");
+ if(manager.config.advancedPriceInfo.value) {
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day");
+ }
+ if(auctionInfo.has("clean_price")) {
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins");
+ if(manager.config.advancedPriceInfo.value) {
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day");
+ }
+ }
+
+ } else if(hasBazaarPrice) {
+ int stackMultiplier = 1;
+ int shiftStackMultiplier = 64;
+ if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ stackMultiplier = shiftStackMultiplier;
+ } else {
+ text.add(EnumChatFormatting.DARK_GRAY.toString()+"[SHIFT show x"+shiftStackMultiplier+"]");
+ }
+ if(bazaarInfo.has("avg_buy")) {
+ int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat()*stackMultiplier;
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins");
+ }
+ if(bazaarInfo.has("avg_sell")) {
+ int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat()*stackMultiplier;
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins");
+ }
+ if(manager.config.advancedPriceInfo.value) {
+ if(bazaarInfo.has("curr_buy")) {
+ int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat()*stackMultiplier;
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins");
+ }
+ if(bazaarInfo.has("curr_sell")) {
+ int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat()*stackMultiplier;
+ text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins");
+ }
+ }
}
- if(craftCost.fromRecipe) {
+ if((hasAuctionPrice || hasBazaarPrice) && craftCost.fromRecipe) {
text.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+
EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins");
}
@@ -1879,6 +2093,8 @@ public class NEUOverlay extends Gui {
GlStateManager.enableAlpha();
GlStateManager.alphaFunc(516, 0.1F);
GlStateManager.disableLighting();
+
+ Utils.pushGuiScale(-1);
}
/**
@@ -1904,8 +2120,8 @@ public class NEUOverlay extends Gui {
* itemPane should be redrawn.
*/
private void checkFramebufferSizes(int width, int height) {
- int sw = width*scaledresolution.getScaleFactor();
- int sh = height*scaledresolution.getScaleFactor();
+ int sw = width*Utils.peekGuiScale().getScaleFactor();
+ int sh = height*Utils.peekGuiScale().getScaleFactor();
for(int i=0; i<itemFramebuffers.length; i++) {
if(itemFramebuffers[i] == null || itemFramebuffers[i].framebufferWidth != sw || itemFramebuffers[i].framebufferHeight != sh) {
if(itemFramebuffers[i] == null) {
@@ -1936,8 +2152,8 @@ public class NEUOverlay extends Gui {
*/
private void renderItemsToImage(int width, int height, Color fgFavourite2,
Color fgFavourite, Color fgCustomOpacity, boolean items, boolean entities) {
- int sw = width*scaledresolution.getScaleFactor();
- int sh = height*scaledresolution.getScaleFactor();
+ int sw = width*Utils.peekGuiScale().getScaleFactor();
+ int sh = height*Utils.peekGuiScale().getScaleFactor();
GL11.glPushMatrix();
prepareFramebuffer(itemFramebuffers[0], sw, sh);
@@ -2158,6 +2374,14 @@ public class NEUOverlay extends Gui {
Utils.drawItemStackWithoutGlint(stack, x, y);
}
}
+
+ GlStateManager.translate(0, 0, 50);
+ if(searchedItemsSubgroup.containsKey(json.get("internalname").getAsString())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(item_haschild);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(x-1, y-1, ITEM_SIZE+2, ITEM_SIZE+2, GL11.GL_NEAREST);
+ }
+ GlStateManager.translate(0, 0, -50);
}
}, xStart);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
index 28ecbc8e..633c1c4b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlayPlacements.java
@@ -1,12 +1,12 @@
package io.github.moulberry.notenoughupdates;
-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.mbgui.*;
+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 net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
import org.lwjgl.util.vector.Vector2f;
@@ -22,22 +22,40 @@ public class NEUOverlayPlacements extends GuiScreen {
private MBGuiElement clickedElement;
private GuiButton guiButton = new GuiButton(0, 5, 5, "Reset to Default");
+ private boolean dropdownMenuShown = false;
+
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
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 {
guiButton.yPosition = 5;
}
+ EnumChatFormatting GOLD = EnumChatFormatting.GOLD;
+
guiButton.drawButton(Minecraft.getMinecraft(), mouseX, mouseY);
NotEnoughUpdates.INSTANCE.overlay.updateGuiGroupSize();
+ drawRect((width-176)/2, (height-166)/2,
+ (width+176)/2, (height+166)/2, new Color(100, 100, 100, 200).getRGB());
+ Utils.drawStringCentered(GOLD+"Inventory", Minecraft.getMinecraft().fontRendererObj, width/2f, height/2f, false, 0);
+
MBGuiGroupFloating mainGroup = NotEnoughUpdates.INSTANCE.overlay.guiGroup;
+ mainGroup.render(0, 0);
+ GlStateManager.translate(0, 0, 500);
for(MBGuiElement element : mainGroup.getChildren()) {
MBAnchorPoint anchorPoint = mainGroup.getChildrenMap().get(element);
Vector2f position = mainGroup.getChildrenPosition().get(element);
@@ -45,7 +63,6 @@ public class NEUOverlayPlacements extends GuiScreen {
drawRect((int)position.x, (int)position.y,
(int)position.x+element.getWidth(), (int)position.y+element.getHeight(), new Color(100, 100, 100, 200).getRGB());
-
switch(anchorPoint.anchorPoint) {
case TOPLEFT:
case TOPRIGHT:
@@ -84,13 +101,23 @@ public class NEUOverlayPlacements extends GuiScreen {
break;
}
+
+ if(anchorPoint.inventoryRelative) {
+ Utils.drawStringCentered(GOLD+"Inv-Relative", Minecraft.getMinecraft().fontRendererObj,
+ position.x+element.getWidth()*0.5f, position.y+element.getHeight()*0.5f, false, 0);
+ }
}
+ GlStateManager.translate(0, 0, -500);
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
+
+ if(mouseButton != 0 && mouseButton != 1) return;
+
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 +131,31 @@ 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();
+ if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) {
+ anchorPoint.inventoryRelative = !anchorPoint.inventoryRelative;
+ } else {
+ MBAnchorPoint.AnchorPoint[] vals = MBAnchorPoint.AnchorPoint.values();
+ anchorPoint.anchorPoint = vals[(anchorPoint.anchorPoint.ordinal()+1)%vals.length];
+
+ 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)) {
@@ -173,7 +209,7 @@ public class NEUOverlayPlacements extends GuiScreen {
}
index++;
}
-
+ try { MBDeserializer.serializeAndSave(mainGroup, "overlay"); } catch(Exception e) {}
mainGroup.recalculate();
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index a589fe2b..3ca2ab04 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -1,6 +1,7 @@
package io.github.moulberry.notenoughupdates;
import com.google.common.collect.Sets;
+import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.authlib.Agent;
import com.mojang.authlib.exceptions.AuthenticationException;
@@ -9,119 +10,190 @@ import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
import io.github.moulberry.notenoughupdates.commands.SimpleCommand;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import io.github.moulberry.notenoughupdates.cosmetics.GuiCosmetics;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonMap;
+import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
+import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor;
+import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes;
+import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes;
import io.github.moulberry.notenoughupdates.infopanes.CollectionLogInfoPane;
-import io.github.moulberry.notenoughupdates.infopanes.CosmeticsInfoPane;
+import io.github.moulberry.notenoughupdates.infopanes.SettingsInfoPane;
+import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats;
+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.SBInfo;
import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.material.MapColor;
import net.minecraft.client.Minecraft;
-import net.minecraft.client.gui.FontRenderer;
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.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.settings.KeyBinding;
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;
-import net.minecraft.inventory.IInventory;
-import net.minecraft.item.Item;
+import net.minecraft.event.HoverEvent;
+import net.minecraft.item.ItemMap;
import net.minecraft.item.ItemStack;
-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.minecraft.world.storage.MapData;
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.common.ForgeVersion;
import net.minecraftforge.common.MinecraftForge;
-import net.minecraftforge.event.entity.player.ItemTooltipEvent;
import net.minecraftforge.fml.client.registry.ClientRegistry;
+import net.minecraftforge.fml.common.Loader;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
+import net.minecraftforge.fml.common.ModContainer;
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.lwjgl.input.Keyboard;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.text.WordUtils;
+import org.apache.commons.lang3.text.translate.UnicodeUnescaper;
+import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.io.*;
+import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.net.Proxy;
-import java.text.NumberFormat;
+import java.net.*;
+import java.nio.charset.StandardCharsets;
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)
+@Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true)
public class NotEnoughUpdates {
public static final String MODID = "notenoughupdates";
- public static final String VERSION = "REL-1.0.0";
+ public static final String VERSION = "1.5-REL";
public static NotEnoughUpdates INSTANCE = null;
public NEUManager manager;
public NEUOverlay overlay;
- private NEUIO neuio;
private static final long CHAT_MSG_COOLDOWN = 200;
private long lastChatMessage = 0;
private long secondLastChatMessage = 0;
private String currChatMessage = null;
- private boolean hoverInv = false;
- private boolean focusInv = false;
-
- private boolean joinedSB = false;
-
//Stolen from Biscut and used for detecting whether in skyblock
- private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58");
-
- //Github Access Token, may change. Value hard-coded.
- //Token is obfuscated so that github doesn't delete it whenever I upload the jar.
- String[] token = new String[]{"b292496d2c","9146a","9f55d0868a545305a8","96344bf"};
- private String getAccessToken() {
- String s = "";
- for(String str : token) {
- s += str;
- }
- return s;
- }
+ private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58");
private GuiScreen openGui = null;
SimpleCommand collectionLogCommand = new SimpleCommand("neucl", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
if(!OpenGlHelper.isFramebufferEnabled()) {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
"This feature requires FBOs to work. Try disabling Optifine's 'Fast Render'."));
} else {
if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {
openGui = new GuiInventory(Minecraft.getMinecraft().thePlayer);
}
- manager.updatePrices();
overlay.displayInformationPane(new CollectionLogInfoPane(overlay, manager));
}
}
});
+ SimpleCommand itemRenameCommand = new SimpleCommand("neurename", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(args.length == 0) {
+ args = new String[]{"help"};
+ }
+ String heldUUID = manager.getUUIDForItem(Minecraft.getMinecraft().thePlayer.getHeldItem());
+ switch(args[0].toLowerCase()) {
+ case "clearall":
+ manager.itemRenameJson = new JsonObject();
+ manager.saveItemRenameConfig();
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for all items"));
+ break;
+ case "clear":
+ if(heldUUID == null) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID"));
+ return;
+ }
+ manager.itemRenameJson.remove(heldUUID);
+ manager.saveItemRenameConfig();
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Cleared custom name for held item"));
+ break;
+ case "copyuuid":
+ if(heldUUID == null) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't clear rename - no UUID"));
+ return;
+ }
+ StringSelection selection = new StringSelection(heldUUID);
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] UUID copied to clipboard"));
+ break;
+ case "uuid":
+ if(heldUUID == null) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't get UUID - no UUID"));
+ return;
+ }
+ ChatStyle style = new ChatStyle();
+ style.setChatHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
+ new ChatComponentText(EnumChatFormatting.GRAY+"Click to copy to clipboard")));
+ style.setChatClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "neurename copyuuid"));
+
+ ChatComponentText text = new ChatComponentText(EnumChatFormatting.YELLOW+"[NEU] The UUID of your currently held item is: " +
+ EnumChatFormatting.GREEN + heldUUID);
+ text.setChatStyle(style);
+ sender.addChatMessage(text);
+ break;
+ case "set":
+ if(heldUUID == null) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Can't rename item - no UUID"));
+ return;
+ }
+ if(args.length == 1) {
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Usage: /neurename set [name...]"));
+ return;
+ }
+ StringBuilder sb = new StringBuilder();
+ for(int i=1; i<args.length; i++) {
+ sb.append(args[i]);
+ if(i<args.length-1) sb.append(" ");
+ }
+ String name = sb.toString()
+ .replace("\\&", "{amp}")
+ .replace("&", "\u00a7")
+ .replace("{amp}", "&");
+ name = new UnicodeUnescaper().translate(name);
+ manager.itemRenameJson.addProperty(heldUUID, name);
+ manager.saveItemRenameConfig();
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN + "[NEU] Set custom name for held item"));
+ break;
+ default:
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "[NEU] Unknown subcommand \""+args[0]+"\""));
+ case "help":
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "[NEU] Available commands:"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "help: Print this message"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clearall: Clears all custom names "
+ + EnumChatFormatting.BOLD + "(Cannot be undone)"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "clear: Clears held item name "
+ + EnumChatFormatting.BOLD + "(Cannot be undone)"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "uuid: Returns the UUID of the currently held item"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "set: Sets the custom name of the currently held item"));
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Usage: /neurename set [name...]"));
+
+ }
+ }
+ });
+
SimpleCommand questingCommand = new SimpleCommand("neuquest", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
@@ -129,18 +201,612 @@ public class NotEnoughUpdates {
}
});
+ SimpleCommand gamemodesCommand = new SimpleCommand("neugamemodes", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ boolean upgradeOverride = args.length == 1 && args[0].equals("upgradeOverride");
+ openGui = new GuiGamemodes(upgradeOverride);
+ }
+ });
+
+ SimpleCommand enchantColourCommand = new SimpleCommand("neuec", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ openGui = new GuiEnchantColour();
+ }
+ });
+
+ SimpleCommand resetRepoCommand = new SimpleCommand("neuresetrepo", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ manager.resetRepo();
+ }
+ });
+
+ SimpleCommand dungeonWinTest = new SimpleCommand("neudungeonwintest", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(args.length > 0) {
+ DungeonWin.TEAM_SCORE = new ResourceLocation("notenoughupdates:dungeon_win/"+args[0].toLowerCase()+".png");
+ }
+
+ DungeonWin.displayWin();
+ }
+ });
+
+ SimpleCommand reloadRepoCommand = new SimpleCommand("neureloadrepo", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ File items = new File(manager.repoLocation, "items");
+ if(items.exists()) {
+ File[] itemFiles = new File(manager.repoLocation, "items").listFiles();
+ if(itemFiles != null) {
+ for(File f : itemFiles) {
+ String internalname = f.getName().substring(0, f.getName().length()-5);
+ manager.loadItem(internalname);
+ }
+ }
+ }
+ }
+ });
+
+ private static HashMap<String, String> petRarityToColourMap = new HashMap<>();
+ static {
+ petRarityToColourMap.put("UNKNOWN", EnumChatFormatting.RED.toString());
+
+ petRarityToColourMap.put("COMMON", EnumChatFormatting.WHITE.toString());
+ petRarityToColourMap.put("UNCOMMON", EnumChatFormatting.GREEN.toString());
+ petRarityToColourMap.put("RARE", EnumChatFormatting.BLUE.toString());
+ petRarityToColourMap.put("EPIC", EnumChatFormatting.DARK_PURPLE.toString());
+ petRarityToColourMap.put("LEGENDARY", EnumChatFormatting.GOLD.toString());
+ }
+ ScheduledExecutorService peekCommandExecutorService = null;
+ SimpleCommand peekCommand = new SimpleCommand("peek", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ String name;
+ if(args.length == 0) {
+ name = Minecraft.getMinecraft().thePlayer.getName();
+ } else {
+ name = args[0];
+ }
+ int id = new Random().nextInt(Integer.MAX_VALUE/2)+Integer.MAX_VALUE/2;
+
+ Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"[PEEK] Getting player information..."), id);
+ profileViewer.getProfileByName(name, profile -> {
+ if (profile == null) {
+ Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(
+ EnumChatFormatting.RED+"[PEEK] Unknown player or api is down."), id);
+ } else {
+ profile.resetCache();
+
+ if(peekCommandExecutorService == null || peekCommandExecutorService.isShutdown()) {
+ peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor();
+ } else {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED+"[PEEK] New peek command run, cancelling old one."));
+ peekCommandExecutorService.shutdownNow();
+ peekCommandExecutorService = Executors.newSingleThreadScheduledExecutor();
+ }
+
+ Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"[PEEK] Getting player skyblock profiles..."), id);
+
+ long startTime = System.currentTimeMillis();
+ peekCommandExecutorService.schedule(new Runnable() {
+ public void run() {
+ if(System.currentTimeMillis() - startTime > 10*1000) {
+
+ Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(
+ EnumChatFormatting.RED+"[PEEK] Getting profile info took too long, aborting."), id);
+ return;
+ }
+
+ String g = EnumChatFormatting.GRAY.toString();
+
+ JsonObject profileInfo = profile.getProfileInformation(null);
+ if(profileInfo != null) {
+ float overallScore = 0;
+
+ boolean isMe = name.equalsIgnoreCase("moulberry");
+
+ PlayerStats.Stats stats = profile.getStats(null);
+ JsonObject skill = profile.getSkillInfo(null);
+
+ Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessageWithOptionalDeletion(new ChatComponentText(EnumChatFormatting.GREEN+" "+
+ EnumChatFormatting.STRIKETHROUGH+"-=-" +EnumChatFormatting.RESET+EnumChatFormatting.GREEN+" "+
+ Utils.getElementAsString(profile.getHypixelProfile().get("displayname"), name) + "'s Info " +
+ EnumChatFormatting.STRIKETHROUGH+"-=-"), id);
+
+ if(skill == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"Skills api disabled!"));
+ } else {
+ float totalSkillLVL = 0;
+ float totalSkillCount = 0;
+
+ for(Map.Entry<String, JsonElement> entry : skill.entrySet()) {
+ if(entry.getKey().startsWith("level_skill")) {
+ if(entry.getKey().contains("runecrafting")) continue;
+ if(entry.getKey().contains("carpentry")) continue;
+ totalSkillLVL += entry.getValue().getAsFloat();
+ totalSkillCount++;
+ }
+ }
+
+ float combat = Utils.getElementAsFloat(skill.get("level_skill_combat"), 0);
+ float zombie = Utils.getElementAsFloat(skill.get("level_slayer_zombie"), 0);
+ float spider = Utils.getElementAsFloat(skill.get("level_slayer_spider"), 0);
+ float wolf = Utils.getElementAsFloat(skill.get("level_slayer_wolf"), 0);
+
+ float avgSkillLVL = totalSkillLVL/totalSkillCount;
+
+ if(isMe) {
+ avgSkillLVL = 6;
+ combat = 4;
+ zombie = 2;
+ spider = 1;
+ wolf = 2;
+ }
+
+ EnumChatFormatting combatPrefix = combat>20?(combat>35?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting zombiePrefix = zombie>3?(zombie>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting spiderPrefix = spider>3?(spider>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting wolfPrefix = wolf>3?(wolf>6?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting avgPrefix = avgSkillLVL>20?(avgSkillLVL>35?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+
+ overallScore += zombie*zombie/81f;
+ overallScore += spider*spider/81f;
+ overallScore += wolf*wolf/81f;
+ overallScore += avgSkillLVL/20f;
+
+ int cata = (int)Utils.getElementAsFloat(skill.get("level_skill_catacombs"), 0);
+ EnumChatFormatting cataPrefix = cata>15?(cata>25?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+
+ overallScore += cata*cata/2000f;
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ g+"Combat: "+combatPrefix+(int)Math.floor(combat) +
+ (cata > 0 ? g+" - Cata: "+cataPrefix+cata : "")+
+ g+" - AVG: " + avgPrefix+(int)Math.floor(avgSkillLVL)));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ g+"Slayer: "+zombiePrefix+(int)Math.floor(zombie)+g+"-"+
+ spiderPrefix+(int)Math.floor(spider)+g+"-"+wolfPrefix+(int)Math.floor(wolf)));
+ }
+ if(stats == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"Skills, collection and/or inventory apis disabled!"));
+ } else {
+ int health = (int)stats.get("health");
+ int defence = (int)stats.get("defence");
+ int strength = (int)stats.get("strength");
+ int intelligence = (int)stats.get("intelligence");
+
+ EnumChatFormatting healthPrefix = health>800?(health>1600?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting defencePrefix = defence>200?(defence>600?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting strengthPrefix = strength>100?(strength>300?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ EnumChatFormatting intelligencePrefix = intelligence>300?(intelligence>900?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ g+"Stats : "+healthPrefix+health+EnumChatFormatting.RED+"\u2764 "+
+ defencePrefix+defence+EnumChatFormatting.GREEN+"\u2748 "+
+ strengthPrefix+strength+EnumChatFormatting.RED+"\u2741 "+
+ intelligencePrefix+intelligence+EnumChatFormatting.AQUA+"\u270e "));
+ }
+ float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), -1);
+ float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
+
+ long networth = profile.getNetWorth(null);
+ float money = Math.max(bankBalance+purseBalance, networth);
+ EnumChatFormatting moneyPrefix = money>50*1000*1000?
+ (money>200*1000*1000?EnumChatFormatting.GREEN:EnumChatFormatting.YELLOW):EnumChatFormatting.RED;
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ g+"Purse: "+moneyPrefix+Utils.shortNumberFormat(purseBalance, 0) + g+" - Bank: " +
+ (bankBalance == -1 ? EnumChatFormatting.YELLOW+"N/A" : moneyPrefix+
+ (isMe?"4.8b":Utils.shortNumberFormat(bankBalance, 0))) +
+ (networth > 0 ? g+" - Net: "+moneyPrefix+Utils.shortNumberFormat(networth, 0) : "")));
+
+ overallScore += Math.min(2, money/(100f*1000*1000));
+
+ String activePet = Utils.getElementAsString(Utils.getElement(profile.getPetsInfo(null), "active_pet.type"),
+ "None Active");
+ String activePetTier = Utils.getElementAsString(Utils.getElement(profile.getPetsInfo(null), "active_pet.tier"), "UNKNOWN");
+
+ String col = petRarityToColourMap.get(activePetTier);
+ if(col == null) col = EnumChatFormatting.LIGHT_PURPLE.toString();
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g+"Pet : " +
+ col + WordUtils.capitalizeFully(activePet.replace("_", " "))));
+
+ String overall = "Skywars Main";
+ if(isMe) {
+ overall = Utils.chromaString("Literally the best player to exist");
+ } else if(overallScore < 5 && (bankBalance+purseBalance) > 500*1000*1000) {
+ overall = EnumChatFormatting.GOLD+"Bill Gates";
+ } else if(overallScore > 9) {
+ overall = Utils.chromaString("Didn't even think this score was possible");
+ } else if(overallScore > 8) {
+ overall = Utils.chromaString("Mentally unstable");
+ } else if(overallScore > 7) {
+ overall = EnumChatFormatting.GOLD+"Why though 0.0";
+ } else if(overallScore > 5.5) {
+ overall = EnumChatFormatting.GOLD+"Bro stop playing";
+ } else if(overallScore > 4) {
+ overall = EnumChatFormatting.GREEN+"Kinda sweaty";
+ } else if(overallScore > 3) {
+ overall = EnumChatFormatting.YELLOW+"Alright I guess";
+ } else if(overallScore > 2) {
+ overall = EnumChatFormatting.YELLOW+"Ender Non";
+ } else if(overallScore > 1) {
+ overall = EnumChatFormatting.RED+"Played Skyblock";
+ }
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(g+"Overall score: " +
+ overall + g + " (" + Math.round(overallScore*10)/10f + ")"));
+
+ peekCommandExecutorService.shutdownNow();
+ } else {
+ peekCommandExecutorService.schedule(this, 200, TimeUnit.MILLISECONDS);
+ }
+ }
+ }, 200, TimeUnit.MILLISECONDS);
+ }
+ });
+ }
+ }, 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 pcStatsCommand = new SimpleCommand("neustats", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ Minecraft mc = Minecraft.getMinecraft();
+ StringBuilder builder = new StringBuilder();
+
+ if (args.length > 0 && args[0].toLowerCase().equals("modlist")){
+ builder.append("```md\n");
+ builder.append("# Mods Loaded").append("\n");
+ for (ModContainer modContainer : Loader.instance().getActiveModList()) {
+ builder.append("[").append(modContainer.getName()).append("]")
+ .append("[").append(modContainer.getSource().getName()).append("]\n");
+ }
+ builder.append("```");
+ } else {
+ long memorySize = -1;
+ try {
+ memorySize = ((com.sun.management.OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean()).getTotalPhysicalMemorySize();
+ } catch(Exception e){}
+ long maxMemory = Runtime.getRuntime().maxMemory();
+ long totalMemory = Runtime.getRuntime().totalMemory();
+ long freeMemory = Runtime.getRuntime().freeMemory();
+ long currentMemory = totalMemory - freeMemory;
+ int modCount = Loader.instance().getModList().size();
+ int activeModCount = Loader.instance().getActiveModList().size();
+
+ builder.append("```md\n");
+ builder.append("# System Stats").append("\n");
+ builder.append("[OS]").append("[").append(System.getProperty("os.name")).append("]").append("\n");
+ builder.append("[CPU]").append("[").append(OpenGlHelper.getCpu()).append("]").append("\n");
+ builder.append("[Display]").append("[").append(String.format("%dx%d (%s)", Display.getWidth(), Display.getHeight(), GL11.glGetString(GL11.GL_VENDOR))).append("]").append("\n");
+ builder.append("[GPU]").append("[").append(GL11.glGetString(GL11.GL_RENDERER)).append("]").append("\n");
+ builder.append("[GPU Driver]").append("[").append(GL11.glGetString(GL11.GL_VERSION)).append("]").append("\n");
+ if(memorySize > 0) {
+ builder.append("[Maximum Memory]").append("[").append(memorySize / 1024L / 1024L).append("MB]").append("\n");
+ }
+ builder.append("[Shaders]").append("[").append((""+OpenGlHelper.areShadersSupported()).toUpperCase()).append("]").append("\n");
+ builder.append("[Framebuffers]").append("[").append((""+OpenGlHelper.isFramebufferEnabled()).toUpperCase()).append("]").append("\n");
+ builder.append("# Java Stats").append("\n");
+ builder.append("[Java]").append("[").append(String.format("%s %dbit", System.getProperty("java.version"), mc.isJava64bit() ? 64 : 32)).append("]").append("\n");
+ builder.append("[Memory]").append("[").append(String.format("% 2d%% %03d/%03dMB", currentMemory * 100L / maxMemory, currentMemory / 1024L / 1024L, maxMemory / 1024L / 1024L)).append("]").append("\n");
+ builder.append("[Memory Allocated]").append("[").append(String.format("% 2d%% %03dMB", totalMemory * 100L / maxMemory, totalMemory / 1024L / 1024L)).append("]").append("\n");
+ builder.append("# Game Stats").append("\n");
+ builder.append("[Current FPS]").append("[").append(Minecraft.getDebugFPS()).append("]").append("\n");
+ builder.append("[Loaded Mods]").append("[").append(activeModCount).append("/").append(modCount).append("]").append("\n");
+ builder.append("[Forge]").append("[").append(ForgeVersion.getVersion()).append("]").append("\n");
+ builder.append("# Neu Settings").append("\n");
+ builder.append("[API Key]").append("[").append(!INSTANCE.manager.config.apiKey.value.isEmpty()).append("]").append("\n");
+ builder.append("[On Skyblock]").append("[").append(hasSkyblockScoreboard).append("]").append("\n");
+ builder.append("[Mod Version]").append("[").append(Loader.instance().getIndexedModList().get(MODID).getSource().getName()).append("]").append("\n");
+ builder.append("# Repo Stats").append("\n");
+ builder.append("[Last Commit]").append("[").append(manager.latestRepoCommit).append("]").append("\n");
+ builder.append("[Loaded Items]").append("[").append(manager.getItemInformation().size()).append("]").append("\n");
+ if (activeModCount <= 15) {
+ builder.append("# Mods Loaded").append("\n");
+ for (ModContainer modContainer : Loader.instance().getActiveModList()) {
+ builder.append("[").append(modContainer.getName()).append("]")
+ .append("[").append(modContainer.getSource().getName()).append("]\n");
+ }
+ builder.append("```");
+ } else {
+ builder.append("```");
+ }
+ }
+ try {
+ StringSelection clipboard = new StringSelection(builder.toString());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(clipboard, clipboard);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + EnumChatFormatting.GREEN + "Dev info copied to clipboard."));
+ } catch (Exception ignored) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "[" + EnumChatFormatting.RED + "NotEnoughUpdates" + EnumChatFormatting.GOLD + "]: " + EnumChatFormatting.DARK_RED + "Could not copy to clipboard."));
+ }
+ }
+ });
+
+ public static ProfileViewer profileViewer;
+
+ SimpleCommand.ProcessCommandRunnable viewProfileRunnable = new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(Loader.isModLoaded("optifine") &&
+ new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt").exists()) {
+ try(InputStream in = new FileInputStream(new File(Minecraft.getMinecraft().mcDataDir, "optionsof.txt"))) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
+
+ String line;
+ while((line = reader.readLine()) != null) {
+ if(line.contains("ofFastRender:true")) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "Some parts of the profile viewer do not work with OF Fast Render. Go to Video > Performance to disable it."));
+ break;
+ }
+ }
+ } catch(Exception e) {
+ }
+ }
+ 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) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "Invalid player name/api key. Maybe api is down? Try /api new."));
+ } else {
+ 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) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED +
+ "Invalid player name/api key. Maybe api is down? Try /api new."));
+ } else {
+ 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(!isOnSkyblock()) {
+ 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(!isOnSkyblock()) {
+ 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();
+ }
+ });
+
+ public Color[][] colourMap = null;
+ SimpleCommand neumapCommand = new SimpleCommand("neumap", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ if(colourMap == null) {
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:maps/F1Full.json")).getInputStream(), StandardCharsets.UTF_8))) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class);
+
+ colourMap = new Color[128][128];
+ for(int x=0; x<128; x++) {
+ for(int y=0; y<128; y++) {
+ colourMap[x][y] = new Color(0, 0, 0, 0);
+ }
+ }
+ for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
+ int x = Integer.parseInt(entry.getKey().split(":")[0]);
+ int y = Integer.parseInt(entry.getKey().split(":")[1]);
+
+ colourMap[x][y] = new Color(entry.getValue().getAsInt(), true);
+ }
+ } catch(Exception ignored) { }
+ }
+
+ if(!manager.config.dev.value) {
+ openGui = new GuiDungeonMapEditor();
+ return;
+ }
+
+ if(args.length == 1 && args[0].equals("reset")) {
+ colourMap = null;
+ return;
+ }
+
+ if(args.length != 2) {
+ openGui = new GuiDungeonMapEditor();
+ return;
+ }
+
+ if(args[0].equals("save")) {
+ ItemStack stack = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ if(stack != null && stack.getItem() instanceof ItemMap) {
+ ItemMap map = (ItemMap) stack.getItem();
+ MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld);
+
+ if (mapData == null) return;
+
+ JsonObject json = new JsonObject();
+ for (int i = 0; i < 16384; ++i) {
+ int x = i % 128;
+ int y = i / 128;
+
+ int j = mapData.colors[i] & 255;
+
+ Color c;
+ if (j / 4 == 0) {
+ c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true);
+ } else {
+ c = new Color(MapColor.mapColorArray[j / 4].func_151643_b(j & 3), true);
+ }
+
+ json.addProperty(x+":"+y, c.getRGB());
+ }
+
+ try {
+ new File(manager.configLocation, "maps").mkdirs();
+ manager.writeJson(json, new File(manager.configLocation, "maps/"+args[1]+".json"));
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+
+ "Saved to file."));
+ }
+
+ return;
+ }
+
+ if(args[0].equals("load")) {
+ JsonObject json = manager.getJsonFromFile(new File(manager.configLocation, "maps/"+args[1]+".json"));
+
+ colourMap = new Color[128][128];
+ for(int x=0; x<128; x++) {
+ for(int y=0; y<128; y++) {
+ colourMap[x][y] = new Color(0, 0, 0, 0);
+ }
+ }
+ for(Map.Entry<String, JsonElement> entry : json.entrySet()) {
+ int x = Integer.parseInt(entry.getKey().split(":")[0]);
+ int y = Integer.parseInt(entry.getKey().split(":")[1]);
+
+ colourMap[x][y] = new Color(entry.getValue().getAsInt(), true);
+ }
+
+ return;
+ }
+
+ openGui = new GuiDungeonMapEditor();
+ }
+ });
+
SimpleCommand cosmeticsCommand = new SimpleCommand("neucosmetics", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
+ openGui = new GuiCosmetics();
+ }
+ });
+
+ SimpleCommand settingsCommand = new SimpleCommand("neusettings", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ overlay.displayInformationPane(new SettingsInfoPane(overlay, manager));
+ if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {
+ openGui = new GuiInventory(Minecraft.getMinecraft().thePlayer);
+ }
+ }
+ });
+
+ SimpleCommand settingsCommand2 = new SimpleCommand("neuconfig", new SimpleCommand.ProcessCommandRunnable() {
+ public void processCommand(ICommandSender sender, String[] args) {
+ overlay.displayInformationPane(new SettingsInfoPane(overlay, manager));
if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) {
openGui = new GuiInventory(Minecraft.getMinecraft().thePlayer);
}
- overlay.displayInformationPane(new CosmeticsInfoPane(overlay, manager));
}
});
@@ -151,12 +817,14 @@ 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();
manager.auctionManager.customAH.clearSearch();
manager.auctionManager.customAH.updateSearch();
+
+ if(args.length > 0) manager.auctionManager.customAH.setSearch(StringUtils.join(args, " "));
}
}
});
@@ -168,21 +836,43 @@ public class NotEnoughUpdates {
@EventHandler
public void preinit(FMLPreInitializationEvent event) {
INSTANCE = this;
+
MinecraftForge.EVENT_BUS.register(this);
+ MinecraftForge.EVENT_BUS.register(new NEUEventListener(this));
MinecraftForge.EVENT_BUS.register(CapeManager.getInstance());
+ MinecraftForge.EVENT_BUS.register(new SBGamemodes());
+ MinecraftForge.EVENT_BUS.register(SBInfo.getInstance());
+ MinecraftForge.EVENT_BUS.register(CustomItemEffects.INSTANCE);
+ MinecraftForge.EVENT_BUS.register(new DungeonMap());
+ //MinecraftForge.EVENT_BUS.register(new BetterPortals());
File f = new File(event.getModConfigurationDirectory(), "notenoughupdates");
f.mkdirs();
ClientCommandHandler.instance.registerCommand(collectionLogCommand);
ClientCommandHandler.instance.registerCommand(cosmeticsCommand);
+ ClientCommandHandler.instance.registerCommand(linksCommand);
+ ClientCommandHandler.instance.registerCommand(gamemodesCommand);
+ ClientCommandHandler.instance.registerCommand(resetRepoCommand);
+ ClientCommandHandler.instance.registerCommand(reloadRepoCommand);
+ ClientCommandHandler.instance.registerCommand(itemRenameCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileShortCommand);
+ ClientCommandHandler.instance.registerCommand(viewProfileShort2Command);
+ ClientCommandHandler.instance.registerCommand(peekCommand);
+ ClientCommandHandler.instance.registerCommand(tutorialCommand);
ClientCommandHandler.instance.registerCommand(overlayPlacementsCommand);
- //ClientCommandHandler.instance.registerCommand(questingCommand);
+ ClientCommandHandler.instance.registerCommand(enchantColourCommand);
ClientCommandHandler.instance.registerCommand(neuAhCommand);
+ ClientCommandHandler.instance.registerCommand(pcStatsCommand);
+ ClientCommandHandler.instance.registerCommand(neumapCommand);
+ ClientCommandHandler.instance.registerCommand(settingsCommand);
+ ClientCommandHandler.instance.registerCommand(settingsCommand2);
+ ClientCommandHandler.instance.registerCommand(dungeonWinTest);
- neuio = new NEUIO(getAccessToken());
- manager = new NEUManager(this, neuio, f);
+ manager = new NEUManager(this, f);
manager.loadItemInformation();
overlay = new NEUOverlay(manager);
+ profileViewer = new ProfileViewer(manager);
for(KeyBinding kb : manager.keybinds) {
ClientRegistry.registerKeyBinding(kb);
@@ -203,7 +893,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 +922,7 @@ public class NotEnoughUpdates {
field.setAccessible(true);
field.set(Minecraft.getMinecraft(), session);
} catch (NoSuchFieldException | AuthenticationException | IllegalAccessException e) {
- }*/
+ }
}
/**
@@ -250,814 +940,117 @@ public class NotEnoughUpdates {
}
}
- /**
- * 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<>();
- @SubscribeEvent
- public void onTick(TickEvent.ClientTickEvent event) {
- 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) {}
- }
- }
- //NEUQuesting.getInstance().tick();
- //GuiQuestLine.questLine.tick();
- }
- if(currChatMessage != null && System.currentTimeMillis() - lastChatMessage > CHAT_MSG_COOLDOWN) {
- lastChatMessage = System.currentTimeMillis();
- 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(stack.hasTagCompound()) {
- NBTTagCompound tag = stack.getTagCompound();
- if(tag.hasKey("ExtraAttributes", 10)) {
- continue;
- }
- }
- usableContainer = false;
- break;
- }
- if(!usableContainer) {
- if(Minecraft.getMinecraft().currentScreen instanceof GuiChest) {
- GuiChest chest = (GuiChest) Minecraft.getMinecraft().currentScreen;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- if(containerName.equals("Accessory Bag")) {
- usableContainer = true;
- }
- }
- }
- if(usableContainer) {
- for(ItemStack stack : Minecraft.getMinecraft().thePlayer.openContainer.getInventory()) {
- processUniqueStack(stack, newItem);
- }
- 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);
- }
- }
-
- private void processUniqueStack(ItemStack stack, HashSet<String> newItem) {
- if(stack != null && stack.hasTagCompound()) {
- String internalname = manager.getInternalNameForItem(stack);
- if(internalname != null) {
- ArrayList<String> log = manager.config.collectionLog.value.computeIfAbsent(
- manager.getCurrentProfile(), k -> new ArrayList<>());
- if(!log.contains(internalname)) {
- newItem.add(internalname);
- if(newItemAddMap.containsKey(internalname)) {
- if(System.currentTimeMillis() - newItemAddMap.get(internalname) > 1000) {
- log.add(internalname);
- }
- } else {
- newItemAddMap.put(internalname, System.currentTimeMillis());
- }
- }
- }
- }
- }
-
- @SubscribeEvent
- public void onRenderGameOverlay(RenderGameOverlayEvent event) {
- if(event.type != null && event.type.equals(RenderGameOverlayEvent.ElementType.BOSSHEALTH) &&
- Minecraft.getMinecraft().currentScreen instanceof GuiContainer && overlay.isUsingMobsFilter()) {
- event.setCanceled(true);
- }
- }
-
- /**
- * When opening a GuiContainer, will reset the overlay and load the config.
- * When closing a GuiContainer, will save the config.
- * Also includes a dev feature used for automatically acquiring crafting information from the "Crafting Table" GUI.
- */
- AtomicBoolean missingRecipe = new AtomicBoolean(false);
- @SubscribeEvent
- public void onGuiOpen(GuiOpenEvent event) {
- manager.auctionManager.customAH.lastGuiScreenSwitch = System.currentTimeMillis();
-
- if(event.gui == null && manager.auctionManager.customAH.isRenderOverAuctionView() &&
- !(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)) {
- event.gui = new CustomAHGui();
+ public 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));
}
-
- if(!(event.gui instanceof GuiChest || event.gui instanceof GuiEditSign)) {
- manager.auctionManager.customAH.setRenderOverAuctionView(false);
- } else if(event.gui instanceof GuiChest && (manager.auctionManager.customAH.isRenderOverAuctionView() ||
- Minecraft.getMinecraft().currentScreen instanceof CustomAHGui)){
- GuiChest chest = (GuiChest) event.gui;
- ContainerChest container = (ContainerChest) chest.inventorySlots;
- String containerName = container.getLowerChestInventory().getDisplayName().getUnformattedText();
-
- manager.auctionManager.customAH.setRenderOverAuctionView(containerName.trim().equals("Auction View") ||
- containerName.trim().equals("BIN Auction View") || containerName.trim().equals("Confirm Bid"));
+ 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);
}
- //OPEN
- if(Minecraft.getMinecraft().currentScreen == null
- && event.gui instanceof GuiContainer) {
- overlay.reset();
- manager.loadConfig();
- }
- //CLOSE
- if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer
- && event.gui == null) {
- try {
- manager.saveConfig();
- } catch(IOException e) {}
- }
- if(event.gui != null && manager.config.dev.value) {
- if(event.gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) event.gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
- ses.schedule(() -> {
- if(Minecraft.getMinecraft().currentScreen != event.gui) {
- return;
- }
- if(lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
- try {
- ItemStack res = lower.getStackInSlot(25);
- String resInternalname = manager.getInternalNameForItem(res);
-
- if(lower.getStackInSlot(48) != null) {
- String backName = null;
- NBTTagCompound tag = lower.getStackInSlot(48).getTagCompound();
- if(tag.hasKey("display", 10)) {
- NBTTagCompound nbttagcompound = tag.getCompoundTag("display");
- if(nbttagcompound.getTagId("Lore") == 9){
- NBTTagList nbttaglist1 = nbttagcompound.getTagList("Lore", 8);
- backName = nbttaglist1.getStringTagAt(0);
- }
- }
-
- if(backName != null) {
- String[] split = backName.split(" ");
- if(split[split.length-1].contains("Rewards")) {
- String col = backName.substring(split[0].length()+1,
- backName.length()-split[split.length-1].length()-1);
-
- JsonObject json = manager.getItemInformation().get(resInternalname);
- json.addProperty("crafttext", "Requires: " + col);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
- manager.writeJsonDefaultDir(json, resInternalname+".json");
- manager.loadItem(resInternalname);
- }
- }
- }
-
- /*JsonArray arr = null;
- File f = new File(manager.configLocation, "missing.json");
- try(InputStream instream = new FileInputStream(f)) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
- JsonObject json = manager.gson.fromJson(reader, JsonObject.class);
- arr = json.getAsJsonArray("missing");
- } catch(IOException e) {}
- try {
- JsonObject json = new JsonObject();
- JsonArray newArr = new JsonArray();
- for(JsonElement e : arr) {
- if(!e.getAsString().equals(resInternalname)) {
- newArr.add(e);
- }
- }
- json.add("missing", newArr);
- manager.writeJson(json, f);
- } catch(IOException e) {}*/
-
-
-
- /*JsonObject recipe = new JsonObject();
-
- String[] x = {"1","2","3"};
- String[] y = {"A","B","C"};
-
- for(int i=0; i<=18; i+=9) {
- for(int j=0; j<3; j++) {
- ItemStack stack = lower.getStackInSlot(10+i+j);
- String internalname = "";
- if(stack != null) {
- internalname = manager.getInternalNameForItem(stack);
- if(!manager.getItemInformation().containsKey(internalname)) {
- manager.writeItemToFile(stack);
- }
- internalname += ":"+stack.stackSize;
- }
- recipe.addProperty(y[i/9]+x[j], internalname);
- }
- }
-
- JsonObject json = manager.getJsonForItem(res);
- json.add("recipe", recipe);
- json.addProperty("internalname", resInternalname);
- json.addProperty("clickcommand", "viewrecipe");
- json.addProperty("modver", NotEnoughUpdates.VERSION);
-
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
- manager.writeJsonDefaultDir(json, resInternalname+".json");
- manager.loadItem(resInternalname);*/
- } catch(Exception e) {
- e.printStackTrace();
- }
- }
- }, 200, TimeUnit.MILLISECONDS);
- return;
- }
- }
+ Minecraft.getMinecraft().thePlayer.addChatMessage(links);
}
- /**
- * 1) When receiving "You are playing on profile" messages, will set the current profile.
- * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI)
- * 3) Replaces lobby join notifications when streamer mode is active
- */
- @SubscribeEvent(priority = EventPriority.LOW)
- public void onGuiChat(ClientChatReceivedEvent e) {
- String r = null;
- String unformatted = Utils.cleanColour(e.message.getUnformattedText());
- if(unformatted.startsWith("You are playing on profile: ")) {
- manager.setCurrentProfile(unformatted.substring("You are playing on profile: ".length()).split(" ")[0].trim());
- } else if(unformatted.startsWith("Your profile was changed to: ")) {//Your profile was changed to:
- manager.setCurrentProfile(unformatted.substring("Your profile was changed to: ".length()).split(" ")[0].trim());
- } else if(unformatted.startsWith("Your new API key is ")) {
- manager.config.apiKey.value = unformatted.substring("Your new API key is ".length());
- try { manager.saveConfig(); } catch(IOException ioe) {}
- }
- if(e.message.getFormattedText().equals(EnumChatFormatting.RESET.toString()+
- EnumChatFormatting.RED+"You haven't unlocked this recipe!"+EnumChatFormatting.RESET)) {
- r = EnumChatFormatting.RED+"You haven't unlocked this recipe!";
- } else if(e.message.getFormattedText().startsWith(EnumChatFormatting.RESET.toString()+
- EnumChatFormatting.RED+"Invalid recipe ")) {
- r = "";
- }
- if(r != null) {
- if(manager.failViewItem(r)) {
- e.setCanceled(true);
- }
- missingRecipe.set(true);
- }
- //System.out.println(e.message);
- if(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)) {
- e.message = new ChatComponentText(m2);
- }
- }
- }
-
- /**
- * Sets hoverInv and focusInv variables, representing whether the NEUOverlay should render behind the inventory when
- * (hoverInv == true) and whether mouse/kbd inputs shouldn't be sent to NEUOverlay (focusInv == true).
- *
- * If hoverInv is true, will render the overlay immediately (resulting in the inventory being drawn over the GUI)
- * If hoverInv is false, the overlay will render in #onGuiScreenDraw (resulting in the GUI being drawn over the inv)
- *
- * All of this only matters if players are using gui scale auto which may result in the inventory being drawn
- * over the various panes.
- * @param event
- */
@SubscribeEvent
- public void onGuiBackgroundDraw(GuiScreenEvent.BackgroundDrawnEvent event) {
- if((event.gui instanceof GuiContainer || event.gui instanceof CustomAHGui) && isOnSkyblock()) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledresolution.getScaledWidth();
-
- boolean hoverPane = event.getMouseX() < width*overlay.getInfoPaneOffsetFactor() ||
- event.getMouseX() > width*overlay.getItemPaneOffsetFactor();
-
- if(event.gui instanceof GuiContainer) {
- try {
- int xSize = (int) Utils.getField(GuiContainer.class, event.gui, "xSize", "field_146999_f");
- int ySize = (int) Utils.getField(GuiContainer.class, event.gui, "ySize", "field_147000_g");
- int guiLeft = (int) Utils.getField(GuiContainer.class, event.gui, "guiLeft", "field_147003_i");
- int guiTop = (int) Utils.getField(GuiContainer.class, event.gui, "guiTop", "field_147009_r");
-
- hoverInv = event.getMouseX() > guiLeft && event.getMouseX() < guiLeft + xSize &&
- event.getMouseY() > guiTop && event.getMouseY() < guiTop + ySize;
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if (event.phase != TickEvent.Phase.START) return;
+ long currentTime = System.currentTimeMillis();
- if(hoverPane) {
- if(!hoverInv) focusInv = false;
- } else {
- focusInv = true;
- }
- } catch(NullPointerException npe) {
- 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 (openGui != null) {
+ if(Minecraft.getMinecraft().thePlayer.openContainer != null) {
+ Minecraft.getMinecraft().thePlayer.closeScreen();
}
+ Minecraft.getMinecraft().displayGuiScreen(openGui);
+ openGui = null;
}
- }
-
- @SubscribeEvent
- public void onGuiScreenDrawPre(GuiScreenEvent.DrawScreenEvent.Pre event) {
- if(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView()) {
- event.setCanceled(true);
-
- ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
- int width = scaledResolution.getScaledWidth();
- int height = scaledResolution.getScaledHeight();
-
- //Dark background
- Utils.drawGradientRect(0, 0, width, height, -1072689136, -804253680);
-
- if(event.mouseX < width*overlay.getWidthMult()/3 || event.mouseX > width-width*overlay.getWidthMult()/3) {
- manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
- overlay.render(event.mouseX, event.mouseY, false);
- } else {
- overlay.render(event.mouseX, event.mouseY, false);
- manager.auctionManager.customAH.drawScreen(event.mouseX, event.mouseY);
- }
-
+ if(currChatMessage != null && currentTime - lastChatMessage > CHAT_MSG_COOLDOWN) {
+ lastChatMessage = currentTime;
+ Minecraft.getMinecraft().thePlayer.sendChatMessage(currChatMessage);
+ currChatMessage = null;
}
}
- /**
- * 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))
- * @param event
- */
- @SubscribeEvent
- public void onGuiScreenDrawPost(GuiScreenEvent.DrawScreenEvent.Post event) {
- if(!(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView())) {
- if(event.gui instanceof GuiContainer && isOnSkyblock()) {
-
- renderDungeonChestOverlay(event.gui);
-
- if(!focusInv) {
- GL11.glTranslatef(0, 0, 300);
- overlay.render(event.mouseX, event.mouseY, hoverInv && focusInv);
- GL11.glTranslatef(0, 0, -300);
- }
- overlay.renderOverlay(event.mouseX, event.mouseY);
- }
- }
+ public boolean isOnSkyblock() {
+ if(!manager.config.onlyShowOnSkyblock.value) return true;
+ return hasSkyblockScoreboard();
}
- private void renderDungeonChestOverlay(GuiScreen gui) {
- if(gui instanceof GuiChest && manager.auctionManager.activeAuctions > 0) {
- try {
- int xSize = (int) Utils.getField(GuiContainer.class, gui, "xSize", "field_146999_f");
- int ySize = (int) Utils.getField(GuiContainer.class, gui, "ySize", "field_147000_g");
- int guiLeft = (int) Utils.getField(GuiContainer.class, gui, "guiLeft", "field_147003_i");
- int guiTop = (int) Utils.getField(GuiContainer.class, gui, "guiTop", "field_147009_r");
-
- GuiChest eventGui = (GuiChest) gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- ItemStack rewardChest = lower.getStackInSlot(31);
- if (rewardChest != null && rewardChest.getDisplayName().endsWith(EnumChatFormatting.GREEN+"Open Reward Chest")) {
- int chestCost = 0;
- String line6 = Utils.cleanColour(manager.getLoreFromNBT(rewardChest.getTagCompound())[6]);
- StringBuilder cost = new StringBuilder();
- for(int i=0; i<line6.length(); i++) {
- char c = line6.charAt(i);
- if("0123456789".indexOf(c) >= 0) {
- cost.append(c);
- }
- }
- if(cost.length() > 0) {
- chestCost = Integer.parseInt(cost.toString());
- }
-
- boolean missing = false;
- int totalValue = 0;
- for(int i=0; i<5; i++) {
- ItemStack item = lower.getStackInSlot(11+i);
- String internal = manager.getInternalNameForItem(item);
- if(internal != null) {
- int worth = manager.auctionManager.getLowestBin(internal);
- if(worth > 0) {
- totalValue += worth;
- } else {
- missing = true;
- break;
- }
- }
- }
- int profitLoss = totalValue - chestCost;
-
- NumberFormat format = NumberFormat.getInstance(Locale.US);
- String valueString;
- if(!missing) {
- valueString = EnumChatFormatting.BLUE+"Chest value: " + EnumChatFormatting.GOLD
- + EnumChatFormatting.BOLD + format.format(totalValue) + " coins";
- } else {
- valueString = EnumChatFormatting.BLUE+"Couldn't find item on AH. Item is very rare!";
- }
- String plString;
- if(missing) {
- plString = "";
- } else if(profitLoss >= 0) {
- plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.DARK_GREEN
- + EnumChatFormatting.BOLD + "+" + format.format(profitLoss) + " coins";
- } else {
- plString = EnumChatFormatting.BLUE+"Profit/loss: " + EnumChatFormatting.RED
- + EnumChatFormatting.BOLD + "-" + format.format(-profitLoss) + " coins";
- }
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(dungeon_chest_worth);
- GL11.glColor4f(1, 1, 1, 1);
- GlStateManager.disableLighting();
- Utils.drawTexturedRect(guiLeft+xSize+4, guiTop, 180, 45, 0, 180/256f, 0, 45/256f, GL11.GL_NEAREST);
+ private boolean hasSkyblockScoreboard;
- Utils.drawStringCenteredScaledMaxWidth(valueString, Minecraft.getMinecraft().fontRendererObj, guiLeft+xSize+4+90,
- 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();
- }
- }
+ public boolean hasSkyblockScoreboard() {
+ return hasSkyblockScoreboard;
}
- /**
- * Sends a mouse event to NEUOverlay if the inventory isn't hovered AND focused.
- * Will also cancel the event if if NEUOverlay#mouseInput returns true.
- * @param event
- */
- @SubscribeEvent
- public void onGuiScreenMouse(GuiScreenEvent.MouseInputEvent.Pre event) {
- if(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView()) {
- event.setCanceled(true);
- manager.auctionManager.customAH.handleMouseInput();
- overlay.mouseInput();
- return;
- }
- if(event.gui instanceof GuiContainer && !(hoverInv && focusInv) && isOnSkyblock()) {
- if(overlay.mouseInput()) {
- event.setCanceled(true);
- }
- }
- }
+ //Stolen from Biscut's SkyblockAddons
+ public void updateSkyblockScoreboard() {
+ final Pattern SERVER_BRAND_PATTERN = Pattern.compile("(.+) <- (?:.+)");
+ final String HYPIXEL_SERVER_BRAND = "BungeeCord (Hypixel)";
- ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+ Minecraft mc = Minecraft.getMinecraft();
- /**
- * Sends a kbd event to NEUOverlay, cancelling if NEUOverlay#keyboardInput returns true.
- * Also includes a dev function used for creating custom named json files with recipes.
- */
- @SubscribeEvent
- public void onGuiScreenKeyboard(GuiScreenEvent.KeyboardInputEvent.Pre event) {
- if(event.gui instanceof CustomAHGui || manager.auctionManager.customAH.isRenderOverAuctionView()) {
- if(manager.auctionManager.customAH.keyboardInput()) {
- event.setCanceled(true);
- Minecraft.getMinecraft().dispatchKeypresses();
- } else if(overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
- }
- return;
- }
+ if (mc != null && mc.theWorld != null && mc.thePlayer != null) {
+ if (!mc.isSingleplayer() && mc.thePlayer.getClientBrand() != null) {
+ Matcher matcher = SERVER_BRAND_PATTERN.matcher(mc.thePlayer.getClientBrand());
- if(event.gui instanceof GuiContainer && isOnSkyblock()) {
- if(overlay.keyboardInput(focusInv)) {
- event.setCanceled(true);
- }
- }
- if(manager.config.dev.value && manager.config.enableItemEditing.value && Minecraft.getMinecraft().theWorld != null &&
- Keyboard.getEventKey() == Keyboard.KEY_O && Keyboard.getEventKeyState()) {
- GuiScreen gui = Minecraft.getMinecraft().currentScreen;
- if(gui instanceof GuiChest) {
- GuiChest eventGui = (GuiChest) event.gui;
- ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
- IInventory lower = cc.getLowerChestInventory();
-
- if(lower.getStackInSlot(23) != null &&
- lower.getStackInSlot(23).getDisplayName().endsWith("Crafting Table")) {
- ItemStack res = lower.getStackInSlot(25);
- String resInternalname = manager.getInternalNameForItem(res);
- JTextField tf = new JTextField();
- tf.setText(resInternalname);
- tf.addAncestorListener(new RequestFocusListener());
- JOptionPane.showOptionDialog(null,
- tf,
- "Enter Name:",
- JOptionPane.NO_OPTION,
- JOptionPane.PLAIN_MESSAGE,
- null, new String[]{"Enter"}, "Enter");
- resInternalname = tf.getText();
- if(resInternalname.trim().length() == 0) {
+ if (matcher.find()) {
+ // Group 1 is the server brand.
+ if(!matcher.group(1).equals(HYPIXEL_SERVER_BRAND)) {
+ hasSkyblockScoreboard = false;
return;
}
-
- JsonObject recipe = new JsonObject();
-
- String[] x = {"1","2","3"};
- String[] y = {"A","B","C"};
-
- for(int i=0; i<=18; i+=9) {
- for(int j=0; j<3; j++) {
- ItemStack stack = lower.getStackInSlot(10+i+j);
- String internalname = "";
- if(stack != null) {
- internalname = manager.getInternalNameForItem(stack);
- if(!manager.getItemInformation().containsKey(internalname)) {
- manager.writeItemToFile(stack);
- }
- internalname += ":"+stack.stackSize;
- }
- recipe.addProperty(y[i/9]+x[j], internalname);
- }
- }
-
- JsonObject json = manager.getJsonForItem(res);
- json.add("recipe", recipe);
- json.addProperty("internalname", resInternalname);
- json.addProperty("clickcommand", "viewrecipe");
- json.addProperty("modver", NotEnoughUpdates.VERSION);
- try {
- Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + resInternalname));
- manager.writeJsonDefaultDir(json, resInternalname+".json");
- manager.loadItem(resInternalname);
- } catch(IOException e) {}
- }
- }
- }
- /*if(Minecraft.getMinecraft().theWorld != null && Keyboard.getEventKey() == Keyboard.KEY_RBRACKET && Keyboard.getEventKeyState()) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- started = true;
- final Object[] items = manager.getItemInformation().values().toArray();
- AtomicInteger i = new AtomicInteger(0);
-
- Runnable checker = new Runnable() {
- @Override
- public void run() {
- int in = i.getAndIncrement();
- /*if(missingRecipe.get()) {
- String internalname = ((JsonObject)items[in]).get("internalname").getAsString();
-
- JsonArray arr = null;
- File f = new File(manager.configLocation, "missing.json");
- try(InputStream instream = new FileInputStream(f)) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(instream, StandardCharsets.UTF_8));
- JsonObject json = manager.gson.fromJson(reader, JsonObject.class);
- arr = json.getAsJsonArray("missing");
- } catch(IOException e) {}
-
- try {
- JsonObject json = new JsonObject();
- if(arr == null) arr = new JsonArray();
- arr.add(new JsonPrimitive(internalname));
- json.add("missing", arr);
- manager.writeJson(json, f);
- } catch(IOException e) {}
- }
- missingRecipe.set(false);
-
- ses.schedule(() -> {
- int index = i.get();
- JsonObject o = (JsonObject)items[index];
- if(Minecraft.getMinecraft().currentScreen != null) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- }
- Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
-
- ses.schedule(this, 1000, TimeUnit.MILLISECONDS);
- }, 100, TimeUnit.MILLISECONDS);
- }
- };
-
- int index = i.get();
- JsonObject o = (JsonObject)items[index];
- if(Minecraft.getMinecraft().currentScreen != null) {
- Minecraft.getMinecraft().displayGuiScreen(null);
- }
- Minecraft.getMinecraft().thePlayer.sendChatMessage("/viewrecipe " + o.get("internalname").getAsString());
-
- ses.schedule(checker, 1000, TimeUnit.MILLISECONDS);
- }*/
- }
-
- /**
- * This makes it so that holding LCONTROL while hovering over an item with NBT will show the NBT of the item.
- * @param event
- */
- @SubscribeEvent
- public void onItemTooltip(ItemTooltipEvent event) {
- if(!isOnSkyblock()) return;
- if(manager.config.hideEmptyPanes.value &&
- event.itemStack.getItem().equals(Item.getItemFromBlock(Blocks.stained_glass_pane))) {
- String first = Utils.cleanColour(event.toolTip.get(0));
- first = first.replaceAll("\\(.*\\)", "").trim();
- if(first.length() == 0) {
- event.toolTip.clear();
- }
- }
- //AH prices
- /*if(Minecraft.getMinecraft().currentScreen != null) {
- 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.trim().equals("Auctions Browser")) {
- String internalname = manager.getInternalNameForItem(event.itemStack);
- if(internalname != null) {
- for(int i=0; i<event.toolTip.size(); i++) {
- String line = event.toolTip.get(i);
- if(line.contains(EnumChatFormatting.GRAY + "Bidder: ") ||
- line.contains(EnumChatFormatting.GRAY + "Starting bid: ") ||
- line.contains(EnumChatFormatting.GRAY + "Buy it now: ")) {
- manager.updatePrices();
- JsonObject auctionInfo = manager.getItemAuctionInfo(internalname);
-
- if(auctionInfo != null) {
- NumberFormat format = NumberFormat.getInstance(Locale.US);
- int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
- float costOfEnchants = manager.getCostOfEnchants(internalname,
- event.itemStack.getTagCompound());
- int priceWithEnchants = auctionPrice+(int)costOfEnchants;
-
- event.toolTip.add(++i, EnumChatFormatting.GRAY + "Average price: " +
- EnumChatFormatting.GOLD + format.format(auctionPrice) + " coins");
- if(costOfEnchants > 0) {
- event.toolTip.add(++i, EnumChatFormatting.GRAY + "Average price (w/ enchants): " +
- EnumChatFormatting.GOLD +
- format.format(priceWithEnchants) + " coins");
- }
-
- if(manager.config.advancedPriceInfo.value) {
- int salesVolume = (int) auctionInfo.get("sales").getAsFloat();
- int flipPrice = (int)(0.93*priceWithEnchants);
-
- event.toolTip.add(++i, EnumChatFormatting.GRAY + "Flip Price (93%): " +
- EnumChatFormatting.GOLD + format.format(flipPrice) + " coins");
- event.toolTip.add(++i, EnumChatFormatting.GRAY + "Volume: " +
- EnumChatFormatting.GOLD + format.format(salesVolume) + " sales/day");
- }
- break;
- }
- }
- }
- }
- }
- }
- }*/
- if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !manager.config.dev.value) return;
- if(event.toolTip.size()>0&&event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) {
- event.toolTip.remove(event.toolTip.size()-1);
-
- StringBuilder sb = new StringBuilder();
- String nbt = event.itemStack.getTagCompound().toString();
- int indent = 0;
- for(char c : nbt.toCharArray()) {
- boolean newline = false;
- if(c == '{' || c == '[') {
- indent++;
- newline = true;
- } else if(c == '}' || c == ']') {
- indent--;
- sb.append("\n");
- for(int i=0; i<indent; i++) sb.append(" ");
- } else if(c == ',') {
- newline = true;
- } else if(c == '\"') {
- sb.append(EnumChatFormatting.RESET.toString() + EnumChatFormatting.GRAY);
+ } else {
+ hasSkyblockScoreboard = false;
+ return;
}
-
- sb.append(c);
- if(newline) {
- sb.append("\n");
- for(int i=0; i<indent; i++) sb.append(" ");
- }
- }
- event.toolTip.add(sb.toString());
- if(Keyboard.isKeyDown(Keyboard.KEY_H)) {
- StringSelection selection = new StringSelection(sb.toString());
- Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ } else {
+ hasSkyblockScoreboard = false;
+ return;
}
- }
- }
-
- //Stolen from Biscut's SkyblockAddons
- public boolean isOnSkyblock() {
- if(!manager.config.onlyShowOnSkyblock.value) return true;
- return hasSkyblockScoreboard();
- }
- public boolean hasSkyblockScoreboard() {
- Minecraft mc = Minecraft.getMinecraft();
-
- if (mc != null && mc.theWorld != null) {
Scoreboard scoreboard = mc.theWorld.getScoreboard();
ScoreObjective sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1);
if (sidebarObjective != null) {
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..d9e9217a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/SBAIntegration.java
@@ -0,0 +1,211 @@
+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.features.backpacks.BackpackManager");
+ }
+ if(backpackManager_getFromItem == null) {
+ backpackManager_getFromItem = backpackManagerClass.getDeclaredMethod("getFromItem", ItemStack.class);
+ }
+ if(backpackClass == null) {
+ backpackClass = Class.forName("codes.biscuit.skyblockaddons.features.backpacks.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) {
+ e.printStackTrace();
+ 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) {
+ e.printStackTrace();
+ 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) {
+ e.printStackTrace();
+ 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) {
+ e.printStackTrace();
+ 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();
+
+ if(Minecraft.getMinecraft().currentScreen instanceof GuiContainer) {
+ guiContainerHook_drawBackpacks.invoke(null, Minecraft.getMinecraft().currentScreen, mouseX, mouseY, fontRendererObj);
+ } else {
+ 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) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java b/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java
new file mode 100644
index 00000000..6bdf2c5d
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/TradeWindow.java
@@ -0,0 +1,1042 @@
+package io.github.moulberry.notenoughupdates;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.gui.inventory.GuiEditSign;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.Slot;
+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.tileentity.TileEntitySign;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.io.ByteArrayInputStream;
+import java.text.NumberFormat;
+import java.util.*;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class TradeWindow {
+
+ private static ResourceLocation location = new ResourceLocation("notenoughupdates", "custom_trade.png");
+
+ private static final int xSize = 176;
+ private static final int ySize = 204;
+ private static int guiLeft;
+ private static int guiTop;
+
+ private static long lastTradeMillis = -1;
+
+ private static final long CHANGE_EXCLAM_MILLIS = 5000;
+
+ private static Integer[] ourTradeIndexes = new Integer[16];
+ private static Integer[] theirTradeIndexes = new Integer[16];
+ private static String[] theirTradeOld = new String[16];
+ private static Long[] theirTradeChangesMillis = new Long[16];
+
+ private static ItemStack lastBackpack;
+ private static int lastBackpackX;
+ private static int lastBackpackY;
+
+ public static boolean tradeWindowActive() {
+ if(!NotEnoughUpdates.INSTANCE.isOnSkyblock()) return false;
+ if(!NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.value) return false;
+
+ GuiScreen guiScreen = Minecraft.getMinecraft().currentScreen;
+ if(guiScreen instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) guiScreen;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+ if(containerName.trim().startsWith("You ")) {
+ return true;
+ }
+ }
+
+ lastTradeMillis = -1;
+ ourTradeIndexes = new Integer[16];
+ theirTradeIndexes = new Integer[16];
+ theirTradeOld = new String[16];
+ theirTradeChangesMillis = new Long[16];
+
+ return false;
+ }
+
+ private static TexLoc tl = new TexLoc(0, 0, Keyboard.KEY_M);
+
+ private static void drawStringShadow(String str, float x, float y, int len) {
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str),
+ Minecraft.getMinecraft().fontRendererObj,
+ x+xOff/2f, y+yOff/2f, false, len,
+ new Color(20, 20, 20, 100/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB());
+ }
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth(str,
+ Minecraft.getMinecraft().fontRendererObj,
+ x, y, false, len,
+ new Color(64, 64, 64, 255).getRGB());
+ }
+
+ private static int processTopItems(ItemStack stack, Map<Integer, Set<String>> topItems,
+ Map<String, ItemStack> topItemsStack, Map<String, Integer> topItemsCount) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if(internalname == null) {
+ if(stack.getDisplayName().endsWith(" coins")) {
+ String clean = Utils.cleanColour(stack.getDisplayName());
+
+ int mult = 1;
+ StringBuilder sb = new StringBuilder();
+ for(int index = 0; index < clean.length(); index++) {
+ char c = clean.charAt(index);
+ if("0123456789.".indexOf(c) >= 0) {
+ sb.append(c);
+ } else {
+ switch(c) {
+ case 'K':
+ case 'k':
+ mult = 1000; break;
+ case 'M':
+ case 'm':
+ mult = 1000000; break;
+ case 'B':
+ case 'b':
+ mult = 1000000000; break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ try {
+ int coins = (int)(Float.parseFloat(sb.toString())*mult);
+
+ topItemsStack.putIfAbsent("TRADE_COINS", stack);
+
+ int existingPrice = coins;
+ Set<Integer> toRemove = new HashSet<>();
+ for(Map.Entry<Integer, Set<String>> entry : topItems.entrySet()) {
+ if(entry.getValue().contains("TRADE_COINS")) {
+ entry.getValue().remove("TRADE_COINS");
+ existingPrice += entry.getKey();
+ }
+ if(entry.getValue().isEmpty()) toRemove.add(entry.getKey());
+ }
+ topItems.keySet().removeAll(toRemove);
+
+ Set<String> items = topItems.computeIfAbsent(existingPrice, k->new HashSet<>());
+ items.add("TRADE_COINS");
+
+ return coins;
+
+ } catch(Exception ignored) {}
+ }
+ } else {
+ JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
+ int pricePer = -1;
+ if(info != null && !NotEnoughUpdates.INSTANCE.manager.auctionManager.isVanillaItem(internalname) &&
+ info.has("price") && info.has("count")) {
+ int auctionPricePer = (int)(info.get("price").getAsFloat() / info.get("count").getAsFloat());
+
+ pricePer = auctionPricePer;
+ } else {
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
+ if(bazaarInfo != null && bazaarInfo.has("avg_buy")) {
+ pricePer = (int)bazaarInfo.get("avg_buy").getAsFloat();
+ }
+ }
+ if(pricePer > 0) {
+ topItemsStack.putIfAbsent(internalname, stack);
+
+ int price = pricePer * stack.stackSize;
+ int priceInclBackpack = price;
+
+ NBTTagCompound tag = stack.getTagCompound();
+ 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) {
+ try {
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ for(int k=0; k<items.tagCount(); k++) {
+ if(items.getCompoundTagAt(k).getKeySet().size() > 0) {
+ NBTTagCompound nbt = items.getCompoundTagAt(k).getCompoundTag("tag");
+
+ int id2 = items.getCompoundTagAt(k).getShort("id");
+ int count2 = items.getCompoundTagAt(k).getByte("Count");
+ int damage2 = items.getCompoundTagAt(k).getShort("Damage");
+
+ if(id2 == 141) id2 = 391; //for some reason hypixel thinks carrots have id 141
+
+ Item mcItem = Item.getItemById(id2);
+ if(mcItem == null) continue;
+
+ ItemStack stack2 = new ItemStack(mcItem, count2, damage2);
+ stack2.setTagCompound(nbt);
+
+ priceInclBackpack += processTopItems(stack2, topItems, topItemsStack, topItemsCount);
+ }
+ }
+ } catch(Exception e) { }
+ }
+ }
+
+ int existingPrice = price;
+ Set<Integer> toRemove = new HashSet<>();
+ for(Map.Entry<Integer, Set<String>> entry : topItems.entrySet()) {
+ if(entry.getValue().contains(internalname)) {
+ entry.getValue().remove(internalname);
+ existingPrice += entry.getKey();
+ }
+ if(entry.getValue().isEmpty()) toRemove.add(entry.getKey());
+ }
+ topItems.keySet().removeAll(toRemove);
+
+ Set<String> items = topItems.computeIfAbsent(existingPrice, k->new HashSet<>());
+ items.add(internalname);
+
+ int count = topItemsCount.computeIfAbsent(internalname, l->0);
+ topItemsCount.put(internalname, count+stack.stackSize);
+
+ return priceInclBackpack;
+ }
+ }
+ return 0;
+ }
+
+ private static int getBackpackValue(ItemStack stack) {
+ int price = 0;
+
+ NBTTagCompound tag = stack.getTagCompound();
+ 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) {
+ try {
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ for(int k=0; k<items.tagCount(); k++) {
+ if(items.getCompoundTagAt(k).getKeySet().size() > 0) {
+ NBTTagCompound nbt = items.getCompoundTagAt(k).getCompoundTag("tag");
+ String internalname2 = NotEnoughUpdates.INSTANCE.manager.getInternalnameFromNBT(nbt);
+ if(internalname2 != null) {
+ JsonObject info2 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname2);
+
+ int pricePer2 = -1;
+ if(info2 != null && info2.has("price") && info2.has("count")) {
+ int auctionPricePer2 = (int)(info2.get("price").getAsFloat() / info2.get("count").getAsFloat());
+
+ pricePer2 = auctionPricePer2;
+ } else {
+ JsonObject bazaarInfo2 = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname2);
+ if(bazaarInfo2 != null && bazaarInfo2.has("avg_buy")) {
+ pricePer2 = (int)bazaarInfo2.get("avg_buy").getAsFloat();
+ }
+ }
+ if(pricePer2 > 0) {
+ int count2 = items.getCompoundTagAt(k).getByte("Count");
+ price += pricePer2 * count2;
+ }
+ }
+ }
+ }
+ } catch(Exception e) { }
+ }
+ }
+ return price;
+ }
+
+ public static void render(int mouseX, int mouseY) {
+ if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ GuiContainer chest = ((GuiContainer)Minecraft.getMinecraft().currentScreen);
+ ContainerChest cc = (ContainerChest) chest.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ guiLeft = (scaledResolution.getScaledWidth()-xSize)/2;
+ guiTop = (scaledResolution.getScaledHeight()-ySize)/2;
+
+ List<String> tooltipToDisplay = null;
+ ItemStack stackToRender = null;
+ int tooltipLen = -1;
+ tl.handleKeyboardInput();
+
+ //Set index mappings
+ //Our slots
+ TreeMap<Integer, List<Integer>> ourTradeMap = new TreeMap<>();
+ for(int i=0; i<16; i++) {
+ ourTradeIndexes[i] = -1;
+
+ int x = i % 4;
+ int y = i / 4;
+ int containerIndex = y*9+x;
+
+ ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
+ if(stack == null) continue;
+
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if(internalname == null) {
+ if(stack.getDisplayName().endsWith(" coins")) {
+ String clean = Utils.cleanColour(stack.getDisplayName());
+
+ int mult = 1;
+ StringBuilder sb = new StringBuilder();
+ for(int index = 0; index < clean.length(); index++) {
+ char c = clean.charAt(index);
+ if("0123456789.".indexOf(c) >= 0) {
+ sb.append(c);
+ } else {
+ switch(c) {
+ case 'K':
+ case 'k':
+ mult = 1000; break;
+ case 'M':
+ case 'm':
+ mult = 1000000; break;
+ case 'B':
+ case 'b':
+ mult = 1000000000; break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ try {
+ int coins = (int)(Float.parseFloat(sb.toString())*mult);
+
+ List<Integer> list = ourTradeMap.computeIfAbsent(coins, k -> new ArrayList<>());
+ list.add(containerIndex);
+
+ } catch(Exception ignored) {
+ List<Integer> list = ourTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ } else {
+ List<Integer> list = ourTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ } else {
+ JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
+ int price = -1;
+ if(info != null && info.has("price") && info.has("count")) {
+ int auctionPricePer = (int)(info.get("price").getAsFloat() / info.get("count").getAsFloat());
+
+ price = auctionPricePer * stack.stackSize;
+ } else {
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
+ if(bazaarInfo != null && bazaarInfo.has("avg_buy")) {
+ price = (int)bazaarInfo.get("avg_buy").getAsFloat() * stack.stackSize;
+ }
+ }
+
+ price += getBackpackValue(stack);
+
+ List<Integer> list = ourTradeMap.computeIfAbsent(price, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ }
+ long currentTime = System.currentTimeMillis();
+ List<String> theirTradeCurrent = new ArrayList<>();
+ TreeMap<Integer, List<Integer>> theirTradeMap = new TreeMap<>();
+ HashMap<String, Integer> displayCountMap = new HashMap<>();
+ for(int i=0; i<16; i++) {
+ theirTradeIndexes[i] = -1;
+ if(theirTradeChangesMillis[i] == null || currentTime - theirTradeChangesMillis[i] > CHANGE_EXCLAM_MILLIS) {
+ theirTradeChangesMillis[i] = -1L;
+ }
+
+ int x = i % 4;
+ int y = i / 4;
+ int containerIndex = y*9+x+5;
+
+ ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
+ if(stack == null) continue;
+
+ NBTTagCompound tag = stack.getTagCompound();
+ String uuid = null;
+ if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ if (ea.hasKey("uuid", 8)) {
+ uuid = ea.getString("uuid");
+ } else {
+ int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k->0);
+ uuid = stack.getDisplayName() + ":" + displayCount;
+ displayCountMap.put(stack.getDisplayName(), displayCount+1);
+ }
+ } else {
+ int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k->0);
+ uuid = stack.getDisplayName() + ":" + displayCount;
+ displayCountMap.put(stack.getDisplayName(), displayCount+1);
+ }
+ if(uuid != null) theirTradeCurrent.add(uuid);
+
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if(internalname == null) {
+ if(stack.getDisplayName().endsWith(" coins")) {
+ String clean = Utils.cleanColour(stack.getDisplayName());
+
+ int mult = 1;
+ StringBuilder sb = new StringBuilder();
+ for(int index = 0; index < clean.length(); index++) {
+ char c = clean.charAt(index);
+ if("0123456789.".indexOf(c) >= 0) {
+ sb.append(c);
+ } else {
+ switch(c) {
+ case 'K':
+ case 'k':
+ mult = 1000; break;
+ case 'M':
+ case 'm':
+ mult = 1000000; break;
+ case 'B':
+ case 'b':
+ mult = 1000000000; break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ try {
+ int coins = (int)(Float.parseFloat(sb.toString())*mult);
+
+ List<Integer> list = theirTradeMap.computeIfAbsent(coins, k -> new ArrayList<>());
+ list.add(containerIndex);
+
+ } catch(Exception ignored) {
+ List<Integer> list = theirTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ } else {
+ List<Integer> list = theirTradeMap.computeIfAbsent(-1, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ } else {
+ JsonObject info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
+ int price = -1;
+ if(info != null && info.has("price") && info.has("count")) {
+ int auctionPricePer = (int)(info.get("price").getAsFloat() / info.get("count").getAsFloat());
+
+ price = auctionPricePer * stack.stackSize;
+ } else {
+ JsonObject bazaarInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo(internalname);
+ if(bazaarInfo != null && bazaarInfo.has("avg_buy")) {
+ price = (int)bazaarInfo.get("avg_buy").getAsFloat() * stack.stackSize;
+ }
+ }
+
+ price += getBackpackValue(stack);
+
+ List<Integer> list = theirTradeMap.computeIfAbsent(price, k -> new ArrayList<>());
+ list.add(containerIndex);
+ }
+ }
+ int ourTradeIndex = 0;
+ for(Map.Entry<Integer, List<Integer>> entry : ourTradeMap.descendingMap().entrySet()) {
+ for(Integer index : entry.getValue()) {
+ ourTradeIndexes[ourTradeIndex++] = index;
+ }
+ }
+
+ //Their slots
+ int maxMissing = 16-theirTradeCurrent.size();
+ int j=0;
+ for(int i=0; i<16; i++) {
+ while(j <= 15 && (j-i<maxMissing) && theirTradeChangesMillis[j] >= 0) j++;
+ j = Math.min(15, j);
+
+ String oldUUID = theirTradeOld[i];
+ if(oldUUID != null && !theirTradeCurrent.contains(oldUUID)) {
+ theirTradeChangesMillis[j] = System.currentTimeMillis();
+ }
+ j++;
+ }
+
+ for(int i=0; i<16; i++) {
+ theirTradeOld[i] = null;
+ }
+ int theirTradeIndex = 0;
+ displayCountMap.clear();
+ j=0;
+ for(Map.Entry<Integer, List<Integer>> entry : theirTradeMap.descendingMap().entrySet()) {
+ for(Integer index : entry.getValue()) {
+ while(j <= 15 && (j-theirTradeIndex<maxMissing) && theirTradeChangesMillis[j] >= 0) j++;
+ j = Math.min(15, j);
+
+ theirTradeIndexes[j] = index;
+
+ ItemStack stack = chest.inventorySlots.getInventory().get(index);
+ if(stack == null) continue;
+
+ NBTTagCompound tag = stack.getTagCompound();
+ String uuid = null;
+ if(tag != null && tag.hasKey("ExtraAttributes", 10)) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+
+ if (ea.hasKey("uuid", 8)) {
+ uuid = ea.getString("uuid");
+ } else {
+ int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k->0);
+ uuid = stack.getDisplayName() + ":" + displayCount;
+ displayCountMap.put(stack.getDisplayName(), displayCount+1);
+ }
+ } else {
+ int displayCount = displayCountMap.computeIfAbsent(stack.getDisplayName(), k->0);
+ uuid = stack.getDisplayName() + ":" + displayCount;
+ displayCountMap.put(stack.getDisplayName(), displayCount+1);
+ }
+ //System.out.println(uuid);
+ theirTradeOld[theirTradeIndex] = uuid;
+
+ j++;
+ theirTradeIndex++;
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, 0, 176/256f, 0, 204/256f, GL11.GL_NEAREST);
+
+ Utils.drawStringF(new ChatComponentTranslation("container.inventory").getUnformattedText(),
+ Minecraft.getMinecraft().fontRendererObj, guiLeft+8, guiTop+111, false, 4210752);
+ Utils.drawStringF("You", Minecraft.getMinecraft().fontRendererObj, guiLeft+8,
+ guiTop+5, false, 4210752);
+ String[] split = containerName.split(" ");
+ if(split.length >= 1) {
+ Utils.drawStringF(split[split.length-1], Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+167-Minecraft.getMinecraft().fontRendererObj.getStringWidth(split[split.length-1]),
+ guiTop+5, false, 4210752);
+ }
+
+ int index=0;
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ int x = 8+18*(index % 9);
+ int y = 104+18*(index / 9);
+ if(index < 9) y = 180;
+
+ Utils.drawItemStack(stack, guiLeft+x, guiTop+y);
+
+ if(mouseX > guiLeft+x-1 && mouseX < guiLeft+x+18) {
+ if(mouseY > guiTop+y-1 && mouseY < guiTop+y+18) {
+ if(stack != null) stackToRender = stack;
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Utils.drawGradientRect(guiLeft+x, guiTop+y,
+ guiLeft+x + 16, guiTop+y + 16, -2130706433, -2130706433);
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ }
+ }
+
+ index++;
+ }
+
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+
+ int containerIndex = ourTradeIndexes[i];
+
+ ItemStack stack = null;
+ if(containerIndex >= 0) {
+ stack = chest.inventorySlots.getInventory().get(containerIndex);
+ Utils.drawItemStack(stack, guiLeft+10+x*18, guiTop+15+y*18);
+ }
+
+ if(mouseX > guiLeft+10+x*18-1 && mouseX < guiLeft+10+x*18+18) {
+ if(mouseY > guiTop+15+y*18-1 && mouseY < guiTop+15+y*18+18) {
+ if(stack != null) stackToRender = stack;
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Utils.drawGradientRect(guiLeft+10+x*18, guiTop+15+y*18,
+ guiLeft+10+x*18 + 16, guiTop+15+y*18 + 16, -2130706433, -2130706433);
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ }
+ }
+ }
+
+ ItemStack bidStack = chest.inventorySlots.getInventory().get(36);
+ if(bidStack != null) {
+ Utils.drawItemStack(bidStack, guiLeft+10, guiTop+90);
+ if(mouseX > guiLeft+10-1 && mouseX < guiLeft+10+18) {
+ if(mouseY > guiTop+90-1 && mouseY < guiTop+90+18) {
+ tooltipToDisplay = bidStack.getTooltip(Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
+ }
+ }
+ }
+
+ ItemStack confirmStack = chest.inventorySlots.getInventory().get(39);
+ if(confirmStack != null) {
+ String confirmDisplay = confirmStack.getDisplayName();
+ if(!confirmDisplay.equals(EnumChatFormatting.GREEN+"Trading!")) {
+ if(mouseX > guiLeft+81-51 && mouseX < guiLeft+81) {
+ if (mouseY > guiTop+91 && mouseY < guiTop+91+14) {
+ tooltipToDisplay = confirmStack.getTooltip(Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
+ }
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft+81-51, guiTop+91, 51, 14,
+ 0, 51/256f, ySize/256f, (ySize+14)/256f, GL11.GL_NEAREST);
+
+ Pattern pattern = Pattern.compile(EnumChatFormatting.GRAY+"\\("+EnumChatFormatting.YELLOW+"([0-9]+)"+EnumChatFormatting.GRAY+"\\)");
+ Matcher matcher = pattern.matcher(confirmDisplay);
+
+ if(!confirmDisplay.equals(EnumChatFormatting.YELLOW+"Warning!") &&
+ !confirmDisplay.equals(EnumChatFormatting.YELLOW+"Deal!")) {
+ lastTradeMillis = -1;
+ }
+
+ if(matcher.find()) {
+ String numS = matcher.group(1);
+ int num = Integer.parseInt(numS);
+
+ Utils.drawStringCentered(EnumChatFormatting.DARK_RED + "Check " + EnumChatFormatting.BOLD + (char) (9311 + num), Minecraft.getMinecraft().fontRendererObj, guiLeft + 56, guiTop + 99,
+ false, 4210752);
+ } else if(confirmDisplay.equals(EnumChatFormatting.AQUA+"Gift!")) {
+ Utils.drawStringCentered(EnumChatFormatting.GREEN+"Accept", Minecraft.getMinecraft().fontRendererObj, guiLeft+56, guiTop+99,
+ true, 4210752);
+ } else if(confirmDisplay.equals(EnumChatFormatting.GREEN+"Deal accepted!")) {
+ Utils.drawStringCentered(EnumChatFormatting.GREEN+"Accepted", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+56, guiTop+99, true, 4210752);
+ } else if(lastTradeMillis > 0) {
+ long delta = System.currentTimeMillis() - lastTradeMillis;
+ if(delta > 2000) {
+ Utils.drawStringCentered(EnumChatFormatting.GREEN+"Accept", Minecraft.getMinecraft().fontRendererObj, guiLeft+56, guiTop+99,
+ true, 4210752);
+ } else {
+ Utils.drawStringCentered(EnumChatFormatting.YELLOW+"Trade "+EnumChatFormatting.BOLD+(char)(9312+(2000-delta)/1000),
+ Minecraft.getMinecraft().fontRendererObj, guiLeft+56, guiTop+99,
+ true, 4210752);
+ }
+ } else {
+ Utils.drawStringCentered(EnumChatFormatting.YELLOW+"Trade "+EnumChatFormatting.BOLD+(char)(9314), Minecraft.getMinecraft().fontRendererObj, guiLeft+56, guiTop+99,
+ true, 4210752);
+ }
+ }
+ }
+
+ ItemStack theirConfirmStack = chest.inventorySlots.getInventory().get(41);
+ if(theirConfirmStack != null) {
+ String confirmDisplay = theirConfirmStack.getDisplayName();
+ if(mouseX > guiLeft+95 && mouseX < guiLeft+95+51) {
+ if (mouseY > guiTop+91 && mouseY < guiTop+91+14) {
+ tooltipToDisplay = theirConfirmStack.getTooltip(Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft+95, guiTop+91, 51, 14,
+ 0, 51/256f, ySize/256f, (ySize+14)/256f, GL11.GL_NEAREST);
+
+ if(confirmDisplay.equals(EnumChatFormatting.YELLOW+"Pending their confirm")) {
+ Utils.drawStringCentered(EnumChatFormatting.YELLOW+"Pending", Minecraft.getMinecraft().fontRendererObj, guiLeft+120, guiTop+99,
+ true, 4210752);
+ } else if(confirmDisplay.equals(EnumChatFormatting.YELLOW+"Deal timer...")) {
+ Utils.drawStringCentered(EnumChatFormatting.YELLOW+"Pending", Minecraft.getMinecraft().fontRendererObj, guiLeft+120, guiTop+99,
+ true, 4210752);
+ } else if(confirmDisplay.equals(EnumChatFormatting.GREEN+"Other player confirmed!")) {
+ Utils.drawStringCentered(EnumChatFormatting.GREEN+"Accepted", Minecraft.getMinecraft().fontRendererObj, guiLeft+120, guiTop+99,
+ true, 4210752);
+ }
+ }
+
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+
+ int containerIndex = theirTradeIndexes[i];
+
+ ItemStack stack = null;
+ if(containerIndex >= 0) {
+ stack = chest.inventorySlots.getInventory().get(containerIndex);
+ Utils.drawItemStack(stack, guiLeft+96+x*18, guiTop+15+y*18);
+ }
+
+ if(currentTime % 400 > 200 && theirTradeChangesMillis[i] != null && theirTradeChangesMillis[i] > 0) {
+ GlStateManager.translate(0, 0, 200);
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft+96+x*18, guiTop+15+y*18, 16, 16,
+ 51/256f, 67/256f, 204/256f, 220/256f, GL11.GL_NEAREST);
+ GlStateManager.translate(0, 0, -200);
+ }
+
+ if(mouseX > guiLeft+96+x*18-1 && mouseX < guiLeft+96+x*18+18) {
+ if(mouseY > guiTop+15+y*18-1 && mouseY < guiTop+15+y*18+18) {
+ if(stack != null) stackToRender = stack;
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ GlStateManager.colorMask(true, true, true, false);
+ Utils.drawGradientRect(guiLeft+96+x*18, guiTop+15+y*18,
+ guiLeft+96+x*18 + 16, guiTop+15+y*18 + 16, -2130706433, -2130706433);
+ GlStateManager.colorMask(true, true, true, true);
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ }
+ }
+ }
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.value) {
+ TreeMap<Integer, Set<String>> ourTopItems = new TreeMap<>();
+ TreeMap<String, ItemStack> ourTopItemsStack = new TreeMap<>();
+ TreeMap<String, Integer> ourTopItemsCount = new TreeMap<>();
+ int ourPrice = 0;
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+ int containerIndex = y*9+x;
+
+ ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
+ if(stack == null) continue;
+
+ ourPrice += processTopItems(stack, ourTopItems, ourTopItemsStack, ourTopItemsCount);
+ }
+ TreeMap<Integer, Set<String>> theirTopItems = new TreeMap<>();
+ TreeMap<String, ItemStack> theirTopItemsStack = new TreeMap<>();
+ TreeMap<String, Integer> theirTopItemsCount = new TreeMap<>();
+ int theirPrice = 0;
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+ int containerIndex = y*9+x+5;
+
+ ItemStack stack = chest.inventorySlots.getInventory().get(containerIndex);
+ if(stack == null) continue;
+
+ theirPrice += processTopItems(stack, theirTopItems, theirTopItemsStack, theirTopItemsCount);
+ }
+
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+
+ GlStateManager.disableLighting();
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft-80-3, guiTop, 80, 106,
+ 176/256f, 1, 0, 106/256f, GL11.GL_NEAREST);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+"Total Value",
+ guiLeft-40-3, guiTop+11, 72);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(ourPrice),
+ guiLeft-40-3, guiTop+21, 72);
+
+ int ourTopIndex = Math.max(0, 3-ourTopItemsStack.size());
+ out:
+ for(Map.Entry<Integer, Set<String>> entry : ourTopItems.descendingMap().entrySet()) {
+ for(String ourTopItemInternal : entry.getValue()) {
+ ItemStack stack = ourTopItemsStack.get(ourTopItemInternal);
+ if(stack == null) continue;
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.value) {
+ String countS = "";
+ if(ourTopItemsCount.containsKey(ourTopItemInternal)) {
+ int count = ourTopItemsCount.get(ourTopItemInternal);
+ if(count > 999999) {
+ countS = Math.floor(count/10000f)/100f+"m";
+ } else if(count > 999) {
+ countS = Math.floor(count/10f)/100f+"k";
+ } else {
+ countS = ""+count;
+ }
+ }
+
+ Utils.drawItemStackWithText(stack, guiLeft-75-3, guiTop+49+18*ourTopIndex, countS);
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableBlend();
+ GlStateManager.color(1, 1, 1, 1);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(entry.getKey()),
+ guiLeft-29-3, guiTop+57+18*ourTopIndex, 52);
+ GlStateManager.enableBlend();
+ } else {
+ drawStringShadow(stack.getDisplayName() + EnumChatFormatting.GRAY+"x"+ourTopItemsCount.get(ourTopItemInternal),
+ guiLeft-40-3, guiTop+46+20*ourTopIndex, 72);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(entry.getKey()),
+ guiLeft-40-3, guiTop+56+20*ourTopIndex, 72);
+ }
+
+ if(++ourTopIndex >= 3) break out;
+ }
+ }
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop, 80, 106,
+ 176/256f, 1, 0, 106/256f, GL11.GL_NEAREST);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+"Total Value",
+ guiLeft+xSize+3+40, guiTop+11, 72);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(theirPrice),
+ guiLeft+xSize+3+40, guiTop+21, 72);
+
+ int theirTopIndex = Math.max(0, 3-theirTopItemsStack.size());
+ out:
+ for(Map.Entry<Integer, Set<String>> entry : theirTopItems.descendingMap().entrySet()) {
+ for(String theirTopItemInternal : entry.getValue()) {
+ ItemStack stack = theirTopItemsStack.get(theirTopItemInternal);
+ if(stack == null) continue;
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.value) {
+ String countS = "";
+ if(theirTopItemsCount.containsKey(theirTopItemInternal)) {
+ int count = theirTopItemsCount.get(theirTopItemInternal);
+ if(count > 999999) {
+ countS = Math.floor(count/10000f)/100f+"m";
+ } else if(count > 999) {
+ countS = Math.floor(count/10f)/100f+"k";
+ } else {
+ countS = ""+count;
+ }
+ }
+
+ Utils.drawItemStackWithText(stack, guiLeft+xSize+25+3-16, guiTop+49+18*theirTopIndex, countS);
+
+ GlStateManager.disableLighting();
+ GlStateManager.disableBlend();
+ GlStateManager.color(1, 1, 1, 1);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(entry.getKey()),
+ guiLeft+xSize+3+51, guiTop+57+18*theirTopIndex, 52);
+ GlStateManager.enableBlend();
+ } else {
+ drawStringShadow(stack.getDisplayName(),
+ guiLeft+xSize+3+40, guiTop+46+20*theirTopIndex, 72);
+ drawStringShadow(EnumChatFormatting.GOLD.toString()+EnumChatFormatting.BOLD+format.format(entry.getKey()),
+ guiLeft+xSize+3+40, guiTop+56+20*theirTopIndex, 72);
+ }
+
+ if(++theirTopIndex >= 3) break out;
+ }
+ }
+ }
+
+
+ boolean button1 = NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.value;
+ boolean button2 = NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.value;
+ boolean button3 = NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.value;
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop+ySize-19, 17, 17,
+ (button3?17:0)/256f, (button3?34:17)/256f, 218/256f, 235/256f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop+ySize-38, 17, 17,
+ (button2?17:0)/256f, (button2?34:17)/256f, 218/256f, 235/256f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(guiLeft+xSize+3, guiTop+ySize-57, 17, 17,
+ (button1?17:0)/256f, (button1?34:17)/256f, 218/256f, 235/256f, GL11.GL_NEAREST);
+
+ if(mouseX >= guiLeft+xSize+3 && mouseX <= guiLeft+xSize+3+17) {
+ if(mouseY >= guiTop+ySize-19 && mouseY <= guiTop+ySize-19+17) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(EnumChatFormatting.GOLD+NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.displayName);
+ tooltipToDisplay.add(EnumChatFormatting.GRAY+NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.desc);
+ tooltipLen = 200;
+ } else if(mouseY >= guiTop+ySize-38 && mouseY <= guiTop+ySize-38+17) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(EnumChatFormatting.GOLD+NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.displayName);
+ tooltipToDisplay.add(EnumChatFormatting.GRAY+NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.desc);
+ tooltipLen = 200;
+ } else if(mouseY >= guiTop+ySize-57 && mouseY <= guiTop+ySize-57+17) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(EnumChatFormatting.GOLD+NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.displayName);
+ tooltipToDisplay.add(EnumChatFormatting.GRAY+NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.desc);
+ tooltipLen = 200;
+ }
+ }
+
+ 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, Minecraft.getMinecraft().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, Minecraft.getMinecraft().fontRendererObj);
+ GlStateManager.translate(0, 0, -100);
+ }
+ } else {
+ renderedBackpack = false;
+ }
+ if(!renderedBackpack) {
+ lastBackpack = null;
+ tooltipToDisplay = stackToRender.getTooltip(Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
+ }
+ }
+ }
+
+ if(tooltipToDisplay != null) {
+ Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(),
+ tooltipLen, Minecraft.getMinecraft().fontRendererObj);
+ }
+ }
+
+ public static void handleMouseInput() {
+ if(!(Minecraft.getMinecraft().currentScreen instanceof GuiContainer)) return;
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int width = scaledResolution.getScaledWidth();
+ int height = scaledResolution.getScaledHeight();
+
+ int mouseX = Mouse.getEventX() * width / Minecraft.getMinecraft().displayWidth;
+ int mouseY = height - Mouse.getEventY() * height / Minecraft.getMinecraft().displayHeight - 1;
+
+ GuiContainer chest = ((GuiContainer)Minecraft.getMinecraft().currentScreen);
+
+ if(Mouse.getEventButtonState() && Mouse.isButtonDown(0)) {
+ int index=0;
+ for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) {
+ if(stack == null) {
+ index++;
+ continue;
+ }
+
+ int x = 8+18*(index % 9);
+ int y = 104+18*(index / 9);
+ if(index < 9) y = 180;
+
+ if(mouseX > guiLeft+x && mouseX < guiLeft+x+16) {
+ if(mouseY > guiTop+y && mouseY < guiTop+y+16) {
+ Slot slot = chest.inventorySlots.getSlotFromInventory(Minecraft.getMinecraft().thePlayer.inventory, index);
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ slot.slotNumber, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+
+ index++;
+ }
+
+ for(int i=0; i<16; i++) {
+ int x = i % 4;
+ int y = i / 4;
+
+ int containerIndex = ourTradeIndexes[i];
+ if(containerIndex < 0) continue;
+
+ if(mouseX > guiLeft+10+x*18-1 && mouseX < guiLeft+10+x*18+18) {
+ if(mouseY > guiTop+15+y*18-1 && mouseY < guiTop+15+y*18+18) {
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ containerIndex, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+ }
+
+ if(mouseX > guiLeft+10-1 && mouseX < guiLeft+10+18) {
+ if(mouseY > guiTop+90-1 && mouseY < guiTop+90+18) {
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ 36, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+
+ ItemStack confirmStack = chest.inventorySlots.getInventory().get(39);
+ if(confirmStack != null) {
+ String confirmDisplay = confirmStack.getDisplayName();
+ if(!confirmDisplay.equals(EnumChatFormatting.GREEN+"Trading!")) {
+ if(mouseX > guiLeft+42 && mouseX < guiLeft+42+40) {
+ if (mouseY > guiTop+92 && mouseY < guiTop+92+14) {
+ if((confirmDisplay.equals(EnumChatFormatting.YELLOW+"Warning!") ||
+ confirmDisplay.equals(EnumChatFormatting.YELLOW+"Deal!")) && lastTradeMillis < 0) {
+ lastTradeMillis = System.currentTimeMillis();
+ } else if(lastTradeMillis < 0 || System.currentTimeMillis() - lastTradeMillis > 2000) {
+ Minecraft.getMinecraft().playerController.windowClick(
+ chest.inventorySlots.windowId,
+ 39, 2, 3, Minecraft.getMinecraft().thePlayer);
+ return;
+ }
+ }
+ }
+
+ }
+ }
+
+ if(mouseX >= guiLeft+xSize+3 && mouseX <= guiLeft+xSize+3+17) {
+ if(mouseY >= guiTop+ySize-19 && mouseY <= guiTop+ySize-19+17) {
+ NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.value =
+ !NotEnoughUpdates.INSTANCE.manager.config.useCustomTrade.value;
+ return;
+ } else if(mouseY >= guiTop+ySize-38 && mouseY <= guiTop+ySize-38+17) {
+ NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.value =
+ !NotEnoughUpdates.INSTANCE.manager.config.customTradePrices.value;
+ return;
+ } else if(mouseY >= guiTop+ySize-57 && mouseY <= guiTop+ySize-57+17) {
+ NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.value =
+ !NotEnoughUpdates.INSTANCE.manager.config.customTradePriceStyle.value;
+ return;
+ }
+ }
+ }
+ }
+
+ public static boolean keyboardInput() {
+ return Keyboard.getEventKey() != Keyboard.KEY_ESCAPE;
+ }
+
+}
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..d6f390c6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -1,12 +1,15 @@
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.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.event.ClickEvent;
import net.minecraft.event.HoverEvent;
+import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
@@ -15,36 +18,47 @@ import net.minecraft.nbt.NBTTagString;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.ChatStyle;
import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
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;
+import java.util.function.Consumer;
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<>();
private HashSet<String> playerBidsNotified = new HashSet<>();
private HashSet<String> playerBidsFinishedNotified = new HashSet<>();
- private HashMap<String, TreeMap<Integer, String>> internalnameToLowestBIN = new HashMap<>();
+ private JsonObject lowestBins = null;
+
+ private LinkedList<Integer> pagesToDownload = null;
- private JsonArray playerInformation = null;
+ private JsonObject bazaarJson = null;
+ private JsonObject auctionPricesJson = null;
+ private HashMap<String, CraftInfo> craftCost = new HashMap<>();
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 lastAuctionAvgUpdate = 0;
+ private long lastBazaarUpdate = 0;
+ private long lastLowestBinUpdate = 0;
+
+ private long lastApiUpdate = 0;
+ private long firstHypixelApiUpdate = 0;
public int activeAuctions = 0;
public int uniqueItems = 0;
@@ -53,28 +67,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;
}
@@ -96,15 +93,15 @@ public class APIManager {
public boolean bin;
public String category;
public String rarity;
- public NBTTagCompound item_tag;
+ public int dungeonTier;
+ public String item_tag_str;
+ public NBTTagCompound item_tag = null;
private ItemStack stack;
- public long lastUpdate = 0;
-
public int enchLevel = 0; //0 = clean, 1 = ench, 2 = ench/hpb
public Auction(String auctioneerUuid, long end, int starting_bid, int highest_bid_amount, int bid_count,
- boolean bin, String category, String rarity, NBTTagCompound item_tag) {
+ boolean bin, String category, String rarity, int dungeonTier, String item_tag_str) {
this.auctioneerUuid = auctioneerUuid;
this.end = end;
this.starting_bid = starting_bid;
@@ -112,79 +109,106 @@ public class APIManager {
this.bid_count = bid_count;
this.bin = bin;
this.category = category;
+ this.dungeonTier = dungeonTier;
this.rarity = rarity;
- this.item_tag = item_tag;
+ this.item_tag_str = item_tag_str;
}
public ItemStack getStack() {
+ if(item_tag == null && item_tag_str != null) {
+ try {
+ item_tag = CompressedStreamTools.readCompressed(
+ new ByteArrayInputStream(Base64.getDecoder().decode(item_tag_str)));
+ item_tag_str = null;
+ } catch(IOException e) {
+ return null;
+ }
+ }
if(stack != null) {
return stack;
} else {
JsonObject item = manager.getJsonFromNBT(item_tag);
ItemStack stack = manager.jsonToStack(item, false);
+
+ JsonObject itemDefault = manager.getItemInformation().get(item.get("internalname").getAsString());
+
+ if(stack != null && itemDefault != null) {
+ ItemStack stackDefault = manager.jsonToStack(itemDefault, true);
+ if(stack.isItemEqual(stackDefault)) {
+ //Item types are the same, compare lore
+
+ String[] stackLore = manager.getLoreFromNBT(stack.getTagCompound());
+ String[] defaultLore = manager.getLoreFromNBT(stackDefault.getTagCompound());
+
+ boolean loreMatches = stackLore != null && defaultLore != null && stackLore.length == defaultLore.length;
+ if(loreMatches) {
+ for(int i=0; i<stackLore.length; i++) {
+ if(!stackLore[i].equals(defaultLore[i])) {
+ loreMatches = false;
+ break;
+ }
+ }
+ }
+ if(loreMatches) {
+ stack = stackDefault;
+ }
+ }
+ }
this.stack = stack;
return stack;
}
}
}
+ public void markNeedsUpdate() {
+ firstHypixelApiUpdate = 0;
+ pagesToDownload = null;
+
+ auctionMap.clear();
+ internalnameToAucIdMap.clear();
+ extrasToAucIdMap.clear();
+ }
+
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();
- updatePageTick();
- ahNotification();
- }
- if(System.currentTimeMillis() - lastProfileUpdate > 10*1000) {
- lastProfileUpdate = System.currentTimeMillis();
- updateProfiles(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""));
- }
- if(System.currentTimeMillis() - lastCleanup > 120*1000) {
- lastCleanup = System.currentTimeMillis();
- cleanup();
- }
- if(System.currentTimeMillis() - lastCustomAHSearch > 60*1000) {
- lastCustomAHSearch = System.currentTimeMillis();
- if(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView()) {
- customAH.updateSearch();
- calculateStats();
+ long currentTime = System.currentTimeMillis();
+ if(manager.config.neuAuctionHouse.value) {
+ if(currentTime - lastAuctionUpdate > 60*1000) {
+ lastAuctionUpdate = currentTime;
+ updatePageTick();
}
- }
- }
-
- 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);
+ if(currentTime - lastShortAuctionUpdate > 10*1000) {
+ lastShortAuctionUpdate = currentTime;
+ updatePageTickShort();
+ ahNotification();
+ }
+ if(currentTime - lastCleanup > 60*1000) {
+ lastCleanup = currentTime;
+ cleanup();
+ }
+ if(currentTime - lastCustomAHSearch > 60*1000) {
+ lastCustomAHSearch = currentTime;
+ if(Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView()) {
+ customAH.updateSearch();
+ calculateStats();
}
}
- );
+ }
+ if(currentTime - lastAuctionAvgUpdate > 30*60*1000) { //30 minutes
+ lastAuctionAvgUpdate = currentTime - 28*60*1000; //Try again in 2 minutes if updateAvgPrices doesn't succeed
+ updateAvgPrices();
+ }
+ if(currentTime - lastBazaarUpdate > 10*60*1000) {
+ lastBazaarUpdate = currentTime;
+ updateBazaar();
+ }
+ if(currentTime - lastLowestBinUpdate > 2*60*1000) {
+ lastLowestBinUpdate = currentTime;
+ updateLowestBin();
+ }
}
private String niceAucId(String aucId) {
@@ -204,9 +228,24 @@ public class APIManager {
}
public int getLowestBin(String internalname) {
- TreeMap<Integer, String> lowestBIN = internalnameToLowestBIN.get(internalname);
- if(lowestBIN == null || lowestBIN.isEmpty()) return -1;
- return lowestBIN.firstKey();
+ if(lowestBins != null && lowestBins.has(internalname)) {
+ JsonElement e = lowestBins.get(internalname);
+ if(e.isJsonPrimitive() && e.getAsJsonPrimitive().isNumber()) {
+ return e.getAsInt();
+ }
+ }
+ return -1;
+ }
+
+ public void updateLowestBin() {
+ manager.hypixelApi.getMyApiGZIPAsync("lowestbin.json.gz", (jsonObject) -> {
+ if(lowestBins == null) {
+ lowestBins = new JsonObject();
+ }
+ for(Map.Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+ lowestBins.add(entry.getKey(), entry.getValue());
+ }
+ }, () -> {});
}
private void ahNotification() {
@@ -246,58 +285,119 @@ 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);
+ }
+ }
+
+ private void updatePageTickShort() {
+ if(pagesToDownload == null || pagesToDownload.isEmpty()) return;
+
+ if(firstHypixelApiUpdate == 0 || (System.currentTimeMillis() - firstHypixelApiUpdate)%(60*1000) > 15*1000) return;
+
+ JsonObject disable = Constants.DISABLE;
+ if(disable != null && disable.has("auctions_new") && disable.get("auctions_new").getAsBoolean()) return;
+
+ while(!pagesToDownload.isEmpty()) {
+ try {
+ int page = pagesToDownload.pop();
+ getPageFromAPI(page);
+ } catch(NoSuchElementException ignored) {} //Weird race condition?
}
}
private void updatePageTick() {
- if(totalPages == 0) {
+ JsonObject disable = Constants.DISABLE;
+ if(disable != null && disable.has("auctions_new") && disable.get("auctions_new").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();
+ Consumer<JsonObject> process = jsonObject -> {
+ if(jsonObject.get("success").getAsBoolean()) {
+ 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);
}
+ };
+
+ manager.hypixelApi.getMyApiGZIPAsync("auctionLast.json.gz", process, () -> {
+ System.out.println("Error downloading auction from Moulberry's jank API. :(");
+ });
+
+ manager.hypixelApi.getMyApiGZIPAsync("auction.json.gz", jsonObject -> {
+ if(jsonObject.get("success").getAsBoolean()) {
+ long apiUpdate = (long) jsonObject.get("time").getAsFloat();
+ if (lastApiUpdate == apiUpdate) {
+ lastAuctionUpdate -= 30 * 1000;
+ }
+ lastApiUpdate = apiUpdate;
+
+ process.accept(jsonObject);
+ }
+ }, () -> {
+ System.out.println("Error downloading auction from Moulberry's jank API. :(");
+ });
- getPageFromAPI(pageToUpdate);
- }
}
public void calculateStats() {
@@ -332,6 +432,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,169 +448,426 @@ public class APIManager {
return -1;
}
+ 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();
+
+ 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);
+
+ 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("ultimate_", "").replace("_", " ");
+ int enchantlevel = enchantments.getInteger(key);
+ String enchantLevelStr;
+ if(enchantlevel >= 1 && enchantlevel <= 20) {
+ enchantLevelStr = romans[enchantlevel-1];
+ } else {
+ enchantLevelStr = String.valueOf(enchantlevel);
+ }
+ extras = extras.replace(enchantname, enchantname + " " + enchantLevelStr);
+ }
+ }
+ }
+
+ 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++;
+ }
+
+ for(int j=0; j<bids.size(); j++) {
+ JsonObject bid = bids.get(j).getAsJsonObject();
+ if(bid.get("bidder").getAsString().equalsIgnoreCase(playerUUID)) {
+ playerBids.add(auctionUuid);
+ }
+ }
+
+ int dungeonTier = -1;
+ if(checkItemType(item_lore, true, "DUNGEON") >= 0) {
+ dungeonTier = 0;
+ for(int i=0; i<item_name.length(); i++) {
+ char c = item_name.charAt(i);
+ if(c == 0x272A) {
+ dungeonTier++;
+ }
+ }
+ }
+
+ //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, dungeonTier, item_bytes);
+
+ 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;
+ }
+ }
+ }
+
+ auctionMap.put(auctionUuid, auction1);
+ internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid);
+ } catch(Exception e) {e.printStackTrace();}
+ }
+
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.get("success").getAsBoolean()) {
- totalPages = jsonObject.get("totalPages").getAsInt();
- activeAuctions = jsonObject.get("totalAuctions").getAsInt();
+ if(jsonObject == null) return;
+
+ if (jsonObject.get("success").getAsBoolean()) {
+ if(pagesToDownload == null) {
+ int totalPages = jsonObject.get("totalPages").getAsInt();
+ pagesToDownload = new LinkedList<>();
+ for(int i=0; i<totalPages+2; i++) {
+ pagesToDownload.add(i);
+ }
+ }
+ if(firstHypixelApiUpdate == 0) {
+ firstHypixelApiUpdate = jsonObject.get("lastUpdated").getAsLong();
+ }
+ activeAuctions = jsonObject.get("totalAuctions").getAsInt();
- int lastUpdated = jsonObject.get("lastUpdated").getAsInt();
+ 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(lastApiUpdate != lastUpdated) {
- if(manager.config.quickAHUpdate.value &&
- (Minecraft.getMinecraft().currentScreen instanceof CustomAHGui || customAH.isRenderOverAuctionView())) {
- doFullUpdate = true;
+ processAuction(auction);
}
- resetNeedUpdate();
+ processMillis = (int)(System.currentTimeMillis() - startProcess);
+ } else {
+ pagesToDownload.addLast(page);
}
+ }, () -> {
+ pagesToDownload.addLast(page);
+ }
+ );
+ }
- lastApiUpdate = lastUpdated;
+ public void updateBazaar() {
+ manager.hypixelApi.getHypixelApiAsync(manager.config.apiKey.value, "skyblock/bazaar", new HashMap<>(), (jsonObject) -> {
+ if(!jsonObject.get("success").getAsBoolean()) return;
+
+ craftCost.clear();
+ bazaarJson = new JsonObject();
+ JsonObject products = jsonObject.get("products").getAsJsonObject();
+ for(Map.Entry<String, JsonElement> entry : products.entrySet()) {
+ if(entry.getValue().isJsonObject()) {
+ JsonObject productInfo = new JsonObject();
+
+ JsonObject product = entry.getValue().getAsJsonObject();
+ JsonObject quickStatus = product.get("quick_status").getAsJsonObject();
+ productInfo.addProperty("avg_buy", quickStatus.get("buyPrice").getAsFloat());
+ productInfo.addProperty("avg_sell", quickStatus.get("sellPrice").getAsFloat());
+
+ for(JsonElement element : product.get("sell_summary").getAsJsonArray()) {
+ if(element.isJsonObject()) {
+ JsonObject sellSummaryFirst = element.getAsJsonObject();
+ productInfo.addProperty("curr_sell", sellSummaryFirst.get("pricePerUnit").getAsFloat());
+ break;
+ }
+ }
- String[] lvl4Maxes = {"Experience", "Life Steal", "Scavenger", "Looting"};
+ for(JsonElement element : product.get("buy_summary").getAsJsonArray()) {
+ if(element.isJsonObject()) {
+ JsonObject sellSummaryFirst = element.getAsJsonObject();
+ productInfo.addProperty("curr_buy", sellSummaryFirst.get("pricePerUnit").getAsFloat());
+ break;
+ }
+ }
- String[] categoryItemType = new String[]{"sword","fishingrod","pickaxe","axe",
- "shovel","petitem","travelscroll","reforgestone","bow"};
- String playerUUID = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replaceAll("-","");
+ bazaarJson.add(entry.getKey().replace(":", "-"), productInfo);
+ }
+ }
+ });
+ }
- long startProcess = System.currentTimeMillis();
- JsonArray auctions = jsonObject.get("auctions").getAsJsonArray();
- for (int i = 0; i < auctions.size(); i++) {
- JsonObject auction = auctions.get(i).getAsJsonObject();
+ public void updateAvgPrices() {
+ manager.hypixelApi.getMyApiGZIPAsync("auction_averages/3day.json.gz", (jsonObject) -> {
+ craftCost.clear();
+ auctionPricesJson = jsonObject;
+ lastAuctionAvgUpdate = System.currentTimeMillis();
+ }, () -> {});
+ }
- 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());
- }
+ public Set<String> getItemAuctionInfoKeySet() {
+ if(auctionPricesJson == null) return new HashSet<>();
+ HashSet<String> keys = new HashSet<>();
+ for(Map.Entry<String, JsonElement> entry : auctionPricesJson.entrySet()) {
+ keys.add(entry.getKey());
+ }
+ return keys;
+ }
- 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++;
- }
+ public JsonObject getItemAuctionInfo(String internalname) {
+ if(auctionPricesJson == null) return null;
+ JsonElement e = auctionPricesJson.get(internalname);
+ if(e == null) {
+ return null;
+ }
+ return e.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());
- }
- }
+ public JsonObject getBazaarInfo(String internalname) {
+ if(bazaarJson == null) return null;
+ JsonElement e = bazaarJson.get(internalname);
+ if(e == null) {
+ return null;
+ }
+ return e.getAsJsonObject();
+ }
- for(int j=0; j<bids.size(); j++) {
- JsonObject bid = bids.get(j).getAsJsonObject();
- if(bid.get("bidder").getAsString().equalsIgnoreCase(playerUUID)) {
- playerBids.add(auctionUuid);
- }
- }
+ private static final List<String> hardcodedVanillaItems = Utils.createList(
+ "WOOD_AXE", "WOOD_HOE", "WOOD_PICKAXE","WOOD_SPADE", "WOOD_SWORD",
+ "GOLD_AXE", "GOLD_HOE", "GOLD_PICKAXE", "GOLD_SPADE", "GOLD_SWORD",
+ "ROOKIE_HOE"
+ );
+ public boolean isVanillaItem(String internalname) {
+ if(hardcodedVanillaItems.contains(internalname)) return true;
+
+ //Removes trailing numbers and underscores, eg. LEAVES_2-3 -> LEAVES
+ String vanillaName = internalname.split("-")[0];
+ if(manager.getItemInformation().containsKey(vanillaName)) {
+ JsonObject json = manager.getItemInformation().get(vanillaName);
+ if(json != null && json.has("vanilla") && json.get("vanilla").getAsBoolean()) return true;
+ }
+ return Item.itemRegistry.getObject(new ResourceLocation(vanillaName)) != null;
+ }
- 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);
- }
+ public class CraftInfo {
+ public boolean fromRecipe = false;
+ public boolean vanillaItem = false;
+ public float craftCost = -1;
+ }
- //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;
- }
- }
- }
+ public CraftInfo getCraftCost(String internalname) {
+ return getCraftCost(internalname, 0);
+ }
- auction1.lastUpdate = System.currentTimeMillis();
+ /**
+ * Recursively calculates the cost of crafting an item from raw materials.
+ */
+ public CraftInfo getCraftCost(String internalname, int depth) {
+ if(craftCost.containsKey(internalname)) {
+ return craftCost.get(internalname);
+ } else {
+ CraftInfo ci = new CraftInfo();
+
+ ci.vanillaItem = isVanillaItem(internalname);
+
+ JsonObject auctionInfo = getItemAuctionInfo(internalname);
+ JsonObject bazaarInfo = getBazaarInfo(internalname);
+
+ if(bazaarInfo != null && bazaarInfo.get("curr_buy") != null) {
+ float bazaarInstantBuyPrice = bazaarInfo.get("curr_buy").getAsFloat();
+ ci.craftCost = bazaarInstantBuyPrice;
+ }
+ //Don't use auction prices for vanilla items cuz people like to transfer money, messing up the cost of vanilla items.
+ if(auctionInfo != null && !ci.vanillaItem) {
+ float auctionPrice = auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat();
+ if(ci.craftCost < 0 || auctionPrice < ci.craftCost) {
+ ci.craftCost = auctionPrice;
+ }
+ }
+
+ if(depth > 16) {
+ craftCost.put(internalname, ci);
+ return ci;
+ }
+
+ JsonObject item = manager.getItemInformation().get(internalname);
+ if(item != null && item.has("recipe")) {
+ float craftPrice = 0;
+ JsonObject recipe = item.get("recipe").getAsJsonObject();
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ String name = y[i/3]+x[i%3];
+ String itemS = recipe.get(name).getAsString();
+ if(itemS == null || itemS.length() == 0) continue;
+
+ int count = 1;
+ if(itemS.split(":").length == 2) {
+ count = Integer.parseInt(itemS.split(":")[1]);
+ itemS = itemS.split(":")[0];
+ }
+ if(itemS.equals(internalname)) { //if item is used a crafting component in its own recipe, return
+ craftCost.put(internalname, ci);
+ return ci;
+ }
- auctionMap.put(auctionUuid, auction1);
- internalnameToAucIdMap.computeIfAbsent(internalname, k -> new HashSet<>()).add(auctionUuid);
- } catch(Exception e) {e.printStackTrace();}
+ float compCost = getCraftCost(itemS, depth+1).craftCost * count;
+ if(compCost < 0) {
+ //If it's a custom item without a cost, return
+ if(!getCraftCost(itemS).vanillaItem) {
+ craftCost.put(internalname, ci);
+ return ci;
+ }
+ } else {
+ craftPrice += compCost;
}
- processMillis = (int)(System.currentTimeMillis() - startProcess);
+ }
+
+ if(ci.craftCost < 0 || craftPrice < ci.craftCost) {
+ ci.craftCost = craftPrice;
+ ci.fromRecipe = true;
}
}
- );
+ craftCost.put(internalname, ci);
+ return ci;
+ }
}
- private void resetNeedUpdate() {
- for(Integer page=0; page<totalPages; page++) {
- if(!needUpdate.contains(page)) {
- needUpdate.addLast(page);
+ /**
+ * Calculates the cost of enchants + other price modifiers such as pet xp, midas price, etc.
+ */
+ public float getCostOfEnchants(String internalname, NBTTagCompound tag) {
+ float costOfEnchants = 0;
+ if(true) return 0;
+
+ JsonObject info = getItemAuctionInfo(internalname);
+ if(info == null || !info.has("price")) {
+ return 0;
+ }
+ if(auctionPricesJson == null || !auctionPricesJson.has("ench_prices") || !auctionPricesJson.has("ench_maximums")) {
+ return 0;
+ }
+ JsonObject ench_prices = auctionPricesJson.getAsJsonObject("ench_prices");
+ JsonObject ench_maximums = auctionPricesJson.getAsJsonObject("ench_maximums");
+ if(!ench_prices.has(internalname) || !ench_maximums.has(internalname)) {
+ return 0;
+ }
+ JsonObject iid_variables = ench_prices.getAsJsonObject(internalname);
+ float ench_maximum = ench_maximums.get(internalname).getAsFloat();
+
+ int enchants = 0;
+ float price = getItemAuctionInfo(internalname).get("price").getAsFloat();
+ if(tag.hasKey("ExtraAttributes")) {
+ NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
+ if(ea.hasKey("enchantments")) {
+
+ NBTTagCompound enchs = ea.getCompoundTag("enchantments");
+ for(String ench : enchs.getKeySet()) {
+ enchants++;
+ int level = enchs.getInteger(ench);
+
+ for(Map.Entry<String, JsonElement> entry : iid_variables.entrySet()) {
+ if(matchEnch(ench, level, entry.getKey())) {
+ costOfEnchants += entry.getValue().getAsJsonObject().get("A").getAsFloat()*price +
+ entry.getValue().getAsJsonObject().get("B").getAsFloat();
+ break;
+ }
+ }
+ }
}
}
+ return costOfEnchants;
+ }
+
+ /**
+ * Checks whether a certain enchant (ench name + lvl) matches an enchant id
+ * eg. PROTECTION_GE6 will match -> ench_name = PROTECTION, lvl >= 6
+ */
+ private boolean matchEnch(String ench, int level, String id) {
+ if(!id.contains(":")) {
+ return false;
+ }
+
+ String idEnch = id.split(":")[0];
+ String idLevel = id.split(":")[1];
+
+ if(!ench.equalsIgnoreCase(idEnch)) {
+ return false;
+ }
+
+ if(String.valueOf(level).equalsIgnoreCase(idLevel)) {
+ return true;
+ }
+
+ if(idLevel.startsWith("LE")) {
+ int idLevelI = Integer.valueOf(idLevel.substring(2));
+ return level <= idLevelI;
+ } else if(idLevel.startsWith("GE")) {
+ int idLevelI = Integer.valueOf(idLevel.substring(2));
+ return level >= idLevelI;
+ }
+
+ return false;
}
/*ScheduledExecutorService auctionUpdateSES = Executors.newSingleThreadScheduledExecutor();
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..42346651 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/CustomAH.java
@@ -1,6 +1,8 @@
package io.github.moulberry.notenoughupdates.auction;
+import com.google.gson.JsonObject;
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.client.gui.FontRenderer;
@@ -34,6 +36,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;
@@ -76,15 +80,18 @@ public class CustomAH extends Gui {
public long lastOpen;
public long lastGuiScreenSwitch;
- private int splits = 2;
+ private final int splits = 2;
- private int ySplit = 35;
- private int ySplitSize = 18;
+ public String latestBid;
+ public long latestBidMillis;
+
+ private final int ySplit = 35;
+ private final int ySplitSize = 18;
private float scrollAmount;
- private int guiLeft = 0;
- private int guiTop = 0;
+ public int guiLeft = -1;
+ public int guiTop = -1;
private Category CATEGORY_SWORD = new Category("sword", "Swords", "diamond_sword");
private Category CATEGORY_ARMOR = new Category("armor", "Armor", "diamond_chestplate");
@@ -103,7 +110,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,
@@ -125,11 +132,11 @@ public class CustomAH extends Gui {
private static final int SORT_MODE_SOON = 2;
private static final String[] rarities = { "COMMON", "UNCOMMON", "RARE", "EPIC",
- "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL" };
+ "LEGENDARY", "MYTHIC", "SPECIAL", "VERY SPECIAL", "SUPREME" };
private static final String[] rarityColours = { ""+EnumChatFormatting.WHITE,
""+EnumChatFormatting.GREEN, ""+EnumChatFormatting.BLUE, ""+EnumChatFormatting.DARK_PURPLE,
""+EnumChatFormatting.GOLD, ""+EnumChatFormatting.LIGHT_PURPLE, ""+EnumChatFormatting.RED,
- ""+EnumChatFormatting.RED };
+ ""+EnumChatFormatting.RED, ""+EnumChatFormatting.DARK_RED };
private static final int BIN_FILTER_ALL = 0;
private static final int BIN_FILTER_BIN = 1;
@@ -140,12 +147,23 @@ public class CustomAH extends Gui {
private static final int ENCH_FILTER_ENCH = 2;
private static final int ENCH_FILTER_ENCHHPB = 3;
+ private static final int DUNGEON_FILTER_ALL = 0;
+ private static final int DUNGEON_FILTER_DUNGEON = 1;
+ private static final int DUNGEON_FILTER_1 = 2;
+ private static final int DUNGEON_FILTER_2 = 3;
+ private static final int DUNGEON_FILTER_3 = 4;
+ private static final int DUNGEON_FILTER_4 = 5;
+ private static final int DUNGEON_FILTER_5 = 6;
+
+ private int dungeonFilter = DUNGEON_FILTER_ALL;
private int sortMode = SORT_MODE_HIGH;
private int rarityFilter = -1;
private boolean filterMyAuctions = false;
private int binFilter = BIN_FILTER_ALL;
private int enchFilter = ENCH_FILTER_ALL;
+ private static ItemStack DUNGEON_SORT = Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush),
+ EnumChatFormatting.GREEN+"Dungeon Sorting");
private static ItemStack CONTROL_SORT = Utils.createItemStack(Item.getItemFromBlock(Blocks.hopper),
EnumChatFormatting.GREEN+"Sort");
private static ItemStack CONTROL_TIER = Utils.createItemStack(Items.ender_eye,
@@ -158,7 +176,7 @@ public class CustomAH extends Gui {
EnumChatFormatting.GREEN+"Enchant Filter");
private static ItemStack CONTROL_STATS = Utils.createItemStack(Item.getItemFromBlock(Blocks.command_block),
EnumChatFormatting.GREEN+"Stats for nerds");
- private ItemStack[] controls = {null,CONTROL_SORT,CONTROL_TIER,null,CONTROL_MYAUC,null,CONTROL_BIN,CONTROL_ENCH,CONTROL_STATS};
+ private ItemStack[] controls = {DUNGEON_SORT,CONTROL_SORT,CONTROL_TIER,null,CONTROL_MYAUC,null,CONTROL_BIN,CONTROL_ENCH,CONTROL_STATS};
private NEUManager manager;
@@ -175,17 +193,25 @@ public class CustomAH extends Gui {
filterMyAuctions = false;
//binFilter = BIN_FILTER_ALL;
enchFilter = ENCH_FILTER_ALL;
+ dungeonFilter = DUNGEON_FILTER_ALL;
searchField.setText("");
searchField.setFocused(true);
priceField.setText("");
}
+ public void setSearch(String search) {
+ searchField.setText(search);
+ updateSearch();
+ }
+
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;
+ }
}
}
@@ -246,11 +272,11 @@ public class CustomAH extends Gui {
this.renderOverAuctionView = renderOverAuctionView;
}
- private int getXSize() {
+ public int getXSize() {
return 195;
}
- private int getYSize() {
+ public int getYSize() {
return 136 + ySplitSize*splits;
}
@@ -313,6 +339,47 @@ public class CustomAH extends Gui {
}
}
+ if(manager.config.auctionPriceInfo.value) {
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(auc.getStack());
+ if(internalname != null) {
+ tooltip.add("");
+ if(!Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) && !Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) {
+ tooltip.add(EnumChatFormatting.GRAY+"[SHIFT for Price Info]");
+ } else {
+ JsonObject auctionInfo = NotEnoughUpdates.INSTANCE.manager.auctionManager.getItemAuctionInfo(internalname);
+
+ boolean hasAuctionPrice = auctionInfo != null;
+
+ int lowestBin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internalname);
+
+ APIManager.CraftInfo craftCost = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internalname);
+
+ if(lowestBin > 0) {
+ tooltip.add(EnumChatFormatting.GRAY+"Lowest BIN: "+
+ EnumChatFormatting.GOLD+format.format(lowestBin)+" coins");
+ }
+ if(hasAuctionPrice) {
+ int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ tooltip.add(EnumChatFormatting.GRAY+"AH Price: "+
+ EnumChatFormatting.GOLD+format.format(auctionPrice)+" coins");
+ tooltip.add(EnumChatFormatting.GRAY+"AH Sales: "+
+ EnumChatFormatting.GOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day");
+ if(auctionInfo.has("clean_price")) {
+ tooltip.add(EnumChatFormatting.GRAY+"AH Price (Clean): "+
+ EnumChatFormatting.GOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins");
+ tooltip.add(EnumChatFormatting.GRAY+"AH Sales (Clean): "+
+ EnumChatFormatting.GOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day");
+ }
+
+ }
+ if(craftCost.fromRecipe) {
+ tooltip.add(EnumChatFormatting.GRAY+"Raw Craft Cost: "+
+ EnumChatFormatting.GOLD+format.format((int)craftCost.craftCost)+" coins");
+ }
+ }
+ }
+ }
+
tooltip.add("");
tooltip.add(EnumChatFormatting.GRAY+"Ends in: "+endsIn);
tooltip.add("");
@@ -401,13 +468,12 @@ public class CustomAH extends Gui {
return -1;
}
- public String findEndsInStr(ItemStack stack) {
+ public String findStrStart(ItemStack stack, String toFind) {
if(stack.hasTagCompound()) {
//§7Ends in:
- String endsIn = EnumChatFormatting.GRAY+"Ends in: ";
for(String line : manager.getLoreFromNBT(stack.getTagCompound())) {
- if(line.trim().startsWith(endsIn)) {
- return line.substring(endsIn.length());
+ if(line.trim().startsWith(toFind)) {
+ return line.substring(toFind.length());
}
}
}
@@ -415,6 +481,10 @@ public class CustomAH extends Gui {
return null;
}
+ public String findEndsInStr(ItemStack stack) {
+ return findStrStart(stack, EnumChatFormatting.GRAY+"Ends in: ");
+ }
+
public void drawScreen(int mouseX, int mouseY) {
if(System.currentTimeMillis() - lastOpen < 1000) Mouse.setGrabbed(false);
@@ -518,11 +588,71 @@ public class CustomAH extends Gui {
if(mouseX > auctionViewLeft+31 && mouseX <auctionViewLeft+31+16) {
if(mouseY > guiTop+35 && mouseY < guiTop+35+16) {
- if(topStack != null) tooltipToRender = topStack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ if(topStack != null) {
+ tooltipToRender = topStack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ tooltipToRender.add("");
+ tooltipToRender.add(EnumChatFormatting.YELLOW+"Click to copy seller name!");
+ }
} else if(mouseY > guiTop+100 && mouseY < guiTop+100+16) {
if(leftStack != null) tooltipToRender = leftStack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
} else if(mouseY > guiTop+61 && mouseY < guiTop+61+16) {
- if(rightStack != null) tooltipToRender = rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
+ tooltipToRender = new ArrayList<>();
+ APIManager.Auction auc = manager.auctionManager.getAuctionItems().get(currentAucId);
+ if(auc != null) {
+ tooltipToRender.add(EnumChatFormatting.WHITE+"Price Info");
+
+ String internalname = manager.getInternalNameForItem(auc.getStack());
+ JsonObject auctionInfo = manager.auctionManager.getItemAuctionInfo(internalname);
+ JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalname);
+
+ boolean hasAuctionPrice = auctionInfo != null;
+ boolean hasBazaarPrice = bazaarInfo != null;
+
+ int lowestBin = manager.auctionManager.getLowestBin(internalname);
+
+ NumberFormat format = NumberFormat.getInstance(Locale.US);
+
+ APIManager.CraftInfo craftCost = manager.auctionManager.getCraftCost(internalname);
+
+ if(lowestBin > 0) {
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Lowest BIN: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(lowestBin)+" coins");
+ }
+ if(hasBazaarPrice) {
+ int bazaarBuyPrice = (int)bazaarInfo.get("avg_buy").getAsFloat();
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarBuyPrice)+" coins");
+ int bazaarSellPrice = (int)bazaarInfo.get("avg_sell").getAsFloat();
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarSellPrice)+" coins");
+ int bazaarInstantBuyPrice = (int)bazaarInfo.get("curr_buy").getAsFloat();
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Buy: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantBuyPrice)+" coins");
+ int bazaarInstantSellPrice = (int)bazaarInfo.get("curr_sell").getAsFloat();
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Bazaar Insta-Sell: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(bazaarInstantSellPrice)+" coins");
+ }
+ if(hasAuctionPrice) {
+ int auctionPrice = (int)(auctionInfo.get("price").getAsFloat() / auctionInfo.get("count").getAsFloat());
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionPrice)+" coins");
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("sales").getAsFloat())+" sales/day");
+ if(auctionInfo.has("clean_price")) {
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Price (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)auctionInfo.get("clean_price").getAsFloat())+" coins");
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"AH Sales (Clean): "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format(auctionInfo.get("clean_sales").getAsFloat())+" sales/day");
+ }
+
+ }
+ if(craftCost.fromRecipe) {
+ tooltipToRender.add(EnumChatFormatting.YELLOW.toString()+EnumChatFormatting.BOLD+"Raw Craft Cost: "+
+ EnumChatFormatting.GOLD+EnumChatFormatting.BOLD+format.format((int)craftCost.craftCost)+" coins");
+ }
+ tooltipToRender.add("");
+ }
+ if(rightStack != null) tooltipToRender.addAll(rightStack.getTooltip(Minecraft.getMinecraft().thePlayer, false));
} else if(mouseY > guiTop+126 && mouseY < guiTop+126+16) {
if(middleStack != null) tooltipToRender = middleStack.getTooltip(Minecraft.getMinecraft().thePlayer, false);
}
@@ -530,8 +660,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);
@@ -728,29 +857,30 @@ public class CustomAH extends Gui {
int maxItemScroll = Math.max(0, totalItems - (5+splits)*9);
itemsScroll = Math.min(itemsScroll, maxItemScroll);
- out:
- for(int i=0; i<5+splits; i++) {
- int itemY = guiTop + i*18 + 18;
- for(int j=0; j<9; j++) {
- int itemX = guiLeft + j*18 + 9;
- int id = itemsScroll + i*9 + j;
- if(auctionIds.size() <= id) break out;
+ if(manager.config.neuAuctionHouse.value) {
+ out:
+ for(int i=0; i<5+splits; i++) {
+ int itemY = guiTop + i*18 + 18;
+ for(int j=0; j<9; j++) {
+ int itemX = guiLeft + j*18 + 9;
+ int id = itemsScroll + i*9 + j;
+ if(auctionIds.size() <= id) break out;
- try {
- String aucid = sortedAuctionIds.get(id);
+ try {
+ String aucid = sortedAuctionIds.get(id);
- GL11.glTranslatef(0,0,100);
- ItemStack stack = manager.auctionManager.getAuctionItems().get(aucid).getStack();
- Utils.drawItemStack(stack, itemX, itemY);
- GL11.glTranslatef(0,0,-100);
+ GL11.glTranslatef(0,0,100);
+ ItemStack stack = manager.auctionManager.getAuctionItems().get(aucid).getStack();
+ Utils.drawItemStack(stack, itemX, itemY);
+ GL11.glTranslatef(0,0,-100);
- if(mouseX > itemX && mouseX < itemX+16) {
- if(mouseY > itemY && mouseY < itemY+16) {
- tooltipToRender = getTooltipForAucId(aucid);
+ if(mouseX > itemX && mouseX < itemX+16) {
+ if(mouseY > itemY && mouseY < itemY+16) {
+ tooltipToRender = getTooltipForAucId(aucid);
+ }
}
+ } catch(Exception e) {
}
- } catch(Exception e) {
- break out;
}
}
}
@@ -773,6 +903,11 @@ public class CustomAH extends Gui {
this.drawTexturedModalRect(guiLeft+175, guiTop+18+(int)((95+ySplitSize*2)*scrollAmount),
256-(scrollClicked?12:24), 0, 12, 15);
+ if(!manager.config.neuAuctionHouse.value) {
+ Utils.drawStringCentered(EnumChatFormatting.RED+"NEUAH is DISABLED! Enable in /neusettings.",
+ Minecraft.getMinecraft().fontRendererObj, guiLeft+getXSize()/2, guiTop+getYSize()/2-5, true, 0);
+ }
+
if(tooltipToRender != null) {
List<String> tooltipGray = new ArrayList<>();
for(String line : tooltipToRender) {
@@ -794,7 +929,30 @@ public class CustomAH extends Gui {
String selPrefix = EnumChatFormatting.DARK_AQUA + selPrefixNC;
String unselPrefix = EnumChatFormatting.GRAY.toString();
switch(index) {
- case 0: break;
+ case 0:
+ lore.add("");
+ String gold = EnumChatFormatting.GOLD.toString();
+ String gray = EnumChatFormatting.GRAY.toString();
+ char s = 0x272A;
+ String[] linesDung = {"Show All","Any Dungeon",
+ gold+s+gray+s+s+s+s,
+ gold+s+s+gray+s+s+s,
+ gold+s+s+s+gray+s+s,
+ gold+s+s+s+s+gray+s,
+ gold+s+s+s+s+s};
+ for(int i=0; i<linesDung.length; i++) {
+ String line = linesDung[i];
+ if(i == dungeonFilter) {
+ line = selPrefix + line.replace(gray, EnumChatFormatting.DARK_AQUA.toString());
+ } else {
+ line = unselPrefix + line;
+ }
+ lore.add(line);
+ }
+ lore.add("");
+ lore.add(EnumChatFormatting.AQUA + "Right-Click to go backwards!");
+ lore.add(EnumChatFormatting.YELLOW + "Click to switch sort!");
+ return lore;
case 1:
lore.add("");
String[] linesSort = {"Highest Bid","Lowest Bid","Ending soon"};
@@ -867,6 +1025,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");
@@ -887,6 +1051,10 @@ public class CustomAH extends Gui {
}
public void handleMouseInput() {
+ if(!manager.config.neuAuctionHouse.value) {
+ return;
+ }
+
ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
int width = scaledResolution.getScaledWidth();
int height = scaledResolution.getScaledHeight();
@@ -907,14 +1075,16 @@ public class CustomAH extends Gui {
mouseClickMove(mouseX, mouseY, this.eventButton, l);
}
- int dWheel = Mouse.getEventDWheel();
- dWheel = Math.max(-1, Math.min(1, dWheel));
+ if(!manager.config.disableAhScroll.value) {
+ int dWheel = Mouse.getEventDWheel();
+ dWheel = Math.max(-1, Math.min(1, dWheel));
- scrollAmount = scrollAmount - dWheel/(float)(auctionIds.size()/9-(5+splits));
- scrollAmount = Math.max(0, Math.min(1, scrollAmount));
+ scrollAmount = scrollAmount - dWheel/(float)(auctionIds.size()/9-(5+splits));
+ scrollAmount = Math.max(0, Math.min(1, scrollAmount));
+ }
}
- private String niceAucId(String aucId) {
+ public String niceAucId(String aucId) {
if(aucId.length()!=32) return aucId;
StringBuilder niceAucId = new StringBuilder();
@@ -976,6 +1146,14 @@ public class CustomAH extends Gui {
}
}
+ if(dungeonFilter > DUNGEON_FILTER_ALL) {
+ if(dungeonFilter == DUNGEON_FILTER_DUNGEON && auc.dungeonTier < 0) {
+ match = false;
+ } else {
+ match &= dungeonFilter == auc.dungeonTier+1;
+ }
+ }
+
return match;
}
@@ -1032,116 +1210,125 @@ public class CustomAH extends Gui {
return matches;
}
+ private ExecutorService es = Executors.newSingleThreadExecutor();
public void updateSearch() {
- if(searchField == null || priceField == null) init();
-
- /*if(searchField.getText().length() > 0 && searchField.getText().length() <= 2 &&
- System.currentTimeMillis() - lastSearchFieldUpdate < 200) {
- shouldUpdateSearch = true;
- return;
- }*/
-
- if(System.currentTimeMillis() - lastUpdateSearch < 500) {
- shouldUpdateSearch = true;
+ if(!manager.config.neuAuctionHouse.value) {
return;
}
- lastUpdateSearch = System.currentTimeMillis();
- shouldUpdateSearch = false;
+ if(searchField == null || priceField == null) init();
+ long currentTime = System.currentTimeMillis();
- 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());
- }
- }
- } else {
- String query = searchField.getText();
- Set<String> dontMatch = new HashSet<>();
+ es.submit(() -> {
+ if(currentTime - lastUpdateSearch < 100) {
+ shouldUpdateSearch = true;
+ return;
+ }
+
+ lastUpdateSearch = currentTime;
+ shouldUpdateSearch = false;
- HashSet<String> allMatch = new HashSet<>();
- if(query.contains("!")) { //only used for inverted queries, so dont need to populate unless ! in query
+ 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 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 {
+ if(!manager.config.neuAuctionHouse.value) {
+ return;
+ }
+
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,12 +1363,18 @@ public class CustomAH extends Gui {
}
return o1.compareTo(o2);
});
+
+ sortedAuctionIds = sortedAuctionIdsNew;
} catch(Exception e) {
shouldSortItems = true;
}
}
public boolean keyboardInput() {
+ if(!manager.config.neuAuctionHouse.value) {
+ return false;
+ }
+
Keyboard.enableRepeatEvents(true);
if(isEditingPrice() && Keyboard.getEventKey() == Keyboard.KEY_RETURN) {
Minecraft.getMinecraft().displayGuiScreen(null);
@@ -1236,7 +1429,11 @@ public class CustomAH extends Gui {
}
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ boolean wasFocused = searchField.isFocused();
searchField.mouseClicked(mouseX, mouseY, mouseButton);
+ if(mouseButton == 1 && !wasFocused && searchField.isFocused()) {
+ searchField.setText("");
+ }
priceField.mouseClicked(mouseX, mouseY, mouseButton);
int totalItems = auctionIds.size();
@@ -1285,7 +1482,15 @@ public class CustomAH extends Gui {
int index = offset/18;
boolean rightClicked = Mouse.getEventButton() == 1;
switch(index) {
- case 0: break;
+ case 0:
+ if(rightClicked) {
+ dungeonFilter--;
+ if(dungeonFilter < DUNGEON_FILTER_ALL) dungeonFilter = DUNGEON_FILTER_5;
+ } else {
+ dungeonFilter++;
+ if(dungeonFilter > DUNGEON_FILTER_5) dungeonFilter = DUNGEON_FILTER_ALL;
+ }
+ break;
case 1:
if(rightClicked) {
sortMode--;
@@ -1350,7 +1555,16 @@ public class CustomAH extends Gui {
if(containerName.trim().equals("Auction View") || containerName.trim().equals("BIN Auction View")) {
if(mouseX > guiLeft+getXSize()+4+31 && mouseX < guiLeft+getXSize()+4+31+16) {
boolean leftFiller = isGuiFiller(auctionView.inventorySlots.getSlot(29).getStack());//isBin
- if(mouseY > guiTop+100 && mouseY < guiTop+100+16) {
+ if(mouseY > guiTop+35 && mouseY < guiTop+35+16) {
+ ItemStack topStack = auctionView.inventorySlots.getSlot(13).getStack();
+ if(topStack != null) {
+ String line = findStrStart(topStack, EnumChatFormatting.GRAY+"Seller: ");
+ String[] split = line.split(" ");
+ String seller = split[split.length-1];
+ StringSelection selection = new StringSelection(seller);
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection);
+ }
+ } else if(mouseY > guiTop+100 && mouseY < guiTop+100+16) {
int slotClick = leftFiller ? 31 : 29;
Minecraft.getMinecraft().playerController.windowClick(auctionView.inventorySlots.windowId,
slotClick, 2, 3, Minecraft.getMinecraft().thePlayer);
@@ -1371,11 +1585,13 @@ 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) {
manager.auctionManager.getPlayerBids().add(currentAucId);
+ latestBid = currentAucId;
+ latestBidMillis = System.currentTimeMillis();
//reset timer to 2m if below
if(manager.auctionManager.getAuctionItems().get(currentAucId).end -
System.currentTimeMillis() < 2*60*1000) {
@@ -1444,6 +1660,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..fa1db64e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -1,7 +1,10 @@
package io.github.moulberry.notenoughupdates.cosmetics;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.HypixelApi;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.client.event.RenderPlayerEvent;
@@ -11,6 +14,7 @@ import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
@@ -18,28 +22,108 @@ import java.util.Set;
public class CapeManager {
public static final CapeManager INSTANCE = new CapeManager();
+ public long lastCapeUpdate = 0;
+ public long lastCapeSynced = 0;
+ public Pair<NEUCape, String> localCape = null;
private HashMap<String, Pair<NEUCape, String>> capeMap = new HashMap<>();
- private String[] capes = new String[]{"testcape", "nullzee", "gravy", "fade", "contrib"};
+
+ private int permSyncTries = 5;
+ private boolean allAvailable = false;
+ private HashSet<String> availableCapes = new HashSet<>();
+
+ private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee", "gravy", "space", "mcworld", "lava", "packshq", "mbstaff" };
+ public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false, false, true, true, true };
public static CapeManager getInstance() {
return INSTANCE;
}
- public void setCape(String player, String capename) {
- if(capename == null) {
- NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value = "";
- capeMap.remove(player);
- return;
+ public void tick() {
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastCapeUpdate > 60*1000) {
+ lastCapeUpdate = currentTime;
+ updateCapes();
}
- if(player.equalsIgnoreCase(Minecraft.getMinecraft().thePlayer.getName())) {
- NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value = capename;
+ }
+
+ private void updateCapes() {
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("activecapes.json", (jsonObject) -> {
+ if(jsonObject.get("success").getAsBoolean()) {
+ lastCapeSynced = System.currentTimeMillis();
+ capeMap.clear();
+ for(JsonElement active : jsonObject.get("active").getAsJsonArray()) {
+ if(active.isJsonObject()) {
+ JsonObject activeObj = (JsonObject) active;
+ setCape(activeObj.get("_id").getAsString(), activeObj.get("capeType").getAsString(), false);
+ }
+ }
+ }
+ }, () -> {
+ System.out.println("[MBAPI] Update capes errored");
+ });
+
+ if(Minecraft.getMinecraft().thePlayer != null && permSyncTries > 0) {
+ String uuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
+ permSyncTries--;
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("permscapes.json", (jsonObject) -> {
+ if(jsonObject.get("success").getAsBoolean()) {
+ permSyncTries = 0;
+
+ availableCapes.clear();
+ for(JsonElement permPlayer : jsonObject.get("perms").getAsJsonArray()) {
+ if(permPlayer.isJsonObject()) {
+ String playerUuid = permPlayer.getAsJsonObject().get("_id").getAsString();
+ if(playerUuid != null && playerUuid.equals(uuid)) {
+ for(JsonElement perm : permPlayer.getAsJsonObject().get("perms").getAsJsonArray()) {
+ if(perm.isJsonPrimitive()) {
+ String cape = perm.getAsString();
+ if(cape.equals("*")) {
+ allAvailable = true;
+ } else {
+ availableCapes.add(cape);
+ }
+ }
+ }
+ return;
+ }
+ }
+ }
+ }
+ }, () -> {
+ System.out.println("[MBAPI] Update capes errored - perms");
+ });
}
- if(capeMap.containsKey(player)) {
- Pair<NEUCape, String> capePair = capeMap.get(player);
- capePair.setValue(capename);
- } else {
- capeMap.put(player, new MutablePair<>(new NEUCape(capename), capename));
+ }
+
+ public HashSet<String> getAvailableCapes() {
+ return allAvailable ? null : availableCapes;
+ }
+
+ public void setCape(String playerUUID, String capename, boolean updateConfig) {
+ boolean none = capename == null || capename.equals("null");
+
+ updateConfig = updateConfig && playerUUID.equals(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""));
+ if(updateConfig) {
+ NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value = String.valueOf(capename);
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
+ }
+
+ if(updateConfig) {
+ if(none) {
+ localCape = null;
+ } else {
+ localCape = new MutablePair<>(new NEUCape(capename), capename);
+ }
+ } else if(capeMap.containsKey(playerUUID)) {
+ if(none) {
+ capeMap.remove(playerUUID);
+ } else {
+ Pair<NEUCape, String> capePair = capeMap.get(playerUUID);
+ capePair.setValue(capename);
+ }
+ } else if(!none) {
+ capeMap.put(playerUUID, new MutablePair<>(new NEUCape(capename), capename));
}
}
@@ -50,10 +134,10 @@ public class CapeManager {
return null;
}
- public EntityPlayer getPlayerForName(String name) {
+ public EntityPlayer getPlayerForUUID(String uuid) {
if(Minecraft.getMinecraft().theWorld != null) {
for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
- if(player.getName().equals(name)) {
+ if(player.getUniqueID().toString().replace("-", "").equals(uuid)) {
return player;
}
}
@@ -64,34 +148,56 @@ public class CapeManager {
@SubscribeEvent
public void onRenderPlayer(RenderPlayerEvent.Post e) {
if(e.partialRenderTick == 1.0F) return; //rendering in inventory
- if(e.entityPlayer == Minecraft.getMinecraft().thePlayer) {
- if(NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value != null &&
- !NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value.isEmpty()) {
- setCape(Minecraft.getMinecraft().thePlayer.getName(),
- NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value);
+
+ String uuid = e.entityPlayer.getUniqueID().toString().replace("-", "");
+ String clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
+
+ if(Minecraft.getMinecraft().thePlayer != null && uuid.equals(clientUuid)) {
+ String selCape = NotEnoughUpdates.INSTANCE.manager.config.selectedCape.value;
+ if(selCape != null && !selCape.isEmpty()) {
+ if(localCape == null) {
+ localCape = new MutablePair<>(new NEUCape(selCape), selCape);
+ } else {
+ localCape.setValue(selCape);
+ }
}
}
- if(capeMap.containsKey(e.entityPlayer.getName())) {
- capeMap.get(e.entityPlayer.getName()).getLeft().onRenderPlayer(e);
+ if(uuid.equals(clientUuid) && localCape != null && localCape.getRight() != null && !localCape.getRight().equals("null")) {
+ localCape.getLeft().onRenderPlayer(e);
+ } else if(capeMap.containsKey(uuid)) {
+ capeMap.get(uuid).getLeft().onRenderPlayer(e);
}
}
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
+ String clientUuid = null;
+ if(Minecraft.getMinecraft().thePlayer != null) {
+ clientUuid = Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "");
+ }
+
Set<String> toRemove = new HashSet<>();
- for(String playerName : capeMap.keySet()) {
- EntityPlayer player = getPlayerForName(playerName);
- if(player == null) {
- toRemove.add(playerName);
- } else {
- String capeName = capeMap.get(playerName).getRight();
- if(capeName != null) {
- capeMap.get(playerName).getLeft().setCapeTexture(capeName);
- capeMap.get(playerName).getLeft().onTick(event, player);
- } else {
- toRemove.add(playerName);
+ try {
+ for(String playerUUID : capeMap.keySet()) {
+ EntityPlayer player = getPlayerForUUID(playerUUID);
+ if(player != null) {
+ String capeName = capeMap.get(playerUUID).getRight();
+ if(capeName != null && !capeName.equals("null")) {
+ if(playerUUID.equals(clientUuid) && localCape != null && localCape.getRight() != null && !localCape.getRight().equals("null")) {
+ continue;
+ }
+ capeMap.get(playerUUID).getLeft().setCapeTexture(capeName);
+ capeMap.get(playerUUID).getLeft().onTick(event, player);
+ } else {
+ toRemove.add(playerUUID);
+ }
}
}
+ } catch(Exception e) {}
+
+ if(localCape != null) {
+ localCape.getLeft().setCapeTexture(localCape.getValue());
+ localCape.getLeft().onTick(event, Minecraft.getMinecraft().thePlayer);
}
for(String playerName : toRemove) {
capeMap.remove(playerName);
@@ -102,22 +208,6 @@ public class CapeManager {
return capes;
}
- private String[] contributors = new String[]{"thatgravyboat", "twasnt", "traxyrr", "some1sm", "meguminqt", "marethyu_77"};
-
- public boolean getPermissionForCape(String player, String capename) {
- if(capename == null) {
- return false;
- } else if(player.equalsIgnoreCase("Moulberry")) {
- return true; //Oh yeah gimme gimme
- } else {
- switch(capename) {
- case "nullzee": return player.equalsIgnoreCase("Nullzee");
- case "gravy": return player.equalsIgnoreCase("ThatGravyBoat");
- case "contrib": return ArrayUtils.contains(contributors, player.toLowerCase());
- case "fade": return true;
- }
- }
- return false;
- }
+ //private String[] contributors = new String[]{"thatgravyboat", "twasnt", "traxyrr", "some1sm", "meguminqt", "marethyu_77"};
}
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..bfd33e48 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeNode.java
@@ -45,8 +45,8 @@ public class CapeNode {
public float vertSideTexU = 0;
public float vertSideTexVTop = 0;
- public static final float gravity = 0.1f;
- public static final float resistance = 0.5f;
+ public final float gravity = 0.1f;
+ public final float resistance = 0.5f;
public static final int FLOAT_NUM = 20;
@@ -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);
@@ -160,8 +160,6 @@ public class CapeNode {
}
public void resolve(CapeNode other, float targetDist, float strength, boolean opt) {
- if(other == null || Keyboard.isKeyDown(Keyboard.KEY_H)) return;
-
double dX = position.x - other.position.x;
double dY = position.y - other.position.y;
double dZ = position.z - other.position.z;
@@ -209,7 +207,7 @@ public class CapeNode {
NEUCape.Offset o = new NEUCape.Offset(d, 1);
CapeNode neighbor = getNeighbor(o);
if(neighbor != null) {
- if(!Keyboard.isKeyDown(Keyboard.KEY_H))resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt);
+ resolve(neighbor, 1f*NEUCape.targetDist*(d.yOff==0?horzDistMult:1f), 0.5f*7.5f, opt);
}
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
new file mode 100644
index 00000000..4723d00f
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/GuiCosmetics.java
@@ -0,0 +1,501 @@
+package io.github.moulberry.notenoughupdates.cosmetics;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.Matrix4f;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+import java.util.List;
+import java.util.*;
+
+public class GuiCosmetics extends GuiScreen {
+
+ public static final ResourceLocation pv_bg = new ResourceLocation("notenoughupdates:pv_bg.png");
+ public static final ResourceLocation pv_dropdown = new ResourceLocation("notenoughupdates:pv_dropdown.png");
+ public static final ResourceLocation cosmetics_fg = new ResourceLocation("notenoughupdates:cosmetics_fg.png");
+ public static final ResourceLocation pv_elements = new ResourceLocation("notenoughupdates:pv_elements.png");
+
+ private CosmeticsPage currentPage = CosmeticsPage.CAPES;
+ private int sizeX;
+ private int sizeY;
+ private int guiLeft;
+ private int guiTop;
+
+ private String wantToEquipCape = null;
+ private long lastCapeEquip = 0;
+
+ private List<String> tooltipToDisplay = null;
+
+ public enum CosmeticsPage {
+ CAPES(new ItemStack(Items.chainmail_chestplate));
+
+ public final ItemStack stack;
+
+ CosmeticsPage(ItemStack stack) {
+ this.stack = stack;
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ 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);
+
+ GlStateManager.color(1, 1, 1, 1);
+ switch (currentPage) {
+ case CAPES:
+ drawCapesPage(mouseX, mouseY, partialTicks);
+ break;
+ }
+
+ 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;
+ }
+
+ StringBuilder statusMsg = new StringBuilder("Last Sync: ");
+ if(CapeManager.INSTANCE.lastCapeSynced == 0) {
+ statusMsg.append("Not Synced");
+ } else {
+ statusMsg.append((System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeSynced)/1000).append("s ago");
+ }
+ statusMsg.append(" - Next Sync: ");
+ if(CapeManager.INSTANCE.lastCapeUpdate == 0) {
+ statusMsg.append("ASAP");
+ } else {
+ statusMsg.append(60 - (System.currentTimeMillis() - CapeManager.INSTANCE.lastCapeUpdate)/1000).append("s");
+ }
+
+ Minecraft.getMinecraft().fontRendererObj.drawString(EnumChatFormatting.AQUA+statusMsg.toString(),
+ guiLeft+sizeX-Minecraft.getMinecraft().fontRendererObj.getStringWidth(statusMsg.toString()), guiTop-12, 0, true);
+
+ if(currentPage == CosmeticsPage.CAPES) {
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
+ Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST);
+
+ String equipMsg;
+ if(wantToEquipCape != null) {
+ equipMsg = EnumChatFormatting.GREEN + "Equip Cape";
+ if(System.currentTimeMillis() - lastCapeEquip < 20*1000) {
+ equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s";
+ }
+ } else {
+ equipMsg = EnumChatFormatting.GREEN + "Unequip";
+ if(System.currentTimeMillis() - lastCapeEquip < 20*1000) {
+ equipMsg += " - " + (20 - (System.currentTimeMillis() - lastCapeEquip)/1000) + "s";
+ }
+ }
+
+ Utils.drawStringCenteredScaledMaxWidth(equipMsg, Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+sizeX/2f, guiTop+sizeY+5+10, false, 90, 0);
+ }
+ }
+
+ private void renderTabs(boolean renderPressed) {
+ int ignoredTabs = 0;
+ for(int i = 0; i< CosmeticsPage.values().length; i++) {
+ CosmeticsPage page = CosmeticsPage.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) {
+ for (int i = 0; i < CosmeticsPage.values().length; i++) {
+ CosmeticsPage page = CosmeticsPage.values()[i];
+ int x = guiLeft + i * 28;
+ int y = guiTop - 28;
+
+ if (mouseX > x && mouseX < x + 28) {
+ if (mouseY > y && mouseY < y + 32) {
+ if (currentPage != page) Utils.playPressSound();
+ currentPage = page;
+ return;
+ }
+ }
+ }
+ if(mouseY > guiTop+177 && mouseY < guiTop+177+12) {
+ if(mouseX > guiLeft+15+371*scroll && mouseX < guiLeft+15+371*scroll+32) {
+ scrollClickedX = mouseX - (int)(guiLeft+15+371*scroll);
+ return;
+ }
+ }
+
+ int index = 0;
+ int displayingCapes = 0;
+ for(String cape : CapeManager.INSTANCE.getCapes()) {
+ boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape);
+ if (!CapeManager.INSTANCE.specialCapes[index++] || equipable) {
+ displayingCapes++;
+ }
+ }
+
+ float totalNeeded = 91*displayingCapes;
+ float totalAvail = sizeX-20;
+ float xOffset = scroll*(totalNeeded-totalAvail);
+
+ index = 0;
+ int displayIndex = 0;
+ for(String cape : CapeManager.INSTANCE.getCapes()) {
+ boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape);
+ if(CapeManager.INSTANCE.specialCapes[index++] && !equipable) continue;
+
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft + 20 + 91 * displayIndex - xOffset, guiTop + 123, 81, 20,
+ 0, 81 / 256f, 216 / 256f, 236 / 256f, GL11.GL_NEAREST);
+
+ if(mouseX > guiLeft + 20 + 91 * displayIndex - xOffset && mouseX < guiLeft + 20 + 91 * displayIndex - xOffset+81) {
+ if(mouseY > guiTop + 123 && mouseY < guiTop + 123 + 20) {
+ if(CapeManager.INSTANCE.localCape != null && CapeManager.INSTANCE.localCape.getRight().equals(cape)) {
+ CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
+ "null", true);
+ } else {
+ CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
+ cape, true);
+ }
+
+ return;
+ } else if(equipable && mouseY > guiTop + 149 && mouseY < guiTop + 149 + 20) {
+ if(cape.equals(wantToEquipCape)) {
+ wantToEquipCape = null;
+ } else {
+ wantToEquipCape = cape;
+ }
+ return;
+ }
+ }
+
+ displayIndex++;
+ }
+
+ if(currentPage == CosmeticsPage.CAPES) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_dropdown);
+ Utils.drawTexturedRect(guiLeft+sizeX/2f-50, guiTop+sizeY+5, 100, 20, 0, 100/200f, 0, 20/185f, GL11.GL_NEAREST);
+
+ if(mouseX > guiLeft+sizeX/2f-50 && mouseX < guiLeft+sizeX/2f+50) {
+ if(mouseY > guiTop+sizeY+5 && mouseY < guiTop+sizeY+25) {
+ if(System.currentTimeMillis() - lastCapeEquip > 20*1000) {
+ CapeManager.INSTANCE.setCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
+ null, true);
+
+ lastCapeEquip = System.currentTimeMillis();
+ if(wantToEquipCape == null) {
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType=null&accessToken="+
+ Minecraft.getMinecraft().getSession().getToken(), (jsonObject) -> { System.out.println(jsonObject); }, () -> {
+ System.out.println("change cape error");
+ });
+ } else {
+ NotEnoughUpdates.INSTANCE.manager.hypixelApi.getMyApiAsync("cgi-bin/changecape.py?capeType="+wantToEquipCape+"&accessToken="+
+ Minecraft.getMinecraft().getSession().getToken(), (jsonObject) -> { System.out.println(jsonObject); }, () -> {
+ System.out.println("change cape error");
+ });
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void mouseReleased(int mouseX, int mouseY, int state) {
+ super.mouseReleased(mouseX, mouseY, state);
+
+ scrollClickedX = -1;
+ }
+
+ @Override
+ protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
+
+ if(scrollClickedX >= 0) {
+ float scrollStartX = mouseX - scrollClickedX;
+ scroll = (scrollStartX-(guiLeft+15))/371f;
+ scroll = Math.max(0, Math.min(1, scroll));
+ }
+ }
+
+ private HashMap<String, ResourceLocation> capesLocation = new HashMap<>();
+ private float scroll = 0f;
+ private int scrollClickedX = -1;
+ private void drawCapesPage(int mouseX, int mouseY, float partialTicks) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(cosmetics_fg);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(guiLeft+15+371*scroll, guiTop+177, 32, 12,
+ 0, 32/256f, 192/256f, 204/256f, GL11.GL_NEAREST);
+
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ GL11.glScissor(Minecraft.getMinecraft().displayWidth*(guiLeft+3)/width, 0,
+ Minecraft.getMinecraft().displayWidth*(sizeX-6)/width, Minecraft.getMinecraft().displayHeight);
+
+ int index = 0;
+ int displayingCapes = 0;
+ for(String cape : CapeManager.INSTANCE.getCapes()) {
+ boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape);
+ if (!CapeManager.INSTANCE.specialCapes[index++] || equipable) {
+ displayingCapes++;
+ }
+ }
+
+ float totalNeeded = 91*displayingCapes;
+ float totalAvail = sizeX-20;
+ float xOffset = scroll*(totalNeeded-totalAvail);
+
+ index = 0;
+ int displayIndex = 0;
+ for(String cape : CapeManager.INSTANCE.getCapes()) {
+ boolean equipable = CapeManager.INSTANCE.getAvailableCapes() == null || CapeManager.INSTANCE.getAvailableCapes().contains(cape);
+ if(CapeManager.INSTANCE.specialCapes[index++] && !equipable) continue;
+
+ if(cape.equals(CapeManager.INSTANCE.getCape(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")))) {
+ GlStateManager.color(250 / 255f, 200 / 255f, 0 / 255f, 1);
+ Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10,
+ guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108,
+ new Color(150, 100, 0, 40).getRGB(), new Color(250, 200, 0, 40).getRGB());
+ } else if(cape.equals(wantToEquipCape)) {
+ GlStateManager.color(0, 200 / 255f, 250 / 255f, 1);
+ Utils.drawGradientRect(guiLeft + 20 + 91 * displayIndex - (int) xOffset, guiTop + 10,
+ guiLeft + 20 + 91 * displayIndex - (int) xOffset + 81, guiTop + 10 + 108,
+ new Color(0, 100, 150, 40).getRGB(), new Color(0, 200, 250, 40).getRGB());
+ } else if(CapeManager.INSTANCE.localCape != null && CapeManager.INSTANCE.localCape.getRight().equals(cape)) {
+ GlStateManager.color(100/255f, 250/255f, 150/255f, 1);
+ Utils.drawGradientRect(guiLeft+20+91*displayIndex-(int)xOffset, guiTop+10,
+ guiLeft+20+91*displayIndex-(int)xOffset+81, guiTop+10+108,
+ new Color(50, 100, 75, 40).getRGB(), new Color(100, 250, 150, 40).getRGB());
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+10, 81, 108,
+ 0, 81/256f, 84/256f, 192/256f, GL11.GL_NEAREST);
+ GlStateManager.color(1, 1, 1, 1);
+
+ Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+123, 81, 20,
+ 0, 81/256f, 216/256f, 236/256f, GL11.GL_NEAREST);
+
+ boolean equipPressed = cape.equals(wantToEquipCape);
+ if(!equipable) GlStateManager.color(1, 1, 1, 0.5f);
+ Utils.drawTexturedRect(guiLeft+20+91*displayIndex-xOffset, guiTop+149, 81, 20,
+ equipPressed?81/256f:0, equipPressed?0:81/256f, equipPressed?236/256f:216/256f, equipPressed?216/256f:236/256f, GL11.GL_NEAREST);
+
+ Utils.drawStringCenteredScaledMaxWidth("Try it out", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+123+10, false, 75, new Color(100, 250, 150).getRGB());
+ if(equipable) {
+ Utils.drawStringCenteredScaledMaxWidth("Equip", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+149+10, false, 75, new Color(100, 250, 150).getRGB());
+ } else {
+ Utils.drawStringCenteredScaledMaxWidth("Not Unlocked", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+20+91*displayIndex+81/2f-xOffset, guiTop+149+10, false, 75, new Color(200, 50, 50, 100).getRGB());
+ }
+ GlStateManager.color(1, 1, 1, 1);
+
+ ResourceLocation capeTexture = capesLocation.computeIfAbsent(cape, k -> new ResourceLocation("notenoughupdates", "capes/"+cape+".png"));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture);
+ Utils.drawTexturedRect(guiLeft+31+91*displayIndex-xOffset, guiTop+24, 59, 84,
+ 0, 293/1024f, 0, 420/1024f, GL11.GL_NEAREST);
+
+ displayIndex++;
+ }
+
+ GL11.glScissor(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_elements);
+ }
+
+ 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/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
index 08d91057..d56a3f8c 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;
@@ -26,16 +27,29 @@ import org.lwjgl.util.vector.Vector3f;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.security.Key;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
public class NEUCape {
- public ResourceLocation capeTex = null;
+ private int currentFrame = 0;
+ private int displayFrame = 0;
+ private String capeName;
+ public ResourceLocation[] capeTextures = null;
+
+ private long lastFrameUpdate = 0;
+
+ private static int ANIM_MODE_LOOP = 0;
+ private static int ANIM_MODE_PINGPONG = 1;
+ private int animMode = ANIM_MODE_LOOP;
private List<List<CapeNode>> nodes = null;
+ private Random random = new Random();
+
+ private long eventMillis;
+ private float eventLength;
+ private float eventRandom;
+
private static double vertOffset = 1.4;
private static double shoulderLength = 0.24;
private static double shoulderWidth = 0.13;
@@ -45,6 +59,8 @@ public class NEUCape {
public static float targetDist = 1/20f;
+ private EntityPlayer currentPlayer;
+
private String shaderName = "cape";
public NEUCape(String capeName) {
@@ -52,14 +68,82 @@ public class NEUCape {
}
public void setCapeTexture(String capeName) {
- if(capeTex == null || !capeTex.getResourcePath().equals(capeName+".png")) {
- if(capeName.equalsIgnoreCase("fade")) {
- shaderName = "fade_cape";
- } else {
- shaderName = "cape";
+ if(this.capeName != null && this.capeName.equalsIgnoreCase(capeName)) return;
+ this.capeName = capeName;
+
+ startTime = System.currentTimeMillis();
+
+ if(capeName.equalsIgnoreCase("fade")) {
+ shaderName = "fade_cape";
+ } else if(capeName.equalsIgnoreCase("space")) {
+ shaderName = "space_cape";
+ } else if(capeName.equalsIgnoreCase("mcworld")) {
+ shaderName = "mcworld_cape";
+ } else if(capeName.equalsIgnoreCase("lava")) {
+ shaderName = "lava_cape";
+ } else if(capeName.equalsIgnoreCase("lightning")) {
+ shaderName = "lightning_cape";
+ } else {
+ shaderName = "cape";
+ }
+
+ ResourceLocation staticCapeTex = new ResourceLocation("notenoughupdates:capes/"+capeName+".png");
+ capeTextures = new ResourceLocation[1];
+ capeTextures[0] = staticCapeTex;
+
+ /*if(rlExists(staticCapeTex)) {
+ capeTextures = new ResourceLocation[1];
+ capeTextures[0] = staticCapeTex;
+ } else {
+ List<ResourceLocation> texs = new ArrayList<>();
+ for(int i=0; i<99; i++) {
+ ResourceLocation frame = new ResourceLocation(
+ "notenoughupdates:capes/"+capeName+"/"+capeName+"_"+String.format("%02d", i)+".png");
+ if(rlExists(frame)) {
+ texs.add(frame);
+ } else {
+ break;
+ }
+ }
+ capeTextures = new ResourceLocation[texs.size()];
+ for(int i=0; i<texs.size(); i++) {
+ capeTextures[i] = texs.get(i);
}
- capeTex = new ResourceLocation("notenoughupdates:"+capeName+".png");
- startTime = System.currentTimeMillis();
+ }*/
+ }
+
+ private void bindTexture() {
+ if(capeTextures != null && capeTextures.length>0) {
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastFrameUpdate > 100) {
+ lastFrameUpdate = currentTime/100*100;
+ currentFrame++;
+
+ if(animMode == ANIM_MODE_PINGPONG) {
+ if(capeTextures.length == 1) {
+ currentFrame = displayFrame = 0;
+ } else {
+ int frameCount = 2*capeTextures.length-2;
+ currentFrame %= frameCount;
+ displayFrame = currentFrame;
+ if(currentFrame >= capeTextures.length) {
+ displayFrame = frameCount - displayFrame;
+ }
+ }
+ } else if(animMode == ANIM_MODE_LOOP) {
+ currentFrame %= capeTextures.length;
+ displayFrame = currentFrame;
+ }
+ }
+ Minecraft.getMinecraft().getTextureManager().bindTexture(capeTextures[displayFrame]);
+ }
+ }
+
+ public boolean rlExists(ResourceLocation loc) {
+ try {
+ return !Minecraft.getMinecraft().getResourceManager().getAllResources(loc).isEmpty();
+ } catch(Exception e) {
+ return false;
}
}
@@ -88,7 +172,7 @@ public class NEUCape {
float centerMult = 1-Math.abs(j-(HORZ_NODES-1)/2f)/((HORZ_NODES-1)/2f);//0-(horzCapeNodes) -> 0-1-0
float vMax = vMaxSide + (vMaxCenter - vMaxSide) * centerMult;
- CapeNode node = new CapeNode(0, 0, 0);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2
+ CapeNode node = new CapeNode(pX, pY, pZ);//pX-1, pY+2-i*targetDist, pZ+(j-(horzCapeNodes-1)/2f)*targetDist*2
node.texU = uMin + (uMax - uMin) * j/(float)(HORZ_NODES-1);
node.texV = vMin + (vMax - vMin) * i/(float)(VERT_NODES-1);
@@ -216,6 +300,16 @@ public class NEUCape {
private void loadShaderUniforms(ShaderManager shaderManager) {
if(shaderName.equalsIgnoreCase("fade_cape")) {
shaderManager.loadData(shaderName, "millis", (int)(System.currentTimeMillis()-startTime));
+ } else if(shaderName.equalsIgnoreCase("space_cape")) {
+ shaderManager.loadData(shaderName, "millis", (int)(System.currentTimeMillis()-startTime));
+ shaderManager.loadData(shaderName, "eventMillis", (int)(System.currentTimeMillis()-eventMillis));
+ shaderManager.loadData(shaderName, "eventRand", eventRandom);
+ } else if(shaderName.equalsIgnoreCase("mcworld_cape")) {
+ shaderManager.loadData(shaderName, "millis", (int) (System.currentTimeMillis() - startTime));
+ } else if(shaderName.equalsIgnoreCase("lava_cape")) {
+ shaderManager.loadData(shaderName, "millis", (int) (System.currentTimeMillis() - startTime));
+ } else if(shaderName.equalsIgnoreCase("lightning_cape")) {
+ shaderManager.loadData(shaderName, "millis", (int) (System.currentTimeMillis() - startTime));
}
}
@@ -223,6 +317,11 @@ 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;
+ if(player.isSpectator() || player.isInvisible()) return;
+
ensureCapeNodesCreated(player);
Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
@@ -234,10 +333,19 @@ public class NEUCape {
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA,
GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO);
- Minecraft.getMinecraft().getTextureManager().bindTexture(capeTex);
+ bindTexture();
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, 0x8191, GL11.GL_TRUE);
GlStateManager.enableTexture2D();
GlStateManager.disableCull();
+ if(shaderName.equals("mcworld_cape")) {
+ 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);
+ } else {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+
GL11.glTranslatef(-(float)viewerX, -(float)viewerY, -(float)viewerZ);
ShaderManager shaderManager = ShaderManager.getInstance();
@@ -258,9 +366,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 +388,12 @@ public class NEUCape {
}
}
updateCape(player);
+
+ notRendering = false;
+ } else {
+ currentPlayer = null;
+
+ notRendering = true;
}
}
@@ -346,128 +469,138 @@ 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(shaderName.equals("space_cape")) {
+ long currentTime = System.currentTimeMillis();
+ if(currentTime-startTime > eventMillis-startTime+eventLength) {
+ eventMillis = currentTime;
+ eventLength = random.nextFloat()*2000+4000;
+ eventRandom = random.nextFloat();
+ }
+ }
+
+ 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 : 50;
+ 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 +682,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/dungeons/DungeonBlocks.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java
new file mode 100644
index 00000000..fb9de198
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonBlocks.java
@@ -0,0 +1,261 @@
+package io.github.moulberry.notenoughupdates.dungeons;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.questing.SBInfo;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.texture.*;
+import net.minecraft.client.resources.IResourceManager;
+import net.minecraft.client.resources.IResourceManagerReloadListener;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.BufferUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.*;
+
+import java.awt.*;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+public class DungeonBlocks {
+
+ private static Framebuffer framebufferBlocksTo = null;
+ private static Framebuffer framebufferBlocksFrom = null;
+
+ private static HashMap<String, Framebuffer> framebuffersDynamicTo = new HashMap<>();
+ public static HashMap<String, Framebuffer> framebuffersDynamicFrom = new HashMap<>();
+ private static HashSet<String> dynamicUpdated = new HashSet<>();
+
+ private static FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16);
+ private static FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16);
+
+ public static boolean textureExists() {
+ return framebufferBlocksFrom != null && isOverriding();
+ }
+
+ public static void bindTextureIfExists() {
+ if(textureExists()) {
+ framebufferBlocksFrom.bindFramebufferTexture();
+ }
+ }
+
+ public static boolean isOverriding() {
+ return OpenGlHelper.isFramebufferEnabled() && !NotEnoughUpdates.INSTANCE.manager.config.disableDungeonBlocks.value &&
+ (NotEnoughUpdates.INSTANCE.manager.config.dungeonBlocksEverywhere.value ||
+ (SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("dungeon")));
+ }
+
+ public static boolean bindModifiedTexture(ResourceLocation location, int colour) {
+ if(!isOverriding()) {
+ return false;
+ }
+
+ if(Utils.disableCustomDungColours) {
+ return false;
+ }
+
+ if(((colour >> 24) & 0xFF) < 10) {
+ return false;
+ }
+
+ String id = location.getResourceDomain()+":"+location.getResourcePath();
+ if(dynamicUpdated.contains(id) && framebuffersDynamicFrom.containsKey(id)) {
+ framebuffersDynamicFrom.get(id).bindFramebufferTexture();
+ return true;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
+ int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT);
+
+ Framebuffer to = checkFramebufferSizes(framebuffersDynamicTo.get(id), w, h);
+ dynamicUpdated.add(id);
+
+ try {
+ GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixOld);
+ GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewMatrixOld);
+
+ GL11.glPushMatrix();
+
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ to.bindFramebuffer(true);
+ GlStateManager.clearColor(0, 1, 0, 1);
+ GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT);
+
+ GlStateManager.disableBlend();
+ GlStateManager.disableLighting();
+ GlStateManager.disableFog();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(location);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR);
+
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ Utils.drawRectNoBlend(0, 0, w, h, colour);
+
+ GL11.glPopMatrix();
+
+ to.bindFramebufferTexture();
+ if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float)Minecraft.getMinecraft().gameSettings.mipmapLevels);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F);
+ GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
+ }
+
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadMatrix(projectionMatrixOld);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadMatrix(modelviewMatrixOld);
+
+ Framebuffer from = checkFramebufferSizes(framebuffersDynamicFrom.get(id), w, h);
+ framebuffersDynamicFrom.put(id, to);
+ framebuffersDynamicTo.put(id, from);
+
+ to.bindFramebufferTexture();
+
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+ GlStateManager.disableBlend();
+ GlStateManager.enableLighting();
+ return true;
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+ GlStateManager.disableBlend();
+ GlStateManager.enableLighting();
+ return false;
+ }
+
+ private static HashMap<ResourceLocation, String> dynamicPreloadMap = new HashMap<>();
+
+ static {
+ dynamicPreloadMap.put(new ResourceLocation("textures/entity/bat.png"),
+ NotEnoughUpdates.INSTANCE.manager.config.dungBatColour.value);
+ dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/normal.png"),
+ NotEnoughUpdates.INSTANCE.manager.config.dungChestColour.value);
+ dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/normal_double.png"),
+ NotEnoughUpdates.INSTANCE.manager.config.dungChestColour.value);
+ dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/trapped.png"),
+ NotEnoughUpdates.INSTANCE.manager.config.dungTrappedChestColour.value);
+ dynamicPreloadMap.put(new ResourceLocation("textures/entity/chest/trapped_double.png"),
+ NotEnoughUpdates.INSTANCE.manager.config.dungTrappedChestColour.value);
+ }
+
+ public static void tick() {
+ if(!isOverriding() || Minecraft.getMinecraft().theWorld == null) {
+ return;
+ }
+
+ dynamicUpdated.clear();
+
+ for(Map.Entry<ResourceLocation, String> entry : dynamicPreloadMap.entrySet()) {
+ bindModifiedTexture(entry.getKey(), SpecialColour.specialToChromaRGB(entry.getValue()));
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
+ int w = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_WIDTH);
+ int h = GL11.glGetTexLevelParameteri(GL11.GL_TEXTURE_2D, 0, GL11.GL_TEXTURE_HEIGHT);
+
+ Framebuffer to = checkFramebufferSizes(framebufferBlocksTo, w, h);
+
+ try {
+ GL11.glPushMatrix();
+
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, w, h, 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ to.bindFramebuffer(true);
+ GlStateManager.clear(GL11.GL_COLOR_BUFFER_BIT);
+
+ GlStateManager.disableBlend();
+ GlStateManager.disableLighting();
+ GlStateManager.disableFog();
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.locationBlocksTexture);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRectNoBlend(0, 0, w, h, 0, 1, 1, 0, GL11.GL_LINEAR);
+
+ HashMap<TextureAtlasSprite, Integer> spriteMap = new HashMap<>();
+ spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/stonebrick_cracked"),
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dungCrackedColour.value));
+ spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/dispenser_front_horizontal"),
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dungDispenserColour.value));
+ spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/lever"),
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dungLeverColour.value));
+ spriteMap.put(Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite("minecraft:blocks/trip_wire"),
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dungTripWireColour.value));
+
+ for(Map.Entry<TextureAtlasSprite, Integer> entry : spriteMap.entrySet()) {
+ if(((entry.getValue() >> 24) & 0xFF) < 10) continue;
+
+ TextureAtlasSprite tas = entry.getKey();
+ Gui.drawRect((int)(w*tas.getMinU()), h-(int)(h*tas.getMaxV())-1,
+ (int)(w*tas.getMaxU())+1, h-(int)(h*tas.getMinV()), entry.getValue());
+ }
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, scaledResolution.getScaledWidth_double(), scaledResolution.getScaledHeight_double(),
+ 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ GL11.glPopMatrix();
+
+ to.bindFramebufferTexture();
+ if (Minecraft.getMinecraft().gameSettings.mipmapLevels >= 0) {
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LEVEL, Minecraft.getMinecraft().gameSettings.mipmapLevels);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MIN_LOD, 0.0F);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL12.GL_TEXTURE_MAX_LOD, (float)Minecraft.getMinecraft().gameSettings.mipmapLevels);
+ GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, 0.0F);
+ GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
+ }
+
+ Framebuffer from = checkFramebufferSizes(framebufferBlocksFrom, w, h);
+ framebufferBlocksFrom = to;
+ framebufferBlocksTo = from;
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+ GlStateManager.enableBlend();
+ }
+
+ 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, false);
+ framebuffer.framebufferColor[0] = 1f;
+ framebuffer.framebufferColor[1] = 0f;
+ framebuffer.framebufferColor[2] = 0f;
+ framebuffer.framebufferColor[3] = 0;
+ } else {
+ framebuffer.createBindFramebuffer(width, height);
+ }
+ framebuffer.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ return framebuffer;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
new file mode 100644
index 00000000..fa49c0c2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
@@ -0,0 +1,1559 @@
+package io.github.moulberry.notenoughupdates.dungeons;
+
+import com.google.common.math.BigIntegerMath;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NEUResourceManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.questing.SBInfo;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.material.MapColor;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.MapItemRenderer;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureUtil;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemMap;
+import net.minecraft.item.ItemStack;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.util.*;
+import net.minecraft.world.storage.MapData;
+import net.minecraftforge.client.event.RenderGameOverlayEvent;
+import net.minecraftforge.fml.common.eventhandler.EventPriority;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+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.awt.image.BufferedImage;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.List;
+
+public class DungeonMap {
+
+ private static final ResourceLocation GREEN_CHECK = new ResourceLocation("notenoughupdates:dungeon_map/green_check.png");
+ private static final ResourceLocation WHITE_CHECK = new ResourceLocation("notenoughupdates:dungeon_map/white_check.png");
+ private static final ResourceLocation QUESTION = new ResourceLocation("notenoughupdates:dungeon_map/question.png");
+ private static final ResourceLocation CROSS = new ResourceLocation("notenoughupdates:dungeon_map/cross.png");
+
+ private static final ResourceLocation ROOM_RED = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/red_room.png");
+ private static final ResourceLocation ROOM_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/brown_room.png");
+ private static final ResourceLocation ROOM_GRAY = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/gray_room.png");
+ private static final ResourceLocation ROOM_GREEN = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/green_room.png");
+ private static final ResourceLocation ROOM_PINK = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/pink_room.png");
+ private static final ResourceLocation ROOM_PURPLE = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/purple_room.png");
+ private static final ResourceLocation ROOM_YELLOW = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/yellow_room.png");
+ private static final ResourceLocation ROOM_ORANGE = new ResourceLocation("notenoughupdates:dungeon_map/rooms_default/orange_room.png");
+
+ private static final ResourceLocation CORRIDOR_RED = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/red_corridor.png");
+ private static final ResourceLocation CORRIDOR_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/brown_corridor.png");
+ private static final ResourceLocation CORRIDOR_GRAY = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/gray_corridor.png");
+ private static final ResourceLocation CORRIDOR_GREEN = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/green_corridor.png");
+ private static final ResourceLocation CORRIDOR_PINK = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/pink_corridor.png");
+ private static final ResourceLocation CORRIDOR_PURPLE = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/purple_corridor.png");
+ private static final ResourceLocation CORRIDOR_YELLOW = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/yellow_corridor.png");
+ private static final ResourceLocation CORRIDOR_ORANGE = new ResourceLocation("notenoughupdates:dungeon_map/corridors_default/orange_corridor.png");
+
+ private static final ResourceLocation DIVIDER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/dividers_default/brown_divider.png");
+
+ private static final ResourceLocation CORNER_BROWN = new ResourceLocation("notenoughupdates:dungeon_map/corners_default/brown_corner.png");
+
+ private final HashMap<RoomOffset, Room> roomMap = new HashMap<>();
+ private Color[][] colourMap = new Color[128][128];
+ private int startRoomX = -1;
+ private int startRoomY = -1;
+ private int connectorSize = 5;
+ private int roomSize = 0;
+
+ //private final List<MapDecoration> decorations = new ArrayList<>();
+ //private final List<MapDecoration> lastDecorations = new ArrayList<>();
+ private long lastDecorationsMillis = -1;
+ private long lastLastDecorationsMillis = -1;
+
+ private Map<String, MapPosition> playerEntityMapPositions = new HashMap<>();
+ private Map<String, MapPosition> playerMarkerMapPositions = new HashMap<>();
+ private Map<String, MapPosition> playerMarkerMapPositionsLast = new HashMap<>();
+
+ private Map<String, ResourceLocation> playerSkinMap = new HashMap<>();
+
+ private class RoomOffset {
+ int x;
+ int y;
+
+ public RoomOffset(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public RoomOffset left() {
+ return new RoomOffset(x-1, y);
+ }
+
+ public RoomOffset right() {
+ return new RoomOffset(x+1, y);
+ }
+
+ public RoomOffset up() {
+ return new RoomOffset(x, y-1);
+ }
+
+ public RoomOffset down() {
+ return new RoomOffset(x, y+1);
+ }
+
+ public RoomOffset[] getNeighbors() {
+ return new RoomOffset[]{left(), right(), up(), down()};
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RoomOffset that = (RoomOffset) o;
+ return x == that.x && y == that.y;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(x, y);
+ }
+ }
+
+ private enum RoomConnectionType {
+ NONE, WALL, CORRIDOR, ROOM_DIVIDER
+ }
+
+ private class RoomConnection {
+ RoomConnectionType type;
+ Color colour;
+
+ public RoomConnection(RoomConnectionType type, Color colour) {
+ this.type = type;
+ this.colour = colour;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ RoomConnection that = (RoomConnection) o;
+ return type == that.type &&
+ Objects.equals(colour, that.colour);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, colour);
+ }
+ }
+
+ private class Room {
+ Color colour = new Color(0, 0, 0, 0);
+ int tickColour = 0;
+ boolean fillCorner = false;
+
+ RoomConnection left = new RoomConnection(RoomConnectionType.NONE, new Color(0, true));
+ RoomConnection up = new RoomConnection(RoomConnectionType.NONE, new Color(0, true));
+ RoomConnection right = new RoomConnection(RoomConnectionType.NONE, new Color(0, true));
+ RoomConnection down = new RoomConnection(RoomConnectionType.NONE, new Color(0, true));
+
+ public void renderNoRotate(int roomSize, int connectorSize, int rotation) {
+ if(tickColour != 0) {
+ Color tick = new Color(tickColour, true);
+ ResourceLocation indicatorTex = null;
+ if(tick.getRed() == 255 && tick.getGreen() == 255 && tick.getBlue() == 255) {
+ indicatorTex = WHITE_CHECK;
+ } else if(tick.getRed() == 0 && tick.getGreen() == 124 && tick.getBlue() == 0) {
+ indicatorTex = GREEN_CHECK;
+ } else if(tick.getRed() == 13 && tick.getGreen() == 13 && tick.getBlue() == 13) {
+ indicatorTex = QUESTION;
+ } else if(tick.getRed() == 255 && tick.getGreen() == 0 && tick.getBlue() == 0) {
+ indicatorTex = CROSS;
+ }
+ if(indicatorTex != null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(indicatorTex);
+ float x = 0;
+ float y = 0;
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmCenterCheck.value) {
+ if(fillCorner) {
+ x += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation-45))*1.414f;
+ y += (roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation-45))*1.414;
+ }
+ if(down.type == RoomConnectionType.ROOM_DIVIDER && right.type != RoomConnectionType.ROOM_DIVIDER) {
+ x += -(roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation));
+ y += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation));
+ } else if(down.type != RoomConnectionType.ROOM_DIVIDER && right.type == RoomConnectionType.ROOM_DIVIDER) {
+ x += -(roomSize+connectorSize)/2f*Math.cos(Math.toRadians(rotation));
+ y += (roomSize+connectorSize)/2f*Math.sin(Math.toRadians(rotation));
+ }
+ }
+ GlStateManager.translate(x, y, 0);
+ if(!NotEnoughUpdates.INSTANCE.manager.config.dmOrientCheck.value) {
+ GlStateManager.rotate(-rotation+180, 0, 0, 1);
+ }
+
+ Utils.drawTexturedRect(-5, -5, 10, 10, GL11.GL_NEAREST);
+
+ if(!NotEnoughUpdates.INSTANCE.manager.config.dmOrientCheck.value) {
+ GlStateManager.rotate(rotation-180, 0, 0, 1);
+ }
+ GlStateManager.translate(-x, -y, 0);
+ }
+ }
+ }
+
+ public void render(int roomSize, int connectorSize) {
+ ResourceLocation roomTex = null;
+ if(colour.getRed() == 114 && colour.getGreen() == 67 && colour.getBlue() == 27) {
+ roomTex = ROOM_BROWN;
+ } else if(colour.getRed() == 65 && colour.getGreen() == 65 && colour.getBlue() == 65) {
+ roomTex = ROOM_GRAY;
+ } else if(colour.getRed() == 0 && colour.getGreen() == 124 && colour.getBlue() == 0) {
+ roomTex = ROOM_GREEN;
+ } else if(colour.getRed() == 242 && colour.getGreen() == 127 && colour.getBlue() == 165) {
+ roomTex = ROOM_PINK;
+ } else if(colour.getRed() == 178 && colour.getGreen() == 76 && colour.getBlue() == 216) {
+ roomTex = ROOM_PURPLE;
+ } else if(colour.getRed() == 255 && colour.getGreen() == 0 && colour.getBlue() == 0) {
+ roomTex = ROOM_RED;
+ } else if(colour.getRed() == 229 && colour.getGreen() == 229 && colour.getBlue() == 51) {
+ roomTex = ROOM_YELLOW;
+ } else if(colour.getRed() == 216 && colour.getGreen() == 127 && colour.getBlue() == 51) {
+ roomTex = ROOM_ORANGE;
+ }
+
+ if(roomTex != null) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(roomTex);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(0, 0, roomSize, roomSize, GL11.GL_LINEAR);
+ } else {
+ Gui.drawRect(0, 0, roomSize, roomSize, colour.getRGB());
+ }
+
+ if(fillCorner) {
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(CORNER_BROWN);
+ Utils.drawTexturedRect(roomSize, roomSize, connectorSize, connectorSize, GL11.GL_NEAREST);
+ }
+
+ for(int k=0; k<2; k++) {
+ RoomConnection connection = down;
+ if(k == 1) connection = right;
+
+ if(connection.type == RoomConnectionType.NONE || connection.type == RoomConnectionType.WALL) continue;
+
+ ResourceLocation corridorTex = null;
+ if(connection.colour.getRed() == 114 && connection.colour.getGreen() == 67 && connection.colour.getBlue() == 27) {
+ corridorTex = connection.type == RoomConnectionType.CORRIDOR ? CORRIDOR_BROWN : DIVIDER_BROWN;
+ } else if(connection.colour.getRed() == 65 && connection.colour.getGreen() == 65 && connection.colour.getBlue() == 65) {
+ corridorTex = CORRIDOR_GRAY;
+ } else if(connection.colour.getRed() == 0 && connection.colour.getGreen() == 124 && connection.colour.getBlue() == 0) {
+ corridorTex = CORRIDOR_GREEN;
+ } else if(connection.colour.getRed() == 242 && connection.colour.getGreen() == 127 && connection.colour.getBlue() == 165) {
+ corridorTex = CORRIDOR_PINK;
+ } else if(connection.colour.getRed() == 178 && connection.colour.getGreen() == 76 && connection.colour.getBlue() == 216) {
+ corridorTex = CORRIDOR_PURPLE;
+ } else if(connection.colour.getRed() == 255 && connection.colour.getGreen() == 0 && connection.colour.getBlue() == 0) {
+ corridorTex = CORRIDOR_RED;
+ } else if(connection.colour.getRed() == 229 && connection.colour.getGreen() == 229 && connection.colour.getBlue() == 51) {
+ corridorTex = CORRIDOR_YELLOW;
+ } else if(connection.colour.getRed() == 216 && connection.colour.getGreen() == 127 && connection.colour.getBlue() == 51) {
+ corridorTex = CORRIDOR_ORANGE;
+ }
+
+ if(corridorTex == null) {
+ int xOffset = 0;
+ int yOffset = 0;
+ int width = 0;
+ int height = 0;
+
+ if(connection == right) {
+ xOffset = roomSize;
+ width = connectorSize;
+ height = roomSize;
+
+ if(connection.type == RoomConnectionType.CORRIDOR) {
+ height = 8;
+ yOffset += 4;
+ }
+ } else if(connection == down) {
+ yOffset = roomSize;
+ width = roomSize;
+ height = connectorSize;
+
+ if(connection.type == RoomConnectionType.CORRIDOR) {
+ width = 8;
+ xOffset += 4;
+ }
+ }
+
+ Gui.drawRect(xOffset, yOffset, xOffset+width, yOffset+height, connection.colour.getRGB());
+ } else {
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(corridorTex);
+ GlStateManager.pushMatrix();
+ if(connection==right) {
+ GlStateManager.translate(roomSize/2f, roomSize/2f, 0);
+ GlStateManager.rotate(-90, 0, 0, 1);
+ GlStateManager.translate(-roomSize/2f, -roomSize/2f, 0);
+ }
+ Utils.drawTexturedRect(0, roomSize, roomSize, connectorSize, GL11.GL_NEAREST);
+ GlStateManager.popMatrix();
+ }
+ }
+ }
+ }
+
+ private static final ResourceLocation mapIcons = new ResourceLocation("textures/map/map_icons.png");
+
+ public static Framebuffer mapFramebuffer1 = null;
+ public static Framebuffer mapFramebuffer2 = null;
+ public static Matrix4f projectionMatrix = null;
+ public static Shader mapShader = null;
+
+ 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;
+ }
+
+ private static void upload(Shader shader, int width, int height, int scale, float radiusSq) {
+ if(shader == null) return;
+ shader.getShaderManager().getShaderUniformOrDefault("ProjMat").set(projectionMatrix);
+ shader.getShaderManager().getShaderUniformOrDefault("InSize").set(width*scale, height*scale);
+ shader.getShaderManager().getShaderUniformOrDefault("OutSize").set(width, height);
+ shader.getShaderManager().getShaderUniformOrDefault("ScreenSize").set((float)width, (float)height);
+ shader.getShaderManager().getShaderUniformOrDefault("radiusSq").set(radiusSq);
+ }
+
+ public int getRenderRoomSize() {
+ int roomSizeOption = NotEnoughUpdates.INSTANCE.manager.config.dmRoomSize.value.intValue();
+ if(roomSizeOption <= 0) return 12;
+ return 12 + roomSizeOption*4;
+ }
+
+ public int getRenderConnSize() {
+ int roomSizeOption = NotEnoughUpdates.INSTANCE.manager.config.dmRoomSize.value.intValue();
+ if(roomSizeOption <= 0) return 3;
+ return 3 + roomSizeOption;
+ }
+
+ private HashMap<Integer, Float> borderRadiusCache = new HashMap<>();
+ public float getBorderRadius() {
+ int borderSizeOption = NotEnoughUpdates.INSTANCE.manager.config.dmBorderSize.value.intValue();
+ String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium";
+
+ int style = NotEnoughUpdates.INSTANCE.manager.config.dmBorderStyle.value.intValue();
+ if(borderRadiusCache.containsKey(style)) {
+ return borderRadiusCache.get(style);
+ }
+
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(Minecraft.getMinecraft().getResourceManager().getResource(
+ new ResourceLocation("notenoughupdates:dungeon_map/borders/"+sizeId+"/"+style+".json")).getInputStream(), StandardCharsets.UTF_8))) {
+ JsonObject json = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(reader, JsonObject.class);
+ float radiusSq = json.get("radiusSq").getAsFloat();
+
+ borderRadiusCache.put(style, radiusSq);
+ return radiusSq;
+ } catch(Exception ignored) { }
+
+ borderRadiusCache.put(style, 1f);
+ return 1f;
+ }
+
+ public void render(int centerX, int centerY) {
+ boolean useFb = NotEnoughUpdates.INSTANCE.manager.config.dmCompat.value <= 1;
+ boolean useShd = NotEnoughUpdates.INSTANCE.manager.config.dmCompat.value <= 0;
+
+ if((useFb && !OpenGlHelper.isFramebufferEnabled()) || (useShd && !OpenGlHelper.areShadersSupported())) {
+ Utils.drawStringCentered(EnumChatFormatting.RED+"NEU Dungeon Map requires framebuffers & shaders",
+ Minecraft.getMinecraft().fontRendererObj, centerX, centerY-10, true, 0);
+ Utils.drawStringCentered(EnumChatFormatting.RED+"Turn off Optifine Fast Render",
+ Minecraft.getMinecraft().fontRendererObj, centerX, centerY, true, 0);
+ Utils.drawStringCentered(EnumChatFormatting.RED+"If that doesn't work, join NEU discord for support",
+ Minecraft.getMinecraft().fontRendererObj, centerX, centerY+10, true, 0);
+ return;
+ }
+
+ ScaledResolution scaledResolution = Utils.pushGuiScale(2);
+
+ int minRoomX = 999;
+ int minRoomY = 999;
+ int maxRoomX = -999;
+ int maxRoomY = -999;
+ for(RoomOffset offset : roomMap.keySet()) {
+ minRoomX = Math.min(offset.x, minRoomX);
+ minRoomY = Math.min(offset.y, minRoomY);
+ maxRoomX = Math.max(offset.x, maxRoomX);
+ maxRoomY = Math.max(offset.y, maxRoomY);
+ }
+
+ int borderSizeOption = NotEnoughUpdates.INSTANCE.manager.config.dmBorderSize.value.intValue();
+
+ int renderRoomSize = getRenderRoomSize();
+ int renderConnSize = getRenderConnSize();
+
+ MapPosition playerPos = null;
+ if(playerEntityMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) {
+ playerPos = playerEntityMapPositions.get(Minecraft.getMinecraft().thePlayer.getName());
+ } else if(playerMarkerMapPositions.containsKey(Minecraft.getMinecraft().thePlayer.getName())) {
+ playerPos = playerMarkerMapPositions.get(Minecraft.getMinecraft().thePlayer.getName());
+ }
+
+ int rotation = 180;
+ if(playerPos != null && NotEnoughUpdates.INSTANCE.manager.config.dmRotatePlayer.value) {
+ rotation = (int)playerPos.rotation;
+ }
+
+ int mapSizeX = borderSizeOption == 0 ? 90 : borderSizeOption == 2 ? 160 : borderSizeOption == 3 ? 240 : 120;
+ int mapSizeY = borderSizeOption == 0 ? 90 : borderSizeOption == 2 ? 160 : borderSizeOption == 3 ? 240 : 120;
+ int roomsSizeX = (maxRoomX-minRoomX)*(renderRoomSize+renderConnSize)+renderRoomSize;
+ int roomsSizeY = (maxRoomY-minRoomY)*(renderRoomSize+renderConnSize)+renderRoomSize;
+ int mapCenterX = mapSizeX/2;
+ int mapCenterY = mapSizeY/2;
+ int scaleFactor = 8;
+
+ projectionMatrix = Utils.createProjectionMatrix(mapSizeX*scaleFactor, mapSizeY*scaleFactor);
+ mapFramebuffer1 = checkFramebufferSizes(mapFramebuffer1, mapSizeX*scaleFactor, mapSizeY*scaleFactor);
+ mapFramebuffer2 = checkFramebufferSizes(mapFramebuffer2, mapSizeX*scaleFactor, mapSizeY*scaleFactor);
+ mapFramebuffer1.framebufferColor[1] = 0;
+ mapFramebuffer1.framebufferColor[2] = 0;
+
+ try {
+ if(mapShader == null) {
+ mapShader = new Shader(new NEUResourceManager(Minecraft.getMinecraft().getResourceManager()),
+ "dungeonmap", mapFramebuffer1, mapFramebuffer2);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ int backgroundColour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundColour.value);
+
+ mapFramebuffer1.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF)/255f;
+ mapFramebuffer1.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF)/255f;
+ mapFramebuffer1.framebufferColor[2] = (backgroundColour & 0xFF)/255f;
+ mapFramebuffer2.framebufferColor[0] = ((backgroundColour >> 16) & 0xFF)/255f;
+ mapFramebuffer2.framebufferColor[1] = ((backgroundColour >> 8) & 0xFF)/255f;
+ mapFramebuffer2.framebufferColor[2] = (backgroundColour & 0xFF)/255f;
+
+ try {
+ if(useFb) {
+ mapFramebuffer1.framebufferClear();
+ mapFramebuffer2.framebufferClear();
+ }
+
+ GlStateManager.pushMatrix(); {
+ if(useFb) {
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, mapSizeX*scaleFactor, mapSizeY*scaleFactor, 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+
+ GlStateManager.scale(scaleFactor, scaleFactor, 1);
+ mapFramebuffer1.bindFramebuffer(true);
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ GlStateManager.disableBlend();
+ } else {
+ GL11.glEnable(GL11.GL_SCISSOR_TEST);
+ GL11.glScissor((centerX-mapSizeX/2)*2, Minecraft.getMinecraft().displayHeight-(centerY+mapSizeY/2)*2, mapSizeX*2, mapSizeY*2);
+
+ GlStateManager.translate(centerX-mapSizeX/2, centerY-mapSizeY/2, 100);
+ }
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.value > 0.1) {
+ GlStateManager.translate(-centerX+mapSizeX/2, -centerY+mapSizeY/2, 0);
+ renderBlurredBackground(scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(),
+ centerX-mapSizeX/2, centerY-mapSizeY/2, mapSizeX, mapSizeY);
+ GlStateManager.translate(centerX-mapSizeX/2, centerY-mapSizeY/2, 0);
+ }
+
+ GlStateManager.translate(mapCenterX, mapCenterY, 10);
+
+ if(!useFb || NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.value > 0.1) {
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ }
+ Utils.drawRectNoBlend(-mapCenterX, -mapCenterY, mapCenterX, mapCenterY, backgroundColour);
+
+ GlStateManager.rotate(-rotation+180, 0, 0, 1);
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmCenterPlayer.value && playerPos != null) {
+ float x = playerPos.getRenderX();
+ float y = playerPos.getRenderY();
+ x -= minRoomX*(renderRoomSize+renderConnSize);
+ y -= minRoomY*(renderRoomSize+renderConnSize);
+
+ GlStateManager.translate(-x, -y, 0);
+ } else {
+ GlStateManager.translate(-roomsSizeX/2, -roomsSizeY/2, 0);
+ }
+
+ for(Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) {
+ RoomOffset roomOffset = entry.getKey();
+ Room room = entry.getValue();
+
+ int x = (roomOffset.x-minRoomX)*(renderRoomSize+renderConnSize);
+ int y = (roomOffset.y-minRoomY)*(renderRoomSize+renderConnSize);
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x, y, 0);
+
+ room.render(renderRoomSize, renderConnSize);
+
+ GlStateManager.translate(-x, -y, 0);
+ GlStateManager.popMatrix();
+ }
+
+ GlStateManager.translate(-mapCenterX+roomsSizeX/2f, -mapCenterY+roomsSizeY/2f, 0);
+
+ GlStateManager.translate(mapCenterX, mapCenterY, 0);
+ GlStateManager.rotate(rotation-180, 0, 0, 1);
+ GlStateManager.translate(-mapCenterX, -mapCenterY, 0);
+
+ GlStateManager.translate(mapCenterX, mapCenterY, 0);
+
+ for(Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) {
+ RoomOffset roomOffset = entry.getKey();
+ Room room = entry.getValue();
+
+ float x = (roomOffset.x-minRoomX)*(renderRoomSize+renderConnSize)-roomsSizeX/2f+renderRoomSize/2f;
+ float y = (roomOffset.y-minRoomY)*(renderRoomSize+renderConnSize)-roomsSizeY/2f+renderRoomSize/2f;
+ float x2 = (float)(-x*Math.cos(Math.toRadians(-rotation)) + y*Math.sin(Math.toRadians(-rotation)));
+ float y2 = (float)(-x*Math.sin(Math.toRadians(-rotation)) - y*Math.cos(Math.toRadians(-rotation)));
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(x2, y2, 0);
+
+ GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F);
+ room.renderNoRotate(renderRoomSize, renderConnSize, rotation);
+
+ GlStateManager.translate(-x2, -y2, 0);
+ GlStateManager.popMatrix();
+ }
+
+
+ GlStateManager.translate(-mapCenterX, -mapCenterY, 0);
+
+ GlStateManager.translate(mapCenterX, mapCenterY, 0);
+ GlStateManager.rotate(-rotation+180, 0, 0, 1);
+ GlStateManager.translate(-mapCenterX, -mapCenterY, 0);
+
+ GlStateManager.translate(mapCenterX-roomsSizeX/2f, mapCenterY-roomsSizeY/2f, 0);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ int k = 0;
+
+ for(Map.Entry<String, MapPosition> entry : playerMarkerMapPositions.entrySet()) {
+ String name = entry.getKey();
+ MapPosition pos = entry.getValue();
+ float x = pos.getRenderX();
+ float y = pos.getRenderY();
+ float angle = pos.rotation;
+
+ boolean doInterp = NotEnoughUpdates.INSTANCE.manager.config.dmPlayerInterp.value;
+ if(playerEntityMapPositions.containsKey(name)) {
+ MapPosition entityPos = playerEntityMapPositions.get(name);
+ angle = entityPos.rotation;
+
+ float deltaX = entityPos.getRenderX() - pos.getRenderX();
+ float deltaY = entityPos.getRenderY() - pos.getRenderY();
+
+ if(deltaX > (renderRoomSize + renderConnSize)/2) {
+ deltaX -= (renderRoomSize + renderConnSize);
+ } else if(deltaX < -(renderRoomSize + renderConnSize)/2) {
+ deltaX += (renderRoomSize + renderConnSize);
+ }
+ if(deltaY > (renderRoomSize + renderConnSize)/2) {
+ deltaY -= (renderRoomSize + renderConnSize);
+ } else if(deltaY < -(renderRoomSize + renderConnSize)/2) {
+ deltaY += (renderRoomSize + renderConnSize);
+ }
+
+ x += deltaX;
+ y += deltaY;
+
+ doInterp = false;
+ }
+
+ float minU = 3/4f;
+ float minV = 0;
+
+ if(name.equals(Minecraft.getMinecraft().thePlayer.getName())) {
+ minU = 1/4f;
+ }
+
+ float maxU = minU + 1/4f;
+ float maxV = minV + 1/4f;
+
+ if(doInterp && playerMarkerMapPositionsLast.containsKey(name)) {
+ MapPosition last = playerMarkerMapPositionsLast.get(name);
+ float xLast = last.getRenderX();
+ float yLast = last.getRenderY();
+
+ float distSq = (x-xLast) * (x-xLast) + (y-yLast) * (y-yLast);
+ if (distSq < renderRoomSize*renderRoomSize/4f) {
+ float angleLast = last.rotation;
+ if (angle > 180 && angleLast < 180) angleLast += 360;
+ if (angleLast > 180 && angle < 180) angle += 360;
+
+ float interpFactor = Math.round((System.currentTimeMillis() - lastDecorationsMillis) * 100f) / 100f / (lastDecorationsMillis - lastLastDecorationsMillis);
+ interpFactor = Math.max(0, Math.min(1, interpFactor));
+
+ x = xLast + (x - xLast) * interpFactor;
+ y = yLast + (y - yLast) * interpFactor;
+ angle = angleLast + (angle - angleLast) * interpFactor;
+ angle %= 360;
+ }
+ }
+
+ boolean headLayer = false;
+ int pixelWidth = 8;
+ int pixelHeight = 8;
+ if(renderRoomSize >= 24) {
+ pixelWidth = pixelHeight = 12;
+ }
+ GlStateManager.color(1, 1, 1, 1);
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmPlayerHeads.value >= 1 &&
+ playerSkinMap.containsKey(entry.getKey())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(playerSkinMap.get(entry.getKey()));
+
+ headLayer = true;
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmPlayerHeads.value >= 3) {
+ minU = 9/64f;
+ minV = 9/64f;
+ maxU = 15/64f;
+ maxV = 15/64f;
+ } else {
+ minU = 8/64f;
+ minV = 8/64f;
+ maxU = 16/64f;
+ maxV = 16/64f;
+ }
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmPlayerHeads.value >= 2) {
+ pixelWidth = pixelWidth*6/8;
+ pixelHeight = pixelHeight*6/8;
+ }
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(mapIcons);
+ }
+
+ x -= minRoomX*(renderRoomSize+renderConnSize);
+ y -= minRoomY*(renderRoomSize+renderConnSize);
+
+ GlStateManager.pushMatrix();
+
+ GlStateManager.disableDepth();
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ GlStateManager.translate(x, y, -0.02F);
+ GlStateManager.rotate(angle, 0.0F, 0.0F, 1.0F);
+ GlStateManager.translate(-0.5F, 0.5F, 0.0F);
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer.pos(-pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)).tex(minU, minV).endVertex();
+ worldrenderer.pos(pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)).tex(maxU, minV).endVertex();
+ worldrenderer.pos(pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)).tex(maxU, maxV).endVertex();
+ worldrenderer.pos(-pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)).tex(minU, maxV).endVertex();
+ tessellator.draw();
+
+ if(headLayer) {
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer.pos(-pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(minU+0.5f, minV).endVertex();
+ worldrenderer.pos(pixelWidth/2f, pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(maxU+0.5f, minV).endVertex();
+ worldrenderer.pos(pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(maxU+0.5f, maxV).endVertex();
+ worldrenderer.pos(-pixelWidth/2f, -pixelHeight/2f, 30+((float)k * -0.005F)+0.001f).tex(minU+0.5f, maxV).endVertex();
+ tessellator.draw();
+ }
+ GlStateManager.popMatrix();
+ k--;
+ }
+
+ if(useFb) {
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+ } else {
+ GL11.glDisable(GL11.GL_SCISSOR_TEST);
+ }
+ } GlStateManager.popMatrix();
+
+ if(useFb) {
+ Framebuffer renderFromBuffer = mapFramebuffer1;
+ if(useShd) {
+ GlStateManager.pushMatrix(); {
+ try {
+ upload(mapShader, mapSizeX, mapSizeY, scaleFactor, getBorderRadius());
+ mapShader.setProjectionMatrix(projectionMatrix);
+ mapShader.loadShader(0);
+ renderFromBuffer = mapFramebuffer2;
+ } catch(Exception e) {
+ }
+ } GlStateManager.popMatrix();
+ }
+
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+
+ Utils.pushGuiScale(2);
+
+ GlStateManager.translate(centerX, centerY, 100);
+
+ renderFromBuffer.bindFramebufferTexture();
+ Utils.drawTexturedRect(-mapSizeX/2, -mapSizeY/2, mapSizeX, mapSizeY,
+ 0, 1, 1, 0, GL11.GL_NEAREST);
+ GlStateManager.bindTexture(0);
+
+ GlStateManager.translate(-centerX, -centerY, -100);
+
+ Utils.pushGuiScale(-1);
+ }
+
+ GlStateManager.translate(centerX, centerY, 100);
+
+ if(NotEnoughUpdates.INSTANCE.manager.config.dmChromaBorder.value) {
+ int colour = SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBorderColour.value);
+
+ Gui.drawRect(-mapCenterX-2, -mapCenterY-2, -mapCenterX, -mapCenterY,
+ colour); //topleft
+ Gui.drawRect(-mapCenterX-2, mapCenterY+2, -mapCenterX, mapCenterY,
+ SpecialColour.rotateHue(colour, -180)); //bottomleft
+ Gui.drawRect(mapCenterX, -mapCenterY-2, mapCenterX+2, mapCenterY,
+ SpecialColour.rotateHue(colour, -180)); //topright
+ Gui.drawRect(mapCenterX, mapCenterY, mapCenterX+2, mapCenterY+2,
+ colour); //bottomright
+
+ for(int i=0; i<20; i++) {
+ int start1 = SpecialColour.rotateHue(colour, -9*i);
+ int start2 = SpecialColour.rotateHue(colour, -9*i-9);
+ int end1 = SpecialColour.rotateHue(colour, -180-9*i);
+ int end2 = SpecialColour.rotateHue(colour, -180-9*i-9);
+
+ Utils.drawGradientRect(-mapCenterX-2, -mapCenterY+(int)(mapSizeY*(i/20f)), -mapCenterX,
+ -mapCenterY+(int)(mapSizeY*((i+1)/20f)), start1, start2); //left
+ Utils.drawGradientRect(mapCenterX, -mapCenterY+(int)(mapSizeX*(i/20f)), mapCenterX+2,
+ -mapCenterY+(int)(mapSizeX*((i+1)/20f)),
+ end1, end2); //right
+ Utils.drawGradientRectHorz(-mapCenterX+(int)(mapSizeX*(i/20f)), -mapCenterY-2,
+ -mapCenterX+(int)(mapSizeX*((i+1)/20f)), -mapCenterY, start1, start2); //top
+ Utils.drawGradientRectHorz(-mapCenterX+(int)(mapSizeX*(i/20f)),
+ mapCenterY, -mapCenterX+(int)(mapSizeX*((i+1)/20f)), mapCenterY+2,
+ end1, end2); //bottom
+ }
+
+ } else {
+ Gui.drawRect(-mapCenterX-2, -mapCenterY, -mapCenterX, mapCenterY,
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBorderColour.value)); //left
+ Gui.drawRect(mapCenterX, -mapCenterY, mapCenterX+2, mapCenterY,
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBorderColour.value)); //right
+ Gui.drawRect(-mapCenterX-2, -mapCenterY-2, mapCenterX+2, -mapCenterY,
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBorderColour.value)); //top
+ Gui.drawRect(-mapCenterX-2, mapCenterY, mapCenterX+2, mapCenterY+2,
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dmBorderColour.value)); //bottom
+ }
+
+ String sizeId = borderSizeOption == 0 ? "small" : borderSizeOption == 2 ? "large" : "medium";
+
+ ResourceLocation rl = new ResourceLocation("notenoughupdates:dungeon_map/borders/"+sizeId+"/"+
+ NotEnoughUpdates.INSTANCE.manager.config.dmBorderStyle.value.intValue()+".png");
+ if(Minecraft.getMinecraft().getTextureManager().getTexture(rl) != TextureUtil.missingTexture) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(rl);
+ GlStateManager.color(1, 1, 1, 1);
+
+ int size = borderSizeOption == 0 ? 165 : borderSizeOption == 2 ? 300 : borderSizeOption == 3 ? 440 : 220;
+ Utils.drawTexturedRect(-size/2, -size/2, size, size, GL11.GL_NEAREST);
+ }
+
+ GlStateManager.translate(-centerX, -centerY, -100);
+ } catch(Exception e) {
+ e.printStackTrace();
+ Minecraft.getMinecraft().entityRenderer.setupOverlayRendering();
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(true);
+ }
+
+ Utils.pushGuiScale(-1);
+
+ GlStateManager.enableBlend();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.enableDepth();
+ }
+
+
+ public void updateRoomConnections(RoomOffset roomOffset) {
+ if(roomMap.containsKey(roomOffset)) {
+ Room room = roomMap.get(roomOffset);
+
+ int otherPixelFilled = 0;
+ int otherPixelColour = 0;
+ for(int xOff=0; xOff<roomSize; xOff++) {
+ for(int yOff=0; yOff<roomSize; yOff++) {
+ int x = startRoomX + roomOffset.x*(roomSize+connectorSize) + xOff;
+ int y = startRoomY + roomOffset.y*(roomSize+connectorSize) + yOff;
+
+ if(x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) {
+ Color c = colourMap[x][y];
+ if(!c.equals(room.colour)) {
+ if(otherPixelColour == c.getRGB()) {
+ otherPixelFilled++;
+ } else {
+ otherPixelFilled--;
+ if(otherPixelFilled <= 0) {
+ otherPixelFilled = 1;
+ otherPixelColour = c.getRGB();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ room.tickColour = 0;
+ if((float)otherPixelFilled/roomSize/connectorSize > 0.05) {
+ room.tickColour = otherPixelColour;
+ }
+
+ for(int k=0; k<4; k++) {
+ Color colour = null;
+ int totalFilled = 0;
+
+ for(int i=0; i<roomSize; i++) {
+ for(int j=1; j<=connectorSize; j++) {
+ int x = startRoomX + roomOffset.x*(roomSize+connectorSize);
+ int y = startRoomY + roomOffset.y*(roomSize+connectorSize);
+
+ if(k == 0) {
+ x += i;
+ y -= j;
+ } else if(k == 1) {
+ x += roomSize+j-1;
+ y += i;
+ } else if(k == 2) {
+ x += i;
+ y += roomSize+j-1;
+ } else {
+ x -= j;
+ y += i;
+ }
+
+ if(x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) {
+ Color pixel = colourMap[x][y];
+ if(pixel.getAlpha() > 40) {
+ if(colour == null) {
+ colour = pixel;
+ totalFilled = 1;
+ } else {
+ if(colour.equals(pixel)) {
+ totalFilled++;
+ } else {
+ totalFilled--;
+ if(totalFilled <= 0) {
+ colour = pixel;
+ totalFilled = 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ float proportionFilled = (float)totalFilled/roomSize/connectorSize;
+
+ RoomConnectionType type = RoomConnectionType.WALL;
+ if(proportionFilled > 0.8) {
+ type = RoomConnectionType.ROOM_DIVIDER;
+ } else if(proportionFilled > 0.1) {
+ type = RoomConnectionType.CORRIDOR;
+ }
+ if(k == 0) {
+ room.up = new RoomConnection(type, colour);
+ } else if(k == 1) {
+ room.right = new RoomConnection(type, colour);
+ } else if(k == 2) {
+ room.down = new RoomConnection(type, colour);
+ } else {
+ room.left = new RoomConnection(type, colour);
+ }
+ }
+
+ int x = startRoomX + roomOffset.x*(roomSize+connectorSize) + roomSize + connectorSize/2;
+ int y = startRoomY + roomOffset.y*(roomSize+connectorSize) + roomSize + connectorSize/2;
+
+ room.fillCorner = false;
+ if(x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) {
+ Color pixel = colourMap[x][y];
+ if(pixel.equals(room.colour)) {
+ room.fillCorner = true;
+ }
+ }
+ }
+ }
+
+ public void loadNeighbors(RoomOffset room) {
+ if(!roomMap.containsKey(room)) {
+ roomMap.put(room, new Room());
+ }
+ for(RoomOffset neighbor : room.getNeighbors()) {
+ if(!roomMap.containsKey(neighbor)) {
+ int x = startRoomX + neighbor.x*(roomSize+connectorSize);
+ int y = startRoomY + neighbor.y*(roomSize+connectorSize);
+
+ if(x >= 0 && y >= 0 && x+roomSize < colourMap.length && y+roomSize < colourMap[x].length) {
+ if(colourMap[x][y].getAlpha() > 100) {
+ roomMap.put(neighbor, new Room());
+ loadNeighbors(neighbor);
+ }
+ }
+ }
+ }
+ }
+
+ public void updateRoomColours() {
+ for(Map.Entry<RoomOffset, Room> entry : roomMap.entrySet()) {
+ int x = startRoomX + entry.getKey().x*(roomSize+connectorSize);
+ int y = startRoomY + entry.getKey().y*(roomSize+connectorSize);
+
+ try {
+ entry.getValue().colour = colourMap[x][y];
+ } catch(Exception e) {}
+ }
+ }
+
+ private class MapPosition {
+ public float roomOffsetX;
+ public float connOffsetX;
+
+ public float roomOffsetY;
+ public float connOffsetY;
+
+ public float rotation;
+
+ public MapPosition(float roomOffsetX, float connOffsetX, float roomOffsetY, float connOffsetY) {
+ this.roomOffsetX = roomOffsetX;
+ this.connOffsetX = connOffsetX;
+ this.roomOffsetY = roomOffsetY;
+ this.connOffsetY = connOffsetY;
+ }
+
+ public float getRenderX() {
+ return roomOffsetX*getRenderRoomSize() + connOffsetX*getRenderConnSize();
+ }
+
+ public float getRenderY() {
+ return roomOffsetY*getRenderRoomSize() + connOffsetY*getRenderConnSize();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MapPosition that = (MapPosition) o;
+ return Float.compare(that.roomOffsetX, roomOffsetX) == 0 &&
+ Float.compare(that.connOffsetX, connOffsetX) == 0 &&
+ Float.compare(that.roomOffsetY, roomOffsetY) == 0 &&
+ Float.compare(that.connOffsetY, connOffsetY) == 0 &&
+ Float.compare(that.rotation, rotation) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(roomOffsetX, connOffsetX, roomOffsetY, connOffsetY, rotation);
+ }
+ }
+
+ private long lastClearCache = 0;
+ public void renderMap(int centerX, int centerY, Color[][] colourMap, Map<String, Vec4b> mapDecorations,
+ int roomSizeBlocks, Set<String> actualPlayers, boolean usePlayerPositions) {
+ if(!NotEnoughUpdates.INSTANCE.manager.config.dmEnable.value) return;
+ if(colourMap == null) return;
+ if(colourMap.length != 128) return;
+ if(colourMap[0].length != 128) return;
+ this.colourMap = colourMap;
+
+ if(System.currentTimeMillis() - lastClearCache > 1000) {
+ roomMap.clear();
+ startRoomX = -1;
+ startRoomY = -1;
+ connectorSize = -1;
+ roomSize = -1;
+ borderRadiusCache.clear();
+
+ lastClearCache = System.currentTimeMillis();
+ }
+
+ if(startRoomX < 0 || startRoomY < 0 || roomSize <= 0) {
+ for(int x=0; x<colourMap.length; x++) {
+ for(int y=0; y<colourMap[x].length; y++) {
+ Color c = colourMap[x][y];
+ if(c.getAlpha() > 80) {
+ if(startRoomX < 0 && startRoomY < 0 && c.getRed() == 0 && c.getGreen() == 124 && c.getBlue() == 0) {
+ roomSize = 0;
+ out:
+ for(int xd=0; xd<=20; xd++) {
+ for(int yd=0; yd<=20; yd++) {
+ if(x+xd >= colourMap.length || y+yd >= colourMap[x+xd].length) continue;
+ Color c2 = colourMap[x+xd][y+yd];
+
+ if(c2.getGreen() != 124 || c2.getAlpha() <= 80) {
+ if(xd < 10 && yd < 10) {
+ break out;
+ }
+ } else {
+ roomSize = Math.max(roomSize, Math.min(xd+1, yd+1));
+ }
+ if(xd == 20 && yd == 20) {
+ if(roomSize == 0) roomSize = 20;
+ startRoomX = x;
+ startRoomY = y;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if(connectorSize <= 0) {
+ for(int i=0; i<roomSize; i++) {
+ for(int k=0; k<4; k++) {
+ for(int j=1; j<8; j++) {
+ int x;
+ int y;
+
+ if(k == 0) {
+ x = startRoomX+i;
+ y = startRoomY-j;
+ } else if(k == 1) {
+ x = startRoomX+roomSize+j-1;
+ y = startRoomY+i;
+ } else if(k == 2) {
+ x = startRoomX+i;
+ y = startRoomY+roomSize+j-1;
+ } else {
+ x = startRoomX-j;
+ y = startRoomY+i;
+ }
+
+ if(x > 0 && y > 0 && x < colourMap.length && y < colourMap[x].length) {
+ if(colourMap[x][y].getAlpha() > 80) {
+ if(j == 1) {
+ break;
+ }
+ connectorSize = Math.min(connectorSize, j-1);
+ }
+ }
+ }
+ }
+ }
+
+ if(connectorSize <= 0) {
+ connectorSize = 4;
+ }
+ }
+
+ for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
+ if(player instanceof AbstractClientPlayer && actualPlayers.contains(player.getName())) {
+ AbstractClientPlayer aplayer = (AbstractClientPlayer) player;
+ ResourceLocation skin = aplayer.getLocationSkin();
+ if(skin != DefaultPlayerSkin.getDefaultSkin(aplayer.getUniqueID())) {
+ playerSkinMap.put(player.getName(), skin);
+ }
+ }
+ }
+
+ playerEntityMapPositions.clear();
+ if(usePlayerPositions) {
+ for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) {
+ if(actualPlayers.contains(player.getName())) {
+ float roomX = (float)player.posX / (roomSizeBlocks+1);
+ float roomY = (float)player.posZ / (roomSizeBlocks+1);
+
+ float playerRoomOffsetX = (float) Math.floor(roomX);
+ float playerConnOffsetX = (float) Math.floor(roomX);
+ float playerRoomOffsetY = (float) Math.floor(roomY);
+ float playerConnOffsetY = (float) Math.floor(roomY);
+
+ float roomXInBlocks = (float)player.posX % (roomSizeBlocks+1);
+ if(roomXInBlocks < 2) { //0,1
+ playerConnOffsetX -= 2/5f-roomXInBlocks/5f;
+ } else if(roomXInBlocks > roomSizeBlocks-2) { //31,30,29
+ playerRoomOffsetX++;
+ playerConnOffsetX += (roomXInBlocks - (roomSizeBlocks-2))/5f;
+ } else {
+ playerRoomOffsetX += (roomXInBlocks-2) / (roomSizeBlocks-4);
+ }
+
+ float roomYInBlocks = (float)player.posZ % (roomSizeBlocks+1);
+ if(roomYInBlocks < 2) { //0,1
+ playerConnOffsetY -= 2/5f-roomYInBlocks/5f;
+ } else if(roomYInBlocks > roomSizeBlocks-2) { //31,30,29
+ playerRoomOffsetY++;
+ playerConnOffsetY += (roomYInBlocks - (roomSizeBlocks-2))/5f;
+ } else {
+ playerRoomOffsetY += (roomYInBlocks-2) / (roomSizeBlocks-4);
+ }
+
+ playerRoomOffsetX -= startRoomX/(roomSize+connectorSize);
+ playerRoomOffsetY -= startRoomY/(roomSize+connectorSize);
+ playerConnOffsetX -= startRoomX/(roomSize+connectorSize);
+ playerConnOffsetY -= startRoomY/(roomSize+connectorSize);
+
+ MapPosition pos = new MapPosition(playerRoomOffsetX, playerConnOffsetX, playerRoomOffsetY, playerConnOffsetY);
+ pos.rotation = player.rotationYawHead % 360;
+ if(pos.rotation < 0) pos.rotation += 360;
+ playerEntityMapPositions.put(player.getName(), pos);
+ }
+ }
+ }
+
+ loadNeighbors(new RoomOffset(0, 0));
+ updateRoomColours();
+ for(RoomOffset offset : roomMap.keySet()) {
+ updateRoomConnections(offset);
+ }
+
+ if(mapDecorations != null && mapDecorations.size() > 0) {
+ List<MapPosition> positions = new ArrayList<>();
+ for (Vec4b vec4b : mapDecorations.values()) {
+ float x = (float) vec4b.func_176112_b() / 2.0F + 64.0F;
+ float y = (float) vec4b.func_176113_c() / 2.0F + 64.0F;
+
+ x = Math.max(0, Math.min(160, x));
+ y = Math.max(0, Math.min(160, y));
+
+ float deltaX = x - startRoomX;
+ float deltaY = y - startRoomY;
+
+ float roomsOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize));
+ float connOffsetX = (int) Math.floor(deltaX / (roomSize + connectorSize));
+ float xRemainder = deltaX % (roomSize + connectorSize);
+ if (Math.abs(xRemainder) > roomSize) {
+ roomsOffsetX += Math.copySign(1, xRemainder);
+ connOffsetX += Math.copySign(1, xRemainder) * (Math.abs(xRemainder) - roomSize) / connectorSize;
+ } else {
+ roomsOffsetX += xRemainder / roomSize;
+ }
+ if (deltaX < 0 && xRemainder != 0) {
+ roomsOffsetX++;
+ connOffsetX++;
+ }
+ float roomsOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize));
+ float connOffsetY = (int) Math.floor(deltaY / (roomSize + connectorSize));
+ float yRemainder = deltaY % (roomSize + connectorSize);
+ if (Math.abs(yRemainder) > roomSize) {
+ roomsOffsetY += Math.copySign(1, yRemainder);
+ connOffsetY += Math.copySign(1, yRemainder) * (Math.abs(yRemainder) - roomSize) / connectorSize;
+ } else {
+ roomsOffsetY += yRemainder / roomSize;
+ }
+ if (deltaY < 0 && yRemainder != 0) {
+ roomsOffsetY++;
+ connOffsetY++;
+ }
+
+ float angle = (float) (vec4b.func_176111_d() * 360) / 16.0F;
+
+ MapPosition pos = new MapPosition(roomsOffsetX, connOffsetX, roomsOffsetY, connOffsetY);
+ pos.rotation = angle % 360;
+ if(pos.rotation < 0) pos.rotation += 360;
+ positions.add(pos);
+ }
+
+ //System.out.println(playerMarkerMapPositions.size() + ":" + positions.size());
+ boolean different = playerMarkerMapPositions.size() != positions.size();
+
+ if (!different) {
+ for (MapPosition pos : playerMarkerMapPositions.values()) {
+ if (!positions.contains(pos)) {
+ different = true;
+ break;
+ }
+ }
+ }
+
+ if(different && positions.size() > 0) {
+ lastLastDecorationsMillis = lastDecorationsMillis;
+ lastDecorationsMillis = System.currentTimeMillis();
+
+ playerMarkerMapPositionsLast.clear();
+ for (Map.Entry<String, MapPosition> entry : playerMarkerMapPositions.entrySet()) {
+ playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue());
+ }
+ playerMarkerMapPositions.clear();
+
+ Set<String> foundPlayers = new HashSet<>();
+ for (Map.Entry<String, MapPosition> entry : playerEntityMapPositions.entrySet()) {
+ playerMarkerMapPositions.put(entry.getKey(), entry.getValue());
+ playerMarkerMapPositionsLast.put(entry.getKey(), entry.getValue());
+ foundPlayers.add(entry.getKey());
+ }
+
+ HashMap<String, HashMap<Integer, Float>> distanceMap = new HashMap<>();
+ for (Map.Entry<String, MapPosition> entry : playerMarkerMapPositionsLast.entrySet()) {
+ HashMap<Integer, Float> deltaDists = new HashMap<>();
+ for (int i = 0; i < positions.size(); i++) {
+ float dx = entry.getValue().getRenderX() - positions.get(i).getRenderX();
+ float dy = entry.getValue().getRenderY() - positions.get(i).getRenderY();
+ deltaDists.put(i, dx * dx + dy * dy);
+ }
+ distanceMap.put(entry.getKey(), deltaDists);
+ }
+
+ List<String> playerList = new ArrayList<>(playerMarkerMapPositionsLast.keySet());
+ List<List<String>> playerPermutations = permutations(playerList);
+
+ //if(playerPermutations.size() > 0 || playerMarkerMapPositionsLast.size() > 0)
+ // System.out.println("Perm Size: " + playerPermutations.size() + " from " + playerMarkerMapPositionsLast.size());
+
+ List<Integer> finalUsedIndexes = new ArrayList<>();
+ if (playerPermutations.size() > 0) {
+ HashMap<String, Integer> smallestPermutation = null;
+ float smallestTotalDistance = 0;
+
+ for (List<String> permutation : playerPermutations) {
+ HashMap<String, Integer> usedIndexes = new HashMap<>();
+
+ float totalDistance = 0;
+ for (String player : permutation) {
+ int smallestIndex = -1;
+ float smallestDist = 0;
+ for (Map.Entry<Integer, Float> entry : distanceMap.get(player).entrySet()) {
+ if (!usedIndexes.containsValue(entry.getKey())) {
+ if (smallestIndex == -1 || entry.getValue() < smallestDist) {
+ smallestIndex = entry.getKey();
+ smallestDist = entry.getValue();
+ }
+ }
+ }
+ if (smallestIndex != -1) {
+ usedIndexes.put(player, smallestIndex);
+ totalDistance += smallestDist;
+ }
+ }
+
+ if (smallestPermutation == null || totalDistance < smallestTotalDistance) {
+ smallestPermutation = usedIndexes;
+ smallestTotalDistance = totalDistance;
+ }
+ }
+
+ //System.out.println("--- PERM START ---");
+ for (Map.Entry<String, Integer> entry : smallestPermutation.entrySet()) {
+ //System.out.println(entry.getKey() + ":" + entry.getValue() + " : Total dist: " + smallestTotalDistance);
+ finalUsedIndexes.add(entry.getValue());
+ playerMarkerMapPositions.put(entry.getKey(), positions.get(entry.getValue()));
+ }
+ }
+
+ List<Integer> nonUsedIndexes = new ArrayList<>();
+ for(int i=0; i<positions.size(); i++) {
+ if(!finalUsedIndexes.contains(i)) {
+ nonUsedIndexes.add(i);
+ }
+ }
+
+ for(String missingPlayer : actualPlayers) {
+ if(!playerList.contains(missingPlayer)) {
+ if(nonUsedIndexes.isEmpty()) break;
+ playerMarkerMapPositions.put(missingPlayer, positions.get(nonUsedIndexes.get(0)));
+ nonUsedIndexes.remove(0);
+ }
+ }
+ }
+ } else if(mapDecorations == null) {
+ playerMarkerMapPositions.clear();
+ playerMarkerMapPositionsLast.clear();
+
+ for (Map.Entry<String, MapPosition> entry : playerEntityMapPositions.entrySet()) {
+ playerMarkerMapPositions.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ if(!roomMap.isEmpty() && startRoomX >= 0 && startRoomY >= 0) {
+ render(centerX, centerY);
+ }
+
+ this.colourMap = colourMap;
+ }
+
+ @SubscribeEvent(priority=EventPriority.HIGH)
+ public void onRenderOverlayPre(RenderGameOverlayEvent.Pre event) {
+ if(event.type == RenderGameOverlayEvent.ElementType.ALL &&
+ NotEnoughUpdates.INSTANCE.manager.config.dmEnable.value &&
+ NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.value > 0.1) {
+ blurBackground();
+ GlStateManager.enableBlend();
+ GlStateManager.enableTexture2D();
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderOverlay(RenderGameOverlayEvent event) {
+ if(event.type == RenderGameOverlayEvent.ElementType.ALL) {
+ if(!NotEnoughUpdates.INSTANCE.manager.config.dmEnable.value) return;
+
+ if(SBInfo.getInstance().getLocation() == null || !SBInfo.getInstance().getLocation().equals("dungeon")) {
+ return;
+ }
+ if(Minecraft.getMinecraft().gameSettings.showDebugInfo ||
+ (Minecraft.getMinecraft().gameSettings.keyBindPlayerList.isKeyDown() &&
+ (!Minecraft.getMinecraft().isIntegratedServerRunning() ||
+ Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap().size() > 1))) {
+ return;
+ }
+
+ ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.mainInventory[8];
+ boolean holdingBow = stack != null && stack.getItem() == Items.arrow;
+ if(holdingBow || (stack != null && stack.getItem() instanceof ItemMap)) {
+ Map<String, Vec4b> decorations = null;
+
+ Color[][] colourMap = new Color[128][128];
+ if(holdingBow) {
+ for(int x=0; x<128; x++) {
+ for(int y=0; y<128; y++) {
+ if(this.colourMap != null && this.colourMap[x][y] != null) {
+ colourMap[x][y] = this.colourMap[x][y];
+ } else {
+ colourMap[x][y] = new Color(0, true);
+ }
+ }
+ }
+ } else {
+ ItemMap map = (ItemMap) stack.getItem();
+ MapData mapData = map.getMapData(stack, Minecraft.getMinecraft().theWorld);
+
+ if(mapData == null) return;
+
+ decorations = mapData.mapDecorations;
+
+ for (int i = 0; i < 16384; ++i) {
+ int x = i % 128;
+ int y = i / 128;
+
+ int j = mapData.colors[i] & 255;
+
+ Color c;
+ if (j / 4 == 0) {
+ c = new Color((i + i / 128 & 1) * 8 + 16 << 24, true);
+ } else {
+ c = new Color(MapColor.mapColorArray[j / 4].func_151643_b(j & 3), true);
+ }
+
+ colourMap[x][y] = c;
+ }
+ }
+
+ int roomSizeBlocks = 31;
+ /*List<Integer> dists = new ArrayList<>();
+ int currentBlockCount = 0;
+ for(int i=0; i<300; i++) {
+ IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(0, 99, i));
+ if(state == null || state.getBlock() == Blocks.air) {
+ if(currentBlockCount > 0) dists.add(currentBlockCount);
+ currentBlockCount = 0;
+ } else {
+ currentBlockCount++;
+ }
+ }
+ currentBlockCount = 0;
+ for(int i=0; i<300; i++) {
+ IBlockState state = Minecraft.getMinecraft().theWorld.getBlockState(new BlockPos(i, 99, 0));
+ if(state == null || state.getBlock() == Blocks.air) {
+ if(currentBlockCount > 0) dists.add(currentBlockCount);
+ currentBlockCount = 0;
+ } else {
+ currentBlockCount++;
+ }
+ }
+ int count = 0;
+ int mostCommonDist = -1;
+ for(int dist : dists) {
+ if(dist == mostCommonDist) {
+ count++;
+ } else {
+ if(--count < 0) {
+ count = 1;
+ mostCommonDist = dist;
+ }
+ }
+ }
+ if(mostCommonDist > 31) roomSizeBlocks = mostCommonDist;*/
+
+ Set<String> actualPlayers = new HashSet<>();
+ for(ScorePlayerTeam team : Minecraft.getMinecraft().thePlayer.getWorldScoreboard().getTeams()) {
+ if(team.getTeamName().startsWith("a")) {
+ actualPlayers.addAll(team.getMembershipCollection());
+ }
+ }
+
+ renderMap((int)(NotEnoughUpdates.INSTANCE.manager.config.dmCenterX.value/100*Minecraft.getMinecraft().displayWidth/2),
+ (int)(NotEnoughUpdates.INSTANCE.manager.config.dmCenterY.value/100*Minecraft.getMinecraft().displayHeight/2),
+ colourMap, decorations, roomSizeBlocks, actualPlayers, true);
+ }
+ }
+ }
+
+ public List<List<String>> permutations(List<String> values) {
+ List<List<String>> permutations = new ArrayList<>();
+
+ if(values.size() == 1) {
+ permutations.add(values);
+ return permutations;
+ }
+
+ for(String first : values) {
+ List<String> newList = new ArrayList<>();
+ for(String val : values) {
+ if(!val.equals(first)) {
+ newList.add(val);
+ }
+ }
+
+ for(List<String> list2 : permutations(newList)) {
+ List<String> perm = new ArrayList<>();
+ perm.add(first);
+ perm.addAll(list2);
+ permutations.add(perm);
+ }
+ }
+
+ return permutations;
+ }
+
+ 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;
+ }
+
+ private double lastBgBlurFactor = -1;
+ private void blurBackground() {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ if(blurOutputHorz == null) {
+ blurOutputHorz = new Framebuffer(width, height, false);
+ blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputVert == null) {
+ blurOutputVert = new Framebuffer(width, height, false);
+ blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
+ blurOutputHorz.createBindFramebuffer(width, height);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ if(blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
+ blurOutputVert.createBindFramebuffer(width, height);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+
+ if(blurShaderHorz == null) {
+ try {
+ blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz);
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch(Exception 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) {
+ float blur = NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.value.floatValue();
+ blur = Math.max(0, Math.min(50, blur));
+ if(blur != lastBgBlurFactor) {
+ blurShaderHorz.getShaderManager().getShaderUniform("Radius").set(blur);
+ blurShaderVert.getShaderManager().getShaderUniform("Radius").set(blur);
+ lastBgBlurFactor = blur;
+ }
+ GL11.glPushMatrix();
+ blurShaderHorz.loadShader(0);
+ blurShaderVert.loadShader(0);
+ GlStateManager.enableDepth();
+ GL11.glPopMatrix();
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ }
+
+ /**
+ * Renders a subsection of the blurred framebuffer on to the corresponding section of the screen.
+ * Essentially, this method will "blur" the background inside the bounds specified by [x->x+blurWidth, y->y+blurHeight]
+ */
+ public void renderBlurredBackground(int width, int height, int x, int y, int blurWidth, int blurHeight) {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ if(blurOutputVert == null) return;
+
+ float uMin = x/(float)width;
+ float uMax = (x+blurWidth)/(float)width;
+ float vMin = (height-y)/(float)height;
+ float vMax = (height-y-blurHeight)/(float)height;
+
+ blurOutputVert.bindFramebufferTexture();
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ Utils.drawTexturedRectNoBlend(x, y, blurWidth, blurHeight, uMin, uMax, vMin, vMax, GL11.GL_LINEAR);
+ blurOutputVert.unbindFramebufferTexture();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java
new file mode 100644
index 00000000..f6538346
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java
@@ -0,0 +1,406 @@
+package io.github.moulberry.notenoughupdates.dungeons;
+
+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.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+
+import java.awt.*;
+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.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class DungeonWin {
+
+ private static class Confetti {
+ private float x;
+ private float y;
+ private float xLast;
+ private float yLast;
+ private int life = 0;
+ private float xVel;
+ private float yVel;
+ private int id;
+
+ public Confetti(float x, float y, float xVel, float yVel) {
+ this.x = x;
+ this.xLast = x;
+ this.y = y;
+ this.yLast = y;
+ this.xVel = xVel;
+ this.yVel = yVel;
+ this.id = rand.nextInt(16);
+ this.life = 20+rand.nextInt(10);
+ }
+ }
+ public static ResourceLocation CONFETTI = new ResourceLocation("notenoughupdates:dungeon_win/confetti.png");
+ public static ResourceLocation SPLUS = new ResourceLocation("notenoughupdates:dungeon_win/splus.png");
+ public static ResourceLocation S = new ResourceLocation("notenoughupdates:dungeon_win/s.png");
+ public static ResourceLocation A = new ResourceLocation("notenoughupdates:dungeon_win/a.png");
+ public static ResourceLocation B = new ResourceLocation("notenoughupdates:dungeon_win/b.png");
+ public static ResourceLocation C = new ResourceLocation("notenoughupdates:dungeon_win/c.png");
+ public static ResourceLocation D = new ResourceLocation("notenoughupdates:dungeon_win/d.png");
+ public static ResourceLocation TEAM_SCORE = SPLUS;
+
+ private static final int SCALE_FACTOR = 3;
+ private static final int WIDTH = 32*SCALE_FACTOR;
+ private static final int HEIGHT = 16*SCALE_FACTOR;
+
+ private static boolean hideChat = false;
+ private static long lastDungeonFinish = 0;
+ private static final Pattern TEAM_SCORE_REGEX = Pattern.compile("Team Score: [0-9]+ \\((S\\+|S|A|B|C|D)\\)");
+
+ private static final ScheduledExecutorService SES = Executors.newScheduledThreadPool(1);
+
+ public static Random rand = new Random();
+ public static List<Confetti> confetti = new ArrayList<>();
+ public static List<String> text = new ArrayList<>();
+ public static long startTime = 0;
+
+ static {
+ for(int i=0; i<10; i++) {
+ text.add("{PLACEHOLDER DUNGEON STAT #"+i+"}");
+ }
+ }
+
+ public static void displayWin() {
+ if(NotEnoughUpdates.INSTANCE.manager.config.dungeonWinMillis.value < 100) return;
+ startTime = System.currentTimeMillis();
+ confetti.clear();
+ }
+
+ public static void tick() {
+ if(NotEnoughUpdates.INSTANCE.manager.config.dungeonWinMillis.value < 100) return;
+ if(System.currentTimeMillis() - startTime > 5000) return;
+ int deltaTime = (int)(System.currentTimeMillis() - startTime);
+
+ if(deltaTime < 1000) {
+ ScaledResolution sr = Utils.pushGuiScale(2);
+ int cap = 0;
+ switch(TEAM_SCORE.getResourcePath()) {
+ case "dungeon_win/splus.png":
+ cap = 200; break;
+ case "dungeon_win/s.png":
+ cap = 100; break;
+ case "dungeon_win/a.png":
+ cap = 50; break;
+ }
+ int maxConfetti = Math.min(cap, deltaTime/5);
+ while(confetti.size() < maxConfetti) {
+ int y;
+ if(deltaTime < 500) {
+ y = sr.getScaledHeight()/2-(int)(Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()/9);
+ } else {
+ y = sr.getScaledHeight()/6+(int)(Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18);
+ }
+ int xOffset = -WIDTH/2+rand.nextInt(WIDTH);
+ int x = sr.getScaledWidth()/2+xOffset;
+
+ int xVel = xOffset/2;
+ int yVel = -25-rand.nextInt(10)+Math.abs(xVel)/2;
+
+ confetti.add(new Confetti(x, y, xVel, yVel));
+ }
+ } else {
+ Set<Confetti> toRemove = new HashSet<>();
+ for(Confetti c : confetti) {
+ if(c.life <= 0) {
+ toRemove.add(c);
+ }
+ }
+ try {
+ confetti.removeAll(toRemove);
+ } catch(ConcurrentModificationException ignored) {}
+ }
+
+ Utils.pushGuiScale(-1);
+ for(Confetti c : confetti) {
+ c.yVel += 1;
+ c.xVel /= 1.1f;
+ c.yVel /= 1.1f;
+ c.xLast = c.x;
+ c.yLast = c.y;
+ c.x += c.xVel;
+ c.y += c.yVel;
+ c.life--;
+ }
+ }
+
+ public static void onChatMessage(ClientChatReceivedEvent e) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.dungeonWinMillis.value < 100) return;
+ long currentTime = System.currentTimeMillis();
+ String unformatted = Utils.cleanColour(e.message.getUnformattedText());
+ if(e.message.getFormattedText().startsWith(EnumChatFormatting.RESET+" ")) {
+ if(currentTime - lastDungeonFinish > 10000) {
+ Matcher matcher = TEAM_SCORE_REGEX.matcher(unformatted);
+ if(matcher.find()) {
+ lastDungeonFinish = currentTime;
+
+ String score = matcher.group(1);
+ System.out.println(score);
+ switch (score.toUpperCase()) {
+ case "S+":
+ TEAM_SCORE = SPLUS; break;
+ case "S":
+ TEAM_SCORE = S; break;
+ case "A":
+ TEAM_SCORE = A; break;
+ case "B":
+ TEAM_SCORE = B; break;
+ case "C":
+ TEAM_SCORE = C; break;
+ default:
+ TEAM_SCORE = D; break;
+ }
+
+ SES.schedule(()->{
+ NotEnoughUpdates.INSTANCE.sendChatMessage("/showextrastats");
+ }, 100L, TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ if(currentTime - lastDungeonFinish > 100 && currentTime - lastDungeonFinish < 10000) {
+ if(hideChat) {
+ e.setCanceled(true);
+ if(unformatted.contains("\u25AC")) {
+ hideChat = false;
+ lastDungeonFinish = 0;
+ displayWin();
+ } else {
+ if(unformatted.trim().length() > 0) {
+ text.add(e.message.getFormattedText().substring(2).trim());
+ }
+ }
+ } else {
+ if(unformatted.contains("\u25AC")) {
+ hideChat = true;
+ text.clear();
+ e.setCanceled(true);
+ }
+ }
+
+ }
+ }
+
+ public static void render(float partialTicks) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.dungeonWinMillis.value < 100) return;
+ int maxTime = Math.min(30000, NotEnoughUpdates.INSTANCE.manager.config.dungeonWinMillis.value.intValue());
+ if(System.currentTimeMillis() - startTime > maxTime) return;
+ int deltaTime = (int)(System.currentTimeMillis() - startTime);
+
+ float alpha = Math.max(0, Math.min(1, 1-(deltaTime-maxTime+150)/150f));
+
+ ScaledResolution sr = Utils.pushGuiScale(2);
+
+ if(deltaTime > 600) {
+ float bottom;
+ if(deltaTime < 1000) {
+ bottom = sr.getScaledHeight()/6f+(float)Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18+HEIGHT/2;
+ } else {
+ bottom = sr.getScaledHeight()/6f+HEIGHT/2;
+ }
+ for(int i=0; i<text.size(); i++) {
+ String line = text.get(i);
+ float textCenterY = sr.getScaledHeight()/6f+HEIGHT/2+7+i*10;
+ if(textCenterY > bottom) {
+ int textAlpha = (int)(alpha * (deltaTime > 1000 ? 255 : Math.min(255, (textCenterY-bottom)/30f*255)));
+ GlStateManager.enableBlend();
+
+ if(textAlpha > 150) {
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ Utils.drawStringCentered(Utils.cleanColourNotModifiers(line), Minecraft.getMinecraft().fontRendererObj,
+ sr.getScaledWidth()/2+xOff/2f, textCenterY+yOff/2f, false,
+ ((textAlpha/Math.max(Math.abs(xOff), Math.abs(yOff))) << 24));
+ }
+ }
+ }
+ }
+
+ Utils.drawStringCentered(line, Minecraft.getMinecraft().fontRendererObj,
+ sr.getScaledWidth()/2, textCenterY, false, (textAlpha << 24) | 0x00FFFFFF);
+ }
+ }
+ }
+
+ for(Confetti c : confetti) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI);
+ GlStateManager.color(1, 1, 1, 1);
+ if(c.life >= 15) {
+ GlStateManager.color(1, 1, 1, Math.min(1, c.life/4f));
+ Utils.drawTexturedRect(c.xLast+(c.x-c.xLast)*partialTicks-4, c.yLast+(c.y-c.yLast)*partialTicks-4,
+ 8, 8, (c.id%4)/4f, (c.id%4+1)/4f, (c.id/4)/4f, (c.id/4+1)/4f, GL11.GL_NEAREST);
+ }
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(TEAM_SCORE);
+ GlStateManager.color(1, 1, 1, alpha);
+
+ GlStateManager.pushMatrix();
+ if(deltaTime < 1600) {
+ GlStateManager.translate(sr.getScaledWidth()/2, 0, 0);
+ if(deltaTime < 500) {
+ GlStateManager.translate(0, sr.getScaledHeight()/2f-Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()/9, 0);
+ } else if(deltaTime < 1000) {
+ GlStateManager.translate(0, sr.getScaledHeight()/6f+Math.sin(deltaTime/1000f*Math.PI)*sr.getScaledHeight()*4/18, 0);
+ } else {
+ GlStateManager.translate(0, sr.getScaledHeight()/6f, 0);
+ }
+ if(deltaTime < 200) {
+ float scale = deltaTime/200f;
+ GlStateManager.scale(scale, scale, 1);
+ } else if(deltaTime < 1000) {
+ float scale = 1+(float)Math.sin((deltaTime-200)/800f*Math.PI)*0.8f;
+ GlStateManager.scale(scale, scale, 1);
+ } else if(deltaTime < 1100) {
+ float scale = 1+(float)Math.sin((deltaTime-1000)/100f*Math.PI)*0.15f;
+ GlStateManager.scale(scale, scale, 1);
+ }
+
+ if(deltaTime < 600) {
+ GlStateManager.rotate(180+deltaTime/600f*180, 0, 1, 0);
+ GlStateManager.rotate(180-deltaTime/600f*180, 1, 0, 0);
+ GlStateManager.rotate(-180-deltaTime/600f*165, 0, 0, 1);
+ } else if(deltaTime < 1000) {
+ GlStateManager.rotate(15-(deltaTime-600)/400f*11, 0, 0, 1);
+ } else {
+ float logFac = 1-(float)Math.log((deltaTime-1000)/600f*1.7f+1);
+ logFac = logFac*logFac;
+
+ GlStateManager.rotate(4f*logFac, 0, 0, 1);
+ float x = (deltaTime-1000)/300f;
+ GlStateManager.rotate((float)(40*(1-Math.log(x*0.85f+1))*Math.sin(10*x*x)), 0, 1, 0);
+ }
+ } else {
+ GlStateManager.translate(sr.getScaledWidth()/2, sr.getScaledHeight()/6f, 0);
+ }
+
+ GlStateManager.disableCull();
+
+ Utils.drawTexturedRect(-WIDTH/2, -HEIGHT/2, WIDTH, HEIGHT, GL11.GL_NEAREST);
+ GlStateManager.translate(0, 0, -SCALE_FACTOR*2);
+ Utils.drawTexturedRect(-WIDTH/2, -HEIGHT/2, WIDTH, HEIGHT, GL11.GL_NEAREST);
+ GlStateManager.translate(0, 0, SCALE_FACTOR*2);
+
+ if(deltaTime < 1600) {
+ float epsilon = 0.01f;
+ for(int xIndex=0; xIndex<32; xIndex++) {
+ for(int yIndex=0; yIndex<16; yIndex++) {
+ float uMin = xIndex/32f;
+ float uMax = (xIndex+1)/32f;
+ float vMin = yIndex/16f;
+ float vMax = (yIndex+1)/16f;
+
+ int x = -WIDTH/2+xIndex*SCALE_FACTOR;
+ int y = -HEIGHT/2+yIndex*SCALE_FACTOR;
+
+ GlStateManager.enableTexture2D();
+ GlStateManager.enableBlend();
+ GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ //Left
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer
+ .pos(x+epsilon, y+SCALE_FACTOR, 0.0D+epsilon)
+ .tex(uMin, vMax).endVertex();
+ worldrenderer
+ .pos(x+epsilon, y, 0.0D+epsilon)
+ .tex(uMax, vMax).endVertex();
+ worldrenderer
+ .pos(x+epsilon, y, -SCALE_FACTOR*2-epsilon)
+ .tex(uMax, vMin).endVertex();
+ worldrenderer
+ .pos(x+epsilon, y+SCALE_FACTOR, -SCALE_FACTOR*2-epsilon)
+ .tex(uMin, vMin).endVertex();
+ tessellator.draw();
+ //Right
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer
+ .pos(x+SCALE_FACTOR-epsilon, y+SCALE_FACTOR, 0.0D+epsilon)
+ .tex(uMin, vMax).endVertex();
+ worldrenderer
+ .pos(x+SCALE_FACTOR-epsilon, y, 0.0D+epsilon)
+ .tex(uMax, vMax).endVertex();
+ worldrenderer
+ .pos(x+SCALE_FACTOR-epsilon, y, -SCALE_FACTOR*2-epsilon)
+ .tex(uMax, vMin).endVertex();
+ worldrenderer
+ .pos(x+SCALE_FACTOR-epsilon, y+SCALE_FACTOR, -SCALE_FACTOR*2-epsilon)
+ .tex(uMin, vMin).endVertex();
+ tessellator.draw();
+ //Top
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer
+ .pos(x+SCALE_FACTOR, y+epsilon, 0.0D+epsilon)
+ .tex(uMin, vMax).endVertex();
+ worldrenderer
+ .pos(x, y+epsilon, 0.0D+epsilon)
+ .tex(uMax, vMax).endVertex();
+ worldrenderer
+ .pos(x, y+epsilon, -SCALE_FACTOR*2-epsilon)
+ .tex(uMax, vMin).endVertex();
+ worldrenderer
+ .pos(x+SCALE_FACTOR, y+epsilon, -SCALE_FACTOR*2-epsilon)
+ .tex(uMin, vMin).endVertex();
+ tessellator.draw();
+ //Top
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer
+ .pos(x+SCALE_FACTOR, y+SCALE_FACTOR-epsilon, 0.0D+epsilon)
+ .tex(uMin, vMax).endVertex();
+ worldrenderer
+ .pos(x, y+SCALE_FACTOR-epsilon, 0.0D+epsilon)
+ .tex(uMax, vMax).endVertex();
+ worldrenderer
+ .pos(x, y+SCALE_FACTOR-epsilon, -SCALE_FACTOR*2-epsilon)
+ .tex(uMax, vMin).endVertex();
+ worldrenderer
+ .pos(x+SCALE_FACTOR, y+SCALE_FACTOR-epsilon, -SCALE_FACTOR*2-epsilon)
+ .tex(uMin, vMin).endVertex();
+ tessellator.draw();
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+
+ GlStateManager.disableBlend();
+ }
+ }
+ }
+
+ GlStateManager.popMatrix();
+
+ for(Confetti c : confetti) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(CONFETTI);
+ GlStateManager.color(1, 1, 1, 1);
+ if(c.life > 0 && c.life < 15) {
+ GlStateManager.color(1, 1, 1, Math.min(1, c.life/4f));
+ Utils.drawTexturedRect(c.xLast+(c.x-c.xLast)*partialTicks-4, c.yLast+(c.y-c.yLast)*partialTicks-4,
+ 8, 8, (c.id%4)/4f, (c.id%4+1)/4f, (c.id/4)/4f, (c.id/4+1)/4f, GL11.GL_NEAREST);
+ }
+ }
+
+ Utils.pushGuiScale(-1);
+
+ GlStateManager.enableBlend();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
new file mode 100644
index 00000000..5890b5c0
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
@@ -0,0 +1,845 @@
+package io.github.moulberry.notenoughupdates.dungeons;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
+import io.github.moulberry.notenoughupdates.options.Options;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.OpenGlHelper;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.Matrix4f;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.Vec4b;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.*;
+import java.util.List;
+
+import static io.github.moulberry.notenoughupdates.GuiTextures.*;
+import static io.github.moulberry.notenoughupdates.GuiTextures.colour_selector_dot;
+
+public class GuiDungeonMapEditor extends GuiScreen {
+
+ public static final ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates:dungeon_map/editor/background.png");
+ public static final ResourceLocation BUTTON = new ResourceLocation("notenoughupdates:button.png");
+ private static final DungeonMap demoMap = new DungeonMap();
+
+ private int sizeX;
+ private int sizeY;
+ private int guiLeft;
+ private int guiTop;
+
+ private List<Button> buttons = new ArrayList<>();
+
+ private static final int colourEditorBG = new Color(80, 80, 80, 220).getRGB();
+ private static ResourceLocation colourPickerLocation = new ResourceLocation("notenoughupdates:dynamic/colourpicker");
+ private static ResourceLocation colourPickerBarValueLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickervalue");
+ private static ResourceLocation colourPickerBarOpacityLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickeropacity");
+
+ private GuiElementTextField hexField = new GuiElementTextField("",
+ GuiElementTextField.SCALE_TEXT | GuiElementTextField.FORCE_CAPS | GuiElementTextField.NO_SPACE);
+
+ private GuiElementTextField xField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
+ private GuiElementTextField yField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
+ private GuiElementTextField blurField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
+ private ColourEditor activeColourEditor = null;
+
+ private class ColourEditor {
+ public int x;
+ public int y;
+ public Options.Option<String> option;
+ public String special;
+
+ public ColourEditor(int x, int y, Options.Option<String> option, String special) {
+ this.x = x;
+ this.y = y;
+ this.option = option;
+ this.special = special;
+ }
+ }
+
+ class Button {
+ private int id;
+ private int x;
+ private int y;
+ private String text;
+ private Color colour = new Color(-1, true);
+ private Options.Option<?> option;
+
+ public Button(int id, int x, int y, String text) {
+ this(id, x, y, text, null);
+ }
+
+ public Button(int id, int x, int y, String text, Options.Option<?> option) {
+ this.id = id;
+ this.x = x;
+ this.y = y;
+ this.text = text;
+ this.option = option;
+ }
+
+ public List<String> getTooltip() {
+ if(option == null) {
+ return null;
+ }
+
+ List<String> tooltip = new ArrayList<>();
+ tooltip.add(EnumChatFormatting.YELLOW+option.displayName);
+ for(String line : option.desc.split("\n")) {
+ tooltip.add(EnumChatFormatting.AQUA+line);
+ }
+ return tooltip;
+ }
+
+ public void render() {
+ if(text == null) return;
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BUTTON);
+ if(isButtonPressed(id)) {
+ GlStateManager.color(colour.getRed()*0.85f/255f, colour.getGreen()*0.85f/255f,
+ colour.getBlue()*0.85f/255f, 1);
+ Utils.drawTexturedRect(guiLeft+x, guiTop+y, 48, 16, 1, 0, 1, 0, GL11.GL_NEAREST);
+ } else {
+ GlStateManager.color(colour.getRed()/255f, colour.getGreen()/255f, colour.getBlue()/255f, 1);
+ Utils.drawTexturedRect(guiLeft+x, guiTop+y, 48, 16, GL11.GL_NEAREST);
+ }
+
+ if(text.length() > 0) {
+ Utils.drawStringCenteredScaledMaxWidth(text, Minecraft.getMinecraft().fontRendererObj , guiLeft+x+24, guiTop+y+8, false, 39, 0xFF000000);
+ }
+ }
+
+ }
+
+ public GuiDungeonMapEditor() {
+ Options options = NotEnoughUpdates.INSTANCE.manager.config;
+ //Map Border Size
+ buttons.add(new Button(0, 6, 37, "Small", options.dmBorderSize));
+ buttons.add(new Button(1, 52, 37, "Medium", options.dmBorderSize));
+ buttons.add(new Button(2, 98, 37, "Large", options.dmBorderSize));
+
+ //Map Rooms Size
+ buttons.add(new Button(3, 6, 67+19, "Small", options.dmRoomSize));
+ buttons.add(new Button(4, 52, 67+19, "Medium", options.dmRoomSize));
+ buttons.add(new Button(5, 98, 67+19, "Large", options.dmRoomSize));
+
+ //Map Border Styles
+ buttons.add(new Button(6, 6, 97+38, "None"));
+ buttons.add(new Button(7, 52, 97+38, "Custom"));
+ buttons.add(new Button(8, 98, 97+38, "Stone"));
+ buttons.add(new Button(9, 6, 116+38, "Wood"));
+ buttons.add(new Button(10, 52, 116+38, "Rustic(S)"));
+ buttons.add(new Button(11, 98, 116+38, "Rustic(C)"));
+ buttons.add(new Button(12, 6, 135+38, "Fade"));
+ buttons.add(new Button(13, 52, 135+38, "Ribbons"));
+ buttons.add(new Button(14, 98, 135+38, "Paper"));
+ buttons.add(new Button(15, 6, 154+38, "Crimson"));
+ buttons.add(new Button(16, 52, 154+38, "Ornate"));
+ buttons.add(new Button(17, 98, 154+38, "Dragon"));
+
+ //Dungeon Map
+ buttons.add(new Button(18, 20+139, 36, "Yes/No", options.dmEnable));
+ //Center
+ buttons.add(new Button(19, 84+139, 36, "Player/Map", options.dmCenterPlayer));
+ //Rotate
+ buttons.add(new Button(20, 20+139, 65, "Player/No Rotate", options.dmRotatePlayer));
+ //Icon Style
+ buttons.add(new Button(21, 84+139, 65, "Default/Heads", options.dmPlayerHeads));
+ //Check Orient
+ buttons.add(new Button(22, 20+139, 94, "Normal/Reorient", options.dmOrientCheck));
+ //Check Center
+ buttons.add(new Button(23, 84+139, 94, "Yes/No", options.dmCenterCheck));
+ //Interpolation
+ buttons.add(new Button(24, 20+139, 123, "Yes/No", options.dmPlayerInterp));
+ //Compatibility
+ buttons.add(new Button(25, 84+139, 123, "Normal/No SHD/No FB/SHD", options.dmCompat));
+
+ //Background
+ buttons.add(new Button(26, 20+139, 152, "", options.dmBackgroundColour));
+ //Border
+ buttons.add(new Button(27, 84+139, 152, "", options.dmBorderColour));
+
+ //Chroma Mode
+ buttons.add(new Button(28, 84+139, 181, "Normal/Scroll", options.dmChromaBorder));
+
+ buttons.add(new Button(29, 52, 86+19, "XLarge", options.dmRoomSize));
+ buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize));
+
+ xField.setText(String.valueOf(NotEnoughUpdates.INSTANCE.manager.config.dmCenterX.value));
+ yField.setText(String.valueOf(NotEnoughUpdates.INSTANCE.manager.config.dmCenterY.value));
+ blurField.setText(String.valueOf(NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.value));
+ }
+
+ private void showColourEditor(int mouseX, int mouseY, Options.Option<String> option, String special) {
+ activeColourEditor = new ColourEditor(mouseX, mouseY, option, special);
+ hexField.otherComponentClick();
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ ScaledResolution scaledResolution = Utils.pushGuiScale(2);
+ this.width = scaledResolution.getScaledWidth();
+ this.height = scaledResolution.getScaledHeight();
+
+ mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
+ mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
+
+ List<String> tooltipToDisplay = null;
+ for(Button button : buttons) {
+ if(mouseX >= guiLeft+button.x && mouseX <= guiLeft+button.x+48 &&
+ mouseY >= guiTop+button.y-13 && mouseY <= guiTop+button.y+16) {
+ if(button.id >= 6 && button.id <= 17) {
+ String mapDesc = null;
+ String mapCredit = null;
+ int id = button.id;
+ switch(id) {
+ case 6:
+ mapDesc = "No Border"; break;
+ case 7:
+ mapDesc = "Used by custom Resource Packs"; break;
+ case 8:
+ mapDesc = "Simple gray border"; mapCredit = "TomEngMaster"; break;
+ case 9:
+ mapDesc = "Viney wood border"; mapCredit = "iDevil4Hell"; break;
+ case 10:
+ mapDesc = "Steampunk-inspired square border"; mapCredit = "ThatGravyBoat"; break;
+ case 11:
+ mapDesc = "Steampunk-inspired circular border"; mapCredit = "ThatGravyBoat"; break;
+ case 12:
+ mapDesc = "Light fade border"; mapCredit = "Qwiken"; break;
+ case 13:
+ mapDesc = "Simple gray border with red ribbons"; mapCredit = "Sai"; break;
+ case 14:
+ mapDesc = "Paper border"; mapCredit = "KingJames02st"; break;
+ case 15:
+ mapDesc = "Nether-inspired border"; mapCredit = "DTRW191"; break;
+ case 16:
+ mapDesc = "Golden ornate border"; mapCredit = "iDevil4Hell"; break;
+ case 17:
+ mapDesc = "Stone dragon border"; mapCredit = "ImperiaL"; break;
+ }
+
+ ArrayList<String> tooltip = new ArrayList<>();
+ tooltip.add(EnumChatFormatting.YELLOW+"Border Style");
+ tooltip.add(EnumChatFormatting.AQUA+"Customize the look of the dungeon border");
+ tooltip.add("");
+ if(mapDesc != null) tooltip.add(EnumChatFormatting.YELLOW+"Set to: "+EnumChatFormatting.AQUA+mapDesc);
+ if(mapCredit != null) tooltip.add(EnumChatFormatting.YELLOW+"Artist: "+EnumChatFormatting.GOLD+mapCredit);
+ tooltipToDisplay = tooltip;
+ } else {
+ tooltipToDisplay = button.getTooltip();
+ }
+ break;
+ }
+ }
+
+ this.sizeX = 431;
+ this.sizeY = 237;
+ this.guiLeft = (this.width - this.sizeX) / 2;
+ this.guiTop = (this.height-this.sizeY)/2;
+
+ super.drawScreen(mouseX, mouseY, partialTicks);
+ drawDefaultBackground();
+
+ blurBackground();
+ renderBlurredBackground(width, height, guiLeft+2, guiTop+2, sizeX-4, sizeY-4);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().fontRendererObj.drawString("NEU Dungeon Map Editor", guiLeft+8, guiTop+6, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Map Border Size", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+76, guiTop+30, false, 137, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Map Rooms Size", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+76, guiTop+60+19, false, 137, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Map Border Style", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+76, guiTop+90+38, false, 137, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Dungeon Map", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+30, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Center", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+30, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Rotate", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+59, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Icon Style", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+59, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Check Orient", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+88, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Check Center", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+88, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Interpolation", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+117, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Compatibility", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+117, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("Background", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+146, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Border", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+146, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("BG Blur", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+175, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+175, false, 60, 0xFFB4B4B4);
+
+ Utils.drawStringCenteredScaledMaxWidth("X (%)", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+44+139, guiTop+204, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Y (%)", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+108+139, guiTop+204, false, 60, 0xFFB4B4B4);
+
+ Options options = NotEnoughUpdates.INSTANCE.manager.config;
+ buttons.get(18).text = options.dmEnable.value ? "Enabled" : "Disabled";
+ buttons.get(19).text = options.dmCenterPlayer.value ? "Player" : "Map";
+ buttons.get(20).text = options.dmRotatePlayer.value ? "Player" : "Vertical";
+ buttons.get(21).text = options.dmPlayerHeads.value <= 0 ? "Default" : options.dmPlayerHeads.value >= 3 ? "SmallHeads" :
+ options.dmPlayerHeads.value == 1 ? "Heads" : "ScaledHeads";
+ buttons.get(22).text = options.dmOrientCheck.value ? "Orient" : "Off";
+ buttons.get(23).text = options.dmCenterCheck.value ? "Center" : "Off";
+ buttons.get(24).text = options.dmPlayerInterp.value ? "Interp" : "No Interp";
+ buttons.get(25).text = options.dmCompat.value <= 0 ? "Normal" : options.dmCompat.value >= 2 ? "No FB/SHD" : "No SHD";
+
+ buttons.get(26).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBackgroundColour.value));
+ buttons.get(27).colour = new Color(SpecialColour.specialToChromaRGB(options.dmBorderColour.value));
+
+ buttons.get(28).text = options.dmChromaBorder.value ? "Scroll" : "Normal";
+
+ blurField.setSize(48, 16);
+ xField.setSize(48, 16);
+ yField.setSize(48, 16);
+ blurField.render(guiLeft+20+139, guiTop+181);
+ xField.render(guiLeft+20+139, guiTop+210);
+ yField.render(guiLeft+84+139, guiTop+210);
+
+ Map<String, Vec4b> decorations = new HashMap<>();
+ Vec4b vec4b = new Vec4b((byte)3, (byte)(((50)-64)*2), (byte)(((40)-64)*2), (byte)((60)*16/360));
+ decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
+
+ HashSet<String> players = new HashSet<>();
+ players.add(Minecraft.getMinecraft().thePlayer.getName());
+ GlStateManager.color(1, 1, 1, 1);
+
+ demoMap.renderMap(guiLeft+357, guiTop+125, NotEnoughUpdates.INSTANCE.colourMap, decorations, 0,
+ players, false);
+
+ for(Button button : buttons) {
+ button.render();
+ }
+
+ //List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font
+ if(tooltipToDisplay != null) {
+ Utils.drawHoveringText(tooltipToDisplay, mouseX, mouseY, width, height, 200, Minecraft.getMinecraft().fontRendererObj);
+ }
+
+ if(activeColourEditor != null) {
+ Gui.drawRect(activeColourEditor.x, activeColourEditor.y, activeColourEditor.x+119, activeColourEditor.y+89, colourEditorBG);
+
+ int currentColour = SpecialColour.specialToSimpleRGB(activeColourEditor.special);
+ Color c = new Color(currentColour, true);
+ float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
+
+ BufferedImage bufferedImage = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<256; x++) {
+ for(int y=0; y<256; y++) {
+ float radius = (float) Math.sqrt(((x-128)*(x-128)+(y-128)*(y-128))/16384f);
+ float angle = (float) Math.toDegrees(Math.atan((128-x)/(y-128+1E-5))+Math.PI/2);
+ if(y < 128) angle += 180;
+ if(radius <= 1) {
+ int rgb = Color.getHSBColor(angle/360f, (float)Math.pow(radius, 1.5f), hsv[2]).getRGB();
+ bufferedImage.setRGB(x, y, rgb);
+ }
+ }
+ }
+
+ BufferedImage bufferedImageValue = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<10; x++) {
+ for(int y=0; y<64; y++) {
+ if((x == 0 || x == 9) && (y == 0 || y == 63)) continue;
+
+ int rgb = Color.getHSBColor(hsv[0], hsv[1], (64-y)/64f).getRGB();
+ bufferedImageValue.setRGB(x, y, rgb);
+ }
+ }
+
+ BufferedImage bufferedImageOpacity = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<10; x++) {
+ for(int y=0; y<64; y++) {
+ if((x == 0 || x == 9) && (y == 0 || y == 63)) continue;
+
+ int rgb = (currentColour & 0x00FFFFFF) | (Math.min(255, (64-y)*4) << 24);
+ bufferedImageOpacity.setRGB(x, y, rgb);
+ }
+ }
+
+ float selradius = (float) Math.pow(hsv[1], 1/1.5f)*32;
+ int selx = (int)(Math.cos(Math.toRadians(hsv[0]*360))*selradius);
+ int sely = (int)(Math.sin(Math.toRadians(hsv[0]*360))*selradius);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar_alpha);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarValueLocation, new DynamicTexture(bufferedImageValue));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarValueLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarOpacityLocation, new DynamicTexture(bufferedImageOpacity));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarOpacityLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ int chromaSpeed = SpecialColour.getSpeed(activeColourEditor.special);
+ int currentColourChroma = SpecialColour.specialToChromaRGB(activeColourEditor.special);
+ Color cChroma = new Color(currentColourChroma, true);
+ float hsvChroma[] = Color.RGBtoHSB(cChroma.getRed(), cChroma.getGreen(), cChroma.getBlue(), null);
+
+ if(chromaSpeed > 0) {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5+1, activeColourEditor.y+5+1,
+ activeColourEditor.x+5+64+5+10+5+10+5+10-1, activeColourEditor.y+5+64-1,
+ Color.HSBtoRGB(hsvChroma[0], 0.8f, 0.8f));
+ } else {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5+1, activeColourEditor.y+5+27+1,
+ activeColourEditor.x+5+64+5+10+5+10+5+10-1, activeColourEditor.y+5+37-1,
+ Color.HSBtoRGB((hsvChroma[0]+(System.currentTimeMillis()-SpecialColour.startTime)/1000f)%1, 0.8f, 0.8f));
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ if(chromaSpeed > 0) {
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_chroma);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5+10+5, activeColourEditor.y+5+27, 10, 10, GL11.GL_NEAREST);
+ }
+
+ Gui.drawRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5+64-(int)(64*hsv[2]),
+ activeColourEditor.x+5+64+5+10, activeColourEditor.y+5+64-(int)(64*hsv[2])+1, 0xFF000000);
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5+64-c.getAlpha()/4,
+ activeColourEditor.x+5+64+5+10+5+10, activeColourEditor.y+5+64-c.getAlpha()/4-1, 0xFF000000);
+ if(chromaSpeed > 0) {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5,
+ activeColourEditor.y+5+64-(int)(chromaSpeed/255f*64),
+ activeColourEditor.x+5+64+5+10+5+10+5+10,
+ activeColourEditor.y+5+64-(int)(chromaSpeed/255f*64)+1, 0xFF000000);
+ }
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerLocation, new DynamicTexture(bufferedImage));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5, activeColourEditor.y+5, 64, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_dot);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+32+selx-4, activeColourEditor.y+5+32+sely-4, 8, 8, GL11.GL_NEAREST);
+
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(hsv[2]*100)+"",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+5-(Math.round(hsv[2]*100)==100?1:0), activeColourEditor.y+5+64+5+5, true, 13, -1);
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(c.getAlpha()/255f*100)+"",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+15+5, activeColourEditor.y+5+64+5+5, true, 13, -1);
+ if(chromaSpeed > 0) {
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+(int)SpecialColour.getSecondsForSpeed(chromaSpeed)+"s",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+30+6, activeColourEditor.y+5+64+5+5, true, 13, -1);
+ }
+
+ hexField.setSize(48, 10);
+ if(!hexField.getFocus()) hexField.setText(Integer.toHexString(c.getRGB() & 0xFFFFFF).toUpperCase());
+
+ StringBuilder sb = new StringBuilder(EnumChatFormatting.GRAY+"#");
+ for(int i=0; i<6-hexField.getText().length(); i++) {
+ sb.append("0");
+ }
+ sb.append(EnumChatFormatting.WHITE);
+
+ hexField.setPrependText(sb.toString());
+ hexField.render(activeColourEditor.x+5+8, activeColourEditor.y+5+64+5);
+ }
+
+ Utils.pushGuiScale(-1);
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) {
+ for(Button button : buttons) {
+ if(mouseX >= guiLeft+button.x && mouseX <= guiLeft+button.x+48 &&
+ mouseY >= guiTop+button.y && mouseY <= guiTop+button.y+16) {
+ buttonClicked(mouseX, mouseY, button.id);
+
+ xField.otherComponentClick();
+ yField.otherComponentClick();
+ blurField.otherComponentClick();
+ return;
+ }
+ }
+
+
+ if(mouseY > guiTop+181 && mouseY < guiTop+181+16) {
+ if(mouseX > guiLeft+20+139 && mouseX < guiLeft+20+139+48) {
+ blurField.mouseClicked(mouseX, mouseY, mouseButton);
+ xField.otherComponentClick();
+ yField.otherComponentClick();
+ return;
+ }
+ } else if(mouseY > guiTop+210 && mouseY < guiTop+210+16) {
+ if(mouseX > guiLeft+20+139 && mouseX < guiLeft+20+139+48) {
+ xField.mouseClicked(mouseX, mouseY, mouseButton);
+ yField.otherComponentClick();
+ blurField.otherComponentClick();
+ return;
+ } else if(mouseX > guiLeft+84+139 && mouseX < guiLeft+84+139+48) {
+ yField.mouseClicked(mouseX, mouseY, mouseButton);
+ xField.otherComponentClick();
+ blurField.otherComponentClick();
+ return;
+ }
+ }
+
+ blurField.otherComponentClick();
+ xField.otherComponentClick();
+ yField.otherComponentClick();
+ }
+
+ @Override
+ public void handleMouseInput() throws IOException {
+ super.handleMouseInput();
+
+ int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
+ int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
+ if(activeColourEditor != null && (Mouse.isButtonDown(0) || Mouse.isButtonDown(1))) {
+ if(mouseX >= activeColourEditor.x && mouseX <= activeColourEditor.x+119) {
+ if(mouseY >= activeColourEditor.y && mouseY <= activeColourEditor.y+89) {
+ if(Mouse.getEventButtonState()) {
+ if(mouseX > activeColourEditor.x+5+8 && mouseX < activeColourEditor.x+5+8+48) {
+ if(mouseY > activeColourEditor.y+5+64+5 && mouseY < activeColourEditor.y+5+64+5+10) {
+ hexField.mouseClicked(mouseX, mouseY, Mouse.getEventButton());
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+ }
+ hexField.otherComponentClick();
+
+ int currentColour = SpecialColour.specialToSimpleRGB(activeColourEditor.special);
+ Color c = new Color(currentColour, true);
+ float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
+
+ int xWheel = mouseX - activeColourEditor.x - 5;
+ int yWheel = mouseY - activeColourEditor.y - 5;
+
+ if(xWheel > 0 && xWheel < 64) {
+ if(yWheel > 0 && yWheel < 64) {
+ float radius = (float) Math.sqrt(((xWheel-32)*(xWheel-32)+(yWheel-32)*(yWheel-32))/1024f);
+ float angle = (float) Math.toDegrees(Math.atan((32-xWheel)/(yWheel-32+1E-5))+Math.PI/2);
+ if(yWheel < 32) angle += 180;
+
+ int rgb = Color.getHSBColor(angle/360f, (float)Math.pow(Math.min(1, radius), 1.5f), hsv[2]).getRGB();
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), c.getAlpha(), rgb);
+ activeColourEditor.option.value = (String) activeColourEditor.special;
+ }
+ }
+
+ int xValue = mouseX - (activeColourEditor.x+5+64+5);
+ int y = mouseY - activeColourEditor.y - 5;
+
+ if(y > -5 && y <= 69) {
+ y = Math.max(0, Math.min(64, y));
+ if(xValue > 0 && xValue < 10) {
+ int rgb = Color.getHSBColor(hsv[0], hsv[1], 1-y/64f).getRGB();
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), c.getAlpha(), rgb);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+
+ int xOpacity = mouseX - (activeColourEditor.x+5+64+5+10+5);
+
+ if(xOpacity > 0 && xOpacity < 10) {
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special),
+ 255-(int)(y/64f*255), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ }
+
+ int chromaSpeed = SpecialColour.getSpeed(activeColourEditor.special);
+
+ int xChroma = mouseX - (activeColourEditor.x+5+64+5+10+5+10+5);
+ if(xChroma > 0 && xChroma < 10) {
+ if(chromaSpeed > 0) {
+ if(y > -5 && y <= 69) {
+ y = Math.max(0, Math.min(64, y));
+ activeColourEditor.special = SpecialColour.special(255-Math.round(y/64f*255), c.getAlpha(), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ } else if(mouseY > activeColourEditor.y+5+27 && mouseY < activeColourEditor.y+5+37) {
+ activeColourEditor.special = SpecialColour.special(200, c.getAlpha(), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ }
+
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
+ return;
+ }
+ }
+ if(Mouse.getEventButtonState()) {
+ activeColourEditor = null;
+ hexField.otherComponentClick();
+ }
+ }
+ }
+
+ @Override
+ public void handleKeyboardInput() throws IOException {
+ super.handleKeyboardInput();
+
+ if(activeColourEditor != null && hexField.getFocus()) {
+ String old = hexField.getText();
+
+ hexField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+
+ if(hexField.getText().length() > 6) {
+ hexField.setText(old);
+ } else {
+ try {
+ String text = hexField.getText().toLowerCase();
+
+ int rgb = Integer.parseInt(text, 16);
+ int alpha = (SpecialColour.specialToSimpleRGB(activeColourEditor.special) >> 24) & 0xFF;
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), alpha, rgb);
+ activeColourEditor.option.value = activeColourEditor.special;
+ } catch(Exception e) {};
+ }
+ }
+ }
+
+ @Override
+ protected void keyTyped(char typedChar, int keyCode) throws IOException {
+ super.keyTyped(typedChar, keyCode);
+
+ if(xField.getFocus()) {
+ xField.keyTyped(typedChar, keyCode);
+
+ try {
+ xField.setCustomBorderColour(-1);
+ NotEnoughUpdates.INSTANCE.manager.config.dmCenterX.setValue(xField.getText());
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
+ } catch(Exception e) {
+ xField.setCustomBorderColour(Color.RED.getRGB());
+ }
+ } else if(yField.getFocus()) {
+ yField.keyTyped(typedChar, keyCode);
+
+ try {
+ yField.setCustomBorderColour(-1);
+ NotEnoughUpdates.INSTANCE.manager.config.dmCenterY.setValue(yField.getText());
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
+ } catch(Exception e) {
+ yField.setCustomBorderColour(Color.RED.getRGB());
+ }
+ } else if(blurField.getFocus()) {
+ blurField.keyTyped(typedChar, keyCode);
+
+ try {
+ blurField.setCustomBorderColour(-1);
+ NotEnoughUpdates.INSTANCE.manager.config.dmBackgroundBlur.setValue(blurField.getText());
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {}
+ } catch(Exception e) {
+ blurField.setCustomBorderColour(Color.RED.getRGB());
+ }
+ }
+ }
+
+ private void buttonClicked(int mouseX, int mouseY, int id) {
+ Options options = NotEnoughUpdates.INSTANCE.manager.config;
+ switch (id) {
+ case 0:
+ options.dmBorderSize.value = 0.0; break;
+ case 1:
+ options.dmBorderSize.value = 1.0; break;
+ case 2:
+ options.dmBorderSize.value = 2.0; break;
+ case 30:
+ options.dmBorderSize.value = 3.0; break;
+ case 3:
+ options.dmRoomSize.value = 0.0; break;
+ case 4:
+ options.dmRoomSize.value = 1.0; break;
+ case 5:
+ options.dmRoomSize.value = 2.0; break;
+ case 29:
+ options.dmRoomSize.value = 3.0; break;
+ case 18:
+ options.dmEnable.value = !options.dmEnable.value; break;
+ case 19:
+ options.dmCenterPlayer.value = !options.dmCenterPlayer.value; break;
+ case 20:
+ options.dmRotatePlayer.value = !options.dmRotatePlayer.value; break;
+ case 21:
+ options.dmPlayerHeads.value++;
+ if(options.dmPlayerHeads.value > 3) options.dmPlayerHeads.value = 0.0;break;
+ case 22:
+ options.dmOrientCheck.value = !options.dmOrientCheck.value; break;
+ case 23:
+ options.dmCenterCheck.value = !options.dmCenterCheck.value; break;
+ case 24:
+ options.dmPlayerInterp.value = !options.dmPlayerInterp.value; break;
+ case 25:
+ options.dmCompat.value++;
+ if(options.dmCompat.value > 2) options.dmCompat.value = 0.0;
+ break;
+ case 26:
+ showColourEditor(mouseX, mouseY, options.dmBackgroundColour, options.dmBackgroundColour.value); break;
+ case 27:
+ showColourEditor(mouseX, mouseY, options.dmBorderColour, options.dmBorderColour.value); break;
+ case 28:
+ options.dmChromaBorder.value = !options.dmChromaBorder.value; break;
+ default:
+ if(id >= 6 && id <= 17) {
+ options.dmBorderStyle.value = (double)id-6; break;
+ }
+ }
+ try { NotEnoughUpdates.INSTANCE.manager.saveConfig(); } catch(IOException ignored) {};
+
+ }
+
+ private boolean isButtonPressed(int id) {
+ Options options = NotEnoughUpdates.INSTANCE.manager.config;
+
+ if(id >= 0 && id <= 2) {
+ return options.dmBorderSize.value == id;
+ } else if(id >= 3 && id <= 5) {
+ return options.dmRoomSize.value == id-3;
+ } else if(id >= 6 && id <= 17) {
+ return options.dmBorderStyle.value == id-6;
+ } else if(id == 29) {
+ return options.dmRoomSize.value == 3;
+ } else if(id == 30) {
+ return options.dmBorderSize.value == 3;
+ }
+ return false;
+ }
+
+ Shader blurShaderHorz = null;
+ Framebuffer blurOutputHorz = null;
+ Shader blurShaderVert = null;
+ Framebuffer blurOutputVert = null;
+
+ /**
+ * Creates a projection matrix that projects from our coordinate space [0->width; 0->height] to OpenGL coordinate
+ * space [-1 -> 1; 1 -> -1] (Note: flipped y-axis).
+ *
+ * This is so that we can render to and from the framebuffer in a way that is familiar to us, instead of needing to
+ * apply scales and translations manually.
+ */
+ private Matrix4f createProjectionMatrix(int width, int height) {
+ Matrix4f projMatrix = new Matrix4f();
+ projMatrix.setIdentity();
+ projMatrix.m00 = 2.0F / (float)width;
+ projMatrix.m11 = 2.0F / (float)(-height);
+ projMatrix.m22 = -0.0020001999F;
+ projMatrix.m33 = 1.0F;
+ projMatrix.m03 = -1.0F;
+ projMatrix.m13 = 1.0F;
+ projMatrix.m23 = -1.0001999F;
+ return projMatrix;
+ }
+
+ private double lastBgBlurFactor = -1;
+ private void blurBackground() {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ if(blurOutputHorz == null) {
+ blurOutputHorz = new Framebuffer(width, height, false);
+ blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputVert == null) {
+ blurOutputVert = new Framebuffer(width, height, false);
+ blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
+ blurOutputHorz.createBindFramebuffer(width, height);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ if(blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
+ blurOutputVert.createBindFramebuffer(width, height);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+
+ if(blurShaderHorz == null) {
+ try {
+ blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz);
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch(Exception 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) {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ float uMin = x/(float)width;
+ float uMax = (x+blurWidth)/(float)width;
+ float vMin = (height-y)/(float)height;
+ float vMax = (height-y-blurHeight)/(float)height;
+
+ blurOutputVert.bindFramebufferTexture();
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ //Utils.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/gamemodes/GuiGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java
new file mode 100644
index 00000000..0f479f53
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/GuiGamemodes.java
@@ -0,0 +1,303 @@
+package io.github.moulberry.notenoughupdates.gamemodes;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+
+import java.awt.*;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static io.github.moulberry.notenoughupdates.GuiTextures.*;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+
+public class GuiGamemodes extends GuiScreen {
+
+ private String currentProfile;
+ private SBGamemodes.Gamemode currentGamemode = null;
+ private boolean upgradeOverride;
+
+ private int guiLeft = 100;
+ private int guiTop = 100;
+ private int xSize = 200;
+ private int ySize = 232;
+
+ public GuiGamemodes(boolean upgradeOverride) {
+ this.currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
+ this.upgradeOverride = upgradeOverride;
+ }
+
+ private boolean canChange(int from, int to) {
+ if(from >= to) {
+ return true;
+ } else {
+ return !currentGamemode.locked || upgradeOverride;
+ }
+ }
+
+ @Override
+ public void updateScreen() {
+ if(currentGamemode == null) {
+ currentGamemode = SBGamemodes.getGamemode();
+ if(currentGamemode == null) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(
+ new ChatComponentText(EnumChatFormatting.RED+"Couldn't automatically detect current profile." +
+ "If you have only 1 profile, try using /api new so that NEU can detect your profile."));
+ }
+ }
+
+ String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
+ if(!this.currentProfile.equals(currentProfile)) {
+ Minecraft.getMinecraft().displayGuiScreen(null);
+ Minecraft.getMinecraft().thePlayer.addChatMessage(
+ new ChatComponentText(EnumChatFormatting.RED+"Profile change detected. Closing gamemodes menu."));
+ }
+ }
+
+ @Override
+ public void handleKeyboardInput() throws IOException {
+ if(Keyboard.getEventKeyState() && Keyboard.getEventKey() == Keyboard.KEY_ESCAPE) {
+ SBGamemodes.saveToFile();
+ }
+
+ super.handleKeyboardInput();
+ }
+
+ public void drawStringShadow(String str, float x, float y, int len) {
+ for(int xOff=-2; xOff<=2; xOff++) {
+ for(int yOff=-2; yOff<=2; yOff++) {
+ if(Math.abs(xOff) != Math.abs(yOff)) {
+ Utils.drawStringScaledMaxWidth(Utils.cleanColourNotModifiers(str),
+ Minecraft.getMinecraft().fontRendererObj,
+ x+xOff/2f, y+yOff/2f, false, len,
+ new Color(20, 20, 20, 100/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB());
+ }
+ }
+ }
+
+ Utils.drawStringScaledMaxWidth(str,
+ Minecraft.getMinecraft().fontRendererObj,
+ x, y, false, len,
+ new Color(64, 64, 64, 255).getRGB());
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ if(mouseButton == 0) {
+ SBGamemodes.HardcoreMode setHC = SBGamemodes.HardcoreMode.NORMAL;
+ SBGamemodes.IronmanMode setIM = SBGamemodes.IronmanMode.NORMAL;
+ int setMod = 0;
+
+ if(mouseX > guiLeft+xSize-27 && mouseX < guiLeft+xSize-9) {
+ if(mouseY > guiTop+30 && mouseY < guiTop+30+16) {
+ setHC = SBGamemodes.HardcoreMode.SOFTCORE;
+ } else if(mouseY > guiTop+50 && mouseY < guiTop+50+16) {
+ setHC = SBGamemodes.HardcoreMode.HARDCORE;
+ } else if(mouseY > guiTop+80 && mouseY < guiTop+80+16) {
+ setIM = SBGamemodes.IronmanMode.IRONMAN;
+ } else if(mouseY > guiTop+100 && mouseY < guiTop+100+16) {
+ setIM = SBGamemodes.IronmanMode.IRONMANPLUS;
+ } else if(mouseY > guiTop+120 && mouseY < guiTop+120+16) {
+ setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN;
+ } else if(mouseY > guiTop+140 && mouseY < guiTop+140+16) {
+ setIM = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS;
+ } else if(mouseY > guiTop+170 && mouseY < guiTop+170+16) {
+ setMod = SBGamemodes.MODIFIER_DEVILISH;
+ } else if(mouseY > guiTop+190 && mouseY < guiTop+190+16) {
+ setMod = SBGamemodes.MODIFIER_NOBANK;
+ } else if(mouseY > guiTop+210 && mouseY < guiTop+210+16) {
+ setMod = SBGamemodes.MODIFIER_SMALLISLAND;
+ }
+ }
+
+ if(setHC != SBGamemodes.HardcoreMode.NORMAL) {
+ if(currentGamemode.hardcoreMode == setHC) {
+ currentGamemode.hardcoreMode = SBGamemodes.HardcoreMode.NORMAL;
+ } else {
+ if(canChange(currentGamemode.hardcoreMode.ordinal(), setHC.ordinal())) {
+ currentGamemode.hardcoreMode = setHC;
+ }
+ }
+ } else if(setIM != SBGamemodes.IronmanMode.NORMAL) {
+ if(currentGamemode.ironmanMode == setIM) {
+ currentGamemode.ironmanMode = SBGamemodes.IronmanMode.NORMAL;
+ } else {
+ if(canChange(currentGamemode.ironmanMode.ordinal(), setIM.ordinal())) {
+ currentGamemode.ironmanMode = setIM;
+ }
+ }
+ } else if(setMod != 0) {
+ if(canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers^setMod)) {
+ currentGamemode.gamemodeModifiers ^= setMod;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ super.drawDefaultBackground();
+
+ guiLeft = (width-xSize)/2;
+ guiTop = (height-ySize)/2;
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(gamemodes);
+ Utils.drawTexturedRect(guiLeft, guiTop, xSize, ySize, GL11.GL_NEAREST);
+
+ if(currentGamemode == null) return;
+
+ Utils.drawStringCentered("NEU Skyblock Gamemodes", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+xSize/2f, guiTop+14, false, new Color(64, 64, 64).getRGB());
+
+ drawStringShadow(SBGamemodes.HardcoreMode.SOFTCORE.display, guiLeft+10, guiTop+30, xSize-47);
+ drawStringShadow(SBGamemodes.HardcoreMode.HARDCORE.display, guiLeft+10, guiTop+50, xSize-47);
+
+ drawStringShadow(SBGamemodes.IronmanMode.IRONMAN.display,guiLeft+10, guiTop+80, xSize-47);
+ drawStringShadow(SBGamemodes.IronmanMode.IRONMANPLUS.display,guiLeft+10, guiTop+100, xSize-47);
+ drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.display,guiLeft+10, guiTop+120, xSize-47);
+ drawStringShadow(SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.display,guiLeft+10, guiTop+140, xSize-47);
+
+ drawStringShadow(SBGamemodes.MODIFIER_DEVILISH_DISPLAY,guiLeft+10, guiTop+170, xSize-47);
+ drawStringShadow(SBGamemodes.MODIFIER_NOBANK_DISPLAY,guiLeft+10, guiTop+190, xSize-47);
+ drawStringShadow(SBGamemodes.MODIFIER_SMALLISLAND_DISPLAY,guiLeft+10, guiTop+210, xSize-47);
+
+ String tooltipToDisplay = null;
+
+ GlStateManager.color(1, 1, 1, 1);
+ if(canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.SOFTCORE.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.SOFTCORE ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+30-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+30-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+30-4 && mouseY < guiTop+30+12) {
+ tooltipToDisplay = SBGamemodes.HardcoreMode.SOFTCORE.desc;
+ }
+ }
+ }
+ if(canChange(currentGamemode.hardcoreMode.ordinal(), SBGamemodes.HardcoreMode.HARDCORE.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.hardcoreMode == SBGamemodes.HardcoreMode.HARDCORE ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+50-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+50-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+50-4 && mouseY < guiTop+50+12) {
+ tooltipToDisplay = SBGamemodes.HardcoreMode.HARDCORE.desc;
+ }
+ }
+ }
+
+ if(canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMAN.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMAN ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+80-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+80-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+80-4 && mouseY < guiTop+80+12) {
+ tooltipToDisplay = SBGamemodes.IronmanMode.IRONMAN.desc;
+ }
+ }
+ }
+ if(canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.IRONMANPLUS.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.ironmanMode == SBGamemodes.IronmanMode.IRONMANPLUS ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+100-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+100-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+100-4 && mouseY < guiTop+100+12) {
+ tooltipToDisplay = SBGamemodes.IronmanMode.IRONMANPLUS.desc;
+ }
+ }
+ }
+ if(canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMAN ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+120-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+120-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+120-4 && mouseY < guiTop+120+12) {
+ tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMAN.desc;
+ }
+ }
+ }
+ if(canChange(currentGamemode.ironmanMode.ordinal(), SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.ordinal())) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ currentGamemode.ironmanMode == SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS ? radial_circle_on : radial_circle_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+140-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+140-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+140-4 && mouseY < guiTop+140+12) {
+ tooltipToDisplay = SBGamemodes.IronmanMode.ULTIMATE_IRONMANPLUS.desc;
+ }
+ }
+ }
+
+ if(canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers^SBGamemodes.MODIFIER_DEVILISH)) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_DEVILISH) != 0 ? radial_square_on : radial_square_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+170-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+170-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+170-4 && mouseY < guiTop+170+12) {
+ tooltipToDisplay = SBGamemodes.MODIFIER_DEVILISH_DESC;
+ }
+ }
+ }
+ if(canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers^SBGamemodes.MODIFIER_NOBANK)) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_NOBANK) != 0 ? radial_square_on : radial_square_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+190-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+190-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+190-4 && mouseY < guiTop+190+12) {
+ tooltipToDisplay = SBGamemodes.MODIFIER_NOBANK_DESC;
+ }
+ }
+ }
+ if(canChange(currentGamemode.gamemodeModifiers, currentGamemode.gamemodeModifiers^SBGamemodes.MODIFIER_SMALLISLAND)) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(
+ (currentGamemode.gamemodeModifiers & SBGamemodes.MODIFIER_SMALLISLAND) != 0 ? radial_square_on : radial_square_off);
+ Utils.drawTexturedRect(guiLeft+xSize-26, guiTop+210-4, 16, 16, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(guiLeft+xSize-47, guiTop+210-4, 16, 16, GL11.GL_NEAREST);
+ if(mouseX > guiLeft+xSize-47 && mouseX < guiLeft+xSize-31) {
+ if(mouseY > guiTop+210-4 && mouseY < guiTop+210+12) {
+ tooltipToDisplay = SBGamemodes.MODIFIER_SMALLISLAND_DESC;
+ }
+ }
+ }
+
+ if(tooltipToDisplay != null) {
+ List<String> lines = new ArrayList<>();
+ for(String line : tooltipToDisplay.split("\n")) {
+ lines.add(EnumChatFormatting.GRAY+line);
+ }
+ Utils.drawHoveringText(lines, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java
new file mode 100644
index 00000000..09f00beb
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java
@@ -0,0 +1,349 @@
+package io.github.moulberry.notenoughupdates.gamemodes;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.questing.SBInfo;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.Key;
+import java.util.Base64;
+import java.util.HashMap;
+
+public class SBGamemodes {
+
+ private static final Gson gson = new Gson();
+
+ public static final int MODIFIER_DEVILISH = 0b1;
+ public static final int MODIFIER_NOBANK = 0b10;
+ public static final int MODIFIER_SMALLISLAND = 0b100;
+
+ public static final String MODIFIER_DEVILISH_DISPLAY = EnumChatFormatting.DARK_PURPLE+"Devilish";
+ public static final String MODIFIER_NOBANK_DISPLAY = EnumChatFormatting.RED+"No"+EnumChatFormatting.GOLD+"Bank";
+ public static final String MODIFIER_SMALLISLAND_DISPLAY = EnumChatFormatting.GREEN+"SmallIsland";
+
+ public static final String MODIFIER_DEVILISH_DESC = EnumChatFormatting.DARK_PURPLE+"Devilish\n" +
+ "You are NOT allowed to use fairy souls.";
+ public static final String MODIFIER_NOBANK_DESC = EnumChatFormatting.RED+"No"+EnumChatFormatting.GOLD+"Bank\n" +
+ "You are NOT allowed to use the bank.";
+ public static final String MODIFIER_SMALLISLAND_DESC = EnumChatFormatting.GREEN+"SmallIsland\n" +
+ "Your private island is 1/4 the normal size.";
+
+ private static HashMap<String, Gamemode> currentGamemode = new HashMap<>();
+ private static long lastDeathExemption = 0;
+
+ public static class Gamemode {
+ public HardcoreMode hardcoreMode = HardcoreMode.NORMAL;
+ public IronmanMode ironmanMode = IronmanMode.NORMAL;
+ public int gamemodeModifiers = 0;
+
+ public boolean locked = true;
+ }
+
+ public enum HardcoreMode {
+ NORMAL("Normal", "Normal"),
+ SOFTCORE(EnumChatFormatting.RED+"Soft"+EnumChatFormatting.DARK_RED+"core\n" +
+ "You only have 1 life.\nDying will remove your hardcore status.\nDeaths to the void or \'unknown\' are exempted.",
+ "You died.", "You fell into the void"),
+ HARDCORE(EnumChatFormatting.DARK_RED+"Hardcore\n" +
+ "You only have 1 life.\nDying will remove your hardcore status.");
+
+ public final String display;
+ public final String desc;
+ private String[] exemptions;
+
+ HardcoreMode(String display, String... exemptions) {
+ this.display = display.split("\n")[0];
+ this.desc = display;
+ this.exemptions = exemptions;
+ }
+
+ public boolean isExemption(String line) {
+ for(String exemption : exemptions) {
+ if(line.contains(exemption)) return true;
+ }
+ return false;
+ }
+ }
+
+ public enum IronmanMode {
+ NORMAL("Normal", "Normal"),
+ IRONMAN(EnumChatFormatting.WHITE+"Ironman\n" +
+ "You are NOT allowed to trade or use the auction house.",
+ "You ", "Auction House", "Auctions Browser", "Auction View"),
+ IRONMANPLUS(EnumChatFormatting.WHITE+"Ironman"+EnumChatFormatting.GOLD+"+\n" +
+ "You are NOT allowed to trade, use the auction house or bazaar.",
+ "You ", "Auction House", "Auctions Browser", "Auction View", "Bazaar"),
+ ULTIMATE_IRONMAN(EnumChatFormatting.DARK_AQUA+"Ultimate "+EnumChatFormatting.WHITE+"Ironman\n" +
+ "You are NOT allowed to trade or use the auction house.\n" +
+ "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).",
+ "You ", "Auction House", "Auctions Browser", "Auction View", "Chest",
+ "Wardrobe", "Weapon Rack", "Shelves"),
+ ULTIMATE_IRONMANPLUS(EnumChatFormatting.DARK_AQUA+"Ultimate "+EnumChatFormatting.WHITE+"Ironman"+EnumChatFormatting.GOLD+"+\n" +
+ "You are NOT allowed to trade, use the auction house or bazaar.\n" +
+ "You are restricted to 1 inventory. (No containers, no echest, no wardrobe).",
+ "You ", "Auction House", "Auctions Browser", "Auction View", "Bazaar",
+ "Chest", "Wardrobe", "Weapon Rack", "Shelves");
+
+ public final String display;
+ public final String desc;
+ private final String[] bannedInventories;
+
+ IronmanMode(String display, String... bannedInventories) {
+ this.display = display.split("\n")[0];
+ this.desc = display;
+ this.bannedInventories = bannedInventories;
+ }
+
+ public boolean isBanned(String inventoryName) {
+ for(String banned : bannedInventories) {
+ if(inventoryName.contains(banned + " ") || inventoryName.endsWith(banned)) return true;
+ }
+ return false;
+ }
+ }
+
+ public static Gamemode getGamemode() {
+ String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
+
+ if(currentProfile == null || currentProfile.isEmpty()) return null;
+
+ return currentGamemode.computeIfAbsent(currentProfile, k -> new Gamemode());
+ }
+
+ public static void loadFromFile() {
+ File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation;
+ File gamemodeFile = new File(configDir,
+ "gamemodes/gamemodes-"+Minecraft.getMinecraft().thePlayer.getUniqueID().toString()+".json");
+ gamemodeFile.getParentFile().mkdirs();
+
+ if(!gamemodeFile.exists()) {
+ return;
+ }
+
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(gamemodeFile), StandardCharsets.UTF_8))) {
+ String line = reader.readLine();
+ String decoded = decrypt(line);
+ currentGamemode = gson.fromJson(decoded, GamemodeWrapper.class).currentGamemode;
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static class GamemodeWrapper {
+ private HashMap<String, Gamemode> currentGamemode;
+
+ public GamemodeWrapper(HashMap<String, Gamemode> currentGamemode) {
+ this.currentGamemode = currentGamemode;
+ }
+ }
+
+ public static void saveToFile() {
+ File configDir = NotEnoughUpdates.INSTANCE.manager.configLocation;
+ File gamemodeFile = new File(configDir,
+ "gamemodes/gamemodes-"+Minecraft.getMinecraft().thePlayer.getUniqueID().toString()+".json");
+ gamemodeFile.getParentFile().mkdirs();
+
+ try {
+ gamemodeFile.createNewFile();
+
+ try(BufferedWriter writer = new BufferedWriter(
+ new OutputStreamWriter(new FileOutputStream(gamemodeFile), StandardCharsets.UTF_8))) {
+ JsonObject obj = new JsonObject();
+ writer.write(encrypt(gson.toJson(new GamemodeWrapper(currentGamemode), GamemodeWrapper.class)));
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static Key getKeyFromPlayerUUID() {
+ byte[] bytes = ByteBuffer.allocate(2 * Long.SIZE / Byte.SIZE)
+ .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getLeastSignificantBits())
+ .putLong(Minecraft.getMinecraft().thePlayer.getUniqueID().getMostSignificantBits())
+ .array();
+ SecretKeySpec key = new SecretKeySpec(bytes, "AES");
+
+ return key;
+ }
+
+
+ public static String encrypt(String value) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES");
+ cipher.init(Cipher.ENCRYPT_MODE, getKeyFromPlayerUUID());
+ String encrypt = Base64.getEncoder().encodeToString(cipher.doFinal(value.getBytes()));
+ return encrypt;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static String decrypt(String encrypted) {
+ try {
+ Cipher cipher = Cipher.getInstance("AES");
+ cipher.init(Cipher.DECRYPT_MODE, getKeyFromPlayerUUID());
+ byte[] b64Decoded = Base64.getDecoder().decode(encrypted);
+ byte[] bytes = cipher.doFinal(b64Decoded);
+
+ return new String(bytes);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static void setGamemode(Gamemode gamemode) {
+ String currentProfile = NotEnoughUpdates.INSTANCE.manager.getCurrentProfile();
+
+ if(currentProfile == null || currentProfile.isEmpty()) return;
+
+ currentGamemode.put(currentProfile, gamemode);
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
+
+ if(!"Your Island".equals(SBInfo.getInstance().location)) return;
+
+ if((getGamemode().gamemodeModifiers & MODIFIER_SMALLISLAND) != 0) {
+ if(event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) {
+ if(Math.abs(event.pos.getX()) > 40 || Math.abs(event.pos.getZ()) > 40) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"[NPC] Builder"+
+ EnumChatFormatting.WHITE+": Sorry, "+Minecraft.getMinecraft().thePlayer.getName()+
+ ", due to budget cuts your skyblock island is now only 80 blocks wide."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA+"(Use "+EnumChatFormatting.YELLOW+"/neugamemodes"+
+ EnumChatFormatting.AQUA+" if you would like to build further out)"));
+
+ event.setCanceled(true);
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
+
+ boolean inDungeons = SBInfo.getInstance().getLocation() != null && SBInfo.getInstance().getLocation().equals("dungeon");
+
+ if("Your Island".equals(SBInfo.getInstance().location) &&
+ (EnumChatFormatting.YELLOW+"Break a log").equals(SBInfo.getInstance().objective)) {
+ getGamemode().locked = false;
+ } else {
+ getGamemode().locked = true;
+ }
+
+ IronmanMode ironmanMode = getGamemode().ironmanMode;
+ GuiScreen gui = Minecraft.getMinecraft().currentScreen;
+ if(gui instanceof GuiChest) {
+ GuiChest eventGui = (GuiChest) gui;
+ ContainerChest cc = (ContainerChest) eventGui.inventorySlots;
+ String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText();
+
+ if(containerName.equals("Bank") && (getGamemode().gamemodeModifiers & MODIFIER_NOBANK) != 0) {
+ Minecraft.getMinecraft().thePlayer.closeScreen();
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"[NPC] Banker"+
+ EnumChatFormatting.WHITE+": Hi, "+Minecraft.getMinecraft().thePlayer.getName()+
+ ", you would like to create an account and make a deposit?"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"[NPC] Banker"+
+ EnumChatFormatting.WHITE+": Alright, I've invested your money into ..."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+"["+
+ EnumChatFormatting.WHITE+"YouTube"+EnumChatFormatting.RED+"] Nullzee"+
+ EnumChatFormatting.WHITE+": Hows it going everyone, welcome to my ultimate bazaar flipping guide ..."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"[NPC] Banker"+
+ EnumChatFormatting.WHITE+": Hmm, it seems as though the economy has crashed. All your money is gone. Poof. Vanished."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW+"[IDIOT] You"+
+ EnumChatFormatting.WHITE+": ... never again ..."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA+"(Use "+EnumChatFormatting.YELLOW+"/neugamemodes"+
+ EnumChatFormatting.AQUA+" if you would like to use the bank)"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ } else if(containerName.equals("Fairy") && (getGamemode().gamemodeModifiers & MODIFIER_DEVILISH) != 0) {
+ Minecraft.getMinecraft().thePlayer.closeScreen();
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.YELLOW+"[NPC] "+EnumChatFormatting.LIGHT_PURPLE+"Tia the Fairy"+
+ EnumChatFormatting.WHITE+": Oh no, "+Minecraft.getMinecraft().thePlayer.getName()+
+ ", you have sold your soul to the devil... please go away!"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA+"(Use "+EnumChatFormatting.YELLOW+"/neugamemodes"+
+ EnumChatFormatting.AQUA+" if you would like to use fairy souls)"));
+ } else if(!inDungeons && ironmanMode.isBanned(containerName)) {
+ Minecraft.getMinecraft().thePlayer.closeScreen();
+
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA+"You cannot access this inventory/menu because of your"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ " "+ironmanMode.display + EnumChatFormatting.AQUA+" status!"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.AQUA+"(Use "+EnumChatFormatting.YELLOW+"/neugamemodes"+
+ EnumChatFormatting.AQUA+" if you would like to downgrade the status)"));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(""));
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onChatMessage(ClientChatReceivedEvent event) {
+ if(event.type != 0) return;
+
+ /*if(Keyboard.isKeyDown(Keyboard.KEY_K)) {
+ boolean has = false;
+ for(char c : event.message.getFormattedText().toCharArray()) {
+ if((int)c > 200) {
+ if(!has) System.out.println("-----START");
+ has = true;
+ System.out.println((int)c);
+ }
+ }
+ if(has) System.out.println("-----END");
+ }*/
+ if(getGamemode() == null || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return;
+
+ String message = event.message.getFormattedText();
+ if(message.contains("\u2620")) { //Death symbol ( ☠ )
+ HardcoreMode hardcoreMode = getGamemode().hardcoreMode;
+ if(hardcoreMode != HardcoreMode.NORMAL) {
+ if(hardcoreMode.isExemption(message)) {
+ lastDeathExemption = System.currentTimeMillis();
+ }
+ }
+ }
+
+ if(System.currentTimeMillis() - lastDeathExemption > 1000 &&
+ message.contains("!") && message.startsWith(EnumChatFormatting.RESET.toString()+EnumChatFormatting.RED+"You died")) {
+ if(getGamemode().hardcoreMode != HardcoreMode.NORMAL) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(
+ EnumChatFormatting.RED.toString()+EnumChatFormatting.OBFUSCATED+"AAA"+
+ EnumChatFormatting.RED+" You have lost your "+
+ getGamemode().hardcoreMode.display+EnumChatFormatting.RED+" status! "+
+ EnumChatFormatting.RED+EnumChatFormatting.OBFUSCATED+"AAA"));
+ getGamemode().hardcoreMode = HardcoreMode.NORMAL;
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
index 5f9e6af1..d0600796 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CollectionLogInfoPane.java
@@ -5,6 +5,7 @@ import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.NEUOverlay;
import io.github.moulberry.notenoughupdates.NEUResourceManager;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
@@ -47,13 +48,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;
@@ -78,7 +79,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
private void refreshItems() {
items.clear();
for(String internalname : manager.getItemInformation().keySet()) {
- if(!manager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) {
+ if(!manager.auctionManager.isVanillaItem(internalname) && !internalname.matches(mobRegex)) {
JsonObject item = manager.getItemInformation().get(internalname);
JsonArray lore = manager.getItemInformation().get(internalname).get("lore").getAsJsonArray();
switch(filterMode) {
@@ -94,8 +95,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;
@@ -121,8 +122,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
float cost1 = manager.auctionManager.getLowestBin(o1);
float cost2 = manager.auctionManager.getLowestBin(o2);
- if(cost1 == -1) cost1 = manager.getCraftCost(o1).craftCost;
- if(cost2 == -1) cost2 = manager.getCraftCost(o2).craftCost;
+ if(cost1 == -1) cost1 = manager.auctionManager.getCraftCost(o1).craftCost;
+ if(cost2 == -1) cost2 = manager.auctionManager.getCraftCost(o2).craftCost;
if(cost1 < cost2) return 1;
if(cost1 > cost2) return -1;
@@ -241,19 +242,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 +256,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 +288,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;
@@ -316,7 +304,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
itemFramebufferGrayscale.bindFramebufferTexture();
- AtomicReference<JsonObject> tooltipToDisplay = new AtomicReference<>(null);
+ AtomicReference<ItemStack> tooltipToDisplay = new AtomicReference<>(null);
AtomicBoolean isTop = new AtomicBoolean(false);
AtomicInteger lowestY = new AtomicInteger(-1);
@@ -339,7 +327,7 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
if(mouseX > leftI && mouseX < rightI) {
if(mouseY > topI && mouseY < bottomI) {
- tooltipToDisplay.set(manager.getItemInformation().get(internalname));
+ tooltipToDisplay.set(manager.jsonToStack(manager.getItemInformation().get(internalname), true));
}
}
@@ -373,16 +361,9 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
itemFramebufferGrayscale.unbindFramebufferTexture();
- 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());
- }
-
+ ItemStack displayStack = tooltipToDisplay.get();
+ if(displayStack != null) {
+ List<String> text = displayStack.getTooltip(Minecraft.getMinecraft().thePlayer, true);
Utils.drawHoveringText(text, mouseX, mouseY, width, height, -1, Minecraft.getMinecraft().fontRendererObj);
}
}
@@ -415,9 +396,8 @@ public class CollectionLogInfoPane extends ScrollableInfoPane {
}
private void renderItemBackgrounds(Color fg, int left, int right, int top, int bottom) {
- int opacity = Math.min(255, Math.max(0, manager.config.fgOpacity.value.intValue()));
- Color fgGold = new Color(limCol(fg.getRed()+100), limCol(fg.getGreen()+50), limCol(fg.getBlue()-50), opacity);
- Color fgCustomOpacity = new Color((fg.getRGB() & 0x00ffffff) | opacity << 24, true);
+ Color fgCustomOpacity = new Color(SpecialColour.specialToChromaRGB(manager.config.itemBackgroundColour.value), true);
+ Color fgGold = new Color(SpecialColour.specialToChromaRGB(manager.config.itemFavouriteColour.value), true);
String[] items = getItemList();
iterateItemSlots(new ItemSlotConsumer() {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java
deleted file mode 100644
index 707968e3..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/CosmeticsInfoPane.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package io.github.moulberry.notenoughupdates.infopanes;
-
-import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
-import io.github.moulberry.notenoughupdates.NEUManager;
-import io.github.moulberry.notenoughupdates.NEUOverlay;
-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.renderer.GlStateManager;
-import net.minecraft.entity.player.EntityPlayer;
-import net.minecraft.util.ResourceLocation;
-
-import java.awt.*;
-import java.util.HashMap;
-
-public class CosmeticsInfoPane extends InfoPane {
-
- public CosmeticsInfoPane(NEUOverlay overlay, NEUManager manager) {
- super(overlay, manager);
- }
-
- private HashMap<String, ResourceLocation> capeTextures = new HashMap<>();
-
- private String selectedCape = null;
-
- public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX,
- int mouseY) {
- super.renderDefaultBackground(width, height, bg);
-
- FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int currentY = overlay.getBoxPadding()+10;
- fr.drawString("NEU Capes", overlay.getBoxPadding()+10, currentY, Color.WHITE.getRGB(), true); currentY += 10;
-
- selectedCape = null;
- for(String cape : CapeManager.getInstance().getCapes()) {
- if(CapeManager.getInstance().getPermissionForCape(Minecraft.getMinecraft().thePlayer.getName(), cape)) {
- currentY += renderCapeSelector(cape, currentY, mouseX, mouseY);
- currentY += 5;
- }
- }
- }
-
- public int renderCapeSelector(String capename, int y, int mouseX, int mouseY) {
- if(mouseX > overlay.getBoxPadding()+5 && mouseX < overlay.getBoxPadding()+75) {
- if(mouseY > y && mouseY < y+100) {
- selectedCape = capename;
- }
- }
- boolean selected = capename.equals(CapeManager.getInstance().getCape(Minecraft.getMinecraft().thePlayer.getName()));
-
- if(selected) {
- drawRect(overlay.getBoxPadding()+5, y, overlay.getBoxPadding()+75, y+100, Color.YELLOW.getRGB());
- drawGradientRect(overlay.getBoxPadding()+10, y+5, overlay.getBoxPadding()+70, y+95, Color.GRAY.darker().getRGB(), Color.GRAY.getRGB());
- } else {
- drawGradientRect(overlay.getBoxPadding()+5, y, overlay.getBoxPadding()+75, y+100, Color.GRAY.darker().getRGB(), Color.GRAY.getRGB());
- }
-
- GlStateManager.color(1, 1, 1, 1);
-
- ResourceLocation capeTex = capeTextures.computeIfAbsent(capename, k -> new ResourceLocation("notenoughupdates:"+capename+".png"));
-
- Minecraft.getMinecraft().getTextureManager().bindTexture(capeTex);
- Utils.drawTexturedRect(overlay.getBoxPadding()+10, y+10, 60, 80, 0, 300/1024f, 0, 425/1024f);
- return 100;
- }
-
- public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) {
- if(mouseDown && selectedCape != null) {
- if(selectedCape.equals(CapeManager.getInstance().getCape(Minecraft.getMinecraft().thePlayer.getName()))) {
- CapeManager.getInstance().setCape(Minecraft.getMinecraft().thePlayer.getName(), null);
- } else {
- CapeManager.getInstance().setCape(Minecraft.getMinecraft().thePlayer.getName(), selectedCape);
- }
- }
- }
-
- @Override
- public boolean keyboardInput() {
- return false;
- }
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
index ec5f8209..22427cee 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/DevInfoPane.java
@@ -4,10 +4,25 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.NEUOverlay;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.crafting.CraftingManager;
+import net.minecraft.item.crafting.IRecipe;
+import net.minecraft.item.crafting.ShapedRecipes;
+import net.minecraft.item.crafting.ShapelessRecipes;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.oredict.ShapedOreRecipe;
+import net.minecraftforge.oredict.ShapelessOreRecipe;
import org.lwjgl.input.Keyboard;
+import java.io.IOException;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -45,7 +60,8 @@ public class DevInfoPane extends TextInfoPane {
}*/
//if(true) return text;
- for(String internalname : manager.auctionManager.internalnameToAucIdMap.keySet()) {
+ for(String internalname : manager.auctionManager.getItemAuctionInfoKeySet()) {
+ if(internalname.contains("-")) continue;
if(!manager.getItemInformation().containsKey(internalname)) {
text += internalname + "\n";
}
@@ -69,12 +85,852 @@ public class DevInfoPane extends TextInfoPane {
AtomicBoolean running = new AtomicBoolean(false);
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
+ String[] bukkitList = new String[] {
+ "ACACIA_DOOR_ITEM",
+ "ACACIA_FENCE",
+ "ACACIA_FENCE_GATE",
+ "ACACIA_STAIRS",
+ "ACTIVATOR_RAIL",
+ "ANVIL",
+ "APPLE",
+ "ARMOR_STAND",
+ "ARROW",
+ "BAKED_POTATO",
+ "BANNER",
+ "BARRIER",
+ "BEACON",
+ "BED",
+ "BEDROCK",
+ "BIRCH_DOOR_ITEM",
+ "BIRCH_FENCE",
+ "BIRCH_FENCE_GATE",
+ "BIRCH_WOOD_STAIRS@birch_stairs",
+ "BLAZE_POWDER",
+ "BLAZE_ROD",
+ "BOAT",
+ "BONE",
+ "BOOK",
+ "BOOK_AND_QUILL@writable_book",
+ "BOOKSHELF",
+ "BOW",
+ "BOWL",
+ "BREAD",
+ "BREWING_STAND_ITEM",
+ "BRICK@brick_block",
+ "BRICK_STAIRS",
+ "BROWN_MUSHROOM",
+ "BUCKET",
+ "CACTUS",
+ "CAKE",
+ "CARPET",
+ "CARROT_ITEM",
+ "CARROT_STICK@carrot_on_a_stick",
+ "CAULDRON_ITEM",
+ "CHAINMAIL_BOOTS",
+ "CHAINMAIL_CHESTPLATE",
+ "CHAINMAIL_HELMET",
+ "CHAINMAIL_LEGGINGS",
+ "CHEST",
+ "CLAY",
+ "CLAY_BALL",
+ "CLAY_BRICK@brick",
+ "COAL",
+ "COAL_BLOCK",
+ "COAL_ORE",
+ "COBBLE_WALL@cobblestone_wall",
+ "COBBLESTONE",
+ "COBBLESTONE_STAIRS@stone_stairs",
+ "COMMAND@command_block",
+ "COMMAND_MINECART@command_block_minecart",
+ "COMPASS",
+ "COOKED_BEEF",
+ "COOKED_CHICKEN",
+ "COOKED_FISH",
+ "COOKED_MUTTON",
+ "COOKED_RABBIT",
+ "COOKIE",
+ "DARK_OAK_DOOR_ITEM",
+ "DARK_OAK_FENCE",
+ "DARK_OAK_FENCE_GATE",
+ "DARK_OAK_STAIRS",
+ "DAYLIGHT_DETECTOR",
+ "DEAD_BUSH@deadbush",
+ "DETECTOR_RAIL",
+ "DIAMOND",
+ "DIAMOND_AXE",
+ "DIAMOND_BARDING@diamond_horse_armor",
+ "DIAMOND_BLOCK",
+ "DIAMOND_BOOTS",
+ "DIAMOND_CHESTPLATE",
+ "DIAMOND_HELMET",
+ "DIAMOND_HOE",
+ "DIAMOND_LEGGINGS",
+ "DIAMOND_ORE",
+ "DIAMOND_PICKAXE",
+ "DIAMOND_SPADE@diamond_shovel",
+ "DIAMOND_SWORD",
+ "DIODE@repeater",
+ "DIRT",
+ "DISPENSER",
+ "DOUBLE_PLANT",
+ "DRAGON_EGG",
+ "DROPPER",
+ "EGG",
+ "EMERALD",
+ "EMERALD_BLOCK",
+ "EMERALD_ORE",
+ "EMPTY_MAP@map",
+ "ENCHANTED_BOOK",
+ "ENCHANTMENT_TABLE@enchanting_table",
+ "ENDER_CHEST",
+ "ENDER_PEARL",
+ "ENDER_PORTAL_FRAME@end_portal_frame",
+ "ENDER_STONE@end_stone",
+ "EXP_BOTTLE@experience_bottle",
+ "EXPLOSIVE_MINECART@tnt_minecart",
+ "EYE_OF_ENDER@ender_eye",
+ "FEATHER",
+ "FENCE",
+ "FENCE_GATE",
+ "FERMENTED_SPIDER_EYE",
+ "FIREBALL@fire_charge",
+ "FIREWORK@fireworks",
+ "FIREWORK_CHARGE",
+ "FISHING_ROD",
+ "FLINT",
+ "FLINT_AND_STEEL",
+ "FLOWER_POT_ITEM",
+ "FURNACE",
+ "GHAST_TEAR",
+ "GLASS",
+ "GLASS_BOTTLE",
+ "GLOWSTONE",
+ "GLOWSTONE_DUST",
+ "GOLD_AXE@golden_axe",
+ "GOLD_BARDING@golden_horse_armor",
+ "GOLD_BLOCK",
+ "GOLD_BOOTS@golden_boots",
+ "GOLD_CHESTPLATE@golden_chestplate",
+ "GOLD_HELMET@golden_helmet",
+ "GOLD_HOE@golden_hoe",
+ "GOLD_INGOT",
+ "GOLD_LEGGINGS@golden_leggings",
+ "GOLD_NUGGET",
+ "GOLD_ORE",
+ "GOLD_PICKAXE@golden_pickaxe",
+ "GOLD_PLATE@light_weighted_pressure_plate",
+ "GOLD_RECORD@record_13",
+ "GOLD_SPADE@golden_shovel",
+ "GOLD_SWORD@golden_sword",
+ "GOLDEN_APPLE",
+ "GOLDEN_CARROT",
+ "GRASS",
+ "GRAVEL",
+ "GREEN_RECORD@record_cat",
+ "GRILLED_PORK@cooked_porkchop",
+ "HARD_CLAY@hardened_clay",
+ "HAY_BLOCK",
+ "HOPPER",
+ "HOPPER_MINECART",
+ "ICE",
+ "INK_SACK@dye",
+ "IRON_AXE",
+ "IRON_BARDING@iron_horse_armor",
+ "IRON_BLOCK",
+ "IRON_BOOTS",
+ "IRON_CHESTPLATE",
+ "IRON_DOOR",
+ "IRON_FENCE@iron_bars",
+ "IRON_HELMET",
+ "IRON_HOE",
+ "IRON_INGOT",
+ "IRON_LEGGINGS",
+ "IRON_ORE",
+ "IRON_PICKAXE",
+ "IRON_PLATE@heavy_weighted_pressure_plate",
+ "IRON_SPADE@iron_shovel",
+ "IRON_SWORD",
+ "IRON_TRAPDOOR",
+ "ITEM_FRAME",
+ "JACK_O_LANTERN@lit_pumpkin",
+ "JUKEBOX",
+ "JUNGLE_DOOR_ITEM",
+ "JUNGLE_FENCE",
+ "JUNGLE_FENCE_GATE",
+ "JUNGLE_WOOD_STAIRS@jungle_stairs",
+ "LADDER",
+ "LAPIS_BLOCK",
+ "LAPIS_ORE",
+ "LAVA_BUCKET",
+ "LEASH@lead",
+ "LEATHER",
+ "LEATHER_BOOTS",
+ "LEATHER_CHESTPLATE",
+ "LEATHER_HELMET",
+ "LEATHER_LEGGINGS",
+ "LEAVES",
+ "LEAVES_2@leaves2",
+ "LEVER",
+ "LOG",
+ "LOG_2@log2",
+ "LONG_GRASS@tallgrass",
+ "MAGMA_CREAM",
+ "MAP",
+ "MELON",
+ "MELON_BLOCK",
+ "MELON_SEEDS",
+ "MILK_BUCKET",
+ "MINECART",
+ "MOB_SPAWNER",
+ "MONSTER_EGG",
+ "MONSTER_EGGS@spawn_egg",
+ "MOSSY_COBBLESTONE",
+ "MUSHROOM_SOUP@mushroom_stew",
+ "MUTTON",
+ "MYCEL@mycelium",
+ "NAME_TAG",
+ "NETHER_BRICK",
+ "NETHER_BRICK_ITEM",
+ "NETHER_BRICK_STAIRS",
+ "NETHER_FENCE@nether_brick_fence",
+ "NETHER_STAR",
+ "NETHER_WARTS@nether_wart",
+ "NETHERRACK",
+ "NOTE_BLOCK@noteblock",
+ "OBSIDIAN",
+ "PACKED_ICE",
+ "PAINTING",
+ "PAPER",
+ "PISTON_BASE@piston",
+ "PISTON_STICKY_BASE@sticky_piston",
+ "POISONOUS_POTATO",
+ "PORK@porkchop",
+ "POTATO_ITEM",
+ "POTION",
+ "POWERED_MINECART@furnace_minecart",
+ "POWERED_RAIL@golden_rail",
+ "PRISMARINE",
+ "PRISMARINE_CRYSTALS",
+ "PRISMARINE_SHARD",
+ "PUMPKIN",
+ "PUMPKIN_PIE",
+ "PUMPKIN_SEEDS",
+ "QUARTZ",
+ "QUARTZ_BLOCK",
+ "QUARTZ_ORE",
+ "QUARTZ_STAIRS",
+ "RABBIT",
+ "RABBIT_FOOT",
+ "RABBIT_HIDE",
+ "RABBIT_STEW",
+ "RAILS@rail",
+ "RAW_BEEF@beef",
+ "RAW_CHICKEN@chicken",
+ "RAW_FISH@fish",
+ "RECORD_10@record_ward",
+ "RECORD_11",
+ "RECORD_12@record_wait",
+ "RECORD_3@record_blocks",
+ "RECORD_4@record_chirp",
+ "RECORD_5@record_far",
+ "RECORD_6@record_mall",
+ "RECORD_7@record_mellohi",
+ "RECORD_8@record_stal",
+ "RECORD_9@record_strad",
+ "RED_MUSHROOM",
+ "RED_ROSE@red_flower",
+ "RED_SANDSTONE",
+ "RED_SANDSTONE_STAIRS",
+ "REDSTONE",
+ "REDSTONE_BLOCK",
+ "REDSTONE_COMPARATOR@comparator",
+ "REDSTONE_LAMP_OFF@redstone_lamp",
+ "REDSTONE_ORE",
+ "REDSTONE_TORCH_ON@redstone_torch",
+ "ROTTEN_FLESH",
+ "SADDLE",
+ "SAND",
+ "SANDSTONE",
+ "SANDSTONE_STAIRS",
+ "SAPLING",
+ "SEA_LANTERN",
+ "SEEDS@wheat_seeds",
+ "SHEARS",
+ "SIGN",
+ "SKULL_ITEM",
+ "SLIME_BALL",
+ "SLIME_BLOCK@slime",
+ "SMOOTH_BRICK@stonebrick",
+ "SMOOTH_STAIRS@stone_brick_stairs",
+ "SNOW@snow_layer",
+ "SNOW_BALL@snowball",
+ "SNOW_BLOCK@snow",
+ "SOUL_SAND",
+ "SPECKLED_MELON",
+ "SPIDER_EYE",
+ "SPONGE",
+ "SPRUCE_DOOR_ITEM",
+ "SPRUCE_FENCE",
+ "SPRUCE_FENCE_GATE",
+ "SPRUCE_WOOD_STAIRS@spruce_stairs",
+ "STAINED_CLAY@stained_hardened_clay",
+ "STAINED_GLASS",
+ "STAINED_GLASS_PANE",
+ "STEP@stone_slab",
+ "STICK",
+ "STONE",
+ "STONE_AXE",
+ "STONE_BUTTON",
+ "STONE_HOE",
+ "STONE_PICKAXE",
+ "STONE_PLATE@stone_pressure_plate",
+ "STONE_SLAB2",
+ "STONE_SPADE@stone_shovel",
+ "STONE_SWORD",
+ "STORAGE_MINECART@chest_minecart",
+ "STRING",
+ "SUGAR",
+ "SUGAR_CANE@reeds",
+ "SULPHUR@gunpowder",
+ "THIN_GLASS@glass_pane",
+ "TNT",
+ "TORCH",
+ "TRAP_DOOR@trapdoor",
+ "TRAPPED_CHEST",
+ "TRIPWIRE_HOOK",
+ "VINE",
+ "WATCH@clock",
+ "WATER_BUCKET",
+ "WATER_LILY@waterlily",
+ "WEB",
+ "WHEAT",
+ "WOOD@planks",
+ "WOOD_AXE@wooden_axe",
+ "WOOD_BUTTON@wooden_button",
+ "WOOD_DOOR@wooden_door",
+ "WOOD_HOE@wooden_hoe",
+ "WOOD_PICKAXE@wooden_pickaxe",
+ "WOOD_PLATE@wooden_pressure_plate",
+ "WOOD_SPADE@wooden_shovel",
+ "WOOD_STAIRS@oak_stairs",
+ "WOOD_STEP@wooden_slab",
+ "WOOD_SWORD@wooden_sword",
+ "WOOL",
+ "WORKBENCH@crafting_table",
+ "WRITTEN_BOOK",
+ "YELLOW_FLOWER"
+ };
+
+ private void addStack(ItemStack stackToAdd, int depth) {
+ if(depth > 16) return;
+
+ String regName2 = stackToAdd.getItem().getRegistryName().replace("minecraft:", "");
+ String internalname = null;
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName2) ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName2))) {
+ internalname = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(internalname == null) return;
+
+ if(stackToAdd.getItemDamage() != 0 && stackToAdd.getItemDamage() < 32000) {
+ internalname += "-" + stackToAdd.getItemDamage();
+ }
+
+ if(manager.getItemInformation().containsKey(internalname)) return;
+
+ JsonObject recipeJson = null;
+ for(IRecipe recipe : CraftingManager.getInstance().getRecipeList()) {
+ ItemStack out = recipe.getRecipeOutput();
+ if(out != null && out.getItem() == stackToAdd.getItem() &&
+ (stackToAdd.getItemDamage() >= 32000 || out.getItemDamage() == stackToAdd.getItemDamage())) {
+ recipeJson = new JsonObject();
+
+ if (recipe instanceof ShapedRecipes) {
+ ShapedRecipes shaped = (ShapedRecipes) recipe;
+
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ int recipeIndex = i-(3-shaped.recipeWidth)*yi;
+ if(xi < shaped.recipeWidth && recipeIndex < shaped.recipeItems.length) {
+ ItemStack stack = shaped.recipeItems[recipeIndex];
+ if(stack != null) {
+ if(stack.getItem() != stackToAdd.getItem() ||
+ (stackToAdd.getItemDamage() < 32000 && stack.getItemDamage() != stackToAdd.getItemDamage())) addStack(stack, depth+1);
+
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ stacki += ":"+stack.stackSize;
+ }
+ }
+ }
+
+ recipeJson.addProperty(y[yi]+x[xi], stacki);
+ }
+ break;
+ } else if(recipe instanceof ShapedOreRecipe) {
+ ShapedOreRecipe shaped = (ShapedOreRecipe) recipe;
+ int width = (int)Utils.getField(ShapedOreRecipe.class, recipe, "width");
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ int recipeIndex = i - (3 - width) * yi;
+ if (xi < width && recipeIndex < shaped.getRecipeSize()) {
+ ItemStack stack = null;
+ if(recipeIndex < shaped.getRecipeSize()) {
+ Object o = shaped.getInput()[recipeIndex];
+ if(o instanceof ItemStack) {
+ stack = (ItemStack) o;
+ } else if(o instanceof List<?>) {
+ for(Object o2 : (List<?>)o) {
+ if(o2 instanceof ItemStack) {
+ stack = (ItemStack) o2;
+ break;
+ }
+ }
+ }
+ }
+ if(stack != null) {
+ if(stack.getItem() != stackToAdd.getItem() ||
+ (stackToAdd.getItemDamage() < 32000 && stack.getItemDamage() != stackToAdd.getItemDamage())) addStack(stack, depth+1);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+ }
+
+ recipeJson.addProperty(y[yi]+x[xi], stacki);
+ }
+ } else if (recipe instanceof ShapelessRecipes) {
+ ShapelessRecipes shapeless = (ShapelessRecipes) recipe;
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ ItemStack stack = null;
+ if(i < shapeless.recipeItems.size()) {
+ stack = shapeless.recipeItems.get(i);
+ }
+ if(stack != null) {
+ if(stack.getItem() != stackToAdd.getItem() ||
+ (stackToAdd.getItemDamage() < 32000 && stack.getItemDamage() != stackToAdd.getItemDamage())) addStack(stack, depth+1);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+
+ recipeJson.addProperty(y[yi]+x[xi], stacki);
+ }
+ break;
+ } else if (recipe instanceof ShapelessOreRecipe) {
+ ShapelessOreRecipe shapeless = (ShapelessOreRecipe) recipe;
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ ItemStack stack = null;
+ if(i < shapeless.getRecipeSize()) {
+ Object o = shapeless.getInput().get(i);;
+ if(o instanceof ItemStack) {
+ stack = (ItemStack) o;
+ } else if(o instanceof List<?>) {
+ for(Object o2 : (List<?>)o) {
+ if(o2 instanceof ItemStack) {
+ stack = (ItemStack) o2;
+ break;
+ }
+ }
+ }
+ }
+ if(stack != null) {
+ if(stack.getItem() != stackToAdd.getItem() ||
+ (stackToAdd.getItemDamage() < 32000 && stack.getItemDamage() != stackToAdd.getItemDamage())) addStack(stack, depth+1);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+
+ recipeJson.addProperty(y[yi]+x[xi], stacki);
+ }
+ break;
+ }
+ }
+
+ }
+ ItemStack res = Utils.createItemStack(stackToAdd.getItem(),
+ EnumChatFormatting.WHITE+stackToAdd.getItem().getItemStackDisplayName(stackToAdd),
+ EnumChatFormatting.WHITE.toString()+EnumChatFormatting.BOLD+"COMMON");
+ if(stackToAdd.getItemDamage() != 0 && stackToAdd.getItemDamage() < 32000) {
+ res.setItemDamage(stackToAdd.getItemDamage());
+ }
+ res.getTagCompound().setInteger("HideFlags", 254);
+ NBTTagCompound ea = new NBTTagCompound();
+ ea.setString("id", internalname);
+ res.getTagCompound().setTag("ExtraAttributes", ea);
+
+
+ JsonObject json = manager.getJsonForItem(res);
+ if(stackToAdd.getItemDamage() != 0 && stackToAdd.getItemDamage() < 32000) {
+ json.addProperty("parent", internalname.split("-")[0]);
+ }
+
+ json.addProperty("internalname", internalname);
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ json.addProperty("vanilla", true);
+
+ if(recipeJson != null) {
+ json.add("recipe", recipeJson);
+ json.addProperty("clickcommand", "viewrecipe");
+ } else {
+ json.addProperty("clickcommand", "");
+ }
+
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname));
+ manager.writeJsonDefaultDir(json, internalname+".json");
+ manager.loadItem(internalname);
+ } catch(IOException e) {}
+ }
+
@Override
public boolean keyboardInput() {
+ if(running.get() || true) return false;
if(Keyboard.isKeyDown(Keyboard.KEY_J)) {
running.set(!running.get());
- for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
+ for(String bukkit : bukkitList) {
+ String internalname = bukkit.split("@")[0];
+ if(true || !manager.getItemInformation().containsKey(internalname)) {
+ //System.out.println("adding vanilla: " + internalname);
+ String vanilla = internalname.toLowerCase().replace("_item", "");
+ if(bukkit.contains("@")) {
+ vanilla = bukkit.split("@")[1];
+ }
+ Item item = Item.itemRegistry.getObject(new ResourceLocation(vanilla));
+ if(item == null) {
+ item = Item.getItemFromBlock(Block.blockRegistry.getObject(new ResourceLocation(vanilla)));
+ }
+ if(item != null) {
+ HashMap<Integer, JsonObject> recipeJsonForDamage = new HashMap<>();
+ for(IRecipe recipe : CraftingManager.getInstance().getRecipeList()) {
+ ItemStack out = recipe.getRecipeOutput();
+ if(out != null && out.getItem() == item) {
+ System.out.println("Found recipe for : " + internalname + ":" + recipe);
+ JsonObject obj = new JsonObject();
+
+ if (recipe instanceof ShapedRecipes) {
+ ShapedRecipes shaped = (ShapedRecipes) recipe;
+ String[] x = {"1", "2", "3"};
+ String[] y = {"A", "B", "C"};
+ for (int i = 0; i < 9; i++) {
+ int xi = i % 3;
+ int yi = i / 3;
+
+ String stacki = "";
+
+ int recipeIndex = i - (3 - shaped.recipeWidth) * yi;
+ if (xi < shaped.recipeWidth && recipeIndex < shaped.recipeItems.length) {
+ ItemStack stack = shaped.recipeItems[recipeIndex];
+ if (stack != null) {
+ addStack(stack, 0);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for (String bukkit2 : bukkitList) {
+ if (bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName + "_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if (!stacki.isEmpty()) {
+ if (stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+ }
+
+ obj.addProperty(y[yi] + x[xi], stacki);
+ }
+ recipeJsonForDamage.put(out.getItemDamage() > 32000 ? 0 : out.getItemDamage(), obj);
+ } else if(recipe instanceof ShapedOreRecipe) {
+ ShapedOreRecipe shaped = (ShapedOreRecipe) recipe;
+ int width = (int)Utils.getField(ShapedOreRecipe.class, recipe, "width");
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ int recipeIndex = i - (3 - width) * yi;
+ if (xi < width && recipeIndex < shaped.getRecipeSize()) {
+ ItemStack stack = null;
+ if(recipeIndex < shaped.getRecipeSize()) {
+ Object o = shaped.getInput()[recipeIndex];
+ if(o instanceof ItemStack) {
+ stack = (ItemStack) o;
+ } else if(o instanceof List<?>) {
+ for(Object o2 : (List<?>)o) {
+ if(o2 instanceof ItemStack) {
+ stack = (ItemStack) o2;
+ break;
+ }
+ }
+ }
+ }
+ if(stack != null) {
+ addStack(stack, 0);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+ }
+
+ obj.addProperty(y[yi]+x[xi], stacki);
+ }
+ recipeJsonForDamage.put(out.getItemDamage()>32000?0:out.getItemDamage(), obj);
+ } else if (recipe instanceof ShapelessRecipes) {
+ ShapelessRecipes shapeless = (ShapelessRecipes) recipe;
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ ItemStack stack = null;
+ if(i < shapeless.recipeItems.size()) {
+ stack = shapeless.recipeItems.get(i);
+ }
+ if(stack != null) {
+ addStack(stack, 0);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+
+ obj.addProperty(y[yi]+x[xi], stacki);
+ }
+ recipeJsonForDamage.put(out.getItemDamage() > 32000 ? 0 : out.getItemDamage(), obj);
+ break;
+ } else if (recipe instanceof ShapelessOreRecipe) {
+ ShapelessOreRecipe shapeless = (ShapelessOreRecipe) recipe;
+ String[] x = {"1","2","3"};
+ String[] y = {"A","B","C"};
+ for(int i=0; i<9; i++) {
+ int xi = i%3;
+ int yi = i/3;
+
+ String stacki = "";
+
+ ItemStack stack = null;
+ if(i < shapeless.getRecipeSize()) {
+ Object o = shapeless.getInput().get(i);;
+ if(o instanceof ItemStack) {
+ stack = (ItemStack) o;
+ } else if(o instanceof List<?>) {
+ for(Object o2 : (List<?>)o) {
+ if(o2 instanceof ItemStack) {
+ stack = (ItemStack) o2;
+ break;
+ }
+ }
+ }
+ }
+ if(stack != null) {
+ addStack(stack, 0);
+ Item stackItem = stack.getItem();
+ String regName = stackItem.getRegistryName().replace("minecraft:", "");
+ for(String bukkit2 : bukkitList) {
+ if(bukkit2.equalsIgnoreCase(regName) || bukkit2.equalsIgnoreCase(regName+"_ITEM") ||
+ (bukkit2.contains("@") && bukkit2.split("@")[1].equalsIgnoreCase(regName))) {
+ stacki = bukkit2.split("@")[0];
+ break;
+ }
+ }
+ if(!stacki.isEmpty()) {
+ if(stack.getItemDamage() != 0 && stack.getItemDamage() < 32000) {
+ stacki += "-" + stack.getItemDamage();
+ }
+ //stacki += ":"+stack.stackSize;
+ stacki += ":1";
+ }
+ }
+
+ obj.addProperty(y[yi]+x[xi], stacki);
+ }
+ recipeJsonForDamage.put(out.getItemDamage() > 32000 ? 0 : out.getItemDamage(), obj);
+ break;
+ }
+ }
+ }
+
+ if(recipeJsonForDamage.isEmpty()) {
+ ItemStack res = Utils.createItemStack(item,
+ EnumChatFormatting.WHITE+item.getItemStackDisplayName(new ItemStack(item)),
+ EnumChatFormatting.WHITE.toString()+EnumChatFormatting.BOLD+"COMMON");
+ res.getTagCompound().setInteger("HideFlags", 254);
+ NBTTagCompound ea = new NBTTagCompound();
+ ea.setString("id", internalname);
+ res.getTagCompound().setTag("ExtraAttributes", ea);
+
+ JsonObject json = manager.getJsonForItem(res);
+ json.addProperty("internalname", internalname);
+
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ json.addProperty("vanilla", true);
+
+ json.addProperty("clickcommand", "");
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname));
+ manager.writeJsonDefaultDir(json, internalname+".json");
+ manager.loadItem(internalname);
+ } catch(IOException e) {}
+ } else {
+ System.out.println("writing with recipe:" + internalname);
+ for(Map.Entry<Integer, JsonObject> entry : recipeJsonForDamage.entrySet()) {
+ ItemStack res = Utils.createItemStack(item,
+ EnumChatFormatting.WHITE+item.getItemStackDisplayName(new ItemStack(item, 1, entry.getKey())),
+ EnumChatFormatting.WHITE.toString()+EnumChatFormatting.BOLD+"COMMON");
+ res.setItemDamage(entry.getKey());
+ res.getTagCompound().setInteger("HideFlags", 254);
+ NBTTagCompound ea = new NBTTagCompound();
+ ea.setString("id", internalname);
+ res.getTagCompound().setTag("ExtraAttributes", ea);
+
+ JsonObject json = manager.getJsonForItem(res);
+
+ if(entry.getKey() != 0 && entry.getKey() < 32000) {
+ json.addProperty("internalname", internalname+"-"+entry.getKey());
+ json.addProperty("parent", internalname);
+ } else {
+ json.addProperty("internalname", internalname);
+ }
+
+ json.addProperty("modver", NotEnoughUpdates.VERSION);
+ json.addProperty("vanilla", true);
+ json.addProperty("clickcommand", "viewrecipe");
+ json.add("recipe", entry.getValue());
+ try {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("Added: " + internalname));
+ if(entry.getKey() != 0 && entry.getKey() < 32000) {
+ manager.writeJsonDefaultDir(json, internalname+"-"+entry.getKey()+".json");
+ } else {
+ manager.writeJsonDefaultDir(json, internalname+".json");
+ }
+ manager.loadItem(internalname);
+ } catch(IOException e) {}
+ }
+ }
+ }
+ }
+ }
+
+ //for(Map.Entry<String, JsonObject> item : manager.getItemInformation().entrySet()) {
/*if(!item.getValue().has("infoType") || item.getValue().get("infoType").getAsString().isEmpty()) {
if(item.getValue().has("info") && item.getValue().get("info").getAsJsonArray().size()>0) {
item.getValue().addProperty("infoType", "WIKI_URL");
@@ -167,7 +1023,7 @@ public class DevInfoPane extends TextInfoPane {
}
}, 1000L, TimeUnit.MILLISECONDS);
}*/
- }
+ //}
/*if(Keyboard.isKeyDown(Keyboard.KEY_J) && !running) {
running = true;
List<String> add = new ArrayList<>();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
index 3e9cdb3f..c03b98fb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/HTMLInfoPane.java
@@ -136,6 +136,10 @@ public class HTMLInfoPane extends TextInfoPane {
return new HTMLInfoPane(overlay, manager, name, filename, html);
}
+ private String spaceEscape(String str) {
+ return str.replace(" ", "\\ ");
+ }
+
/**
* Uses the wkhtmltoimage command-line tool to generate an image from the HTML code. This
* generation is done asynchronously as sometimes it can take up to 10 seconds for more
@@ -190,9 +194,16 @@ public class HTMLInfoPane extends TextInfoPane {
EnumChatFormatting.GRAY+"), please wait...";
Runtime runtime = Runtime.getRuntime();
- Process p = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+
+
+ String[] wkCommand = new String[]{ wkHtmlToImage.getAbsolutePath(), "--width", ""+IMAGE_WIDTH*ZOOM_FACTOR,
+ "--transparent", "--zoom", ""+ZOOM_FACTOR, input.getAbsolutePath(), output.getAbsolutePath()};
+ Process p = runtime.exec(wkCommand);
+ /*Process p = runtime.exec(spaceEscape(wkHtmlToImage.getAbsolutePath()) + " --width "+
+ IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR + " " + spaceEscape(input.getAbsolutePath()) +
+ " " + spaceEscape(output.getAbsolutePath()));*/
+ /*Process p = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+
IMAGE_WIDTH*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() +
- "\" \"" + output.getAbsolutePath() + "\"");
+ "\" \"" + output.getAbsolutePath() + "\"");*/
/*Process p2 = runtime.exec("\""+wkHtmlToImage.getAbsolutePath() + "\" --width "+
(IMAGE_WIDTH+EXT_WIDTH)*ZOOM_FACTOR+" --transparent --zoom "+ZOOM_FACTOR+" \"" + input.getAbsolutePath() +
"\" \"" + outputExt.getAbsolutePath() + "\"");*/
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
index 60f8ca72..76b500f5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/InfoPane.java
@@ -17,6 +17,8 @@ public abstract class InfoPane extends Gui {
this.manager = manager;
}
+ public void reset() {}
+
public void tick() {}
public abstract void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX,
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
index 2bba6426..4938770d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/infopanes/SettingsInfoPane.java
@@ -1,19 +1,29 @@
package io.github.moulberry.notenoughupdates.infopanes;
+import io.github.moulberry.notenoughupdates.BetterContainers;
import io.github.moulberry.notenoughupdates.NEUManager;
import io.github.moulberry.notenoughupdates.NEUOverlay;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.itemeditor.GuiElementTextField;
import io.github.moulberry.notenoughupdates.options.Options;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import scala.tools.cmd.Spec;
import java.awt.*;
+import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -25,6 +35,11 @@ import static io.github.moulberry.notenoughupdates.GuiTextures.*;
public class SettingsInfoPane extends InfoPane {
+ private int currentCategory = Options.CAT_ALL;
+ private final String[] CATEGORY_NAMES = {"All", "Misc", "Features", "Sliders", "Colours"};
+
+ private GuiElementTextField searchBar = new GuiElementTextField("", 0);
+
private final Map<Options.Option<?>, GuiElementTextField> textConfigMap = new HashMap<>();
private int page = 0;
private int maxPages = 1;
@@ -33,19 +48,60 @@ public class SettingsInfoPane extends InfoPane {
private int clickedSliderX = 0;
private float clickedSliderMult = 0;
+ private static final int colourEditorBG = new Color(80, 80, 80, 220).getRGB();
+ private static ResourceLocation colourPickerLocation = new ResourceLocation("notenoughupdates:dynamic/colourpicker");
+ private static ResourceLocation colourPickerBarValueLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickervalue");
+ private static ResourceLocation colourPickerBarOpacityLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickeropacity");
+
+ private GuiElementTextField hexField = new GuiElementTextField("",
+ GuiElementTextField.SCALE_TEXT | GuiElementTextField.FORCE_CAPS | GuiElementTextField.NO_SPACE);
+ private ColourEditor activeColourEditor = null;
+
+ private class ColourEditor {
+ public int x;
+ public int y;
+ public Options.Option<String> option;
+ public String special;
+
+ public ColourEditor(int x, int y, Options.Option<String> option, String special) {
+ this.x = x;
+ this.y = y;
+ this.option = option;
+ this.special = special;
+ }
+ }
+
public SettingsInfoPane(NEUOverlay overlay, NEUManager manager) {
super(overlay, manager);
}
- public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledresolution, int mouseX,
+ public void reset() {
+ textConfigMap.clear();
+ activeColourEditor = null;
+ hexField.otherComponentClick();
+ }
+
+ private void showColourEditor(int mouseX, int mouseY, Options.Option<String> option, String special) {
+ activeColourEditor = new ColourEditor(mouseX, mouseY, option, special);
+ hexField.otherComponentClick();
+ }
+
+ public void render(int width, int height, Color bg, Color fg, ScaledResolution scaledResolution, int mouseX,
int mouseY) {
+ Utils.pushGuiScale(2);
+
+ int widthN = Utils.peekGuiScale().getScaledWidth();
+ int heightN = Utils.peekGuiScale().getScaledHeight();
+ int mouseXN = Mouse.getX() * widthN / Minecraft.getMinecraft().displayWidth;
+ int mouseYN = heightN - Mouse.getY() * heightN / Minecraft.getMinecraft().displayHeight - 1;
+
FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
- int paneWidth = (int)(width/3*overlay.getWidthMult());
- int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
+ int paneWidth = (int)(widthN/3*overlay.getWidthMult());
+ int rightSide = (int)(widthN*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- this.renderDefaultBackground(width, height, bg);
+ this.renderDefaultBackground(widthN, heightN, bg);
if(page > maxPages-1) page = maxPages-1;
if(page < 0) page = 0;
@@ -53,6 +109,29 @@ public class SettingsInfoPane extends InfoPane {
overlay.renderNavElement(leftSide+overlay.getBoxPadding(), rightSide-overlay.getBoxPadding(),
maxPages,page+1,"Settings: ");
+ int area = rightSide-leftSide-overlay.getBoxPadding()*2;
+ int categoryArea = (area-3*4)/5;
+ int ySize = overlay.getSearchBarYSize();
+ int yStartCat = overlay.getBoxPadding()+overlay.getSearchBarYSize()+3;
+ for(int i=0; i<5; i++) {
+ boolean pressed = currentCategory == i;
+ drawRect(leftSide+overlay.getBoxPadding()+i*(categoryArea+3), yStartCat,
+ leftSide+overlay.getBoxPadding()+i*(categoryArea+3)+categoryArea, yStartCat+ySize, fg.getRGB());
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(rightarrow_overlay);
+ Utils.drawTexturedRect(leftSide+overlay.getBoxPadding()+i*(categoryArea+3),
+ yStartCat, categoryArea, ySize, pressed?0:1, pressed?1:0, pressed?0:1, pressed?1:0, GL11.GL_NEAREST);
+
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.BOLD+CATEGORY_NAMES[i],
+ Minecraft.getMinecraft().fontRendererObj,
+ leftSide+overlay.getBoxPadding()+i*(categoryArea+3)+categoryArea/2f,
+ yStartCat+ySize/2f, false, categoryArea-6, 0);
+ }
+
+ searchBar.setSize(area-5, ySize);
+ searchBar.setMaxStringLength(45);
+ searchBar.render(leftSide+overlay.getBoxPadding()+1, overlay.getBoxPadding()+overlay.getSearchBarYSize()*2+7);
+
AtomicReference<List<String>> textToDisplay = new AtomicReference<>(null);
AtomicReference<GuiElementTextField> tfTop = new AtomicReference<>();
AtomicInteger tfTopX = new AtomicInteger();
@@ -61,14 +140,22 @@ public class SettingsInfoPane extends InfoPane {
public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button) {
float mult = tileWidth/90f;
- drawRect(x, y, x+tileWidth, y+tileHeight, fg.getRGB());
+ drawRect(x+2, y+2, x+tileWidth-2, y+tileHeight-2, fg.getRGB());
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(setting_border);
+ GlStateManager.color(1, 1, 1, 1);
+
+ Utils.drawTexturedRect(x, y, tileWidth, 5, 0, 1, 0, 5/75f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(x, y+tileHeight-5, tileWidth, 5, 0, 1, 70/75f, 1, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(x, y+5, tileWidth, tileHeight-10, 0, 1, 5/75f, 70/75f, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(x+5, y, tileWidth-10, tileHeight, 5/100f, 95/100f, 0, 1, GL11.GL_NEAREST);
if(manager.config.hideApiKey.value && option==manager.config.apiKey) return;
if(option == null) {
Utils.renderStringTrimWidth(button.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult),
tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3,
- 2f/scaledresolution.getScaleFactor());
+ 2f/Utils.peekGuiScale().getScaleFactor());
GlStateManager.color(1f, 1f, 1f, 1f);
Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex);
@@ -78,8 +165,8 @@ public class SettingsInfoPane extends InfoPane {
Utils.drawTexturedRect(x + tileWidth/2f + (int) (19 * mult), y + tileHeight - (int) (19 * mult), (int) (14 * mult), (int) (14 * mult));
GlStateManager.bindTexture(0);
- if (mouseX > x + tileWidth / 2 + (int) (19 * mult) && mouseX < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) {
- if (mouseY > y + tileHeight - (int) (19 * mult) && mouseY < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) {
+ if (mouseXN > x + tileWidth / 2 + (int) (19 * mult) && mouseXN < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) {
+ if (mouseYN > y + tileHeight - (int) (19 * mult) && mouseYN < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) {
List<String> textLines = new ArrayList<>();
textLines.add(button.displayName);
textLines.add(EnumChatFormatting.GRAY + button.desc);
@@ -91,7 +178,7 @@ public class SettingsInfoPane extends InfoPane {
Utils.renderStringTrimWidth(option.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult),
tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3,
- 2f/scaledresolution.getScaleFactor());
+ 2f/Utils.peekGuiScale().getScaleFactor());
if(option.value instanceof Boolean) {
GlStateManager.color(1f, 1f, 1f, 1f);
@@ -102,8 +189,8 @@ public class SettingsInfoPane extends InfoPane {
Utils.drawTexturedRect(x + tileWidth/2f + (int) (19 * mult), y + tileHeight - (int) (19 * mult), (int) (14 * mult), (int) (14 * mult));
GlStateManager.bindTexture(0);
- if (mouseX > x + tileWidth / 2 + (int) (19 * mult) && mouseX < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) {
- if (mouseY > y + tileHeight - (int) (19 * mult) && mouseY < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) {
+ if (mouseXN > x + tileWidth / 2 + (int) (19 * mult) && mouseXN < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) {
+ if (mouseYN > y + tileHeight - (int) (19 * mult) && mouseYN < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) {
List<String> textLines = new ArrayList<>();
textLines.add(option.displayName);
textLines.add(EnumChatFormatting.GRAY + option.desc);
@@ -115,6 +202,7 @@ public class SettingsInfoPane extends InfoPane {
textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value),
GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE | GuiElementTextField.SCALE_TEXT));
}
+
GuiElementTextField tf = textConfigMap.get(option);
if(tf.getText().trim().endsWith(".0")) {
tf.setText(tf.getText().trim().substring(0, tf.getText().trim().length()-2));
@@ -146,18 +234,46 @@ public class SettingsInfoPane extends InfoPane {
Utils.drawTexturedRect(x+1*mult+(float)(54*sliderAmount*mult), y + tileHeight - 20*mult,
8*mult, 16*mult);
} else {
- if(!textConfigMap.containsKey(option)) {
- textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
- }
- GuiElementTextField tf = textConfigMap.get(option);
- if(tf.getFocus()) {
- tf.setSize(Math.max(tileWidth-(int)(20*mult), fr.getStringWidth(tf.getText())+10), (int)(16*mult));
- tfTop.set(tf);
- tfTopX.set(x+(int)(10*mult));
- tfTopY.set(y+tileHeight-(int)(20*mult));
+ if((option.flags & Options.FLAG_COLOUR) != 0) {
+ Utils.renderStringTrimWidth(option.displayName, fr, true, x+(int)(8*mult), y+(int)(8*mult),
+ tileWidth-(int)(16*mult), new Color(100,255,150).getRGB(), 3,
+ 2f/Utils.peekGuiScale().getScaleFactor());
+
+ Color c = new Color(SpecialColour.specialToChromaRGB((String)option.value));
+ GlStateManager.color(
+ Math.min(1f, c.getRed()/255f),
+ Math.min(1f, c.getGreen()/255f),
+ Math.min(1f, c.getBlue()/255f), 1f);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(button_white);
+ Utils.drawTexturedRect(x + tileWidth/2f - (int) (32 * mult), y + tileHeight - (int) (20 * mult), (int) (48 * mult), (int) (16 * mult));
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(help);
+ Utils.drawTexturedRect(x + tileWidth/2f + (int) (19 * mult), y + tileHeight - (int) (19 * mult), (int) (14 * mult), (int) (14 * mult));
+ GlStateManager.bindTexture(0);
+
+ if (mouseXN > x + tileWidth / 2 + (int) (19 * mult) && mouseXN < x + tileWidth / 2 + (int) (19 * mult) + (int) (14 * mult)) {
+ if (mouseYN > y + tileHeight - (int) (19 * mult) && mouseYN < y + tileHeight - (int) (19 * mult) + (int) (14 * mult)) {
+ List<String> textLines = new ArrayList<>();
+ textLines.add(option.displayName);
+ textLines.add(EnumChatFormatting.GRAY + option.desc);
+ textToDisplay.set(textLines);
+ }
+ }
} else {
- tf.setSize(tileWidth-(int)(20*mult), (int)(16*mult));
- tf.render(x+(int)(10*mult), y+tileHeight-(int)(20*mult));
+ if(!textConfigMap.containsKey(option)) {
+ textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ }
+ GuiElementTextField tf = textConfigMap.get(option);
+ if(tf.getFocus()) {
+ tf.setSize(Math.max(tileWidth-(int)(20*mult), fr.getStringWidth(tf.getText())+10), (int)(16*mult));
+ tfTop.set(tf);
+ tfTopX.set(x+(int)(10*mult));
+ tfTopY.set(y+tileHeight-(int)(20*mult));
+ } else {
+ tf.setSize(tileWidth-(int)(20*mult), (int)(16*mult));
+ tf.render(x+(int)(10*mult), y+tileHeight-(int)(20*mult));
+ }
}
}
}
@@ -165,9 +281,142 @@ public class SettingsInfoPane extends InfoPane {
if(tfTop.get() != null) {
tfTop.get().render(tfTopX.get(), tfTopY.get());
}
+
+ if(activeColourEditor != null) {
+ Gui.drawRect(activeColourEditor.x, activeColourEditor.y, activeColourEditor.x+119, activeColourEditor.y+89, colourEditorBG);
+
+ int currentColour = SpecialColour.specialToSimpleRGB(activeColourEditor.special);
+ Color c = new Color(currentColour, true);
+ float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
+
+ BufferedImage bufferedImage = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<256; x++) {
+ for(int y=0; y<256; y++) {
+ float radius = (float) Math.sqrt(((x-128)*(x-128)+(y-128)*(y-128))/16384f);
+ float angle = (float) Math.toDegrees(Math.atan((128-x)/(y-128+1E-5))+Math.PI/2);
+ if(y < 128) angle += 180;
+ if(radius <= 1) {
+ int rgb = Color.getHSBColor(angle/360f, (float)Math.pow(radius, 1.5f), hsv[2]).getRGB();
+ bufferedImage.setRGB(x, y, rgb);
+ }
+ }
+ }
+
+ BufferedImage bufferedImageValue = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<10; x++) {
+ for(int y=0; y<64; y++) {
+ if((x == 0 || x == 9) && (y == 0 || y == 63)) continue;
+
+ int rgb = Color.getHSBColor(hsv[0], hsv[1], (64-y)/64f).getRGB();
+ bufferedImageValue.setRGB(x, y, rgb);
+ }
+ }
+
+ BufferedImage bufferedImageOpacity = new BufferedImage(10, 64, BufferedImage.TYPE_INT_ARGB);
+ for(int x=0; x<10; x++) {
+ for(int y=0; y<64; y++) {
+ if((x == 0 || x == 9) && (y == 0 || y == 63)) continue;
+
+ int rgb = (currentColour & 0x00FFFFFF) | (Math.min(255, (64-y)*4) << 24);
+ bufferedImageOpacity.setRGB(x, y, rgb);
+ }
+ }
+
+ float selradius = (float) Math.pow(hsv[1], 1/1.5f)*32;
+ int selx = (int)(Math.cos(Math.toRadians(hsv[0]*360))*selradius);
+ int sely = (int)(Math.sin(Math.toRadians(hsv[0]*360))*selradius);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar_alpha);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarValueLocation, new DynamicTexture(bufferedImageValue));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarValueLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerBarOpacityLocation, new DynamicTexture(bufferedImageOpacity));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerBarOpacityLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ int chromaSpeed = SpecialColour.getSpeed(activeColourEditor.special);
+ int currentColourChroma = SpecialColour.specialToChromaRGB(activeColourEditor.special);
+ Color cChroma = new Color(currentColourChroma, true);
+ float hsvChroma[] = Color.RGBtoHSB(cChroma.getRed(), cChroma.getGreen(), cChroma.getBlue(), null);
+
+ if(chromaSpeed > 0) {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5+1, activeColourEditor.y+5+1,
+ activeColourEditor.x+5+64+5+10+5+10+5+10-1, activeColourEditor.y+5+64-1,
+ Color.HSBtoRGB(hsvChroma[0], 0.8f, 0.8f));
+ } else {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5+1, activeColourEditor.y+5+27+1,
+ activeColourEditor.x+5+64+5+10+5+10+5+10-1, activeColourEditor.y+5+37-1,
+ Color.HSBtoRGB((hsvChroma[0]+(System.currentTimeMillis()-SpecialColour.startTime)/1000f)%1, 0.8f, 0.8f));
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_bar);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+
+ if(chromaSpeed > 0) {
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5+10+5, activeColourEditor.y+5, 10, 64, GL11.GL_NEAREST);
+ } else {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_chroma);
+ Utils.drawTexturedRect(activeColourEditor.x+5+64+5+10+5+10+5, activeColourEditor.y+5+27, 10, 10, GL11.GL_NEAREST);
+ }
+
+ Gui.drawRect(activeColourEditor.x+5+64+5, activeColourEditor.y+5+64-(int)(64*hsv[2]),
+ activeColourEditor.x+5+64+5+10, activeColourEditor.y+5+64-(int)(64*hsv[2])+1, 0xFF000000);
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5, activeColourEditor.y+5+64-c.getAlpha()/4,
+ activeColourEditor.x+5+64+5+10+5+10, activeColourEditor.y+5+64-c.getAlpha()/4-1, 0xFF000000);
+ if(chromaSpeed > 0) {
+ Gui.drawRect(activeColourEditor.x+5+64+5+10+5+10+5,
+ activeColourEditor.y+5+64-(int)(chromaSpeed/255f*64),
+ activeColourEditor.x+5+64+5+10+5+10+5+10,
+ activeColourEditor.y+5+64-(int)(chromaSpeed/255f*64)+1, 0xFF000000);
+ }
+
+ Minecraft.getMinecraft().getTextureManager().loadTexture(colourPickerLocation, new DynamicTexture(bufferedImage));
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colourPickerLocation);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5, activeColourEditor.y+5, 64, 64, GL11.GL_NEAREST);
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(colour_selector_dot);
+ GlStateManager.color(1, 1, 1, 1);
+ Utils.drawTexturedRect(activeColourEditor.x+5+32+selx-4, activeColourEditor.y+5+32+sely-4, 8, 8, GL11.GL_NEAREST);
+
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(hsv[2]*100)+"",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+5-(Math.round(hsv[2]*100)==100?1:0), activeColourEditor.y+5+64+5+5, true, 13, -1);
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(c.getAlpha()/255f*100)+"",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+15+5, activeColourEditor.y+5+64+5+5, true, 13, -1);
+ if(chromaSpeed > 0) {
+ Utils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+(int)SpecialColour.getSecondsForSpeed(chromaSpeed)+"s",
+ Minecraft.getMinecraft().fontRendererObj,
+ activeColourEditor.x+5+64+5+30+6, activeColourEditor.y+5+64+5+5, true, 13, -1);
+ }
+
+ hexField.setSize(48, 10);
+ if(!hexField.getFocus()) hexField.setText(Integer.toHexString(c.getRGB() & 0xFFFFFF).toUpperCase());
+
+ StringBuilder sb = new StringBuilder(EnumChatFormatting.GRAY+"#");
+ for(int i=0; i<6-hexField.getText().length(); i++) {
+ sb.append("0");
+ }
+ sb.append(EnumChatFormatting.WHITE);
+
+ hexField.setPrependText(sb.toString());
+ hexField.render(activeColourEditor.x+5+8, activeColourEditor.y+5+64+5);
+ }
+
if(textToDisplay.get() != null) {
- Utils.drawHoveringText(textToDisplay.get(), mouseX, mouseY, width, height, 200, fr);
+ Utils.drawHoveringText(textToDisplay.get(), mouseXN, mouseYN, widthN, heightN, 200, fr);
}
+
+ Utils.pushGuiScale(-1);
}
private void onTextfieldChange(GuiElementTextField tf, Options.Option<?> option) {
@@ -175,6 +424,7 @@ public class SettingsInfoPane extends InfoPane {
tf.setCustomBorderColour(-1);
option.setValue(tf.getText());
overlay.redrawItems();
+ BetterContainers.reset();
} catch(Exception e) {
tf.setCustomBorderColour(Color.RED.getRGB());
}
@@ -185,28 +435,146 @@ public class SettingsInfoPane extends InfoPane {
for(GuiElementTextField tf : textConfigMap.values()) {
tf.otherComponentClick();
}
+ activeColourEditor = null;
+ hexField.otherComponentClick();
+ searchBar.otherComponentClick();
}
public void mouseInput(int width, int height, int mouseX, int mouseY, boolean mouseDown) {
+ Utils.pushGuiScale(2);
+
+ int widthN = Utils.peekGuiScale().getScaledWidth();
+ int heightN = Utils.peekGuiScale().getScaledHeight();
+ int mouseXN = Mouse.getX() * widthN / Minecraft.getMinecraft().displayWidth;
+ int mouseYN = heightN - Mouse.getY() * heightN / Minecraft.getMinecraft().displayHeight - 1;
+
+ int paneWidth = (int)(widthN/3*overlay.getWidthMult());
+ int rightSide = (int)(widthN*overlay.getInfoPaneOffsetFactor());
+ int leftSide = rightSide - paneWidth;
+
+ int area = rightSide-leftSide-overlay.getBoxPadding()*2;
+ int categoryArea = (area-3*4)/5;
+ int ySize = overlay.getSearchBarYSize();
+ int yStartCat = overlay.getBoxPadding()+overlay.getSearchBarYSize()+3;
+ for(int i=0; i<5; i++) {
+ if(mouseDown && mouseXN > leftSide + overlay.getBoxPadding() + i * (categoryArea + 3) &&
+ mouseXN < leftSide + overlay.getBoxPadding() + i * (categoryArea + 3) + categoryArea &&
+ mouseYN > yStartCat && mouseYN < yStartCat + ySize) {
+ currentCategory = i;
+ searchBar.otherComponentClick();
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+
+ if(mouseDown) {
+ if(mouseXN > leftSide+overlay.getBoxPadding() && mouseXN < leftSide+overlay.getBoxPadding()+area-3) {
+ if(mouseYN > overlay.getBoxPadding()+overlay.getSearchBarYSize()*2+7 &&
+ mouseYN < overlay.getBoxPadding()+overlay.getSearchBarYSize()*2+7+ySize) {
+ searchBar.mouseClicked(mouseXN, mouseYN, Mouse.getEventButton());
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+ searchBar.otherComponentClick();
+ }
+
+ if(activeColourEditor != null && (Mouse.isButtonDown(0) || Mouse.isButtonDown(1))) {
+ if(mouseXN >= activeColourEditor.x && mouseXN <= activeColourEditor.x+119) {
+ if(mouseYN >= activeColourEditor.y && mouseYN <= activeColourEditor.y+89) {
+ if(Mouse.getEventButtonState()) {
+ if(mouseXN > activeColourEditor.x+5+8 && mouseXN < activeColourEditor.x+5+8+48) {
+ if(mouseYN > activeColourEditor.y+5+64+5 && mouseYN < activeColourEditor.y+5+64+5+10) {
+ hexField.mouseClicked(mouseXN, mouseYN, Mouse.getEventButton());
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+ }
+ hexField.otherComponentClick();
+
+ int currentColour = SpecialColour.specialToSimpleRGB(activeColourEditor.special);
+ Color c = new Color(currentColour, true);
+ float[] hsv = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
+
+ int xWheel = mouseXN - activeColourEditor.x - 5;
+ int yWheel = mouseYN - activeColourEditor.y - 5;
+
+ if(xWheel > 0 && xWheel < 64) {
+ if(yWheel > 0 && yWheel < 64) {
+ float radius = (float) Math.sqrt(((xWheel-32)*(xWheel-32)+(yWheel-32)*(yWheel-32))/1024f);
+ float angle = (float) Math.toDegrees(Math.atan((32-xWheel)/(yWheel-32+1E-5))+Math.PI/2);
+ if(yWheel < 32) angle += 180;
+
+ int rgb = Color.getHSBColor(angle/360f, (float)Math.pow(Math.min(1, radius), 1.5f), hsv[2]).getRGB();
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), c.getAlpha(), rgb);
+ activeColourEditor.option.value = (String) activeColourEditor.special;
+ }
+ }
+
+ int xValue = mouseXN - (activeColourEditor.x+5+64+5);
+ int y = mouseYN - activeColourEditor.y - 5;
+
+ if(y > -5 && y <= 69) {
+ y = Math.max(0, Math.min(64, y));
+ if(xValue > 0 && xValue < 10) {
+ int rgb = Color.getHSBColor(hsv[0], hsv[1], 1-y/64f).getRGB();
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), c.getAlpha(), rgb);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+
+ int xOpacity = mouseXN - (activeColourEditor.x+5+64+5+10+5);
+
+ if(xOpacity > 0 && xOpacity < 10) {
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special),
+ 255-(int)(y/64f*255), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ }
+
+ int chromaSpeed = SpecialColour.getSpeed(activeColourEditor.special);
+
+ int xChroma = mouseXN - (activeColourEditor.x+5+64+5+10+5+10+5);
+ if(xChroma > 0 && xChroma < 10) {
+ if(chromaSpeed > 0) {
+ if(y > -5 && y <= 69) {
+ y = Math.max(0, Math.min(64, y));
+ activeColourEditor.special = SpecialColour.special(255-Math.round(y/64f*255), c.getAlpha(), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ } else if(mouseYN > activeColourEditor.y+5+27 && mouseYN < activeColourEditor.y+5+37) {
+ activeColourEditor.special = SpecialColour.special(200, c.getAlpha(), currentColour);
+ activeColourEditor.option.value = activeColourEditor.special;
+ }
+ }
+
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+ if(Mouse.getEventButtonState()) activeColourEditor = null;
+ }
iterateSettingTile(new SettingsTileConsumer() {
@Override
public void consume(int x, int y, int tileWidth, int tileHeight, Options.Option<?> option, Options.Button button) {
float mult = tileWidth/90f;
if(option == null) {
if(Mouse.getEventButtonState()) {
- if(mouseX > x+tileWidth/2-(int)(32*mult) && mouseX < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
- if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
+ if(mouseXN > x+tileWidth/2-(int)(32*mult) && mouseXN < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
+ if(mouseYN > y+tileHeight-(int)(20*mult) && mouseYN < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
button.click.run();
+ Utils.pushGuiScale(-1);
return;
}
}
}
} else if(option.value instanceof Boolean) {
if(Mouse.getEventButtonState()) {
- if(mouseX > x+tileWidth/2-(int)(32*mult) && mouseX < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
- if(mouseY > y+tileHeight-(int)(20*mult) && mouseY < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
+ if(mouseXN > x+tileWidth/2-(int)(32*mult) && mouseXN < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
+ if(mouseYN > y+tileHeight-(int)(20*mult) && mouseYN < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
((Options.Option<Boolean>)option).value = !((Boolean)option.value);
overlay.redrawItems();
+ Utils.pushGuiScale(-1);
return;
}
}
@@ -222,17 +590,19 @@ public class SettingsInfoPane extends InfoPane {
int tfY = y+tileHeight-(int)(20*mult);
int tfWidth = tf.getWidth();
int tfHeight = tf.getHeight();
- if(mouseY > tfY && mouseY < tfY+tfHeight) {
- if(mouseX > tfX && mouseX < tfX+tfWidth) {
+ if(mouseYN > tfY && mouseYN < tfY+tfHeight) {
+ if(mouseXN > tfX && mouseXN < tfX+tfWidth) {
if(Mouse.getEventButtonState()) {
- tf.mouseClicked(mouseX, mouseY, Mouse.getEventButton());
+ tf.mouseClicked(mouseXN, mouseYN, Mouse.getEventButton());
onTextfieldChange(tf, option);
+ Utils.pushGuiScale(-1);
return;
} else if(Mouse.getEventButton() == -1 && mouseDown) {
- tf.mouseClickMove(mouseX, mouseY, 0, 0); //last 2 values are unused
+ tf.mouseClickMove(mouseXN, mouseYN, 0, 0); //last 2 values are unused
+ Utils.pushGuiScale(-1);
return;
}
- } else if(clickedSlider != option && Mouse.getEventButtonState() && mouseX > x+1*mult && mouseX < x+63*mult) {
+ } else if(clickedSlider != option && Mouse.getEventButtonState() && mouseXN > x+1*mult && mouseXN < x+63*mult) {
clickedSlider = option;
clickedSliderX = x;
clickedSliderMult = mult;
@@ -243,13 +613,13 @@ public class SettingsInfoPane extends InfoPane {
float xMin = clickedSliderX+5*clickedSliderMult;
float xMax = clickedSliderX+59*clickedSliderMult;
- float sliderAmount = (mouseX - xMin)/(xMax - xMin);
+ float sliderAmount = (mouseXN - xMin)/(xMax - xMin);
sliderAmount = Math.max(0, Math.min(1, sliderAmount));
double range = option.maxValue - option.minValue;
double value = option.minValue + sliderAmount*range;
- if(range >= 10) {
+ if(range >= 10 || (option.flags & Options.FLAG_INT) != 0) {
value = Math.round(value);
} else if(range >= 1) {
value = Math.round(value*10)/10.0;
@@ -269,35 +639,48 @@ public class SettingsInfoPane extends InfoPane {
if(Mouse.getEventButtonState()) tf.otherComponentClick();
} else {
- if(!textConfigMap.containsKey(option)) {
- textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
- }
- GuiElementTextField tf = textConfigMap.get(option);
- int tfX = x+(int)(10*mult);
- int tfY = y+tileHeight-(int)(20*mult);
- int tfWidth = tf.getWidth();
- int tfHeight = tf.getHeight();
- if(mouseX > tfX && mouseX < tfX+tfWidth) {
- if(mouseY > tfY && mouseY < tfY+tfHeight) {
- if(Mouse.getEventButtonState()) {
- tf.mouseClicked(mouseX, mouseY, Mouse.getEventButton());
- onTextfieldChange(tf, option);
- return;
- } else if(Mouse.getEventButton() == -1 && mouseDown) {
- tf.mouseClickMove(mouseX, mouseY, 0, 0); //last 2 values are unused
- return;
+ if((option.flags & Options.FLAG_COLOUR) != 0) {
+ if(Mouse.getEventButtonState()) {
+ if(mouseXN > x+tileWidth/2-(int)(32*mult) && mouseXN < x+tileWidth/2-(int)(32*mult)+(int)(48*mult)) {
+ if(mouseYN > y+tileHeight-(int)(20*mult) && mouseYN < y+tileHeight-(int)(20*mult)+(int)(16*mult)) {
+ int editorX = (int)Math.min(mouseXN, widthN*overlay.getInfoPaneOffsetFactor()-129);
+ int editorY = Math.min(mouseYN, heightN-99);
+ showColourEditor(editorX, editorY, (Options.Option<String>) option, (String)option.value);
+ Utils.pushGuiScale(-1);
+ return;
+ }
}
}
+ } else {
+ if(!textConfigMap.containsKey(option)) {
+ textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ }
+ GuiElementTextField tf = textConfigMap.get(option);
+ int tfX = x+(int)(10*mult);
+ int tfY = y+tileHeight-(int)(20*mult);
+ int tfWidth = tf.getWidth();
+ int tfHeight = tf.getHeight();
+ if(mouseXN > tfX && mouseXN < tfX+tfWidth) {
+ if(mouseYN > tfY && mouseYN < tfY+tfHeight) {
+ if(Mouse.getEventButtonState()) {
+ tf.mouseClicked(mouseXN, mouseYN, Mouse.getEventButton());
+ onTextfieldChange(tf, option);
+ Utils.pushGuiScale(-1);
+ return;
+ } else if(Mouse.getEventButton() == -1 && mouseDown) {
+ tf.mouseClickMove(mouseXN, mouseYN, 0, 0); //last 2 values are unused
+ Utils.pushGuiScale(-1);
+ return;
+ }
+ }
+ }
+ if(Mouse.getEventButtonState()) tf.otherComponentClick();
}
- if(Mouse.getEventButtonState()) tf.otherComponentClick();
}
}
});
if(Mouse.getEventButtonState()) {
- int paneWidth = (int)(width/3*overlay.getWidthMult());
- int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
- int leftSide = rightSide - paneWidth;
rightSide -= overlay.getBoxPadding();
leftSide += overlay.getBoxPadding();
@@ -305,24 +688,31 @@ public class SettingsInfoPane extends InfoPane {
float maxStrLen = fr.getStringWidth(EnumChatFormatting.BOLD+"Settings: " + maxPages + "/" + maxPages);
float maxButtonXSize = (rightSide-leftSide+2 - maxStrLen*0.5f - 10)/2f;
int buttonXSize = (int)Math.min(maxButtonXSize, overlay.getSearchBarYSize()*480/160f);
- int ySize = (int)(buttonXSize/480f*160);
- int yOffset = (int)((overlay.getSearchBarYSize()-ySize)/2f);
+ int ySize2 = (int)(buttonXSize/480f*160);
+ int yOffset = (int)((overlay.getSearchBarYSize()-ySize2)/2f);
int top = overlay.getBoxPadding()+yOffset;
- if(mouseY >= top && mouseY <= top+ySize) {
+ if(mouseYN >= top && mouseYN <= top+ySize2) {
int leftPrev = leftSide-1;
- if(mouseX > leftPrev && mouseX < leftPrev+buttonXSize) { //"Previous" button
+ if(mouseXN > leftPrev && mouseXN < leftPrev+buttonXSize) { //"Previous" button
page--;
}
int leftNext = rightSide+1-buttonXSize;
- if(mouseX > leftNext && mouseX < leftNext+buttonXSize) { //"Next" button
+ if(mouseXN > leftNext && mouseXN < leftNext+buttonXSize) { //"Next" button
page++;
}
}
}
+
+ Utils.pushGuiScale(-1);
}
public boolean keyboardInput() {
+ if(searchBar.getFocus()) {
+ searchBar.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+ return true;
+ }
+
AtomicBoolean ret = new AtomicBoolean(false);
iterateSettingTile(new SettingsTileConsumer() {
@Override
@@ -330,7 +720,7 @@ public class SettingsInfoPane extends InfoPane {
if(option == null) return;
if(!textConfigMap.containsKey(option)) {
- textConfigMap.put(option, new GuiElementTextField(String.valueOf(option.value), 0));
+ return;
}
GuiElementTextField tf = textConfigMap.get(option);
@@ -343,6 +733,24 @@ public class SettingsInfoPane extends InfoPane {
}
}
});
+ if(activeColourEditor != null && hexField.getFocus()) {
+ String old = hexField.getText();
+
+ hexField.keyTyped(Keyboard.getEventCharacter(), Keyboard.getEventKey());
+
+ if(hexField.getText().length() > 6) {
+ hexField.setText(old);
+ } else {
+ try {
+ String text = hexField.getText().toLowerCase();
+
+ int rgb = Integer.parseInt(text, 16);
+ int alpha = (SpecialColour.specialToSimpleRGB(activeColourEditor.special) >> 24) & 0xFF;
+ activeColourEditor.special = SpecialColour.special(SpecialColour.getSpeed(activeColourEditor.special), alpha, rgb);
+ activeColourEditor.option.value = activeColourEditor.special;
+ } catch(Exception e) {};
+ }
+ }
return ret.get();
}
@@ -351,7 +759,7 @@ public class SettingsInfoPane extends InfoPane {
}
public void iterateSettingTile(SettingsTileConsumer settingsTileConsumer) {
- ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ ScaledResolution scaledresolution = Utils.pushGuiScale(2);
int width = scaledresolution.getScaledWidth();
int height = scaledresolution.getScaledHeight();
@@ -361,28 +769,64 @@ public class SettingsInfoPane extends InfoPane {
int rightSide = (int)(width*overlay.getInfoPaneOffsetFactor());
int leftSide = rightSide - paneWidth;
- int boxLeft = leftSide+overlay.getBoxPadding()-5;
- int boxRight = rightSide-overlay.getBoxPadding()+5;
+ int padding = overlay.getBoxPadding();
+
+ int boxLeft = leftSide+padding-5;
+ int boxRight = rightSide-padding+5;
- int boxBottom = height - overlay.getBoxPadding() + 5;
+ int boxBottom = height - padding + 5;
int boxWidth = boxRight-boxLeft;
int tilePadding = 7;
int tileWidth = (boxWidth-tilePadding*4)/numHorz;
int tileHeight = tileWidth*3/4;
+ int top = tilePadding+padding+overlay.getSearchBarYSize()*3+3*2;
+ int bottom = height - padding;
+ int leftover = (bottom-top)%(tileHeight+tilePadding);
+
+ top += leftover/2;
+
maxPages=1;
int currPage=0;
int x=0;
- int y=tilePadding+overlay.getBoxPadding()+overlay.getSearchBarYSize();
+ int y=top;
+ int tileCount = 0;
+ out:
for(int i=0; i<manager.config.getOptions().size()+manager.config.getButtons().size(); i++) {
- if(i!=0 && i%numHorz==0) {
+ if(i < manager.config.getButtons().size()) {
+ if(currentCategory != Options.CAT_ALL || searchBar.getText().trim().length() != 0) {
+ continue;
+ }
+ } else {
+ Options.Option<?> option = manager.config.getOptions().get(i-manager.config.getButtons().size());
+ if(searchBar.getText().trim().length() != 0) {
+ for(String s : searchBar.getText().split(" ")) {
+ s = s.replaceAll("[^A-Za-z]", "").toLowerCase();
+ boolean contains = false;
+ for(String tag : option.tags) {
+ if(tag.contains(s)) {
+ contains = true;
+ break;
+ }
+ }
+ if(!contains) {
+ continue out;
+ }
+ }
+ }
+ if(currentCategory != Options.CAT_ALL && currentCategory != option.category) {
+ continue;
+ }
+ }
+
+ if(tileCount != 0 && tileCount % numHorz == 0) {
x = 0;
y += tileHeight+tilePadding;
}
if(y + tileHeight > boxBottom) {
x=0;
- y=tilePadding+overlay.getBoxPadding()+overlay.getSearchBarYSize();
+ y=top;
currPage++;
maxPages = currPage+1;
}
@@ -398,7 +842,10 @@ public class SettingsInfoPane extends InfoPane {
}
}
+ tileCount++;
x+=tileWidth;
}
+
+ Utils.pushGuiScale(-1);
}
}
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..7b279ac9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/itemeditor/GuiElementTextField.java
@@ -32,6 +32,8 @@ public class GuiElementTextField extends GuiElement {
private int x;
private int y;
+ private String prependText = "";
+
private GuiTextField textField = new GuiTextField(0, Minecraft.getMinecraft().fontRendererObj,
0 , 0, 0, 0);
@@ -45,6 +47,10 @@ public class GuiElementTextField extends GuiElement {
this.options = options;
}
+ public void setMaxStringLength(int len) {
+ textField.setMaxStringLength(len);
+ }
+
public void setCustomBorderColour(int colour) {
this.customBorderColour = colour;
}
@@ -53,8 +59,14 @@ public class GuiElementTextField extends GuiElement {
return textField.getText();
}
+ public void setPrependText(String text) {
+ this.prependText = text;
+ }
+
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) {
@@ -113,16 +125,20 @@ public class GuiElementTextField extends GuiElement {
int extraSize = (searchBarYSize-8)/2+8;
+ String renderText = prependText + textField.getText();
+
int lineNum = Math.round(((yComp - (searchBarYSize-8)/2))/extraSize);
Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6])(?!\\u00B6)");
- String text = textField.getText();
- String textNoColour = textField.getText();
- while(true) {
- Matcher matcher = patternControlCode.matcher(text);
- if(!matcher.find() || matcher.groupCount() < 1) break;
- String code = matcher.group(1);
- text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code);
+ String text = renderText;
+ String textNoColour = renderText;
+ if((options & COLOUR) != 0) {
+ while(true) {
+ Matcher matcher = patternControlCode.matcher(text);
+ if(!matcher.find() || matcher.groupCount() < 1) break;
+ String code = matcher.group(1);
+ text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code);
+ }
}
while(true) {
Matcher matcher = patternControlCode.matcher(textNoColour);
@@ -139,20 +155,31 @@ public class GuiElementTextField extends GuiElement {
currentLine++;
}
}
+
+
String textNC = textNoColour.substring(0, cursorIndex);
int colorCodes = StringUtils.countMatches(textNC, "\u00B6");
- String line = text.substring(cursorIndex+colorCodes*2).split("\n")[0];
- String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(line, xComp-5);
+ String line = text.substring(cursorIndex+(((options & COLOUR) != 0)?colorCodes*2:0)).split("\n")[0];
+ int padding = Math.min(5, searchBarXSize-strLenNoColor(line))/2;
+ String trimmed = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(line, xComp-padding);
int linePos = strLenNoColor(trimmed);
if(linePos != strLenNoColor(line)) {
char after = line.charAt(linePos);
int trimmedWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(trimmed);
int charWidth = Minecraft.getMinecraft().fontRendererObj.getCharWidth(after);
- if(trimmedWidth + charWidth/2 < xComp-5) {
+ if(trimmedWidth + charWidth/2 < xComp-padding) {
linePos++;
}
}
cursorIndex += linePos;
+
+ int pre = Utils.cleanColour(prependText).length();
+ if(cursorIndex < pre) {
+ cursorIndex = 0;
+ } else {
+ cursorIndex -= pre;
+ }
+
return cursorIndex;
}
@@ -300,6 +327,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) {
@@ -316,7 +344,6 @@ public class GuiElementTextField extends GuiElement {
textField.setCursorPosition(pos+1);
}
}
-
}
}
@@ -333,6 +360,7 @@ public class GuiElementTextField extends GuiElement {
private void drawTextbox(int x, int y, int searchBarXSize, int searchBarYSize, int searchBarPadding,
GuiTextField textField, boolean focus) {
ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ String renderText = prependText + textField.getText();
GlStateManager.disableLighting();
@@ -342,7 +370,7 @@ public class GuiElementTextField extends GuiElement {
int paddingUnscaled = searchBarPadding/scaledresolution.getScaleFactor();
if(paddingUnscaled < 1) paddingUnscaled = 1;
- int numLines = StringUtils.countMatches(textField.getText(), "\n")+1;
+ int numLines = StringUtils.countMatches(renderText, "\n")+1;
int extraSize = (searchBarYSize-8)/2+8;
int bottomTextBox = y + searchBarYSize + extraSize*(numLines-1);
@@ -363,13 +391,15 @@ public class GuiElementTextField extends GuiElement {
//bar text
Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n])(?!\\u00B6)");
- String text = textField.getText();
- String textNoColor = textField.getText();
- while(true) {
- Matcher matcher = patternControlCode.matcher(text);
- if(!matcher.find() || matcher.groupCount() < 1) break;
- String code = matcher.group(1);
- text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code);
+ String text = renderText;
+ String textNoColor = renderText;
+ if((options & COLOUR) != 0) {
+ while(true) {
+ Matcher matcher = patternControlCode.matcher(text);
+ if(!matcher.find() || matcher.groupCount() < 1) break;
+ String code = matcher.group(1);
+ text = matcher.replaceFirst("\u00A7"+code+"\u00B6"+code);
+ }
}
while(true) {
Matcher matcher = patternControlCode.matcher(textNoColor);
@@ -378,11 +408,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,13 +427,12 @@ 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) {
- String textNCBeforeCursor = textNoColor.substring(0, textField.getCursorPosition());
+ String textNCBeforeCursor = textNoColor.substring(0, textField.getCursorPosition()+prependText.length());
int colorCodes = StringUtils.countMatches(textNCBeforeCursor, "\u00B6");
- String textBeforeCursor = text.substring(0, textField.getCursorPosition()+colorCodes*2);
+ String textBeforeCursor = text.substring(0, textField.getCursorPosition()+prependText.length()+(((options & COLOUR) != 0) ? colorCodes*2 : 0));
int numLinesBeforeCursor = StringUtils.countMatches(textBeforeCursor, "\n");
int yOff = numLinesBeforeCursor*extraSize;
@@ -406,22 +442,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()+prependText.length(), textField.getSelectionEnd()+prependText.length());
+ int rightIndex = Math.max(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length());
- int texX = 0;
+ float texX = 0;
int texY = 0;
boolean sectionSignPrev = false;
boolean bold = false;
@@ -440,9 +474,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 +490,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..da1b9ddc 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBAnchorPoint.java
@@ -22,27 +22,33 @@ public class MBAnchorPoint implements Serializable {
public AnchorPoint anchorPoint;
public Vector2f offset;
+ public boolean inventoryRelative;
public MBAnchorPoint(AnchorPoint anchorPoint, Vector2f offset) {
+ this(anchorPoint, offset, false);
+ }
+
+ public MBAnchorPoint(AnchorPoint anchorPoint, Vector2f offset, boolean inventoryRelative) {
this.anchorPoint = anchorPoint;
this.offset = offset;
+ this.inventoryRelative = inventoryRelative;
}
public static MBAnchorPoint createFromString(String str) {
- if(str == null || str.split(":").length != 3) {
+ if(str == null || str.split(":").length != 4) {
return null;
}
try {
String[] split = str.split(":");
AnchorPoint point = AnchorPoint.valueOf(split[0].toUpperCase());
- Vector2f pos = new Vector2f(Float.valueOf(split[1]), Float.valueOf(split[2]));
- return new MBAnchorPoint(point, pos);
+ Vector2f pos = new Vector2f(Float.parseFloat(split[1]), Float.parseFloat(split[2]));
+ return new MBAnchorPoint(point, pos, Boolean.parseBoolean(split[3]));
} catch(Exception e) { return null; }
}
@Override
public String toString() {
- return anchorPoint.toString() + ":" + offset.x + ":" + offset.y;
+ return anchorPoint.toString() + ":" + offset.x + ":" + offset.y + ":" + inventoryRelative;
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java
new file mode 100644
index 00000000..8f7d1bc0
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBDeserializer.java
@@ -0,0 +1,20 @@
+package io.github.moulberry.notenoughupdates.mbgui;
+
+import com.google.gson.JsonObject;
+
+import java.io.IOException;
+
+public class MBDeserializer {
+
+ public static MBGuiElement deserialize(JsonObject json) {
+ return null;
+ }
+
+ public static void serializeAndSave(MBGuiElement element, String filename) throws IOException {
+ /*JsonObject json = element.serialize();
+
+ File file = new File(NotEnoughUpdates.INSTANCE.manager.configLocation, filename+".json");
+ NotEnoughUpdates.INSTANCE.manager.writeJson(json, file);*/
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
index 56a3f42c..1ff51238 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiElement.java
@@ -9,4 +9,6 @@ public abstract class MBGuiElement {
public abstract void mouseClickOutside();
public abstract void render(float x, float y);
+ //public abstract JsonObject serialize();
+
}
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..86ff7278 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroup.java
@@ -35,8 +35,10 @@ public abstract class MBGuiGroup extends MBGuiElement {
@Override
public void mouseClick(float x, float y, int mouseX, int mouseY) {
+ Map<MBGuiElement, Vector2f> childrenPos = getChildrenPosition();
+
for(MBGuiElement child : getChildren()) {
- Vector2f childPos = childrenPosition.get(child);
+ Vector2f childPos = childrenPos.get(child);
if(mouseX > x+childPos.x && mouseX < x+childPos.x+child.getWidth()) {
if(mouseY > y+childPos.y && mouseY < y+childPos.y+child.getHeight()) {
child.mouseClick(x+childPos.x, y+childPos.y, mouseX, mouseY);
@@ -54,8 +56,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/MBGuiGroupAligned.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java
new file mode 100644
index 00000000..77a28fd5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupAligned.java
@@ -0,0 +1,67 @@
+package io.github.moulberry.notenoughupdates.mbgui;
+
+import org.lwjgl.util.vector.Vector2f;
+
+import java.util.Collection;
+import java.util.List;
+
+public abstract class MBGuiGroupAligned extends MBGuiGroup {
+
+ //Serialized
+ private List<MBGuiElement> children;
+ private boolean vertical;
+
+ public MBGuiGroupAligned(List<MBGuiElement> children, boolean vertical) {
+ this.children = children;
+ this.vertical = vertical;
+ recalculate();
+ }
+
+ public abstract int getPadding();
+
+ public Collection<MBGuiElement> getChildren() {
+ return children;
+ }
+
+ public void recalculate() {
+ for(MBGuiElement child : children) {
+ child.recalculate();
+ }
+
+ if(vertical) {
+ height = 0;
+ for(int i=0; i<children.size(); i++) {
+ MBGuiElement child = children.get(i);
+ childrenPosition.put(child, new Vector2f(0, height));
+ height += child.getHeight();
+ if(i != children.size()-1) height += getPadding();
+ }
+
+ width = 0;
+ for(MBGuiElement child : children) {
+ int childWidth = child.getWidth();
+ if(childWidth > width) {
+ width = childWidth;
+ }
+ }
+ } else {
+ width = 0;
+ for(int i=0; i<children.size(); i++) {
+ MBGuiElement child = children.get(i);
+ childrenPosition.put(child, new Vector2f(width, 0));
+ width += child.getWidth();
+ if(i != children.size()-1) width += getPadding();
+ }
+
+ height = 0;
+ for(MBGuiElement child : children) {
+ int childHeight = child.getHeight();
+ if(childHeight > height) {
+ height = childHeight;
+ }
+ }
+ }
+
+ }
+
+}
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..293fc241 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupFloating.java
@@ -1,11 +1,23 @@
package io.github.moulberry.notenoughupdates.mbgui;
+import io.github.moulberry.notenoughupdates.GuiItemRecipe;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.gui.inventory.GuiContainer;
import org.lwjgl.util.vector.Vector2f;
import java.util.*;
public class MBGuiGroupFloating extends MBGuiGroup {
+ private GuiScreen lastScreen = null;
+ private HashMap<MBGuiElement, Vector2f> childrenPositionOffset = new HashMap<>();
+
+ //Serialized
private LinkedHashMap<MBGuiElement, MBAnchorPoint> children;
public MBGuiGroupFloating(int width, int height, LinkedHashMap<MBGuiElement, MBAnchorPoint> children) {
@@ -20,7 +32,84 @@ public class MBGuiGroupFloating extends MBGuiGroup {
}
@Override
+ public Map<MBGuiElement, Vector2f> getChildrenPosition() {
+ GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
+
+ if(currentScreen instanceof GuiContainer || currentScreen instanceof GuiItemRecipe
+ || currentScreen instanceof CustomAHGui || NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+
+ if(lastScreen != currentScreen) {
+ lastScreen = currentScreen;
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ int screenWidth = scaledResolution.getScaledWidth();
+ int screenHeight = scaledResolution.getScaledHeight();
+
+ int xSize = -1;
+ int ySize = -1;
+ int guiLeft = -1;
+ int guiTop = -1;
+
+ if(currentScreen instanceof GuiContainer) {
+ GuiContainer currentContainer = (GuiContainer) currentScreen;
+
+ try {
+ xSize = (int) Utils.getField(GuiContainer.class, currentContainer, "xSize", "field_146999_f");
+ ySize = (int) Utils.getField(GuiContainer.class, currentContainer, "ySize", "field_147000_g");
+ guiLeft = (int) Utils.getField(GuiContainer.class, currentContainer, "guiLeft", "field_147003_i");
+ guiTop = (int) Utils.getField(GuiContainer.class, currentContainer, "guiTop", "field_147009_r");
+ } catch(Exception ignored) {
+ }
+ } else if(currentScreen instanceof GuiItemRecipe) {
+ xSize = ((GuiItemRecipe)currentScreen).xSize;
+ ySize = ((GuiItemRecipe)currentScreen).ySize;
+ guiLeft = ((GuiItemRecipe)currentScreen).guiLeft;
+ guiTop = ((GuiItemRecipe)currentScreen).guiTop;
+ } else if(currentScreen instanceof CustomAHGui ||
+ NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.isRenderOverAuctionView()) {
+ xSize = NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.getXSize();
+ ySize = NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.getYSize();
+ guiLeft = NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.guiLeft;
+ guiTop = NotEnoughUpdates.INSTANCE.manager.auctionManager.customAH.guiTop;
+ }
+
+ if(xSize <= 0 && ySize <= 0 && guiLeft <= 0 && guiTop <= 0) {
+ lastScreen = null;
+ return Collections.unmodifiableMap(childrenPosition);
+ }
+
+ 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.inventoryRelative) {
+ int defGuiLeft = (screenWidth - xSize) / 2;
+ int defGuiTop = (screenHeight - ySize) / 2;
+
+ childPos.x += guiLeft-defGuiLeft + (0.5f-anchorPoint.anchorPoint.x)*xSize;
+ childPos.y += guiTop-defGuiTop + (0.5f-anchorPoint.anchorPoint.y)*ySize;
+ }
+
+ childrenPositionOffset.put(child, childPos);
+ }
+ }
+ return Collections.unmodifiableMap(childrenPositionOffset);
+ } else {
+ return Collections.unmodifiableMap(childrenPosition);
+ }
+ }
+
+ @Override
public void recalculate() {
+ lastScreen = null;
+
for(MBGuiElement child : children.keySet()) {
child.recalculate();
}
@@ -30,6 +119,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.inventoryRelative) {
+ 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/mbgui/MBGuiGroupHorz.java b/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java
deleted file mode 100644
index cf477eac..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/mbgui/MBGuiGroupHorz.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.github.moulberry.notenoughupdates.mbgui;
-
-import org.lwjgl.util.vector.Vector2f;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-public abstract class MBGuiGroupHorz extends MBGuiGroup {
-
- private List<MBGuiElement> children;
-
- public MBGuiGroupHorz(List<MBGuiElement> children) {
- this.children = children;
- recalculate();
- }
-
- public abstract int getPadding();
-
- public Collection<MBGuiElement> getChildren() {
- return children;
- }
-
- public void recalculate() {
- for(MBGuiElement child : children) {
- child.recalculate();
- }
-
- width = 0;
- for(int i=0; i<children.size(); i++) {
- MBGuiElement child = children.get(i);
- childrenPosition.put(child, new Vector2f(width, 0));
- width += child.getWidth();
- if(i != children.size()-1) width += getPadding();
- }
-
- height = 0;
- for(MBGuiElement child : children) {
- int childHeight = child.getHeight();
- if(childHeight > height) {
- height = childHeight;
- }
- }
- }
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
new file mode 100644
index 00000000..8757e369
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
@@ -0,0 +1,25 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EnumPlayerModelParts;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin({EntityPlayer.class})
+public abstract class MixinEntityPlayer {
+
+ @Inject(method="isWearing", at=@At("HEAD"), cancellable = true)
+ public void isWearing(EnumPlayerModelParts part, CallbackInfoReturnable<Boolean> cir) {
+ if(part == EnumPlayerModelParts.CAPE) {
+ EntityPlayer $this = (EntityPlayer)(Object)this;
+ String uuid = $this.getUniqueID().toString().replace("-", "");
+ String cape = CapeManager.getInstance().getCape(uuid);
+ if(cape != null && !cape.equalsIgnoreCase("null")) {
+ cir.setReturnValue(false);
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java
new file mode 100644
index 00000000..1f77b9cc
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityRenderer.java
@@ -0,0 +1,72 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.CustomItemEffects;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import net.minecraft.client.renderer.EntityRenderer;
+import org.lwjgl.util.vector.Vector3f;
+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;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(EntityRenderer.class)
+public class MixinEntityRenderer {
+
+ //orientCamera
+ @ModifyVariable(method="orientCamera", at=@At(value="STORE"), ordinal = 0)
+ public double orientCamera_d0(double d0) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.x;
+ }
+ return d0;
+ }
+
+ @ModifyVariable(method="orientCamera", at=@At(value="STORE"), ordinal = 1)
+ public double orientCamera_d1(double d1) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.y;
+ }
+ return d1;
+ }
+
+ @ModifyVariable(method="orientCamera", at=@At(value="STORE"), ordinal = 2)
+ public double orientCamera_d2(double d2) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.z;
+ }
+ return d2;
+ }
+
+ //renderWorldPass
+ @ModifyVariable(method="renderWorldPass", at=@At(value="STORE"), ordinal = 0)
+ public double renderWorldPass_d0(double d0) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.x;
+ }
+ return d0;
+ }
+
+ @ModifyVariable(method="renderWorldPass", at=@At(value="STORE"), ordinal = 1)
+ public double renderWorldPass_d1(double d1) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.y;
+ }
+ return d1;
+ }
+
+ @ModifyVariable(method="renderWorldPass", at=@At(value="STORE"), ordinal = 2)
+ public double renderWorldPass_d2(double d2) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.z;
+ }
+ return d2;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java
new file mode 100644
index 00000000..bd74b44c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiChest.java
@@ -0,0 +1,52 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.BetterContainers;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.StreamerMode;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiIngame;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Team;
+import net.minecraft.util.ResourceLocation;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin({GuiChest.class})
+public class MixinGuiChest {
+
+ private static final String TARGET = "Lnet/minecraft/client/renderer/texture/TextureManager;" +
+ "bindTexture(Lnet/minecraft/util/ResourceLocation;)V";
+ @Redirect(method="drawGuiContainerBackgroundLayer", at=@At(value="INVOKE", target=TARGET))
+ public void drawGuiContainerBackgroundLayer_bindTexture(TextureManager textureManager, ResourceLocation location) {
+ BetterContainers.bindHook(textureManager, location);
+ }
+
+ private static final String TARGET_DRAWSTRING = "Lnet/minecraft/client/gui/FontRenderer;drawString(Ljava/lang/String;III)I";
+ @Redirect(method="drawGuiContainerForegroundLayer", at=@At(value="INVOKE", target = TARGET_DRAWSTRING))
+ public int drawGuiContainerForegroundLayer_drawString(FontRenderer fontRenderer, String text, int x, int y, int color) {
+ return fontRenderer.drawString(text, x, y, BetterContainers.isOverriding() ? BetterContainers.getTextColour() : color);
+ }
+
+ private static final String TARGET_SBADRAWSTRING = "Lcodes/biscuit/skyblockaddons/asm/hooks/GuiChestHook;" +
+ "drawString(Lnet/minecraft/client/gui/FontRenderer;Ljava/lang/String;III)I";
+ @Redirect(method="drawGuiContainerForegroundLayer", at=@At(value="INVOKE", target = TARGET_SBADRAWSTRING, remap = false))
+ public int drawGuiContainerForegroundLayer_SBA_drawString(FontRenderer fontRenderer, String text, int x, int y, int color) {
+ try {
+ return (int)Class.forName("codes.biscuit.skyblockaddons.asm.hooks.GuiChestHook")
+ .getDeclaredMethod("drawString", FontRenderer.class, String.class, int.class, int.class, int.class)
+ .invoke(null, fontRenderer, text, x, y, BetterContainers.isOverriding() ? BetterContainers.getTextColour() : color);
+ } catch(Exception e) {}
+ return fontRenderer.drawString(text, x, y, BetterContainers.isOverriding() ? BetterContainers.getTextColour() : color);
+ }
+
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
new file mode 100644
index 00000000..2290e4a7
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java
@@ -0,0 +1,118 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.BetterContainers;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.inventory.GuiChest;
+import net.minecraft.client.gui.inventory.GuiContainer;
+import net.minecraft.client.renderer.texture.TextureManager;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.Container;
+import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.IInventory;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.ResourceLocation;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin(GuiContainer.class)
+public abstract class MixinGuiContainer {
+
+ @Inject(method="drawSlot", at=@At("HEAD"), cancellable = true)
+ public void drawSlot(Slot slot, CallbackInfo ci) {
+ if(slot == null) return;
+
+ GuiContainer $this = (GuiContainer)(Object)this;
+ ItemStack stack = slot.getStack();
+
+ if(stack == null && System.currentTimeMillis() - BetterContainers.lastRenderMillis < 300 && $this instanceof GuiChest) {
+ Container container = ((GuiChest)$this).inventorySlots;
+ if(container instanceof ContainerChest) {
+ IInventory lower = ((ContainerChest)container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ if(slot.slotNumber < size) {
+ boolean found = false;
+ for(int index=0; index<size; index++) {
+ if(lower.getStackInSlot(index) != null) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ stack = BetterContainers.itemCache.get(slot.slotNumber);
+ }
+ }
+
+ }
+ }
+
+ if(BetterContainers.isOverriding() && !BetterContainers.shouldRenderStack(stack)) {
+ ci.cancel();
+ }
+ }
+
+ private static final String TARGET_GETSTACK = "Lnet/minecraft/inventory/Slot;getStack()Lnet/minecraft/item/ItemStack;";
+ @Redirect(method="drawSlot", at=@At(value="INVOKE", target=TARGET_GETSTACK))
+ public ItemStack drawSlot_getStack(Slot slot) {
+ GuiContainer $this = (GuiContainer)(Object)this;
+ ItemStack stack = slot.getStack();
+
+ if($this instanceof GuiChest) {
+ Container container = ((GuiChest)$this).inventorySlots;
+ if(container instanceof ContainerChest) {
+ IInventory lower = ((ContainerChest)container).getLowerChestInventory();
+ int size = lower.getSizeInventory();
+ if(slot.slotNumber >= size) {
+ return stack;
+ }
+ if(System.currentTimeMillis() - BetterContainers.lastRenderMillis < 300 && stack == null) {
+ for(int index=0; index<size; index++) {
+ if(lower.getStackInSlot(index) != null) {
+ BetterContainers.itemCache.put(slot.slotNumber, null);
+ return null;
+ }
+ }
+ return BetterContainers.itemCache.get(slot.slotNumber);
+ } else {
+ BetterContainers.itemCache.put(slot.slotNumber, stack);
+ }
+ }
+ }
+ return stack;
+ }
+
+ private static final String TARGET_CANBEHOVERED = "Lnet/minecraft/inventory/Slot;canBeHovered()Z";
+ @Redirect(method="drawScreen", at=@At(value="INVOKE", target=TARGET_CANBEHOVERED))
+ public boolean drawScreen_canBeHovered(Slot slot) {
+ if(NotEnoughUpdates.INSTANCE.manager.config.hideEmptyPanes.value &&
+ BetterContainers.isOverriding() && BetterContainers.isBlankStack(slot.getStack())) {
+ return false;
+ }
+ return slot.canBeHovered();
+ }
+
+ @Inject(method="handleMouseClick", at=@At(value="HEAD"), cancellable = true)
+ public void handleMouseClick(Slot slotIn, int slotId, int clickedButton, int clickType, CallbackInfo ci) {
+ if(slotIn != null && BetterContainers.isOverriding() && (BetterContainers.isBlankStack(slotIn.getStack()) ||
+ BetterContainers.isButtonStack(slotIn.getStack()))) {
+ System.out.println("handling click");
+ BetterContainers.clickSlot(slotIn.getSlotIndex());
+ Utils.playPressSound();
+
+ if(BetterContainers.isBlankStack(slotIn.getStack())) {
+ System.out.println("cancelling click");
+ GuiContainer $this = (GuiContainer)(Object)this;
+ $this.mc.playerController.windowClick($this.inventorySlots.windowId, slotId, 2, clickType, $this.mc.thePlayer);
+ ci.cancel();
+ }
+ }
+ }
+
+}
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/MixinItemStack.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
index 123c8cb9..34f1ea62 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
@@ -1,8 +1,12 @@
package io.github.moulberry.notenoughupdates.mixins;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
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.CallbackInfoReturnable;
@@ -17,4 +21,37 @@ public class MixinItemStack {
}
}
+ @Shadow
+ private NBTTagCompound stackTagCompound;
+
+ @Inject(method="getDisplayName",at=@At("HEAD"), cancellable=true)
+ public void getDisplayName(CallbackInfoReturnable<String> returnable) {
+ try {
+ String customName = NotEnoughUpdates.INSTANCE.manager.itemRenameJson
+ .get(stackTagCompound.getCompoundTag("ExtraAttributes").getString("uuid")).getAsString();
+ if(customName != null && !customName.equals("")) {
+ String prefix = EnumChatFormatting.RESET.toString();
+ if (stackTagCompound != null && stackTagCompound.hasKey("display", 10)) {
+ NBTTagCompound nbttagcompound = stackTagCompound.getCompoundTag("display");
+
+ if (nbttagcompound.hasKey("Name", 8)) {
+ String name = nbttagcompound.getString("Name");
+ char[] chars = name.toCharArray();
+
+ int i;
+ for(i=0; i<chars.length; i+=2) {
+ if(chars[i] != '\u00a7'){
+ break;
+ }
+ }
+
+ prefix = name.substring(0, i);
+ }
+ }
+ returnable.setReturnValue(prefix+customName);
+ }
+ } catch(Exception e) { }
+ }
+
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
new file mode 100644
index 00000000..0bb84f44
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
@@ -0,0 +1,29 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.CustomItemEffects;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.StreamerMode;
+import net.minecraft.client.network.NetHandlerPlayClient;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Team;
+import org.lwjgl.util.vector.Vector3f;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Redirect;
+
+@Mixin(NetHandlerPlayClient.class)
+public class MixinNetHandlerPlayClient {
+
+ private static final String TARGET = "Lnet/minecraft/entity/player/EntityPlayer;" +
+ "setPositionAndRotation(DDDFF)V";
+ @Redirect(method="handlePlayerPosLook", at=@At(value="INVOKE", target=TARGET))
+ public void handlePlayerPosLook_setPositionAndRotation(EntityPlayer player, double x, double y, double z, float yaw, float pitch) {
+ if(CustomItemEffects.INSTANCE.aoteTeleportationCurr != null) {
+ CustomItemEffects.INSTANCE.aoteTeleportationMillis +=
+ Math.max(0, Math.min(300, NotEnoughUpdates.INSTANCE.manager.config.smoothAoteMillis.value));
+ }
+ player.setPositionAndRotation(x, y, z, yaw, pitch);
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java
new file mode 100644
index 00000000..2c92a0b1
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRender.java
@@ -0,0 +1,31 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import net.minecraft.client.renderer.entity.Render;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.passive.EntityBat;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(Render.class)
+public class MixinRender {
+
+ @Inject(method="bindEntityTexture", at=@At("HEAD"), cancellable = true)
+ public void bindEntityTexture(Entity entity, CallbackInfoReturnable<Boolean> cir) {
+ if(entity instanceof EntityBat && DungeonBlocks.isOverriding()) {
+ if(DungeonBlocks.bindModifiedTexture(new ResourceLocation("textures/entity/bat.png"),
+ SpecialColour.specialToChromaRGB(NotEnoughUpdates.INSTANCE.manager.config.dungChestColour.value))) {
+ cir.setReturnValue(true);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST_MIPMAP_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java
new file mode 100644
index 00000000..fc536267
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderFish.java
@@ -0,0 +1,139 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.entity.Render;
+import net.minecraft.client.renderer.entity.RenderFish;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.entity.projectile.EntityFishHook;
+import net.minecraft.init.Items;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.Vec3;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+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.Redirect;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.awt.*;
+
+@Mixin(RenderFish.class)
+public abstract class MixinRenderFish extends Render<EntityFishHook> {
+
+ protected MixinRenderFish(RenderManager renderManager) {
+ super(renderManager);
+ }
+
+ @Inject(method = "doRender(Lnet/minecraft/entity/projectile/EntityFishHook;DDDFF)V", at=@At(value = "HEAD"), cancellable = true)
+ public void render(EntityFishHook entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) {
+ if(!NotEnoughUpdates.INSTANCE.manager.config.rodColours.value || entity == null) return;
+
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(entity.angler.getHeldItem());
+ if (NotEnoughUpdates.INSTANCE.isOnSkyblock() && internalname != null && entity.angler != null &&
+ entity.angler.getHeldItem().getItem().equals(Items.fishing_rod)) {
+ if (!internalname.equals("GRAPPLING_HOOK") && !internalname.endsWith("_WHIP")) {
+ ci.cancel();
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate((float)x, (float)y, (float)z);
+ GlStateManager.enableRescaleNormal();
+ GlStateManager.scale(0.5F, 0.5F, 0.5F);
+ this.bindEntityTexture(entity);
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ GlStateManager.rotate(180.0F - this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
+ GlStateManager.rotate(-this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX_NORMAL);
+ worldrenderer.pos(-0.5D, -0.5D, 0.0D).tex(0.0625D, 0.1875D).normal(0.0F, 1.0F, 0.0F).endVertex();
+ worldrenderer.pos(0.5D, -0.5D, 0.0D).tex(0.125D, 0.1875D).normal(0.0F, 1.0F, 0.0F).endVertex();
+ worldrenderer.pos(0.5D, 0.5D, 0.0D).tex(0.125D, 0.125D).normal(0.0F, 1.0F, 0.0F).endVertex();
+ worldrenderer.pos(-0.5D, 0.5D, 0.0D).tex(0.0625D, 0.125D).normal(0.0F, 1.0F, 0.0F).endVertex();
+ tessellator.draw();
+ GlStateManager.disableRescaleNormal();
+ GlStateManager.popMatrix();
+
+ double playerVecX;
+ double playerVecY;
+ double playerVecZ;
+ double startY;
+ if(this.renderManager.options.thirdPersonView == 0 && entity.angler == Minecraft.getMinecraft().thePlayer) {
+ float f7 = entity.angler.getSwingProgress(partialTicks);
+ float sqrtSinSwing = MathHelper.sin(MathHelper.sqrt_float(f7) * (float)Math.PI);
+
+ double decimalFov = (this.renderManager.options.fovSetting / 110.0D);
+ Vec3 fppOffset = new Vec3((-decimalFov + (decimalFov / 2.5) - (decimalFov / 8)) + 0.025, -0.045D * (this.renderManager.options.fovSetting / 100.0D), 0.4D);
+ fppOffset = fppOffset.rotatePitch(-mathLerp(partialTicks, entity.angler.prevRotationPitch, entity.angler.rotationPitch) * ((float)Math.PI / 180.0F));
+ fppOffset = fppOffset.rotateYaw(-mathLerp(partialTicks, entity.angler.prevRotationYaw, entity.angler.rotationYaw) * ((float)Math.PI / 180.0F));
+ fppOffset = fppOffset.rotateYaw(sqrtSinSwing * 0.5F);
+ fppOffset = fppOffset.rotatePitch(-sqrtSinSwing * 0.7F);
+
+ playerVecX = entity.angler.prevPosX + (entity.angler.posX - entity.angler.prevPosX) * (double)partialTicks + fppOffset.xCoord;
+ playerVecY = entity.angler.prevPosY + (entity.angler.posY - entity.angler.prevPosY) * (double)partialTicks + fppOffset.yCoord;
+ playerVecZ = entity.angler.prevPosZ + (entity.angler.posZ - entity.angler.prevPosZ) * (double)partialTicks + fppOffset.zCoord;
+ startY = entity.angler.getEyeHeight();
+ } else {
+ float angle = (entity.angler.prevRenderYawOffset + (entity.angler.renderYawOffset - entity.angler.prevRenderYawOffset) * partialTicks) * (float)Math.PI / 180.0F;
+ double d4 = MathHelper.sin(angle);
+ double d6 = MathHelper.cos(angle);
+ playerVecX = entity.angler.prevPosX + (entity.angler.posX - entity.angler.prevPosX) * (double)partialTicks - d6 * 0.35D - d4 * 0.8D;
+ playerVecY = entity.angler.prevPosY + entity.angler.getEyeHeight() + (entity.angler.posY - entity.angler.prevPosY) * (double)partialTicks - 0.45D;
+ playerVecZ = entity.angler.prevPosZ + (entity.angler.posZ - entity.angler.prevPosZ) * (double)partialTicks - d4 * 0.35D + d6 * 0.8D;
+ startY = entity.angler.isSneaking() ? -0.1875D : 0.0D;
+ }
+
+ double d13 = entity.prevPosX + (entity.posX - entity.prevPosX) * (double)partialTicks;
+ double d5 = entity.prevPosY + (entity.posY - entity.prevPosY) * (double)partialTicks + 0.25D;
+ double d7 = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * (double)partialTicks;
+ double d9 = (double)((float)(playerVecX - d13));
+ double d11 = (double)((float)(playerVecY - d5)) + startY;
+ double d12 = (double)((float)(playerVecZ - d7));
+ GlStateManager.disableTexture2D();
+ 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);
+ worldrenderer.begin(3, DefaultVertexFormats.POSITION_COLOR);
+
+ String specialColour;
+ if (entity.angler.getUniqueID().equals(Minecraft.getMinecraft().thePlayer.getUniqueID())) {
+ specialColour = NotEnoughUpdates.INSTANCE.manager.config.selfRodLineColour.value;
+ } else {
+ specialColour = NotEnoughUpdates.INSTANCE.manager.config.otherRodLineColour.value;
+ }
+ int colourI = SpecialColour.specialToChromaRGB(specialColour);
+
+ for (int l = 0; l <= 16; ++l) {
+ if(SpecialColour.getSpeed(specialColour) > 0) { //has chroma
+ colourI = SpecialColour.rotateHue(colourI, 10);
+ }
+ Color colour = new Color(colourI, true);
+
+ float f10 = (float)l / 16.0F;
+ worldrenderer.pos(x + d9 * (double)f10, y + d11 * (double)(f10 * f10 + f10) * 0.5D + 0.25D, z + d12 * (double)f10)
+ .color(colour.getRed(), colour.getGreen(), colour.getBlue(), colour.getAlpha()).endVertex();
+ }
+
+ tessellator.draw();
+ GlStateManager.disableBlend();
+ GlStateManager.enableLighting();
+ GlStateManager.enableTexture2D();
+ }
+ }
+ }
+
+ private static float mathLerp(float var1, float var2, float var3) {
+ return var2 + var1 * (var3 - var2);
+ }
+
+ private static double mathLerp(double var1, double var2, double var3) {
+ return var2 + var1 * (var3 - var2);
+ }
+
+} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java
new file mode 100644
index 00000000..2bb5503b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderGlobal.java
@@ -0,0 +1,69 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.CustomItemEffects;
+import net.minecraft.client.renderer.RenderGlobal;
+import org.lwjgl.util.vector.Vector3f;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
+
+@Mixin(RenderGlobal.class)
+public class MixinRenderGlobal {
+
+ //setupTerrain
+ @ModifyVariable(method="setupTerrain", at=@At(value="STORE"), ordinal = 4)
+ public double setupTerrain_d0(double d3) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.x;
+ }
+ return d3;
+ }
+
+ @ModifyVariable(method="setupTerrain", at=@At(value="STORE"), ordinal = 5)
+ public double setupTerrain_d1(double d4) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.y;
+ }
+ return d4;
+ }
+
+ @ModifyVariable(method="setupTerrain", at=@At(value="STORE"), ordinal = 6)
+ public double setupTerrain_d2(double d5) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.z;
+ }
+ return d5;
+ }
+
+ //renderEntities
+ @ModifyVariable(method="renderEntities", at=@At(value="STORE"), ordinal = 3)
+ public double renderEntities_d0(double d3) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.x;
+ }
+ return d3;
+ }
+
+ @ModifyVariable(method="renderEntities", at=@At(value="STORE"), ordinal = 4)
+ public double renderEntities_d1(double d4) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.y;
+ }
+ return d4;
+ }
+
+ @ModifyVariable(method="renderEntities", at=@At(value="STORE"), ordinal = 5)
+ public double renderEntities_d2(double d5) {
+ Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
+ if(currentPosition != null) {
+ return currentPosition.z;
+ }
+ return d5;
+ }
+
+}
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/mixins/MixinRenderList.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java
new file mode 100644
index 00000000..ffaf9ebb
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderList.java
@@ -0,0 +1,24 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import net.minecraft.client.renderer.*;
+import net.minecraft.util.EnumWorldBlockLayer;
+import org.lwjgl.opengl.GL11;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin({RenderList.class})
+public abstract class MixinRenderList {
+
+ @Inject(method="renderChunkLayer", at=@At("HEAD"))
+ public void renderChunkLayer(EnumWorldBlockLayer layer, CallbackInfo ci) {
+ if(DungeonBlocks.textureExists()) {
+ DungeonBlocks.bindTextureIfExists();
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST_MIPMAP_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java
new file mode 100644
index 00000000..d53f62c9
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinTileEntitySpecialRenderer.java
@@ -0,0 +1,35 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
+import net.minecraft.util.ResourceLocation;
+import org.lwjgl.opengl.GL11;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin({TileEntitySpecialRenderer.class})
+public abstract class MixinTileEntitySpecialRenderer {
+
+ @Inject(method="bindTexture", at=@At("HEAD"), cancellable = true)
+ public void bindTexture(ResourceLocation location, CallbackInfo info) {
+ if(DungeonBlocks.isOverriding()) {
+ if(location.getResourcePath().equals("textures/entity/chest/normal.png") ||
+ location.getResourcePath().equals("textures/entity/chest/normal_double.png") ||
+ location.getResourcePath().equals("textures/entity/chest/trapped.png") ||
+ location.getResourcePath().equals("textures/entity/chest/trapped_double.png")) {
+ String colour = location.getResourcePath().contains("trapped") ? NotEnoughUpdates.INSTANCE.manager.config.dungTrappedChestColour.value :
+ NotEnoughUpdates.INSTANCE.manager.config.dungChestColour.value;
+ if(DungeonBlocks.bindModifiedTexture(location,
+ SpecialColour.specialToChromaRGB(colour))) {
+ info.cancel();
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST_MIPMAP_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java
new file mode 100644
index 00000000..42d81781
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinVboRenderList.java
@@ -0,0 +1,24 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
+import net.minecraft.client.renderer.VboRenderList;
+import net.minecraft.util.EnumWorldBlockLayer;
+import org.lwjgl.opengl.GL11;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+@Mixin({VboRenderList.class})
+public abstract class MixinVboRenderList {
+
+ @Inject(method="renderChunkLayer", at=@At("HEAD"))
+ public void renderChunkLayer(EnumWorldBlockLayer layer, CallbackInfo ci) {
+ if(DungeonBlocks.textureExists()) {
+ DungeonBlocks.bindTextureIfExists();
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST_MIPMAP_LINEAR);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+ }
+}
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..0aedc306 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/Options.java
@@ -1,15 +1,12 @@
package io.github.moulberry.notenoughupdates.options;
import com.google.gson.*;
+import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor;
+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;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
-import net.minecraft.util.Util;
-import net.minecraftforge.client.ClientCommandHandler;
-import net.minecraftforge.client.ForgeHooksClient;
-import org.lwjgl.util.vector.Vector2f;
import java.awt.*;
import java.io.*;
@@ -27,131 +24,330 @@ public class Options {
* variables with defaults values/etc. It works. I'm happy.
*/
+ public static final transient int FLAG_COLOUR = 0b1;
+ public static final transient int FLAG_INT = 0b10;
+
+ public static final int CAT_ALL = 0;
+ public static final int CAT_MISC = 1;
+ public static final int CAT_FEATURES = 2;
+ public static final int CAT_SLIDERS = 3;
+ public static final int CAT_COLOURS = 4;
+
public Option<Boolean> enableItemEditing = new Option(
false,
"Enable Item Editing",
true,
- "Dev Feature.");
+ "Dev Feature.", CAT_ALL);
public Option<Boolean> onlyShowOnSkyblock = new Option(
true,
"Only Show On Skyblock",
false,
- "NEU Overlay only appears when you are playing Skyblock.");
+ "NEU Overlay only appears when you are playing Skyblock.", CAT_MISC);
+ public Option<Boolean> showVanillaItems = new Option(
+ true,
+ "Show Vanilla Items",
+ false,
+ "Shows vanilla items in the itemlist.", CAT_MISC);
public Option<Boolean> hidePotionEffect = new Option(
true,
"Hide Potion Effects",
false,
- "Potion effects are hidden in the inventory GUI. Contrib: All the gamers that play on GUI AUTO");
+ "Potion effects are hidden in the inventory GUI. Contrib: All the gamers that play on GUI AUTO", CAT_MISC);
public Option<Boolean> showQuickCommands = new Option(
true,
"Quick Commands",
false,
- "Shows QuickCommandsâ„¢ above search bar.");
+ "Shows QuickCommands\u2122 above search bar.", CAT_FEATURES);
public Option<Boolean> showUpdateMsg = new Option(
true,
"Show Update Notifs",
false,
- "Shows update messages if NEU is out-of-date.");
+ "Shows update messages if NEU is out-of-date.", CAT_MISC);
public Option<Boolean> tooltipBorderColours = new Option(
true,
"Coloured Tooltip Borders",
false,
- "Makes the border of tooltips coloured. (Only NEU Tooltips)");
+ "Makes the border of tooltips coloured. (Only NEU Tooltips)", CAT_MISC);
+ public Option<Boolean> disableAhScroll = new Option(
+ false,
+ "No NeuAH Scroll",
+ false,
+ "Disables Scrolling in NeuAH", CAT_MISC);
public Option<Boolean> advancedPriceInfo = new Option(
false,
"Adv. Item Price Info",
false,
- "Shows some extra information about item prices.");
+ "Shows some extra information about item prices.", CAT_MISC);
public Option<Boolean> cacheRenderedItempane = new Option(
true,
"Cache Itempane",
false,
- "Caches the drawn itempane, drastically improving performance. Animated textures will not work.");
+ "Caches the drawn itempane, drastically improving performance. Animated textures will not work.", CAT_MISC);
public Option<Boolean> streamerMode = new Option(
false,
"Streamer Mode",
false,
- "Hides or randomises some stuff on your screen to prevent sniping.");
- public Option<Boolean> hideApiKey = new Option(
+ "Hides or randomises some stuff on your screen to prevent sniping", CAT_MISC);
+ public Option<Boolean> disableTreecapOverlay = new Option(
false,
- "Hide Apikey Setting",
+ "Disable Treecap Overlay",
+ false,
+ "Disables the treecapitator overlay effect", CAT_FEATURES);
+ public Option<Boolean> disableWandOverlay = new Option(
false,
- "Hides the Apikey setting (please try not to leak Apikey if you're recording)");
- public Option<Boolean> quickAHUpdate = new Option(
+ "Disable Builder's Wand Overlay",
+ false,
+ "Disables the builder's wand overlay effect", CAT_FEATURES);
+ public Option<Boolean> wandBlockCount = new Option(
+ true,
+ "Builder's Wand Block Count",
false,
- "NeuAH Quick Update",
+ "If true, will show how many blocks you have remaining when holding a builder's wand.", CAT_MISC);
+ public Option<Boolean> hideApiKey = new Option(
+ false,
+ "Hide Apikey Setting",
false,
- "Will instantly update the whole AH when an api update is detected (aka as fast as possible). Warning: Uses lots of data.");
+ "Hides the Apikey setting (please try not to leak Apikey if you're recording)", CAT_MISC);
public Option<Double> bgBlurFactor = new Option(
5.0,
"Background Blur",
false,
- "Changes the strength of pane background blur. 0-50.", 0, 50);
+ "Changes the strength of pane background blur. 0-50.", 0, 50, CAT_SLIDERS);
public Option<String> apiKey = new Option(
"",
"Api Key",
false,
- "Type /api new to receive key and put it here.");
+ "Type /api new to receive key and put it here.", CAT_MISC);
public Option<Boolean> autoupdate = new Option(
true,
"Automatically Update Items",
false,
- "If true, updated items will automatically download from the remote repository when you start the game. \nHIGHLY RECOMMENDED.");
+ "If true, updated items will automatically download from the remote repository when you start the game. \nHIGHLY RECOMMENDED.", CAT_MISC);
public Option<Boolean> quickcommandMousePress = new Option(
false,
"QuickCommand on Mouse Press",
false,
- "If true, quickcommands will trigger on mouse down instead of mouse up.");
+ "If true, quickcommands will trigger on mouse down instead of mouse up.", CAT_MISC);
public Option<Boolean> disableItemTabOpen = new Option(
false,
"No Tab Open",
false,
- "If True, moving your mouse to the item tab on the right side won't open the itempane.");
+ "If True, moving your mouse to the item tab on the right side won't open the itempane.", CAT_MISC);
public Option<Boolean> keepopen = new Option(
false,
"Keep Itempane Open",
false,
- "If true, the itempane will stay open after the gui is closed.");
+ "If true, the itempane will stay open after the gui is closed.", CAT_MISC);
public Option<Boolean> itemStyle = new Option(
true,
"Circular Item Style",
false,
- "Uses the circular item background style instead of the square style. Contrib: Calyps0");
+ "Uses the circular item background style instead of the square style. Contrib: Calyps0", CAT_MISC);
public Option<Boolean> hideEmptyPanes = new Option(
true,
"Hide GUI Filler Tooltips",
false,
- "Hides the tooltip of glass panes in skyblock GUIs. Contrib: ThatGravyBoat");
+ "Hides the tooltip of glass panes in skyblock GUIs. Contrib: ThatGravyBoat", CAT_MISC);
+ public Option<Boolean> dungeonProfitLore = new Option(
+ false,
+ "Dungeon Profit in Lore",
+ false,
+ "If true, will show the dungeon profit on the tooltip of the 'reward chest' instead of as a GUI.", CAT_MISC);
+ public Option<Boolean> auctionPriceInfo = new Option(
+ true,
+ "Price Info in Auction Lore",
+ false,
+ "If true, will show price information about an item inside the auction house item tooltip.", CAT_MISC);
+ public Option<Boolean> useCustomTrade = new Option(
+ true,
+ "Custom Trade",
+ false,
+ "If true, uses the custom trade window for skyblock trades.", CAT_FEATURES);
+ public Option<Boolean> invBazaarPrice = new Option(
+ false,
+ "Show Bazaar Price In Inventory",
+ false,
+ "If true, shows the bazaar price for the item you hover in your inventory.", CAT_MISC);
+ public Option<Boolean> invAuctionPrice = new Option(
+ false,
+ "Show Auction Price In Inventory",
+ false,
+ "If true, shows the auction price for the item you hover in your inventory.", CAT_MISC);
+ public Option<Boolean> dungeonBlocksEverywhere = new Option(
+ false,
+ "Show Dungeon Block Overlay Everywhere",
+ false,
+ "If true, will show the overlay for cracked bricks, etc. even when not in dungeons.", CAT_MISC);
+ public Option<Boolean> disableDungeonBlocks = new Option(
+ true,
+ "Disable the dungeon blocks feature",
+ false,
+ "If true, the dungeon block overlay will be disabled. WARNING: May cause memory/fps issues on some machines", CAT_FEATURES);
+ public Option<Boolean> slowDungeonBlocks = new Option(
+ false,
+ "Slowly Update Dungeon Block Textures",
+ false,
+ "If true, dungeon blocks will only update once every second.\n" +
+ "Use this option if you are having performance\n" +
+ "issues relating to the dungeon blocks.", CAT_MISC);
+ public Option<Boolean> missingEnchantList = new Option(
+ true,
+ "Missing Enchant List",
+ false,
+ "If true, will show enchants that are missing on an enchanted item when LSHIFT is pressed.", CAT_FEATURES);
+ public Option<Boolean> neuAuctionHouse = new Option(
+ false,
+ "NEU Auction House",
+ false,
+ "Enables the auction house which can be found using /neuah.\n" +
+ "Don't enable this option unless you use /neuah\n" +
+ "You *may* need to restart after enabling this for the auctions to download properly", CAT_FEATURES);
+ public Option<Boolean> accessoryBagOverlay = new Option(
+ true,
+ "Accessory Bag Overlay",
+ false,
+ "If true, will an overlay with useful information in your accessory bag.", CAT_FEATURES);
+ public Option<Boolean> rodColours = new Option(
+ true,
+ "Custom Rod Line Colours",
+ false,
+ "If true, will use custom colours for fishing line rods in skyblock.", CAT_FEATURES);
+ public Option<Double> paneGuiScale = new Option(
+ 0.0,
+ "Pane GUI Scale",
+ false,
+ "Changes the GUI scale of the item pane. 0 = use game default. 1-4 = scale", FLAG_INT, 0, 4, CAT_SLIDERS);
public Option<Double> paneWidthMult = new Option(
1.0,
"Pane Width",
false,
- "Changes how wide the item and info panes are. Value between 0.5-1.5.", 0.5, 1.5);
- public Option<Double> bgOpacity = new Option(
- 30.0,
- "Pane Background Opacity",
+ "Changes how wide the item and info panes are. Value between 0.5-1.5.", 0.5, 1.5, CAT_SLIDERS);
+ public Option<Double> smoothAoteMillis = new Option(
+ 175.0,
+ "Smooth AOTE Milliseconds",
false,
- "Changes the background colour opacity of item and info panes. Value between 0-255.", 0, 255);
- public Option<Double> fgOpacity = new Option(
- 255.0,
- "Item Background Opacity",
+ "How long teleporting with the AOTE takes. 0 = disable.", 0, 300, CAT_SLIDERS);
+ public Option<Double> itemHighlightOpacity = new Option(
+ 178.0,
+ "Item Highlight Opacity",
false,
- "Changes the opacity of item background. Value between 0-255.", 0, 255);
+ "Changes the opacity of item highlights. Value between 0-255.", 0, 255, CAT_SLIDERS);
public Option<Double> panePadding = new Option(
10.0,
"Pane Padding",
false,
- "Changes the padding of the panes. Value between 0-20.", 0, 20);
+ "Changes the padding of the panes. Value between 0-20.", 0, 20, CAT_SLIDERS);
public Option<Double> ahNotification = new Option(
2.0,
"AH Notification (Mins, 0 = off)",
false,
- "Minutes before AH ends to notify. 0-10.", 0, 10);
+ "Minutes before AH ends to notify. 0-10.", 0, 10, CAT_SLIDERS);
public Option<Double> tooltipBorderOpacity = new Option(
200.0,
"Coloured Tooltip Border Opacity",
false,
- "Coloured tooltips only apply to tooltips in my GUIs. Value between 0-255.", 0, 255);
+ "Coloured tooltips only apply to tooltips in my GUIs. Value between 0-255.", 0, 255, CAT_SLIDERS);
+ public Option<Double> dynamicMenuBackgroundStyle = new Option(
+ 1.0,
+ "SBMenu Background Style",
+ false,
+ "Style of the background used for the skyblock menu.", 0, 10, CAT_FEATURES);
+ public Option<Double> dynamicMenuButtonStyle = new Option(
+ 1.0,
+ "SBMenu Button Style",
+ false,
+ "Style of the buttons used for the skyblock menu.", 0, 10, CAT_FEATURES);
+ public Option<Double> dungeonWinMillis = new Option(
+ 5000.0,
+ "Dungeon Victory Screen Millis",
+ false,
+ "Changes how long the victory screen at the end of dungeons appears for. 0 = off", FLAG_INT, 0, 15000, CAT_SLIDERS);
+
+ public Option<String> itemBackgroundColour = new Option(
+ "00:255:100:100:100",
+ "Item BG Colour",
+ false,
+ "Item BG Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> itemFavouriteColour = new Option(
+ "00:255:200:150:50",
+ "Item BG Favourite Colour",
+ false,
+ "Item BG Favourite Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> paneBackgroundColour = new Option(
+ "15:6:0:0:255",
+ "Pane Background Colour",
+ false,
+ "Pane Background Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> treecapOverlayColour = new Option(
+ "00:50:64:224:208",
+ "Treecapitator Overlay Colour",
+ false,
+ "Treecapitator Overlay Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> wandOverlayColour = new Option(
+ "00:50:64:224:208",
+ "Builder's Wand Overlay Colour",
+ false,
+ "Builder's Wand Overlay Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+
+ public Option<String> dungCrackedColour = new Option(
+ "0:252:7:255:217",
+ "Dungeon Cracked Brick Colour",
+ false,
+ "Dungeon Cracked Brick Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungDispenserColour = new Option(
+ "0:255:255:76:0",
+ "Dungeon Dispenser Colour",
+ false,
+ "Dungeon Dispenser Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungLeverColour = new Option(
+ "0:252:24:249:255",
+ "Dungeon Lever Colour",
+ false,
+ "Dungeon Lever Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungTripWireColour = new Option(
+ "0:255:255:0:0",
+ "Dungeon Trip Wire Colour",
+ false,
+ "Dungeon Trip Wire Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungChestColour = new Option(
+ "0:255:0:163:36",
+ "Dungeon Chest Colour",
+ false,
+ "Dungeon Chest Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungTrappedChestColour = new Option(
+ "0:255:0:163:36",
+ "Dungeon Trapped Chest Colour",
+ false,
+ "Dungeon Trapped Chest Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> dungBatColour = new Option(
+ "0:255:12:255:0",
+ "Dungeon Bat Colour",
+ false,
+ "Dungeon Bat Colour",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> selfRodLineColour = new Option(
+ "0:255:0:0:0",
+ "Your Rod Line Colour",
+ false,
+ "Changes the colour of your rod's fishing line.\nContrib: ThatGravyBoat",
+ FLAG_COLOUR, CAT_COLOURS);
+ public Option<String> otherRodLineColour = new Option(
+ "0:255:0:0:0",
+ "Other Rod Line Colour",
+ false,
+ "Changes the colour of other players' rod's fishing line.\nContrib: ThatGravyBoat",
+ FLAG_COLOUR, CAT_COLOURS);
/**
* OPTIONS THAT DON'T SHOW IN GUI
@@ -160,52 +356,165 @@ public class Options {
false,
"Show Dev Options",
true,
- "Dev Feature. Please don't use.");
+ "Dev Feature. Please don't use.", CAT_ALL);
+ public Option<Boolean> loadedModBefore = new Option(
+ false,
+ "loadedModBefore",
+ true,
+ "loadedModBefore", CAT_ALL);
+ public Option<Boolean> customTradePrices = new Option(
+ true,
+ "Trade Item Values",
+ true,
+ "If true, shows a window with the total item value of either side", CAT_ALL);
+ public Option<Boolean> customTradePriceStyle = new Option(
+ true,
+ "Trade Prices Style",
+ true,
+ "Changes the style of the top item prices", CAT_ALL);
public Option<String> selectedCape = new Option(
"",
"Selected Cape",
true,
- "Selected Cape");
+ "Selected Cape", CAT_ALL);
public Option<Double> compareMode = new Option(
0.0,
"Compare Mode",
false,
- "Compare Mode");
+ "Compare Mode", CAT_ALL);
public Option<Double> sortMode = new Option(
0.0,
"Sort Mode",
false,
- "Sort Mode");
+ "Sort Mode", CAT_ALL);
public Option<ArrayList<Boolean>> compareAscending = new Option(
Utils.createList(true, true, true),
"Compare Ascending",
false,
- "Compare Ascending");
+ "Compare Ascending", CAT_ALL);
public Option<ArrayList<String>> favourites = new Option(
new ArrayList<String>(),
"Favourites",
false,
- "Favourites");
+ "Favourites", CAT_ALL);
public Option<Map<String, ArrayList<String>>> collectionLog = new Option(
new HashMap<String, ArrayList<String>>(),
"CollectionLog",
false,
- "CollectionLog");
+ "CollectionLog", CAT_ALL);
public Option<ArrayList<String>> quickCommands = new Option(
createDefaultQuickCommands(),
"Quick Commands",
false,
- "Quick Commands");
+ "Quick Commands", CAT_ALL);
public Option<String> overlaySearchBar = new Option(
"",
"OverlaySearchBar",
false,
- "OverlaySearchBar");
+ "OverlaySearchBar", CAT_ALL);
public Option<String> overlayQuickCommand = new Option(
"",
"OverlaySearchBar",
false,
- "OverlaySearchBar");
+ "OverlaySearchBar", CAT_ALL);
+ 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", CAT_ALL);
+
+ //Dungeon Map Options
+ public Option<Double> dmBorderSize = new Option(
+ 1.0,
+ "Border Size",
+ false,
+ "Changes the size of the map border, without changing the size of the contents\nSmall = 90x\nMedium = 120x\nLarge = 160x", CAT_ALL);
+ public Option<Double> dmRoomSize = new Option(
+ 1.0,
+ "Room Size",
+ false,
+ "Changes the size of rooms. Useful for higher dungeons with larger maps\nSmall = 12x\nMedium = 16x\nLarge = 20x\nXLarge = 24x", CAT_ALL);
+ public Option<Double> dmBorderStyle = new Option(
+ 0.0,
+ "Border Style",
+ false,
+ "Various custom borders from various talented artists.\nUse 'custom' if your texture pack has a custom border", CAT_ALL);
+ public Option<Boolean> dmEnable = new Option(
+ true,
+ "Show Dungeon Map",
+ false,
+ "Show/hide the NEU dungeon map", CAT_ALL);
+ public Option<Boolean> dmCenterPlayer = new Option(
+ false,
+ "Map Center",
+ false,
+ "Center on rooms, or center on your player", CAT_ALL);
+ public Option<Boolean> dmRotatePlayer = new Option(
+ true,
+ "Rotate with Player",
+ false,
+ "Rotate the map to face the same direction as your player", CAT_ALL);
+ public Option<Boolean> dmOrientCheck = new Option(
+ true,
+ "Orient Checkmarks",
+ false,
+ "Checkmarks will always show vertically, regardless of rotation", CAT_ALL);
+ public Option<Boolean> dmCenterCheck = new Option(
+ false,
+ "Center Checkmarks",
+ false,
+ "Checkmarks will show closer to the center of rooms", CAT_ALL);
+ public Option<Double> dmPlayerHeads = new Option(
+ 0.0,
+ "Player Icon Style",
+ false,
+ "Various player icon styles", CAT_ALL);
+ public Option<Boolean> dmPlayerInterp = new Option(
+ true,
+ "Interpolate Far Players",
+ false,
+ "Will make players far away move smoothly", CAT_ALL);
+ public Option<Double> dmCompat = new Option(
+ 0.0,
+ "OpenGL Compatibility",
+ false,
+ "Compatiblity options for people with bad computers. ONLY use this if you know what you are doing, otherwise the map will look worse", CAT_ALL);
+ public Option<String> dmBackgroundColour = new Option(
+ "00:170:75:75:75",
+ "Background Colour",
+ false,
+ "Colour of the map background. Supports opacity & chroma", FLAG_COLOUR, CAT_ALL);
+ public Option<String> dmBorderColour = new Option(
+ "00:0:0:0:0",
+ "Border Colour",
+ false,
+ "Colour of the map border. Supports opacity & chroma. Turn off custom borders to see", FLAG_COLOUR, CAT_ALL);
+ public Option<Boolean> dmChromaBorder = new Option(
+ false,
+ "Chroma Border Mode",
+ false,
+ "Applies a hue offset around the map border", CAT_ALL);
+ public Option<Double> dmBackgroundBlur = new Option(
+ 3.0,
+ "Background Blur Factor",
+ false,
+ "Changes the blur factor behind the map. Set to 0 to disable blur", CAT_ALL);
+ public Option<Double> dmCenterX = new Option(
+ 8.5,
+ "Center X (%)",
+ false,
+ "The horizontal position of the map", CAT_ALL);
+ public Option<Double> dmCenterY = new Option(
+ 15.0,
+ "Center Y (%)",
+ false,
+ "The vertical position of the map", CAT_ALL);
private ArrayList<String> createDefaultQuickCommands() {
ArrayList<String> arr = new ArrayList<>();
@@ -233,14 +542,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 +559,15 @@ 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());
+ }));
+
+
+ buttons.add(new Button("Edit Dungeon Map", "Allows you to configure the NEU dungeon map.", () -> {
+ Minecraft.getMinecraft().displayGuiScreen(new GuiDungeonMapEditor());
+ }));
}
public List<Button> getButtons() {
@@ -257,39 +577,77 @@ 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);
+ tryAddOption(showVanillaItems, options);
tryAddOption(showQuickCommands, options);
tryAddOption(hidePotionEffect, options);
tryAddOption(hideEmptyPanes, options);
- //tryAddOption(advancedPriceInfo, options);
+ tryAddOption(advancedPriceInfo, options);
tryAddOption(showUpdateMsg, options);
tryAddOption(tooltipBorderColours, options);
+ tryAddOption(disableAhScroll, options);
tryAddOption(hideApiKey, options);
tryAddOption(streamerMode, options);
- tryAddOption(quickAHUpdate, options);
+ tryAddOption(disableTreecapOverlay, options);
+ tryAddOption(disableWandOverlay, options);
+ tryAddOption(wandBlockCount, options);
tryAddOption(autoupdate, options);
tryAddOption(cacheRenderedItempane, options);
tryAddOption(itemStyle, options);
tryAddOption(keepopen, options);
tryAddOption(disableItemTabOpen, options);
+ tryAddOption(dungeonProfitLore, options);
+ tryAddOption(auctionPriceInfo, options);
+ tryAddOption(useCustomTrade, options);
+ tryAddOption(customTradePrices, options);
+ tryAddOption(customTradePriceStyle, options);
+ tryAddOption(invBazaarPrice, options);
+ tryAddOption(invAuctionPrice, options);
+ tryAddOption(dungeonBlocksEverywhere, options);
+ tryAddOption(disableDungeonBlocks, options);
+ tryAddOption(slowDungeonBlocks, options);
+ tryAddOption(missingEnchantList, options);
+ tryAddOption(accessoryBagOverlay, options);
+ tryAddOption(rodColours, options);
+ tryAddOption(neuAuctionHouse, options);
//Sliders
+ tryAddOption(paneGuiScale, options);
+ tryAddOption(smoothAoteMillis, options);
tryAddOption(bgBlurFactor, options);
- tryAddOption(paneWidthMult, options);
tryAddOption(ahNotification, options);
- tryAddOption(bgOpacity, options);
- tryAddOption(fgOpacity, options);
tryAddOption(panePadding, options);
tryAddOption(tooltipBorderOpacity, options);
+ tryAddOption(dynamicMenuBackgroundStyle, options);
+ tryAddOption(dynamicMenuButtonStyle, options);
+ tryAddOption(dungeonWinMillis, options);
//Text
tryAddOption(apiKey, options);
+ //Colour
+ tryAddOption(paneBackgroundColour, options);
+ tryAddOption(itemBackgroundColour, options);
+ tryAddOption(itemFavouriteColour, options);
+ tryAddOption(treecapOverlayColour, options);
+ tryAddOption(wandOverlayColour, options);
+ tryAddOption(selfRodLineColour, options);
+ tryAddOption(otherRodLineColour, options);
+
+ tryAddOption(dungCrackedColour, options);
+ tryAddOption(dungDispenserColour, options);
+ tryAddOption(dungLeverColour, options);
+ tryAddOption(dungTripWireColour, options);
+ tryAddOption(dungChestColour, options);
+ tryAddOption(dungTrappedChestColour, options);
+ tryAddOption(dungBatColour, options);
return options;
}
private void tryAddOption(Option<?> option, List<Option> list) {
- if(!option.secret) {// || dev.value) {
+ if (!option.secret) {// || dev.value) {
list.add(option);
}
}
@@ -300,37 +658,64 @@ public class Options {
public final transient String displayName;
public final transient boolean secret;
public final transient String desc;
+ public final transient int flags;
public final transient double minValue;
public final transient double maxValue;
+ public final transient int category;
+ public final transient ArrayList<String> tags;
- public Option(T defaultValue, String displayName, boolean secret, String desc) {
- this(defaultValue, displayName, secret, desc, 0, 100);
+ public Option(T defaultValue, String displayName, boolean secret, String desc, int category) {
+ this(defaultValue, displayName, secret, desc, 0, 0, 100, category);
}
- public Option(T defaultValue, String displayName, boolean secret, String desc, double minValue, double maxValue) {
+ public Option(T defaultValue, String displayName, boolean secret, String desc, int flags, int category) {
+ this(defaultValue, displayName, secret, desc, flags, 0, 100, category);
+ }
+
+ public Option(T defaultValue, String displayName, boolean secret, String desc, double minValue, double maxValue, int category) {
+ this(defaultValue, displayName, secret, desc, 0, minValue, maxValue, category);
+ }
+
+ public Option(T defaultValue, String displayName, boolean secret, String desc, int flags, double minValue, double maxValue, int category) {
this.value = defaultValue;
this.defaultValue = defaultValue;
this.displayName = displayName;
this.secret = secret;
this.desc = desc;
+ this.flags = flags;
this.minValue = minValue;
this.maxValue = maxValue;
+ this.category = category;
+
+ this.tags = new ArrayList<>();
+ for(String s : displayName.split(" ")) {
+ s = s.replaceAll("[^A-Za-z]", "").toLowerCase();
+ if(s.length() > 0) {
+ tags.add(s);
+ }
+ }
+ for(String s : desc.split(" ")) {
+ s = s.replaceAll("[^A-Za-z]", "").toLowerCase();
+ if(s.length() >= 4) {
+ tags.add(s);
+ }
+ }
}
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);
@@ -340,35 +725,38 @@ public class Options {
public static JsonDeserializer<Option<?>> createDeserializer() {
return (json, typeOfT, context) -> {
try {
- return new Option(context.deserialize(json, Object.class), "unknown", false, "unknown");
- } catch(Exception e) {
+ return new Option(context.deserialize(json, Object.class), "unknown", false, "unknown", CAT_ALL);
+ } catch (Exception e) {
return null;
}
};
}
public static Options loadFromFile(Gson gson, File file) throws IOException {
- InputStream in = new FileInputStream(file);
- BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
-
- Options oLoad = gson.fromJson(reader, Options.class);
- Options oDefault = new Options();
- if(oLoad == null) return oDefault;
+ try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8))) {
+ Options oLoad = gson.fromJson(reader, Options.class);
+ Options oDefault = new Options();
+ if (oLoad == null) return oDefault;
- for(Field f : Options.class.getDeclaredFields()) {
- try {
- 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;
+ for (Field f : Options.class.getDeclaredFields()) {
+ try {
+ 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(((Option<?>) f.get(oDefault)).value.getClass().isAssignableFrom(((Option<?>) f.get(oLoad)).value.getClass())) {
+ ((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;
}
- return oDefault;
}
+
public void saveToFile(Gson gson, File file) throws IOException {
file.createNewFile();
@@ -377,6 +765,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..8e3a5015
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/GuiProfileViewer.java
@@ -0,0 +1,2499 @@
+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 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.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Constants;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityOtherPlayerMP;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.renderer.*;
+import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.resources.DefaultPlayerSkin;
+import net.minecraft.client.resources.SkinManager;
+import net.minecraft.client.shader.Framebuffer;
+import net.minecraft.client.shader.Shader;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EnumPlayerModelParts;
+import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.*;
+import net.minecraft.util.*;
+import org.apache.commons.lang3.text.WordUtils;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.input.Mouse;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL14;
+import org.lwjgl.opengl.GL20;
+
+import java.awt.*;
+import java.io.IOException;
+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");
+ public static final ResourceLocation icons = new ResourceLocation("textures/gui/icons.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) && profileId != null) {
+ 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 = Constants.PETS;
+ if(petsJson == null) return;
+
+ String location = null;
+ JsonObject status = profile.getPlayerStatus();
+ if(status != null && status.has("mode")) {
+ location = status.get("mode").getAsString();
+ }
+
+ backgroundRotation += (currentTime - lastTime)/400f;
+ backgroundRotation %= 360;
+
+ String panoramaIdentifier = "day";
+ if(SBInfo.getInstance().currentTimeDate != null) {
+ if(SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
+ panoramaIdentifier = "night";
+ }
+ }
+
+ JsonArray pets = petsInfo.get("pets").getAsJsonArray();
+ if(sortedPets == null) {
+ sortedPets = new ArrayList<>();
+ sortedPetsStack = new ArrayList<>();
+ for(int i=0; i<pets.size(); i++) {
+ sortedPets.add(pets.get(i).getAsJsonObject());
+ }
+ sortedPets.sort((pet1, pet2) -> {
+ String tier1 = pet1.get("tier").getAsString();
+ String tierNum1 = 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").isJsonNull() && 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 = Constants.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);
+
+ if(armorItems == null) {
+ armorItems = new ItemStack[4];
+ JsonArray armor = Utils.getElement(inventoryInfo, "inv_armor").getAsJsonArray();
+ for(int i=0; i<armor.size(); i++) {
+ if(armor.get(i) == null || !armor.get(i).isJsonObject()) continue;
+ armorItems[i] = NotEnoughUpdates.INSTANCE.manager.jsonToStack(armor.get(i).getAsJsonObject(), false);
+ }
+ }
+
+ for(int i=0; i<armorItems.length; i++) {
+ ItemStack stack = armorItems[i];
+ if(stack != null) {
+ Utils.drawItemStack(stack, guiLeft+173, guiTop+67-18*i);
+ if(stack != fillerStack) {
+ if(mouseX >= guiLeft+173-1 && mouseX <= guiLeft+173+16+1) {
+ if(mouseY >= guiTop+67-18*i-1 && mouseY <= guiTop+67-18*i+16+1) {
+ tooltipToDisplay = stack.getTooltip(Minecraft.getMinecraft().thePlayer,
+ Minecraft.getMinecraft().gameSettings.advancedItemTooltips);
+ }
+ }
+ }
+ }
+ }
+
+ ItemStack[][][] inventories = getItemsForInventory(inventoryInfo, 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(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 totalTrueSkillLVL = 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;
+ if(entry.getKey().contains("carpentry")) continue;
+ if(entry.getKey().contains("catacombs")) continue;
+
+ totalSkillLVL += entry.getValue().getAsFloat();
+ totalTrueSkillLVL += Math.floor(entry.getValue().getAsFloat());
+ totalSkillCount++;
+ } else if(entry.getKey().startsWith("level_slayer")) {
+ totalSlayerLVL += entry.getValue().getAsFloat();
+ totalSlayerCount++;
+ }
+ }
+
+ float avgSkillLVL = totalSkillLVL/totalSkillCount;
+ float avgTrueSkillLVL = totalTrueSkillLVL/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);
+ renderAlignedString(EnumChatFormatting.RED+"True AVG Skill Level", EnumChatFormatting.WHITE.toString()+Math.floor(avgTrueSkillLVL*10)/10,
+ guiLeft+xStart, guiTop+yStartBottom+yOffset*3, 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(SBInfo.getInstance().currentTimeDate != null) {
+ if(SBInfo.getInstance().currentTimeDate.getHours() <= 6 ||
+ SBInfo.getInstance().currentTimeDate.getHours() >= 20) {
+ panoramaIdentifier = "night";
+ }
+ }
+
+ Panorama.drawPanorama(-backgroundRotation-extraRotation, guiLeft+23, guiTop+44, 81, 108, 0.37f, 0.8f,
+ getPanoramasForLocation(location==null?"unknown":location, panoramaIdentifier));
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(pv_basic);
+ Utils.drawTexturedRect(guiLeft, guiTop, sizeX, sizeY, GL11.GL_NEAREST);
+
+ if(entityPlayer != null && profile.getHypixelProfile() != null) {
+ String playerName = null;
+ if(profile.getHypixelProfile().has("prefix")) {
+ playerName = Utils.getElementAsString(profile.getHypixelProfile().get("prefix"), "") + " " + entityPlayer.getName();
+ } else {
+ String rank = Utils.getElementAsString(profile.getHypixelProfile().get("rank"),
+ Utils.getElementAsString(profile.getHypixelProfile().get("newPackageRank"), "NONE"));;
+ String monthlyPackageRank = Utils.getElementAsString(profile.getHypixelProfile().get("monthlyPackageRank"), "NONE");
+ if(!rank.equals("YOUTUBER") && !monthlyPackageRank.equals("NONE")) {
+ rank = monthlyPackageRank;
+ }
+ EnumChatFormatting rankPlusColorECF = EnumChatFormatting.getValueByName(Utils.getElementAsString(profile.getHypixelProfile().get("rankPlusColor"), "WHITE"));
+ String rankPlusColor = EnumChatFormatting.WHITE.toString();
+ if(rankPlusColorECF != null) {
+ rankPlusColor = rankPlusColorECF.toString();
+ }
+
+ JsonObject misc = Constants.MISC;
+ if(misc != null) {
+ if(misc.has("ranks")) {
+ String rankName = Utils.getElementAsString(Utils.getElement(misc, "ranks."+rank+".tag"), null);
+ String rankColor = Utils.getElementAsString(Utils.getElement(misc, "ranks."+rank+".color"), "7");
+ String rankPlus = Utils.getElementAsString(Utils.getElement(misc, "ranks."+rank+".plus"), "");
+
+ String name = entityPlayer.getName();
+
+ if(misc.has("special_bois")) {
+ JsonArray special_bois = misc.get("special_bois").getAsJsonArray();
+ for(int i=0; i<special_bois.size(); i++) {
+ if(special_bois.get(i).getAsString().equals(profile.getUuid())) {
+ name = Utils.chromaString(name);
+ break;
+ }
+ }
+ }
+
+ playerName = EnumChatFormatting.GRAY.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);
+ }
+ }
+
+ long networth = profile.getNetWorth(profileId);
+ if(networth > 0) {
+ Utils.drawStringCentered(EnumChatFormatting.GREEN+"Net Worth: "+EnumChatFormatting.GOLD+numberFormat.format(networth), fr, guiLeft+63, guiTop+38, true, 0);
+ try {
+ double networthInCookies = (networth / NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarInfo("BOOSTER_COOKIE").get("avg_buy").getAsDouble());
+ String networthIRLMoney = Long.toString(Math.round(((networthInCookies * 325) / 675) * 4.99));
+
+ if(mouseX > guiLeft+8 && mouseX < guiLeft+8+fontRendererObj.getStringWidth("Net Worth: " + numberFormat.format(networth))) {
+ if(mouseY > guiTop+32 && mouseY < guiTop+32+fontRendererObj.FONT_HEIGHT) {
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(EnumChatFormatting.GREEN+"Net worth in IRL money: "+EnumChatFormatting.DARK_GREEN+"$" +EnumChatFormatting.GOLD+networthIRLMoney);
+ tooltipToDisplay.add("");
+ if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
+ tooltipToDisplay.add(EnumChatFormatting.RED+"This is calculated using the current");
+ tooltipToDisplay.add(EnumChatFormatting.RED+"price of booster cookies on bazaar and the price");
+ tooltipToDisplay.add(EnumChatFormatting.RED+"for cookies using gems, then the price of gems");
+ tooltipToDisplay.add(EnumChatFormatting.RED+"is where we get the amount of IRL money you" );
+ tooltipToDisplay.add(EnumChatFormatting.RED+"theoretically have on skyblock in net worth.");
+ } else {
+ tooltipToDisplay.add(EnumChatFormatting.GRAY+"[SHIFT for Info]");
+ }
+ tooltipToDisplay.add("");
+ tooltipToDisplay.add(EnumChatFormatting.RED+"THIS IS IN NO WAY ENDORSING IRL TRADING!");
+
+ }
+ }
+ } catch(Exception e){}
+ }
+
+ if(status != null) {
+ JsonElement onlineElement = Utils.getElement(status, "online");
+ boolean online = onlineElement != null && onlineElement.isJsonPrimitive() && onlineElement.getAsBoolean();
+ String statusStr = online ? EnumChatFormatting.GREEN + "ONLINE" : EnumChatFormatting.RED + "OFFLINE";
+ String locationStr = null;
+ if(profile.getUuid().equals("20934ef9488c465180a78f861586b4cf")) {
+ locationStr = "Ignoring DMs";
+ } else {
+ if(location != null) {
+ JsonObject misc = Constants.MISC;
+ if(misc != null) {
+ locationStr = Utils.getElementAsString(Utils.getElement(misc, "area_names."+location), "Unknown");
+ }
+ }
+ }
+ if(locationStr != null) {
+ statusStr += EnumChatFormatting.GRAY+" - "+EnumChatFormatting.GREEN+locationStr;
+ }
+
+ Utils.drawStringCentered(statusStr, fr, guiLeft+63, guiTop+160, true, 0);
+ }
+
+ if(entityPlayer == null) {
+ 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) {
+ if(!OpenGlHelper.areShadersSupported()) {
+ renderBar(x, y, xSize, 1);
+ return;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(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(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() {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ int width = Minecraft.getMinecraft().displayWidth;
+ int height = Minecraft.getMinecraft().displayHeight;
+
+ if(blurOutputHorz == null) {
+ blurOutputHorz = new Framebuffer(width, height, false);
+ blurOutputHorz.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputVert == null) {
+ blurOutputVert = new Framebuffer(width, height, false);
+ blurOutputVert.setFramebufferFilter(GL11.GL_NEAREST);
+ }
+ if(blurOutputHorz.framebufferWidth != width || blurOutputHorz.framebufferHeight != height) {
+ blurOutputHorz.createBindFramebuffer(width, height);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+ if(blurOutputVert.framebufferWidth != width || blurOutputVert.framebufferHeight != height) {
+ blurOutputVert.createBindFramebuffer(width, height);
+ blurShaderVert.setProjectionMatrix(createProjectionMatrix(width, height));
+ Minecraft.getMinecraft().getFramebuffer().bindFramebuffer(false);
+ }
+
+ if(blurShaderHorz == null) {
+ try {
+ blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur",
+ Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz);
+ blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0);
+ blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height));
+ } catch(Exception 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) {
+ if(!OpenGlHelper.isFramebufferEnabled()) return;
+
+ float uMin = x/(float)width;
+ float uMax = (x+blurWidth)/(float)width;
+ float vMin = (height-y)/(float)height;
+ float vMax = (height-y-blurHeight)/(float)height;
+
+ blurOutputVert.bindFramebufferTexture();
+ GlStateManager.color(1f, 1f, 1f, 1f);
+ //Utils.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..379935ad
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/Panorama.java
@@ -0,0 +1,157 @@
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+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.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) {
+ if(!OpenGlHelper.isFramebufferEnabled()) {
+ Minecraft.getMinecraft().getTextureManager().bindTexture(panoramas[0]);
+
+ float aspect = width/(float)height;
+ Utils.drawTexturedRect(x, y, width, height, 0.5f-aspect/2, 0.5f+aspect/2, 0, 1);
+
+ return;
+ }
+
+ 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..5223e127
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/PlayerStats.java
@@ -0,0 +1,514 @@
+package io.github.moulberry.notenoughupdates.profileviewer;
+
+import com.google.gson.*;
+import io.github.moulberry.notenoughupdates.util.Constants;
+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 = Constants.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 = Constants.BONUSES;
+ if(bonuses == null) return null;
+
+ Stats skillBonus = new Stats();
+
+ for(Map.Entry<String, JsonElement> entry : skillInfo.entrySet()) {
+ if(entry.getKey().startsWith("level_")) {
+ String skill = entry.getKey().substring("level_".length());
+ JsonElement element = Utils.getElement(bonuses, "bonus_stats."+skill);
+ if(element != null && element.isJsonObject()) {
+ JsonObject skillStatMap = element.getAsJsonObject();
+
+ Stats currentBonus = new Stats();
+ for(int i=1; i<=entry.getValue().getAsFloat(); i++) {
+ if(skillStatMap.has(""+i)) {
+ currentBonus = new Stats();
+ for(Map.Entry<String, JsonElement> entry2 : skillStatMap.get(""+i).getAsJsonObject().entrySet()) {
+ currentBonus.addStat(entry2.getKey(), entry2.getValue().getAsFloat());
+ }
+ }
+ skillBonus.add(currentBonus);
+ }
+ }
+ }
+ }
+
+ return skillBonus;
+ }
+
+ private static Stats getPetBonus(JsonObject profile) {
+ JsonObject bonuses = Constants.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) {
+ System.out.println(petBonus);
+ 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 = Constants.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..e4ab29d2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -0,0 +1,1017 @@
+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.Constants;
+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 HashMap<String, String> petRarityToNumMap = new HashMap<>();
+ static {
+ petRarityToNumMap.put("COMMON", "0");
+ petRarityToNumMap.put("UNCOMMON", "1");
+ petRarityToNumMap.put("RARE", "2");
+ petRarityToNumMap.put("EPIC", "3");
+ petRarityToNumMap.put("LEGENDARY", "4");
+ }
+
+ 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("skill_catacombs", Utils.createItemStack(Item.getItemFromBlock(Blocks.deadbush), EnumChatFormatting.GOLD+"Catacombs"));
+ 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<>();
+ private long networth = -1;
+
+ 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 long getNetWorth(String profileId) {
+ if(networth != -1) return networth;
+ if(getProfileInformation(profileId) == null) return -1;
+ if(getInventoryInfo(profileId) == null) return -1;
+
+ JsonObject inventoryInfo = getInventoryInfo(profileId);
+ JsonObject profileInfo = getProfileInformation(profileId);
+
+ long networth = 0;
+ for(Map.Entry<String, JsonElement> entry : inventoryInfo.entrySet()) {
+ if(entry.getValue().isJsonArray()) {
+ for(JsonElement element : entry.getValue().getAsJsonArray()) {
+ if(element != null && element.isJsonObject()) {
+ JsonObject item = element.getAsJsonObject();
+ String internalname = item.get("internalname").getAsString();
+
+ if(manager.auctionManager.isVanillaItem(internalname)) continue;
+
+ JsonObject info = manager.auctionManager.getItemAuctionInfo(internalname);
+ if(info == null || !info.has("price") || !info.has("count")) continue;
+
+ int auctionPrice = (int)(info.get("price").getAsFloat() / info.get("count").getAsFloat());
+
+ try {
+ 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();
+ }
+ NBTTagCompound contents_nbt = CompressedStreamTools.readCompressed(new ByteArrayInputStream(bytes));
+ NBTTagList items = contents_nbt.getTagList("i", 10);
+ for(int j=0; j<items.tagCount(); j++) {
+ if(items.getCompoundTagAt(j).getKeySet().size() > 0) {
+ NBTTagCompound nbt = items.getCompoundTagAt(j).getCompoundTag("tag");
+ String internalname2 = manager.getInternalnameFromNBT(nbt);
+ if(internalname2 != null) {
+ if(manager.auctionManager.isVanillaItem(internalname2)) continue;
+
+ JsonObject info2 = manager.auctionManager.getItemAuctionInfo(internalname2);
+ if(info2 == null || !info2.has("price") || !info2.has("count")) continue;
+ int auctionPrice2 = (int)(info2.get("price").getAsFloat() / info2.get("count").getAsFloat());
+
+ int count2 = items.getCompoundTagAt(j).getByte("Count");
+ networth += auctionPrice2 * count2;
+ }
+ }
+ }
+ }
+ } catch(IOException ignored) {}
+
+ int count = 1;
+ if(element.getAsJsonObject().has("count")) {
+ count = element.getAsJsonObject().get("count").getAsInt();
+ }
+
+ networth += auctionPrice * count;
+ }
+ }
+ }
+ }
+ if(networth == 0) return -1;
+
+ JsonObject petsInfo = getPetsInfo(profileId);
+ if(petsInfo != null && petsInfo.has("pets")) {
+ if(petsInfo.get("pets").isJsonArray()) {
+ JsonArray pets = petsInfo.get("pets").getAsJsonArray();
+ for(JsonElement element : pets) {
+ if(element.isJsonObject()) {
+ JsonObject pet = element.getAsJsonObject();
+
+ String petname = pet.get("type").getAsString();
+ String tier = pet.get("tier").getAsString();
+ String tierNum = petRarityToNumMap.get(tier);
+ if(tierNum != null) {
+ String internalname2 = petname+";"+tierNum;
+ JsonObject info2 = manager.auctionManager.getItemAuctionInfo(internalname2);
+ if(info2 == null || !info2.has("price") || !info2.has("count")) continue;
+ int auctionPrice2 = (int)(info2.get("price").getAsFloat() / info2.get("count").getAsFloat());
+
+ networth += auctionPrice2;
+ }
+ }
+ }
+ }
+ }
+
+ float bankBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "banking.balance"), 0);
+ float purseBalance = Utils.getElementAsFloat(Utils.getElement(profileInfo, "coin_purse"), 0);
+
+ networth += bankBalance+purseBalance;
+
+ this.networth = networth;
+ return networth;
+ }
+
+ 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();
+ networth = -1;
+ }
+
+ 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 = Constants.LEVELING;
+ if(leveling == null) return null;
+
+ float experience_skill_taming = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_taming"), 0);
+ float experience_skill_mining = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_mining"), 0);
+ float experience_skill_foraging = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_foraging"), 0);
+ float experience_skill_enchanting = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_enchanting"), 0);
+ float experience_skill_carpentry = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_carpentry"), 0);
+ float experience_skill_farming = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_farming"), 0);
+ float experience_skill_combat = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_combat"), 0);
+ float experience_skill_fishing = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_fishing"), 0);
+ float experience_skill_alchemy = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_alchemy"), 0);
+ float experience_skill_runecrafting = Utils.getElementAsFloat(Utils.getElement(profileInfo, "experience_skill_runecrafting"), 0);
+
+ float experience_skill_catacombs = Utils.getElementAsFloat(Utils.getElement(profileInfo, "dungeons.dungeon_types.catacombs.experience"), 0);
+ if(uuid.equals("d14403fd77664905929ee1a6e365e623")) experience_skill_catacombs = 569809640; //lvl 50
+
+ 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_catacombs
+ + 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_skill_catacombs", experience_skill_catacombs);
+
+ skillInfo.addProperty("experience_slayer_zombie", experience_slayer_zombie);
+ skillInfo.addProperty("experience_slayer_spider", experience_slayer_spider);
+ skillInfo.addProperty("experience_slayer_wolf", experience_slayer_wolf);
+
+ 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_skill_catacombs = getLevel(Utils.getElement(leveling, "catacombs").getAsJsonArray(), experience_skill_catacombs, 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_skill_catacombs", level_skill_catacombs.level);
+
+ skillInfo.addProperty("level_slayer_zombie", level_slayer_zombie.level);
+ skillInfo.addProperty("level_slayer_spider", level_slayer_spider.level);
+ skillInfo.addProperty("level_slayer_wolf", level_slayer_wolf.level);
+
+ skillInfo.addProperty("maxed_skill_taming", level_skill_taming.maxed);
+ skillInfo.addProperty("maxed_skill_mining", level_skill_mining.maxed);
+ skillInfo.addProperty("maxed_skill_foraging", level_skill_foraging.maxed);
+ skillInfo.addProperty("maxed_skill_enchanting", level_skill_enchanting.maxed);
+ skillInfo.addProperty("maxed_skill_carpentry", level_skill_carpentry.maxed);
+ skillInfo.addProperty("maxed_skill_farming", level_skill_farming.maxed);
+ skillInfo.addProperty("maxed_skill_combat", level_skill_combat.maxed);
+ skillInfo.addProperty("maxed_skill_fishing", level_skill_fishing.maxed);
+ skillInfo.addProperty("maxed_skill_alchemy", level_skill_alchemy.maxed);
+ skillInfo.addProperty("maxed_skill_runecrafting", level_skill_runecrafting.maxed);
+
+ skillInfo.addProperty("maxed_skill_catacombs", level_skill_catacombs.maxed);
+
+ skillInfo.addProperty("maxed_slayer_zombie", level_slayer_zombie.maxed);
+ skillInfo.addProperty("maxed_slayer_spider", level_slayer_spider.maxed);
+ skillInfo.addProperty("maxed_slayer_wolf", level_slayer_wolf.maxed);
+
+ skillInfo.addProperty("maxxp_skill_taming", level_skill_taming.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_mining", level_skill_mining.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_foraging", level_skill_foraging.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_enchanting", level_skill_enchanting.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_carpentry", level_skill_carpentry.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_farming", level_skill_farming.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_combat", level_skill_combat.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_fishing", level_skill_fishing.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_alchemy", level_skill_alchemy.maxXpForLevel);
+ skillInfo.addProperty("maxxp_skill_runecrafting", level_skill_runecrafting.maxXpForLevel);
+
+ skillInfo.addProperty("maxxp_skill_catacombs", level_skill_catacombs.maxXpForLevel);
+
+ skillInfo.addProperty("maxxp_slayer_zombie", level_slayer_zombie.maxXpForLevel);
+ skillInfo.addProperty("maxxp_slayer_spider", level_slayer_spider.maxXpForLevel);
+ skillInfo.addProperty("maxxp_slayer_wolf", level_slayer_wolf.maxXpForLevel);
+
+ 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());
+ }
+ }
+
+ inventoryInfoMap.put(profileId, inventoryInfo);
+
+ 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/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/questing/SBInfo.java
new file mode 100644
index 00000000..2d594ccf
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/questing/SBInfo.java
@@ -0,0 +1,128 @@
+package io.github.moulberry.notenoughupdates.questing;
+
+import com.google.gson.JsonObject;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.scoreboard.Score;
+import net.minecraft.scoreboard.ScoreObjective;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Scoreboard;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+
+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 SBInfo {
+
+ private static final SBInfo INSTANCE = new SBInfo();
+
+ private static final Pattern timePattern = Pattern.compile(".+(am|pm)");
+
+ public String location = "";
+ public String date = "";
+ public String time = "";
+ public String objective = "";
+
+ public String mode = "";
+
+ public Date currentTimeDate = null;
+
+ public static SBInfo getInstance() {
+ return INSTANCE;
+ }
+
+ private long lastLocRaw = -1;
+ private JsonObject locraw = null;
+
+ @SubscribeEvent
+ public void onWorldChange(WorldEvent.Load event) {
+ lastLocRaw = -1;
+ locraw = null;
+ }
+
+ @SubscribeEvent
+ public void onChatMessage(ClientChatReceivedEvent event) {
+ if(event.message.getUnformattedText().startsWith("{")) {
+ try {
+ JsonObject obj = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(event.message.getUnformattedText(), JsonObject.class);
+ if(obj.has("server")) {
+ event.setCanceled(true);
+ if(obj.has("gametype") && obj.has("mode") && obj.has("map")) {
+ locraw = obj;
+ }
+ }
+
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public String getLocation() {
+ if(locraw == null) {
+ return null;
+ }
+ return locraw.get("mode").getAsString();
+ }
+
+ public void tick() {
+ if(locraw == null && (System.currentTimeMillis() - lastLocRaw) > 20000) {
+ lastLocRaw = System.currentTimeMillis();
+ NotEnoughUpdates.INSTANCE.sendChatMessage("/locraw");
+ }
+
+ 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(1)).trim();
+ //§74:40am
+ Matcher matcher = timePattern.matcher(lines.get(2));
+ 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) {}
+ }
+ location = Utils.cleanColour(lines.get(3)).replaceAll("[^A-Za-z0-9() ]", "").trim();
+ }
+ objective = null;
+
+ boolean objTextLast = false;
+ for(String line : lines) {
+ if(objTextLast) {
+ objective = line;
+ }
+
+ objTextLast = line.equals("Objective");
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+}
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..c0aef344 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.SBInfo;
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(SBInfo.getInstance().location);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
new file mode 100644
index 00000000..f70d3a3c
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Constants.java
@@ -0,0 +1,15 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.gson.JsonObject;
+
+public class Constants {
+
+ public static final JsonObject BONUSES = Utils.getConstant("bonuses");
+ public static final JsonObject DISABLE = Utils.getConstant("disable");
+ public static final JsonObject ENCHANTS = Utils.getConstant("enchants");
+ public static final JsonObject LEVELING = Utils.getConstant("leveling");
+ public static final JsonObject MISC = Utils.getConstant("misc");
+ public static final JsonObject PETNUMS = Utils.getConstant("petnums");
+ public static final JsonObject PETS = Utils.getConstant("pets");
+
+}
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..2e6b29da 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,99 @@ 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);
+
+ private int myApiErrors = 0;
+ private String[] myApiURLs = {"https://moulberry.codes/", "http://51.75.78.252/", "http://moulberry.codes/" };
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 apiKey, String method, HashMap<String, String> args, Consumer<JsonObject> consumer, Runnable error) {
+ getApiAsync(generateApiUrl(apiKey.trim(), method, args), consumer, error);
+ }
+
+ private String getMyApiURL() {
+ return myApiURLs[myApiErrors%myApiURLs.length];
}
- public void getHypixelApiAsync(String urlS, Consumer<JsonObject> consumer) {
+ public void getApiAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
es.submit(() -> {
- consumer.accept(getHypixelApiSync(urlS));
+ try {
+ consumer.accept(getApiSync(urlS));
+ } catch(Exception 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;
- }
+ public void getMyApiAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
+ es.submit(() -> {
+ try {
+ consumer.accept(getApiSync(getMyApiURL()+urlS));
+ } catch(Exception e) {
+ myApiErrors++;
+ error.run();
+ }
+ });
+ }
+
+ public void getMyApiGZIPAsync(String urlS, Consumer<JsonObject> consumer, Runnable error) {
+ es.submit(() -> {
+ try {
+ consumer.accept(getApiGZIPSync(getMyApiURL()+urlS));
+ } catch(Exception e) {
+ myApiErrors++;
+ error.run();
+ }
+ });
+ }
- 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(Exception 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(10000);
+ connection.setReadTimeout(10000);
+
+ 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(10000);
+ connection.setReadTimeout(10000);
+
+ String response = IOUtils.toString(new GZIPInputStream(connection.getInputStream()), StandardCharsets.UTF_8);
+
+ JsonObject json = gson.fromJson(response, JsonObject.class);
+ return json;
}
public String generateApiUrl(String apiKey, String method, HashMap<String, String> args) {
- 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/SpecialColour.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java
new file mode 100644
index 00000000..5bcd23c3
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SpecialColour.java
@@ -0,0 +1,95 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import java.awt.*;
+
+public class SpecialColour {
+
+ public static String special(int chromaSpeed, int alpha, int rgb) {
+ return special(chromaSpeed, alpha, (rgb & 0xFF0000) >> 16, (rgb & 0x00FF00) >> 8, (rgb & 0x0000FF));
+ }
+
+ private static final int RADIX = 10;
+
+ public static String special(int chromaSpeed, int alpha, int r, int g, int b) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Integer.toString(chromaSpeed, RADIX)).append(":");
+ sb.append(Integer.toString(alpha, RADIX)).append(":");
+ sb.append(Integer.toString(r, RADIX)).append(":");
+ sb.append(Integer.toString(g, RADIX)).append(":");
+ sb.append(Integer.toString(b, RADIX));
+ return sb.toString();
+ }
+
+ private static int[] decompose(String csv) {
+ String[] split = csv.split(":");
+
+ int[] arr = new int[split.length];
+
+
+ for(int i=0; i<split.length; i++) {
+ arr[i] = Integer.parseInt(split[split.length-1-i], RADIX);
+ }
+ return arr;
+ }
+
+ public static int specialToSimpleRGB(String special) {
+ int[] d = decompose(special);
+ int r = d[2];
+ int g = d[1];
+ int b = d[0];
+ int a = d[3];
+ int chr = d[4];
+
+ return (a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF) << 8 | (b & 0xFF);
+ }
+
+ public static int getSpeed(String special) {
+ return decompose(special)[4];
+ }
+
+ public static float getSecondsForSpeed(int speed) {
+ return (255-speed)/254f*(MAX_CHROMA_SECS-MIN_CHROMA_SECS)+MIN_CHROMA_SECS;
+ }
+
+ private static final int MIN_CHROMA_SECS = 1;
+ private static final int MAX_CHROMA_SECS = 60;
+
+ public static long startTime = -1;
+ public static int specialToChromaRGB(String special) {
+ if(startTime < 0) startTime = System.currentTimeMillis();
+
+ int[] d = decompose(special);
+ int chr = d[4];
+ int a = d[3];
+ int r = d[2];
+ int g = d[1];
+ int b = d[0];
+
+ float[] hsv = Color.RGBtoHSB(r, g, b, null);
+
+ if(chr > 0) {
+ float seconds = getSecondsForSpeed(chr);
+ hsv[0] += (System.currentTimeMillis()-startTime)/1000f/seconds;
+ hsv[0] %= 1;
+ if(hsv[0] < 0) hsv[0] += 1;
+ }
+
+ return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
+ }
+
+ public static int rotateHue(int argb, int degrees) {
+ int a = (argb >> 24) & 0xFF;
+ int r = (argb >> 16) & 0xFF;
+ int g = (argb >> 8) & 0xFF;
+ int b = (argb) & 0xFF;
+
+ float[] hsv = Color.RGBtoHSB(r, g, b, null);
+
+ hsv[0] += degrees/360f;
+ hsv[0] %= 1;
+
+ return (a & 0xFF) << 24 | (Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0x00FFFFFF);
+ }
+
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
index 48eea22d..5e792cf5 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/TexLoc.java
@@ -20,7 +20,7 @@ public class TexLoc {
this.toggleKey = toggleKey;
}
- public void handleKeyboardInput() {
+ public boolean handleKeyboardInput() {
int mult=1;
if(Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) mult=10;
if(Keyboard.isKeyDown(toggleKey)) {
@@ -31,7 +31,7 @@ public class TexLoc {
} else {
pressedLastTick = false;
}
- if(toggled) {
+ if(toggled || toggleKey == 0) {
if(Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
if(!dirPressed) x-=mult;
dirPressed = true;
@@ -46,10 +46,12 @@ public class TexLoc {
dirPressed = true;
} else {
dirPressed = false;
- return;
+ return false;
}
System.out.println("X: " + x + " ; Y: " + y);
+ return true;
}
+ return false;
}
}
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..e2faa5aa 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,15 @@ 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.*;
+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;
@@ -24,11 +31,15 @@ import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.nbt.NBTTagString;
+import net.minecraft.potion.Potion;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.*;
+import net.minecraftforge.fml.common.Loader;
+import org.lwjgl.BufferUtils;
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.*;
@@ -37,16 +48,22 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.Proxy;
+import java.nio.FloatBuffer;
import java.nio.file.Files;
-import java.util.ArrayList;
+import java.util.*;
import java.util.List;
-import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
private static boolean hasEffectOverride = false;
+ public static boolean disableCustomDungColours = false;
+ private static LinkedList<Integer> guiScales = new LinkedList<>();
+ private static ScaledResolution lastScale = new ScaledResolution(Minecraft.getMinecraft());
+ //Labymod compatibility
+ private static FloatBuffer projectionMatrixOld = BufferUtils.createFloatBuffer(16);
+ private static FloatBuffer modelviewMatrixOld = BufferUtils.createFloatBuffer(16);
public static <T> ArrayList<T> createList(T... values) {
ArrayList<T> list = new ArrayList<>();
@@ -54,6 +71,74 @@ public class Utils {
return list;
}
+ public static void resetGuiScale() {
+ guiScales.clear();
+ }
+
+ public static ScaledResolution peekGuiScale() {
+ return lastScale;
+ }
+
+ public static ScaledResolution pushGuiScale(int scale) {
+ if(guiScales.size() == 0) {
+ if(Loader.isModLoaded("labymod")) {
+ GL11.glGetFloat(GL11.GL_PROJECTION_MATRIX, projectionMatrixOld);
+ GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, modelviewMatrixOld);
+ }
+ }
+
+ if(scale < 0) {
+ if(guiScales.size() > 0) {
+ guiScales.pop();
+ }
+ } else {
+ if(scale == 0) {
+ guiScales.push(Minecraft.getMinecraft().gameSettings.guiScale);
+ } else {
+ guiScales.push(scale);
+ }
+ }
+
+ int newScale = guiScales.size() > 0 ? Math.max(1, Math.min(4, guiScales.peek())) : Minecraft.getMinecraft().gameSettings.guiScale;
+ if(newScale == 0) newScale = Minecraft.getMinecraft().gameSettings.guiScale;
+
+ int oldScale = Minecraft.getMinecraft().gameSettings.guiScale;
+ Minecraft.getMinecraft().gameSettings.guiScale = newScale;
+ ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft());
+ Minecraft.getMinecraft().gameSettings.guiScale = oldScale;
+
+ if(guiScales.size() > 0) {
+ GlStateManager.viewport(0, 0, Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight);
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D,
+ scaledresolution.getScaledWidth_double(),
+ scaledresolution.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+ } else {
+ if(Loader.isModLoaded("labymod") && projectionMatrixOld.limit() > 0 && modelviewMatrixOld.limit() > 0) {
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GL11.glLoadMatrix(projectionMatrixOld);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GL11.glLoadMatrix(modelviewMatrixOld);
+ } else {
+ GlStateManager.matrixMode(GL11.GL_PROJECTION);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D,
+ scaledresolution.getScaledWidth_double(),
+ scaledresolution.getScaledHeight_double(), 0.0D, 1000.0D, 3000.0D);
+ GlStateManager.matrixMode(GL11.GL_MODELVIEW);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(0.0F, 0.0F, -2000.0F);
+ }
+ }
+
+ lastScale = scaledresolution;
+ return scaledresolution;
+ }
+
public static boolean getHasEffectOverride() {
return hasEffectOverride;
}
@@ -61,6 +146,7 @@ public class Utils {
public static void drawItemStackWithoutGlint(ItemStack stack, int x, int y) {
RenderItem itemRender = Minecraft.getMinecraft().getRenderItem();
+ disableCustomDungColours = true;
RenderHelper.enableGUIStandardItemLighting();
itemRender.zLevel = -145; //Negates the z-offset of the below method.
hasEffectOverride = true;
@@ -70,21 +156,129 @@ public class Utils {
hasEffectOverride = false;
itemRender.zLevel = 0;
RenderHelper.disableStandardItemLighting();
+ disableCustomDungColours = false;
}
- 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();
+ disableCustomDungColours = true;
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();
+ disableCustomDungColours = false;
+ }
+
+ 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) {
+ return chromaString(str, 0, false);
+ }
+
+ private static long startTime = 0;
+ public static String chromaString(String str, float offset, boolean bold) {
+ str = cleanColour(str);
+
+ long currentTimeMillis = System.currentTimeMillis();
+ if(startTime == 0) startTime = currentTimeMillis;
+
+ StringBuilder rainbowText = new StringBuilder();
+ int len = 0;
+ for(int i=0; i<str.length(); i++) {
+ char c = str.charAt(i);
+ int index = ((int)(offset+len/12f-(currentTimeMillis-startTime)/100))%rainbow.length;
+ len += Minecraft.getMinecraft().fontRendererObj.getCharWidth(c);
+ if(bold) len++;
+
+ if(index < 0) index += rainbow.length;
+ rainbowText.append(rainbow[index]);
+ if(bold) rainbowText.append(EnumChatFormatting.BOLD);
+ rainbowText.append(c);
+ }
+ return rainbowText.toString();
+ }
+
+ 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));
+ }
+
+ 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 +338,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));
@@ -205,8 +426,39 @@ public class Utils {
GlStateManager.disableBlend();
}
+ public static void drawTexturedRectNoBlend(float x, float y, float width, float height, float uMin, float uMax, float vMin, float vMax, int filter) {
+ GlStateManager.enableTexture2D();
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter);
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX);
+ worldrenderer
+ .pos(x, y+height, 0.0D)
+ .tex(uMin, vMax).endVertex();
+ worldrenderer
+ .pos(x+width, y+height, 0.0D)
+ .tex(uMax, vMax).endVertex();
+ worldrenderer
+ .pos(x+width, y, 0.0D)
+ .tex(uMax, vMin).endVertex();
+ worldrenderer
+ .pos(x, y, 0.0D)
+ .tex(uMin, vMin).endVertex();
+ tessellator.draw();
+
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
+ GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
+ }
+
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 +471,19 @@ 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, 0, 0, colour, shadow);
+ GL11.glTranslatef(-x, -y, 0);
+ }
+
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 +520,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 +549,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);
}
@@ -372,10 +653,82 @@ public class Utils {
GlStateManager.enableTexture2D();
}
+ public static void drawGradientRectHorz(int left, int top, int right, int bottom, int startColor, int endColor) {
+ float f = (float)(startColor >> 24 & 255) / 255.0F;
+ float f1 = (float)(startColor >> 16 & 255) / 255.0F;
+ float f2 = (float)(startColor >> 8 & 255) / 255.0F;
+ float f3 = (float)(startColor & 255) / 255.0F;
+ float f4 = (float)(endColor >> 24 & 255) / 255.0F;
+ float f5 = (float)(endColor >> 16 & 255) / 255.0F;
+ float f6 = (float)(endColor >> 8 & 255) / 255.0F;
+ float f7 = (float)(endColor & 255) / 255.0F;
+ GlStateManager.disableTexture2D();
+ GlStateManager.enableBlend();
+ GlStateManager.disableAlpha();
+ GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
+ GlStateManager.shadeModel(7425);
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR);
+ worldrenderer.pos((double)right, (double)top, 0).color(f5, f6, f7, f4).endVertex();
+ worldrenderer.pos((double)left, (double)top, 0).color(f1, f2, f3, f).endVertex();
+ worldrenderer.pos((double)left, (double)bottom, 0).color(f1, f2, f3, f).endVertex();
+ worldrenderer.pos((double)right, (double)bottom, 0).color(f5, f6, f7, f4).endVertex();
+ tessellator.draw();
+ GlStateManager.shadeModel(7424);
+ GlStateManager.disableBlend();
+ GlStateManager.enableAlpha();
+ GlStateManager.enableTexture2D();
+ }
+
public static void drawHoveringText(List<String> textLines, final int mouseX, final int mouseY, final int screenWidth, final int screenHeight, final int maxTextWidth, FontRenderer font) {
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 +745,45 @@ 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 scrollTooltip(int dY) {
+ scrollY.setTarget(scrollY.getTarget()+dY/10f);
+ scrollY.resetTimer();
+ }
+
+ private static LerpingFloat scrollY = new LerpingFloat(0, 100);
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())
{
@@ -485,9 +877,24 @@ public class Utils {
}
}
+ //Scrollable tooltips
+ if(tooltipHeight + 6 > screenHeight) {
+ if(scrollY.getTarget() < 0) {
+ scrollY.setTarget(0);
+ scrollY.resetTimer();
+ } else if(screenHeight - tooltipHeight - 12 + (int)scrollY.getTarget() > 0) {
+ scrollY.setTarget(-screenHeight + tooltipHeight + 12);
+ scrollY.resetTimer();
+ }
+ } else {
+ scrollY.setValue(0);
+ scrollY.resetTimer();
+ }
+ scrollY.tick();
+
if (tooltipY + tooltipHeight + 6 > screenHeight)
{
- tooltipY = screenHeight - tooltipHeight - 6;
+ tooltipY = screenHeight - tooltipHeight - 6 + (int)scrollY.getValue();
}
final int zLevel = 300;
@@ -502,36 +909,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);
}
}
@@ -593,4 +971,34 @@ public class Utils {
GlStateManager.enableTexture2D();
}
+ public static void drawRectNoBlend(int left, int top, int right, int bottom, int color) {
+ if (left < right) {
+ int i = left;
+ left = right;
+ right = i;
+ }
+
+ if (top < bottom) {
+ int j = top;
+ top = bottom;
+ bottom = j;
+ }
+
+ float f3 = (float)(color >> 24 & 255) / 255.0F;
+ float f = (float)(color >> 16 & 255) / 255.0F;
+ float f1 = (float)(color >> 8 & 255) / 255.0F;
+ float f2 = (float)(color & 255) / 255.0F;
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ GlStateManager.disableTexture2D();
+ GlStateManager.color(f, f1, f2, f3);
+ worldrenderer.begin(7, DefaultVertexFormats.POSITION);
+ worldrenderer.pos((double)left, (double)bottom, 0.0D).endVertex();
+ worldrenderer.pos((double)right, (double)bottom, 0.0D).endVertex();
+ worldrenderer.pos((double)right, (double)top, 0.0D).endVertex();
+ worldrenderer.pos((double)left, (double)top, 0.0D).endVertex();
+ tessellator.draw();
+ GlStateManager.enableTexture2D();
+ }
+
}
diff --git a/src/main/resources/assets/notenoughupdates/accessory_bag_overlay.png b/src/main/resources/assets/notenoughupdates/accessory_bag_overlay.png
new file mode 100644
index 00000000..6fcac4d1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/accessory_bag_overlay.png
Binary files differ
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/button_white.png b/src/main/resources/assets/notenoughupdates/button_white.png
new file mode 100644
index 00000000..7763716d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/button_white.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/contrib.png b/src/main/resources/assets/notenoughupdates/capes/contrib.png
index 51699e6e..51699e6e 100644
--- a/src/main/resources/assets/notenoughupdates/contrib.png
+++ b/src/main/resources/assets/notenoughupdates/capes/contrib.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/fade.png b/src/main/resources/assets/notenoughupdates/capes/fade.png
index d898ec4d..d898ec4d 100644
--- a/src/main/resources/assets/notenoughupdates/fade.png
+++ b/src/main/resources/assets/notenoughupdates/capes/fade.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/gravy.png b/src/main/resources/assets/notenoughupdates/capes/gravy.png
index e43ba7d2..e43ba7d2 100644
--- a/src/main/resources/assets/notenoughupdates/gravy.png
+++ b/src/main/resources/assets/notenoughupdates/capes/gravy.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/lava.png b/src/main/resources/assets/notenoughupdates/capes/lava.png
new file mode 100644
index 00000000..8f60a03e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/lava.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/lightning.png b/src/main/resources/assets/notenoughupdates/capes/lightning.png
new file mode 100644
index 00000000..dc0afce1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/lightning.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/mbstaff.png b/src/main/resources/assets/notenoughupdates/capes/mbstaff.png
new file mode 100644
index 00000000..15961c7c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/mbstaff.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/mcworld.png b/src/main/resources/assets/notenoughupdates/capes/mcworld.png
new file mode 100644
index 00000000..89b3b367
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/mcworld.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/nullzee.png b/src/main/resources/assets/notenoughupdates/capes/nullzee.png
index 5939034b..5939034b 100644
--- a/src/main/resources/assets/notenoughupdates/nullzee.png
+++ b/src/main/resources/assets/notenoughupdates/capes/nullzee.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/packshq.png b/src/main/resources/assets/notenoughupdates/capes/packshq.png
new file mode 100644
index 00000000..860b10f5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/packshq.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/patreon1.png b/src/main/resources/assets/notenoughupdates/capes/patreon1.png
new file mode 100644
index 00000000..aba027bc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/patreon1.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/patreon2.png b/src/main/resources/assets/notenoughupdates/capes/patreon2.png
new file mode 100644
index 00000000..1c5a848a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/patreon2.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/space.png b/src/main/resources/assets/notenoughupdates/capes/space.png
new file mode 100644
index 00000000..ba239e22
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/space.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/testcape.png b/src/main/resources/assets/notenoughupdates/capes/testcape.png
index 4b8ba499..4b8ba499 100644
--- a/src/main/resources/assets/notenoughupdates/testcape.png
+++ b/src/main/resources/assets/notenoughupdates/capes/testcape.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/colour_selector_bar.png b/src/main/resources/assets/notenoughupdates/colour_selector_bar.png
new file mode 100644
index 00000000..f176af90
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/colour_selector_bar.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/colour_selector_bar_alpha.png b/src/main/resources/assets/notenoughupdates/colour_selector_bar_alpha.png
new file mode 100644
index 00000000..7a89510c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/colour_selector_bar_alpha.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/colour_selector_chroma.png b/src/main/resources/assets/notenoughupdates/colour_selector_chroma.png
new file mode 100644
index 00000000..ea273959
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/colour_selector_chroma.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/colour_selector_dot.png b/src/main/resources/assets/notenoughupdates/colour_selector_dot.png
new file mode 100644
index 00000000..1150c8bb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/colour_selector_dot.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/cosmetics_fg.png b/src/main/resources/assets/notenoughupdates/cosmetics_fg.png
new file mode 100644
index 00000000..445753ac
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/cosmetics_fg.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/custom_trade.png b/src/main/resources/assets/notenoughupdates/custom_trade.png
new file mode 100644
index 00000000..1b6c82a6
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/custom_trade.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png b/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png
index 48b4af95..37ad163e 100644
--- a/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png
+++ b/src/main/resources/assets/notenoughupdates/dungeon_chest_worth.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/1.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/1.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/1.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.png
new file mode 100644
index 00000000..6cd64ed1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/10.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.png
new file mode 100644
index 00000000..65898e8f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/11.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.png
new file mode 100644
index 00000000..6f0daba0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/2.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.png
new file mode 100644
index 00000000..4c123e77
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/3.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.png
new file mode 100644
index 00000000..833b9017
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/4.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.png
new file mode 100644
index 00000000..93bef87d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/5.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.png
new file mode 100644
index 00000000..43d71ad1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/6.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.png
new file mode 100644
index 00000000..054e0e84
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/7.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.json
new file mode 100644
index 00000000..b2625fc5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.21
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.png
new file mode 100644
index 00000000..54db6fbc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/8.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.png
new file mode 100644
index 00000000..c5fedff9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/large/9.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/map_border_dragon_stone.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/map_border_dragon_stone.png
new file mode 100644
index 00000000..c79eee7f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/map_border_dragon_stone.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/1.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/1.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/1.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.png
new file mode 100644
index 00000000..4f4b1dc7
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/10.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.png
new file mode 100644
index 00000000..3730ab57
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/11.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.png
new file mode 100644
index 00000000..3627d35e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/2.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.png
new file mode 100644
index 00000000..68824d04
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/3.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.png
new file mode 100644
index 00000000..3b8776e7
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/4.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.png
new file mode 100644
index 00000000..3a708494
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/5.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.png
new file mode 100644
index 00000000..149c4117
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/6.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.png
new file mode 100644
index 00000000..8b3ae258
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/7.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.json
new file mode 100644
index 00000000..8c12699d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.22
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.png
new file mode 100644
index 00000000..c131badf
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/8.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.png
new file mode 100644
index 00000000..a42870f2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/medium/9.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/1.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/1.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/1.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.png
new file mode 100644
index 00000000..b9bcac1d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/10.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.png
new file mode 100644
index 00000000..2fdbe252
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/11.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.png
new file mode 100644
index 00000000..c1b2e303
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/2.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.png
new file mode 100644
index 00000000..fe0ba4b9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/3.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.png
new file mode 100644
index 00000000..bd580c8e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/4.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.json
new file mode 100644
index 00000000..23e86d67
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.25
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.png
new file mode 100644
index 00000000..6f2bdc29
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/5.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.png
new file mode 100644
index 00000000..0bf30077
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/6.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.png
new file mode 100644
index 00000000..a060875a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/7.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.json
new file mode 100644
index 00000000..8c12699d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 0.22
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.png
new file mode 100644
index 00000000..5dd06a89
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/8.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.json b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.json
new file mode 100644
index 00000000..9576ae4f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.json
@@ -0,0 +1,3 @@
+{
+ "radiusSq": 1
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.png
new file mode 100644
index 00000000..1d275525
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/small/9.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/borders/steampunk.png b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/steampunk.png
new file mode 100644
index 00000000..3d1c0833
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/borders/steampunk.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corners_default/brown_corner.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corners_default/brown_corner.png
new file mode 100644
index 00000000..23ae39fd
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corners_default/brown_corner.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/brown_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/brown_corridor.png
new file mode 100644
index 00000000..abc06bab
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/brown_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/gray_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/gray_corridor.png
new file mode 100644
index 00000000..78deccbb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/gray_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/green_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/green_corridor.png
new file mode 100644
index 00000000..8ae999fc
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/green_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/orange_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/orange_corridor.png
new file mode 100644
index 00000000..62515723
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/orange_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/pink_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/pink_corridor.png
new file mode 100644
index 00000000..89dfc4b3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/pink_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/purple_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/purple_corridor.png
new file mode 100644
index 00000000..a1fcfc83
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/purple_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/red_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/red_corridor.png
new file mode 100644
index 00000000..ec80a4c5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/red_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/yellow_corridor.png b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/yellow_corridor.png
new file mode 100644
index 00000000..cc10b875
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/corridors_default/yellow_corridor.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/cross.png b/src/main/resources/assets/notenoughupdates/dungeon_map/cross.png
new file mode 100644
index 00000000..e98151a8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/cross.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/dividers_default/brown_divider.png b/src/main/resources/assets/notenoughupdates/dungeon_map/dividers_default/brown_divider.png
new file mode 100644
index 00000000..30a0357c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/dividers_default/brown_divider.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/editor/background.png b/src/main/resources/assets/notenoughupdates/dungeon_map/editor/background.png
new file mode 100644
index 00000000..7e8f68ea
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/editor/background.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/green_check.png b/src/main/resources/assets/notenoughupdates/dungeon_map/green_check.png
new file mode 100644
index 00000000..eeef275d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/green_check.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/question.png b/src/main/resources/assets/notenoughupdates/dungeon_map/question.png
new file mode 100644
index 00000000..79c4c100
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/question.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/brown_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/brown_room.png
new file mode 100644
index 00000000..2d2ec6b1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/brown_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/gray_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/gray_room.png
new file mode 100644
index 00000000..41db61f0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/gray_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/green_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/green_room.png
new file mode 100644
index 00000000..acda8072
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/green_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/orange_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/orange_room.png
new file mode 100644
index 00000000..5e32636a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/orange_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/pink_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/pink_room.png
new file mode 100644
index 00000000..19104f7c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/pink_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/purple_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/purple_room.png
new file mode 100644
index 00000000..b7f5ebd5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/purple_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/red_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/red_room.png
new file mode 100644
index 00000000..48e0ecac
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/red_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/yellow_room.png b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/yellow_room.png
new file mode 100644
index 00000000..f5846150
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/rooms_default/yellow_room.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_map/white_check.png b/src/main/resources/assets/notenoughupdates/dungeon_map/white_check.png
new file mode 100644
index 00000000..8e8d8685
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_map/white_check.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/a.png b/src/main/resources/assets/notenoughupdates/dungeon_win/a.png
new file mode 100644
index 00000000..85322946
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/a.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/b.png b/src/main/resources/assets/notenoughupdates/dungeon_win/b.png
new file mode 100644
index 00000000..11c7384c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/b.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/c.png b/src/main/resources/assets/notenoughupdates/dungeon_win/c.png
new file mode 100644
index 00000000..2009179f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/c.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/confetti.png b/src/main/resources/assets/notenoughupdates/dungeon_win/confetti.png
new file mode 100644
index 00000000..a5529dc8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/confetti.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/d.png b/src/main/resources/assets/notenoughupdates/dungeon_win/d.png
new file mode 100644
index 00000000..c08baaf4
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/d.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/s.png b/src/main/resources/assets/notenoughupdates/dungeon_win/s.png
new file mode 100644
index 00000000..a514f285
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/s.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dungeon_win/splus.png b/src/main/resources/assets/notenoughupdates/dungeon_win/splus.png
new file mode 100644
index 00000000..732d30a3
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dungeon_win/splus.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54.png
new file mode 100644
index 00000000..a8c9eac9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..a29a685d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..7eaecfc2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_config.json b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_config.json
new file mode 100644
index 00000000..05dbf61a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style1/dynamic_config.json
@@ -0,0 +1,3 @@
+{
+ "text-colour": "FF000000"
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54.png
new file mode 100644
index 00000000..63479a74
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..4b28ee06
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..7eaecfc2
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_config.json b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_config.json
new file mode 100644
index 00000000..05dbf61a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style2/dynamic_config.json
@@ -0,0 +1,3 @@
+{
+ "text-colour": "FF000000"
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54.png
new file mode 100644
index 00000000..d14f0ed1
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..800acade
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..800acade
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_config.json b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_config.json
new file mode 100644
index 00000000..5ae75066
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style3/dynamic_config.json
@@ -0,0 +1,3 @@
+{
+ "text-colour": "FFC8C8C8"
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54.png
new file mode 100644
index 00000000..934f6b4a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..956d085a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..fa43a0ed
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style4/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54.png
new file mode 100644
index 00000000..73711ee8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..bab0eab7
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..fa43a0ed
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style5/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54.png
new file mode 100644
index 00000000..3a24654d
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..fa43a0ed
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..fa43a0ed
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style6/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54.png
new file mode 100644
index 00000000..934f6b4a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_button_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_button_ctm.png
new file mode 100644
index 00000000..ea57f0d0
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_button_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_slot_ctm.png b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_slot_ctm.png
new file mode 100644
index 00000000..fa43a0ed
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/style7/dynamic_54_slot_ctm.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_off.png b/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_off.png
new file mode 100644
index 00000000..7a1aa4a4
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_off.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_on.png b/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_on.png
new file mode 100644
index 00000000..5f4960f9
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dynamic_54/toggle_on.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/gamemodes.png b/src/main/resources/assets/notenoughupdates/gamemodes.png
new file mode 100644
index 00000000..8a1aa2fa
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/gamemodes.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/item_haschild.png b/src/main/resources/assets/notenoughupdates/item_haschild.png
new file mode 100644
index 00000000..c3f3369a
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/item_haschild.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png b/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png
index d8fc8530..fd23cc35 100644
--- a/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png
+++ b/src/main/resources/assets/notenoughupdates/item_pane_tab_arrow.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/maps/F1Full.json b/src/main/resources/assets/notenoughupdates/maps/F1Full.json
new file mode 100644
index 00000000..44d72fc8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/maps/F1Full.json
@@ -0,0 +1,16386 @@
+{
+ "0:0": 268435456,
+ "1:0": 402653184,
+ "2:0": 268435456,
+ "3:0": 402653184,
+ "4:0": 268435456,
+ "5:0": 402653184,
+ "6:0": 268435456,
+ "7:0": 402653184,
+ "8:0": 268435456,
+ "9:0": 402653184,
+ "10:0": 268435456,
+ "11:0": 402653184,
+ "12:0": 268435456,
+ "13:0": 402653184,
+ "14:0": 268435456,
+ "15:0": 402653184,
+ "16:0": 268435456,
+ "17:0": 402653184,
+ "18:0": 268435456,
+ "19:0": 402653184,
+ "20:0": 268435456,
+ "21:0": 402653184,
+ "22:0": 268435456,
+ "23:0": 402653184,
+ "24:0": 268435456,
+ "25:0": 402653184,
+ "26:0": 268435456,
+ "27:0": 402653184,
+ "28:0": 268435456,
+ "29:0": 402653184,
+ "30:0": 268435456,
+ "31:0": 402653184,
+ "32:0": 268435456,
+ "33:0": 402653184,
+ "34:0": 268435456,
+ "35:0": 402653184,
+ "36:0": 268435456,
+ "37:0": 402653184,
+ "38:0": 268435456,
+ "39:0": 402653184,
+ "40:0": 268435456,
+ "41:0": 402653184,
+ "42:0": 268435456,
+ "43:0": 402653184,
+ "44:0": 268435456,
+ "45:0": 402653184,
+ "46:0": 268435456,
+ "47:0": 402653184,
+ "48:0": 268435456,
+ "49:0": 402653184,
+ "50:0": 268435456,
+ "51:0": 402653184,
+ "52:0": 268435456,
+ "53:0": 402653184,
+ "54:0": 268435456,
+ "55:0": 402653184,
+ "56:0": 268435456,
+ "57:0": 402653184,
+ "58:0": 268435456,
+ "59:0": 402653184,
+ "60:0": 268435456,
+ "61:0": 402653184,
+ "62:0": 268435456,
+ "63:0": 402653184,
+ "64:0": 268435456,
+ "65:0": 402653184,
+ "66:0": 268435456,
+ "67:0": 402653184,
+ "68:0": 268435456,
+ "69:0": 402653184,
+ "70:0": 268435456,
+ "71:0": 402653184,
+ "72:0": 268435456,
+ "73:0": 402653184,
+ "74:0": 268435456,
+ "75:0": 402653184,
+ "76:0": 268435456,
+ "77:0": 402653184,
+ "78:0": 268435456,
+ "79:0": 402653184,
+ "80:0": 268435456,
+ "81:0": 402653184,
+ "82:0": 268435456,
+ "83:0": 402653184,
+ "84:0": 268435456,
+ "85:0": 402653184,
+ "86:0": 268435456,
+ "87:0": 402653184,
+ "88:0": 268435456,
+ "89:0": 402653184,
+ "90:0": 268435456,
+ "91:0": 402653184,
+ "92:0": 268435456,
+ "93:0": 402653184,
+ "94:0": 268435456,
+ "95:0": 402653184,
+ "96:0": 268435456,
+ "97:0": 402653184,
+ "98:0": 268435456,
+ "99:0": 402653184,
+ "100:0": 268435456,
+ "101:0": 402653184,
+ "102:0": 268435456,
+ "103:0": 402653184,
+ "104:0": 268435456,
+ "105:0": 402653184,
+ "106:0": 268435456,
+ "107:0": 402653184,
+ "108:0": 268435456,
+ "109:0": 402653184,
+ "110:0": 268435456,
+ "111:0": 402653184,
+ "112:0": 268435456,
+ "113:0": 402653184,
+ "114:0": 268435456,
+ "115:0": 402653184,
+ "116:0": 268435456,
+ "117:0": 402653184,
+ "118:0": 268435456,
+ "119:0": 402653184,
+ "120:0": 268435456,
+ "121:0": 402653184,
+ "122:0": 268435456,
+ "123:0": 402653184,
+ "124:0": 268435456,
+ "125:0": 402653184,
+ "126:0": 268435456,
+ "127:0": 402653184,
+ "0:1": 402653184,
+ "1:1": 268435456,
+ "2:1": 402653184,
+ "3:1": 268435456,
+ "4:1": 402653184,
+ "5:1": 268435456,
+ "6:1": 402653184,
+ "7:1": 268435456,
+ "8:1": 402653184,
+ "9:1": 268435456,
+ "10:1": 402653184,
+ "11:1": 268435456,
+ "12:1": 402653184,
+ "13:1": 268435456,
+ "14:1": 402653184,
+ "15:1": 268435456,
+ "16:1": 402653184,
+ "17:1": 268435456,
+ "18:1": 402653184,
+ "19:1": 268435456,
+ "20:1": 402653184,
+ "21:1": 268435456,
+ "22:1": 402653184,
+ "23:1": 268435456,
+ "24:1": 402653184,
+ "25:1": 268435456,
+ "26:1": 402653184,
+ "27:1": 268435456,
+ "28:1": 402653184,
+ "29:1": 268435456,
+ "30:1": 402653184,
+ "31:1": 268435456,
+ "32:1": 402653184,
+ "33:1": 268435456,
+ "34:1": 402653184,
+ "35:1": 268435456,
+ "36:1": 402653184,
+ "37:1": 268435456,
+ "38:1": 402653184,
+ "39:1": 268435456,
+ "40:1": 402653184,
+ "41:1": 268435456,
+ "42:1": 402653184,
+ "43:1": 268435456,
+ "44:1": 402653184,
+ "45:1": 268435456,
+ "46:1": 402653184,
+ "47:1": 268435456,
+ "48:1": 402653184,
+ "49:1": 268435456,
+ "50:1": 402653184,
+ "51:1": 268435456,
+ "52:1": 402653184,
+ "53:1": 268435456,
+ "54:1": 402653184,
+ "55:1": 268435456,
+ "56:1": 402653184,
+ "57:1": 268435456,
+ "58:1": 402653184,
+ "59:1": 268435456,
+ "60:1": 402653184,
+ "61:1": 268435456,
+ "62:1": 402653184,
+ "63:1": 268435456,
+ "64:1": 402653184,
+ "65:1": 268435456,
+ "66:1": 402653184,
+ "67:1": 268435456,
+ "68:1": 402653184,
+ "69:1": 268435456,
+ "70:1": 402653184,
+ "71:1": 268435456,
+ "72:1": 402653184,
+ "73:1": 268435456,
+ "74:1": 402653184,
+ "75:1": 268435456,
+ "76:1": 402653184,
+ "77:1": 268435456,
+ "78:1": 402653184,
+ "79:1": 268435456,
+ "80:1": 402653184,
+ "81:1": 268435456,
+ "82:1": 402653184,
+ "83:1": 268435456,
+ "84:1": 402653184,
+ "85:1": 268435456,
+ "86:1": 402653184,
+ "87:1": 268435456,
+ "88:1": 402653184,
+ "89:1": 268435456,
+ "90:1": 402653184,
+ "91:1": 268435456,
+ "92:1": 402653184,
+ "93:1": 268435456,
+ "94:1": 402653184,
+ "95:1": 268435456,
+ "96:1": 402653184,
+ "97:1": 268435456,
+ "98:1": 402653184,
+ "99:1": 268435456,
+ "100:1": 402653184,
+ "101:1": 268435456,
+ "102:1": 402653184,
+ "103:1": 268435456,
+ "104:1": 402653184,
+ "105:1": 268435456,
+ "106:1": 402653184,
+ "107:1": 268435456,
+ "108:1": 402653184,
+ "109:1": 268435456,
+ "110:1": 402653184,
+ "111:1": 268435456,
+ "112:1": 402653184,
+ "113:1": 268435456,
+ "114:1": 402653184,
+ "115:1": 268435456,
+ "116:1": 402653184,
+ "117:1": 268435456,
+ "118:1": 402653184,
+ "119:1": 268435456,
+ "120:1": 402653184,
+ "121:1": 268435456,
+ "122:1": 402653184,
+ "123:1": 268435456,
+ "124:1": 402653184,
+ "125:1": 268435456,
+ "126:1": 402653184,
+ "127:1": 268435456,
+ "0:2": 268435456,
+ "1:2": 402653184,
+ "2:2": 268435456,
+ "3:2": 402653184,
+ "4:2": 268435456,
+ "5:2": 402653184,
+ "6:2": 268435456,
+ "7:2": 402653184,
+ "8:2": 268435456,
+ "9:2": 402653184,
+ "10:2": 268435456,
+ "11:2": 402653184,
+ "12:2": 268435456,
+ "13:2": 402653184,
+ "14:2": 268435456,
+ "15:2": 402653184,
+ "16:2": 268435456,
+ "17:2": 402653184,
+ "18:2": 268435456,
+ "19:2": 402653184,
+ "20:2": 268435456,
+ "21:2": 402653184,
+ "22:2": 268435456,
+ "23:2": 402653184,
+ "24:2": 268435456,
+ "25:2": 402653184,
+ "26:2": 268435456,
+ "27:2": 402653184,
+ "28:2": 268435456,
+ "29:2": 402653184,
+ "30:2": 268435456,
+ "31:2": 402653184,
+ "32:2": 268435456,
+ "33:2": 402653184,
+ "34:2": 268435456,
+ "35:2": 402653184,
+ "36:2": 268435456,
+ "37:2": 402653184,
+ "38:2": 268435456,
+ "39:2": 402653184,
+ "40:2": 268435456,
+ "41:2": 402653184,
+ "42:2": 268435456,
+ "43:2": 402653184,
+ "44:2": 268435456,
+ "45:2": 402653184,
+ "46:2": 268435456,
+ "47:2": 402653184,
+ "48:2": 268435456,
+ "49:2": 402653184,
+ "50:2": 268435456,
+ "51:2": 402653184,
+ "52:2": 268435456,
+ "53:2": 402653184,
+ "54:2": 268435456,
+ "55:2": 402653184,
+ "56:2": 268435456,
+ "57:2": 402653184,
+ "58:2": 268435456,
+ "59:2": 402653184,
+ "60:2": 268435456,
+ "61:2": 402653184,
+ "62:2": 268435456,
+ "63:2": 402653184,
+ "64:2": 268435456,
+ "65:2": 402653184,
+ "66:2": 268435456,
+ "67:2": 402653184,
+ "68:2": 268435456,
+ "69:2": 402653184,
+ "70:2": 268435456,
+ "71:2": 402653184,
+ "72:2": 268435456,
+ "73:2": 402653184,
+ "74:2": 268435456,
+ "75:2": 402653184,
+ "76:2": 268435456,
+ "77:2": 402653184,
+ "78:2": 268435456,
+ "79:2": 402653184,
+ "80:2": 268435456,
+ "81:2": 402653184,
+ "82:2": 268435456,
+ "83:2": 402653184,
+ "84:2": 268435456,
+ "85:2": 402653184,
+ "86:2": 268435456,
+ "87:2": 402653184,
+ "88:2": 268435456,
+ "89:2": 402653184,
+ "90:2": 268435456,
+ "91:2": 402653184,
+ "92:2": 268435456,
+ "93:2": 402653184,
+ "94:2": 268435456,
+ "95:2": 402653184,
+ "96:2": 268435456,
+ "97:2": 402653184,
+ "98:2": 268435456,
+ "99:2": 402653184,
+ "100:2": 268435456,
+ "101:2": 402653184,
+ "102:2": 268435456,
+ "103:2": 402653184,
+ "104:2": 268435456,
+ "105:2": 402653184,
+ "106:2": 268435456,
+ "107:2": 402653184,
+ "108:2": 268435456,
+ "109:2": 402653184,
+ "110:2": 268435456,
+ "111:2": 402653184,
+ "112:2": 268435456,
+ "113:2": 402653184,
+ "114:2": 268435456,
+ "115:2": 402653184,
+ "116:2": 268435456,
+ "117:2": 402653184,
+ "118:2": 268435456,
+ "119:2": 402653184,
+ "120:2": 268435456,
+ "121:2": 402653184,
+ "122:2": 268435456,
+ "123:2": 402653184,
+ "124:2": 268435456,
+ "125:2": 402653184,
+ "126:2": 268435456,
+ "127:2": 402653184,
+ "0:3": 402653184,
+ "1:3": 268435456,
+ "2:3": 402653184,
+ "3:3": 268435456,
+ "4:3": 402653184,
+ "5:3": 268435456,
+ "6:3": 402653184,
+ "7:3": 268435456,
+ "8:3": 402653184,
+ "9:3": 268435456,
+ "10:3": 402653184,
+ "11:3": 268435456,
+ "12:3": 402653184,
+ "13:3": 268435456,
+ "14:3": 402653184,
+ "15:3": 268435456,
+ "16:3": 402653184,
+ "17:3": 268435456,
+ "18:3": 402653184,
+ "19:3": 268435456,
+ "20:3": 402653184,
+ "21:3": 268435456,
+ "22:3": 402653184,
+ "23:3": 268435456,
+ "24:3": 402653184,
+ "25:3": 268435456,
+ "26:3": 402653184,
+ "27:3": 268435456,
+ "28:3": 402653184,
+ "29:3": 268435456,
+ "30:3": 402653184,
+ "31:3": 268435456,
+ "32:3": 402653184,
+ "33:3": 268435456,
+ "34:3": 402653184,
+ "35:3": 268435456,
+ "36:3": 402653184,
+ "37:3": 268435456,
+ "38:3": 402653184,
+ "39:3": 268435456,
+ "40:3": 402653184,
+ "41:3": 268435456,
+ "42:3": 402653184,
+ "43:3": 268435456,
+ "44:3": 402653184,
+ "45:3": 268435456,
+ "46:3": 402653184,
+ "47:3": 268435456,
+ "48:3": 402653184,
+ "49:3": 268435456,
+ "50:3": 402653184,
+ "51:3": 268435456,
+ "52:3": 402653184,
+ "53:3": 268435456,
+ "54:3": 402653184,
+ "55:3": 268435456,
+ "56:3": 402653184,
+ "57:3": 268435456,
+ "58:3": 402653184,
+ "59:3": 268435456,
+ "60:3": 402653184,
+ "61:3": 268435456,
+ "62:3": 402653184,
+ "63:3": 268435456,
+ "64:3": 402653184,
+ "65:3": 268435456,
+ "66:3": 402653184,
+ "67:3": 268435456,
+ "68:3": 402653184,
+ "69:3": 268435456,
+ "70:3": 402653184,
+ "71:3": 268435456,
+ "72:3": 402653184,
+ "73:3": 268435456,
+ "74:3": 402653184,
+ "75:3": 268435456,
+ "76:3": 402653184,
+ "77:3": 268435456,
+ "78:3": 402653184,
+ "79:3": 268435456,
+ "80:3": 402653184,
+ "81:3": 268435456,
+ "82:3": 402653184,
+ "83:3": 268435456,
+ "84:3": 402653184,
+ "85:3": 268435456,
+ "86:3": 402653184,
+ "87:3": 268435456,
+ "88:3": 402653184,
+ "89:3": 268435456,
+ "90:3": 402653184,
+ "91:3": 268435456,
+ "92:3": 402653184,
+ "93:3": 268435456,
+ "94:3": 402653184,
+ "95:3": 268435456,
+ "96:3": 402653184,
+ "97:3": 268435456,
+ "98:3": 402653184,
+ "99:3": 268435456,
+ "100:3": 402653184,
+ "101:3": 268435456,
+ "102:3": 402653184,
+ "103:3": 268435456,
+ "104:3": 402653184,
+ "105:3": 268435456,
+ "106:3": 402653184,
+ "107:3": 268435456,
+ "108:3": 402653184,
+ "109:3": 268435456,
+ "110:3": 402653184,
+ "111:3": 268435456,
+ "112:3": 402653184,
+ "113:3": 268435456,
+ "114:3": 402653184,
+ "115:3": 268435456,
+ "116:3": 402653184,
+ "117:3": 268435456,
+ "118:3": 402653184,
+ "119:3": 268435456,
+ "120:3": 402653184,
+ "121:3": 268435456,
+ "122:3": 402653184,
+ "123:3": 268435456,
+ "124:3": 402653184,
+ "125:3": 268435456,
+ "126:3": 402653184,
+ "127:3": 268435456,
+ "0:4": 268435456,
+ "1:4": 402653184,
+ "2:4": 268435456,
+ "3:4": 402653184,
+ "4:4": 268435456,
+ "5:4": 402653184,
+ "6:4": 268435456,
+ "7:4": 402653184,
+ "8:4": 268435456,
+ "9:4": 402653184,
+ "10:4": 268435456,
+ "11:4": 402653184,
+ "12:4": 268435456,
+ "13:4": 402653184,
+ "14:4": 268435456,
+ "15:4": 402653184,
+ "16:4": 268435456,
+ "17:4": 402653184,
+ "18:4": 268435456,
+ "19:4": 402653184,
+ "20:4": 268435456,
+ "21:4": 402653184,
+ "22:4": 268435456,
+ "23:4": 402653184,
+ "24:4": 268435456,
+ "25:4": 402653184,
+ "26:4": 268435456,
+ "27:4": 402653184,
+ "28:4": 268435456,
+ "29:4": 402653184,
+ "30:4": 268435456,
+ "31:4": 402653184,
+ "32:4": 268435456,
+ "33:4": 402653184,
+ "34:4": 268435456,
+ "35:4": 402653184,
+ "36:4": 268435456,
+ "37:4": 402653184,
+ "38:4": 268435456,
+ "39:4": 402653184,
+ "40:4": 268435456,
+ "41:4": 402653184,
+ "42:4": 268435456,
+ "43:4": 402653184,
+ "44:4": 268435456,
+ "45:4": 402653184,
+ "46:4": 268435456,
+ "47:4": 402653184,
+ "48:4": 268435456,
+ "49:4": 402653184,
+ "50:4": 268435456,
+ "51:4": 402653184,
+ "52:4": 268435456,
+ "53:4": 402653184,
+ "54:4": 268435456,
+ "55:4": 402653184,
+ "56:4": 268435456,
+ "57:4": 402653184,
+ "58:4": 268435456,
+ "59:4": 402653184,
+ "60:4": 268435456,
+ "61:4": 402653184,
+ "62:4": 268435456,
+ "63:4": 402653184,
+ "64:4": 268435456,
+ "65:4": 402653184,
+ "66:4": 268435456,
+ "67:4": 402653184,
+ "68:4": 268435456,
+ "69:4": 402653184,
+ "70:4": 268435456,
+ "71:4": 402653184,
+ "72:4": 268435456,
+ "73:4": 402653184,
+ "74:4": 268435456,
+ "75:4": 402653184,
+ "76:4": 268435456,
+ "77:4": 402653184,
+ "78:4": 268435456,
+ "79:4": 402653184,
+ "80:4": 268435456,
+ "81:4": 402653184,
+ "82:4": 268435456,
+ "83:4": 402653184,
+ "84:4": 268435456,
+ "85:4": 402653184,
+ "86:4": 268435456,
+ "87:4": 402653184,
+ "88:4": 268435456,
+ "89:4": 402653184,
+ "90:4": 268435456,
+ "91:4": 402653184,
+ "92:4": 268435456,
+ "93:4": 402653184,
+ "94:4": 268435456,
+ "95:4": 402653184,
+ "96:4": 268435456,
+ "97:4": 402653184,
+ "98:4": 268435456,
+ "99:4": 402653184,
+ "100:4": 268435456,
+ "101:4": 402653184,
+ "102:4": 268435456,
+ "103:4": 402653184,
+ "104:4": 268435456,
+ "105:4": 402653184,
+ "106:4": 268435456,
+ "107:4": 402653184,
+ "108:4": 268435456,
+ "109:4": 402653184,
+ "110:4": 268435456,
+ "111:4": 402653184,
+ "112:4": 268435456,
+ "113:4": 402653184,
+ "114:4": 268435456,
+ "115:4": 402653184,
+ "116:4": 268435456,
+ "117:4": 402653184,
+ "118:4": 268435456,
+ "119:4": 402653184,
+ "120:4": 268435456,
+ "121:4": 402653184,
+ "122:4": 268435456,
+ "123:4": 402653184,
+ "124:4": 268435456,
+ "125:4": 402653184,
+ "126:4": 268435456,
+ "127:4": 402653184,
+ "0:5": 402653184,
+ "1:5": 268435456,
+ "2:5": 402653184,
+ "3:5": 268435456,
+ "4:5": 402653184,
+ "5:5": 268435456,
+ "6:5": 402653184,
+ "7:5": 268435456,
+ "8:5": 402653184,
+ "9:5": 268435456,
+ "10:5": 402653184,
+ "11:5": 268435456,
+ "12:5": 402653184,
+ "13:5": 268435456,
+ "14:5": 402653184,
+ "15:5": 268435456,
+ "16:5": 402653184,
+ "17:5": 268435456,
+ "18:5": 402653184,
+ "19:5": 268435456,
+ "20:5": 402653184,
+ "21:5": 268435456,
+ "22:5": 402653184,
+ "23:5": 268435456,
+ "24:5": 402653184,
+ "25:5": 268435456,
+ "26:5": 402653184,
+ "27:5": 268435456,
+ "28:5": 402653184,
+ "29:5": 268435456,
+ "30:5": 402653184,
+ "31:5": 268435456,
+ "32:5": 402653184,
+ "33:5": 268435456,
+ "34:5": 402653184,
+ "35:5": 268435456,
+ "36:5": 402653184,
+ "37:5": 268435456,
+ "38:5": 402653184,
+ "39:5": 268435456,
+ "40:5": 402653184,
+ "41:5": 268435456,
+ "42:5": 402653184,
+ "43:5": 268435456,
+ "44:5": 402653184,
+ "45:5": 268435456,
+ "46:5": 402653184,
+ "47:5": 268435456,
+ "48:5": 402653184,
+ "49:5": 268435456,
+ "50:5": 402653184,
+ "51:5": 268435456,
+ "52:5": 402653184,
+ "53:5": 268435456,
+ "54:5": 402653184,
+ "55:5": 268435456,
+ "56:5": 402653184,
+ "57:5": 268435456,
+ "58:5": 402653184,
+ "59:5": 268435456,
+ "60:5": 402653184,
+ "61:5": 268435456,
+ "62:5": 402653184,
+ "63:5": 268435456,
+ "64:5": 402653184,
+ "65:5": 268435456,
+ "66:5": 402653184,
+ "67:5": 268435456,
+ "68:5": 402653184,
+ "69:5": 268435456,
+ "70:5": 402653184,
+ "71:5": 268435456,
+ "72:5": 402653184,
+ "73:5": 268435456,
+ "74:5": 402653184,
+ "75:5": 268435456,
+ "76:5": 402653184,
+ "77:5": 268435456,
+ "78:5": 402653184,
+ "79:5": 268435456,
+ "80:5": 402653184,
+ "81:5": 268435456,
+ "82:5": 402653184,
+ "83:5": 268435456,
+ "84:5": 402653184,
+ "85:5": 268435456,
+ "86:5": 402653184,
+ "87:5": 268435456,
+ "88:5": 402653184,
+ "89:5": 268435456,
+ "90:5": 402653184,
+ "91:5": 268435456,
+ "92:5": 402653184,
+ "93:5": 268435456,
+ "94:5": 402653184,
+ "95:5": 268435456,
+ "96:5": 402653184,
+ "97:5": 268435456,
+ "98:5": 402653184,
+ "99:5": 268435456,
+ "100:5": 402653184,
+ "101:5": 268435456,
+ "102:5": 402653184,
+ "103:5": 268435456,
+ "104:5": 402653184,
+ "105:5": 268435456,
+ "106:5": 402653184,
+ "107:5": 268435456,
+ "108:5": 402653184,
+ "109:5": 268435456,
+ "110:5": 402653184,
+ "111:5": 268435456,
+ "112:5": 402653184,
+ "113:5": 268435456,
+ "114:5": 402653184,
+ "115:5": 268435456,
+ "116:5": 402653184,
+ "117:5": 268435456,
+ "118:5": 402653184,
+ "119:5": 268435456,
+ "120:5": 402653184,
+ "121:5": 268435456,
+ "122:5": 402653184,
+ "123:5": 268435456,
+ "124:5": 402653184,
+ "125:5": 268435456,
+ "126:5": 402653184,
+ "127:5": 268435456,
+ "0:6": 268435456,
+ "1:6": 402653184,
+ "2:6": 268435456,
+ "3:6": 402653184,
+ "4:6": 268435456,
+ "5:6": 402653184,
+ "6:6": 268435456,
+ "7:6": 402653184,
+ "8:6": 268435456,
+ "9:6": 402653184,
+ "10:6": 268435456,
+ "11:6": 402653184,
+ "12:6": 268435456,
+ "13:6": 402653184,
+ "14:6": 268435456,
+ "15:6": 402653184,
+ "16:6": 268435456,
+ "17:6": 402653184,
+ "18:6": 268435456,
+ "19:6": 402653184,
+ "20:6": 268435456,
+ "21:6": 402653184,
+ "22:6": 268435456,
+ "23:6": 402653184,
+ "24:6": 268435456,
+ "25:6": 402653184,
+ "26:6": 268435456,
+ "27:6": 402653184,
+ "28:6": 268435456,
+ "29:6": 402653184,
+ "30:6": 268435456,
+ "31:6": 402653184,
+ "32:6": 268435456,
+ "33:6": 402653184,
+ "34:6": 268435456,
+ "35:6": 402653184,
+ "36:6": 268435456,
+ "37:6": 402653184,
+ "38:6": 268435456,
+ "39:6": 402653184,
+ "40:6": 268435456,
+ "41:6": 402653184,
+ "42:6": 268435456,
+ "43:6": 402653184,
+ "44:6": 268435456,
+ "45:6": 402653184,
+ "46:6": 268435456,
+ "47:6": 402653184,
+ "48:6": 268435456,
+ "49:6": 402653184,
+ "50:6": 268435456,
+ "51:6": 402653184,
+ "52:6": 268435456,
+ "53:6": 402653184,
+ "54:6": 268435456,
+ "55:6": 402653184,
+ "56:6": 268435456,
+ "57:6": 402653184,
+ "58:6": 268435456,
+ "59:6": 402653184,
+ "60:6": 268435456,
+ "61:6": 402653184,
+ "62:6": 268435456,
+ "63:6": 402653184,
+ "64:6": 268435456,
+ "65:6": 402653184,
+ "66:6": 268435456,
+ "67:6": 402653184,
+ "68:6": 268435456,
+ "69:6": 402653184,
+ "70:6": 268435456,
+ "71:6": 402653184,
+ "72:6": 268435456,
+ "73:6": 402653184,
+ "74:6": 268435456,
+ "75:6": 402653184,
+ "76:6": 268435456,
+ "77:6": 402653184,
+ "78:6": 268435456,
+ "79:6": 402653184,
+ "80:6": 268435456,
+ "81:6": 402653184,
+ "82:6": 268435456,
+ "83:6": 402653184,
+ "84:6": 268435456,
+ "85:6": 402653184,
+ "86:6": 268435456,
+ "87:6": 402653184,
+ "88:6": 268435456,
+ "89:6": 402653184,
+ "90:6": 268435456,
+ "91:6": 402653184,
+ "92:6": 268435456,
+ "93:6": 402653184,
+ "94:6": 268435456,
+ "95:6": 402653184,
+ "96:6": 268435456,
+ "97:6": 402653184,
+ "98:6": 268435456,
+ "99:6": 402653184,
+ "100:6": 268435456,
+ "101:6": 402653184,
+ "102:6": 268435456,
+ "103:6": 402653184,
+ "104:6": 268435456,
+ "105:6": 402653184,
+ "106:6": 268435456,
+ "107:6": 402653184,
+ "108:6": 268435456,
+ "109:6": 402653184,
+ "110:6": 268435456,
+ "111:6": 402653184,
+ "112:6": 268435456,
+ "113:6": 402653184,
+ "114:6": 268435456,
+ "115:6": 402653184,
+ "116:6": 268435456,
+ "117:6": 402653184,
+ "118:6": 268435456,
+ "119:6": 402653184,
+ "120:6": 268435456,
+ "121:6": 402653184,
+ "122:6": 268435456,
+ "123:6": 402653184,
+ "124:6": 268435456,
+ "125:6": 402653184,
+ "126:6": 268435456,
+ "127:6": 402653184,
+ "0:7": 402653184,
+ "1:7": 268435456,
+ "2:7": 402653184,
+ "3:7": 268435456,
+ "4:7": 402653184,
+ "5:7": 268435456,
+ "6:7": 402653184,
+ "7:7": 268435456,
+ "8:7": 402653184,
+ "9:7": 268435456,
+ "10:7": 402653184,
+ "11:7": 268435456,
+ "12:7": 402653184,
+ "13:7": 268435456,
+ "14:7": 402653184,
+ "15:7": 268435456,
+ "16:7": 402653184,
+ "17:7": 268435456,
+ "18:7": 402653184,
+ "19:7": 268435456,
+ "20:7": 402653184,
+ "21:7": 268435456,
+ "22:7": 402653184,
+ "23:7": 268435456,
+ "24:7": 402653184,
+ "25:7": 268435456,
+ "26:7": 402653184,
+ "27:7": 268435456,
+ "28:7": 402653184,
+ "29:7": 268435456,
+ "30:7": 402653184,
+ "31:7": 268435456,
+ "32:7": 402653184,
+ "33:7": 268435456,
+ "34:7": 402653184,
+ "35:7": 268435456,
+ "36:7": 402653184,
+ "37:7": 268435456,
+ "38:7": 402653184,
+ "39:7": 268435456,
+ "40:7": 402653184,
+ "41:7": 268435456,
+ "42:7": 402653184,
+ "43:7": 268435456,
+ "44:7": 402653184,
+ "45:7": 268435456,
+ "46:7": 402653184,
+ "47:7": 268435456,
+ "48:7": 402653184,
+ "49:7": 268435456,
+ "50:7": 402653184,
+ "51:7": 268435456,
+ "52:7": 402653184,
+ "53:7": 268435456,
+ "54:7": 402653184,
+ "55:7": 268435456,
+ "56:7": 402653184,
+ "57:7": 268435456,
+ "58:7": 402653184,
+ "59:7": 268435456,
+ "60:7": 402653184,
+ "61:7": 268435456,
+ "62:7": 402653184,
+ "63:7": 268435456,
+ "64:7": 402653184,
+ "65:7": 268435456,
+ "66:7": 402653184,
+ "67:7": 268435456,
+ "68:7": 402653184,
+ "69:7": 268435456,
+ "70:7": 402653184,
+ "71:7": 268435456,
+ "72:7": 402653184,
+ "73:7": 268435456,
+ "74:7": 402653184,
+ "75:7": 268435456,
+ "76:7": 402653184,
+ "77:7": 268435456,
+ "78:7": 402653184,
+ "79:7": 268435456,
+ "80:7": 402653184,
+ "81:7": 268435456,
+ "82:7": 402653184,
+ "83:7": 268435456,
+ "84:7": 402653184,
+ "85:7": 268435456,
+ "86:7": 402653184,
+ "87:7": 268435456,
+ "88:7": 402653184,
+ "89:7": 268435456,
+ "90:7": 402653184,
+ "91:7": 268435456,
+ "92:7": 402653184,
+ "93:7": 268435456,
+ "94:7": 402653184,
+ "95:7": 268435456,
+ "96:7": 402653184,
+ "97:7": 268435456,
+ "98:7": 402653184,
+ "99:7": 268435456,
+ "100:7": 402653184,
+ "101:7": 268435456,
+ "102:7": 402653184,
+ "103:7": 268435456,
+ "104:7": 402653184,
+ "105:7": 268435456,
+ "106:7": 402653184,
+ "107:7": 268435456,
+ "108:7": 402653184,
+ "109:7": 268435456,
+ "110:7": 402653184,
+ "111:7": 268435456,
+ "112:7": 402653184,
+ "113:7": 268435456,
+ "114:7": 402653184,
+ "115:7": 268435456,
+ "116:7": 402653184,
+ "117:7": 268435456,
+ "118:7": 402653184,
+ "119:7": 268435456,
+ "120:7": 402653184,
+ "121:7": 268435456,
+ "122:7": 402653184,
+ "123:7": 268435456,
+ "124:7": 402653184,
+ "125:7": 268435456,
+ "126:7": 402653184,
+ "127:7": 268435456,
+ "0:8": 268435456,
+ "1:8": 402653184,
+ "2:8": 268435456,
+ "3:8": 402653184,
+ "4:8": 268435456,
+ "5:8": 402653184,
+ "6:8": 268435456,
+ "7:8": 402653184,
+ "8:8": 268435456,
+ "9:8": 402653184,
+ "10:8": 268435456,
+ "11:8": 402653184,
+ "12:8": 268435456,
+ "13:8": 402653184,
+ "14:8": 268435456,
+ "15:8": 402653184,
+ "16:8": 268435456,
+ "17:8": 402653184,
+ "18:8": 268435456,
+ "19:8": 402653184,
+ "20:8": 268435456,
+ "21:8": 402653184,
+ "22:8": 268435456,
+ "23:8": 402653184,
+ "24:8": 268435456,
+ "25:8": 402653184,
+ "26:8": 268435456,
+ "27:8": 402653184,
+ "28:8": 268435456,
+ "29:8": 402653184,
+ "30:8": 268435456,
+ "31:8": 402653184,
+ "32:8": 268435456,
+ "33:8": 402653184,
+ "34:8": 268435456,
+ "35:8": 402653184,
+ "36:8": 268435456,
+ "37:8": 402653184,
+ "38:8": 268435456,
+ "39:8": 402653184,
+ "40:8": 268435456,
+ "41:8": 402653184,
+ "42:8": 268435456,
+ "43:8": 402653184,
+ "44:8": 268435456,
+ "45:8": 402653184,
+ "46:8": 268435456,
+ "47:8": 402653184,
+ "48:8": 268435456,
+ "49:8": 402653184,
+ "50:8": 268435456,
+ "51:8": 402653184,
+ "52:8": 268435456,
+ "53:8": 402653184,
+ "54:8": 268435456,
+ "55:8": 402653184,
+ "56:8": 268435456,
+ "57:8": 402653184,
+ "58:8": 268435456,
+ "59:8": 402653184,
+ "60:8": 268435456,
+ "61:8": 402653184,
+ "62:8": 268435456,
+ "63:8": 402653184,
+ "64:8": 268435456,
+ "65:8": 402653184,
+ "66:8": 268435456,
+ "67:8": 402653184,
+ "68:8": 268435456,
+ "69:8": 402653184,
+ "70:8": 268435456,
+ "71:8": 402653184,
+ "72:8": 268435456,
+ "73:8": 402653184,
+ "74:8": 268435456,
+ "75:8": 402653184,
+ "76:8": 268435456,
+ "77:8": 402653184,
+ "78:8": 268435456,
+ "79:8": 402653184,
+ "80:8": 268435456,
+ "81:8": 402653184,
+ "82:8": 268435456,
+ "83:8": 402653184,
+ "84:8": 268435456,
+ "85:8": 402653184,
+ "86:8": 268435456,
+ "87:8": 402653184,
+ "88:8": 268435456,
+ "89:8": 402653184,
+ "90:8": 268435456,
+ "91:8": 402653184,
+ "92:8": 268435456,
+ "93:8": 402653184,
+ "94:8": 268435456,
+ "95:8": 402653184,
+ "96:8": 268435456,
+ "97:8": 402653184,
+ "98:8": 268435456,
+ "99:8": 402653184,
+ "100:8": 268435456,
+ "101:8": 402653184,
+ "102:8": 268435456,
+ "103:8": 402653184,
+ "104:8": 268435456,
+ "105:8": 402653184,
+ "106:8": 268435456,
+ "107:8": 402653184,
+ "108:8": 268435456,
+ "109:8": 402653184,
+ "110:8": 268435456,
+ "111:8": 402653184,
+ "112:8": 268435456,
+ "113:8": 402653184,
+ "114:8": 268435456,
+ "115:8": 402653184,
+ "116:8": 268435456,
+ "117:8": 402653184,
+ "118:8": 268435456,
+ "119:8": 402653184,
+ "120:8": 268435456,
+ "121:8": 402653184,
+ "122:8": 268435456,
+ "123:8": 402653184,
+ "124:8": 268435456,
+ "125:8": 402653184,
+ "126:8": 268435456,
+ "127:8": 402653184,
+ "0:9": 402653184,
+ "1:9": 268435456,
+ "2:9": 402653184,
+ "3:9": 268435456,
+ "4:9": 402653184,
+ "5:9": 268435456,
+ "6:9": 402653184,
+ "7:9": 268435456,
+ "8:9": 402653184,
+ "9:9": 268435456,
+ "10:9": 402653184,
+ "11:9": 268435456,
+ "12:9": 402653184,
+ "13:9": 268435456,
+ "14:9": 402653184,
+ "15:9": 268435456,
+ "16:9": 402653184,
+ "17:9": 268435456,
+ "18:9": 402653184,
+ "19:9": 268435456,
+ "20:9": 402653184,
+ "21:9": 268435456,
+ "22:9": 402653184,
+ "23:9": 268435456,
+ "24:9": 402653184,
+ "25:9": 268435456,
+ "26:9": 402653184,
+ "27:9": 268435456,
+ "28:9": 402653184,
+ "29:9": 268435456,
+ "30:9": 402653184,
+ "31:9": 268435456,
+ "32:9": 402653184,
+ "33:9": 268435456,
+ "34:9": 402653184,
+ "35:9": 268435456,
+ "36:9": 402653184,
+ "37:9": 268435456,
+ "38:9": 402653184,
+ "39:9": 268435456,
+ "40:9": 402653184,
+ "41:9": 268435456,
+ "42:9": 402653184,
+ "43:9": 268435456,
+ "44:9": 402653184,
+ "45:9": 268435456,
+ "46:9": 402653184,
+ "47:9": 268435456,
+ "48:9": 402653184,
+ "49:9": 268435456,
+ "50:9": 402653184,
+ "51:9": 268435456,
+ "52:9": 402653184,
+ "53:9": 268435456,
+ "54:9": 402653184,
+ "55:9": 268435456,
+ "56:9": 402653184,
+ "57:9": 268435456,
+ "58:9": 402653184,
+ "59:9": 268435456,
+ "60:9": 402653184,
+ "61:9": 268435456,
+ "62:9": 402653184,
+ "63:9": 268435456,
+ "64:9": 402653184,
+ "65:9": 268435456,
+ "66:9": 402653184,
+ "67:9": 268435456,
+ "68:9": 402653184,
+ "69:9": 268435456,
+ "70:9": 402653184,
+ "71:9": 268435456,
+ "72:9": 402653184,
+ "73:9": 268435456,
+ "74:9": 402653184,
+ "75:9": 268435456,
+ "76:9": 402653184,
+ "77:9": 268435456,
+ "78:9": 402653184,
+ "79:9": 268435456,
+ "80:9": 402653184,
+ "81:9": 268435456,
+ "82:9": 402653184,
+ "83:9": 268435456,
+ "84:9": 402653184,
+ "85:9": 268435456,
+ "86:9": 402653184,
+ "87:9": 268435456,
+ "88:9": 402653184,
+ "89:9": 268435456,
+ "90:9": 402653184,
+ "91:9": 268435456,
+ "92:9": 402653184,
+ "93:9": 268435456,
+ "94:9": 402653184,
+ "95:9": 268435456,
+ "96:9": 402653184,
+ "97:9": 268435456,
+ "98:9": 402653184,
+ "99:9": 268435456,
+ "100:9": 402653184,
+ "101:9": 268435456,
+ "102:9": 402653184,
+ "103:9": 268435456,
+ "104:9": 402653184,
+ "105:9": 268435456,
+ "106:9": 402653184,
+ "107:9": 268435456,
+ "108:9": 402653184,
+ "109:9": 268435456,
+ "110:9": 402653184,
+ "111:9": 268435456,
+ "112:9": 402653184,
+ "113:9": 268435456,
+ "114:9": 402653184,
+ "115:9": 268435456,
+ "116:9": 402653184,
+ "117:9": 268435456,
+ "118:9": 402653184,
+ "119:9": 268435456,
+ "120:9": 402653184,
+ "121:9": 268435456,
+ "122:9": 402653184,
+ "123:9": 268435456,
+ "124:9": 402653184,
+ "125:9": 268435456,
+ "126:9": 402653184,
+ "127:9": 268435456,
+ "0:10": 268435456,
+ "1:10": 402653184,
+ "2:10": 268435456,
+ "3:10": 402653184,
+ "4:10": 268435456,
+ "5:10": 402653184,
+ "6:10": 268435456,
+ "7:10": 402653184,
+ "8:10": 268435456,
+ "9:10": 402653184,
+ "10:10": 268435456,
+ "11:10": 402653184,
+ "12:10": 268435456,
+ "13:10": 402653184,
+ "14:10": 268435456,
+ "15:10": 402653184,
+ "16:10": 268435456,
+ "17:10": 402653184,
+ "18:10": 268435456,
+ "19:10": 402653184,
+ "20:10": 268435456,
+ "21:10": 402653184,
+ "22:10": 268435456,
+ "23:10": 402653184,
+ "24:10": 268435456,
+ "25:10": 402653184,
+ "26:10": 268435456,
+ "27:10": 402653184,
+ "28:10": 268435456,
+ "29:10": 402653184,
+ "30:10": 268435456,
+ "31:10": 402653184,
+ "32:10": 268435456,
+ "33:10": 402653184,
+ "34:10": 268435456,
+ "35:10": 402653184,
+ "36:10": 268435456,
+ "37:10": 402653184,
+ "38:10": 268435456,
+ "39:10": 402653184,
+ "40:10": 268435456,
+ "41:10": 402653184,
+ "42:10": 268435456,
+ "43:10": 402653184,
+ "44:10": 268435456,
+ "45:10": 402653184,
+ "46:10": 268435456,
+ "47:10": 402653184,
+ "48:10": 268435456,
+ "49:10": 402653184,
+ "50:10": 268435456,
+ "51:10": 402653184,
+ "52:10": 268435456,
+ "53:10": 402653184,
+ "54:10": 268435456,
+ "55:10": 402653184,
+ "56:10": 268435456,
+ "57:10": 402653184,
+ "58:10": 268435456,
+ "59:10": 402653184,
+ "60:10": 268435456,
+ "61:10": 402653184,
+ "62:10": 268435456,
+ "63:10": 402653184,
+ "64:10": 268435456,
+ "65:10": 402653184,
+ "66:10": 268435456,
+ "67:10": 402653184,
+ "68:10": 268435456,
+ "69:10": 402653184,
+ "70:10": 268435456,
+ "71:10": 402653184,
+ "72:10": 268435456,
+ "73:10": 402653184,
+ "74:10": 268435456,
+ "75:10": 402653184,
+ "76:10": 268435456,
+ "77:10": 402653184,
+ "78:10": 268435456,
+ "79:10": 402653184,
+ "80:10": 268435456,
+ "81:10": 402653184,
+ "82:10": 268435456,
+ "83:10": 402653184,
+ "84:10": 268435456,
+ "85:10": 402653184,
+ "86:10": 268435456,
+ "87:10": 402653184,
+ "88:10": 268435456,
+ "89:10": 402653184,
+ "90:10": 268435456,
+ "91:10": 402653184,
+ "92:10": 268435456,
+ "93:10": 402653184,
+ "94:10": 268435456,
+ "95:10": 402653184,
+ "96:10": 268435456,
+ "97:10": 402653184,
+ "98:10": 268435456,
+ "99:10": 402653184,
+ "100:10": 268435456,
+ "101:10": 402653184,
+ "102:10": 268435456,
+ "103:10": 402653184,
+ "104:10": 268435456,
+ "105:10": 402653184,
+ "106:10": 268435456,
+ "107:10": 402653184,
+ "108:10": 268435456,
+ "109:10": 402653184,
+ "110:10": 268435456,
+ "111:10": 402653184,
+ "112:10": 268435456,
+ "113:10": 402653184,
+ "114:10": 268435456,
+ "115:10": 402653184,
+ "116:10": 268435456,
+ "117:10": 402653184,
+ "118:10": 268435456,
+ "119:10": 402653184,
+ "120:10": 268435456,
+ "121:10": 402653184,
+ "122:10": 268435456,
+ "123:10": 402653184,
+ "124:10": 268435456,
+ "125:10": 402653184,
+ "126:10": 268435456,
+ "127:10": 402653184,
+ "0:11": 402653184,
+ "1:11": 268435456,
+ "2:11": 402653184,
+ "3:11": 268435456,
+ "4:11": 402653184,
+ "5:11": 268435456,
+ "6:11": 402653184,
+ "7:11": 268435456,
+ "8:11": 402653184,
+ "9:11": 268435456,
+ "10:11": 402653184,
+ "11:11": 268435456,
+ "12:11": 402653184,
+ "13:11": 268435456,
+ "14:11": 402653184,
+ "15:11": 268435456,
+ "16:11": 402653184,
+ "17:11": 268435456,
+ "18:11": 402653184,
+ "19:11": 268435456,
+ "20:11": 402653184,
+ "21:11": 268435456,
+ "22:11": -9288933,
+ "23:11": -9288933,
+ "24:11": -9288933,
+ "25:11": -9288933,
+ "26:11": -9288933,
+ "27:11": -9288933,
+ "28:11": -9288933,
+ "29:11": -9288933,
+ "30:11": -9288933,
+ "31:11": -9288933,
+ "32:11": -9288933,
+ "33:11": -9288933,
+ "34:11": -9288933,
+ "35:11": -9288933,
+ "36:11": -9288933,
+ "37:11": -9288933,
+ "38:11": -9288933,
+ "39:11": -9288933,
+ "40:11": -9288933,
+ "41:11": -9288933,
+ "42:11": -9288933,
+ "43:11": -9288933,
+ "44:11": -9288933,
+ "45:11": -9288933,
+ "46:11": -9288933,
+ "47:11": -9288933,
+ "48:11": -9288933,
+ "49:11": -9288933,
+ "50:11": -9288933,
+ "51:11": -9288933,
+ "52:11": -9288933,
+ "53:11": -9288933,
+ "54:11": -9288933,
+ "55:11": -9288933,
+ "56:11": -9288933,
+ "57:11": -9288933,
+ "58:11": -9288933,
+ "59:11": -9288933,
+ "60:11": -9288933,
+ "61:11": -9288933,
+ "62:11": 402653184,
+ "63:11": 268435456,
+ "64:11": 402653184,
+ "65:11": 268435456,
+ "66:11": -16745472,
+ "67:11": -16745472,
+ "68:11": -16745472,
+ "69:11": -16745472,
+ "70:11": -16745472,
+ "71:11": -16745472,
+ "72:11": -16745472,
+ "73:11": -16745472,
+ "74:11": -16745472,
+ "75:11": -16745472,
+ "76:11": -16745472,
+ "77:11": -16745472,
+ "78:11": -16745472,
+ "79:11": -16745472,
+ "80:11": -16745472,
+ "81:11": -16745472,
+ "82:11": -16745472,
+ "83:11": -16745472,
+ "84:11": 402653184,
+ "85:11": 268435456,
+ "86:11": 402653184,
+ "87:11": 268435456,
+ "88:11": -9288933,
+ "89:11": -9288933,
+ "90:11": -9288933,
+ "91:11": -9288933,
+ "92:11": -9288933,
+ "93:11": -9288933,
+ "94:11": -9288933,
+ "95:11": -9288933,
+ "96:11": -9288933,
+ "97:11": -9288933,
+ "98:11": -9288933,
+ "99:11": -9288933,
+ "100:11": -9288933,
+ "101:11": -9288933,
+ "102:11": -9288933,
+ "103:11": -9288933,
+ "104:11": -9288933,
+ "105:11": -9288933,
+ "106:11": 402653184,
+ "107:11": 268435456,
+ "108:11": 402653184,
+ "109:11": 268435456,
+ "110:11": 402653184,
+ "111:11": 268435456,
+ "112:11": 402653184,
+ "113:11": 268435456,
+ "114:11": 402653184,
+ "115:11": 268435456,
+ "116:11": 402653184,
+ "117:11": 268435456,
+ "118:11": 402653184,
+ "119:11": 268435456,
+ "120:11": 402653184,
+ "121:11": 268435456,
+ "122:11": 402653184,
+ "123:11": 268435456,
+ "124:11": 402653184,
+ "125:11": 268435456,
+ "126:11": 402653184,
+ "127:11": 268435456,
+ "0:12": 268435456,
+ "1:12": 402653184,
+ "2:12": 268435456,
+ "3:12": 402653184,
+ "4:12": 268435456,
+ "5:12": 402653184,
+ "6:12": 268435456,
+ "7:12": 402653184,
+ "8:12": 268435456,
+ "9:12": 402653184,
+ "10:12": 268435456,
+ "11:12": 402653184,
+ "12:12": 268435456,
+ "13:12": 402653184,
+ "14:12": 268435456,
+ "15:12": 402653184,
+ "16:12": 268435456,
+ "17:12": 402653184,
+ "18:12": 268435456,
+ "19:12": 402653184,
+ "20:12": 268435456,
+ "21:12": 402653184,
+ "22:12": -9288933,
+ "23:12": -9288933,
+ "24:12": -9288933,
+ "25:12": -9288933,
+ "26:12": -9288933,
+ "27:12": -9288933,
+ "28:12": -9288933,
+ "29:12": -9288933,
+ "30:12": -9288933,
+ "31:12": -9288933,
+ "32:12": -9288933,
+ "33:12": -9288933,
+ "34:12": -9288933,
+ "35:12": -9288933,
+ "36:12": -9288933,
+ "37:12": -9288933,
+ "38:12": -9288933,
+ "39:12": -9288933,
+ "40:12": -9288933,
+ "41:12": -9288933,
+ "42:12": -9288933,
+ "43:12": -9288933,
+ "44:12": -9288933,
+ "45:12": -9288933,
+ "46:12": -9288933,
+ "47:12": -9288933,
+ "48:12": -9288933,
+ "49:12": -9288933,
+ "50:12": -9288933,
+ "51:12": -9288933,
+ "52:12": -9288933,
+ "53:12": -9288933,
+ "54:12": -9288933,
+ "55:12": -9288933,
+ "56:12": -9288933,
+ "57:12": -9288933,
+ "58:12": -9288933,
+ "59:12": -9288933,
+ "60:12": -9288933,
+ "61:12": -9288933,
+ "62:12": 268435456,
+ "63:12": 402653184,
+ "64:12": 268435456,
+ "65:12": 402653184,
+ "66:12": -16745472,
+ "67:12": -16745472,
+ "68:12": -16745472,
+ "69:12": -16745472,
+ "70:12": -16745472,
+ "71:12": -16745472,
+ "72:12": -16745472,
+ "73:12": -16745472,
+ "74:12": -16745472,
+ "75:12": -16745472,
+ "76:12": -16745472,
+ "77:12": -16745472,
+ "78:12": -16745472,
+ "79:12": -16745472,
+ "80:12": -16745472,
+ "81:12": -16745472,
+ "82:12": -16745472,
+ "83:12": -16745472,
+ "84:12": 268435456,
+ "85:12": 402653184,
+ "86:12": 268435456,
+ "87:12": 402653184,
+ "88:12": -9288933,
+ "89:12": -9288933,
+ "90:12": -9288933,
+ "91:12": -9288933,
+ "92:12": -9288933,
+ "93:12": -9288933,
+ "94:12": -9288933,
+ "95:12": -9288933,
+ "96:12": -9288933,
+ "97:12": -9288933,
+ "98:12": -9288933,
+ "99:12": -9288933,
+ "100:12": -9288933,
+ "101:12": -9288933,
+ "102:12": -9288933,
+ "103:12": -9288933,
+ "104:12": -9288933,
+ "105:12": -9288933,
+ "106:12": 268435456,
+ "107:12": 402653184,
+ "108:12": 268435456,
+ "109:12": 402653184,
+ "110:12": 268435456,
+ "111:12": 402653184,
+ "112:12": 268435456,
+ "113:12": 402653184,
+ "114:12": 268435456,
+ "115:12": 402653184,
+ "116:12": 268435456,
+ "117:12": 402653184,
+ "118:12": 268435456,
+ "119:12": 402653184,
+ "120:12": 268435456,
+ "121:12": 402653184,
+ "122:12": 268435456,
+ "123:12": 402653184,
+ "124:12": 268435456,
+ "125:12": 402653184,
+ "126:12": 268435456,
+ "127:12": 402653184,
+ "0:13": 402653184,
+ "1:13": 268435456,
+ "2:13": 402653184,
+ "3:13": 268435456,
+ "4:13": 402653184,
+ "5:13": 268435456,
+ "6:13": 402653184,
+ "7:13": 268435456,
+ "8:13": 402653184,
+ "9:13": 268435456,
+ "10:13": 402653184,
+ "11:13": 268435456,
+ "12:13": 402653184,
+ "13:13": 268435456,
+ "14:13": 402653184,
+ "15:13": 268435456,
+ "16:13": 402653184,
+ "17:13": 268435456,
+ "18:13": 402653184,
+ "19:13": 268435456,
+ "20:13": 402653184,
+ "21:13": 268435456,
+ "22:13": -9288933,
+ "23:13": -9288933,
+ "24:13": -9288933,
+ "25:13": -9288933,
+ "26:13": -9288933,
+ "27:13": -9288933,
+ "28:13": -9288933,
+ "29:13": -9288933,
+ "30:13": -9288933,
+ "31:13": -9288933,
+ "32:13": -9288933,
+ "33:13": -9288933,
+ "34:13": -9288933,
+ "35:13": -9288933,
+ "36:13": -9288933,
+ "37:13": -9288933,
+ "38:13": -9288933,
+ "39:13": -9288933,
+ "40:13": -9288933,
+ "41:13": -9288933,
+ "42:13": -9288933,
+ "43:13": -9288933,
+ "44:13": -9288933,
+ "45:13": -9288933,
+ "46:13": -9288933,
+ "47:13": -9288933,
+ "48:13": -9288933,
+ "49:13": -9288933,
+ "50:13": -9288933,
+ "51:13": -9288933,
+ "52:13": -9288933,
+ "53:13": -9288933,
+ "54:13": -9288933,
+ "55:13": -9288933,
+ "56:13": -9288933,
+ "57:13": -9288933,
+ "58:13": -9288933,
+ "59:13": -9288933,
+ "60:13": -9288933,
+ "61:13": -9288933,
+ "62:13": 402653184,
+ "63:13": 268435456,
+ "64:13": 402653184,
+ "65:13": 268435456,
+ "66:13": -16745472,
+ "67:13": -16745472,
+ "68:13": -16745472,
+ "69:13": -16745472,
+ "70:13": -16745472,
+ "71:13": -16745472,
+ "72:13": -16745472,
+ "73:13": -16745472,
+ "74:13": -16745472,
+ "75:13": -16745472,
+ "76:13": -16745472,
+ "77:13": -16745472,
+ "78:13": -16745472,
+ "79:13": -16745472,
+ "80:13": -16745472,
+ "81:13": -16745472,
+ "82:13": -16745472,
+ "83:13": -16745472,
+ "84:13": 402653184,
+ "85:13": 268435456,
+ "86:13": 402653184,
+ "87:13": 268435456,
+ "88:13": -9288933,
+ "89:13": -9288933,
+ "90:13": -9288933,
+ "91:13": -9288933,
+ "92:13": -9288933,
+ "93:13": -9288933,
+ "94:13": -9288933,
+ "95:13": -9288933,
+ "96:13": -9288933,
+ "97:13": -9288933,
+ "98:13": -9288933,
+ "99:13": -9288933,
+ "100:13": -9288933,
+ "101:13": -9288933,
+ "102:13": -9288933,
+ "103:13": -9288933,
+ "104:13": -9288933,
+ "105:13": -9288933,
+ "106:13": 402653184,
+ "107:13": 268435456,
+ "108:13": 402653184,
+ "109:13": 268435456,
+ "110:13": 402653184,
+ "111:13": 268435456,
+ "112:13": 402653184,
+ "113:13": 268435456,
+ "114:13": 402653184,
+ "115:13": 268435456,
+ "116:13": 402653184,
+ "117:13": 268435456,
+ "118:13": 402653184,
+ "119:13": 268435456,
+ "120:13": 402653184,
+ "121:13": 268435456,
+ "122:13": 402653184,
+ "123:13": 268435456,
+ "124:13": 402653184,
+ "125:13": 268435456,
+ "126:13": 402653184,
+ "127:13": 268435456,
+ "0:14": 268435456,
+ "1:14": 402653184,
+ "2:14": 268435456,
+ "3:14": 402653184,
+ "4:14": 268435456,
+ "5:14": 402653184,
+ "6:14": 268435456,
+ "7:14": 402653184,
+ "8:14": 268435456,
+ "9:14": 402653184,
+ "10:14": 268435456,
+ "11:14": 402653184,
+ "12:14": 268435456,
+ "13:14": 402653184,
+ "14:14": 268435456,
+ "15:14": 402653184,
+ "16:14": 268435456,
+ "17:14": 402653184,
+ "18:14": 268435456,
+ "19:14": 402653184,
+ "20:14": 268435456,
+ "21:14": 402653184,
+ "22:14": -9288933,
+ "23:14": -9288933,
+ "24:14": -9288933,
+ "25:14": -9288933,
+ "26:14": -9288933,
+ "27:14": -9288933,
+ "28:14": -9288933,
+ "29:14": -9288933,
+ "30:14": -9288933,
+ "31:14": -9288933,
+ "32:14": -9288933,
+ "33:14": -9288933,
+ "34:14": -9288933,
+ "35:14": -9288933,
+ "36:14": -9288933,
+ "37:14": -9288933,
+ "38:14": -9288933,
+ "39:14": -9288933,
+ "40:14": -9288933,
+ "41:14": -9288933,
+ "42:14": -9288933,
+ "43:14": -9288933,
+ "44:14": -9288933,
+ "45:14": -9288933,
+ "46:14": -9288933,
+ "47:14": -9288933,
+ "48:14": -9288933,
+ "49:14": -9288933,
+ "50:14": -9288933,
+ "51:14": -9288933,
+ "52:14": -9288933,
+ "53:14": -9288933,
+ "54:14": -9288933,
+ "55:14": -9288933,
+ "56:14": -9288933,
+ "57:14": -9288933,
+ "58:14": -9288933,
+ "59:14": -9288933,
+ "60:14": -9288933,
+ "61:14": -9288933,
+ "62:14": 268435456,
+ "63:14": 402653184,
+ "64:14": 268435456,
+ "65:14": 402653184,
+ "66:14": -16745472,
+ "67:14": -16745472,
+ "68:14": -16745472,
+ "69:14": -16745472,
+ "70:14": -16745472,
+ "71:14": -16745472,
+ "72:14": -16745472,
+ "73:14": -16745472,
+ "74:14": -16745472,
+ "75:14": -16745472,
+ "76:14": -16745472,
+ "77:14": -16745472,
+ "78:14": -16745472,
+ "79:14": -16745472,
+ "80:14": -16745472,
+ "81:14": -16745472,
+ "82:14": -16745472,
+ "83:14": -16745472,
+ "84:14": 268435456,
+ "85:14": 402653184,
+ "86:14": 268435456,
+ "87:14": 402653184,
+ "88:14": -9288933,
+ "89:14": -9288933,
+ "90:14": -9288933,
+ "91:14": -9288933,
+ "92:14": -9288933,
+ "93:14": -9288933,
+ "94:14": -9288933,
+ "95:14": -9288933,
+ "96:14": -9288933,
+ "97:14": -9288933,
+ "98:14": -9288933,
+ "99:14": -9288933,
+ "100:14": -9288933,
+ "101:14": -9288933,
+ "102:14": -9288933,
+ "103:14": -9288933,
+ "104:14": -9288933,
+ "105:14": -9288933,
+ "106:14": 268435456,
+ "107:14": 402653184,
+ "108:14": 268435456,
+ "109:14": 402653184,
+ "110:14": 268435456,
+ "111:14": 402653184,
+ "112:14": 268435456,
+ "113:14": 402653184,
+ "114:14": 268435456,
+ "115:14": 402653184,
+ "116:14": 268435456,
+ "117:14": 402653184,
+ "118:14": 268435456,
+ "119:14": 402653184,
+ "120:14": 268435456,
+ "121:14": 402653184,
+ "122:14": 268435456,
+ "123:14": 402653184,
+ "124:14": 268435456,
+ "125:14": 402653184,
+ "126:14": 268435456,
+ "127:14": 402653184,
+ "0:15": 402653184,
+ "1:15": 268435456,
+ "2:15": 402653184,
+ "3:15": 268435456,
+ "4:15": 402653184,
+ "5:15": 268435456,
+ "6:15": 402653184,
+ "7:15": 268435456,
+ "8:15": 402653184,
+ "9:15": 268435456,
+ "10:15": 402653184,
+ "11:15": 268435456,
+ "12:15": 402653184,
+ "13:15": 268435456,
+ "14:15": 402653184,
+ "15:15": 268435456,
+ "16:15": 402653184,
+ "17:15": 268435456,
+ "18:15": 402653184,
+ "19:15": 268435456,
+ "20:15": 402653184,
+ "21:15": 268435456,
+ "22:15": -9288933,
+ "23:15": -9288933,
+ "24:15": -9288933,
+ "25:15": -9288933,
+ "26:15": -9288933,
+ "27:15": -9288933,
+ "28:15": -9288933,
+ "29:15": -9288933,
+ "30:15": -9288933,
+ "31:15": -9288933,
+ "32:15": -9288933,
+ "33:15": -9288933,
+ "34:15": -9288933,
+ "35:15": -9288933,
+ "36:15": -9288933,
+ "37:15": -9288933,
+ "38:15": -9288933,
+ "39:15": -9288933,
+ "40:15": -9288933,
+ "41:15": -9288933,
+ "42:15": -9288933,
+ "43:15": -9288933,
+ "44:15": -9288933,
+ "45:15": -9288933,
+ "46:15": -9288933,
+ "47:15": -9288933,
+ "48:15": -9288933,
+ "49:15": -9288933,
+ "50:15": -9288933,
+ "51:15": -9288933,
+ "52:15": -9288933,
+ "53:15": -9288933,
+ "54:15": -9288933,
+ "55:15": -9288933,
+ "56:15": -9288933,
+ "57:15": -9288933,
+ "58:15": -9288933,
+ "59:15": -9288933,
+ "60:15": -9288933,
+ "61:15": -9288933,
+ "62:15": 402653184,
+ "63:15": 268435456,
+ "64:15": 402653184,
+ "65:15": 268435456,
+ "66:15": -16745472,
+ "67:15": -16745472,
+ "68:15": -16745472,
+ "69:15": -16745472,
+ "70:15": -16745472,
+ "71:15": -16745472,
+ "72:15": -16745472,
+ "73:15": -16745472,
+ "74:15": -16745472,
+ "75:15": -16745472,
+ "76:15": -16745472,
+ "77:15": -16745472,
+ "78:15": -16745472,
+ "79:15": -16745472,
+ "80:15": -16745472,
+ "81:15": -16745472,
+ "82:15": -16745472,
+ "83:15": -16745472,
+ "84:15": 402653184,
+ "85:15": 268435456,
+ "86:15": 402653184,
+ "87:15": 268435456,
+ "88:15": -9288933,
+ "89:15": -9288933,
+ "90:15": -9288933,
+ "91:15": -9288933,
+ "92:15": -9288933,
+ "93:15": -9288933,
+ "94:15": -9288933,
+ "95:15": -9288933,
+ "96:15": -9288933,
+ "97:15": -9288933,
+ "98:15": -9288933,
+ "99:15": -9288933,
+ "100:15": -9288933,
+ "101:15": -9288933,
+ "102:15": -9288933,
+ "103:15": -9288933,
+ "104:15": -9288933,
+ "105:15": -9288933,
+ "106:15": 402653184,
+ "107:15": 268435456,
+ "108:15": 402653184,
+ "109:15": 268435456,
+ "110:15": 402653184,
+ "111:15": 268435456,
+ "112:15": 402653184,
+ "113:15": 268435456,
+ "114:15": 402653184,
+ "115:15": 268435456,
+ "116:15": 402653184,
+ "117:15": 268435456,
+ "118:15": 402653184,
+ "119:15": 268435456,
+ "120:15": 402653184,
+ "121:15": 268435456,
+ "122:15": 402653184,
+ "123:15": 268435456,
+ "124:15": 402653184,
+ "125:15": 268435456,
+ "126:15": 402653184,
+ "127:15": 268435456,
+ "0:16": 268435456,
+ "1:16": 402653184,
+ "2:16": 268435456,
+ "3:16": 402653184,
+ "4:16": 268435456,
+ "5:16": 402653184,
+ "6:16": 268435456,
+ "7:16": 402653184,
+ "8:16": 268435456,
+ "9:16": 402653184,
+ "10:16": 268435456,
+ "11:16": 402653184,
+ "12:16": 268435456,
+ "13:16": 402653184,
+ "14:16": 268435456,
+ "15:16": 402653184,
+ "16:16": 268435456,
+ "17:16": 402653184,
+ "18:16": 268435456,
+ "19:16": 402653184,
+ "20:16": 268435456,
+ "21:16": 402653184,
+ "22:16": -9288933,
+ "23:16": -9288933,
+ "24:16": -9288933,
+ "25:16": -9288933,
+ "26:16": -9288933,
+ "27:16": -9288933,
+ "28:16": -9288933,
+ "29:16": -9288933,
+ "30:16": -9288933,
+ "31:16": -9288933,
+ "32:16": -9288933,
+ "33:16": -9288933,
+ "34:16": -9288933,
+ "35:16": -9288933,
+ "36:16": -9288933,
+ "37:16": -9288933,
+ "38:16": -9288933,
+ "39:16": -9288933,
+ "40:16": -9288933,
+ "41:16": -9288933,
+ "42:16": -9288933,
+ "43:16": -9288933,
+ "44:16": -9288933,
+ "45:16": -9288933,
+ "46:16": -9288933,
+ "47:16": -9288933,
+ "48:16": -9288933,
+ "49:16": -9288933,
+ "50:16": -9288933,
+ "51:16": -9288933,
+ "52:16": -9288933,
+ "53:16": -9288933,
+ "54:16": -9288933,
+ "55:16": -9288933,
+ "56:16": -9288933,
+ "57:16": -9288933,
+ "58:16": -9288933,
+ "59:16": -9288933,
+ "60:16": -9288933,
+ "61:16": -9288933,
+ "62:16": 268435456,
+ "63:16": 402653184,
+ "64:16": 268435456,
+ "65:16": 402653184,
+ "66:16": -16745472,
+ "67:16": -16745472,
+ "68:16": -16745472,
+ "69:16": -16745472,
+ "70:16": -16745472,
+ "71:16": -16745472,
+ "72:16": -16745472,
+ "73:16": -16745472,
+ "74:16": -16745472,
+ "75:16": -16745472,
+ "76:16": -16745472,
+ "77:16": -16745472,
+ "78:16": -16745472,
+ "79:16": -16745472,
+ "80:16": -16745472,
+ "81:16": -16745472,
+ "82:16": -16745472,
+ "83:16": -16745472,
+ "84:16": 268435456,
+ "85:16": 402653184,
+ "86:16": 268435456,
+ "87:16": 402653184,
+ "88:16": -9288933,
+ "89:16": -9288933,
+ "90:16": -9288933,
+ "91:16": -9288933,
+ "92:16": -9288933,
+ "93:16": -9288933,
+ "94:16": -9288933,
+ "95:16": -9288933,
+ "96:16": -9288933,
+ "97:16": -9288933,
+ "98:16": -9288933,
+ "99:16": -9288933,
+ "100:16": -9288933,
+ "101:16": -9288933,
+ "102:16": -9288933,
+ "103:16": -9288933,
+ "104:16": -9288933,
+ "105:16": -9288933,
+ "106:16": 268435456,
+ "107:16": 402653184,
+ "108:16": 268435456,
+ "109:16": 402653184,
+ "110:16": 268435456,
+ "111:16": 402653184,
+ "112:16": 268435456,
+ "113:16": 402653184,
+ "114:16": 268435456,
+ "115:16": 402653184,
+ "116:16": 268435456,
+ "117:16": 402653184,
+ "118:16": 268435456,
+ "119:16": 402653184,
+ "120:16": 268435456,
+ "121:16": 402653184,
+ "122:16": 268435456,
+ "123:16": 402653184,
+ "124:16": 268435456,
+ "125:16": 402653184,
+ "126:16": 268435456,
+ "127:16": 402653184,
+ "0:17": 402653184,
+ "1:17": 268435456,
+ "2:17": 402653184,
+ "3:17": 268435456,
+ "4:17": 402653184,
+ "5:17": 268435456,
+ "6:17": 402653184,
+ "7:17": 268435456,
+ "8:17": 402653184,
+ "9:17": 268435456,
+ "10:17": 402653184,
+ "11:17": 268435456,
+ "12:17": 402653184,
+ "13:17": 268435456,
+ "14:17": 402653184,
+ "15:17": 268435456,
+ "16:17": 402653184,
+ "17:17": 268435456,
+ "18:17": 402653184,
+ "19:17": 268435456,
+ "20:17": 402653184,
+ "21:17": 268435456,
+ "22:17": -9288933,
+ "23:17": -9288933,
+ "24:17": -9288933,
+ "25:17": -9288933,
+ "26:17": -9288933,
+ "27:17": -9288933,
+ "28:17": -9288933,
+ "29:17": -9288933,
+ "30:17": -9288933,
+ "31:17": -9288933,
+ "32:17": -9288933,
+ "33:17": -9288933,
+ "34:17": -9288933,
+ "35:17": -9288933,
+ "36:17": -9288933,
+ "37:17": -9288933,
+ "38:17": -9288933,
+ "39:17": -9288933,
+ "40:17": -9288933,
+ "41:17": -9288933,
+ "42:17": -9288933,
+ "43:17": -9288933,
+ "44:17": -9288933,
+ "45:17": -9288933,
+ "46:17": -9288933,
+ "47:17": -9288933,
+ "48:17": -9288933,
+ "49:17": -9288933,
+ "50:17": -9288933,
+ "51:17": -9288933,
+ "52:17": -9288933,
+ "53:17": -9288933,
+ "54:17": -9288933,
+ "55:17": -9288933,
+ "56:17": -9288933,
+ "57:17": -9288933,
+ "58:17": -9288933,
+ "59:17": -9288933,
+ "60:17": -9288933,
+ "61:17": -9288933,
+ "62:17": -9288933,
+ "63:17": -9288933,
+ "64:17": -9288933,
+ "65:17": -9288933,
+ "66:17": -16745472,
+ "67:17": -16745472,
+ "68:17": -16745472,
+ "69:17": -16745472,
+ "70:17": -16745472,
+ "71:17": -16745472,
+ "72:17": -16745472,
+ "73:17": -16745472,
+ "74:17": -16745472,
+ "75:17": -16745472,
+ "76:17": -16745472,
+ "77:17": -16745472,
+ "78:17": -16745472,
+ "79:17": -16745472,
+ "80:17": -16745472,
+ "81:17": -16745472,
+ "82:17": -16745472,
+ "83:17": -16745472,
+ "84:17": 402653184,
+ "85:17": 268435456,
+ "86:17": 402653184,
+ "87:17": 268435456,
+ "88:17": -9288933,
+ "89:17": -9288933,
+ "90:17": -9288933,
+ "91:17": -9288933,
+ "92:17": -9288933,
+ "93:17": -9288933,
+ "94:17": -9288933,
+ "95:17": -9288933,
+ "96:17": -9288933,
+ "97:17": -9288933,
+ "98:17": -9288933,
+ "99:17": -9288933,
+ "100:17": -9288933,
+ "101:17": -9288933,
+ "102:17": -9288933,
+ "103:17": -9288933,
+ "104:17": -9288933,
+ "105:17": -9288933,
+ "106:17": 402653184,
+ "107:17": 268435456,
+ "108:17": 402653184,
+ "109:17": 268435456,
+ "110:17": 402653184,
+ "111:17": 268435456,
+ "112:17": 402653184,
+ "113:17": 268435456,
+ "114:17": 402653184,
+ "115:17": 268435456,
+ "116:17": 402653184,
+ "117:17": 268435456,
+ "118:17": 402653184,
+ "119:17": 268435456,
+ "120:17": 402653184,
+ "121:17": 268435456,
+ "122:17": 402653184,
+ "123:17": 268435456,
+ "124:17": 402653184,
+ "125:17": 268435456,
+ "126:17": 402653184,
+ "127:17": 268435456,
+ "0:18": 268435456,
+ "1:18": 402653184,
+ "2:18": 268435456,
+ "3:18": 402653184,
+ "4:18": 268435456,
+ "5:18": 402653184,
+ "6:18": 268435456,
+ "7:18": 402653184,
+ "8:18": 268435456,
+ "9:18": 402653184,
+ "10:18": 268435456,
+ "11:18": 402653184,
+ "12:18": 268435456,
+ "13:18": 402653184,
+ "14:18": 268435456,
+ "15:18": 402653184,
+ "16:18": 268435456,
+ "17:18": 402653184,
+ "18:18": 268435456,
+ "19:18": 402653184,
+ "20:18": 268435456,
+ "21:18": 402653184,
+ "22:18": -9288933,
+ "23:18": -9288933,
+ "24:18": -9288933,
+ "25:18": -9288933,
+ "26:18": -9288933,
+ "27:18": -9288933,
+ "28:18": -9288933,
+ "29:18": -9288933,
+ "30:18": -9288933,
+ "31:18": -9288933,
+ "32:18": -1,
+ "33:18": -1,
+ "34:18": -1,
+ "35:18": -9288933,
+ "36:18": -9288933,
+ "37:18": -9288933,
+ "38:18": -9288933,
+ "39:18": -9288933,
+ "40:18": -9288933,
+ "41:18": -9288933,
+ "42:18": -9288933,
+ "43:18": -9288933,
+ "44:18": -9288933,
+ "45:18": -9288933,
+ "46:18": -9288933,
+ "47:18": -9288933,
+ "48:18": -9288933,
+ "49:18": -9288933,
+ "50:18": -9288933,
+ "51:18": -9288933,
+ "52:18": -9288933,
+ "53:18": -9288933,
+ "54:18": -9288933,
+ "55:18": -9288933,
+ "56:18": -9288933,
+ "57:18": -9288933,
+ "58:18": -9288933,
+ "59:18": -9288933,
+ "60:18": -9288933,
+ "61:18": -9288933,
+ "62:18": -9288933,
+ "63:18": -9288933,
+ "64:18": -9288933,
+ "65:18": -9288933,
+ "66:18": -16745472,
+ "67:18": -16745472,
+ "68:18": -16745472,
+ "69:18": -16745472,
+ "70:18": -16745472,
+ "71:18": -16745472,
+ "72:18": -16745472,
+ "73:18": -16745472,
+ "74:18": -16745472,
+ "75:18": -16745472,
+ "76:18": -16745472,
+ "77:18": -16745472,
+ "78:18": -16745472,
+ "79:18": -16745472,
+ "80:18": -16745472,
+ "81:18": -16745472,
+ "82:18": -16745472,
+ "83:18": -16745472,
+ "84:18": 268435456,
+ "85:18": 402653184,
+ "86:18": 268435456,
+ "87:18": 402653184,
+ "88:18": -9288933,
+ "89:18": -9288933,
+ "90:18": -9288933,
+ "91:18": -9288933,
+ "92:18": -9288933,
+ "93:18": -9288933,
+ "94:18": -9288933,
+ "95:18": -9288933,
+ "96:18": -9288933,
+ "97:18": -9288933,
+ "98:18": -1,
+ "99:18": -1,
+ "100:18": -1,
+ "101:18": -9288933,
+ "102:18": -9288933,
+ "103:18": -9288933,
+ "104:18": -9288933,
+ "105:18": -9288933,
+ "106:18": 268435456,
+ "107:18": 402653184,
+ "108:18": 268435456,
+ "109:18": 402653184,
+ "110:18": 268435456,
+ "111:18": 402653184,
+ "112:18": 268435456,
+ "113:18": 402653184,
+ "114:18": 268435456,
+ "115:18": 402653184,
+ "116:18": 268435456,
+ "117:18": 402653184,
+ "118:18": 268435456,
+ "119:18": 402653184,
+ "120:18": 268435456,
+ "121:18": 402653184,
+ "122:18": 268435456,
+ "123:18": 402653184,
+ "124:18": 268435456,
+ "125:18": 402653184,
+ "126:18": 268435456,
+ "127:18": 402653184,
+ "0:19": 402653184,
+ "1:19": 268435456,
+ "2:19": 402653184,
+ "3:19": 268435456,
+ "4:19": 402653184,
+ "5:19": 268435456,
+ "6:19": 402653184,
+ "7:19": 268435456,
+ "8:19": 402653184,
+ "9:19": 268435456,
+ "10:19": 402653184,
+ "11:19": 268435456,
+ "12:19": 402653184,
+ "13:19": 268435456,
+ "14:19": 402653184,
+ "15:19": 268435456,
+ "16:19": 402653184,
+ "17:19": 268435456,
+ "18:19": 402653184,
+ "19:19": 268435456,
+ "20:19": 402653184,
+ "21:19": 268435456,
+ "22:19": -9288933,
+ "23:19": -9288933,
+ "24:19": -9288933,
+ "25:19": -9288933,
+ "26:19": -9288933,
+ "27:19": -9288933,
+ "28:19": -9288933,
+ "29:19": -9288933,
+ "30:19": -9288933,
+ "31:19": -1,
+ "32:19": -1,
+ "33:19": -1,
+ "34:19": -9288933,
+ "35:19": -9288933,
+ "36:19": -9288933,
+ "37:19": -9288933,
+ "38:19": -9288933,
+ "39:19": -9288933,
+ "40:19": -9288933,
+ "41:19": -9288933,
+ "42:19": -9288933,
+ "43:19": -9288933,
+ "44:19": -9288933,
+ "45:19": -9288933,
+ "46:19": -9288933,
+ "47:19": -9288933,
+ "48:19": -9288933,
+ "49:19": -9288933,
+ "50:19": -9288933,
+ "51:19": -9288933,
+ "52:19": -9288933,
+ "53:19": -9288933,
+ "54:19": -9288933,
+ "55:19": -9288933,
+ "56:19": -9288933,
+ "57:19": -9288933,
+ "58:19": -9288933,
+ "59:19": -9288933,
+ "60:19": -9288933,
+ "61:19": -9288933,
+ "62:19": -9288933,
+ "63:19": -9288933,
+ "64:19": -9288933,
+ "65:19": -9288933,
+ "66:19": -16745472,
+ "67:19": -16745472,
+ "68:19": -16745472,
+ "69:19": -16745472,
+ "70:19": -16745472,
+ "71:19": -16745472,
+ "72:19": -16745472,
+ "73:19": -16745472,
+ "74:19": -16745472,
+ "75:19": -16745472,
+ "76:19": -16745472,
+ "77:19": -16745472,
+ "78:19": -16745472,
+ "79:19": -16745472,
+ "80:19": -16745472,
+ "81:19": -16745472,
+ "82:19": -16745472,
+ "83:19": -16745472,
+ "84:19": 402653184,
+ "85:19": 268435456,
+ "86:19": 402653184,
+ "87:19": 268435456,
+ "88:19": -9288933,
+ "89:19": -9288933,
+ "90:19": -9288933,
+ "91:19": -9288933,
+ "92:19": -9288933,
+ "93:19": -9288933,
+ "94:19": -9288933,
+ "95:19": -9288933,
+ "96:19": -9288933,
+ "97:19": -1,
+ "98:19": -1,
+ "99:19": -1,
+ "100:19": -9288933,
+ "101:19": -9288933,
+ "102:19": -9288933,
+ "103:19": -9288933,
+ "104:19": -9288933,
+ "105:19": -9288933,
+ "106:19": 402653184,
+ "107:19": 268435456,
+ "108:19": 402653184,
+ "109:19": 268435456,
+ "110:19": 402653184,
+ "111:19": 268435456,
+ "112:19": 402653184,
+ "113:19": 268435456,
+ "114:19": 402653184,
+ "115:19": 268435456,
+ "116:19": 402653184,
+ "117:19": 268435456,
+ "118:19": 402653184,
+ "119:19": 268435456,
+ "120:19": 402653184,
+ "121:19": 268435456,
+ "122:19": 402653184,
+ "123:19": 268435456,
+ "124:19": 402653184,
+ "125:19": 268435456,
+ "126:19": 402653184,
+ "127:19": 268435456,
+ "0:20": 268435456,
+ "1:20": 402653184,
+ "2:20": 268435456,
+ "3:20": 402653184,
+ "4:20": 268435456,
+ "5:20": 402653184,
+ "6:20": 268435456,
+ "7:20": 402653184,
+ "8:20": 268435456,
+ "9:20": 402653184,
+ "10:20": 268435456,
+ "11:20": 402653184,
+ "12:20": 268435456,
+ "13:20": 402653184,
+ "14:20": 268435456,
+ "15:20": 402653184,
+ "16:20": 268435456,
+ "17:20": 402653184,
+ "18:20": 268435456,
+ "19:20": 402653184,
+ "20:20": 268435456,
+ "21:20": 402653184,
+ "22:20": -9288933,
+ "23:20": -9288933,
+ "24:20": -9288933,
+ "25:20": -9288933,
+ "26:20": -9288933,
+ "27:20": -9288933,
+ "28:20": -9288933,
+ "29:20": -9288933,
+ "30:20": -9288933,
+ "31:20": -1,
+ "32:20": -1,
+ "33:20": -9288933,
+ "34:20": -9288933,
+ "35:20": -9288933,
+ "36:20": -9288933,
+ "37:20": -9288933,
+ "38:20": -9288933,
+ "39:20": -9288933,
+ "40:20": -9288933,
+ "41:20": -9288933,
+ "42:20": -9288933,
+ "43:20": -9288933,
+ "44:20": -9288933,
+ "45:20": -9288933,
+ "46:20": -9288933,
+ "47:20": -9288933,
+ "48:20": -9288933,
+ "49:20": -9288933,
+ "50:20": -9288933,
+ "51:20": -9288933,
+ "52:20": -9288933,
+ "53:20": -9288933,
+ "54:20": -9288933,
+ "55:20": -9288933,
+ "56:20": -9288933,
+ "57:20": -9288933,
+ "58:20": -9288933,
+ "59:20": -9288933,
+ "60:20": -9288933,
+ "61:20": -9288933,
+ "62:20": -9288933,
+ "63:20": -9288933,
+ "64:20": -9288933,
+ "65:20": -9288933,
+ "66:20": -16745472,
+ "67:20": -16745472,
+ "68:20": -16745472,
+ "69:20": -16745472,
+ "70:20": -16745472,
+ "71:20": -16745472,
+ "72:20": -16745472,
+ "73:20": -16745472,
+ "74:20": -16745472,
+ "75:20": -16745472,
+ "76:20": -16745472,
+ "77:20": -16745472,
+ "78:20": -16745472,
+ "79:20": -16745472,
+ "80:20": -16745472,
+ "81:20": -16745472,
+ "82:20": -16745472,
+ "83:20": -16745472,
+ "84:20": 268435456,
+ "85:20": 402653184,
+ "86:20": 268435456,
+ "87:20": 402653184,
+ "88:20": -9288933,
+ "89:20": -9288933,
+ "90:20": -9288933,
+ "91:20": -9288933,
+ "92:20": -9288933,
+ "93:20": -9288933,
+ "94:20": -9288933,
+ "95:20": -9288933,
+ "96:20": -9288933,
+ "97:20": -1,
+ "98:20": -1,
+ "99:20": -9288933,
+ "100:20": -9288933,
+ "101:20": -9288933,
+ "102:20": -9288933,
+ "103:20": -9288933,
+ "104:20": -9288933,
+ "105:20": -9288933,
+ "106:20": 268435456,
+ "107:20": 402653184,
+ "108:20": 268435456,
+ "109:20": 402653184,
+ "110:20": 268435456,
+ "111:20": 402653184,
+ "112:20": 268435456,
+ "113:20": 402653184,
+ "114:20": 268435456,
+ "115:20": 402653184,
+ "116:20": 268435456,
+ "117:20": 402653184,
+ "118:20": 268435456,
+ "119:20": 402653184,
+ "120:20": 268435456,
+ "121:20": 402653184,
+ "122:20": 268435456,
+ "123:20": 402653184,
+ "124:20": 268435456,
+ "125:20": 402653184,
+ "126:20": 268435456,
+ "127:20": 402653184,
+ "0:21": 402653184,
+ "1:21": 268435456,
+ "2:21": 402653184,
+ "3:21": 268435456,
+ "4:21": 402653184,
+ "5:21": 268435456,
+ "6:21": 402653184,
+ "7:21": 268435456,
+ "8:21": 402653184,
+ "9:21": 268435456,
+ "10:21": 402653184,
+ "11:21": 268435456,
+ "12:21": 402653184,
+ "13:21": 268435456,
+ "14:21": 402653184,
+ "15:21": 268435456,
+ "16:21": 402653184,
+ "17:21": 268435456,
+ "18:21": 402653184,
+ "19:21": 268435456,
+ "20:21": 402653184,
+ "21:21": 268435456,
+ "22:21": -9288933,
+ "23:21": -9288933,
+ "24:21": -9288933,
+ "25:21": -9288933,
+ "26:21": -9288933,
+ "27:21": -9288933,
+ "28:21": -1,
+ "29:21": -1,
+ "30:21": -9288933,
+ "31:21": -1,
+ "32:21": -1,
+ "33:21": -9288933,
+ "34:21": -9288933,
+ "35:21": -9288933,
+ "36:21": -9288933,
+ "37:21": -9288933,
+ "38:21": -9288933,
+ "39:21": -9288933,
+ "40:21": -9288933,
+ "41:21": -9288933,
+ "42:21": -9288933,
+ "43:21": -9288933,
+ "44:21": -9288933,
+ "45:21": -9288933,
+ "46:21": -9288933,
+ "47:21": -9288933,
+ "48:21": -9288933,
+ "49:21": -9288933,
+ "50:21": -9288933,
+ "51:21": -9288933,
+ "52:21": -9288933,
+ "53:21": -9288933,
+ "54:21": -9288933,
+ "55:21": -9288933,
+ "56:21": -9288933,
+ "57:21": -9288933,
+ "58:21": -9288933,
+ "59:21": -9288933,
+ "60:21": -9288933,
+ "61:21": -9288933,
+ "62:21": -9288933,
+ "63:21": -9288933,
+ "64:21": -9288933,
+ "65:21": -9288933,
+ "66:21": -16745472,
+ "67:21": -16745472,
+ "68:21": -16745472,
+ "69:21": -16745472,
+ "70:21": -16745472,
+ "71:21": -16745472,
+ "72:21": -16745472,
+ "73:21": -16745472,
+ "74:21": -16745472,
+ "75:21": -16745472,
+ "76:21": -16745472,
+ "77:21": -16745472,
+ "78:21": -16745472,
+ "79:21": -16745472,
+ "80:21": -16745472,
+ "81:21": -16745472,
+ "82:21": -16745472,
+ "83:21": -16745472,
+ "84:21": 402653184,
+ "85:21": 268435456,
+ "86:21": 402653184,
+ "87:21": 268435456,
+ "88:21": -9288933,
+ "89:21": -9288933,
+ "90:21": -9288933,
+ "91:21": -9288933,
+ "92:21": -9288933,
+ "93:21": -9288933,
+ "94:21": -1,
+ "95:21": -1,
+ "96:21": -9288933,
+ "97:21": -1,
+ "98:21": -1,
+ "99:21": -9288933,
+ "100:21": -9288933,
+ "101:21": -9288933,
+ "102:21": -9288933,
+ "103:21": -9288933,
+ "104:21": -9288933,
+ "105:21": -9288933,
+ "106:21": 402653184,
+ "107:21": 268435456,
+ "108:21": 402653184,
+ "109:21": 268435456,
+ "110:21": 402653184,
+ "111:21": 268435456,
+ "112:21": 402653184,
+ "113:21": 268435456,
+ "114:21": 402653184,
+ "115:21": 268435456,
+ "116:21": 402653184,
+ "117:21": 268435456,
+ "118:21": 402653184,
+ "119:21": 268435456,
+ "120:21": 402653184,
+ "121:21": 268435456,
+ "122:21": 402653184,
+ "123:21": 268435456,
+ "124:21": 402653184,
+ "125:21": 268435456,
+ "126:21": 402653184,
+ "127:21": 268435456,
+ "0:22": 268435456,
+ "1:22": 402653184,
+ "2:22": 268435456,
+ "3:22": 402653184,
+ "4:22": 268435456,
+ "5:22": 402653184,
+ "6:22": 268435456,
+ "7:22": 402653184,
+ "8:22": 268435456,
+ "9:22": 402653184,
+ "10:22": 268435456,
+ "11:22": 402653184,
+ "12:22": 268435456,
+ "13:22": 402653184,
+ "14:22": 268435456,
+ "15:22": 402653184,
+ "16:22": 268435456,
+ "17:22": 402653184,
+ "18:22": 268435456,
+ "19:22": 402653184,
+ "20:22": 268435456,
+ "21:22": 402653184,
+ "22:22": -9288933,
+ "23:22": -9288933,
+ "24:22": -9288933,
+ "25:22": -9288933,
+ "26:22": -9288933,
+ "27:22": -9288933,
+ "28:22": -9288933,
+ "29:22": -1,
+ "30:22": -1,
+ "31:22": -1,
+ "32:22": -9288933,
+ "33:22": -9288933,
+ "34:22": -9288933,
+ "35:22": -9288933,
+ "36:22": -9288933,
+ "37:22": -9288933,
+ "38:22": -9288933,
+ "39:22": -9288933,
+ "40:22": -9288933,
+ "41:22": -9288933,
+ "42:22": -9288933,
+ "43:22": -9288933,
+ "44:22": -9288933,
+ "45:22": -9288933,
+ "46:22": -9288933,
+ "47:22": -9288933,
+ "48:22": -9288933,
+ "49:22": -9288933,
+ "50:22": -9288933,
+ "51:22": -9288933,
+ "52:22": -9288933,
+ "53:22": -9288933,
+ "54:22": -9288933,
+ "55:22": -9288933,
+ "56:22": -9288933,
+ "57:22": -9288933,
+ "58:22": -9288933,
+ "59:22": -9288933,
+ "60:22": -9288933,
+ "61:22": -9288933,
+ "62:22": -9288933,
+ "63:22": -9288933,
+ "64:22": -9288933,
+ "65:22": -9288933,
+ "66:22": -16745472,
+ "67:22": -16745472,
+ "68:22": -16745472,
+ "69:22": -16745472,
+ "70:22": -16745472,
+ "71:22": -16745472,
+ "72:22": -16745472,
+ "73:22": -16745472,
+ "74:22": -16745472,
+ "75:22": -16745472,
+ "76:22": -16745472,
+ "77:22": -16745472,
+ "78:22": -16745472,
+ "79:22": -16745472,
+ "80:22": -16745472,
+ "81:22": -16745472,
+ "82:22": -16745472,
+ "83:22": -16745472,
+ "84:22": 268435456,
+ "85:22": 402653184,
+ "86:22": 268435456,
+ "87:22": 402653184,
+ "88:22": -9288933,
+ "89:22": -9288933,
+ "90:22": -9288933,
+ "91:22": -9288933,
+ "92:22": -9288933,
+ "93:22": -9288933,
+ "94:22": -9288933,
+ "95:22": -1,
+ "96:22": -1,
+ "97:22": -1,
+ "98:22": -9288933,
+ "99:22": -9288933,
+ "100:22": -9288933,
+ "101:22": -9288933,
+ "102:22": -9288933,
+ "103:22": -9288933,
+ "104:22": -9288933,
+ "105:22": -9288933,
+ "106:22": 268435456,
+ "107:22": 402653184,
+ "108:22": 268435456,
+ "109:22": 402653184,
+ "110:22": 268435456,
+ "111:22": 402653184,
+ "112:22": 268435456,
+ "113:22": 402653184,
+ "114:22": 268435456,
+ "115:22": 402653184,
+ "116:22": 268435456,
+ "117:22": 402653184,
+ "118:22": 268435456,
+ "119:22": 402653184,
+ "120:22": 268435456,
+ "121:22": 402653184,
+ "122:22": 268435456,
+ "123:22": 402653184,
+ "124:22": 268435456,
+ "125:22": 402653184,
+ "126:22": 268435456,
+ "127:22": 402653184,
+ "0:23": 402653184,
+ "1:23": 268435456,
+ "2:23": 402653184,
+ "3:23": 268435456,
+ "4:23": 402653184,
+ "5:23": 268435456,
+ "6:23": 402653184,
+ "7:23": 268435456,
+ "8:23": 402653184,
+ "9:23": 268435456,
+ "10:23": 402653184,
+ "11:23": 268435456,
+ "12:23": 402653184,
+ "13:23": 268435456,
+ "14:23": 402653184,
+ "15:23": 268435456,
+ "16:23": 402653184,
+ "17:23": 268435456,
+ "18:23": 402653184,
+ "19:23": 268435456,
+ "20:23": 402653184,
+ "21:23": 268435456,
+ "22:23": -9288933,
+ "23:23": -9288933,
+ "24:23": -9288933,
+ "25:23": -9288933,
+ "26:23": -9288933,
+ "27:23": -9288933,
+ "28:23": -9288933,
+ "29:23": -1,
+ "30:23": -1,
+ "31:23": -1,
+ "32:23": -9288933,
+ "33:23": -9288933,
+ "34:23": -9288933,
+ "35:23": -9288933,
+ "36:23": -9288933,
+ "37:23": -9288933,
+ "38:23": -9288933,
+ "39:23": -9288933,
+ "40:23": -9288933,
+ "41:23": -9288933,
+ "42:23": -9288933,
+ "43:23": -9288933,
+ "44:23": -9288933,
+ "45:23": -9288933,
+ "46:23": -9288933,
+ "47:23": -9288933,
+ "48:23": -9288933,
+ "49:23": -9288933,
+ "50:23": -9288933,
+ "51:23": -9288933,
+ "52:23": -9288933,
+ "53:23": -9288933,
+ "54:23": -9288933,
+ "55:23": -9288933,
+ "56:23": -9288933,
+ "57:23": -9288933,
+ "58:23": -9288933,
+ "59:23": -9288933,
+ "60:23": -9288933,
+ "61:23": -9288933,
+ "62:23": -9288933,
+ "63:23": -9288933,
+ "64:23": -9288933,
+ "65:23": -9288933,
+ "66:23": -16745472,
+ "67:23": -16745472,
+ "68:23": -16745472,
+ "69:23": -16745472,
+ "70:23": -16745472,
+ "71:23": -16745472,
+ "72:23": -16745472,
+ "73:23": -16745472,
+ "74:23": -16745472,
+ "75:23": -16745472,
+ "76:23": -16745472,
+ "77:23": -16745472,
+ "78:23": -16745472,
+ "79:23": -16745472,
+ "80:23": -16745472,
+ "81:23": -16745472,
+ "82:23": -16745472,
+ "83:23": -16745472,
+ "84:23": 402653184,
+ "85:23": 268435456,
+ "86:23": 402653184,
+ "87:23": 268435456,
+ "88:23": -9288933,
+ "89:23": -9288933,
+ "90:23": -9288933,
+ "91:23": -9288933,
+ "92:23": -9288933,
+ "93:23": -9288933,
+ "94:23": -9288933,
+ "95:23": -1,
+ "96:23": -1,
+ "97:23": -1,
+ "98:23": -9288933,
+ "99:23": -9288933,
+ "100:23": -9288933,
+ "101:23": -9288933,
+ "102:23": -9288933,
+ "103:23": -9288933,
+ "104:23": -9288933,
+ "105:23": -9288933,
+ "106:23": 402653184,
+ "107:23": 268435456,
+ "108:23": 402653184,
+ "109:23": 268435456,
+ "110:23": 402653184,
+ "111:23": 268435456,
+ "112:23": 402653184,
+ "113:23": 268435456,
+ "114:23": 402653184,
+ "115:23": 268435456,
+ "116:23": 402653184,
+ "117:23": 268435456,
+ "118:23": 402653184,
+ "119:23": 268435456,
+ "120:23": 402653184,
+ "121:23": 268435456,
+ "122:23": 402653184,
+ "123:23": 268435456,
+ "124:23": 402653184,
+ "125:23": 268435456,
+ "126:23": 402653184,
+ "127:23": 268435456,
+ "0:24": 268435456,
+ "1:24": 402653184,
+ "2:24": 268435456,
+ "3:24": 402653184,
+ "4:24": 268435456,
+ "5:24": 402653184,
+ "6:24": 268435456,
+ "7:24": 402653184,
+ "8:24": 268435456,
+ "9:24": 402653184,
+ "10:24": 268435456,
+ "11:24": 402653184,
+ "12:24": 268435456,
+ "13:24": 402653184,
+ "14:24": 268435456,
+ "15:24": 402653184,
+ "16:24": 268435456,
+ "17:24": 402653184,
+ "18:24": 268435456,
+ "19:24": 402653184,
+ "20:24": 268435456,
+ "21:24": 402653184,
+ "22:24": -9288933,
+ "23:24": -9288933,
+ "24:24": -9288933,
+ "25:24": -9288933,
+ "26:24": -9288933,
+ "27:24": -9288933,
+ "28:24": -9288933,
+ "29:24": -9288933,
+ "30:24": -9288933,
+ "31:24": -9288933,
+ "32:24": -9288933,
+ "33:24": -9288933,
+ "34:24": -9288933,
+ "35:24": -9288933,
+ "36:24": -9288933,
+ "37:24": -9288933,
+ "38:24": -9288933,
+ "39:24": -9288933,
+ "40:24": -9288933,
+ "41:24": -9288933,
+ "42:24": -9288933,
+ "43:24": -9288933,
+ "44:24": -9288933,
+ "45:24": -9288933,
+ "46:24": -9288933,
+ "47:24": -9288933,
+ "48:24": -9288933,
+ "49:24": -9288933,
+ "50:24": -9288933,
+ "51:24": -9288933,
+ "52:24": -9288933,
+ "53:24": -9288933,
+ "54:24": -9288933,
+ "55:24": -9288933,
+ "56:24": -9288933,
+ "57:24": -9288933,
+ "58:24": -9288933,
+ "59:24": -9288933,
+ "60:24": -9288933,
+ "61:24": -9288933,
+ "62:24": 268435456,
+ "63:24": 402653184,
+ "64:24": 268435456,
+ "65:24": 402653184,
+ "66:24": -16745472,
+ "67:24": -16745472,
+ "68:24": -16745472,
+ "69:24": -16745472,
+ "70:24": -16745472,
+ "71:24": -16745472,
+ "72:24": -16745472,
+ "73:24": -16745472,
+ "74:24": -16745472,
+ "75:24": -16745472,
+ "76:24": -16745472,
+ "77:24": -16745472,
+ "78:24": -16745472,
+ "79:24": -16745472,
+ "80:24": -16745472,
+ "81:24": -16745472,
+ "82:24": -16745472,
+ "83:24": -16745472,
+ "84:24": 268435456,
+ "85:24": 402653184,
+ "86:24": 268435456,
+ "87:24": 402653184,
+ "88:24": -9288933,
+ "89:24": -9288933,
+ "90:24": -9288933,
+ "91:24": -9288933,
+ "92:24": -9288933,
+ "93:24": -9288933,
+ "94:24": -9288933,
+ "95:24": -9288933,
+ "96:24": -9288933,
+ "97:24": -9288933,
+ "98:24": -9288933,
+ "99:24": -9288933,
+ "100:24": -9288933,
+ "101:24": -9288933,
+ "102:24": -9288933,
+ "103:24": -9288933,
+ "104:24": -9288933,
+ "105:24": -9288933,
+ "106:24": 268435456,
+ "107:24": 402653184,
+ "108:24": 268435456,
+ "109:24": 402653184,
+ "110:24": 268435456,
+ "111:24": 402653184,
+ "112:24": 268435456,
+ "113:24": 402653184,
+ "114:24": 268435456,
+ "115:24": 402653184,
+ "116:24": 268435456,
+ "117:24": 402653184,
+ "118:24": 268435456,
+ "119:24": 402653184,
+ "120:24": 268435456,
+ "121:24": 402653184,
+ "122:24": 268435456,
+ "123:24": 402653184,
+ "124:24": 268435456,
+ "125:24": 402653184,
+ "126:24": 268435456,
+ "127:24": 402653184,
+ "0:25": 402653184,
+ "1:25": 268435456,
+ "2:25": 402653184,
+ "3:25": 268435456,
+ "4:25": 402653184,
+ "5:25": 268435456,
+ "6:25": 402653184,
+ "7:25": 268435456,
+ "8:25": 402653184,
+ "9:25": 268435456,
+ "10:25": 402653184,
+ "11:25": 268435456,
+ "12:25": 402653184,
+ "13:25": 268435456,
+ "14:25": 402653184,
+ "15:25": 268435456,
+ "16:25": 402653184,
+ "17:25": 268435456,
+ "18:25": 402653184,
+ "19:25": 268435456,
+ "20:25": 402653184,
+ "21:25": 268435456,
+ "22:25": -9288933,
+ "23:25": -9288933,
+ "24:25": -9288933,
+ "25:25": -9288933,
+ "26:25": -9288933,
+ "27:25": -9288933,
+ "28:25": -9288933,
+ "29:25": -9288933,
+ "30:25": -9288933,
+ "31:25": -9288933,
+ "32:25": -9288933,
+ "33:25": -9288933,
+ "34:25": -9288933,
+ "35:25": -9288933,
+ "36:25": -9288933,
+ "37:25": -9288933,
+ "38:25": -9288933,
+ "39:25": -9288933,
+ "40:25": -9288933,
+ "41:25": -9288933,
+ "42:25": -9288933,
+ "43:25": -9288933,
+ "44:25": -9288933,
+ "45:25": -9288933,
+ "46:25": -9288933,
+ "47:25": -9288933,
+ "48:25": -9288933,
+ "49:25": -9288933,
+ "50:25": -9288933,
+ "51:25": -9288933,
+ "52:25": -9288933,
+ "53:25": -9288933,
+ "54:25": -9288933,
+ "55:25": -9288933,
+ "56:25": -9288933,
+ "57:25": -9288933,
+ "58:25": -9288933,
+ "59:25": -9288933,
+ "60:25": -9288933,
+ "61:25": -9288933,
+ "62:25": 402653184,
+ "63:25": 268435456,
+ "64:25": 402653184,
+ "65:25": 268435456,
+ "66:25": -16745472,
+ "67:25": -16745472,
+ "68:25": -16745472,
+ "69:25": -16745472,
+ "70:25": -16745472,
+ "71:25": -16745472,
+ "72:25": -16745472,
+ "73:25": -16745472,
+ "74:25": -16745472,
+ "75:25": -16745472,
+ "76:25": -16745472,
+ "77:25": -16745472,
+ "78:25": -16745472,
+ "79:25": -16745472,
+ "80:25": -16745472,
+ "81:25": -16745472,
+ "82:25": -16745472,
+ "83:25": -16745472,
+ "84:25": 402653184,
+ "85:25": 268435456,
+ "86:25": 402653184,
+ "87:25": 268435456,
+ "88:25": -9288933,
+ "89:25": -9288933,
+ "90:25": -9288933,
+ "91:25": -9288933,
+ "92:25": -9288933,
+ "93:25": -9288933,
+ "94:25": -9288933,
+ "95:25": -9288933,
+ "96:25": -9288933,
+ "97:25": -9288933,
+ "98:25": -9288933,
+ "99:25": -9288933,
+ "100:25": -9288933,
+ "101:25": -9288933,
+ "102:25": -9288933,
+ "103:25": -9288933,
+ "104:25": -9288933,
+ "105:25": -9288933,
+ "106:25": 402653184,
+ "107:25": 268435456,
+ "108:25": 402653184,
+ "109:25": 268435456,
+ "110:25": 402653184,
+ "111:25": 268435456,
+ "112:25": 402653184,
+ "113:25": 268435456,
+ "114:25": 402653184,
+ "115:25": 268435456,
+ "116:25": 402653184,
+ "117:25": 268435456,
+ "118:25": 402653184,
+ "119:25": 268435456,
+ "120:25": 402653184,
+ "121:25": 268435456,
+ "122:25": 402653184,
+ "123:25": 268435456,
+ "124:25": 402653184,
+ "125:25": 268435456,
+ "126:25": 402653184,
+ "127:25": 268435456,
+ "0:26": 268435456,
+ "1:26": 402653184,
+ "2:26": 268435456,
+ "3:26": 402653184,
+ "4:26": 268435456,
+ "5:26": 402653184,
+ "6:26": 268435456,
+ "7:26": 402653184,
+ "8:26": 268435456,
+ "9:26": 402653184,
+ "10:26": 268435456,
+ "11:26": 402653184,
+ "12:26": 268435456,
+ "13:26": 402653184,
+ "14:26": 268435456,
+ "15:26": 402653184,
+ "16:26": 268435456,
+ "17:26": 402653184,
+ "18:26": 268435456,
+ "19:26": 402653184,
+ "20:26": 268435456,
+ "21:26": 402653184,
+ "22:26": -9288933,
+ "23:26": -9288933,
+ "24:26": -9288933,
+ "25:26": -9288933,
+ "26:26": -9288933,
+ "27:26": -9288933,
+ "28:26": -9288933,
+ "29:26": -9288933,
+ "30:26": -9288933,
+ "31:26": -9288933,
+ "32:26": -9288933,
+ "33:26": -9288933,
+ "34:26": -9288933,
+ "35:26": -9288933,
+ "36:26": -9288933,
+ "37:26": -9288933,
+ "38:26": -9288933,
+ "39:26": -9288933,
+ "40:26": -9288933,
+ "41:26": -9288933,
+ "42:26": -9288933,
+ "43:26": -9288933,
+ "44:26": -9288933,
+ "45:26": -9288933,
+ "46:26": -9288933,
+ "47:26": -9288933,
+ "48:26": -9288933,
+ "49:26": -9288933,
+ "50:26": -9288933,
+ "51:26": -9288933,
+ "52:26": -9288933,
+ "53:26": -9288933,
+ "54:26": -9288933,
+ "55:26": -9288933,
+ "56:26": -9288933,
+ "57:26": -9288933,
+ "58:26": -9288933,
+ "59:26": -9288933,
+ "60:26": -9288933,
+ "61:26": -9288933,
+ "62:26": 268435456,
+ "63:26": 402653184,
+ "64:26": 268435456,
+ "65:26": 402653184,
+ "66:26": -16745472,
+ "67:26": -16745472,
+ "68:26": -16745472,
+ "69:26": -16745472,
+ "70:26": -16745472,
+ "71:26": -16745472,
+ "72:26": -16745472,
+ "73:26": -16745472,
+ "74:26": -16745472,
+ "75:26": -16745472,
+ "76:26": -16745472,
+ "77:26": -16745472,
+ "78:26": -16745472,
+ "79:26": -16745472,
+ "80:26": -16745472,
+ "81:26": -16745472,
+ "82:26": -16745472,
+ "83:26": -16745472,
+ "84:26": 268435456,
+ "85:26": 402653184,
+ "86:26": 268435456,
+ "87:26": 402653184,
+ "88:26": -9288933,
+ "89:26": -9288933,
+ "90:26": -9288933,
+ "91:26": -9288933,
+ "92:26": -9288933,
+ "93:26": -9288933,
+ "94:26": -9288933,
+ "95:26": -9288933,
+ "96:26": -9288933,
+ "97:26": -9288933,
+ "98:26": -9288933,
+ "99:26": -9288933,
+ "100:26": -9288933,
+ "101:26": -9288933,
+ "102:26": -9288933,
+ "103:26": -9288933,
+ "104:26": -9288933,
+ "105:26": -9288933,
+ "106:26": 268435456,
+ "107:26": 402653184,
+ "108:26": 268435456,
+ "109:26": 402653184,
+ "110:26": 268435456,
+ "111:26": 402653184,
+ "112:26": 268435456,
+ "113:26": 402653184,
+ "114:26": 268435456,
+ "115:26": 402653184,
+ "116:26": 268435456,
+ "117:26": 402653184,
+ "118:26": 268435456,
+ "119:26": 402653184,
+ "120:26": 268435456,
+ "121:26": 402653184,
+ "122:26": 268435456,
+ "123:26": 402653184,
+ "124:26": 268435456,
+ "125:26": 402653184,
+ "126:26": 268435456,
+ "127:26": 402653184,
+ "0:27": 402653184,
+ "1:27": 268435456,
+ "2:27": 402653184,
+ "3:27": 268435456,
+ "4:27": 402653184,
+ "5:27": 268435456,
+ "6:27": 402653184,
+ "7:27": 268435456,
+ "8:27": 402653184,
+ "9:27": 268435456,
+ "10:27": 402653184,
+ "11:27": 268435456,
+ "12:27": 402653184,
+ "13:27": 268435456,
+ "14:27": 402653184,
+ "15:27": 268435456,
+ "16:27": 402653184,
+ "17:27": 268435456,
+ "18:27": 402653184,
+ "19:27": 268435456,
+ "20:27": 402653184,
+ "21:27": 268435456,
+ "22:27": -9288933,
+ "23:27": -9288933,
+ "24:27": -9288933,
+ "25:27": -9288933,
+ "26:27": -9288933,
+ "27:27": -9288933,
+ "28:27": -9288933,
+ "29:27": -9288933,
+ "30:27": -9288933,
+ "31:27": -9288933,
+ "32:27": -9288933,
+ "33:27": -9288933,
+ "34:27": -9288933,
+ "35:27": -9288933,
+ "36:27": -9288933,
+ "37:27": -9288933,
+ "38:27": -9288933,
+ "39:27": -9288933,
+ "40:27": -9288933,
+ "41:27": -9288933,
+ "42:27": -9288933,
+ "43:27": -9288933,
+ "44:27": -9288933,
+ "45:27": -9288933,
+ "46:27": -9288933,
+ "47:27": -9288933,
+ "48:27": -9288933,
+ "49:27": -9288933,
+ "50:27": -9288933,
+ "51:27": -9288933,
+ "52:27": -9288933,
+ "53:27": -9288933,
+ "54:27": -9288933,
+ "55:27": -9288933,
+ "56:27": -9288933,
+ "57:27": -9288933,
+ "58:27": -9288933,
+ "59:27": -9288933,
+ "60:27": -9288933,
+ "61:27": -9288933,
+ "62:27": 402653184,
+ "63:27": 268435456,
+ "64:27": 402653184,
+ "65:27": 268435456,
+ "66:27": -16745472,
+ "67:27": -16745472,
+ "68:27": -16745472,
+ "69:27": -16745472,
+ "70:27": -16745472,
+ "71:27": -16745472,
+ "72:27": -16745472,
+ "73:27": -16745472,
+ "74:27": -16745472,
+ "75:27": -16745472,
+ "76:27": -16745472,
+ "77:27": -16745472,
+ "78:27": -16745472,
+ "79:27": -16745472,
+ "80:27": -16745472,
+ "81:27": -16745472,
+ "82:27": -16745472,
+ "83:27": -16745472,
+ "84:27": 402653184,
+ "85:27": 268435456,
+ "86:27": 402653184,
+ "87:27": 268435456,
+ "88:27": -9288933,
+ "89:27": -9288933,
+ "90:27": -9288933,
+ "91:27": -9288933,
+ "92:27": -9288933,
+ "93:27": -9288933,
+ "94:27": -9288933,
+ "95:27": -9288933,
+ "96:27": -9288933,
+ "97:27": -9288933,
+ "98:27": -9288933,
+ "99:27": -9288933,
+ "100:27": -9288933,
+ "101:27": -9288933,
+ "102:27": -9288933,
+ "103:27": -9288933,
+ "104:27": -9288933,
+ "105:27": -9288933,
+ "106:27": 402653184,
+ "107:27": 268435456,
+ "108:27": 402653184,
+ "109:27": 268435456,
+ "110:27": 402653184,
+ "111:27": 268435456,
+ "112:27": 402653184,
+ "113:27": 268435456,
+ "114:27": 402653184,
+ "115:27": 268435456,
+ "116:27": 402653184,
+ "117:27": 268435456,
+ "118:27": 402653184,
+ "119:27": 268435456,
+ "120:27": 402653184,
+ "121:27": 268435456,
+ "122:27": 402653184,
+ "123:27": 268435456,
+ "124:27": 402653184,
+ "125:27": 268435456,
+ "126:27": 402653184,
+ "127:27": 268435456,
+ "0:28": 268435456,
+ "1:28": 402653184,
+ "2:28": 268435456,
+ "3:28": 402653184,
+ "4:28": 268435456,
+ "5:28": 402653184,
+ "6:28": 268435456,
+ "7:28": 402653184,
+ "8:28": 268435456,
+ "9:28": 402653184,
+ "10:28": 268435456,
+ "11:28": 402653184,
+ "12:28": 268435456,
+ "13:28": 402653184,
+ "14:28": 268435456,
+ "15:28": 402653184,
+ "16:28": 268435456,
+ "17:28": 402653184,
+ "18:28": 268435456,
+ "19:28": 402653184,
+ "20:28": 268435456,
+ "21:28": 402653184,
+ "22:28": -9288933,
+ "23:28": -9288933,
+ "24:28": -9288933,
+ "25:28": -9288933,
+ "26:28": -9288933,
+ "27:28": -9288933,
+ "28:28": -9288933,
+ "29:28": -9288933,
+ "30:28": -9288933,
+ "31:28": -9288933,
+ "32:28": -9288933,
+ "33:28": -9288933,
+ "34:28": -9288933,
+ "35:28": -9288933,
+ "36:28": -9288933,
+ "37:28": -9288933,
+ "38:28": -9288933,
+ "39:28": -9288933,
+ "40:28": -9288933,
+ "41:28": -9288933,
+ "42:28": -9288933,
+ "43:28": -9288933,
+ "44:28": -9288933,
+ "45:28": -9288933,
+ "46:28": -9288933,
+ "47:28": -9288933,
+ "48:28": -9288933,
+ "49:28": -9288933,
+ "50:28": -9288933,
+ "51:28": -9288933,
+ "52:28": -9288933,
+ "53:28": -9288933,
+ "54:28": -9288933,
+ "55:28": -9288933,
+ "56:28": -9288933,
+ "57:28": -9288933,
+ "58:28": -9288933,
+ "59:28": -9288933,
+ "60:28": -9288933,
+ "61:28": -9288933,
+ "62:28": 268435456,
+ "63:28": 402653184,
+ "64:28": 268435456,
+ "65:28": 402653184,
+ "66:28": -16745472,
+ "67:28": -16745472,
+ "68:28": -16745472,
+ "69:28": -16745472,
+ "70:28": -16745472,
+ "71:28": -16745472,
+ "72:28": -16745472,
+ "73:28": -16745472,
+ "74:28": -16745472,
+ "75:28": -16745472,
+ "76:28": -16745472,
+ "77:28": -16745472,
+ "78:28": -16745472,
+ "79:28": -16745472,
+ "80:28": -16745472,
+ "81:28": -16745472,
+ "82:28": -16745472,
+ "83:28": -16745472,
+ "84:28": 268435456,
+ "85:28": 402653184,
+ "86:28": 268435456,
+ "87:28": 402653184,
+ "88:28": -9288933,
+ "89:28": -9288933,
+ "90:28": -9288933,
+ "91:28": -9288933,
+ "92:28": -9288933,
+ "93:28": -9288933,
+ "94:28": -9288933,
+ "95:28": -9288933,
+ "96:28": -9288933,
+ "97:28": -9288933,
+ "98:28": -9288933,
+ "99:28": -9288933,
+ "100:28": -9288933,
+ "101:28": -9288933,
+ "102:28": -9288933,
+ "103:28": -9288933,
+ "104:28": -9288933,
+ "105:28": -9288933,
+ "106:28": 268435456,
+ "107:28": 402653184,
+ "108:28": 268435456,
+ "109:28": 402653184,
+ "110:28": 268435456,
+ "111:28": 402653184,
+ "112:28": 268435456,
+ "113:28": 402653184,
+ "114:28": 268435456,
+ "115:28": 402653184,
+ "116:28": 268435456,
+ "117:28": 402653184,
+ "118:28": 268435456,
+ "119:28": 402653184,
+ "120:28": 268435456,
+ "121:28": 402653184,
+ "122:28": 268435456,
+ "123:28": 402653184,
+ "124:28": 268435456,
+ "125:28": 402653184,
+ "126:28": 268435456,
+ "127:28": 402653184,
+ "0:29": 402653184,
+ "1:29": 268435456,
+ "2:29": 402653184,
+ "3:29": 268435456,
+ "4:29": 402653184,
+ "5:29": 268435456,
+ "6:29": 402653184,
+ "7:29": 268435456,
+ "8:29": 402653184,
+ "9:29": 268435456,
+ "10:29": 402653184,
+ "11:29": 268435456,
+ "12:29": 402653184,
+ "13:29": 268435456,
+ "14:29": 402653184,
+ "15:29": 268435456,
+ "16:29": 402653184,
+ "17:29": 268435456,
+ "18:29": 402653184,
+ "19:29": 268435456,
+ "20:29": 402653184,
+ "21:29": 268435456,
+ "22:29": -9288933,
+ "23:29": -9288933,
+ "24:29": -9288933,
+ "25:29": -9288933,
+ "26:29": -9288933,
+ "27:29": -9288933,
+ "28:29": -9288933,
+ "29:29": -9288933,
+ "30:29": -9288933,
+ "31:29": -9288933,
+ "32:29": -9288933,
+ "33:29": -9288933,
+ "34:29": -9288933,
+ "35:29": -9288933,
+ "36:29": -9288933,
+ "37:29": -9288933,
+ "38:29": -9288933,
+ "39:29": -9288933,
+ "40:29": -9288933,
+ "41:29": -9288933,
+ "42:29": -9288933,
+ "43:29": -9288933,
+ "44:29": -9288933,
+ "45:29": -9288933,
+ "46:29": -9288933,
+ "47:29": -9288933,
+ "48:29": -9288933,
+ "49:29": -9288933,
+ "50:29": -9288933,
+ "51:29": -9288933,
+ "52:29": -9288933,
+ "53:29": -9288933,
+ "54:29": -9288933,
+ "55:29": -9288933,
+ "56:29": -9288933,
+ "57:29": -9288933,
+ "58:29": -9288933,
+ "59:29": -9288933,
+ "60:29": -9288933,
+ "61:29": -9288933,
+ "62:29": 402653184,
+ "63:29": 268435456,
+ "64:29": 402653184,
+ "65:29": 268435456,
+ "66:29": 402653184,
+ "67:29": 268435456,
+ "68:29": 402653184,
+ "69:29": 268435456,
+ "70:29": 402653184,
+ "71:29": 268435456,
+ "72:29": 402653184,
+ "73:29": 268435456,
+ "74:29": 402653184,
+ "75:29": 268435456,
+ "76:29": 402653184,
+ "77:29": 268435456,
+ "78:29": 402653184,
+ "79:29": 268435456,
+ "80:29": 402653184,
+ "81:29": 268435456,
+ "82:29": 402653184,
+ "83:29": 268435456,
+ "84:29": 402653184,
+ "85:29": 268435456,
+ "86:29": 402653184,
+ "87:29": 268435456,
+ "88:29": -9288933,
+ "89:29": -9288933,
+ "90:29": -9288933,
+ "91:29": -9288933,
+ "92:29": -9288933,
+ "93:29": -9288933,
+ "94:29": -9288933,
+ "95:29": -9288933,
+ "96:29": -9288933,
+ "97:29": -9288933,
+ "98:29": -9288933,
+ "99:29": -9288933,
+ "100:29": -9288933,
+ "101:29": -9288933,
+ "102:29": -9288933,
+ "103:29": -9288933,
+ "104:29": -9288933,
+ "105:29": -9288933,
+ "106:29": 402653184,
+ "107:29": 268435456,
+ "108:29": 402653184,
+ "109:29": 268435456,
+ "110:29": 402653184,
+ "111:29": 268435456,
+ "112:29": 402653184,
+ "113:29": 268435456,
+ "114:29": 402653184,
+ "115:29": 268435456,
+ "116:29": 402653184,
+ "117:29": 268435456,
+ "118:29": 402653184,
+ "119:29": 268435456,
+ "120:29": 402653184,
+ "121:29": 268435456,
+ "122:29": 402653184,
+ "123:29": 268435456,
+ "124:29": 402653184,
+ "125:29": 268435456,
+ "126:29": 402653184,
+ "127:29": 268435456,
+ "0:30": 268435456,
+ "1:30": 402653184,
+ "2:30": 268435456,
+ "3:30": 402653184,
+ "4:30": 268435456,
+ "5:30": 402653184,
+ "6:30": 268435456,
+ "7:30": 402653184,
+ "8:30": 268435456,
+ "9:30": 402653184,
+ "10:30": 268435456,
+ "11:30": 402653184,
+ "12:30": 268435456,
+ "13:30": 402653184,
+ "14:30": 268435456,
+ "15:30": 402653184,
+ "16:30": 268435456,
+ "17:30": 402653184,
+ "18:30": 268435456,
+ "19:30": 402653184,
+ "20:30": 268435456,
+ "21:30": 402653184,
+ "22:30": -9288933,
+ "23:30": -9288933,
+ "24:30": -9288933,
+ "25:30": -9288933,
+ "26:30": -9288933,
+ "27:30": -9288933,
+ "28:30": -9288933,
+ "29:30": -9288933,
+ "30:30": -9288933,
+ "31:30": -9288933,
+ "32:30": -9288933,
+ "33:30": -9288933,
+ "34:30": -9288933,
+ "35:30": -9288933,
+ "36:30": -9288933,
+ "37:30": -9288933,
+ "38:30": -9288933,
+ "39:30": -9288933,
+ "40:30": -9288933,
+ "41:30": -9288933,
+ "42:30": -9288933,
+ "43:30": -9288933,
+ "44:30": -9288933,
+ "45:30": -9288933,
+ "46:30": -9288933,
+ "47:30": -9288933,
+ "48:30": -9288933,
+ "49:30": -9288933,
+ "50:30": -9288933,
+ "51:30": -9288933,
+ "52:30": -9288933,
+ "53:30": -9288933,
+ "54:30": -9288933,
+ "55:30": -9288933,
+ "56:30": -9288933,
+ "57:30": -9288933,
+ "58:30": -9288933,
+ "59:30": -9288933,
+ "60:30": -9288933,
+ "61:30": -9288933,
+ "62:30": 268435456,
+ "63:30": 402653184,
+ "64:30": 268435456,
+ "65:30": 402653184,
+ "66:30": 268435456,
+ "67:30": 402653184,
+ "68:30": 268435456,
+ "69:30": 402653184,
+ "70:30": 268435456,
+ "71:30": 402653184,
+ "72:30": 268435456,
+ "73:30": 402653184,
+ "74:30": 268435456,
+ "75:30": 402653184,
+ "76:30": 268435456,
+ "77:30": 402653184,
+ "78:30": 268435456,
+ "79:30": 402653184,
+ "80:30": 268435456,
+ "81:30": 402653184,
+ "82:30": 268435456,
+ "83:30": 402653184,
+ "84:30": 268435456,
+ "85:30": 402653184,
+ "86:30": 268435456,
+ "87:30": 402653184,
+ "88:30": -9288933,
+ "89:30": -9288933,
+ "90:30": -9288933,
+ "91:30": -9288933,
+ "92:30": -9288933,
+ "93:30": -9288933,
+ "94:30": -9288933,
+ "95:30": -9288933,
+ "96:30": -9288933,
+ "97:30": -9288933,
+ "98:30": -9288933,
+ "99:30": -9288933,
+ "100:30": -9288933,
+ "101:30": -9288933,
+ "102:30": -9288933,
+ "103:30": -9288933,
+ "104:30": -9288933,
+ "105:30": -9288933,
+ "106:30": 268435456,
+ "107:30": 402653184,
+ "108:30": 268435456,
+ "109:30": 402653184,
+ "110:30": 268435456,
+ "111:30": 402653184,
+ "112:30": 268435456,
+ "113:30": 402653184,
+ "114:30": 268435456,
+ "115:30": 402653184,
+ "116:30": 268435456,
+ "117:30": 402653184,
+ "118:30": 268435456,
+ "119:30": 402653184,
+ "120:30": 268435456,
+ "121:30": 402653184,
+ "122:30": 268435456,
+ "123:30": 402653184,
+ "124:30": 268435456,
+ "125:30": 402653184,
+ "126:30": 268435456,
+ "127:30": 402653184,
+ "0:31": 402653184,
+ "1:31": 268435456,
+ "2:31": 402653184,
+ "3:31": 268435456,
+ "4:31": 402653184,
+ "5:31": 268435456,
+ "6:31": 402653184,
+ "7:31": 268435456,
+ "8:31": 402653184,
+ "9:31": 268435456,
+ "10:31": 402653184,
+ "11:31": 268435456,
+ "12:31": 402653184,
+ "13:31": 268435456,
+ "14:31": 402653184,
+ "15:31": 268435456,
+ "16:31": 402653184,
+ "17:31": 268435456,
+ "18:31": 402653184,
+ "19:31": 268435456,
+ "20:31": 402653184,
+ "21:31": 268435456,
+ "22:31": -9288933,
+ "23:31": -9288933,
+ "24:31": -9288933,
+ "25:31": -9288933,
+ "26:31": -9288933,
+ "27:31": -9288933,
+ "28:31": -9288933,
+ "29:31": -9288933,
+ "30:31": -9288933,
+ "31:31": -9288933,
+ "32:31": -9288933,
+ "33:31": -9288933,
+ "34:31": -9288933,
+ "35:31": -9288933,
+ "36:31": -9288933,
+ "37:31": -9288933,
+ "38:31": -9288933,
+ "39:31": -9288933,
+ "40:31": -9288933,
+ "41:31": -9288933,
+ "42:31": -9288933,
+ "43:31": -9288933,
+ "44:31": -9288933,
+ "45:31": -9288933,
+ "46:31": -9288933,
+ "47:31": -9288933,
+ "48:31": -9288933,
+ "49:31": -9288933,
+ "50:31": -9288933,
+ "51:31": -9288933,
+ "52:31": -9288933,
+ "53:31": -9288933,
+ "54:31": -9288933,
+ "55:31": -9288933,
+ "56:31": -9288933,
+ "57:31": -9288933,
+ "58:31": -9288933,
+ "59:31": -9288933,
+ "60:31": -9288933,
+ "61:31": -9288933,
+ "62:31": 402653184,
+ "63:31": 268435456,
+ "64:31": 402653184,
+ "65:31": 268435456,
+ "66:31": 402653184,
+ "67:31": 268435456,
+ "68:31": 402653184,
+ "69:31": 268435456,
+ "70:31": 402653184,
+ "71:31": 268435456,
+ "72:31": 402653184,
+ "73:31": 268435456,
+ "74:31": 402653184,
+ "75:31": 268435456,
+ "76:31": 402653184,
+ "77:31": 268435456,
+ "78:31": 402653184,
+ "79:31": 268435456,
+ "80:31": 402653184,
+ "81:31": 268435456,
+ "82:31": 402653184,
+ "83:31": 268435456,
+ "84:31": 402653184,
+ "85:31": 268435456,
+ "86:31": 402653184,
+ "87:31": 268435456,
+ "88:31": -9288933,
+ "89:31": -9288933,
+ "90:31": -9288933,
+ "91:31": -9288933,
+ "92:31": -9288933,
+ "93:31": -9288933,
+ "94:31": -9288933,
+ "95:31": -9288933,
+ "96:31": -9288933,
+ "97:31": -9288933,
+ "98:31": -9288933,
+ "99:31": -9288933,
+ "100:31": -9288933,
+ "101:31": -9288933,
+ "102:31": -9288933,
+ "103:31": -9288933,
+ "104:31": -9288933,
+ "105:31": -9288933,
+ "106:31": 402653184,
+ "107:31": 268435456,
+ "108:31": 402653184,
+ "109:31": 268435456,
+ "110:31": 402653184,
+ "111:31": 268435456,
+ "112:31": 402653184,
+ "113:31": 268435456,
+ "114:31": 402653184,
+ "115:31": 268435456,
+ "116:31": 402653184,
+ "117:31": 268435456,
+ "118:31": 402653184,
+ "119:31": 268435456,
+ "120:31": 402653184,
+ "121:31": 268435456,
+ "122:31": 402653184,
+ "123:31": 268435456,
+ "124:31": 402653184,
+ "125:31": 268435456,
+ "126:31": 402653184,
+ "127:31": 268435456,
+ "0:32": 268435456,
+ "1:32": 402653184,
+ "2:32": 268435456,
+ "3:32": 402653184,
+ "4:32": 268435456,
+ "5:32": 402653184,
+ "6:32": 268435456,
+ "7:32": 402653184,
+ "8:32": 268435456,
+ "9:32": 402653184,
+ "10:32": 268435456,
+ "11:32": 402653184,
+ "12:32": 268435456,
+ "13:32": 402653184,
+ "14:32": 268435456,
+ "15:32": 402653184,
+ "16:32": 268435456,
+ "17:32": 402653184,
+ "18:32": 268435456,
+ "19:32": 402653184,
+ "20:32": 268435456,
+ "21:32": 402653184,
+ "22:32": -9288933,
+ "23:32": -9288933,
+ "24:32": -9288933,
+ "25:32": -9288933,
+ "26:32": -9288933,
+ "27:32": -9288933,
+ "28:32": -9288933,
+ "29:32": -9288933,
+ "30:32": -9288933,
+ "31:32": -9288933,
+ "32:32": -9288933,
+ "33:32": -9288933,
+ "34:32": -9288933,
+ "35:32": -9288933,
+ "36:32": -9288933,
+ "37:32": -9288933,
+ "38:32": -9288933,
+ "39:32": -9288933,
+ "40:32": -9288933,
+ "41:32": -9288933,
+ "42:32": -9288933,
+ "43:32": -9288933,
+ "44:32": -9288933,
+ "45:32": -9288933,
+ "46:32": -9288933,
+ "47:32": -9288933,
+ "48:32": -9288933,
+ "49:32": -9288933,
+ "50:32": -9288933,
+ "51:32": -9288933,
+ "52:32": -9288933,
+ "53:32": -9288933,
+ "54:32": -9288933,
+ "55:32": -9288933,
+ "56:32": -9288933,
+ "57:32": -9288933,
+ "58:32": -9288933,
+ "59:32": -9288933,
+ "60:32": -9288933,
+ "61:32": -9288933,
+ "62:32": 268435456,
+ "63:32": 402653184,
+ "64:32": 268435456,
+ "65:32": 402653184,
+ "66:32": 268435456,
+ "67:32": 402653184,
+ "68:32": 268435456,
+ "69:32": 402653184,
+ "70:32": 268435456,
+ "71:32": 402653184,
+ "72:32": 268435456,
+ "73:32": 402653184,
+ "74:32": 268435456,
+ "75:32": 402653184,
+ "76:32": 268435456,
+ "77:32": 402653184,
+ "78:32": 268435456,
+ "79:32": 402653184,
+ "80:32": 268435456,
+ "81:32": 402653184,
+ "82:32": 268435456,
+ "83:32": 402653184,
+ "84:32": 268435456,
+ "85:32": 402653184,
+ "86:32": 268435456,
+ "87:32": 402653184,
+ "88:32": -9288933,
+ "89:32": -9288933,
+ "90:32": -9288933,
+ "91:32": -9288933,
+ "92:32": -9288933,
+ "93:32": -9288933,
+ "94:32": -9288933,
+ "95:32": -9288933,
+ "96:32": -9288933,
+ "97:32": -9288933,
+ "98:32": -9288933,
+ "99:32": -9288933,
+ "100:32": -9288933,
+ "101:32": -9288933,
+ "102:32": -9288933,
+ "103:32": -9288933,
+ "104:32": -9288933,
+ "105:32": -9288933,
+ "106:32": 268435456,
+ "107:32": 402653184,
+ "108:32": 268435456,
+ "109:32": 402653184,
+ "110:32": 268435456,
+ "111:32": 402653184,
+ "112:32": 268435456,
+ "113:32": 402653184,
+ "114:32": 268435456,
+ "115:32": 402653184,
+ "116:32": 268435456,
+ "117:32": 402653184,
+ "118:32": 268435456,
+ "119:32": 402653184,
+ "120:32": 268435456,
+ "121:32": 402653184,
+ "122:32": 268435456,
+ "123:32": 402653184,
+ "124:32": 268435456,
+ "125:32": 402653184,
+ "126:32": 268435456,
+ "127:32": 402653184,
+ "0:33": 402653184,
+ "1:33": 268435456,
+ "2:33": 402653184,
+ "3:33": 268435456,
+ "4:33": 402653184,
+ "5:33": 268435456,
+ "6:33": 402653184,
+ "7:33": 268435456,
+ "8:33": 402653184,
+ "9:33": 268435456,
+ "10:33": 402653184,
+ "11:33": 268435456,
+ "12:33": 402653184,
+ "13:33": 268435456,
+ "14:33": 402653184,
+ "15:33": 268435456,
+ "16:33": 402653184,
+ "17:33": 268435456,
+ "18:33": 402653184,
+ "19:33": 268435456,
+ "20:33": 402653184,
+ "21:33": 268435456,
+ "22:33": -9288933,
+ "23:33": -9288933,
+ "24:33": -9288933,
+ "25:33": -9288933,
+ "26:33": -9288933,
+ "27:33": -9288933,
+ "28:33": -9288933,
+ "29:33": -9288933,
+ "30:33": -9288933,
+ "31:33": -9288933,
+ "32:33": -9288933,
+ "33:33": -9288933,
+ "34:33": -9288933,
+ "35:33": -9288933,
+ "36:33": -9288933,
+ "37:33": -9288933,
+ "38:33": -9288933,
+ "39:33": -9288933,
+ "40:33": -9288933,
+ "41:33": -9288933,
+ "42:33": -9288933,
+ "43:33": -9288933,
+ "44:33": -9288933,
+ "45:33": -9288933,
+ "46:33": -9288933,
+ "47:33": -9288933,
+ "48:33": -9288933,
+ "49:33": -9288933,
+ "50:33": -9288933,
+ "51:33": -9288933,
+ "52:33": -9288933,
+ "53:33": -9288933,
+ "54:33": -9288933,
+ "55:33": -9288933,
+ "56:33": -9288933,
+ "57:33": -9288933,
+ "58:33": -9288933,
+ "59:33": -9288933,
+ "60:33": -9288933,
+ "61:33": -9288933,
+ "62:33": 402653184,
+ "63:33": 268435456,
+ "64:33": 402653184,
+ "65:33": 268435456,
+ "66:33": -9288933,
+ "67:33": -9288933,
+ "68:33": -9288933,
+ "69:33": -9288933,
+ "70:33": -9288933,
+ "71:33": -9288933,
+ "72:33": -9288933,
+ "73:33": -9288933,
+ "74:33": -9288933,
+ "75:33": -9288933,
+ "76:33": -9288933,
+ "77:33": -9288933,
+ "78:33": -9288933,
+ "79:33": -9288933,
+ "80:33": -9288933,
+ "81:33": -9288933,
+ "82:33": -9288933,
+ "83:33": -9288933,
+ "84:33": 402653184,
+ "85:33": 268435456,
+ "86:33": 402653184,
+ "87:33": 268435456,
+ "88:33": -9288933,
+ "89:33": -9288933,
+ "90:33": -9288933,
+ "91:33": -9288933,
+ "92:33": -9288933,
+ "93:33": -9288933,
+ "94:33": -9288933,
+ "95:33": -9288933,
+ "96:33": -9288933,
+ "97:33": -9288933,
+ "98:33": -9288933,
+ "99:33": -9288933,
+ "100:33": -9288933,
+ "101:33": -9288933,
+ "102:33": -9288933,
+ "103:33": -9288933,
+ "104:33": -9288933,
+ "105:33": -9288933,
+ "106:33": 402653184,
+ "107:33": 268435456,
+ "108:33": 402653184,
+ "109:33": 268435456,
+ "110:33": 402653184,
+ "111:33": 268435456,
+ "112:33": 402653184,
+ "113:33": 268435456,
+ "114:33": 402653184,
+ "115:33": 268435456,
+ "116:33": 402653184,
+ "117:33": 268435456,
+ "118:33": 402653184,
+ "119:33": 268435456,
+ "120:33": 402653184,
+ "121:33": 268435456,
+ "122:33": 402653184,
+ "123:33": 268435456,
+ "124:33": 402653184,
+ "125:33": 268435456,
+ "126:33": 402653184,
+ "127:33": 268435456,
+ "0:34": 268435456,
+ "1:34": 402653184,
+ "2:34": 268435456,
+ "3:34": 402653184,
+ "4:34": 268435456,
+ "5:34": 402653184,
+ "6:34": 268435456,
+ "7:34": 402653184,
+ "8:34": 268435456,
+ "9:34": 402653184,
+ "10:34": 268435456,
+ "11:34": 402653184,
+ "12:34": 268435456,
+ "13:34": 402653184,
+ "14:34": 268435456,
+ "15:34": 402653184,
+ "16:34": 268435456,
+ "17:34": 402653184,
+ "18:34": 268435456,
+ "19:34": 402653184,
+ "20:34": 268435456,
+ "21:34": 402653184,
+ "22:34": -9288933,
+ "23:34": -9288933,
+ "24:34": -9288933,
+ "25:34": -9288933,
+ "26:34": -9288933,
+ "27:34": -9288933,
+ "28:34": -9288933,
+ "29:34": -9288933,
+ "30:34": -9288933,
+ "31:34": -9288933,
+ "32:34": -9288933,
+ "33:34": -9288933,
+ "34:34": -9288933,
+ "35:34": -9288933,
+ "36:34": -9288933,
+ "37:34": -9288933,
+ "38:34": -9288933,
+ "39:34": -9288933,
+ "40:34": -9288933,
+ "41:34": -9288933,
+ "42:34": -9288933,
+ "43:34": -9288933,
+ "44:34": -9288933,
+ "45:34": -9288933,
+ "46:34": -9288933,
+ "47:34": -9288933,
+ "48:34": -9288933,
+ "49:34": -9288933,
+ "50:34": -9288933,
+ "51:34": -9288933,
+ "52:34": -9288933,
+ "53:34": -9288933,
+ "54:34": -9288933,
+ "55:34": -9288933,
+ "56:34": -9288933,
+ "57:34": -9288933,
+ "58:34": -9288933,
+ "59:34": -9288933,
+ "60:34": -9288933,
+ "61:34": -9288933,
+ "62:34": 268435456,
+ "63:34": 402653184,
+ "64:34": 268435456,
+ "65:34": 402653184,
+ "66:34": -9288933,
+ "67:34": -9288933,
+ "68:34": -9288933,
+ "69:34": -9288933,
+ "70:34": -9288933,
+ "71:34": -9288933,
+ "72:34": -9288933,
+ "73:34": -9288933,
+ "74:34": -9288933,
+ "75:34": -9288933,
+ "76:34": -9288933,
+ "77:34": -9288933,
+ "78:34": -9288933,
+ "79:34": -9288933,
+ "80:34": -9288933,
+ "81:34": -9288933,
+ "82:34": -9288933,
+ "83:34": -9288933,
+ "84:34": 268435456,
+ "85:34": 402653184,
+ "86:34": 268435456,
+ "87:34": 402653184,
+ "88:34": -9288933,
+ "89:34": -9288933,
+ "90:34": -9288933,
+ "91:34": -9288933,
+ "92:34": -9288933,
+ "93:34": -9288933,
+ "94:34": -9288933,
+ "95:34": -9288933,
+ "96:34": -9288933,
+ "97:34": -9288933,
+ "98:34": -9288933,
+ "99:34": -9288933,
+ "100:34": -9288933,
+ "101:34": -9288933,
+ "102:34": -9288933,
+ "103:34": -9288933,
+ "104:34": -9288933,
+ "105:34": -9288933,
+ "106:34": 268435456,
+ "107:34": 402653184,
+ "108:34": 268435456,
+ "109:34": 402653184,
+ "110:34": 268435456,
+ "111:34": 402653184,
+ "112:34": 268435456,
+ "113:34": 402653184,
+ "114:34": 268435456,
+ "115:34": 402653184,
+ "116:34": 268435456,
+ "117:34": 402653184,
+ "118:34": 268435456,
+ "119:34": 402653184,
+ "120:34": 268435456,
+ "121:34": 402653184,
+ "122:34": 268435456,
+ "123:34": 402653184,
+ "124:34": 268435456,
+ "125:34": 402653184,
+ "126:34": 268435456,
+ "127:34": 402653184,
+ "0:35": 402653184,
+ "1:35": 268435456,
+ "2:35": 402653184,
+ "3:35": 268435456,
+ "4:35": 402653184,
+ "5:35": 268435456,
+ "6:35": 402653184,
+ "7:35": 268435456,
+ "8:35": 402653184,
+ "9:35": 268435456,
+ "10:35": 402653184,
+ "11:35": 268435456,
+ "12:35": 402653184,
+ "13:35": 268435456,
+ "14:35": 402653184,
+ "15:35": 268435456,
+ "16:35": 402653184,
+ "17:35": 268435456,
+ "18:35": 402653184,
+ "19:35": 268435456,
+ "20:35": 402653184,
+ "21:35": 268435456,
+ "22:35": -9288933,
+ "23:35": -9288933,
+ "24:35": -9288933,
+ "25:35": -9288933,
+ "26:35": -9288933,
+ "27:35": -9288933,
+ "28:35": -9288933,
+ "29:35": -9288933,
+ "30:35": -9288933,
+ "31:35": -9288933,
+ "32:35": -9288933,
+ "33:35": -9288933,
+ "34:35": -9288933,
+ "35:35": -9288933,
+ "36:35": -9288933,
+ "37:35": -9288933,
+ "38:35": -9288933,
+ "39:35": -9288933,
+ "40:35": -9288933,
+ "41:35": -9288933,
+ "42:35": -9288933,
+ "43:35": -9288933,
+ "44:35": -9288933,
+ "45:35": -9288933,
+ "46:35": -9288933,
+ "47:35": -9288933,
+ "48:35": -9288933,
+ "49:35": -9288933,
+ "50:35": -9288933,
+ "51:35": -9288933,
+ "52:35": -9288933,
+ "53:35": -9288933,
+ "54:35": -9288933,
+ "55:35": -9288933,
+ "56:35": -9288933,
+ "57:35": -9288933,
+ "58:35": -9288933,
+ "59:35": -9288933,
+ "60:35": -9288933,
+ "61:35": -9288933,
+ "62:35": 402653184,
+ "63:35": 268435456,
+ "64:35": 402653184,
+ "65:35": 268435456,
+ "66:35": -9288933,
+ "67:35": -9288933,
+ "68:35": -9288933,
+ "69:35": -9288933,
+ "70:35": -9288933,
+ "71:35": -9288933,
+ "72:35": -9288933,
+ "73:35": -9288933,
+ "74:35": -9288933,
+ "75:35": -9288933,
+ "76:35": -9288933,
+ "77:35": -9288933,
+ "78:35": -9288933,
+ "79:35": -9288933,
+ "80:35": -9288933,
+ "81:35": -9288933,
+ "82:35": -9288933,
+ "83:35": -9288933,
+ "84:35": 402653184,
+ "85:35": 268435456,
+ "86:35": 402653184,
+ "87:35": 268435456,
+ "88:35": -9288933,
+ "89:35": -9288933,
+ "90:35": -9288933,
+ "91:35": -9288933,
+ "92:35": -9288933,
+ "93:35": -9288933,
+ "94:35": -9288933,
+ "95:35": -9288933,
+ "96:35": -9288933,
+ "97:35": -9288933,
+ "98:35": -9288933,
+ "99:35": -9288933,
+ "100:35": -9288933,
+ "101:35": -9288933,
+ "102:35": -9288933,
+ "103:35": -9288933,
+ "104:35": -9288933,
+ "105:35": -9288933,
+ "106:35": 402653184,
+ "107:35": 268435456,
+ "108:35": 402653184,
+ "109:35": 268435456,
+ "110:35": 402653184,
+ "111:35": 268435456,
+ "112:35": 402653184,
+ "113:35": 268435456,
+ "114:35": 402653184,
+ "115:35": 268435456,
+ "116:35": 402653184,
+ "117:35": 268435456,
+ "118:35": 402653184,
+ "119:35": 268435456,
+ "120:35": 402653184,
+ "121:35": 268435456,
+ "122:35": 402653184,
+ "123:35": 268435456,
+ "124:35": 402653184,
+ "125:35": 268435456,
+ "126:35": 402653184,
+ "127:35": 268435456,
+ "0:36": 268435456,
+ "1:36": 402653184,
+ "2:36": 268435456,
+ "3:36": 402653184,
+ "4:36": 268435456,
+ "5:36": 402653184,
+ "6:36": 268435456,
+ "7:36": 402653184,
+ "8:36": 268435456,
+ "9:36": 402653184,
+ "10:36": 268435456,
+ "11:36": 402653184,
+ "12:36": 268435456,
+ "13:36": 402653184,
+ "14:36": 268435456,
+ "15:36": 402653184,
+ "16:36": 268435456,
+ "17:36": 402653184,
+ "18:36": 268435456,
+ "19:36": 402653184,
+ "20:36": 268435456,
+ "21:36": 402653184,
+ "22:36": -9288933,
+ "23:36": -9288933,
+ "24:36": -9288933,
+ "25:36": -9288933,
+ "26:36": -9288933,
+ "27:36": -9288933,
+ "28:36": -9288933,
+ "29:36": -9288933,
+ "30:36": -9288933,
+ "31:36": -9288933,
+ "32:36": -9288933,
+ "33:36": -9288933,
+ "34:36": -9288933,
+ "35:36": -9288933,
+ "36:36": -9288933,
+ "37:36": -9288933,
+ "38:36": -9288933,
+ "39:36": -9288933,
+ "40:36": -9288933,
+ "41:36": -9288933,
+ "42:36": -9288933,
+ "43:36": -9288933,
+ "44:36": -9288933,
+ "45:36": -9288933,
+ "46:36": -9288933,
+ "47:36": -9288933,
+ "48:36": -9288933,
+ "49:36": -9288933,
+ "50:36": -9288933,
+ "51:36": -9288933,
+ "52:36": -9288933,
+ "53:36": -9288933,
+ "54:36": -9288933,
+ "55:36": -9288933,
+ "56:36": -9288933,
+ "57:36": -9288933,
+ "58:36": -9288933,
+ "59:36": -9288933,
+ "60:36": -9288933,
+ "61:36": -9288933,
+ "62:36": 268435456,
+ "63:36": 402653184,
+ "64:36": 268435456,
+ "65:36": 402653184,
+ "66:36": -9288933,
+ "67:36": -9288933,
+ "68:36": -9288933,
+ "69:36": -9288933,
+ "70:36": -9288933,
+ "71:36": -9288933,
+ "72:36": -9288933,
+ "73:36": -9288933,
+ "74:36": -9288933,
+ "75:36": -9288933,
+ "76:36": -9288933,
+ "77:36": -9288933,
+ "78:36": -9288933,
+ "79:36": -9288933,
+ "80:36": -9288933,
+ "81:36": -9288933,
+ "82:36": -9288933,
+ "83:36": -9288933,
+ "84:36": 268435456,
+ "85:36": 402653184,
+ "86:36": 268435456,
+ "87:36": 402653184,
+ "88:36": -9288933,
+ "89:36": -9288933,
+ "90:36": -9288933,
+ "91:36": -9288933,
+ "92:36": -9288933,
+ "93:36": -9288933,
+ "94:36": -9288933,
+ "95:36": -9288933,
+ "96:36": -9288933,
+ "97:36": -9288933,
+ "98:36": -9288933,
+ "99:36": -9288933,
+ "100:36": -9288933,
+ "101:36": -9288933,
+ "102:36": -9288933,
+ "103:36": -9288933,
+ "104:36": -9288933,
+ "105:36": -9288933,
+ "106:36": 268435456,
+ "107:36": 402653184,
+ "108:36": 268435456,
+ "109:36": 402653184,
+ "110:36": 268435456,
+ "111:36": 402653184,
+ "112:36": 268435456,
+ "113:36": 402653184,
+ "114:36": 268435456,
+ "115:36": 402653184,
+ "116:36": 268435456,
+ "117:36": 402653184,
+ "118:36": 268435456,
+ "119:36": 402653184,
+ "120:36": 268435456,
+ "121:36": 402653184,
+ "122:36": 268435456,
+ "123:36": 402653184,
+ "124:36": 268435456,
+ "125:36": 402653184,
+ "126:36": 268435456,
+ "127:36": 402653184,
+ "0:37": 402653184,
+ "1:37": 268435456,
+ "2:37": 402653184,
+ "3:37": 268435456,
+ "4:37": 402653184,
+ "5:37": 268435456,
+ "6:37": 402653184,
+ "7:37": 268435456,
+ "8:37": 402653184,
+ "9:37": 268435456,
+ "10:37": 402653184,
+ "11:37": 268435456,
+ "12:37": 402653184,
+ "13:37": 268435456,
+ "14:37": 402653184,
+ "15:37": 268435456,
+ "16:37": 402653184,
+ "17:37": 268435456,
+ "18:37": 402653184,
+ "19:37": 268435456,
+ "20:37": 402653184,
+ "21:37": 268435456,
+ "22:37": -9288933,
+ "23:37": -9288933,
+ "24:37": -9288933,
+ "25:37": -9288933,
+ "26:37": -9288933,
+ "27:37": -9288933,
+ "28:37": -9288933,
+ "29:37": -9288933,
+ "30:37": -9288933,
+ "31:37": -9288933,
+ "32:37": -9288933,
+ "33:37": -9288933,
+ "34:37": -9288933,
+ "35:37": -9288933,
+ "36:37": -9288933,
+ "37:37": -9288933,
+ "38:37": -9288933,
+ "39:37": -9288933,
+ "40:37": -9288933,
+ "41:37": -9288933,
+ "42:37": -9288933,
+ "43:37": -9288933,
+ "44:37": -9288933,
+ "45:37": -9288933,
+ "46:37": -9288933,
+ "47:37": -9288933,
+ "48:37": -9288933,
+ "49:37": -9288933,
+ "50:37": -9288933,
+ "51:37": -9288933,
+ "52:37": -9288933,
+ "53:37": -9288933,
+ "54:37": -9288933,
+ "55:37": -9288933,
+ "56:37": -9288933,
+ "57:37": -9288933,
+ "58:37": -9288933,
+ "59:37": -9288933,
+ "60:37": -9288933,
+ "61:37": -9288933,
+ "62:37": 402653184,
+ "63:37": 268435456,
+ "64:37": 402653184,
+ "65:37": 268435456,
+ "66:37": -9288933,
+ "67:37": -9288933,
+ "68:37": -9288933,
+ "69:37": -9288933,
+ "70:37": -9288933,
+ "71:37": -9288933,
+ "72:37": -9288933,
+ "73:37": -9288933,
+ "74:37": -9288933,
+ "75:37": -9288933,
+ "76:37": -9288933,
+ "77:37": -9288933,
+ "78:37": -9288933,
+ "79:37": -9288933,
+ "80:37": -9288933,
+ "81:37": -9288933,
+ "82:37": -9288933,
+ "83:37": -9288933,
+ "84:37": 402653184,
+ "85:37": 268435456,
+ "86:37": 402653184,
+ "87:37": 268435456,
+ "88:37": -9288933,
+ "89:37": -9288933,
+ "90:37": -9288933,
+ "91:37": -9288933,
+ "92:37": -9288933,
+ "93:37": -9288933,
+ "94:37": -9288933,
+ "95:37": -9288933,
+ "96:37": -9288933,
+ "97:37": -9288933,
+ "98:37": -9288933,
+ "99:37": -9288933,
+ "100:37": -9288933,
+ "101:37": -9288933,
+ "102:37": -9288933,
+ "103:37": -9288933,
+ "104:37": -9288933,
+ "105:37": -9288933,
+ "106:37": 402653184,
+ "107:37": 268435456,
+ "108:37": 402653184,
+ "109:37": 268435456,
+ "110:37": 402653184,
+ "111:37": 268435456,
+ "112:37": 402653184,
+ "113:37": 268435456,
+ "114:37": 402653184,
+ "115:37": 268435456,
+ "116:37": 402653184,
+ "117:37": 268435456,
+ "118:37": 402653184,
+ "119:37": 268435456,
+ "120:37": 402653184,
+ "121:37": 268435456,
+ "122:37": 402653184,
+ "123:37": 268435456,
+ "124:37": 402653184,
+ "125:37": 268435456,
+ "126:37": 402653184,
+ "127:37": 268435456,
+ "0:38": 268435456,
+ "1:38": 402653184,
+ "2:38": 268435456,
+ "3:38": 402653184,
+ "4:38": 268435456,
+ "5:38": 402653184,
+ "6:38": 268435456,
+ "7:38": 402653184,
+ "8:38": 268435456,
+ "9:38": 402653184,
+ "10:38": 268435456,
+ "11:38": 402653184,
+ "12:38": 268435456,
+ "13:38": 402653184,
+ "14:38": 268435456,
+ "15:38": 402653184,
+ "16:38": 268435456,
+ "17:38": 402653184,
+ "18:38": 268435456,
+ "19:38": 402653184,
+ "20:38": 268435456,
+ "21:38": 402653184,
+ "22:38": -9288933,
+ "23:38": -9288933,
+ "24:38": -9288933,
+ "25:38": -9288933,
+ "26:38": -9288933,
+ "27:38": -9288933,
+ "28:38": -9288933,
+ "29:38": -9288933,
+ "30:38": -9288933,
+ "31:38": -9288933,
+ "32:38": -9288933,
+ "33:38": -9288933,
+ "34:38": -9288933,
+ "35:38": -9288933,
+ "36:38": -9288933,
+ "37:38": -9288933,
+ "38:38": -9288933,
+ "39:38": -9288933,
+ "40:38": -9288933,
+ "41:38": -9288933,
+ "42:38": -9288933,
+ "43:38": -9288933,
+ "44:38": -9288933,
+ "45:38": -9288933,
+ "46:38": -9288933,
+ "47:38": -9288933,
+ "48:38": -9288933,
+ "49:38": -9288933,
+ "50:38": -9288933,
+ "51:38": -9288933,
+ "52:38": -9288933,
+ "53:38": -9288933,
+ "54:38": -9288933,
+ "55:38": -9288933,
+ "56:38": -9288933,
+ "57:38": -9288933,
+ "58:38": -9288933,
+ "59:38": -9288933,
+ "60:38": -9288933,
+ "61:38": -9288933,
+ "62:38": 268435456,
+ "63:38": 402653184,
+ "64:38": 268435456,
+ "65:38": 402653184,
+ "66:38": -9288933,
+ "67:38": -9288933,
+ "68:38": -9288933,
+ "69:38": -9288933,
+ "70:38": -9288933,
+ "71:38": -9288933,
+ "72:38": -9288933,
+ "73:38": -9288933,
+ "74:38": -9288933,
+ "75:38": -9288933,
+ "76:38": -9288933,
+ "77:38": -9288933,
+ "78:38": -9288933,
+ "79:38": -9288933,
+ "80:38": -9288933,
+ "81:38": -9288933,
+ "82:38": -9288933,
+ "83:38": -9288933,
+ "84:38": 268435456,
+ "85:38": 402653184,
+ "86:38": 268435456,
+ "87:38": 402653184,
+ "88:38": -9288933,
+ "89:38": -9288933,
+ "90:38": -9288933,
+ "91:38": -9288933,
+ "92:38": -9288933,
+ "93:38": -9288933,
+ "94:38": -9288933,
+ "95:38": -9288933,
+ "96:38": -9288933,
+ "97:38": -9288933,
+ "98:38": -9288933,
+ "99:38": -9288933,
+ "100:38": -9288933,
+ "101:38": -9288933,
+ "102:38": -9288933,
+ "103:38": -9288933,
+ "104:38": -9288933,
+ "105:38": -9288933,
+ "106:38": 268435456,
+ "107:38": 402653184,
+ "108:38": 268435456,
+ "109:38": 402653184,
+ "110:38": 268435456,
+ "111:38": 402653184,
+ "112:38": 268435456,
+ "113:38": 402653184,
+ "114:38": 268435456,
+ "115:38": 402653184,
+ "116:38": 268435456,
+ "117:38": 402653184,
+ "118:38": 268435456,
+ "119:38": 402653184,
+ "120:38": 268435456,
+ "121:38": 402653184,
+ "122:38": 268435456,
+ "123:38": 402653184,
+ "124:38": 268435456,
+ "125:38": 402653184,
+ "126:38": 268435456,
+ "127:38": 402653184,
+ "0:39": 402653184,
+ "1:39": 268435456,
+ "2:39": 402653184,
+ "3:39": 268435456,
+ "4:39": 402653184,
+ "5:39": 268435456,
+ "6:39": 402653184,
+ "7:39": 268435456,
+ "8:39": 402653184,
+ "9:39": 268435456,
+ "10:39": 402653184,
+ "11:39": 268435456,
+ "12:39": 402653184,
+ "13:39": 268435456,
+ "14:39": 402653184,
+ "15:39": 268435456,
+ "16:39": 402653184,
+ "17:39": 268435456,
+ "18:39": 402653184,
+ "19:39": 268435456,
+ "20:39": 402653184,
+ "21:39": 268435456,
+ "22:39": -9288933,
+ "23:39": -9288933,
+ "24:39": -9288933,
+ "25:39": -9288933,
+ "26:39": -9288933,
+ "27:39": -9288933,
+ "28:39": -9288933,
+ "29:39": -9288933,
+ "30:39": -9288933,
+ "31:39": -9288933,
+ "32:39": -9288933,
+ "33:39": -9288933,
+ "34:39": -9288933,
+ "35:39": -9288933,
+ "36:39": -9288933,
+ "37:39": -9288933,
+ "38:39": -9288933,
+ "39:39": -9288933,
+ "40:39": -9288933,
+ "41:39": -9288933,
+ "42:39": -9288933,
+ "43:39": -9288933,
+ "44:39": -9288933,
+ "45:39": -9288933,
+ "46:39": -9288933,
+ "47:39": -9288933,
+ "48:39": -9288933,
+ "49:39": -9288933,
+ "50:39": -9288933,
+ "51:39": -9288933,
+ "52:39": -9288933,
+ "53:39": -9288933,
+ "54:39": -9288933,
+ "55:39": -9288933,
+ "56:39": -9288933,
+ "57:39": -9288933,
+ "58:39": -9288933,
+ "59:39": -9288933,
+ "60:39": -9288933,
+ "61:39": -9288933,
+ "62:39": 402653184,
+ "63:39": 268435456,
+ "64:39": 402653184,
+ "65:39": 268435456,
+ "66:39": -9288933,
+ "67:39": -9288933,
+ "68:39": -9288933,
+ "69:39": -9288933,
+ "70:39": -9288933,
+ "71:39": -9288933,
+ "72:39": -9288933,
+ "73:39": -9288933,
+ "74:39": -9288933,
+ "75:39": -9288933,
+ "76:39": -9288933,
+ "77:39": -9288933,
+ "78:39": -9288933,
+ "79:39": -9288933,
+ "80:39": -9288933,
+ "81:39": -9288933,
+ "82:39": -9288933,
+ "83:39": -9288933,
+ "84:39": 402653184,
+ "85:39": 268435456,
+ "86:39": 402653184,
+ "87:39": 268435456,
+ "88:39": -9288933,
+ "89:39": -9288933,
+ "90:39": -9288933,
+ "91:39": -9288933,
+ "92:39": -9288933,
+ "93:39": -9288933,
+ "94:39": -9288933,
+ "95:39": -9288933,
+ "96:39": -9288933,
+ "97:39": -9288933,
+ "98:39": -9288933,
+ "99:39": -9288933,
+ "100:39": -9288933,
+ "101:39": -9288933,
+ "102:39": -9288933,
+ "103:39": -9288933,
+ "104:39": -9288933,
+ "105:39": -9288933,
+ "106:39": 402653184,
+ "107:39": 268435456,
+ "108:39": 402653184,
+ "109:39": 268435456,
+ "110:39": 402653184,
+ "111:39": 268435456,
+ "112:39": 402653184,
+ "113:39": 268435456,
+ "114:39": 402653184,
+ "115:39": 268435456,
+ "116:39": 402653184,
+ "117:39": 268435456,
+ "118:39": 402653184,
+ "119:39": 268435456,
+ "120:39": 402653184,
+ "121:39": 268435456,
+ "122:39": 402653184,
+ "123:39": 268435456,
+ "124:39": 402653184,
+ "125:39": 268435456,
+ "126:39": 402653184,
+ "127:39": 268435456,
+ "0:40": 268435456,
+ "1:40": 402653184,
+ "2:40": 268435456,
+ "3:40": 402653184,
+ "4:40": 268435456,
+ "5:40": 402653184,
+ "6:40": 268435456,
+ "7:40": 402653184,
+ "8:40": 268435456,
+ "9:40": 402653184,
+ "10:40": 268435456,
+ "11:40": 402653184,
+ "12:40": 268435456,
+ "13:40": 402653184,
+ "14:40": 268435456,
+ "15:40": 402653184,
+ "16:40": 268435456,
+ "17:40": 402653184,
+ "18:40": 268435456,
+ "19:40": 402653184,
+ "20:40": 268435456,
+ "21:40": 402653184,
+ "22:40": -9288933,
+ "23:40": -9288933,
+ "24:40": -9288933,
+ "25:40": -9288933,
+ "26:40": -9288933,
+ "27:40": -9288933,
+ "28:40": -9288933,
+ "29:40": -9288933,
+ "30:40": -9288933,
+ "31:40": -9288933,
+ "32:40": -9288933,
+ "33:40": -9288933,
+ "34:40": -9288933,
+ "35:40": -9288933,
+ "36:40": -9288933,
+ "37:40": -9288933,
+ "38:40": -9288933,
+ "39:40": -9288933,
+ "40:40": -9288933,
+ "41:40": -9288933,
+ "42:40": -9288933,
+ "43:40": -9288933,
+ "44:40": -9288933,
+ "45:40": -9288933,
+ "46:40": -9288933,
+ "47:40": -9288933,
+ "48:40": -9288933,
+ "49:40": -9288933,
+ "50:40": -9288933,
+ "51:40": -9288933,
+ "52:40": -9288933,
+ "53:40": -9288933,
+ "54:40": -9288933,
+ "55:40": -9288933,
+ "56:40": -9288933,
+ "57:40": -9288933,
+ "58:40": -9288933,
+ "59:40": -9288933,
+ "60:40": -9288933,
+ "61:40": -9288933,
+ "62:40": 268435456,
+ "63:40": 402653184,
+ "64:40": 268435456,
+ "65:40": 402653184,
+ "66:40": -9288933,
+ "67:40": -9288933,
+ "68:40": -9288933,
+ "69:40": -9288933,
+ "70:40": -9288933,
+ "71:40": -9288933,
+ "72:40": -9288933,
+ "73:40": -9288933,
+ "74:40": -9288933,
+ "75:40": -9288933,
+ "76:40": -1,
+ "77:40": -1,
+ "78:40": -1,
+ "79:40": -9288933,
+ "80:40": -9288933,
+ "81:40": -9288933,
+ "82:40": -9288933,
+ "83:40": -9288933,
+ "84:40": 268435456,
+ "85:40": 402653184,
+ "86:40": 268435456,
+ "87:40": 402653184,
+ "88:40": -9288933,
+ "89:40": -9288933,
+ "90:40": -9288933,
+ "91:40": -9288933,
+ "92:40": -9288933,
+ "93:40": -9288933,
+ "94:40": -9288933,
+ "95:40": -9288933,
+ "96:40": -9288933,
+ "97:40": -9288933,
+ "98:40": -9288933,
+ "99:40": -9288933,
+ "100:40": -9288933,
+ "101:40": -9288933,
+ "102:40": -9288933,
+ "103:40": -9288933,
+ "104:40": -9288933,
+ "105:40": -9288933,
+ "106:40": 268435456,
+ "107:40": 402653184,
+ "108:40": 268435456,
+ "109:40": 402653184,
+ "110:40": 268435456,
+ "111:40": 402653184,
+ "112:40": 268435456,
+ "113:40": 402653184,
+ "114:40": 268435456,
+ "115:40": 402653184,
+ "116:40": 268435456,
+ "117:40": 402653184,
+ "118:40": 268435456,
+ "119:40": 402653184,
+ "120:40": 268435456,
+ "121:40": 402653184,
+ "122:40": 268435456,
+ "123:40": 402653184,
+ "124:40": 268435456,
+ "125:40": 402653184,
+ "126:40": 268435456,
+ "127:40": 402653184,
+ "0:41": 402653184,
+ "1:41": 268435456,
+ "2:41": 402653184,
+ "3:41": 268435456,
+ "4:41": 402653184,
+ "5:41": 268435456,
+ "6:41": 402653184,
+ "7:41": 268435456,
+ "8:41": 402653184,
+ "9:41": 268435456,
+ "10:41": 402653184,
+ "11:41": 268435456,
+ "12:41": 402653184,
+ "13:41": 268435456,
+ "14:41": 402653184,
+ "15:41": 268435456,
+ "16:41": 402653184,
+ "17:41": 268435456,
+ "18:41": 402653184,
+ "19:41": 268435456,
+ "20:41": 402653184,
+ "21:41": 268435456,
+ "22:41": -9288933,
+ "23:41": -9288933,
+ "24:41": -9288933,
+ "25:41": -9288933,
+ "26:41": -9288933,
+ "27:41": -9288933,
+ "28:41": -9288933,
+ "29:41": -9288933,
+ "30:41": -9288933,
+ "31:41": -9288933,
+ "32:41": -9288933,
+ "33:41": -9288933,
+ "34:41": -9288933,
+ "35:41": -9288933,
+ "36:41": -9288933,
+ "37:41": -9288933,
+ "38:41": -9288933,
+ "39:41": -9288933,
+ "40:41": -9288933,
+ "41:41": -9288933,
+ "42:41": -9288933,
+ "43:41": -9288933,
+ "44:41": -9288933,
+ "45:41": -9288933,
+ "46:41": -9288933,
+ "47:41": -9288933,
+ "48:41": -9288933,
+ "49:41": -9288933,
+ "50:41": -9288933,
+ "51:41": -9288933,
+ "52:41": -9288933,
+ "53:41": -9288933,
+ "54:41": -9288933,
+ "55:41": -9288933,
+ "56:41": -9288933,
+ "57:41": -9288933,
+ "58:41": -9288933,
+ "59:41": -9288933,
+ "60:41": -9288933,
+ "61:41": -9288933,
+ "62:41": 402653184,
+ "63:41": 268435456,
+ "64:41": 402653184,
+ "65:41": 268435456,
+ "66:41": -9288933,
+ "67:41": -9288933,
+ "68:41": -9288933,
+ "69:41": -9288933,
+ "70:41": -9288933,
+ "71:41": -9288933,
+ "72:41": -9288933,
+ "73:41": -9288933,
+ "74:41": -9288933,
+ "75:41": -1,
+ "76:41": -1,
+ "77:41": -1,
+ "78:41": -9288933,
+ "79:41": -9288933,
+ "80:41": -9288933,
+ "81:41": -9288933,
+ "82:41": -9288933,
+ "83:41": -9288933,
+ "84:41": 402653184,
+ "85:41": 268435456,
+ "86:41": 402653184,
+ "87:41": 268435456,
+ "88:41": -9288933,
+ "89:41": -9288933,
+ "90:41": -9288933,
+ "91:41": -9288933,
+ "92:41": -9288933,
+ "93:41": -9288933,
+ "94:41": -9288933,
+ "95:41": -9288933,
+ "96:41": -9288933,
+ "97:41": -9288933,
+ "98:41": -9288933,
+ "99:41": -9288933,
+ "100:41": -9288933,
+ "101:41": -9288933,
+ "102:41": -9288933,
+ "103:41": -9288933,
+ "104:41": -9288933,
+ "105:41": -9288933,
+ "106:41": 402653184,
+ "107:41": 268435456,
+ "108:41": 402653184,
+ "109:41": 268435456,
+ "110:41": 402653184,
+ "111:41": 268435456,
+ "112:41": 402653184,
+ "113:41": 268435456,
+ "114:41": 402653184,
+ "115:41": 268435456,
+ "116:41": 402653184,
+ "117:41": 268435456,
+ "118:41": 402653184,
+ "119:41": 268435456,
+ "120:41": 402653184,
+ "121:41": 268435456,
+ "122:41": 402653184,
+ "123:41": 268435456,
+ "124:41": 402653184,
+ "125:41": 268435456,
+ "126:41": 402653184,
+ "127:41": 268435456,
+ "0:42": 268435456,
+ "1:42": 402653184,
+ "2:42": 268435456,
+ "3:42": 402653184,
+ "4:42": 268435456,
+ "5:42": 402653184,
+ "6:42": 268435456,
+ "7:42": 402653184,
+ "8:42": 268435456,
+ "9:42": 402653184,
+ "10:42": 268435456,
+ "11:42": 402653184,
+ "12:42": 268435456,
+ "13:42": 402653184,
+ "14:42": 268435456,
+ "15:42": 402653184,
+ "16:42": 268435456,
+ "17:42": 402653184,
+ "18:42": 268435456,
+ "19:42": 402653184,
+ "20:42": 268435456,
+ "21:42": 402653184,
+ "22:42": -9288933,
+ "23:42": -9288933,
+ "24:42": -9288933,
+ "25:42": -9288933,
+ "26:42": -9288933,
+ "27:42": -9288933,
+ "28:42": -9288933,
+ "29:42": -9288933,
+ "30:42": -9288933,
+ "31:42": -9288933,
+ "32:42": -9288933,
+ "33:42": -9288933,
+ "34:42": -9288933,
+ "35:42": -9288933,
+ "36:42": -9288933,
+ "37:42": -9288933,
+ "38:42": -9288933,
+ "39:42": -9288933,
+ "40:42": -9288933,
+ "41:42": -9288933,
+ "42:42": -9288933,
+ "43:42": -9288933,
+ "44:42": -9288933,
+ "45:42": -9288933,
+ "46:42": -9288933,
+ "47:42": -9288933,
+ "48:42": -9288933,
+ "49:42": -9288933,
+ "50:42": -9288933,
+ "51:42": -9288933,
+ "52:42": -9288933,
+ "53:42": -9288933,
+ "54:42": -9288933,
+ "55:42": -9288933,
+ "56:42": -9288933,
+ "57:42": -9288933,
+ "58:42": -9288933,
+ "59:42": -9288933,
+ "60:42": -9288933,
+ "61:42": -9288933,
+ "62:42": 268435456,
+ "63:42": 402653184,
+ "64:42": 268435456,
+ "65:42": 402653184,
+ "66:42": -9288933,
+ "67:42": -9288933,
+ "68:42": -9288933,
+ "69:42": -9288933,
+ "70:42": -9288933,
+ "71:42": -9288933,
+ "72:42": -9288933,
+ "73:42": -9288933,
+ "74:42": -9288933,
+ "75:42": -1,
+ "76:42": -1,
+ "77:42": -9288933,
+ "78:42": -9288933,
+ "79:42": -9288933,
+ "80:42": -9288933,
+ "81:42": -9288933,
+ "82:42": -9288933,
+ "83:42": -9288933,
+ "84:42": 268435456,
+ "85:42": 402653184,
+ "86:42": 268435456,
+ "87:42": 402653184,
+ "88:42": -9288933,
+ "89:42": -9288933,
+ "90:42": -9288933,
+ "91:42": -9288933,
+ "92:42": -9288933,
+ "93:42": -9288933,
+ "94:42": -9288933,
+ "95:42": -9288933,
+ "96:42": -9288933,
+ "97:42": -9288933,
+ "98:42": -9288933,
+ "99:42": -9288933,
+ "100:42": -9288933,
+ "101:42": -9288933,
+ "102:42": -9288933,
+ "103:42": -9288933,
+ "104:42": -9288933,
+ "105:42": -9288933,
+ "106:42": 268435456,
+ "107:42": 402653184,
+ "108:42": 268435456,
+ "109:42": 402653184,
+ "110:42": 268435456,
+ "111:42": 402653184,
+ "112:42": 268435456,
+ "113:42": 402653184,
+ "114:42": 268435456,
+ "115:42": 402653184,
+ "116:42": 268435456,
+ "117:42": 402653184,
+ "118:42": 268435456,
+ "119:42": 402653184,
+ "120:42": 268435456,
+ "121:42": 402653184,
+ "122:42": 268435456,
+ "123:42": 402653184,
+ "124:42": 268435456,
+ "125:42": 402653184,
+ "126:42": 268435456,
+ "127:42": 402653184,
+ "0:43": 402653184,
+ "1:43": 268435456,
+ "2:43": 402653184,
+ "3:43": 268435456,
+ "4:43": 402653184,
+ "5:43": 268435456,
+ "6:43": 402653184,
+ "7:43": 268435456,
+ "8:43": 402653184,
+ "9:43": 268435456,
+ "10:43": 402653184,
+ "11:43": 268435456,
+ "12:43": 402653184,
+ "13:43": 268435456,
+ "14:43": 402653184,
+ "15:43": 268435456,
+ "16:43": 402653184,
+ "17:43": 268435456,
+ "18:43": 402653184,
+ "19:43": 268435456,
+ "20:43": 402653184,
+ "21:43": 268435456,
+ "22:43": -9288933,
+ "23:43": -9288933,
+ "24:43": -9288933,
+ "25:43": -9288933,
+ "26:43": -9288933,
+ "27:43": -9288933,
+ "28:43": -9288933,
+ "29:43": -9288933,
+ "30:43": -9288933,
+ "31:43": -9288933,
+ "32:43": -9288933,
+ "33:43": -9288933,
+ "34:43": -9288933,
+ "35:43": -9288933,
+ "36:43": -9288933,
+ "37:43": -9288933,
+ "38:43": -9288933,
+ "39:43": -9288933,
+ "40:43": -9288933,
+ "41:43": -9288933,
+ "42:43": -9288933,
+ "43:43": -9288933,
+ "44:43": -9288933,
+ "45:43": -9288933,
+ "46:43": -9288933,
+ "47:43": -9288933,
+ "48:43": -9288933,
+ "49:43": -9288933,
+ "50:43": -9288933,
+ "51:43": -9288933,
+ "52:43": -9288933,
+ "53:43": -9288933,
+ "54:43": -9288933,
+ "55:43": -9288933,
+ "56:43": -9288933,
+ "57:43": -9288933,
+ "58:43": -9288933,
+ "59:43": -9288933,
+ "60:43": -9288933,
+ "61:43": -9288933,
+ "62:43": 402653184,
+ "63:43": 268435456,
+ "64:43": 402653184,
+ "65:43": 268435456,
+ "66:43": -9288933,
+ "67:43": -9288933,
+ "68:43": -9288933,
+ "69:43": -9288933,
+ "70:43": -9288933,
+ "71:43": -9288933,
+ "72:43": -1,
+ "73:43": -1,
+ "74:43": -9288933,
+ "75:43": -1,
+ "76:43": -1,
+ "77:43": -9288933,
+ "78:43": -9288933,
+ "79:43": -9288933,
+ "80:43": -9288933,
+ "81:43": -9288933,
+ "82:43": -9288933,
+ "83:43": -9288933,
+ "84:43": 402653184,
+ "85:43": 268435456,
+ "86:43": 402653184,
+ "87:43": 268435456,
+ "88:43": -9288933,
+ "89:43": -9288933,
+ "90:43": -9288933,
+ "91:43": -9288933,
+ "92:43": -9288933,
+ "93:43": -9288933,
+ "94:43": -9288933,
+ "95:43": -9288933,
+ "96:43": -9288933,
+ "97:43": -9288933,
+ "98:43": -9288933,
+ "99:43": -9288933,
+ "100:43": -9288933,
+ "101:43": -9288933,
+ "102:43": -9288933,
+ "103:43": -9288933,
+ "104:43": -9288933,
+ "105:43": -9288933,
+ "106:43": 402653184,
+ "107:43": 268435456,
+ "108:43": 402653184,
+ "109:43": 268435456,
+ "110:43": 402653184,
+ "111:43": 268435456,
+ "112:43": 402653184,
+ "113:43": 268435456,
+ "114:43": 402653184,
+ "115:43": 268435456,
+ "116:43": 402653184,
+ "117:43": 268435456,
+ "118:43": 402653184,
+ "119:43": 268435456,
+ "120:43": 402653184,
+ "121:43": 268435456,
+ "122:43": 402653184,
+ "123:43": 268435456,
+ "124:43": 402653184,
+ "125:43": 268435456,
+ "126:43": 402653184,
+ "127:43": 268435456,
+ "0:44": 268435456,
+ "1:44": 402653184,
+ "2:44": 268435456,
+ "3:44": 402653184,
+ "4:44": 268435456,
+ "5:44": 402653184,
+ "6:44": 268435456,
+ "7:44": 402653184,
+ "8:44": 268435456,
+ "9:44": 402653184,
+ "10:44": 268435456,
+ "11:44": 402653184,
+ "12:44": 268435456,
+ "13:44": 402653184,
+ "14:44": 268435456,
+ "15:44": 402653184,
+ "16:44": 268435456,
+ "17:44": 402653184,
+ "18:44": 268435456,
+ "19:44": 402653184,
+ "20:44": 268435456,
+ "21:44": 402653184,
+ "22:44": -9288933,
+ "23:44": -9288933,
+ "24:44": -9288933,
+ "25:44": -9288933,
+ "26:44": -9288933,
+ "27:44": -9288933,
+ "28:44": -9288933,
+ "29:44": -9288933,
+ "30:44": -9288933,
+ "31:44": -9288933,
+ "32:44": -9288933,
+ "33:44": -9288933,
+ "34:44": -9288933,
+ "35:44": -9288933,
+ "36:44": -9288933,
+ "37:44": -9288933,
+ "38:44": -9288933,
+ "39:44": -9288933,
+ "40:44": -9288933,
+ "41:44": -9288933,
+ "42:44": -9288933,
+ "43:44": -9288933,
+ "44:44": -9288933,
+ "45:44": -9288933,
+ "46:44": -9288933,
+ "47:44": -9288933,
+ "48:44": -9288933,
+ "49:44": -9288933,
+ "50:44": -9288933,
+ "51:44": -9288933,
+ "52:44": -9288933,
+ "53:44": -9288933,
+ "54:44": -9288933,
+ "55:44": -9288933,
+ "56:44": -9288933,
+ "57:44": -9288933,
+ "58:44": -9288933,
+ "59:44": -9288933,
+ "60:44": -9288933,
+ "61:44": -9288933,
+ "62:44": 268435456,
+ "63:44": 402653184,
+ "64:44": 268435456,
+ "65:44": 402653184,
+ "66:44": -9288933,
+ "67:44": -9288933,
+ "68:44": -9288933,
+ "69:44": -9288933,
+ "70:44": -9288933,
+ "71:44": -9288933,
+ "72:44": -9288933,
+ "73:44": -1,
+ "74:44": -1,
+ "75:44": -1,
+ "76:44": -9288933,
+ "77:44": -9288933,
+ "78:44": -9288933,
+ "79:44": -9288933,
+ "80:44": -9288933,
+ "81:44": -9288933,
+ "82:44": -9288933,
+ "83:44": -9288933,
+ "84:44": 268435456,
+ "85:44": 402653184,
+ "86:44": 268435456,
+ "87:44": 402653184,
+ "88:44": -9288933,
+ "89:44": -9288933,
+ "90:44": -9288933,
+ "91:44": -9288933,
+ "92:44": -9288933,
+ "93:44": -9288933,
+ "94:44": -9288933,
+ "95:44": -9288933,
+ "96:44": -9288933,
+ "97:44": -9288933,
+ "98:44": -9288933,
+ "99:44": -9288933,
+ "100:44": -9288933,
+ "101:44": -9288933,
+ "102:44": -9288933,
+ "103:44": -9288933,
+ "104:44": -9288933,
+ "105:44": -9288933,
+ "106:44": 268435456,
+ "107:44": 402653184,
+ "108:44": 268435456,
+ "109:44": 402653184,
+ "110:44": 268435456,
+ "111:44": 402653184,
+ "112:44": 268435456,
+ "113:44": 402653184,
+ "114:44": 268435456,
+ "115:44": 402653184,
+ "116:44": 268435456,
+ "117:44": 402653184,
+ "118:44": 268435456,
+ "119:44": 402653184,
+ "120:44": 268435456,
+ "121:44": 402653184,
+ "122:44": 268435456,
+ "123:44": 402653184,
+ "124:44": 268435456,
+ "125:44": 402653184,
+ "126:44": 268435456,
+ "127:44": 402653184,
+ "0:45": 402653184,
+ "1:45": 268435456,
+ "2:45": 402653184,
+ "3:45": 268435456,
+ "4:45": 402653184,
+ "5:45": 268435456,
+ "6:45": 402653184,
+ "7:45": 268435456,
+ "8:45": 402653184,
+ "9:45": 268435456,
+ "10:45": 402653184,
+ "11:45": 268435456,
+ "12:45": 402653184,
+ "13:45": 268435456,
+ "14:45": 402653184,
+ "15:45": 268435456,
+ "16:45": 402653184,
+ "17:45": 268435456,
+ "18:45": 402653184,
+ "19:45": 268435456,
+ "20:45": 402653184,
+ "21:45": 268435456,
+ "22:45": -9288933,
+ "23:45": -9288933,
+ "24:45": -9288933,
+ "25:45": -9288933,
+ "26:45": -9288933,
+ "27:45": -9288933,
+ "28:45": -9288933,
+ "29:45": -9288933,
+ "30:45": -9288933,
+ "31:45": -9288933,
+ "32:45": -9288933,
+ "33:45": -9288933,
+ "34:45": -9288933,
+ "35:45": -9288933,
+ "36:45": -9288933,
+ "37:45": -9288933,
+ "38:45": -9288933,
+ "39:45": -9288933,
+ "40:45": -9288933,
+ "41:45": -9288933,
+ "42:45": -9288933,
+ "43:45": -9288933,
+ "44:45": -9288933,
+ "45:45": -9288933,
+ "46:45": -9288933,
+ "47:45": -9288933,
+ "48:45": -9288933,
+ "49:45": -9288933,
+ "50:45": -9288933,
+ "51:45": -9288933,
+ "52:45": -9288933,
+ "53:45": -9288933,
+ "54:45": -9288933,
+ "55:45": -9288933,
+ "56:45": -9288933,
+ "57:45": -9288933,
+ "58:45": -9288933,
+ "59:45": -9288933,
+ "60:45": -9288933,
+ "61:45": -9288933,
+ "62:45": 402653184,
+ "63:45": 268435456,
+ "64:45": 402653184,
+ "65:45": 268435456,
+ "66:45": -9288933,
+ "67:45": -9288933,
+ "68:45": -9288933,
+ "69:45": -9288933,
+ "70:45": -9288933,
+ "71:45": -9288933,
+ "72:45": -9288933,
+ "73:45": -1,
+ "74:45": -1,
+ "75:45": -1,
+ "76:45": -9288933,
+ "77:45": -9288933,
+ "78:45": -9288933,
+ "79:45": -9288933,
+ "80:45": -9288933,
+ "81:45": -9288933,
+ "82:45": -9288933,
+ "83:45": -9288933,
+ "84:45": 402653184,
+ "85:45": 268435456,
+ "86:45": 402653184,
+ "87:45": 268435456,
+ "88:45": -9288933,
+ "89:45": -9288933,
+ "90:45": -9288933,
+ "91:45": -9288933,
+ "92:45": -9288933,
+ "93:45": -9288933,
+ "94:45": -9288933,
+ "95:45": -9288933,
+ "96:45": -9288933,
+ "97:45": -9288933,
+ "98:45": -9288933,
+ "99:45": -9288933,
+ "100:45": -9288933,
+ "101:45": -9288933,
+ "102:45": -9288933,
+ "103:45": -9288933,
+ "104:45": -9288933,
+ "105:45": -9288933,
+ "106:45": 402653184,
+ "107:45": 268435456,
+ "108:45": 402653184,
+ "109:45": 268435456,
+ "110:45": 402653184,
+ "111:45": 268435456,
+ "112:45": 402653184,
+ "113:45": 268435456,
+ "114:45": 402653184,
+ "115:45": 268435456,
+ "116:45": 402653184,
+ "117:45": 268435456,
+ "118:45": 402653184,
+ "119:45": 268435456,
+ "120:45": 402653184,
+ "121:45": 268435456,
+ "122:45": 402653184,
+ "123:45": 268435456,
+ "124:45": 402653184,
+ "125:45": 268435456,
+ "126:45": 402653184,
+ "127:45": 268435456,
+ "0:46": 268435456,
+ "1:46": 402653184,
+ "2:46": 268435456,
+ "3:46": 402653184,
+ "4:46": 268435456,
+ "5:46": 402653184,
+ "6:46": 268435456,
+ "7:46": 402653184,
+ "8:46": 268435456,
+ "9:46": 402653184,
+ "10:46": 268435456,
+ "11:46": 402653184,
+ "12:46": 268435456,
+ "13:46": 402653184,
+ "14:46": 268435456,
+ "15:46": 402653184,
+ "16:46": 268435456,
+ "17:46": 402653184,
+ "18:46": 268435456,
+ "19:46": 402653184,
+ "20:46": 268435456,
+ "21:46": 402653184,
+ "22:46": -9288933,
+ "23:46": -9288933,
+ "24:46": -9288933,
+ "25:46": -9288933,
+ "26:46": -9288933,
+ "27:46": -9288933,
+ "28:46": -9288933,
+ "29:46": -9288933,
+ "30:46": -9288933,
+ "31:46": -9288933,
+ "32:46": -9288933,
+ "33:46": -9288933,
+ "34:46": -9288933,
+ "35:46": -9288933,
+ "36:46": -9288933,
+ "37:46": -9288933,
+ "38:46": -9288933,
+ "39:46": -9288933,
+ "40:46": -9288933,
+ "41:46": -9288933,
+ "42:46": -9288933,
+ "43:46": -9288933,
+ "44:46": -9288933,
+ "45:46": -9288933,
+ "46:46": -9288933,
+ "47:46": -9288933,
+ "48:46": -9288933,
+ "49:46": -9288933,
+ "50:46": -9288933,
+ "51:46": -9288933,
+ "52:46": -9288933,
+ "53:46": -9288933,
+ "54:46": -9288933,
+ "55:46": -9288933,
+ "56:46": -9288933,
+ "57:46": -9288933,
+ "58:46": -9288933,
+ "59:46": -9288933,
+ "60:46": -9288933,
+ "61:46": -9288933,
+ "62:46": 268435456,
+ "63:46": 402653184,
+ "64:46": 268435456,
+ "65:46": 402653184,
+ "66:46": -9288933,
+ "67:46": -9288933,
+ "68:46": -9288933,
+ "69:46": -9288933,
+ "70:46": -9288933,
+ "71:46": -9288933,
+ "72:46": -9288933,
+ "73:46": -9288933,
+ "74:46": -9288933,
+ "75:46": -9288933,
+ "76:46": -9288933,
+ "77:46": -9288933,
+ "78:46": -9288933,
+ "79:46": -9288933,
+ "80:46": -9288933,
+ "81:46": -9288933,
+ "82:46": -9288933,
+ "83:46": -9288933,
+ "84:46": 268435456,
+ "85:46": 402653184,
+ "86:46": 268435456,
+ "87:46": 402653184,
+ "88:46": -9288933,
+ "89:46": -9288933,
+ "90:46": -9288933,
+ "91:46": -9288933,
+ "92:46": -9288933,
+ "93:46": -9288933,
+ "94:46": -9288933,
+ "95:46": -9288933,
+ "96:46": -9288933,
+ "97:46": -9288933,
+ "98:46": -9288933,
+ "99:46": -9288933,
+ "100:46": -9288933,
+ "101:46": -9288933,
+ "102:46": -9288933,
+ "103:46": -9288933,
+ "104:46": -9288933,
+ "105:46": -9288933,
+ "106:46": 268435456,
+ "107:46": 402653184,
+ "108:46": 268435456,
+ "109:46": 402653184,
+ "110:46": 268435456,
+ "111:46": 402653184,
+ "112:46": 268435456,
+ "113:46": 402653184,
+ "114:46": 268435456,
+ "115:46": 402653184,
+ "116:46": 268435456,
+ "117:46": 402653184,
+ "118:46": 268435456,
+ "119:46": 402653184,
+ "120:46": 268435456,
+ "121:46": 402653184,
+ "122:46": 268435456,
+ "123:46": 402653184,
+ "124:46": 268435456,
+ "125:46": 402653184,
+ "126:46": 268435456,
+ "127:46": 402653184,
+ "0:47": 402653184,
+ "1:47": 268435456,
+ "2:47": 402653184,
+ "3:47": 268435456,
+ "4:47": 402653184,
+ "5:47": 268435456,
+ "6:47": 402653184,
+ "7:47": 268435456,
+ "8:47": 402653184,
+ "9:47": 268435456,
+ "10:47": 402653184,
+ "11:47": 268435456,
+ "12:47": 402653184,
+ "13:47": 268435456,
+ "14:47": 402653184,
+ "15:47": 268435456,
+ "16:47": 402653184,
+ "17:47": 268435456,
+ "18:47": 402653184,
+ "19:47": 268435456,
+ "20:47": 402653184,
+ "21:47": 268435456,
+ "22:47": -9288933,
+ "23:47": -9288933,
+ "24:47": -9288933,
+ "25:47": -9288933,
+ "26:47": -9288933,
+ "27:47": -9288933,
+ "28:47": -9288933,
+ "29:47": -9288933,
+ "30:47": -9288933,
+ "31:47": -9288933,
+ "32:47": -9288933,
+ "33:47": -9288933,
+ "34:47": -9288933,
+ "35:47": -9288933,
+ "36:47": -9288933,
+ "37:47": -9288933,
+ "38:47": -9288933,
+ "39:47": -9288933,
+ "40:47": -9288933,
+ "41:47": -9288933,
+ "42:47": -9288933,
+ "43:47": -9288933,
+ "44:47": -9288933,
+ "45:47": -9288933,
+ "46:47": -9288933,
+ "47:47": -9288933,
+ "48:47": -9288933,
+ "49:47": -9288933,
+ "50:47": -9288933,
+ "51:47": -9288933,
+ "52:47": -9288933,
+ "53:47": -9288933,
+ "54:47": -9288933,
+ "55:47": -9288933,
+ "56:47": -9288933,
+ "57:47": -9288933,
+ "58:47": -9288933,
+ "59:47": -9288933,
+ "60:47": -9288933,
+ "61:47": -9288933,
+ "62:47": 402653184,
+ "63:47": 268435456,
+ "64:47": 402653184,
+ "65:47": 268435456,
+ "66:47": -9288933,
+ "67:47": -9288933,
+ "68:47": -9288933,
+ "69:47": -9288933,
+ "70:47": -9288933,
+ "71:47": -9288933,
+ "72:47": -9288933,
+ "73:47": -9288933,
+ "74:47": -9288933,
+ "75:47": -9288933,
+ "76:47": -9288933,
+ "77:47": -9288933,
+ "78:47": -9288933,
+ "79:47": -9288933,
+ "80:47": -9288933,
+ "81:47": -9288933,
+ "82:47": -9288933,
+ "83:47": -9288933,
+ "84:47": 402653184,
+ "85:47": 268435456,
+ "86:47": 402653184,
+ "87:47": 268435456,
+ "88:47": -9288933,
+ "89:47": -9288933,
+ "90:47": -9288933,
+ "91:47": -9288933,
+ "92:47": -9288933,
+ "93:47": -9288933,
+ "94:47": -9288933,
+ "95:47": -9288933,
+ "96:47": -9288933,
+ "97:47": -9288933,
+ "98:47": -9288933,
+ "99:47": -9288933,
+ "100:47": -9288933,
+ "101:47": -9288933,
+ "102:47": -9288933,
+ "103:47": -9288933,
+ "104:47": -9288933,
+ "105:47": -9288933,
+ "106:47": 402653184,
+ "107:47": 268435456,
+ "108:47": 402653184,
+ "109:47": 268435456,
+ "110:47": 402653184,
+ "111:47": 268435456,
+ "112:47": 402653184,
+ "113:47": 268435456,
+ "114:47": 402653184,
+ "115:47": 268435456,
+ "116:47": 402653184,
+ "117:47": 268435456,
+ "118:47": 402653184,
+ "119:47": 268435456,
+ "120:47": 402653184,
+ "121:47": 268435456,
+ "122:47": 402653184,
+ "123:47": 268435456,
+ "124:47": 402653184,
+ "125:47": 268435456,
+ "126:47": 402653184,
+ "127:47": 268435456,
+ "0:48": 268435456,
+ "1:48": 402653184,
+ "2:48": 268435456,
+ "3:48": 402653184,
+ "4:48": 268435456,
+ "5:48": 402653184,
+ "6:48": 268435456,
+ "7:48": 402653184,
+ "8:48": 268435456,
+ "9:48": 402653184,
+ "10:48": 268435456,
+ "11:48": 402653184,
+ "12:48": 268435456,
+ "13:48": 402653184,
+ "14:48": 268435456,
+ "15:48": 402653184,
+ "16:48": 268435456,
+ "17:48": 402653184,
+ "18:48": 268435456,
+ "19:48": 402653184,
+ "20:48": 268435456,
+ "21:48": 402653184,
+ "22:48": -9288933,
+ "23:48": -9288933,
+ "24:48": -9288933,
+ "25:48": -9288933,
+ "26:48": -9288933,
+ "27:48": -9288933,
+ "28:48": -9288933,
+ "29:48": -9288933,
+ "30:48": -9288933,
+ "31:48": -9288933,
+ "32:48": -9288933,
+ "33:48": -9288933,
+ "34:48": -9288933,
+ "35:48": -9288933,
+ "36:48": -9288933,
+ "37:48": -9288933,
+ "38:48": -9288933,
+ "39:48": -9288933,
+ "40:48": -9288933,
+ "41:48": -9288933,
+ "42:48": -9288933,
+ "43:48": -9288933,
+ "44:48": -9288933,
+ "45:48": -9288933,
+ "46:48": -9288933,
+ "47:48": -9288933,
+ "48:48": -9288933,
+ "49:48": -9288933,
+ "50:48": -9288933,
+ "51:48": -9288933,
+ "52:48": -9288933,
+ "53:48": -9288933,
+ "54:48": -9288933,
+ "55:48": -9288933,
+ "56:48": -9288933,
+ "57:48": -9288933,
+ "58:48": -9288933,
+ "59:48": -9288933,
+ "60:48": -9288933,
+ "61:48": -9288933,
+ "62:48": 268435456,
+ "63:48": 402653184,
+ "64:48": 268435456,
+ "65:48": 402653184,
+ "66:48": -9288933,
+ "67:48": -9288933,
+ "68:48": -9288933,
+ "69:48": -9288933,
+ "70:48": -9288933,
+ "71:48": -9288933,
+ "72:48": -9288933,
+ "73:48": -9288933,
+ "74:48": -9288933,
+ "75:48": -9288933,
+ "76:48": -9288933,
+ "77:48": -9288933,
+ "78:48": -9288933,
+ "79:48": -9288933,
+ "80:48": -9288933,
+ "81:48": -9288933,
+ "82:48": -9288933,
+ "83:48": -9288933,
+ "84:48": 268435456,
+ "85:48": 402653184,
+ "86:48": 268435456,
+ "87:48": 402653184,
+ "88:48": -9288933,
+ "89:48": -9288933,
+ "90:48": -9288933,
+ "91:48": -9288933,
+ "92:48": -9288933,
+ "93:48": -9288933,
+ "94:48": -9288933,
+ "95:48": -9288933,
+ "96:48": -9288933,
+ "97:48": -9288933,
+ "98:48": -9288933,
+ "99:48": -9288933,
+ "100:48": -9288933,
+ "101:48": -9288933,
+ "102:48": -9288933,
+ "103:48": -9288933,
+ "104:48": -9288933,
+ "105:48": -9288933,
+ "106:48": 268435456,
+ "107:48": 402653184,
+ "108:48": 268435456,
+ "109:48": 402653184,
+ "110:48": 268435456,
+ "111:48": 402653184,
+ "112:48": 268435456,
+ "113:48": 402653184,
+ "114:48": 268435456,
+ "115:48": 402653184,
+ "116:48": 268435456,
+ "117:48": 402653184,
+ "118:48": 268435456,
+ "119:48": 402653184,
+ "120:48": 268435456,
+ "121:48": 402653184,
+ "122:48": 268435456,
+ "123:48": 402653184,
+ "124:48": 268435456,
+ "125:48": 402653184,
+ "126:48": 268435456,
+ "127:48": 402653184,
+ "0:49": 402653184,
+ "1:49": 268435456,
+ "2:49": 402653184,
+ "3:49": 268435456,
+ "4:49": 402653184,
+ "5:49": 268435456,
+ "6:49": 402653184,
+ "7:49": 268435456,
+ "8:49": 402653184,
+ "9:49": 268435456,
+ "10:49": 402653184,
+ "11:49": 268435456,
+ "12:49": 402653184,
+ "13:49": 268435456,
+ "14:49": 402653184,
+ "15:49": 268435456,
+ "16:49": 402653184,
+ "17:49": 268435456,
+ "18:49": 402653184,
+ "19:49": 268435456,
+ "20:49": 402653184,
+ "21:49": 268435456,
+ "22:49": -9288933,
+ "23:49": -9288933,
+ "24:49": -9288933,
+ "25:49": -9288933,
+ "26:49": -9288933,
+ "27:49": -9288933,
+ "28:49": -9288933,
+ "29:49": -9288933,
+ "30:49": -9288933,
+ "31:49": -9288933,
+ "32:49": -9288933,
+ "33:49": -9288933,
+ "34:49": -9288933,
+ "35:49": -9288933,
+ "36:49": -9288933,
+ "37:49": -9288933,
+ "38:49": -9288933,
+ "39:49": -9288933,
+ "40:49": -9288933,
+ "41:49": -9288933,
+ "42:49": -9288933,
+ "43:49": -9288933,
+ "44:49": -9288933,
+ "45:49": -9288933,
+ "46:49": -9288933,
+ "47:49": -9288933,
+ "48:49": -9288933,
+ "49:49": -9288933,
+ "50:49": -9288933,
+ "51:49": -9288933,
+ "52:49": -9288933,
+ "53:49": -9288933,
+ "54:49": -9288933,
+ "55:49": -9288933,
+ "56:49": -9288933,
+ "57:49": -9288933,
+ "58:49": -9288933,
+ "59:49": -9288933,
+ "60:49": -9288933,
+ "61:49": -9288933,
+ "62:49": 402653184,
+ "63:49": 268435456,
+ "64:49": 402653184,
+ "65:49": 268435456,
+ "66:49": -9288933,
+ "67:49": -9288933,
+ "68:49": -9288933,
+ "69:49": -9288933,
+ "70:49": -9288933,
+ "71:49": -9288933,
+ "72:49": -9288933,
+ "73:49": -9288933,
+ "74:49": -9288933,
+ "75:49": -9288933,
+ "76:49": -9288933,
+ "77:49": -9288933,
+ "78:49": -9288933,
+ "79:49": -9288933,
+ "80:49": -9288933,
+ "81:49": -9288933,
+ "82:49": -9288933,
+ "83:49": -9288933,
+ "84:49": 402653184,
+ "85:49": 268435456,
+ "86:49": 402653184,
+ "87:49": 268435456,
+ "88:49": -9288933,
+ "89:49": -9288933,
+ "90:49": -9288933,
+ "91:49": -9288933,
+ "92:49": -9288933,
+ "93:49": -9288933,
+ "94:49": -9288933,
+ "95:49": -9288933,
+ "96:49": -9288933,
+ "97:49": -9288933,
+ "98:49": -9288933,
+ "99:49": -9288933,
+ "100:49": -9288933,
+ "101:49": -9288933,
+ "102:49": -9288933,
+ "103:49": -9288933,
+ "104:49": -9288933,
+ "105:49": -9288933,
+ "106:49": 402653184,
+ "107:49": 268435456,
+ "108:49": 402653184,
+ "109:49": 268435456,
+ "110:49": 402653184,
+ "111:49": 268435456,
+ "112:49": 402653184,
+ "113:49": 268435456,
+ "114:49": 402653184,
+ "115:49": 268435456,
+ "116:49": 402653184,
+ "117:49": 268435456,
+ "118:49": 402653184,
+ "119:49": 268435456,
+ "120:49": 402653184,
+ "121:49": 268435456,
+ "122:49": 402653184,
+ "123:49": 268435456,
+ "124:49": 402653184,
+ "125:49": 268435456,
+ "126:49": 402653184,
+ "127:49": 268435456,
+ "0:50": 268435456,
+ "1:50": 402653184,
+ "2:50": 268435456,
+ "3:50": 402653184,
+ "4:50": 268435456,
+ "5:50": 402653184,
+ "6:50": 268435456,
+ "7:50": 402653184,
+ "8:50": 268435456,
+ "9:50": 402653184,
+ "10:50": 268435456,
+ "11:50": 402653184,
+ "12:50": 268435456,
+ "13:50": 402653184,
+ "14:50": 268435456,
+ "15:50": 402653184,
+ "16:50": 268435456,
+ "17:50": 402653184,
+ "18:50": 268435456,
+ "19:50": 402653184,
+ "20:50": 268435456,
+ "21:50": 402653184,
+ "22:50": -9288933,
+ "23:50": -9288933,
+ "24:50": -9288933,
+ "25:50": -9288933,
+ "26:50": -9288933,
+ "27:50": -9288933,
+ "28:50": -9288933,
+ "29:50": -9288933,
+ "30:50": -9288933,
+ "31:50": -9288933,
+ "32:50": -9288933,
+ "33:50": -9288933,
+ "34:50": -9288933,
+ "35:50": -9288933,
+ "36:50": -9288933,
+ "37:50": -9288933,
+ "38:50": -9288933,
+ "39:50": -9288933,
+ "40:50": -9288933,
+ "41:50": -9288933,
+ "42:50": -9288933,
+ "43:50": -9288933,
+ "44:50": -9288933,
+ "45:50": -9288933,
+ "46:50": -9288933,
+ "47:50": -9288933,
+ "48:50": -9288933,
+ "49:50": -9288933,
+ "50:50": -9288933,
+ "51:50": -9288933,
+ "52:50": -9288933,
+ "53:50": -9288933,
+ "54:50": -9288933,
+ "55:50": -9288933,
+ "56:50": -9288933,
+ "57:50": -9288933,
+ "58:50": -9288933,
+ "59:50": -9288933,
+ "60:50": -9288933,
+ "61:50": -9288933,
+ "62:50": 268435456,
+ "63:50": 402653184,
+ "64:50": 268435456,
+ "65:50": 402653184,
+ "66:50": -9288933,
+ "67:50": -9288933,
+ "68:50": -9288933,
+ "69:50": -9288933,
+ "70:50": -9288933,
+ "71:50": -9288933,
+ "72:50": -9288933,
+ "73:50": -9288933,
+ "74:50": -9288933,
+ "75:50": -9288933,
+ "76:50": -9288933,
+ "77:50": -9288933,
+ "78:50": -9288933,
+ "79:50": -9288933,
+ "80:50": -9288933,
+ "81:50": -9288933,
+ "82:50": -9288933,
+ "83:50": -9288933,
+ "84:50": 268435456,
+ "85:50": 402653184,
+ "86:50": 268435456,
+ "87:50": 402653184,
+ "88:50": -9288933,
+ "89:50": -9288933,
+ "90:50": -9288933,
+ "91:50": -9288933,
+ "92:50": -9288933,
+ "93:50": -9288933,
+ "94:50": -9288933,
+ "95:50": -9288933,
+ "96:50": -9288933,
+ "97:50": -9288933,
+ "98:50": -9288933,
+ "99:50": -9288933,
+ "100:50": -9288933,
+ "101:50": -9288933,
+ "102:50": -9288933,
+ "103:50": -9288933,
+ "104:50": -9288933,
+ "105:50": -9288933,
+ "106:50": 268435456,
+ "107:50": 402653184,
+ "108:50": 268435456,
+ "109:50": 402653184,
+ "110:50": 268435456,
+ "111:50": 402653184,
+ "112:50": 268435456,
+ "113:50": 402653184,
+ "114:50": 268435456,
+ "115:50": 402653184,
+ "116:50": 268435456,
+ "117:50": 402653184,
+ "118:50": 268435456,
+ "119:50": 402653184,
+ "120:50": 268435456,
+ "121:50": 402653184,
+ "122:50": 268435456,
+ "123:50": 402653184,
+ "124:50": 268435456,
+ "125:50": 402653184,
+ "126:50": 268435456,
+ "127:50": 402653184,
+ "0:51": 402653184,
+ "1:51": 268435456,
+ "2:51": 402653184,
+ "3:51": 268435456,
+ "4:51": 402653184,
+ "5:51": 268435456,
+ "6:51": 402653184,
+ "7:51": 268435456,
+ "8:51": 402653184,
+ "9:51": 268435456,
+ "10:51": 402653184,
+ "11:51": 268435456,
+ "12:51": 402653184,
+ "13:51": 268435456,
+ "14:51": 402653184,
+ "15:51": 268435456,
+ "16:51": 402653184,
+ "17:51": 268435456,
+ "18:51": 402653184,
+ "19:51": 268435456,
+ "20:51": 402653184,
+ "21:51": 268435456,
+ "22:51": 402653184,
+ "23:51": 268435456,
+ "24:51": 402653184,
+ "25:51": 268435456,
+ "26:51": 402653184,
+ "27:51": 268435456,
+ "28:51": 402653184,
+ "29:51": 268435456,
+ "30:51": 402653184,
+ "31:51": 268435456,
+ "32:51": 402653184,
+ "33:51": 268435456,
+ "34:51": 402653184,
+ "35:51": 268435456,
+ "36:51": 402653184,
+ "37:51": 268435456,
+ "38:51": 402653184,
+ "39:51": 268435456,
+ "40:51": 402653184,
+ "41:51": 268435456,
+ "42:51": 402653184,
+ "43:51": 268435456,
+ "44:51": 402653184,
+ "45:51": 268435456,
+ "46:51": 402653184,
+ "47:51": 268435456,
+ "48:51": 402653184,
+ "49:51": 268435456,
+ "50:51": -884827,
+ "51:51": -884827,
+ "52:51": -884827,
+ "53:51": -884827,
+ "54:51": -884827,
+ "55:51": -884827,
+ "56:51": -884827,
+ "57:51": 268435456,
+ "58:51": 402653184,
+ "59:51": 268435456,
+ "60:51": 402653184,
+ "61:51": 268435456,
+ "62:51": 402653184,
+ "63:51": 268435456,
+ "64:51": 402653184,
+ "65:51": 268435456,
+ "66:51": -9288933,
+ "67:51": -9288933,
+ "68:51": -9288933,
+ "69:51": -9288933,
+ "70:51": -9288933,
+ "71:51": -9288933,
+ "72:51": -9288933,
+ "73:51": -9288933,
+ "74:51": -9288933,
+ "75:51": -9288933,
+ "76:51": -9288933,
+ "77:51": -9288933,
+ "78:51": -9288933,
+ "79:51": -9288933,
+ "80:51": -9288933,
+ "81:51": -9288933,
+ "82:51": -9288933,
+ "83:51": -9288933,
+ "84:51": 402653184,
+ "85:51": 268435456,
+ "86:51": 402653184,
+ "87:51": 268435456,
+ "88:51": -9288933,
+ "89:51": -9288933,
+ "90:51": -9288933,
+ "91:51": -9288933,
+ "92:51": -9288933,
+ "93:51": -9288933,
+ "94:51": -9288933,
+ "95:51": -9288933,
+ "96:51": -9288933,
+ "97:51": -9288933,
+ "98:51": -9288933,
+ "99:51": -9288933,
+ "100:51": -9288933,
+ "101:51": -9288933,
+ "102:51": -9288933,
+ "103:51": -9288933,
+ "104:51": -9288933,
+ "105:51": -9288933,
+ "106:51": 402653184,
+ "107:51": 268435456,
+ "108:51": 402653184,
+ "109:51": 268435456,
+ "110:51": 402653184,
+ "111:51": 268435456,
+ "112:51": 402653184,
+ "113:51": 268435456,
+ "114:51": 402653184,
+ "115:51": 268435456,
+ "116:51": 402653184,
+ "117:51": 268435456,
+ "118:51": 402653184,
+ "119:51": 268435456,
+ "120:51": 402653184,
+ "121:51": 268435456,
+ "122:51": 402653184,
+ "123:51": 268435456,
+ "124:51": 402653184,
+ "125:51": 268435456,
+ "126:51": 402653184,
+ "127:51": 268435456,
+ "0:52": 268435456,
+ "1:52": 402653184,
+ "2:52": 268435456,
+ "3:52": 402653184,
+ "4:52": 268435456,
+ "5:52": 402653184,
+ "6:52": 268435456,
+ "7:52": 402653184,
+ "8:52": 268435456,
+ "9:52": 402653184,
+ "10:52": 268435456,
+ "11:52": 402653184,
+ "12:52": 268435456,
+ "13:52": 402653184,
+ "14:52": 268435456,
+ "15:52": 402653184,
+ "16:52": 268435456,
+ "17:52": 402653184,
+ "18:52": 268435456,
+ "19:52": 402653184,
+ "20:52": 268435456,
+ "21:52": 402653184,
+ "22:52": 268435456,
+ "23:52": 402653184,
+ "24:52": 268435456,
+ "25:52": 402653184,
+ "26:52": 268435456,
+ "27:52": 402653184,
+ "28:52": 268435456,
+ "29:52": 402653184,
+ "30:52": 268435456,
+ "31:52": 402653184,
+ "32:52": 268435456,
+ "33:52": 402653184,
+ "34:52": 268435456,
+ "35:52": 402653184,
+ "36:52": 268435456,
+ "37:52": 402653184,
+ "38:52": 268435456,
+ "39:52": 402653184,
+ "40:52": 268435456,
+ "41:52": 402653184,
+ "42:52": 268435456,
+ "43:52": 402653184,
+ "44:52": 268435456,
+ "45:52": 402653184,
+ "46:52": 268435456,
+ "47:52": 402653184,
+ "48:52": 268435456,
+ "49:52": 402653184,
+ "50:52": -884827,
+ "51:52": -884827,
+ "52:52": -884827,
+ "53:52": -884827,
+ "54:52": -884827,
+ "55:52": -884827,
+ "56:52": -884827,
+ "57:52": 402653184,
+ "58:52": 268435456,
+ "59:52": 402653184,
+ "60:52": 268435456,
+ "61:52": 402653184,
+ "62:52": 268435456,
+ "63:52": 402653184,
+ "64:52": 268435456,
+ "65:52": 402653184,
+ "66:52": -9288933,
+ "67:52": -9288933,
+ "68:52": -9288933,
+ "69:52": -9288933,
+ "70:52": -9288933,
+ "71:52": -9288933,
+ "72:52": -9288933,
+ "73:52": -9288933,
+ "74:52": -9288933,
+ "75:52": -9288933,
+ "76:52": -9288933,
+ "77:52": -9288933,
+ "78:52": -9288933,
+ "79:52": -9288933,
+ "80:52": -9288933,
+ "81:52": -9288933,
+ "82:52": -9288933,
+ "83:52": -9288933,
+ "84:52": 268435456,
+ "85:52": 402653184,
+ "86:52": 268435456,
+ "87:52": 402653184,
+ "88:52": -9288933,
+ "89:52": -9288933,
+ "90:52": -9288933,
+ "91:52": -9288933,
+ "92:52": -9288933,
+ "93:52": -9288933,
+ "94:52": -9288933,
+ "95:52": -9288933,
+ "96:52": -9288933,
+ "97:52": -9288933,
+ "98:52": -9288933,
+ "99:52": -9288933,
+ "100:52": -9288933,
+ "101:52": -9288933,
+ "102:52": -9288933,
+ "103:52": -9288933,
+ "104:52": -9288933,
+ "105:52": -9288933,
+ "106:52": 268435456,
+ "107:52": 402653184,
+ "108:52": 268435456,
+ "109:52": 402653184,
+ "110:52": 268435456,
+ "111:52": 402653184,
+ "112:52": 268435456,
+ "113:52": 402653184,
+ "114:52": 268435456,
+ "115:52": 402653184,
+ "116:52": 268435456,
+ "117:52": 402653184,
+ "118:52": 268435456,
+ "119:52": 402653184,
+ "120:52": 268435456,
+ "121:52": 402653184,
+ "122:52": 268435456,
+ "123:52": 402653184,
+ "124:52": 268435456,
+ "125:52": 402653184,
+ "126:52": 268435456,
+ "127:52": 402653184,
+ "0:53": 402653184,
+ "1:53": 268435456,
+ "2:53": 402653184,
+ "3:53": 268435456,
+ "4:53": 402653184,
+ "5:53": 268435456,
+ "6:53": 402653184,
+ "7:53": 268435456,
+ "8:53": 402653184,
+ "9:53": 268435456,
+ "10:53": 402653184,
+ "11:53": 268435456,
+ "12:53": 402653184,
+ "13:53": 268435456,
+ "14:53": 402653184,
+ "15:53": 268435456,
+ "16:53": 402653184,
+ "17:53": 268435456,
+ "18:53": 402653184,
+ "19:53": 268435456,
+ "20:53": 402653184,
+ "21:53": 268435456,
+ "22:53": 402653184,
+ "23:53": 268435456,
+ "24:53": 402653184,
+ "25:53": 268435456,
+ "26:53": 402653184,
+ "27:53": 268435456,
+ "28:53": 402653184,
+ "29:53": 268435456,
+ "30:53": 402653184,
+ "31:53": 268435456,
+ "32:53": 402653184,
+ "33:53": 268435456,
+ "34:53": 402653184,
+ "35:53": 268435456,
+ "36:53": 402653184,
+ "37:53": 268435456,
+ "38:53": 402653184,
+ "39:53": 268435456,
+ "40:53": 402653184,
+ "41:53": 268435456,
+ "42:53": 402653184,
+ "43:53": 268435456,
+ "44:53": 402653184,
+ "45:53": 268435456,
+ "46:53": 402653184,
+ "47:53": 268435456,
+ "48:53": 402653184,
+ "49:53": 268435456,
+ "50:53": -884827,
+ "51:53": -884827,
+ "52:53": -884827,
+ "53:53": -884827,
+ "54:53": -884827,
+ "55:53": -884827,
+ "56:53": -884827,
+ "57:53": 268435456,
+ "58:53": 402653184,
+ "59:53": 268435456,
+ "60:53": 402653184,
+ "61:53": 268435456,
+ "62:53": 402653184,
+ "63:53": 268435456,
+ "64:53": 402653184,
+ "65:53": 268435456,
+ "66:53": -9288933,
+ "67:53": -9288933,
+ "68:53": -9288933,
+ "69:53": -9288933,
+ "70:53": -9288933,
+ "71:53": -9288933,
+ "72:53": -9288933,
+ "73:53": -9288933,
+ "74:53": -9288933,
+ "75:53": -9288933,
+ "76:53": -9288933,
+ "77:53": -9288933,
+ "78:53": -9288933,
+ "79:53": -9288933,
+ "80:53": -9288933,
+ "81:53": -9288933,
+ "82:53": -9288933,
+ "83:53": -9288933,
+ "84:53": 402653184,
+ "85:53": 268435456,
+ "86:53": 402653184,
+ "87:53": 268435456,
+ "88:53": -9288933,
+ "89:53": -9288933,
+ "90:53": -9288933,
+ "91:53": -9288933,
+ "92:53": -9288933,
+ "93:53": -9288933,
+ "94:53": -9288933,
+ "95:53": -9288933,
+ "96:53": -9288933,
+ "97:53": -9288933,
+ "98:53": -9288933,
+ "99:53": -9288933,
+ "100:53": -9288933,
+ "101:53": -9288933,
+ "102:53": -9288933,
+ "103:53": -9288933,
+ "104:53": -9288933,
+ "105:53": -9288933,
+ "106:53": 402653184,
+ "107:53": 268435456,
+ "108:53": 402653184,
+ "109:53": 268435456,
+ "110:53": 402653184,
+ "111:53": 268435456,
+ "112:53": 402653184,
+ "113:53": 268435456,
+ "114:53": 402653184,
+ "115:53": 268435456,
+ "116:53": 402653184,
+ "117:53": 268435456,
+ "118:53": 402653184,
+ "119:53": 268435456,
+ "120:53": 402653184,
+ "121:53": 268435456,
+ "122:53": 402653184,
+ "123:53": 268435456,
+ "124:53": 402653184,
+ "125:53": 268435456,
+ "126:53": 402653184,
+ "127:53": 268435456,
+ "0:54": 268435456,
+ "1:54": 402653184,
+ "2:54": 268435456,
+ "3:54": 402653184,
+ "4:54": 268435456,
+ "5:54": 402653184,
+ "6:54": 268435456,
+ "7:54": 402653184,
+ "8:54": 268435456,
+ "9:54": 402653184,
+ "10:54": 268435456,
+ "11:54": 402653184,
+ "12:54": 268435456,
+ "13:54": 402653184,
+ "14:54": 268435456,
+ "15:54": 402653184,
+ "16:54": 268435456,
+ "17:54": 402653184,
+ "18:54": 268435456,
+ "19:54": 402653184,
+ "20:54": 268435456,
+ "21:54": 402653184,
+ "22:54": 268435456,
+ "23:54": 402653184,
+ "24:54": 268435456,
+ "25:54": 402653184,
+ "26:54": 268435456,
+ "27:54": 402653184,
+ "28:54": 268435456,
+ "29:54": 402653184,
+ "30:54": 268435456,
+ "31:54": 402653184,
+ "32:54": 268435456,
+ "33:54": 402653184,
+ "34:54": 268435456,
+ "35:54": 402653184,
+ "36:54": 268435456,
+ "37:54": 402653184,
+ "38:54": 268435456,
+ "39:54": 402653184,
+ "40:54": 268435456,
+ "41:54": 402653184,
+ "42:54": 268435456,
+ "43:54": 402653184,
+ "44:54": 268435456,
+ "45:54": 402653184,
+ "46:54": 268435456,
+ "47:54": 402653184,
+ "48:54": 268435456,
+ "49:54": 402653184,
+ "50:54": -884827,
+ "51:54": -884827,
+ "52:54": -884827,
+ "53:54": -884827,
+ "54:54": -884827,
+ "55:54": -884827,
+ "56:54": -884827,
+ "57:54": 402653184,
+ "58:54": 268435456,
+ "59:54": 402653184,
+ "60:54": 268435456,
+ "61:54": 402653184,
+ "62:54": 268435456,
+ "63:54": 402653184,
+ "64:54": 268435456,
+ "65:54": 402653184,
+ "66:54": -9288933,
+ "67:54": -9288933,
+ "68:54": -9288933,
+ "69:54": -9288933,
+ "70:54": -9288933,
+ "71:54": -9288933,
+ "72:54": -9288933,
+ "73:54": -9288933,
+ "74:54": -9288933,
+ "75:54": -9288933,
+ "76:54": -9288933,
+ "77:54": -9288933,
+ "78:54": -9288933,
+ "79:54": -9288933,
+ "80:54": -9288933,
+ "81:54": -9288933,
+ "82:54": -9288933,
+ "83:54": -9288933,
+ "84:54": 268435456,
+ "85:54": 402653184,
+ "86:54": 268435456,
+ "87:54": 402653184,
+ "88:54": -9288933,
+ "89:54": -9288933,
+ "90:54": -9288933,
+ "91:54": -9288933,
+ "92:54": -9288933,
+ "93:54": -9288933,
+ "94:54": -9288933,
+ "95:54": -9288933,
+ "96:54": -9288933,
+ "97:54": -9288933,
+ "98:54": -9288933,
+ "99:54": -9288933,
+ "100:54": -9288933,
+ "101:54": -9288933,
+ "102:54": -9288933,
+ "103:54": -9288933,
+ "104:54": -9288933,
+ "105:54": -9288933,
+ "106:54": 268435456,
+ "107:54": 402653184,
+ "108:54": 268435456,
+ "109:54": 402653184,
+ "110:54": 268435456,
+ "111:54": 402653184,
+ "112:54": 268435456,
+ "113:54": 402653184,
+ "114:54": 268435456,
+ "115:54": 402653184,
+ "116:54": 268435456,
+ "117:54": 402653184,
+ "118:54": 268435456,
+ "119:54": 402653184,
+ "120:54": 268435456,
+ "121:54": 402653184,
+ "122:54": 268435456,
+ "123:54": 402653184,
+ "124:54": 268435456,
+ "125:54": 402653184,
+ "126:54": 268435456,
+ "127:54": 402653184,
+ "0:55": 402653184,
+ "1:55": 268435456,
+ "2:55": 402653184,
+ "3:55": 268435456,
+ "4:55": 402653184,
+ "5:55": 268435456,
+ "6:55": 402653184,
+ "7:55": 268435456,
+ "8:55": 402653184,
+ "9:55": 268435456,
+ "10:55": 402653184,
+ "11:55": 268435456,
+ "12:55": 402653184,
+ "13:55": 268435456,
+ "14:55": 402653184,
+ "15:55": 268435456,
+ "16:55": 402653184,
+ "17:55": 268435456,
+ "18:55": 402653184,
+ "19:55": 268435456,
+ "20:55": 402653184,
+ "21:55": 268435456,
+ "22:55": -5092136,
+ "23:55": -5092136,
+ "24:55": -5092136,
+ "25:55": -5092136,
+ "26:55": -5092136,
+ "27:55": -5092136,
+ "28:55": -5092136,
+ "29:55": -5092136,
+ "30:55": -5092136,
+ "31:55": -5092136,
+ "32:55": -5092136,
+ "33:55": -5092136,
+ "34:55": -5092136,
+ "35:55": -5092136,
+ "36:55": -5092136,
+ "37:55": -5092136,
+ "38:55": -5092136,
+ "39:55": -5092136,
+ "40:55": 402653184,
+ "41:55": 268435456,
+ "42:55": 402653184,
+ "43:55": 268435456,
+ "44:55": -884827,
+ "45:55": -884827,
+ "46:55": -884827,
+ "47:55": -884827,
+ "48:55": -884827,
+ "49:55": -884827,
+ "50:55": -884827,
+ "51:55": -884827,
+ "52:55": -884827,
+ "53:55": -884827,
+ "54:55": -884827,
+ "55:55": -884827,
+ "56:55": -884827,
+ "57:55": -884827,
+ "58:55": -884827,
+ "59:55": -884827,
+ "60:55": -884827,
+ "61:55": -884827,
+ "62:55": 402653184,
+ "63:55": 268435456,
+ "64:55": 402653184,
+ "65:55": 268435456,
+ "66:55": -9288933,
+ "67:55": -9288933,
+ "68:55": -9288933,
+ "69:55": -9288933,
+ "70:55": -9288933,
+ "71:55": -9288933,
+ "72:55": -9288933,
+ "73:55": -9288933,
+ "74:55": -9288933,
+ "75:55": -9288933,
+ "76:55": -9288933,
+ "77:55": -9288933,
+ "78:55": -9288933,
+ "79:55": -9288933,
+ "80:55": -9288933,
+ "81:55": -9288933,
+ "82:55": -9288933,
+ "83:55": -9288933,
+ "84:55": 402653184,
+ "85:55": 268435456,
+ "86:55": 402653184,
+ "87:55": 268435456,
+ "88:55": -9288933,
+ "89:55": -9288933,
+ "90:55": -9288933,
+ "91:55": -9288933,
+ "92:55": -9288933,
+ "93:55": -9288933,
+ "94:55": -9288933,
+ "95:55": -9288933,
+ "96:55": -9288933,
+ "97:55": -9288933,
+ "98:55": -9288933,
+ "99:55": -9288933,
+ "100:55": -9288933,
+ "101:55": -9288933,
+ "102:55": -9288933,
+ "103:55": -9288933,
+ "104:55": -9288933,
+ "105:55": -9288933,
+ "106:55": 402653184,
+ "107:55": 268435456,
+ "108:55": 402653184,
+ "109:55": 268435456,
+ "110:55": 402653184,
+ "111:55": 268435456,
+ "112:55": 402653184,
+ "113:55": 268435456,
+ "114:55": 402653184,
+ "115:55": 268435456,
+ "116:55": 402653184,
+ "117:55": 268435456,
+ "118:55": 402653184,
+ "119:55": 268435456,
+ "120:55": 402653184,
+ "121:55": 268435456,
+ "122:55": 402653184,
+ "123:55": 268435456,
+ "124:55": 402653184,
+ "125:55": 268435456,
+ "126:55": 402653184,
+ "127:55": 268435456,
+ "0:56": 268435456,
+ "1:56": 402653184,
+ "2:56": 268435456,
+ "3:56": 402653184,
+ "4:56": 268435456,
+ "5:56": 402653184,
+ "6:56": 268435456,
+ "7:56": 402653184,
+ "8:56": 268435456,
+ "9:56": 402653184,
+ "10:56": 268435456,
+ "11:56": 402653184,
+ "12:56": 268435456,
+ "13:56": 402653184,
+ "14:56": 268435456,
+ "15:56": 402653184,
+ "16:56": 268435456,
+ "17:56": 402653184,
+ "18:56": 268435456,
+ "19:56": 402653184,
+ "20:56": 268435456,
+ "21:56": 402653184,
+ "22:56": -5092136,
+ "23:56": -5092136,
+ "24:56": -5092136,
+ "25:56": -5092136,
+ "26:56": -5092136,
+ "27:56": -5092136,
+ "28:56": -5092136,
+ "29:56": -5092136,
+ "30:56": -5092136,
+ "31:56": -5092136,
+ "32:56": -5092136,
+ "33:56": -5092136,
+ "34:56": -5092136,
+ "35:56": -5092136,
+ "36:56": -5092136,
+ "37:56": -5092136,
+ "38:56": -5092136,
+ "39:56": -5092136,
+ "40:56": 268435456,
+ "41:56": 402653184,
+ "42:56": 268435456,
+ "43:56": 402653184,
+ "44:56": -884827,
+ "45:56": -884827,
+ "46:56": -884827,
+ "47:56": -884827,
+ "48:56": -884827,
+ "49:56": -884827,
+ "50:56": -884827,
+ "51:56": -884827,
+ "52:56": -884827,
+ "53:56": -884827,
+ "54:56": -884827,
+ "55:56": -884827,
+ "56:56": -884827,
+ "57:56": -884827,
+ "58:56": -884827,
+ "59:56": -884827,
+ "60:56": -884827,
+ "61:56": -884827,
+ "62:56": 268435456,
+ "63:56": 402653184,
+ "64:56": 268435456,
+ "65:56": 402653184,
+ "66:56": -9288933,
+ "67:56": -9288933,
+ "68:56": -9288933,
+ "69:56": -9288933,
+ "70:56": -9288933,
+ "71:56": -9288933,
+ "72:56": -9288933,
+ "73:56": -9288933,
+ "74:56": -9288933,
+ "75:56": -9288933,
+ "76:56": -9288933,
+ "77:56": -9288933,
+ "78:56": -9288933,
+ "79:56": -9288933,
+ "80:56": -9288933,
+ "81:56": -9288933,
+ "82:56": -9288933,
+ "83:56": -9288933,
+ "84:56": 268435456,
+ "85:56": 402653184,
+ "86:56": 268435456,
+ "87:56": 402653184,
+ "88:56": -9288933,
+ "89:56": -9288933,
+ "90:56": -9288933,
+ "91:56": -9288933,
+ "92:56": -9288933,
+ "93:56": -9288933,
+ "94:56": -9288933,
+ "95:56": -9288933,
+ "96:56": -9288933,
+ "97:56": -9288933,
+ "98:56": -9288933,
+ "99:56": -9288933,
+ "100:56": -9288933,
+ "101:56": -9288933,
+ "102:56": -9288933,
+ "103:56": -9288933,
+ "104:56": -9288933,
+ "105:56": -9288933,
+ "106:56": 268435456,
+ "107:56": 402653184,
+ "108:56": 268435456,
+ "109:56": 402653184,
+ "110:56": 268435456,
+ "111:56": 402653184,
+ "112:56": 268435456,
+ "113:56": 402653184,
+ "114:56": 268435456,
+ "115:56": 402653184,
+ "116:56": 268435456,
+ "117:56": 402653184,
+ "118:56": 268435456,
+ "119:56": 402653184,
+ "120:56": 268435456,
+ "121:56": 402653184,
+ "122:56": 268435456,
+ "123:56": 402653184,
+ "124:56": 268435456,
+ "125:56": 402653184,
+ "126:56": 268435456,
+ "127:56": 402653184,
+ "0:57": 402653184,
+ "1:57": 268435456,
+ "2:57": 402653184,
+ "3:57": 268435456,
+ "4:57": 402653184,
+ "5:57": 268435456,
+ "6:57": 402653184,
+ "7:57": 268435456,
+ "8:57": 402653184,
+ "9:57": 268435456,
+ "10:57": 402653184,
+ "11:57": 268435456,
+ "12:57": 402653184,
+ "13:57": 268435456,
+ "14:57": 402653184,
+ "15:57": 268435456,
+ "16:57": 402653184,
+ "17:57": 268435456,
+ "18:57": 402653184,
+ "19:57": 268435456,
+ "20:57": 402653184,
+ "21:57": 268435456,
+ "22:57": -5092136,
+ "23:57": -5092136,
+ "24:57": -5092136,
+ "25:57": -5092136,
+ "26:57": -5092136,
+ "27:57": -5092136,
+ "28:57": -5092136,
+ "29:57": -5092136,
+ "30:57": -5092136,
+ "31:57": -5092136,
+ "32:57": -5092136,
+ "33:57": -5092136,
+ "34:57": -5092136,
+ "35:57": -5092136,
+ "36:57": -5092136,
+ "37:57": -5092136,
+ "38:57": -5092136,
+ "39:57": -5092136,
+ "40:57": 402653184,
+ "41:57": 268435456,
+ "42:57": 402653184,
+ "43:57": 268435456,
+ "44:57": -884827,
+ "45:57": -884827,
+ "46:57": -884827,
+ "47:57": -884827,
+ "48:57": -884827,
+ "49:57": -884827,
+ "50:57": -884827,
+ "51:57": -884827,
+ "52:57": -884827,
+ "53:57": -884827,
+ "54:57": -884827,
+ "55:57": -884827,
+ "56:57": -884827,
+ "57:57": -884827,
+ "58:57": -884827,
+ "59:57": -884827,
+ "60:57": -884827,
+ "61:57": -884827,
+ "62:57": 402653184,
+ "63:57": 268435456,
+ "64:57": 402653184,
+ "65:57": 268435456,
+ "66:57": -9288933,
+ "67:57": -9288933,
+ "68:57": -9288933,
+ "69:57": -9288933,
+ "70:57": -9288933,
+ "71:57": -9288933,
+ "72:57": -9288933,
+ "73:57": -9288933,
+ "74:57": -9288933,
+ "75:57": -9288933,
+ "76:57": -9288933,
+ "77:57": -9288933,
+ "78:57": -9288933,
+ "79:57": -9288933,
+ "80:57": -9288933,
+ "81:57": -9288933,
+ "82:57": -9288933,
+ "83:57": -9288933,
+ "84:57": 402653184,
+ "85:57": 268435456,
+ "86:57": 402653184,
+ "87:57": 268435456,
+ "88:57": -9288933,
+ "89:57": -9288933,
+ "90:57": -9288933,
+ "91:57": -9288933,
+ "92:57": -9288933,
+ "93:57": -9288933,
+ "94:57": -9288933,
+ "95:57": -9288933,
+ "96:57": -9288933,
+ "97:57": -9288933,
+ "98:57": -9288933,
+ "99:57": -9288933,
+ "100:57": -9288933,
+ "101:57": -9288933,
+ "102:57": -9288933,
+ "103:57": -9288933,
+ "104:57": -9288933,
+ "105:57": -9288933,
+ "106:57": 402653184,
+ "107:57": 268435456,
+ "108:57": 402653184,
+ "109:57": 268435456,
+ "110:57": 402653184,
+ "111:57": 268435456,
+ "112:57": 402653184,
+ "113:57": 268435456,
+ "114:57": 402653184,
+ "115:57": 268435456,
+ "116:57": 402653184,
+ "117:57": 268435456,
+ "118:57": 402653184,
+ "119:57": 268435456,
+ "120:57": 402653184,
+ "121:57": 268435456,
+ "122:57": 402653184,
+ "123:57": 268435456,
+ "124:57": 402653184,
+ "125:57": 268435456,
+ "126:57": 402653184,
+ "127:57": 268435456,
+ "0:58": 268435456,
+ "1:58": 402653184,
+ "2:58": 268435456,
+ "3:58": 402653184,
+ "4:58": 268435456,
+ "5:58": 402653184,
+ "6:58": 268435456,
+ "7:58": 402653184,
+ "8:58": 268435456,
+ "9:58": 402653184,
+ "10:58": 268435456,
+ "11:58": 402653184,
+ "12:58": 268435456,
+ "13:58": 402653184,
+ "14:58": 268435456,
+ "15:58": 402653184,
+ "16:58": 268435456,
+ "17:58": 402653184,
+ "18:58": 268435456,
+ "19:58": 402653184,
+ "20:58": 268435456,
+ "21:58": 402653184,
+ "22:58": -5092136,
+ "23:58": -5092136,
+ "24:58": -5092136,
+ "25:58": -5092136,
+ "26:58": -5092136,
+ "27:58": -5092136,
+ "28:58": -5092136,
+ "29:58": -5092136,
+ "30:58": -5092136,
+ "31:58": -5092136,
+ "32:58": -5092136,
+ "33:58": -5092136,
+ "34:58": -5092136,
+ "35:58": -5092136,
+ "36:58": -5092136,
+ "37:58": -5092136,
+ "38:58": -5092136,
+ "39:58": -5092136,
+ "40:58": 268435456,
+ "41:58": 402653184,
+ "42:58": 268435456,
+ "43:58": 402653184,
+ "44:58": -884827,
+ "45:58": -884827,
+ "46:58": -884827,
+ "47:58": -884827,
+ "48:58": -884827,
+ "49:58": -884827,
+ "50:58": -884827,
+ "51:58": -884827,
+ "52:58": -884827,
+ "53:58": -884827,
+ "54:58": -884827,
+ "55:58": -884827,
+ "56:58": -884827,
+ "57:58": -884827,
+ "58:58": -884827,
+ "59:58": -884827,
+ "60:58": -884827,
+ "61:58": -884827,
+ "62:58": 268435456,
+ "63:58": 402653184,
+ "64:58": 268435456,
+ "65:58": 402653184,
+ "66:58": -9288933,
+ "67:58": -9288933,
+ "68:58": -9288933,
+ "69:58": -9288933,
+ "70:58": -9288933,
+ "71:58": -9288933,
+ "72:58": -9288933,
+ "73:58": -9288933,
+ "74:58": -9288933,
+ "75:58": -9288933,
+ "76:58": -9288933,
+ "77:58": -9288933,
+ "78:58": -9288933,
+ "79:58": -9288933,
+ "80:58": -9288933,
+ "81:58": -9288933,
+ "82:58": -9288933,
+ "83:58": -9288933,
+ "84:58": 268435456,
+ "85:58": 402653184,
+ "86:58": 268435456,
+ "87:58": 402653184,
+ "88:58": -9288933,
+ "89:58": -9288933,
+ "90:58": -9288933,
+ "91:58": -9288933,
+ "92:58": -9288933,
+ "93:58": -9288933,
+ "94:58": -9288933,
+ "95:58": -9288933,
+ "96:58": -9288933,
+ "97:58": -9288933,
+ "98:58": -9288933,
+ "99:58": -9288933,
+ "100:58": -9288933,
+ "101:58": -9288933,
+ "102:58": -9288933,
+ "103:58": -9288933,
+ "104:58": -9288933,
+ "105:58": -9288933,
+ "106:58": 268435456,
+ "107:58": 402653184,
+ "108:58": 268435456,
+ "109:58": 402653184,
+ "110:58": 268435456,
+ "111:58": 402653184,
+ "112:58": 268435456,
+ "113:58": 402653184,
+ "114:58": 268435456,
+ "115:58": 402653184,
+ "116:58": 268435456,
+ "117:58": 402653184,
+ "118:58": 268435456,
+ "119:58": 402653184,
+ "120:58": 268435456,
+ "121:58": 402653184,
+ "122:58": 268435456,
+ "123:58": 402653184,
+ "124:58": 268435456,
+ "125:58": 402653184,
+ "126:58": 268435456,
+ "127:58": 402653184,
+ "0:59": 402653184,
+ "1:59": 268435456,
+ "2:59": 402653184,
+ "3:59": 268435456,
+ "4:59": 402653184,
+ "5:59": 268435456,
+ "6:59": 402653184,
+ "7:59": 268435456,
+ "8:59": 402653184,
+ "9:59": 268435456,
+ "10:59": 402653184,
+ "11:59": 268435456,
+ "12:59": 402653184,
+ "13:59": 268435456,
+ "14:59": 402653184,
+ "15:59": 268435456,
+ "16:59": 402653184,
+ "17:59": 268435456,
+ "18:59": 402653184,
+ "19:59": 268435456,
+ "20:59": 402653184,
+ "21:59": 268435456,
+ "22:59": -5092136,
+ "23:59": -5092136,
+ "24:59": -5092136,
+ "25:59": -5092136,
+ "26:59": -5092136,
+ "27:59": -5092136,
+ "28:59": -5092136,
+ "29:59": -5092136,
+ "30:59": -5092136,
+ "31:59": -5092136,
+ "32:59": -5092136,
+ "33:59": -5092136,
+ "34:59": -5092136,
+ "35:59": -5092136,
+ "36:59": -5092136,
+ "37:59": -5092136,
+ "38:59": -5092136,
+ "39:59": -5092136,
+ "40:59": 402653184,
+ "41:59": 268435456,
+ "42:59": 402653184,
+ "43:59": 268435456,
+ "44:59": -884827,
+ "45:59": -884827,
+ "46:59": -884827,
+ "47:59": -884827,
+ "48:59": -884827,
+ "49:59": -884827,
+ "50:59": -884827,
+ "51:59": -884827,
+ "52:59": -884827,
+ "53:59": -884827,
+ "54:59": -884827,
+ "55:59": -884827,
+ "56:59": -884827,
+ "57:59": -884827,
+ "58:59": -884827,
+ "59:59": -884827,
+ "60:59": -884827,
+ "61:59": -884827,
+ "62:59": 402653184,
+ "63:59": 268435456,
+ "64:59": 402653184,
+ "65:59": 268435456,
+ "66:59": -9288933,
+ "67:59": -9288933,
+ "68:59": -9288933,
+ "69:59": -9288933,
+ "70:59": -9288933,
+ "71:59": -9288933,
+ "72:59": -9288933,
+ "73:59": -9288933,
+ "74:59": -9288933,
+ "75:59": -9288933,
+ "76:59": -9288933,
+ "77:59": -9288933,
+ "78:59": -9288933,
+ "79:59": -9288933,
+ "80:59": -9288933,
+ "81:59": -9288933,
+ "82:59": -9288933,
+ "83:59": -9288933,
+ "84:59": 402653184,
+ "85:59": 268435456,
+ "86:59": 402653184,
+ "87:59": 268435456,
+ "88:59": -9288933,
+ "89:59": -9288933,
+ "90:59": -9288933,
+ "91:59": -9288933,
+ "92:59": -9288933,
+ "93:59": -9288933,
+ "94:59": -9288933,
+ "95:59": -9288933,
+ "96:59": -9288933,
+ "97:59": -9288933,
+ "98:59": -9288933,
+ "99:59": -9288933,
+ "100:59": -9288933,
+ "101:59": -9288933,
+ "102:59": -9288933,
+ "103:59": -9288933,
+ "104:59": -9288933,
+ "105:59": -9288933,
+ "106:59": 402653184,
+ "107:59": 268435456,
+ "108:59": 402653184,
+ "109:59": 268435456,
+ "110:59": 402653184,
+ "111:59": 268435456,
+ "112:59": 402653184,
+ "113:59": 268435456,
+ "114:59": 402653184,
+ "115:59": 268435456,
+ "116:59": 402653184,
+ "117:59": 268435456,
+ "118:59": 402653184,
+ "119:59": 268435456,
+ "120:59": 402653184,
+ "121:59": 268435456,
+ "122:59": 402653184,
+ "123:59": 268435456,
+ "124:59": 402653184,
+ "125:59": 268435456,
+ "126:59": 402653184,
+ "127:59": 268435456,
+ "0:60": 268435456,
+ "1:60": 402653184,
+ "2:60": 268435456,
+ "3:60": 402653184,
+ "4:60": 268435456,
+ "5:60": 402653184,
+ "6:60": 268435456,
+ "7:60": 402653184,
+ "8:60": 268435456,
+ "9:60": 402653184,
+ "10:60": 268435456,
+ "11:60": 402653184,
+ "12:60": 268435456,
+ "13:60": 402653184,
+ "14:60": 268435456,
+ "15:60": 402653184,
+ "16:60": 268435456,
+ "17:60": 402653184,
+ "18:60": 268435456,
+ "19:60": 402653184,
+ "20:60": 268435456,
+ "21:60": 402653184,
+ "22:60": -5092136,
+ "23:60": -5092136,
+ "24:60": -5092136,
+ "25:60": -5092136,
+ "26:60": -5092136,
+ "27:60": -5092136,
+ "28:60": -5092136,
+ "29:60": -5092136,
+ "30:60": -5092136,
+ "31:60": -5092136,
+ "32:60": -5092136,
+ "33:60": -5092136,
+ "34:60": -5092136,
+ "35:60": -5092136,
+ "36:60": -5092136,
+ "37:60": -5092136,
+ "38:60": -5092136,
+ "39:60": -5092136,
+ "40:60": 268435456,
+ "41:60": 402653184,
+ "42:60": 268435456,
+ "43:60": 402653184,
+ "44:60": -884827,
+ "45:60": -884827,
+ "46:60": -884827,
+ "47:60": -884827,
+ "48:60": -884827,
+ "49:60": -884827,
+ "50:60": -884827,
+ "51:60": -884827,
+ "52:60": -884827,
+ "53:60": -884827,
+ "54:60": -884827,
+ "55:60": -884827,
+ "56:60": -884827,
+ "57:60": -884827,
+ "58:60": -884827,
+ "59:60": -884827,
+ "60:60": -884827,
+ "61:60": -884827,
+ "62:60": 268435456,
+ "63:60": 402653184,
+ "64:60": 268435456,
+ "65:60": 402653184,
+ "66:60": -9288933,
+ "67:60": -9288933,
+ "68:60": -9288933,
+ "69:60": -9288933,
+ "70:60": -9288933,
+ "71:60": -9288933,
+ "72:60": -9288933,
+ "73:60": -9288933,
+ "74:60": -9288933,
+ "75:60": -9288933,
+ "76:60": -9288933,
+ "77:60": -9288933,
+ "78:60": -9288933,
+ "79:60": -9288933,
+ "80:60": -9288933,
+ "81:60": -9288933,
+ "82:60": -9288933,
+ "83:60": -9288933,
+ "84:60": 268435456,
+ "85:60": 402653184,
+ "86:60": 268435456,
+ "87:60": 402653184,
+ "88:60": -9288933,
+ "89:60": -9288933,
+ "90:60": -9288933,
+ "91:60": -9288933,
+ "92:60": -9288933,
+ "93:60": -9288933,
+ "94:60": -9288933,
+ "95:60": -9288933,
+ "96:60": -9288933,
+ "97:60": -9288933,
+ "98:60": -9288933,
+ "99:60": -9288933,
+ "100:60": -9288933,
+ "101:60": -9288933,
+ "102:60": -9288933,
+ "103:60": -9288933,
+ "104:60": -9288933,
+ "105:60": -9288933,
+ "106:60": 268435456,
+ "107:60": 402653184,
+ "108:60": 268435456,
+ "109:60": 402653184,
+ "110:60": 268435456,
+ "111:60": 402653184,
+ "112:60": 268435456,
+ "113:60": 402653184,
+ "114:60": 268435456,
+ "115:60": 402653184,
+ "116:60": 268435456,
+ "117:60": 402653184,
+ "118:60": 268435456,
+ "119:60": 402653184,
+ "120:60": 268435456,
+ "121:60": 402653184,
+ "122:60": 268435456,
+ "123:60": 402653184,
+ "124:60": 268435456,
+ "125:60": 402653184,
+ "126:60": 268435456,
+ "127:60": 402653184,
+ "0:61": 402653184,
+ "1:61": 268435456,
+ "2:61": 402653184,
+ "3:61": 268435456,
+ "4:61": 402653184,
+ "5:61": 268435456,
+ "6:61": 402653184,
+ "7:61": 268435456,
+ "8:61": 402653184,
+ "9:61": 268435456,
+ "10:61": 402653184,
+ "11:61": 268435456,
+ "12:61": 402653184,
+ "13:61": 268435456,
+ "14:61": 402653184,
+ "15:61": 268435456,
+ "16:61": 402653184,
+ "17:61": 268435456,
+ "18:61": 402653184,
+ "19:61": 268435456,
+ "20:61": 402653184,
+ "21:61": 268435456,
+ "22:61": -5092136,
+ "23:61": -5092136,
+ "24:61": -5092136,
+ "25:61": -5092136,
+ "26:61": -5092136,
+ "27:61": -5092136,
+ "28:61": -5092136,
+ "29:61": -5092136,
+ "30:61": -5092136,
+ "31:61": -5092136,
+ "32:61": -5092136,
+ "33:61": -5092136,
+ "34:61": -5092136,
+ "35:61": -5092136,
+ "36:61": -5092136,
+ "37:61": -5092136,
+ "38:61": -5092136,
+ "39:61": -5092136,
+ "40:61": -5092136,
+ "41:61": -5092136,
+ "42:61": -5092136,
+ "43:61": -5092136,
+ "44:61": -884827,
+ "45:61": -884827,
+ "46:61": -884827,
+ "47:61": -884827,
+ "48:61": -884827,
+ "49:61": -884827,
+ "50:61": -884827,
+ "51:61": -884827,
+ "52:61": -884827,
+ "53:61": -884827,
+ "54:61": -884827,
+ "55:61": -884827,
+ "56:61": -884827,
+ "57:61": -884827,
+ "58:61": -884827,
+ "59:61": -884827,
+ "60:61": -884827,
+ "61:61": -884827,
+ "62:61": -9288933,
+ "63:61": -9288933,
+ "64:61": -9288933,
+ "65:61": -9288933,
+ "66:61": -9288933,
+ "67:61": -9288933,
+ "68:61": -9288933,
+ "69:61": -9288933,
+ "70:61": -9288933,
+ "71:61": -9288933,
+ "72:61": -9288933,
+ "73:61": -9288933,
+ "74:61": -9288933,
+ "75:61": -9288933,
+ "76:61": -9288933,
+ "77:61": -9288933,
+ "78:61": -9288933,
+ "79:61": -9288933,
+ "80:61": -9288933,
+ "81:61": -9288933,
+ "82:61": -9288933,
+ "83:61": -9288933,
+ "84:61": -9288933,
+ "85:61": -9288933,
+ "86:61": -9288933,
+ "87:61": -9288933,
+ "88:61": -9288933,
+ "89:61": -9288933,
+ "90:61": -9288933,
+ "91:61": -9288933,
+ "92:61": -9288933,
+ "93:61": -9288933,
+ "94:61": -9288933,
+ "95:61": -9288933,
+ "96:61": -9288933,
+ "97:61": -9288933,
+ "98:61": -9288933,
+ "99:61": -9288933,
+ "100:61": -9288933,
+ "101:61": -9288933,
+ "102:61": -9288933,
+ "103:61": -9288933,
+ "104:61": -9288933,
+ "105:61": -9288933,
+ "106:61": 402653184,
+ "107:61": 268435456,
+ "108:61": 402653184,
+ "109:61": 268435456,
+ "110:61": 402653184,
+ "111:61": 268435456,
+ "112:61": 402653184,
+ "113:61": 268435456,
+ "114:61": 402653184,
+ "115:61": 268435456,
+ "116:61": 402653184,
+ "117:61": 268435456,
+ "118:61": 402653184,
+ "119:61": 268435456,
+ "120:61": 402653184,
+ "121:61": 268435456,
+ "122:61": 402653184,
+ "123:61": 268435456,
+ "124:61": 402653184,
+ "125:61": 268435456,
+ "126:61": 402653184,
+ "127:61": 268435456,
+ "0:62": 268435456,
+ "1:62": 402653184,
+ "2:62": 268435456,
+ "3:62": 402653184,
+ "4:62": 268435456,
+ "5:62": 402653184,
+ "6:62": 268435456,
+ "7:62": 402653184,
+ "8:62": 268435456,
+ "9:62": 402653184,
+ "10:62": 268435456,
+ "11:62": 402653184,
+ "12:62": 268435456,
+ "13:62": 402653184,
+ "14:62": 268435456,
+ "15:62": 402653184,
+ "16:62": 268435456,
+ "17:62": 402653184,
+ "18:62": 268435456,
+ "19:62": 402653184,
+ "20:62": 268435456,
+ "21:62": 402653184,
+ "22:62": -5092136,
+ "23:62": -5092136,
+ "24:62": -5092136,
+ "25:62": -5092136,
+ "26:62": -5092136,
+ "27:62": -5092136,
+ "28:62": -5092136,
+ "29:62": -5092136,
+ "30:62": -5092136,
+ "31:62": -5092136,
+ "32:62": -16745472,
+ "33:62": -16745472,
+ "34:62": -16745472,
+ "35:62": -5092136,
+ "36:62": -5092136,
+ "37:62": -5092136,
+ "38:62": -5092136,
+ "39:62": -5092136,
+ "40:62": -5092136,
+ "41:62": -5092136,
+ "42:62": -5092136,
+ "43:62": -5092136,
+ "44:62": -884827,
+ "45:62": -884827,
+ "46:62": -884827,
+ "47:62": -884827,
+ "48:62": -884827,
+ "49:62": -884827,
+ "50:62": -884827,
+ "51:62": -884827,
+ "52:62": -884827,
+ "53:62": -884827,
+ "54:62": -16745472,
+ "55:62": -16745472,
+ "56:62": -16745472,
+ "57:62": -884827,
+ "58:62": -884827,
+ "59:62": -884827,
+ "60:62": -884827,
+ "61:62": -884827,
+ "62:62": -9288933,
+ "63:62": -9288933,
+ "64:62": -9288933,
+ "65:62": -9288933,
+ "66:62": -9288933,
+ "67:62": -9288933,
+ "68:62": -9288933,
+ "69:62": -9288933,
+ "70:62": -9288933,
+ "71:62": -9288933,
+ "72:62": -9288933,
+ "73:62": -9288933,
+ "74:62": -9288933,
+ "75:62": -9288933,
+ "76:62": -9288933,
+ "77:62": -9288933,
+ "78:62": -9288933,
+ "79:62": -9288933,
+ "80:62": -9288933,
+ "81:62": -9288933,
+ "82:62": -9288933,
+ "83:62": -9288933,
+ "84:62": -9288933,
+ "85:62": -9288933,
+ "86:62": -9288933,
+ "87:62": -9288933,
+ "88:62": -9288933,
+ "89:62": -9288933,
+ "90:62": -9288933,
+ "91:62": -9288933,
+ "92:62": -9288933,
+ "93:62": -9288933,
+ "94:62": -9288933,
+ "95:62": -9288933,
+ "96:62": -9288933,
+ "97:62": -9288933,
+ "98:62": -9288933,
+ "99:62": -9288933,
+ "100:62": -9288933,
+ "101:62": -9288933,
+ "102:62": -9288933,
+ "103:62": -9288933,
+ "104:62": -9288933,
+ "105:62": -9288933,
+ "106:62": 268435456,
+ "107:62": 402653184,
+ "108:62": 268435456,
+ "109:62": 402653184,
+ "110:62": 268435456,
+ "111:62": 402653184,
+ "112:62": 268435456,
+ "113:62": 402653184,
+ "114:62": 268435456,
+ "115:62": 402653184,
+ "116:62": 268435456,
+ "117:62": 402653184,
+ "118:62": 268435456,
+ "119:62": 402653184,
+ "120:62": 268435456,
+ "121:62": 402653184,
+ "122:62": 268435456,
+ "123:62": 402653184,
+ "124:62": 268435456,
+ "125:62": 402653184,
+ "126:62": 268435456,
+ "127:62": 402653184,
+ "0:63": 402653184,
+ "1:63": 268435456,
+ "2:63": 402653184,
+ "3:63": 268435456,
+ "4:63": 402653184,
+ "5:63": 268435456,
+ "6:63": 402653184,
+ "7:63": 268435456,
+ "8:63": 402653184,
+ "9:63": 268435456,
+ "10:63": 402653184,
+ "11:63": 268435456,
+ "12:63": 402653184,
+ "13:63": 268435456,
+ "14:63": 402653184,
+ "15:63": 268435456,
+ "16:63": 402653184,
+ "17:63": 268435456,
+ "18:63": 402653184,
+ "19:63": 268435456,
+ "20:63": 402653184,
+ "21:63": 268435456,
+ "22:63": -5092136,
+ "23:63": -5092136,
+ "24:63": -5092136,
+ "25:63": -5092136,
+ "26:63": -5092136,
+ "27:63": -5092136,
+ "28:63": -5092136,
+ "29:63": -5092136,
+ "30:63": -5092136,
+ "31:63": -16745472,
+ "32:63": -16745472,
+ "33:63": -16745472,
+ "34:63": -5092136,
+ "35:63": -5092136,
+ "36:63": -5092136,
+ "37:63": -5092136,
+ "38:63": -5092136,
+ "39:63": -5092136,
+ "40:63": -5092136,
+ "41:63": -5092136,
+ "42:63": -5092136,
+ "43:63": -5092136,
+ "44:63": -884827,
+ "45:63": -884827,
+ "46:63": -884827,
+ "47:63": -884827,
+ "48:63": -884827,
+ "49:63": -884827,
+ "50:63": -884827,
+ "51:63": -884827,
+ "52:63": -884827,
+ "53:63": -16745472,
+ "54:63": -16745472,
+ "55:63": -16745472,
+ "56:63": -884827,
+ "57:63": -884827,
+ "58:63": -884827,
+ "59:63": -884827,
+ "60:63": -884827,
+ "61:63": -884827,
+ "62:63": -9288933,
+ "63:63": -9288933,
+ "64:63": -9288933,
+ "65:63": -9288933,
+ "66:63": -9288933,
+ "67:63": -9288933,
+ "68:63": -9288933,
+ "69:63": -9288933,
+ "70:63": -9288933,
+ "71:63": -9288933,
+ "72:63": -9288933,
+ "73:63": -9288933,
+ "74:63": -9288933,
+ "75:63": -9288933,
+ "76:63": -9288933,
+ "77:63": -9288933,
+ "78:63": -9288933,
+ "79:63": -9288933,
+ "80:63": -9288933,
+ "81:63": -9288933,
+ "82:63": -9288933,
+ "83:63": -9288933,
+ "84:63": -9288933,
+ "85:63": -9288933,
+ "86:63": -9288933,
+ "87:63": -9288933,
+ "88:63": -9288933,
+ "89:63": -9288933,
+ "90:63": -9288933,
+ "91:63": -9288933,
+ "92:63": -9288933,
+ "93:63": -9288933,
+ "94:63": -9288933,
+ "95:63": -9288933,
+ "96:63": -9288933,
+ "97:63": -9288933,
+ "98:63": -9288933,
+ "99:63": -9288933,
+ "100:63": -9288933,
+ "101:63": -9288933,
+ "102:63": -9288933,
+ "103:63": -9288933,
+ "104:63": -9288933,
+ "105:63": -9288933,
+ "106:63": 402653184,
+ "107:63": 268435456,
+ "108:63": 402653184,
+ "109:63": 268435456,
+ "110:63": 402653184,
+ "111:63": 268435456,
+ "112:63": 402653184,
+ "113:63": 268435456,
+ "114:63": 402653184,
+ "115:63": 268435456,
+ "116:63": 402653184,
+ "117:63": 268435456,
+ "118:63": 402653184,
+ "119:63": 268435456,
+ "120:63": 402653184,
+ "121:63": 268435456,
+ "122:63": 402653184,
+ "123:63": 268435456,
+ "124:63": 402653184,
+ "125:63": 268435456,
+ "126:63": 402653184,
+ "127:63": 268435456,
+ "0:64": 268435456,
+ "1:64": 402653184,
+ "2:64": 268435456,
+ "3:64": 402653184,
+ "4:64": 268435456,
+ "5:64": 402653184,
+ "6:64": 268435456,
+ "7:64": 402653184,
+ "8:64": 268435456,
+ "9:64": 402653184,
+ "10:64": 268435456,
+ "11:64": 402653184,
+ "12:64": 268435456,
+ "13:64": 402653184,
+ "14:64": 268435456,
+ "15:64": 402653184,
+ "16:64": 268435456,
+ "17:64": 402653184,
+ "18:64": 268435456,
+ "19:64": 402653184,
+ "20:64": 268435456,
+ "21:64": 402653184,
+ "22:64": -5092136,
+ "23:64": -5092136,
+ "24:64": -5092136,
+ "25:64": -5092136,
+ "26:64": -5092136,
+ "27:64": -5092136,
+ "28:64": -5092136,
+ "29:64": -5092136,
+ "30:64": -5092136,
+ "31:64": -16745472,
+ "32:64": -16745472,
+ "33:64": -5092136,
+ "34:64": -5092136,
+ "35:64": -5092136,
+ "36:64": -5092136,
+ "37:64": -5092136,
+ "38:64": -5092136,
+ "39:64": -5092136,
+ "40:64": -5092136,
+ "41:64": -5092136,
+ "42:64": -5092136,
+ "43:64": -5092136,
+ "44:64": -884827,
+ "45:64": -884827,
+ "46:64": -884827,
+ "47:64": -884827,
+ "48:64": -884827,
+ "49:64": -884827,
+ "50:64": -884827,
+ "51:64": -884827,
+ "52:64": -884827,
+ "53:64": -16745472,
+ "54:64": -16745472,
+ "55:64": -884827,
+ "56:64": -884827,
+ "57:64": -884827,
+ "58:64": -884827,
+ "59:64": -884827,
+ "60:64": -884827,
+ "61:64": -884827,
+ "62:64": -9288933,
+ "63:64": -9288933,
+ "64:64": -9288933,
+ "65:64": -9288933,
+ "66:64": -9288933,
+ "67:64": -9288933,
+ "68:64": -9288933,
+ "69:64": -9288933,
+ "70:64": -9288933,
+ "71:64": -9288933,
+ "72:64": -9288933,
+ "73:64": -9288933,
+ "74:64": -9288933,
+ "75:64": -9288933,
+ "76:64": -9288933,
+ "77:64": -9288933,
+ "78:64": -9288933,
+ "79:64": -9288933,
+ "80:64": -9288933,
+ "81:64": -9288933,
+ "82:64": -9288933,
+ "83:64": -9288933,
+ "84:64": -9288933,
+ "85:64": -9288933,
+ "86:64": -9288933,
+ "87:64": -9288933,
+ "88:64": -9288933,
+ "89:64": -9288933,
+ "90:64": -9288933,
+ "91:64": -9288933,
+ "92:64": -9288933,
+ "93:64": -9288933,
+ "94:64": -9288933,
+ "95:64": -9288933,
+ "96:64": -9288933,
+ "97:64": -9288933,
+ "98:64": -9288933,
+ "99:64": -9288933,
+ "100:64": -9288933,
+ "101:64": -9288933,
+ "102:64": -9288933,
+ "103:64": -9288933,
+ "104:64": -9288933,
+ "105:64": -9288933,
+ "106:64": 268435456,
+ "107:64": 402653184,
+ "108:64": 268435456,
+ "109:64": 402653184,
+ "110:64": 268435456,
+ "111:64": 402653184,
+ "112:64": 268435456,
+ "113:64": 402653184,
+ "114:64": 268435456,
+ "115:64": 402653184,
+ "116:64": 268435456,
+ "117:64": 402653184,
+ "118:64": 268435456,
+ "119:64": 402653184,
+ "120:64": 268435456,
+ "121:64": 402653184,
+ "122:64": 268435456,
+ "123:64": 402653184,
+ "124:64": 268435456,
+ "125:64": 402653184,
+ "126:64": 268435456,
+ "127:64": 402653184,
+ "0:65": 402653184,
+ "1:65": 268435456,
+ "2:65": 402653184,
+ "3:65": 268435456,
+ "4:65": 402653184,
+ "5:65": 268435456,
+ "6:65": 402653184,
+ "7:65": 268435456,
+ "8:65": 402653184,
+ "9:65": 268435456,
+ "10:65": 402653184,
+ "11:65": 268435456,
+ "12:65": 402653184,
+ "13:65": 268435456,
+ "14:65": 402653184,
+ "15:65": 268435456,
+ "16:65": 402653184,
+ "17:65": 268435456,
+ "18:65": 402653184,
+ "19:65": 268435456,
+ "20:65": 402653184,
+ "21:65": 268435456,
+ "22:65": -5092136,
+ "23:65": -5092136,
+ "24:65": -5092136,
+ "25:65": -5092136,
+ "26:65": -5092136,
+ "27:65": -5092136,
+ "28:65": -16745472,
+ "29:65": -16745472,
+ "30:65": -5092136,
+ "31:65": -16745472,
+ "32:65": -16745472,
+ "33:65": -5092136,
+ "34:65": -5092136,
+ "35:65": -5092136,
+ "36:65": -5092136,
+ "37:65": -5092136,
+ "38:65": -5092136,
+ "39:65": -5092136,
+ "40:65": -5092136,
+ "41:65": -5092136,
+ "42:65": -5092136,
+ "43:65": -5092136,
+ "44:65": -884827,
+ "45:65": -884827,
+ "46:65": -884827,
+ "47:65": -884827,
+ "48:65": -884827,
+ "49:65": -884827,
+ "50:65": -16745472,
+ "51:65": -16745472,
+ "52:65": -884827,
+ "53:65": -16745472,
+ "54:65": -16745472,
+ "55:65": -884827,
+ "56:65": -884827,
+ "57:65": -884827,
+ "58:65": -884827,
+ "59:65": -884827,
+ "60:65": -884827,
+ "61:65": -884827,
+ "62:65": -9288933,
+ "63:65": -9288933,
+ "64:65": -9288933,
+ "65:65": -9288933,
+ "66:65": -9288933,
+ "67:65": -9288933,
+ "68:65": -9288933,
+ "69:65": -9288933,
+ "70:65": -9288933,
+ "71:65": -9288933,
+ "72:65": -9288933,
+ "73:65": -9288933,
+ "74:65": -9288933,
+ "75:65": -9288933,
+ "76:65": -9288933,
+ "77:65": -9288933,
+ "78:65": -9288933,
+ "79:65": -9288933,
+ "80:65": -9288933,
+ "81:65": -9288933,
+ "82:65": -9288933,
+ "83:65": -9288933,
+ "84:65": -9288933,
+ "85:65": -9288933,
+ "86:65": -9288933,
+ "87:65": -9288933,
+ "88:65": -9288933,
+ "89:65": -9288933,
+ "90:65": -9288933,
+ "91:65": -9288933,
+ "92:65": -9288933,
+ "93:65": -9288933,
+ "94:65": -9288933,
+ "95:65": -9288933,
+ "96:65": -9288933,
+ "97:65": -9288933,
+ "98:65": -9288933,
+ "99:65": -9288933,
+ "100:65": -9288933,
+ "101:65": -9288933,
+ "102:65": -9288933,
+ "103:65": -9288933,
+ "104:65": -9288933,
+ "105:65": -9288933,
+ "106:65": 402653184,
+ "107:65": 268435456,
+ "108:65": 402653184,
+ "109:65": 268435456,
+ "110:65": 402653184,
+ "111:65": 268435456,
+ "112:65": 402653184,
+ "113:65": 268435456,
+ "114:65": 402653184,
+ "115:65": 268435456,
+ "116:65": 402653184,
+ "117:65": 268435456,
+ "118:65": 402653184,
+ "119:65": 268435456,
+ "120:65": 402653184,
+ "121:65": 268435456,
+ "122:65": 402653184,
+ "123:65": 268435456,
+ "124:65": 402653184,
+ "125:65": 268435456,
+ "126:65": 402653184,
+ "127:65": 268435456,
+ "0:66": 268435456,
+ "1:66": 402653184,
+ "2:66": 268435456,
+ "3:66": 402653184,
+ "4:66": 268435456,
+ "5:66": 402653184,
+ "6:66": 268435456,
+ "7:66": 402653184,
+ "8:66": 268435456,
+ "9:66": 402653184,
+ "10:66": 268435456,
+ "11:66": 402653184,
+ "12:66": 268435456,
+ "13:66": 402653184,
+ "14:66": 268435456,
+ "15:66": 402653184,
+ "16:66": 268435456,
+ "17:66": 402653184,
+ "18:66": 268435456,
+ "19:66": 402653184,
+ "20:66": 268435456,
+ "21:66": 402653184,
+ "22:66": -5092136,
+ "23:66": -5092136,
+ "24:66": -5092136,
+ "25:66": -5092136,
+ "26:66": -5092136,
+ "27:66": -5092136,
+ "28:66": -5092136,
+ "29:66": -16745472,
+ "30:66": -16745472,
+ "31:66": -16745472,
+ "32:66": -5092136,
+ "33:66": -5092136,
+ "34:66": -5092136,
+ "35:66": -5092136,
+ "36:66": -5092136,
+ "37:66": -5092136,
+ "38:66": -5092136,
+ "39:66": -5092136,
+ "40:66": -5092136,
+ "41:66": -5092136,
+ "42:66": -5092136,
+ "43:66": -5092136,
+ "44:66": -884827,
+ "45:66": -884827,
+ "46:66": -884827,
+ "47:66": -884827,
+ "48:66": -884827,
+ "49:66": -884827,
+ "50:66": -884827,
+ "51:66": -16745472,
+ "52:66": -16745472,
+ "53:66": -16745472,
+ "54:66": -884827,
+ "55:66": -884827,
+ "56:66": -884827,
+ "57:66": -884827,
+ "58:66": -884827,
+ "59:66": -884827,
+ "60:66": -884827,
+ "61:66": -884827,
+ "62:66": -9288933,
+ "63:66": -9288933,
+ "64:66": -9288933,
+ "65:66": -9288933,
+ "66:66": -9288933,
+ "67:66": -9288933,
+ "68:66": -9288933,
+ "69:66": -9288933,
+ "70:66": -9288933,
+ "71:66": -9288933,
+ "72:66": -9288933,
+ "73:66": -9288933,
+ "74:66": -9288933,
+ "75:66": -9288933,
+ "76:66": -9288933,
+ "77:66": -9288933,
+ "78:66": -9288933,
+ "79:66": -9288933,
+ "80:66": -9288933,
+ "81:66": -9288933,
+ "82:66": -9288933,
+ "83:66": -9288933,
+ "84:66": -9288933,
+ "85:66": -9288933,
+ "86:66": -9288933,
+ "87:66": -9288933,
+ "88:66": -9288933,
+ "89:66": -9288933,
+ "90:66": -9288933,
+ "91:66": -9288933,
+ "92:66": -9288933,
+ "93:66": -9288933,
+ "94:66": -9288933,
+ "95:66": -9288933,
+ "96:66": -9288933,
+ "97:66": -9288933,
+ "98:66": -9288933,
+ "99:66": -9288933,
+ "100:66": -9288933,
+ "101:66": -9288933,
+ "102:66": -9288933,
+ "103:66": -9288933,
+ "104:66": -9288933,
+ "105:66": -9288933,
+ "106:66": 268435456,
+ "107:66": 402653184,
+ "108:66": 268435456,
+ "109:66": 402653184,
+ "110:66": 268435456,
+ "111:66": 402653184,
+ "112:66": 268435456,
+ "113:66": 402653184,
+ "114:66": 268435456,
+ "115:66": 402653184,
+ "116:66": 268435456,
+ "117:66": 402653184,
+ "118:66": 268435456,
+ "119:66": 402653184,
+ "120:66": 268435456,
+ "121:66": 402653184,
+ "122:66": 268435456,
+ "123:66": 402653184,
+ "124:66": 268435456,
+ "125:66": 402653184,
+ "126:66": 268435456,
+ "127:66": 402653184,
+ "0:67": 402653184,
+ "1:67": 268435456,
+ "2:67": 402653184,
+ "3:67": 268435456,
+ "4:67": 402653184,
+ "5:67": 268435456,
+ "6:67": 402653184,
+ "7:67": 268435456,
+ "8:67": 402653184,
+ "9:67": 268435456,
+ "10:67": 402653184,
+ "11:67": 268435456,
+ "12:67": 402653184,
+ "13:67": 268435456,
+ "14:67": 402653184,
+ "15:67": 268435456,
+ "16:67": 402653184,
+ "17:67": 268435456,
+ "18:67": 402653184,
+ "19:67": 268435456,
+ "20:67": 402653184,
+ "21:67": 268435456,
+ "22:67": -5092136,
+ "23:67": -5092136,
+ "24:67": -5092136,
+ "25:67": -5092136,
+ "26:67": -5092136,
+ "27:67": -5092136,
+ "28:67": -5092136,
+ "29:67": -16745472,
+ "30:67": -16745472,
+ "31:67": -16745472,
+ "32:67": -5092136,
+ "33:67": -5092136,
+ "34:67": -5092136,
+ "35:67": -5092136,
+ "36:67": -5092136,
+ "37:67": -5092136,
+ "38:67": -5092136,
+ "39:67": -5092136,
+ "40:67": -5092136,
+ "41:67": -5092136,
+ "42:67": -5092136,
+ "43:67": -5092136,
+ "44:67": -884827,
+ "45:67": -884827,
+ "46:67": -884827,
+ "47:67": -884827,
+ "48:67": -884827,
+ "49:67": -884827,
+ "50:67": -884827,
+ "51:67": -16745472,
+ "52:67": -16745472,
+ "53:67": -16745472,
+ "54:67": -884827,
+ "55:67": -884827,
+ "56:67": -884827,
+ "57:67": -884827,
+ "58:67": -884827,
+ "59:67": -884827,
+ "60:67": -884827,
+ "61:67": -884827,
+ "62:67": -9288933,
+ "63:67": -9288933,
+ "64:67": -9288933,
+ "65:67": -9288933,
+ "66:67": -9288933,
+ "67:67": -9288933,
+ "68:67": -9288933,
+ "69:67": -9288933,
+ "70:67": -9288933,
+ "71:67": -9288933,
+ "72:67": -9288933,
+ "73:67": -9288933,
+ "74:67": -9288933,
+ "75:67": -9288933,
+ "76:67": -9288933,
+ "77:67": -9288933,
+ "78:67": -9288933,
+ "79:67": -9288933,
+ "80:67": -9288933,
+ "81:67": -9288933,
+ "82:67": -9288933,
+ "83:67": -9288933,
+ "84:67": -9288933,
+ "85:67": -9288933,
+ "86:67": -9288933,
+ "87:67": -9288933,
+ "88:67": -9288933,
+ "89:67": -9288933,
+ "90:67": -9288933,
+ "91:67": -9288933,
+ "92:67": -9288933,
+ "93:67": -9288933,
+ "94:67": -9288933,
+ "95:67": -9288933,
+ "96:67": -9288933,
+ "97:67": -9288933,
+ "98:67": -9288933,
+ "99:67": -9288933,
+ "100:67": -9288933,
+ "101:67": -9288933,
+ "102:67": -9288933,
+ "103:67": -9288933,
+ "104:67": -9288933,
+ "105:67": -9288933,
+ "106:67": 402653184,
+ "107:67": 268435456,
+ "108:67": 402653184,
+ "109:67": 268435456,
+ "110:67": 402653184,
+ "111:67": 268435456,
+ "112:67": 402653184,
+ "113:67": 268435456,
+ "114:67": 402653184,
+ "115:67": 268435456,
+ "116:67": 402653184,
+ "117:67": 268435456,
+ "118:67": 402653184,
+ "119:67": 268435456,
+ "120:67": 402653184,
+ "121:67": 268435456,
+ "122:67": 402653184,
+ "123:67": 268435456,
+ "124:67": 402653184,
+ "125:67": 268435456,
+ "126:67": 402653184,
+ "127:67": 268435456,
+ "0:68": 268435456,
+ "1:68": 402653184,
+ "2:68": 268435456,
+ "3:68": 402653184,
+ "4:68": 268435456,
+ "5:68": 402653184,
+ "6:68": 268435456,
+ "7:68": 402653184,
+ "8:68": 268435456,
+ "9:68": 402653184,
+ "10:68": 268435456,
+ "11:68": 402653184,
+ "12:68": 268435456,
+ "13:68": 402653184,
+ "14:68": 268435456,
+ "15:68": 402653184,
+ "16:68": 268435456,
+ "17:68": 402653184,
+ "18:68": 268435456,
+ "19:68": 402653184,
+ "20:68": 268435456,
+ "21:68": 402653184,
+ "22:68": -5092136,
+ "23:68": -5092136,
+ "24:68": -5092136,
+ "25:68": -5092136,
+ "26:68": -5092136,
+ "27:68": -5092136,
+ "28:68": -5092136,
+ "29:68": -5092136,
+ "30:68": -5092136,
+ "31:68": -5092136,
+ "32:68": -5092136,
+ "33:68": -5092136,
+ "34:68": -5092136,
+ "35:68": -5092136,
+ "36:68": -5092136,
+ "37:68": -5092136,
+ "38:68": -5092136,
+ "39:68": -5092136,
+ "40:68": 268435456,
+ "41:68": 402653184,
+ "42:68": 268435456,
+ "43:68": 402653184,
+ "44:68": -884827,
+ "45:68": -884827,
+ "46:68": -884827,
+ "47:68": -884827,
+ "48:68": -884827,
+ "49:68": -884827,
+ "50:68": -884827,
+ "51:68": -884827,
+ "52:68": -884827,
+ "53:68": -884827,
+ "54:68": -884827,
+ "55:68": -884827,
+ "56:68": -884827,
+ "57:68": -884827,
+ "58:68": -884827,
+ "59:68": -884827,
+ "60:68": -884827,
+ "61:68": -884827,
+ "62:68": 268435456,
+ "63:68": 402653184,
+ "64:68": 268435456,
+ "65:68": 402653184,
+ "66:68": -9288933,
+ "67:68": -9288933,
+ "68:68": -9288933,
+ "69:68": -9288933,
+ "70:68": -9288933,
+ "71:68": -9288933,
+ "72:68": -9288933,
+ "73:68": -9288933,
+ "74:68": -9288933,
+ "75:68": -9288933,
+ "76:68": -9288933,
+ "77:68": -9288933,
+ "78:68": -9288933,
+ "79:68": -9288933,
+ "80:68": -9288933,
+ "81:68": -9288933,
+ "82:68": -9288933,
+ "83:68": -9288933,
+ "84:68": 268435456,
+ "85:68": 402653184,
+ "86:68": 268435456,
+ "87:68": 402653184,
+ "88:68": -9288933,
+ "89:68": -9288933,
+ "90:68": -9288933,
+ "91:68": -9288933,
+ "92:68": -9288933,
+ "93:68": -9288933,
+ "94:68": -9288933,
+ "95:68": -9288933,
+ "96:68": -9288933,
+ "97:68": -9288933,
+ "98:68": -9288933,
+ "99:68": -9288933,
+ "100:68": -9288933,
+ "101:68": -9288933,
+ "102:68": -9288933,
+ "103:68": -9288933,
+ "104:68": -9288933,
+ "105:68": -9288933,
+ "106:68": 268435456,
+ "107:68": 402653184,
+ "108:68": 268435456,
+ "109:68": 402653184,
+ "110:68": 268435456,
+ "111:68": 402653184,
+ "112:68": 268435456,
+ "113:68": 402653184,
+ "114:68": 268435456,
+ "115:68": 402653184,
+ "116:68": 268435456,
+ "117:68": 402653184,
+ "118:68": 268435456,
+ "119:68": 402653184,
+ "120:68": 268435456,
+ "121:68": 402653184,
+ "122:68": 268435456,
+ "123:68": 402653184,
+ "124:68": 268435456,
+ "125:68": 402653184,
+ "126:68": 268435456,
+ "127:68": 402653184,
+ "0:69": 402653184,
+ "1:69": 268435456,
+ "2:69": 402653184,
+ "3:69": 268435456,
+ "4:69": 402653184,
+ "5:69": 268435456,
+ "6:69": 402653184,
+ "7:69": 268435456,
+ "8:69": 402653184,
+ "9:69": 268435456,
+ "10:69": 402653184,
+ "11:69": 268435456,
+ "12:69": 402653184,
+ "13:69": 268435456,
+ "14:69": 402653184,
+ "15:69": 268435456,
+ "16:69": 402653184,
+ "17:69": 268435456,
+ "18:69": 402653184,
+ "19:69": 268435456,
+ "20:69": 402653184,
+ "21:69": 268435456,
+ "22:69": -5092136,
+ "23:69": -5092136,
+ "24:69": -5092136,
+ "25:69": -5092136,
+ "26:69": -5092136,
+ "27:69": -5092136,
+ "28:69": -5092136,
+ "29:69": -5092136,
+ "30:69": -5092136,
+ "31:69": -5092136,
+ "32:69": -5092136,
+ "33:69": -5092136,
+ "34:69": -5092136,
+ "35:69": -5092136,
+ "36:69": -5092136,
+ "37:69": -5092136,
+ "38:69": -5092136,
+ "39:69": -5092136,
+ "40:69": 402653184,
+ "41:69": 268435456,
+ "42:69": 402653184,
+ "43:69": 268435456,
+ "44:69": -884827,
+ "45:69": -884827,
+ "46:69": -884827,
+ "47:69": -884827,
+ "48:69": -884827,
+ "49:69": -884827,
+ "50:69": -884827,
+ "51:69": -884827,
+ "52:69": -884827,
+ "53:69": -884827,
+ "54:69": -884827,
+ "55:69": -884827,
+ "56:69": -884827,
+ "57:69": -884827,
+ "58:69": -884827,
+ "59:69": -884827,
+ "60:69": -884827,
+ "61:69": -884827,
+ "62:69": 402653184,
+ "63:69": 268435456,
+ "64:69": 402653184,
+ "65:69": 268435456,
+ "66:69": -9288933,
+ "67:69": -9288933,
+ "68:69": -9288933,
+ "69:69": -9288933,
+ "70:69": -9288933,
+ "71:69": -9288933,
+ "72:69": -9288933,
+ "73:69": -9288933,
+ "74:69": -9288933,
+ "75:69": -9288933,
+ "76:69": -9288933,
+ "77:69": -9288933,
+ "78:69": -9288933,
+ "79:69": -9288933,
+ "80:69": -9288933,
+ "81:69": -9288933,
+ "82:69": -9288933,
+ "83:69": -9288933,
+ "84:69": 402653184,
+ "85:69": 268435456,
+ "86:69": 402653184,
+ "87:69": 268435456,
+ "88:69": -9288933,
+ "89:69": -9288933,
+ "90:69": -9288933,
+ "91:69": -9288933,
+ "92:69": -9288933,
+ "93:69": -9288933,
+ "94:69": -9288933,
+ "95:69": -9288933,
+ "96:69": -9288933,
+ "97:69": -9288933,
+ "98:69": -9288933,
+ "99:69": -9288933,
+ "100:69": -9288933,
+ "101:69": -9288933,
+ "102:69": -9288933,
+ "103:69": -9288933,
+ "104:69": -9288933,
+ "105:69": -9288933,
+ "106:69": 402653184,
+ "107:69": 268435456,
+ "108:69": 402653184,
+ "109:69": 268435456,
+ "110:69": 402653184,
+ "111:69": 268435456,
+ "112:69": 402653184,
+ "113:69": 268435456,
+ "114:69": 402653184,
+ "115:69": 268435456,
+ "116:69": 402653184,
+ "117:69": 268435456,
+ "118:69": 402653184,
+ "119:69": 268435456,
+ "120:69": 402653184,
+ "121:69": 268435456,
+ "122:69": 402653184,
+ "123:69": 268435456,
+ "124:69": 402653184,
+ "125:69": 268435456,
+ "126:69": 402653184,
+ "127:69": 268435456,
+ "0:70": 268435456,
+ "1:70": 402653184,
+ "2:70": 268435456,
+ "3:70": 402653184,
+ "4:70": 268435456,
+ "5:70": 402653184,
+ "6:70": 268435456,
+ "7:70": 402653184,
+ "8:70": 268435456,
+ "9:70": 402653184,
+ "10:70": 268435456,
+ "11:70": 402653184,
+ "12:70": 268435456,
+ "13:70": 402653184,
+ "14:70": 268435456,
+ "15:70": 402653184,
+ "16:70": 268435456,
+ "17:70": 402653184,
+ "18:70": 268435456,
+ "19:70": 402653184,
+ "20:70": 268435456,
+ "21:70": 402653184,
+ "22:70": -5092136,
+ "23:70": -5092136,
+ "24:70": -5092136,
+ "25:70": -5092136,
+ "26:70": -5092136,
+ "27:70": -5092136,
+ "28:70": -5092136,
+ "29:70": -5092136,
+ "30:70": -5092136,
+ "31:70": -5092136,
+ "32:70": -5092136,
+ "33:70": -5092136,
+ "34:70": -5092136,
+ "35:70": -5092136,
+ "36:70": -5092136,
+ "37:70": -5092136,
+ "38:70": -5092136,
+ "39:70": -5092136,
+ "40:70": 268435456,
+ "41:70": 402653184,
+ "42:70": 268435456,
+ "43:70": 402653184,
+ "44:70": -884827,
+ "45:70": -884827,
+ "46:70": -884827,
+ "47:70": -884827,
+ "48:70": -884827,
+ "49:70": -884827,
+ "50:70": -884827,
+ "51:70": -884827,
+ "52:70": -884827,
+ "53:70": -884827,
+ "54:70": -884827,
+ "55:70": -884827,
+ "56:70": -884827,
+ "57:70": -884827,
+ "58:70": -884827,
+ "59:70": -884827,
+ "60:70": -884827,
+ "61:70": -884827,
+ "62:70": 268435456,
+ "63:70": 402653184,
+ "64:70": 268435456,
+ "65:70": 402653184,
+ "66:70": -9288933,
+ "67:70": -9288933,
+ "68:70": -9288933,
+ "69:70": -9288933,
+ "70:70": -9288933,
+ "71:70": -9288933,
+ "72:70": -9288933,
+ "73:70": -9288933,
+ "74:70": -9288933,
+ "75:70": -9288933,
+ "76:70": -9288933,
+ "77:70": -9288933,
+ "78:70": -9288933,
+ "79:70": -9288933,
+ "80:70": -9288933,
+ "81:70": -9288933,
+ "82:70": -9288933,
+ "83:70": -9288933,
+ "84:70": 268435456,
+ "85:70": 402653184,
+ "86:70": 268435456,
+ "87:70": 402653184,
+ "88:70": -9288933,
+ "89:70": -9288933,
+ "90:70": -9288933,
+ "91:70": -9288933,
+ "92:70": -9288933,
+ "93:70": -9288933,
+ "94:70": -9288933,
+ "95:70": -9288933,
+ "96:70": -9288933,
+ "97:70": -9288933,
+ "98:70": -9288933,
+ "99:70": -9288933,
+ "100:70": -9288933,
+ "101:70": -9288933,
+ "102:70": -9288933,
+ "103:70": -9288933,
+ "104:70": -9288933,
+ "105:70": -9288933,
+ "106:70": 268435456,
+ "107:70": 402653184,
+ "108:70": 268435456,
+ "109:70": 402653184,
+ "110:70": 268435456,
+ "111:70": 402653184,
+ "112:70": 268435456,
+ "113:70": 402653184,
+ "114:70": 268435456,
+ "115:70": 402653184,
+ "116:70": 268435456,
+ "117:70": 402653184,
+ "118:70": 268435456,
+ "119:70": 402653184,
+ "120:70": 268435456,
+ "121:70": 402653184,
+ "122:70": 268435456,
+ "123:70": 402653184,
+ "124:70": 268435456,
+ "125:70": 402653184,
+ "126:70": 268435456,
+ "127:70": 402653184,
+ "0:71": 402653184,
+ "1:71": 268435456,
+ "2:71": 402653184,
+ "3:71": 268435456,
+ "4:71": 402653184,
+ "5:71": 268435456,
+ "6:71": 402653184,
+ "7:71": 268435456,
+ "8:71": 402653184,
+ "9:71": 268435456,
+ "10:71": 402653184,
+ "11:71": 268435456,
+ "12:71": 402653184,
+ "13:71": 268435456,
+ "14:71": 402653184,
+ "15:71": 268435456,
+ "16:71": 402653184,
+ "17:71": 268435456,
+ "18:71": 402653184,
+ "19:71": 268435456,
+ "20:71": 402653184,
+ "21:71": 268435456,
+ "22:71": -5092136,
+ "23:71": -5092136,
+ "24:71": -5092136,
+ "25:71": -5092136,
+ "26:71": -5092136,
+ "27:71": -5092136,
+ "28:71": -5092136,
+ "29:71": -5092136,
+ "30:71": -5092136,
+ "31:71": -5092136,
+ "32:71": -5092136,
+ "33:71": -5092136,
+ "34:71": -5092136,
+ "35:71": -5092136,
+ "36:71": -5092136,
+ "37:71": -5092136,
+ "38:71": -5092136,
+ "39:71": -5092136,
+ "40:71": 402653184,
+ "41:71": 268435456,
+ "42:71": 402653184,
+ "43:71": 268435456,
+ "44:71": -884827,
+ "45:71": -884827,
+ "46:71": -884827,
+ "47:71": -884827,
+ "48:71": -884827,
+ "49:71": -884827,
+ "50:71": -884827,
+ "51:71": -884827,
+ "52:71": -884827,
+ "53:71": -884827,
+ "54:71": -884827,
+ "55:71": -884827,
+ "56:71": -884827,
+ "57:71": -884827,
+ "58:71": -884827,
+ "59:71": -884827,
+ "60:71": -884827,
+ "61:71": -884827,
+ "62:71": 402653184,
+ "63:71": 268435456,
+ "64:71": 402653184,
+ "65:71": 268435456,
+ "66:71": -9288933,
+ "67:71": -9288933,
+ "68:71": -9288933,
+ "69:71": -9288933,
+ "70:71": -9288933,
+ "71:71": -9288933,
+ "72:71": -9288933,
+ "73:71": -9288933,
+ "74:71": -9288933,
+ "75:71": -9288933,
+ "76:71": -9288933,
+ "77:71": -9288933,
+ "78:71": -9288933,
+ "79:71": -9288933,
+ "80:71": -9288933,
+ "81:71": -9288933,
+ "82:71": -9288933,
+ "83:71": -9288933,
+ "84:71": 402653184,
+ "85:71": 268435456,
+ "86:71": 402653184,
+ "87:71": 268435456,
+ "88:71": -9288933,
+ "89:71": -9288933,
+ "90:71": -9288933,
+ "91:71": -9288933,
+ "92:71": -9288933,
+ "93:71": -9288933,
+ "94:71": -9288933,
+ "95:71": -9288933,
+ "96:71": -9288933,
+ "97:71": -9288933,
+ "98:71": -9288933,
+ "99:71": -9288933,
+ "100:71": -9288933,
+ "101:71": -9288933,
+ "102:71": -9288933,
+ "103:71": -9288933,
+ "104:71": -9288933,
+ "105:71": -9288933,
+ "106:71": 402653184,
+ "107:71": 268435456,
+ "108:71": 402653184,
+ "109:71": 268435456,
+ "110:71": 402653184,
+ "111:71": 268435456,
+ "112:71": 402653184,
+ "113:71": 268435456,
+ "114:71": 402653184,
+ "115:71": 268435456,
+ "116:71": 402653184,
+ "117:71": 268435456,
+ "118:71": 402653184,
+ "119:71": 268435456,
+ "120:71": 402653184,
+ "121:71": 268435456,
+ "122:71": 402653184,
+ "123:71": 268435456,
+ "124:71": 402653184,
+ "125:71": 268435456,
+ "126:71": 402653184,
+ "127:71": 268435456,
+ "0:72": 268435456,
+ "1:72": 402653184,
+ "2:72": 268435456,
+ "3:72": 402653184,
+ "4:72": 268435456,
+ "5:72": 402653184,
+ "6:72": 268435456,
+ "7:72": 402653184,
+ "8:72": 268435456,
+ "9:72": 402653184,
+ "10:72": 268435456,
+ "11:72": 402653184,
+ "12:72": 268435456,
+ "13:72": 402653184,
+ "14:72": 268435456,
+ "15:72": 402653184,
+ "16:72": 268435456,
+ "17:72": 402653184,
+ "18:72": 268435456,
+ "19:72": 402653184,
+ "20:72": 268435456,
+ "21:72": 402653184,
+ "22:72": -5092136,
+ "23:72": -5092136,
+ "24:72": -5092136,
+ "25:72": -5092136,
+ "26:72": -5092136,
+ "27:72": -5092136,
+ "28:72": -5092136,
+ "29:72": -5092136,
+ "30:72": -5092136,
+ "31:72": -5092136,
+ "32:72": -5092136,
+ "33:72": -5092136,
+ "34:72": -5092136,
+ "35:72": -5092136,
+ "36:72": -5092136,
+ "37:72": -5092136,
+ "38:72": -5092136,
+ "39:72": -5092136,
+ "40:72": 268435456,
+ "41:72": 402653184,
+ "42:72": 268435456,
+ "43:72": 402653184,
+ "44:72": -884827,
+ "45:72": -884827,
+ "46:72": -884827,
+ "47:72": -884827,
+ "48:72": -884827,
+ "49:72": -884827,
+ "50:72": -884827,
+ "51:72": -884827,
+ "52:72": -884827,
+ "53:72": -884827,
+ "54:72": -884827,
+ "55:72": -884827,
+ "56:72": -884827,
+ "57:72": -884827,
+ "58:72": -884827,
+ "59:72": -884827,
+ "60:72": -884827,
+ "61:72": -884827,
+ "62:72": 268435456,
+ "63:72": 402653184,
+ "64:72": 268435456,
+ "65:72": 402653184,
+ "66:72": -9288933,
+ "67:72": -9288933,
+ "68:72": -9288933,
+ "69:72": -9288933,
+ "70:72": -9288933,
+ "71:72": -9288933,
+ "72:72": -9288933,
+ "73:72": -9288933,
+ "74:72": -9288933,
+ "75:72": -9288933,
+ "76:72": -9288933,
+ "77:72": -9288933,
+ "78:72": -9288933,
+ "79:72": -9288933,
+ "80:72": -9288933,
+ "81:72": -9288933,
+ "82:72": -9288933,
+ "83:72": -9288933,
+ "84:72": 268435456,
+ "85:72": 402653184,
+ "86:72": 268435456,
+ "87:72": 402653184,
+ "88:72": -9288933,
+ "89:72": -9288933,
+ "90:72": -9288933,
+ "91:72": -9288933,
+ "92:72": -9288933,
+ "93:72": -9288933,
+ "94:72": -9288933,
+ "95:72": -9288933,
+ "96:72": -9288933,
+ "97:72": -9288933,
+ "98:72": -9288933,
+ "99:72": -9288933,
+ "100:72": -9288933,
+ "101:72": -9288933,
+ "102:72": -9288933,
+ "103:72": -9288933,
+ "104:72": -9288933,
+ "105:72": -9288933,
+ "106:72": 268435456,
+ "107:72": 402653184,
+ "108:72": 268435456,
+ "109:72": 402653184,
+ "110:72": 268435456,
+ "111:72": 402653184,
+ "112:72": 268435456,
+ "113:72": 402653184,
+ "114:72": 268435456,
+ "115:72": 402653184,
+ "116:72": 268435456,
+ "117:72": 402653184,
+ "118:72": 268435456,
+ "119:72": 402653184,
+ "120:72": 268435456,
+ "121:72": 402653184,
+ "122:72": 268435456,
+ "123:72": 402653184,
+ "124:72": 268435456,
+ "125:72": 402653184,
+ "126:72": 268435456,
+ "127:72": 402653184,
+ "0:73": 402653184,
+ "1:73": 268435456,
+ "2:73": 402653184,
+ "3:73": 268435456,
+ "4:73": 402653184,
+ "5:73": 268435456,
+ "6:73": 402653184,
+ "7:73": 268435456,
+ "8:73": 402653184,
+ "9:73": 268435456,
+ "10:73": 402653184,
+ "11:73": 268435456,
+ "12:73": 402653184,
+ "13:73": 268435456,
+ "14:73": 402653184,
+ "15:73": 268435456,
+ "16:73": 402653184,
+ "17:73": 268435456,
+ "18:73": 402653184,
+ "19:73": 268435456,
+ "20:73": 402653184,
+ "21:73": 268435456,
+ "22:73": 402653184,
+ "23:73": 268435456,
+ "24:73": 402653184,
+ "25:73": 268435456,
+ "26:73": 402653184,
+ "27:73": 268435456,
+ "28:73": 402653184,
+ "29:73": 268435456,
+ "30:73": 402653184,
+ "31:73": 268435456,
+ "32:73": 402653184,
+ "33:73": 268435456,
+ "34:73": 402653184,
+ "35:73": 268435456,
+ "36:73": 402653184,
+ "37:73": 268435456,
+ "38:73": 402653184,
+ "39:73": 268435456,
+ "40:73": 402653184,
+ "41:73": 268435456,
+ "42:73": 402653184,
+ "43:73": 268435456,
+ "44:73": 402653184,
+ "45:73": 268435456,
+ "46:73": 402653184,
+ "47:73": 268435456,
+ "48:73": 402653184,
+ "49:73": 268435456,
+ "50:73": -9288933,
+ "51:73": -9288933,
+ "52:73": -9288933,
+ "53:73": -9288933,
+ "54:73": -9288933,
+ "55:73": -9288933,
+ "56:73": -9288933,
+ "57:73": 268435456,
+ "58:73": 402653184,
+ "59:73": 268435456,
+ "60:73": 402653184,
+ "61:73": 268435456,
+ "62:73": 402653184,
+ "63:73": 268435456,
+ "64:73": 402653184,
+ "65:73": 268435456,
+ "66:73": 402653184,
+ "67:73": 268435456,
+ "68:73": 402653184,
+ "69:73": 268435456,
+ "70:73": 402653184,
+ "71:73": 268435456,
+ "72:73": 402653184,
+ "73:73": 268435456,
+ "74:73": 402653184,
+ "75:73": 268435456,
+ "76:73": 402653184,
+ "77:73": 268435456,
+ "78:73": 402653184,
+ "79:73": 268435456,
+ "80:73": 402653184,
+ "81:73": 268435456,
+ "82:73": 402653184,
+ "83:73": 268435456,
+ "84:73": 402653184,
+ "85:73": 268435456,
+ "86:73": 402653184,
+ "87:73": 268435456,
+ "88:73": 402653184,
+ "89:73": 268435456,
+ "90:73": 402653184,
+ "91:73": 268435456,
+ "92:73": 402653184,
+ "93:73": 268435456,
+ "94:73": -65536,
+ "95:73": -65536,
+ "96:73": -65536,
+ "97:73": -65536,
+ "98:73": -65536,
+ "99:73": -65536,
+ "100:73": -65536,
+ "101:73": 268435456,
+ "102:73": 402653184,
+ "103:73": 268435456,
+ "104:73": 402653184,
+ "105:73": 268435456,
+ "106:73": 402653184,
+ "107:73": 268435456,
+ "108:73": 402653184,
+ "109:73": 268435456,
+ "110:73": 402653184,
+ "111:73": 268435456,
+ "112:73": 402653184,
+ "113:73": 268435456,
+ "114:73": 402653184,
+ "115:73": 268435456,
+ "116:73": 402653184,
+ "117:73": 268435456,
+ "118:73": 402653184,
+ "119:73": 268435456,
+ "120:73": 402653184,
+ "121:73": 268435456,
+ "122:73": 402653184,
+ "123:73": 268435456,
+ "124:73": 402653184,
+ "125:73": 268435456,
+ "126:73": 402653184,
+ "127:73": 268435456,
+ "0:74": 268435456,
+ "1:74": 402653184,
+ "2:74": 268435456,
+ "3:74": 402653184,
+ "4:74": 268435456,
+ "5:74": 402653184,
+ "6:74": 268435456,
+ "7:74": 402653184,
+ "8:74": 268435456,
+ "9:74": 402653184,
+ "10:74": 268435456,
+ "11:74": 402653184,
+ "12:74": 268435456,
+ "13:74": 402653184,
+ "14:74": 268435456,
+ "15:74": 402653184,
+ "16:74": 268435456,
+ "17:74": 402653184,
+ "18:74": 268435456,
+ "19:74": 402653184,
+ "20:74": 268435456,
+ "21:74": 402653184,
+ "22:74": 268435456,
+ "23:74": 402653184,
+ "24:74": 268435456,
+ "25:74": 402653184,
+ "26:74": 268435456,
+ "27:74": 402653184,
+ "28:74": 268435456,
+ "29:74": 402653184,
+ "30:74": 268435456,
+ "31:74": 402653184,
+ "32:74": 268435456,
+ "33:74": 402653184,
+ "34:74": 268435456,
+ "35:74": 402653184,
+ "36:74": 268435456,
+ "37:74": 402653184,
+ "38:74": 268435456,
+ "39:74": 402653184,
+ "40:74": 268435456,
+ "41:74": 402653184,
+ "42:74": 268435456,
+ "43:74": 402653184,
+ "44:74": 268435456,
+ "45:74": 402653184,
+ "46:74": 268435456,
+ "47:74": 402653184,
+ "48:74": 268435456,
+ "49:74": 402653184,
+ "50:74": -9288933,
+ "51:74": -9288933,
+ "52:74": -9288933,
+ "53:74": -9288933,
+ "54:74": -9288933,
+ "55:74": -9288933,
+ "56:74": -9288933,
+ "57:74": 402653184,
+ "58:74": 268435456,
+ "59:74": 402653184,
+ "60:74": 268435456,
+ "61:74": 402653184,
+ "62:74": 268435456,
+ "63:74": 402653184,
+ "64:74": 268435456,
+ "65:74": 402653184,
+ "66:74": 268435456,
+ "67:74": 402653184,
+ "68:74": 268435456,
+ "69:74": 402653184,
+ "70:74": 268435456,
+ "71:74": 402653184,
+ "72:74": 268435456,
+ "73:74": 402653184,
+ "74:74": 268435456,
+ "75:74": 402653184,
+ "76:74": 268435456,
+ "77:74": 402653184,
+ "78:74": 268435456,
+ "79:74": 402653184,
+ "80:74": 268435456,
+ "81:74": 402653184,
+ "82:74": 268435456,
+ "83:74": 402653184,
+ "84:74": 268435456,
+ "85:74": 402653184,
+ "86:74": 268435456,
+ "87:74": 402653184,
+ "88:74": 268435456,
+ "89:74": 402653184,
+ "90:74": 268435456,
+ "91:74": 402653184,
+ "92:74": 268435456,
+ "93:74": 402653184,
+ "94:74": -65536,
+ "95:74": -65536,
+ "96:74": -65536,
+ "97:74": -65536,
+ "98:74": -65536,
+ "99:74": -65536,
+ "100:74": -65536,
+ "101:74": 402653184,
+ "102:74": 268435456,
+ "103:74": 402653184,
+ "104:74": 268435456,
+ "105:74": 402653184,
+ "106:74": 268435456,
+ "107:74": 402653184,
+ "108:74": 268435456,
+ "109:74": 402653184,
+ "110:74": 268435456,
+ "111:74": 402653184,
+ "112:74": 268435456,
+ "113:74": 402653184,
+ "114:74": 268435456,
+ "115:74": 402653184,
+ "116:74": 268435456,
+ "117:74": 402653184,
+ "118:74": 268435456,
+ "119:74": 402653184,
+ "120:74": 268435456,
+ "121:74": 402653184,
+ "122:74": 268435456,
+ "123:74": 402653184,
+ "124:74": 268435456,
+ "125:74": 402653184,
+ "126:74": 268435456,
+ "127:74": 402653184,
+ "0:75": 402653184,
+ "1:75": 268435456,
+ "2:75": 402653184,
+ "3:75": 268435456,
+ "4:75": 402653184,
+ "5:75": 268435456,
+ "6:75": 402653184,
+ "7:75": 268435456,
+ "8:75": 402653184,
+ "9:75": 268435456,
+ "10:75": 402653184,
+ "11:75": 268435456,
+ "12:75": 402653184,
+ "13:75": 268435456,
+ "14:75": 402653184,
+ "15:75": 268435456,
+ "16:75": 402653184,
+ "17:75": 268435456,
+ "18:75": 402653184,
+ "19:75": 268435456,
+ "20:75": 402653184,
+ "21:75": 268435456,
+ "22:75": 402653184,
+ "23:75": 268435456,
+ "24:75": 402653184,
+ "25:75": 268435456,
+ "26:75": 402653184,
+ "27:75": 268435456,
+ "28:75": 402653184,
+ "29:75": 268435456,
+ "30:75": 402653184,
+ "31:75": 268435456,
+ "32:75": 402653184,
+ "33:75": 268435456,
+ "34:75": 402653184,
+ "35:75": 268435456,
+ "36:75": 402653184,
+ "37:75": 268435456,
+ "38:75": 402653184,
+ "39:75": 268435456,
+ "40:75": 402653184,
+ "41:75": 268435456,
+ "42:75": 402653184,
+ "43:75": 268435456,
+ "44:75": 402653184,
+ "45:75": 268435456,
+ "46:75": 402653184,
+ "47:75": 268435456,
+ "48:75": 402653184,
+ "49:75": 268435456,
+ "50:75": -9288933,
+ "51:75": -9288933,
+ "52:75": -9288933,
+ "53:75": -9288933,
+ "54:75": -9288933,
+ "55:75": -9288933,
+ "56:75": -9288933,
+ "57:75": 268435456,
+ "58:75": 402653184,
+ "59:75": 268435456,
+ "60:75": 402653184,
+ "61:75": 268435456,
+ "62:75": 402653184,
+ "63:75": 268435456,
+ "64:75": 402653184,
+ "65:75": 268435456,
+ "66:75": 402653184,
+ "67:75": 268435456,
+ "68:75": 402653184,
+ "69:75": 268435456,
+ "70:75": 402653184,
+ "71:75": 268435456,
+ "72:75": 402653184,
+ "73:75": 268435456,
+ "74:75": 402653184,
+ "75:75": 268435456,
+ "76:75": 402653184,
+ "77:75": 268435456,
+ "78:75": 402653184,
+ "79:75": 268435456,
+ "80:75": 402653184,
+ "81:75": 268435456,
+ "82:75": 402653184,
+ "83:75": 268435456,
+ "84:75": 402653184,
+ "85:75": 268435456,
+ "86:75": 402653184,
+ "87:75": 268435456,
+ "88:75": 402653184,
+ "89:75": 268435456,
+ "90:75": 402653184,
+ "91:75": 268435456,
+ "92:75": 402653184,
+ "93:75": 268435456,
+ "94:75": -65536,
+ "95:75": -65536,
+ "96:75": -65536,
+ "97:75": -65536,
+ "98:75": -65536,
+ "99:75": -65536,
+ "100:75": -65536,
+ "101:75": 268435456,
+ "102:75": 402653184,
+ "103:75": 268435456,
+ "104:75": 402653184,
+ "105:75": 268435456,
+ "106:75": 402653184,
+ "107:75": 268435456,
+ "108:75": 402653184,
+ "109:75": 268435456,
+ "110:75": 402653184,
+ "111:75": 268435456,
+ "112:75": 402653184,
+ "113:75": 268435456,
+ "114:75": 402653184,
+ "115:75": 268435456,
+ "116:75": 402653184,
+ "117:75": 268435456,
+ "118:75": 402653184,
+ "119:75": 268435456,
+ "120:75": 402653184,
+ "121:75": 268435456,
+ "122:75": 402653184,
+ "123:75": 268435456,
+ "124:75": 402653184,
+ "125:75": 268435456,
+ "126:75": 402653184,
+ "127:75": 268435456,
+ "0:76": 268435456,
+ "1:76": 402653184,
+ "2:76": 268435456,
+ "3:76": 402653184,
+ "4:76": 268435456,
+ "5:76": 402653184,
+ "6:76": 268435456,
+ "7:76": 402653184,
+ "8:76": 268435456,
+ "9:76": 402653184,
+ "10:76": 268435456,
+ "11:76": 402653184,
+ "12:76": 268435456,
+ "13:76": 402653184,
+ "14:76": 268435456,
+ "15:76": 402653184,
+ "16:76": 268435456,
+ "17:76": 402653184,
+ "18:76": 268435456,
+ "19:76": 402653184,
+ "20:76": 268435456,
+ "21:76": 402653184,
+ "22:76": 268435456,
+ "23:76": 402653184,
+ "24:76": 268435456,
+ "25:76": 402653184,
+ "26:76": 268435456,
+ "27:76": 402653184,
+ "28:76": 268435456,
+ "29:76": 402653184,
+ "30:76": 268435456,
+ "31:76": 402653184,
+ "32:76": 268435456,
+ "33:76": 402653184,
+ "34:76": 268435456,
+ "35:76": 402653184,
+ "36:76": 268435456,
+ "37:76": 402653184,
+ "38:76": 268435456,
+ "39:76": 402653184,
+ "40:76": 268435456,
+ "41:76": 402653184,
+ "42:76": 268435456,
+ "43:76": 402653184,
+ "44:76": 268435456,
+ "45:76": 402653184,
+ "46:76": 268435456,
+ "47:76": 402653184,
+ "48:76": 268435456,
+ "49:76": 402653184,
+ "50:76": -9288933,
+ "51:76": -9288933,
+ "52:76": -9288933,
+ "53:76": -9288933,
+ "54:76": -9288933,
+ "55:76": -9288933,
+ "56:76": -9288933,
+ "57:76": 402653184,
+ "58:76": 268435456,
+ "59:76": 402653184,
+ "60:76": 268435456,
+ "61:76": 402653184,
+ "62:76": 268435456,
+ "63:76": 402653184,
+ "64:76": 268435456,
+ "65:76": 402653184,
+ "66:76": 268435456,
+ "67:76": 402653184,
+ "68:76": 268435456,
+ "69:76": 402653184,
+ "70:76": 268435456,
+ "71:76": 402653184,
+ "72:76": 268435456,
+ "73:76": 402653184,
+ "74:76": 268435456,
+ "75:76": 402653184,
+ "76:76": 268435456,
+ "77:76": 402653184,
+ "78:76": 268435456,
+ "79:76": 402653184,
+ "80:76": 268435456,
+ "81:76": 402653184,
+ "82:76": 268435456,
+ "83:76": 402653184,
+ "84:76": 268435456,
+ "85:76": 402653184,
+ "86:76": 268435456,
+ "87:76": 402653184,
+ "88:76": 268435456,
+ "89:76": 402653184,
+ "90:76": 268435456,
+ "91:76": 402653184,
+ "92:76": 268435456,
+ "93:76": 402653184,
+ "94:76": -65536,
+ "95:76": -65536,
+ "96:76": -65536,
+ "97:76": -65536,
+ "98:76": -65536,
+ "99:76": -65536,
+ "100:76": -65536,
+ "101:76": 402653184,
+ "102:76": 268435456,
+ "103:76": 402653184,
+ "104:76": 268435456,
+ "105:76": 402653184,
+ "106:76": 268435456,
+ "107:76": 402653184,
+ "108:76": 268435456,
+ "109:76": 402653184,
+ "110:76": 268435456,
+ "111:76": 402653184,
+ "112:76": 268435456,
+ "113:76": 402653184,
+ "114:76": 268435456,
+ "115:76": 402653184,
+ "116:76": 268435456,
+ "117:76": 402653184,
+ "118:76": 268435456,
+ "119:76": 402653184,
+ "120:76": 268435456,
+ "121:76": 402653184,
+ "122:76": 268435456,
+ "123:76": 402653184,
+ "124:76": 268435456,
+ "125:76": 402653184,
+ "126:76": 268435456,
+ "127:76": 402653184,
+ "0:77": 402653184,
+ "1:77": 268435456,
+ "2:77": 402653184,
+ "3:77": 268435456,
+ "4:77": 402653184,
+ "5:77": 268435456,
+ "6:77": 402653184,
+ "7:77": 268435456,
+ "8:77": 402653184,
+ "9:77": 268435456,
+ "10:77": 402653184,
+ "11:77": 268435456,
+ "12:77": 402653184,
+ "13:77": 268435456,
+ "14:77": 402653184,
+ "15:77": 268435456,
+ "16:77": 402653184,
+ "17:77": 268435456,
+ "18:77": 402653184,
+ "19:77": 268435456,
+ "20:77": 402653184,
+ "21:77": 268435456,
+ "22:77": -9288933,
+ "23:77": -9288933,
+ "24:77": -9288933,
+ "25:77": -9288933,
+ "26:77": -9288933,
+ "27:77": -9288933,
+ "28:77": -9288933,
+ "29:77": -9288933,
+ "30:77": -9288933,
+ "31:77": -9288933,
+ "32:77": -9288933,
+ "33:77": -9288933,
+ "34:77": -9288933,
+ "35:77": -9288933,
+ "36:77": -9288933,
+ "37:77": -9288933,
+ "38:77": -9288933,
+ "39:77": -9288933,
+ "40:77": -9288933,
+ "41:77": -9288933,
+ "42:77": -9288933,
+ "43:77": -9288933,
+ "44:77": -9288933,
+ "45:77": -9288933,
+ "46:77": -9288933,
+ "47:77": -9288933,
+ "48:77": -9288933,
+ "49:77": -9288933,
+ "50:77": -9288933,
+ "51:77": -9288933,
+ "52:77": -9288933,
+ "53:77": -9288933,
+ "54:77": -9288933,
+ "55:77": -9288933,
+ "56:77": -9288933,
+ "57:77": -9288933,
+ "58:77": -9288933,
+ "59:77": -9288933,
+ "60:77": -9288933,
+ "61:77": -9288933,
+ "62:77": 402653184,
+ "63:77": 268435456,
+ "64:77": 402653184,
+ "65:77": 268435456,
+ "66:77": -9288933,
+ "67:77": -9288933,
+ "68:77": -9288933,
+ "69:77": -9288933,
+ "70:77": -9288933,
+ "71:77": -9288933,
+ "72:77": -9288933,
+ "73:77": -9288933,
+ "74:77": -9288933,
+ "75:77": -9288933,
+ "76:77": -9288933,
+ "77:77": -9288933,
+ "78:77": -9288933,
+ "79:77": -9288933,
+ "80:77": -9288933,
+ "81:77": -9288933,
+ "82:77": -9288933,
+ "83:77": -9288933,
+ "84:77": 402653184,
+ "85:77": 268435456,
+ "86:77": 402653184,
+ "87:77": 268435456,
+ "88:77": -65536,
+ "89:77": -65536,
+ "90:77": -65536,
+ "91:77": -65536,
+ "92:77": -65536,
+ "93:77": -65536,
+ "94:77": -65536,
+ "95:77": -65536,
+ "96:77": -65536,
+ "97:77": -65536,
+ "98:77": -65536,
+ "99:77": -65536,
+ "100:77": -65536,
+ "101:77": -65536,
+ "102:77": -65536,
+ "103:77": -65536,
+ "104:77": -65536,
+ "105:77": -65536,
+ "106:77": 402653184,
+ "107:77": 268435456,
+ "108:77": 402653184,
+ "109:77": 268435456,
+ "110:77": 402653184,
+ "111:77": 268435456,
+ "112:77": 402653184,
+ "113:77": 268435456,
+ "114:77": 402653184,
+ "115:77": 268435456,
+ "116:77": 402653184,
+ "117:77": 268435456,
+ "118:77": 402653184,
+ "119:77": 268435456,
+ "120:77": 402653184,
+ "121:77": 268435456,
+ "122:77": 402653184,
+ "123:77": 268435456,
+ "124:77": 402653184,
+ "125:77": 268435456,
+ "126:77": 402653184,
+ "127:77": 268435456,
+ "0:78": 268435456,
+ "1:78": 402653184,
+ "2:78": 268435456,
+ "3:78": 402653184,
+ "4:78": 268435456,
+ "5:78": 402653184,
+ "6:78": 268435456,
+ "7:78": 402653184,
+ "8:78": 268435456,
+ "9:78": 402653184,
+ "10:78": 268435456,
+ "11:78": 402653184,
+ "12:78": 268435456,
+ "13:78": 402653184,
+ "14:78": 268435456,
+ "15:78": 402653184,
+ "16:78": 268435456,
+ "17:78": 402653184,
+ "18:78": 268435456,
+ "19:78": 402653184,
+ "20:78": 268435456,
+ "21:78": 402653184,
+ "22:78": -9288933,
+ "23:78": -9288933,
+ "24:78": -9288933,
+ "25:78": -9288933,
+ "26:78": -9288933,
+ "27:78": -9288933,
+ "28:78": -9288933,
+ "29:78": -9288933,
+ "30:78": -9288933,
+ "31:78": -9288933,
+ "32:78": -9288933,
+ "33:78": -9288933,
+ "34:78": -9288933,
+ "35:78": -9288933,
+ "36:78": -9288933,
+ "37:78": -9288933,
+ "38:78": -9288933,
+ "39:78": -9288933,
+ "40:78": -9288933,
+ "41:78": -9288933,
+ "42:78": -9288933,
+ "43:78": -9288933,
+ "44:78": -9288933,
+ "45:78": -9288933,
+ "46:78": -9288933,
+ "47:78": -9288933,
+ "48:78": -9288933,
+ "49:78": -9288933,
+ "50:78": -9288933,
+ "51:78": -9288933,
+ "52:78": -9288933,
+ "53:78": -9288933,
+ "54:78": -9288933,
+ "55:78": -9288933,
+ "56:78": -9288933,
+ "57:78": -9288933,
+ "58:78": -9288933,
+ "59:78": -9288933,
+ "60:78": -9288933,
+ "61:78": -9288933,
+ "62:78": 268435456,
+ "63:78": 402653184,
+ "64:78": 268435456,
+ "65:78": 402653184,
+ "66:78": -9288933,
+ "67:78": -9288933,
+ "68:78": -9288933,
+ "69:78": -9288933,
+ "70:78": -9288933,
+ "71:78": -9288933,
+ "72:78": -9288933,
+ "73:78": -9288933,
+ "74:78": -9288933,
+ "75:78": -9288933,
+ "76:78": -9288933,
+ "77:78": -9288933,
+ "78:78": -9288933,
+ "79:78": -9288933,
+ "80:78": -9288933,
+ "81:78": -9288933,
+ "82:78": -9288933,
+ "83:78": -9288933,
+ "84:78": 268435456,
+ "85:78": 402653184,
+ "86:78": 268435456,
+ "87:78": 402653184,
+ "88:78": -65536,
+ "89:78": -65536,
+ "90:78": -65536,
+ "91:78": -65536,
+ "92:78": -65536,
+ "93:78": -65536,
+ "94:78": -65536,
+ "95:78": -65536,
+ "96:78": -65536,
+ "97:78": -65536,
+ "98:78": -65536,
+ "99:78": -65536,
+ "100:78": -65536,
+ "101:78": -65536,
+ "102:78": -65536,
+ "103:78": -65536,
+ "104:78": -65536,
+ "105:78": -65536,
+ "106:78": 268435456,
+ "107:78": 402653184,
+ "108:78": 268435456,
+ "109:78": 402653184,
+ "110:78": 268435456,
+ "111:78": 402653184,
+ "112:78": 268435456,
+ "113:78": 402653184,
+ "114:78": 268435456,
+ "115:78": 402653184,
+ "116:78": 268435456,
+ "117:78": 402653184,
+ "118:78": 268435456,
+ "119:78": 402653184,
+ "120:78": 268435456,
+ "121:78": 402653184,
+ "122:78": 268435456,
+ "123:78": 402653184,
+ "124:78": 268435456,
+ "125:78": 402653184,
+ "126:78": 268435456,
+ "127:78": 402653184,
+ "0:79": 402653184,
+ "1:79": 268435456,
+ "2:79": 402653184,
+ "3:79": 268435456,
+ "4:79": 402653184,
+ "5:79": 268435456,
+ "6:79": 402653184,
+ "7:79": 268435456,
+ "8:79": 402653184,
+ "9:79": 268435456,
+ "10:79": 402653184,
+ "11:79": 268435456,
+ "12:79": 402653184,
+ "13:79": 268435456,
+ "14:79": 402653184,
+ "15:79": 268435456,
+ "16:79": 402653184,
+ "17:79": 268435456,
+ "18:79": 402653184,
+ "19:79": 268435456,
+ "20:79": 402653184,
+ "21:79": 268435456,
+ "22:79": -9288933,
+ "23:79": -9288933,
+ "24:79": -9288933,
+ "25:79": -9288933,
+ "26:79": -9288933,
+ "27:79": -9288933,
+ "28:79": -9288933,
+ "29:79": -9288933,
+ "30:79": -9288933,
+ "31:79": -9288933,
+ "32:79": -9288933,
+ "33:79": -9288933,
+ "34:79": -9288933,
+ "35:79": -9288933,
+ "36:79": -9288933,
+ "37:79": -9288933,
+ "38:79": -9288933,
+ "39:79": -9288933,
+ "40:79": -9288933,
+ "41:79": -9288933,
+ "42:79": -9288933,
+ "43:79": -9288933,
+ "44:79": -9288933,
+ "45:79": -9288933,
+ "46:79": -9288933,
+ "47:79": -9288933,
+ "48:79": -9288933,
+ "49:79": -9288933,
+ "50:79": -9288933,
+ "51:79": -9288933,
+ "52:79": -9288933,
+ "53:79": -9288933,
+ "54:79": -9288933,
+ "55:79": -9288933,
+ "56:79": -9288933,
+ "57:79": -9288933,
+ "58:79": -9288933,
+ "59:79": -9288933,
+ "60:79": -9288933,
+ "61:79": -9288933,
+ "62:79": 402653184,
+ "63:79": 268435456,
+ "64:79": 402653184,
+ "65:79": 268435456,
+ "66:79": -9288933,
+ "67:79": -9288933,
+ "68:79": -9288933,
+ "69:79": -9288933,
+ "70:79": -9288933,
+ "71:79": -9288933,
+ "72:79": -9288933,
+ "73:79": -9288933,
+ "74:79": -9288933,
+ "75:79": -9288933,
+ "76:79": -9288933,
+ "77:79": -9288933,
+ "78:79": -9288933,
+ "79:79": -9288933,
+ "80:79": -9288933,
+ "81:79": -9288933,
+ "82:79": -9288933,
+ "83:79": -9288933,
+ "84:79": 402653184,
+ "85:79": 268435456,
+ "86:79": 402653184,
+ "87:79": 268435456,
+ "88:79": -65536,
+ "89:79": -65536,
+ "90:79": -65536,
+ "91:79": -65536,
+ "92:79": -65536,
+ "93:79": -65536,
+ "94:79": -65536,
+ "95:79": -65536,
+ "96:79": -65536,
+ "97:79": -65536,
+ "98:79": -65536,
+ "99:79": -65536,
+ "100:79": -65536,
+ "101:79": -65536,
+ "102:79": -65536,
+ "103:79": -65536,
+ "104:79": -65536,
+ "105:79": -65536,
+ "106:79": 402653184,
+ "107:79": 268435456,
+ "108:79": 402653184,
+ "109:79": 268435456,
+ "110:79": 402653184,
+ "111:79": 268435456,
+ "112:79": 402653184,
+ "113:79": 268435456,
+ "114:79": 402653184,
+ "115:79": 268435456,
+ "116:79": 402653184,
+ "117:79": 268435456,
+ "118:79": 402653184,
+ "119:79": 268435456,
+ "120:79": 402653184,
+ "121:79": 268435456,
+ "122:79": 402653184,
+ "123:79": 268435456,
+ "124:79": 402653184,
+ "125:79": 268435456,
+ "126:79": 402653184,
+ "127:79": 268435456,
+ "0:80": 268435456,
+ "1:80": 402653184,
+ "2:80": 268435456,
+ "3:80": 402653184,
+ "4:80": 268435456,
+ "5:80": 402653184,
+ "6:80": 268435456,
+ "7:80": 402653184,
+ "8:80": 268435456,
+ "9:80": 402653184,
+ "10:80": 268435456,
+ "11:80": 402653184,
+ "12:80": 268435456,
+ "13:80": 402653184,
+ "14:80": 268435456,
+ "15:80": 402653184,
+ "16:80": 268435456,
+ "17:80": 402653184,
+ "18:80": 268435456,
+ "19:80": 402653184,
+ "20:80": 268435456,
+ "21:80": 402653184,
+ "22:80": -9288933,
+ "23:80": -9288933,
+ "24:80": -9288933,
+ "25:80": -9288933,
+ "26:80": -9288933,
+ "27:80": -9288933,
+ "28:80": -9288933,
+ "29:80": -9288933,
+ "30:80": -9288933,
+ "31:80": -9288933,
+ "32:80": -9288933,
+ "33:80": -9288933,
+ "34:80": -9288933,
+ "35:80": -9288933,
+ "36:80": -9288933,
+ "37:80": -9288933,
+ "38:80": -9288933,
+ "39:80": -9288933,
+ "40:80": -9288933,
+ "41:80": -9288933,
+ "42:80": -9288933,
+ "43:80": -9288933,
+ "44:80": -9288933,
+ "45:80": -9288933,
+ "46:80": -9288933,
+ "47:80": -9288933,
+ "48:80": -9288933,
+ "49:80": -9288933,
+ "50:80": -9288933,
+ "51:80": -9288933,
+ "52:80": -9288933,
+ "53:80": -9288933,
+ "54:80": -9288933,
+ "55:80": -9288933,
+ "56:80": -9288933,
+ "57:80": -9288933,
+ "58:80": -9288933,
+ "59:80": -9288933,
+ "60:80": -9288933,
+ "61:80": -9288933,
+ "62:80": 268435456,
+ "63:80": 402653184,
+ "64:80": 268435456,
+ "65:80": 402653184,
+ "66:80": -9288933,
+ "67:80": -9288933,
+ "68:80": -9288933,
+ "69:80": -9288933,
+ "70:80": -9288933,
+ "71:80": -9288933,
+ "72:80": -9288933,
+ "73:80": -9288933,
+ "74:80": -9288933,
+ "75:80": -9288933,
+ "76:80": -9288933,
+ "77:80": -9288933,
+ "78:80": -9288933,
+ "79:80": -9288933,
+ "80:80": -9288933,
+ "81:80": -9288933,
+ "82:80": -9288933,
+ "83:80": -9288933,
+ "84:80": 268435456,
+ "85:80": 402653184,
+ "86:80": 268435456,
+ "87:80": 402653184,
+ "88:80": -65536,
+ "89:80": -65536,
+ "90:80": -65536,
+ "91:80": -65536,
+ "92:80": -65536,
+ "93:80": -65536,
+ "94:80": -65536,
+ "95:80": -65536,
+ "96:80": -65536,
+ "97:80": -65536,
+ "98:80": -65536,
+ "99:80": -65536,
+ "100:80": -65536,
+ "101:80": -65536,
+ "102:80": -65536,
+ "103:80": -65536,
+ "104:80": -65536,
+ "105:80": -65536,
+ "106:80": 268435456,
+ "107:80": 402653184,
+ "108:80": 268435456,
+ "109:80": 402653184,
+ "110:80": 268435456,
+ "111:80": 402653184,
+ "112:80": 268435456,
+ "113:80": 402653184,
+ "114:80": 268435456,
+ "115:80": 402653184,
+ "116:80": 268435456,
+ "117:80": 402653184,
+ "118:80": 268435456,
+ "119:80": 402653184,
+ "120:80": 268435456,
+ "121:80": 402653184,
+ "122:80": 268435456,
+ "123:80": 402653184,
+ "124:80": 268435456,
+ "125:80": 402653184,
+ "126:80": 268435456,
+ "127:80": 402653184,
+ "0:81": 402653184,
+ "1:81": 268435456,
+ "2:81": 402653184,
+ "3:81": 268435456,
+ "4:81": 402653184,
+ "5:81": 268435456,
+ "6:81": 402653184,
+ "7:81": 268435456,
+ "8:81": 402653184,
+ "9:81": 268435456,
+ "10:81": 402653184,
+ "11:81": 268435456,
+ "12:81": 402653184,
+ "13:81": 268435456,
+ "14:81": 402653184,
+ "15:81": 268435456,
+ "16:81": 402653184,
+ "17:81": 268435456,
+ "18:81": 402653184,
+ "19:81": 268435456,
+ "20:81": 402653184,
+ "21:81": 268435456,
+ "22:81": -9288933,
+ "23:81": -9288933,
+ "24:81": -9288933,
+ "25:81": -9288933,
+ "26:81": -9288933,
+ "27:81": -9288933,
+ "28:81": -9288933,
+ "29:81": -9288933,
+ "30:81": -9288933,
+ "31:81": -9288933,
+ "32:81": -9288933,
+ "33:81": -9288933,
+ "34:81": -9288933,
+ "35:81": -9288933,
+ "36:81": -9288933,
+ "37:81": -9288933,
+ "38:81": -9288933,
+ "39:81": -9288933,
+ "40:81": -9288933,
+ "41:81": -9288933,
+ "42:81": -9288933,
+ "43:81": -9288933,
+ "44:81": -9288933,
+ "45:81": -9288933,
+ "46:81": -9288933,
+ "47:81": -9288933,
+ "48:81": -9288933,
+ "49:81": -9288933,
+ "50:81": -9288933,
+ "51:81": -9288933,
+ "52:81": -9288933,
+ "53:81": -9288933,
+ "54:81": -9288933,
+ "55:81": -9288933,
+ "56:81": -9288933,
+ "57:81": -9288933,
+ "58:81": -9288933,
+ "59:81": -9288933,
+ "60:81": -9288933,
+ "61:81": -9288933,
+ "62:81": 402653184,
+ "63:81": 268435456,
+ "64:81": 402653184,
+ "65:81": 268435456,
+ "66:81": -9288933,
+ "67:81": -9288933,
+ "68:81": -9288933,
+ "69:81": -9288933,
+ "70:81": -9288933,
+ "71:81": -9288933,
+ "72:81": -9288933,
+ "73:81": -9288933,
+ "74:81": -9288933,
+ "75:81": -9288933,
+ "76:81": -9288933,
+ "77:81": -9288933,
+ "78:81": -9288933,
+ "79:81": -9288933,
+ "80:81": -9288933,
+ "81:81": -9288933,
+ "82:81": -9288933,
+ "83:81": -9288933,
+ "84:81": 402653184,
+ "85:81": 268435456,
+ "86:81": 402653184,
+ "87:81": 268435456,
+ "88:81": -65536,
+ "89:81": -65536,
+ "90:81": -65536,
+ "91:81": -65536,
+ "92:81": -65536,
+ "93:81": -65536,
+ "94:81": -65536,
+ "95:81": -65536,
+ "96:81": -65536,
+ "97:81": -65536,
+ "98:81": -65536,
+ "99:81": -65536,
+ "100:81": -65536,
+ "101:81": -65536,
+ "102:81": -65536,
+ "103:81": -65536,
+ "104:81": -65536,
+ "105:81": -65536,
+ "106:81": 402653184,
+ "107:81": 268435456,
+ "108:81": 402653184,
+ "109:81": 268435456,
+ "110:81": 402653184,
+ "111:81": 268435456,
+ "112:81": 402653184,
+ "113:81": 268435456,
+ "114:81": 402653184,
+ "115:81": 268435456,
+ "116:81": 402653184,
+ "117:81": 268435456,
+ "118:81": 402653184,
+ "119:81": 268435456,
+ "120:81": 402653184,
+ "121:81": 268435456,
+ "122:81": 402653184,
+ "123:81": 268435456,
+ "124:81": 402653184,
+ "125:81": 268435456,
+ "126:81": 402653184,
+ "127:81": 268435456,
+ "0:82": 268435456,
+ "1:82": 402653184,
+ "2:82": 268435456,
+ "3:82": 402653184,
+ "4:82": 268435456,
+ "5:82": 402653184,
+ "6:82": 268435456,
+ "7:82": 402653184,
+ "8:82": 268435456,
+ "9:82": 402653184,
+ "10:82": 268435456,
+ "11:82": 402653184,
+ "12:82": 268435456,
+ "13:82": 402653184,
+ "14:82": 268435456,
+ "15:82": 402653184,
+ "16:82": 268435456,
+ "17:82": 402653184,
+ "18:82": 268435456,
+ "19:82": 402653184,
+ "20:82": 268435456,
+ "21:82": 402653184,
+ "22:82": -9288933,
+ "23:82": -9288933,
+ "24:82": -9288933,
+ "25:82": -9288933,
+ "26:82": -9288933,
+ "27:82": -9288933,
+ "28:82": -9288933,
+ "29:82": -9288933,
+ "30:82": -9288933,
+ "31:82": -9288933,
+ "32:82": -9288933,
+ "33:82": -9288933,
+ "34:82": -9288933,
+ "35:82": -9288933,
+ "36:82": -9288933,
+ "37:82": -9288933,
+ "38:82": -9288933,
+ "39:82": -9288933,
+ "40:82": -9288933,
+ "41:82": -9288933,
+ "42:82": -9288933,
+ "43:82": -9288933,
+ "44:82": -9288933,
+ "45:82": -9288933,
+ "46:82": -9288933,
+ "47:82": -9288933,
+ "48:82": -9288933,
+ "49:82": -9288933,
+ "50:82": -9288933,
+ "51:82": -9288933,
+ "52:82": -9288933,
+ "53:82": -9288933,
+ "54:82": -9288933,
+ "55:82": -9288933,
+ "56:82": -9288933,
+ "57:82": -9288933,
+ "58:82": -9288933,
+ "59:82": -9288933,
+ "60:82": -9288933,
+ "61:82": -9288933,
+ "62:82": 268435456,
+ "63:82": 402653184,
+ "64:82": 268435456,
+ "65:82": 402653184,
+ "66:82": -9288933,
+ "67:82": -9288933,
+ "68:82": -9288933,
+ "69:82": -9288933,
+ "70:82": -9288933,
+ "71:82": -9288933,
+ "72:82": -9288933,
+ "73:82": -9288933,
+ "74:82": -9288933,
+ "75:82": -9288933,
+ "76:82": -9288933,
+ "77:82": -9288933,
+ "78:82": -9288933,
+ "79:82": -9288933,
+ "80:82": -9288933,
+ "81:82": -9288933,
+ "82:82": -9288933,
+ "83:82": -9288933,
+ "84:82": 268435456,
+ "85:82": 402653184,
+ "86:82": 268435456,
+ "87:82": 402653184,
+ "88:82": -65536,
+ "89:82": -65536,
+ "90:82": -65536,
+ "91:82": -65536,
+ "92:82": -65536,
+ "93:82": -65536,
+ "94:82": -65536,
+ "95:82": -65536,
+ "96:82": -65536,
+ "97:82": -65536,
+ "98:82": -65536,
+ "99:82": -65536,
+ "100:82": -65536,
+ "101:82": -65536,
+ "102:82": -65536,
+ "103:82": -65536,
+ "104:82": -65536,
+ "105:82": -65536,
+ "106:82": 268435456,
+ "107:82": 402653184,
+ "108:82": 268435456,
+ "109:82": 402653184,
+ "110:82": 268435456,
+ "111:82": 402653184,
+ "112:82": 268435456,
+ "113:82": 402653184,
+ "114:82": 268435456,
+ "115:82": 402653184,
+ "116:82": 268435456,
+ "117:82": 402653184,
+ "118:82": 268435456,
+ "119:82": 402653184,
+ "120:82": 268435456,
+ "121:82": 402653184,
+ "122:82": 268435456,
+ "123:82": 402653184,
+ "124:82": 268435456,
+ "125:82": 402653184,
+ "126:82": 268435456,
+ "127:82": 402653184,
+ "0:83": 402653184,
+ "1:83": 268435456,
+ "2:83": 402653184,
+ "3:83": 268435456,
+ "4:83": 402653184,
+ "5:83": 268435456,
+ "6:83": 402653184,
+ "7:83": 268435456,
+ "8:83": 402653184,
+ "9:83": 268435456,
+ "10:83": 402653184,
+ "11:83": 268435456,
+ "12:83": 402653184,
+ "13:83": 268435456,
+ "14:83": 402653184,
+ "15:83": 268435456,
+ "16:83": 402653184,
+ "17:83": 268435456,
+ "18:83": 402653184,
+ "19:83": 268435456,
+ "20:83": 402653184,
+ "21:83": 268435456,
+ "22:83": -9288933,
+ "23:83": -9288933,
+ "24:83": -9288933,
+ "25:83": -9288933,
+ "26:83": -9288933,
+ "27:83": -9288933,
+ "28:83": -9288933,
+ "29:83": -9288933,
+ "30:83": -9288933,
+ "31:83": -9288933,
+ "32:83": -9288933,
+ "33:83": -9288933,
+ "34:83": -9288933,
+ "35:83": -9288933,
+ "36:83": -9288933,
+ "37:83": -9288933,
+ "38:83": -9288933,
+ "39:83": -9288933,
+ "40:83": -9288933,
+ "41:83": -9288933,
+ "42:83": -9288933,
+ "43:83": -9288933,
+ "44:83": -9288933,
+ "45:83": -9288933,
+ "46:83": -9288933,
+ "47:83": -9288933,
+ "48:83": -9288933,
+ "49:83": -9288933,
+ "50:83": -9288933,
+ "51:83": -9288933,
+ "52:83": -9288933,
+ "53:83": -9288933,
+ "54:83": -9288933,
+ "55:83": -9288933,
+ "56:83": -9288933,
+ "57:83": -9288933,
+ "58:83": -9288933,
+ "59:83": -9288933,
+ "60:83": -9288933,
+ "61:83": -9288933,
+ "62:83": -9288933,
+ "63:83": -9288933,
+ "64:83": -9288933,
+ "65:83": -9288933,
+ "66:83": -9288933,
+ "67:83": -9288933,
+ "68:83": -9288933,
+ "69:83": -9288933,
+ "70:83": -9288933,
+ "71:83": -9288933,
+ "72:83": -9288933,
+ "73:83": -9288933,
+ "74:83": -9288933,
+ "75:83": -9288933,
+ "76:83": -9288933,
+ "77:83": -9288933,
+ "78:83": -9288933,
+ "79:83": -9288933,
+ "80:83": -9288933,
+ "81:83": -9288933,
+ "82:83": -9288933,
+ "83:83": -9288933,
+ "84:83": 402653184,
+ "85:83": 268435456,
+ "86:83": 402653184,
+ "87:83": 268435456,
+ "88:83": -65536,
+ "89:83": -65536,
+ "90:83": -65536,
+ "91:83": -65536,
+ "92:83": -65536,
+ "93:83": -65536,
+ "94:83": -65536,
+ "95:83": -65536,
+ "96:83": -65536,
+ "97:83": -65536,
+ "98:83": -65536,
+ "99:83": -65536,
+ "100:83": -65536,
+ "101:83": -65536,
+ "102:83": -65536,
+ "103:83": -65536,
+ "104:83": -65536,
+ "105:83": -65536,
+ "106:83": 402653184,
+ "107:83": 268435456,
+ "108:83": 402653184,
+ "109:83": 268435456,
+ "110:83": 402653184,
+ "111:83": 268435456,
+ "112:83": 402653184,
+ "113:83": 268435456,
+ "114:83": 402653184,
+ "115:83": 268435456,
+ "116:83": 402653184,
+ "117:83": 268435456,
+ "118:83": 402653184,
+ "119:83": 268435456,
+ "120:83": 402653184,
+ "121:83": 268435456,
+ "122:83": 402653184,
+ "123:83": 268435456,
+ "124:83": 402653184,
+ "125:83": 268435456,
+ "126:83": 402653184,
+ "127:83": 268435456,
+ "0:84": 268435456,
+ "1:84": 402653184,
+ "2:84": 268435456,
+ "3:84": 402653184,
+ "4:84": 268435456,
+ "5:84": 402653184,
+ "6:84": 268435456,
+ "7:84": 402653184,
+ "8:84": 268435456,
+ "9:84": 402653184,
+ "10:84": 268435456,
+ "11:84": 402653184,
+ "12:84": 268435456,
+ "13:84": 402653184,
+ "14:84": 268435456,
+ "15:84": 402653184,
+ "16:84": 268435456,
+ "17:84": 402653184,
+ "18:84": 268435456,
+ "19:84": 402653184,
+ "20:84": 268435456,
+ "21:84": 402653184,
+ "22:84": -9288933,
+ "23:84": -9288933,
+ "24:84": -9288933,
+ "25:84": -9288933,
+ "26:84": -9288933,
+ "27:84": -9288933,
+ "28:84": -9288933,
+ "29:84": -9288933,
+ "30:84": -9288933,
+ "31:84": -9288933,
+ "32:84": -1,
+ "33:84": -1,
+ "34:84": -1,
+ "35:84": -9288933,
+ "36:84": -9288933,
+ "37:84": -9288933,
+ "38:84": -9288933,
+ "39:84": -9288933,
+ "40:84": -9288933,
+ "41:84": -9288933,
+ "42:84": -9288933,
+ "43:84": -9288933,
+ "44:84": -9288933,
+ "45:84": -9288933,
+ "46:84": -9288933,
+ "47:84": -9288933,
+ "48:84": -9288933,
+ "49:84": -9288933,
+ "50:84": -9288933,
+ "51:84": -9288933,
+ "52:84": -9288933,
+ "53:84": -9288933,
+ "54:84": -9288933,
+ "55:84": -9288933,
+ "56:84": -9288933,
+ "57:84": -9288933,
+ "58:84": -9288933,
+ "59:84": -9288933,
+ "60:84": -9288933,
+ "61:84": -9288933,
+ "62:84": -9288933,
+ "63:84": -9288933,
+ "64:84": -9288933,
+ "65:84": -9288933,
+ "66:84": -9288933,
+ "67:84": -9288933,
+ "68:84": -9288933,
+ "69:84": -9288933,
+ "70:84": -9288933,
+ "71:84": -9288933,
+ "72:84": -9288933,
+ "73:84": -9288933,
+ "74:84": -9288933,
+ "75:84": -9288933,
+ "76:84": -16745472,
+ "77:84": -16745472,
+ "78:84": -16745472,
+ "79:84": -9288933,
+ "80:84": -9288933,
+ "81:84": -9288933,
+ "82:84": -9288933,
+ "83:84": -9288933,
+ "84:84": 268435456,
+ "85:84": 402653184,
+ "86:84": 268435456,
+ "87:84": 402653184,
+ "88:84": -65536,
+ "89:84": -65536,
+ "90:84": -65536,
+ "91:84": -65536,
+ "92:84": -65536,
+ "93:84": -65536,
+ "94:84": -65536,
+ "95:84": -65536,
+ "96:84": -65536,
+ "97:84": -65536,
+ "98:84": -65536,
+ "99:84": -65536,
+ "100:84": -65536,
+ "101:84": -65536,
+ "102:84": -65536,
+ "103:84": -65536,
+ "104:84": -65536,
+ "105:84": -65536,
+ "106:84": 268435456,
+ "107:84": 402653184,
+ "108:84": 268435456,
+ "109:84": 402653184,
+ "110:84": 268435456,
+ "111:84": 402653184,
+ "112:84": 268435456,
+ "113:84": 402653184,
+ "114:84": 268435456,
+ "115:84": 402653184,
+ "116:84": 268435456,
+ "117:84": 402653184,
+ "118:84": 268435456,
+ "119:84": 402653184,
+ "120:84": 268435456,
+ "121:84": 402653184,
+ "122:84": 268435456,
+ "123:84": 402653184,
+ "124:84": 268435456,
+ "125:84": 402653184,
+ "126:84": 268435456,
+ "127:84": 402653184,
+ "0:85": 402653184,
+ "1:85": 268435456,
+ "2:85": 402653184,
+ "3:85": 268435456,
+ "4:85": 402653184,
+ "5:85": 268435456,
+ "6:85": 402653184,
+ "7:85": 268435456,
+ "8:85": 402653184,
+ "9:85": 268435456,
+ "10:85": 402653184,
+ "11:85": 268435456,
+ "12:85": 402653184,
+ "13:85": 268435456,
+ "14:85": 402653184,
+ "15:85": 268435456,
+ "16:85": 402653184,
+ "17:85": 268435456,
+ "18:85": 402653184,
+ "19:85": 268435456,
+ "20:85": 402653184,
+ "21:85": 268435456,
+ "22:85": -9288933,
+ "23:85": -9288933,
+ "24:85": -9288933,
+ "25:85": -9288933,
+ "26:85": -9288933,
+ "27:85": -9288933,
+ "28:85": -9288933,
+ "29:85": -9288933,
+ "30:85": -9288933,
+ "31:85": -1,
+ "32:85": -1,
+ "33:85": -1,
+ "34:85": -9288933,
+ "35:85": -9288933,
+ "36:85": -9288933,
+ "37:85": -9288933,
+ "38:85": -9288933,
+ "39:85": -9288933,
+ "40:85": -9288933,
+ "41:85": -9288933,
+ "42:85": -9288933,
+ "43:85": -9288933,
+ "44:85": -9288933,
+ "45:85": -9288933,
+ "46:85": -9288933,
+ "47:85": -9288933,
+ "48:85": -9288933,
+ "49:85": -9288933,
+ "50:85": -9288933,
+ "51:85": -9288933,
+ "52:85": -9288933,
+ "53:85": -9288933,
+ "54:85": -9288933,
+ "55:85": -9288933,
+ "56:85": -9288933,
+ "57:85": -9288933,
+ "58:85": -9288933,
+ "59:85": -9288933,
+ "60:85": -9288933,
+ "61:85": -9288933,
+ "62:85": -9288933,
+ "63:85": -9288933,
+ "64:85": -9288933,
+ "65:85": -9288933,
+ "66:85": -9288933,
+ "67:85": -9288933,
+ "68:85": -9288933,
+ "69:85": -9288933,
+ "70:85": -9288933,
+ "71:85": -9288933,
+ "72:85": -9288933,
+ "73:85": -9288933,
+ "74:85": -9288933,
+ "75:85": -16745472,
+ "76:85": -16745472,
+ "77:85": -16745472,
+ "78:85": -9288933,
+ "79:85": -9288933,
+ "80:85": -9288933,
+ "81:85": -9288933,
+ "82:85": -9288933,
+ "83:85": -9288933,
+ "84:85": 402653184,
+ "85:85": 268435456,
+ "86:85": 402653184,
+ "87:85": 268435456,
+ "88:85": -65536,
+ "89:85": -65536,
+ "90:85": -65536,
+ "91:85": -65536,
+ "92:85": -65536,
+ "93:85": -65536,
+ "94:85": -65536,
+ "95:85": -65536,
+ "96:85": -65536,
+ "97:85": -65536,
+ "98:85": -65536,
+ "99:85": -65536,
+ "100:85": -65536,
+ "101:85": -65536,
+ "102:85": -65536,
+ "103:85": -65536,
+ "104:85": -65536,
+ "105:85": -65536,
+ "106:85": 402653184,
+ "107:85": 268435456,
+ "108:85": 402653184,
+ "109:85": 268435456,
+ "110:85": 402653184,
+ "111:85": 268435456,
+ "112:85": 402653184,
+ "113:85": 268435456,
+ "114:85": 402653184,
+ "115:85": 268435456,
+ "116:85": 402653184,
+ "117:85": 268435456,
+ "118:85": 402653184,
+ "119:85": 268435456,
+ "120:85": 402653184,
+ "121:85": 268435456,
+ "122:85": 402653184,
+ "123:85": 268435456,
+ "124:85": 402653184,
+ "125:85": 268435456,
+ "126:85": 402653184,
+ "127:85": 268435456,
+ "0:86": 268435456,
+ "1:86": 402653184,
+ "2:86": 268435456,
+ "3:86": 402653184,
+ "4:86": 268435456,
+ "5:86": 402653184,
+ "6:86": 268435456,
+ "7:86": 402653184,
+ "8:86": 268435456,
+ "9:86": 402653184,
+ "10:86": 268435456,
+ "11:86": 402653184,
+ "12:86": 268435456,
+ "13:86": 402653184,
+ "14:86": 268435456,
+ "15:86": 402653184,
+ "16:86": 268435456,
+ "17:86": 402653184,
+ "18:86": 268435456,
+ "19:86": 402653184,
+ "20:86": 268435456,
+ "21:86": 402653184,
+ "22:86": -9288933,
+ "23:86": -9288933,
+ "24:86": -9288933,
+ "25:86": -9288933,
+ "26:86": -9288933,
+ "27:86": -9288933,
+ "28:86": -9288933,
+ "29:86": -9288933,
+ "30:86": -9288933,
+ "31:86": -1,
+ "32:86": -1,
+ "33:86": -9288933,
+ "34:86": -9288933,
+ "35:86": -9288933,
+ "36:86": -9288933,
+ "37:86": -9288933,
+ "38:86": -9288933,
+ "39:86": -9288933,
+ "40:86": -9288933,
+ "41:86": -9288933,
+ "42:86": -9288933,
+ "43:86": -9288933,
+ "44:86": -9288933,
+ "45:86": -9288933,
+ "46:86": -9288933,
+ "47:86": -9288933,
+ "48:86": -9288933,
+ "49:86": -9288933,
+ "50:86": -9288933,
+ "51:86": -9288933,
+ "52:86": -9288933,
+ "53:86": -9288933,
+ "54:86": -9288933,
+ "55:86": -9288933,
+ "56:86": -9288933,
+ "57:86": -9288933,
+ "58:86": -9288933,
+ "59:86": -9288933,
+ "60:86": -9288933,
+ "61:86": -9288933,
+ "62:86": -9288933,
+ "63:86": -9288933,
+ "64:86": -9288933,
+ "65:86": -9288933,
+ "66:86": -9288933,
+ "67:86": -9288933,
+ "68:86": -9288933,
+ "69:86": -9288933,
+ "70:86": -9288933,
+ "71:86": -9288933,
+ "72:86": -9288933,
+ "73:86": -9288933,
+ "74:86": -9288933,
+ "75:86": -16745472,
+ "76:86": -16745472,
+ "77:86": -9288933,
+ "78:86": -9288933,
+ "79:86": -9288933,
+ "80:86": -9288933,
+ "81:86": -9288933,
+ "82:86": -9288933,
+ "83:86": -9288933,
+ "84:86": 268435456,
+ "85:86": 402653184,
+ "86:86": 268435456,
+ "87:86": 402653184,
+ "88:86": -65536,
+ "89:86": -65536,
+ "90:86": -65536,
+ "91:86": -65536,
+ "92:86": -65536,
+ "93:86": -65536,
+ "94:86": -65536,
+ "95:86": -65536,
+ "96:86": -65536,
+ "97:86": -65536,
+ "98:86": -65536,
+ "99:86": -65536,
+ "100:86": -65536,
+ "101:86": -65536,
+ "102:86": -65536,
+ "103:86": -65536,
+ "104:86": -65536,
+ "105:86": -65536,
+ "106:86": 268435456,
+ "107:86": 402653184,
+ "108:86": 268435456,
+ "109:86": 402653184,
+ "110:86": 268435456,
+ "111:86": 402653184,
+ "112:86": 268435456,
+ "113:86": 402653184,
+ "114:86": 268435456,
+ "115:86": 402653184,
+ "116:86": 268435456,
+ "117:86": 402653184,
+ "118:86": 268435456,
+ "119:86": 402653184,
+ "120:86": 268435456,
+ "121:86": 402653184,
+ "122:86": 268435456,
+ "123:86": 402653184,
+ "124:86": 268435456,
+ "125:86": 402653184,
+ "126:86": 268435456,
+ "127:86": 402653184,
+ "0:87": 402653184,
+ "1:87": 268435456,
+ "2:87": 402653184,
+ "3:87": 268435456,
+ "4:87": 402653184,
+ "5:87": 268435456,
+ "6:87": 402653184,
+ "7:87": 268435456,
+ "8:87": 402653184,
+ "9:87": 268435456,
+ "10:87": 402653184,
+ "11:87": 268435456,
+ "12:87": 402653184,
+ "13:87": 268435456,
+ "14:87": 402653184,
+ "15:87": 268435456,
+ "16:87": 402653184,
+ "17:87": 268435456,
+ "18:87": 402653184,
+ "19:87": 268435456,
+ "20:87": 402653184,
+ "21:87": 268435456,
+ "22:87": -9288933,
+ "23:87": -9288933,
+ "24:87": -9288933,
+ "25:87": -9288933,
+ "26:87": -9288933,
+ "27:87": -9288933,
+ "28:87": -1,
+ "29:87": -1,
+ "30:87": -9288933,
+ "31:87": -1,
+ "32:87": -1,
+ "33:87": -9288933,
+ "34:87": -9288933,
+ "35:87": -9288933,
+ "36:87": -9288933,
+ "37:87": -9288933,
+ "38:87": -9288933,
+ "39:87": -9288933,
+ "40:87": -9288933,
+ "41:87": -9288933,
+ "42:87": -9288933,
+ "43:87": -9288933,
+ "44:87": -9288933,
+ "45:87": -9288933,
+ "46:87": -9288933,
+ "47:87": -9288933,
+ "48:87": -9288933,
+ "49:87": -9288933,
+ "50:87": -9288933,
+ "51:87": -9288933,
+ "52:87": -9288933,
+ "53:87": -9288933,
+ "54:87": -9288933,
+ "55:87": -9288933,
+ "56:87": -9288933,
+ "57:87": -9288933,
+ "58:87": -9288933,
+ "59:87": -9288933,
+ "60:87": -9288933,
+ "61:87": -9288933,
+ "62:87": -9288933,
+ "63:87": -9288933,
+ "64:87": -9288933,
+ "65:87": -9288933,
+ "66:87": -9288933,
+ "67:87": -9288933,
+ "68:87": -9288933,
+ "69:87": -9288933,
+ "70:87": -9288933,
+ "71:87": -9288933,
+ "72:87": -16745472,
+ "73:87": -16745472,
+ "74:87": -9288933,
+ "75:87": -16745472,
+ "76:87": -16745472,
+ "77:87": -9288933,
+ "78:87": -9288933,
+ "79:87": -9288933,
+ "80:87": -9288933,
+ "81:87": -9288933,
+ "82:87": -9288933,
+ "83:87": -9288933,
+ "84:87": 402653184,
+ "85:87": 268435456,
+ "86:87": 402653184,
+ "87:87": 268435456,
+ "88:87": -65536,
+ "89:87": -65536,
+ "90:87": -65536,
+ "91:87": -65536,
+ "92:87": -65536,
+ "93:87": -65536,
+ "94:87": -65536,
+ "95:87": -65536,
+ "96:87": -65536,
+ "97:87": -65536,
+ "98:87": -65536,
+ "99:87": -65536,
+ "100:87": -65536,
+ "101:87": -65536,
+ "102:87": -65536,
+ "103:87": -65536,
+ "104:87": -65536,
+ "105:87": -65536,
+ "106:87": 402653184,
+ "107:87": 268435456,
+ "108:87": 402653184,
+ "109:87": 268435456,
+ "110:87": 402653184,
+ "111:87": 268435456,
+ "112:87": 402653184,
+ "113:87": 268435456,
+ "114:87": 402653184,
+ "115:87": 268435456,
+ "116:87": 402653184,
+ "117:87": 268435456,
+ "118:87": 402653184,
+ "119:87": 268435456,
+ "120:87": 402653184,
+ "121:87": 268435456,
+ "122:87": 402653184,
+ "123:87": 268435456,
+ "124:87": 402653184,
+ "125:87": 268435456,
+ "126:87": 402653184,
+ "127:87": 268435456,
+ "0:88": 268435456,
+ "1:88": 402653184,
+ "2:88": 268435456,
+ "3:88": 402653184,
+ "4:88": 268435456,
+ "5:88": 402653184,
+ "6:88": 268435456,
+ "7:88": 402653184,
+ "8:88": 268435456,
+ "9:88": 402653184,
+ "10:88": 268435456,
+ "11:88": 402653184,
+ "12:88": 268435456,
+ "13:88": 402653184,
+ "14:88": 268435456,
+ "15:88": 402653184,
+ "16:88": 268435456,
+ "17:88": 402653184,
+ "18:88": 268435456,
+ "19:88": 402653184,
+ "20:88": 268435456,
+ "21:88": 402653184,
+ "22:88": -9288933,
+ "23:88": -9288933,
+ "24:88": -9288933,
+ "25:88": -9288933,
+ "26:88": -9288933,
+ "27:88": -9288933,
+ "28:88": -9288933,
+ "29:88": -1,
+ "30:88": -1,
+ "31:88": -1,
+ "32:88": -9288933,
+ "33:88": -9288933,
+ "34:88": -9288933,
+ "35:88": -9288933,
+ "36:88": -9288933,
+ "37:88": -9288933,
+ "38:88": -9288933,
+ "39:88": -9288933,
+ "40:88": -9288933,
+ "41:88": -9288933,
+ "42:88": -9288933,
+ "43:88": -9288933,
+ "44:88": -9288933,
+ "45:88": -9288933,
+ "46:88": -9288933,
+ "47:88": -9288933,
+ "48:88": -9288933,
+ "49:88": -9288933,
+ "50:88": -9288933,
+ "51:88": -9288933,
+ "52:88": -9288933,
+ "53:88": -9288933,
+ "54:88": -9288933,
+ "55:88": -9288933,
+ "56:88": -9288933,
+ "57:88": -9288933,
+ "58:88": -9288933,
+ "59:88": -9288933,
+ "60:88": -9288933,
+ "61:88": -9288933,
+ "62:88": -9288933,
+ "63:88": -9288933,
+ "64:88": -9288933,
+ "65:88": -9288933,
+ "66:88": -9288933,
+ "67:88": -9288933,
+ "68:88": -9288933,
+ "69:88": -9288933,
+ "70:88": -9288933,
+ "71:88": -9288933,
+ "72:88": -9288933,
+ "73:88": -16745472,
+ "74:88": -16745472,
+ "75:88": -16745472,
+ "76:88": -9288933,
+ "77:88": -9288933,
+ "78:88": -9288933,
+ "79:88": -9288933,
+ "80:88": -9288933,
+ "81:88": -9288933,
+ "82:88": -9288933,
+ "83:88": -9288933,
+ "84:88": 268435456,
+ "85:88": 402653184,
+ "86:88": 268435456,
+ "87:88": 402653184,
+ "88:88": -65536,
+ "89:88": -65536,
+ "90:88": -65536,
+ "91:88": -65536,
+ "92:88": -65536,
+ "93:88": -65536,
+ "94:88": -65536,
+ "95:88": -65536,
+ "96:88": -65536,
+ "97:88": -65536,
+ "98:88": -65536,
+ "99:88": -65536,
+ "100:88": -65536,
+ "101:88": -65536,
+ "102:88": -65536,
+ "103:88": -65536,
+ "104:88": -65536,
+ "105:88": -65536,
+ "106:88": 268435456,
+ "107:88": 402653184,
+ "108:88": 268435456,
+ "109:88": 402653184,
+ "110:88": 268435456,
+ "111:88": 402653184,
+ "112:88": 268435456,
+ "113:88": 402653184,
+ "114:88": 268435456,
+ "115:88": 402653184,
+ "116:88": 268435456,
+ "117:88": 402653184,
+ "118:88": 268435456,
+ "119:88": 402653184,
+ "120:88": 268435456,
+ "121:88": 402653184,
+ "122:88": 268435456,
+ "123:88": 402653184,
+ "124:88": 268435456,
+ "125:88": 402653184,
+ "126:88": 268435456,
+ "127:88": 402653184,
+ "0:89": 402653184,
+ "1:89": 268435456,
+ "2:89": 402653184,
+ "3:89": 268435456,
+ "4:89": 402653184,
+ "5:89": 268435456,
+ "6:89": 402653184,
+ "7:89": 268435456,
+ "8:89": 402653184,
+ "9:89": 268435456,
+ "10:89": 402653184,
+ "11:89": 268435456,
+ "12:89": 402653184,
+ "13:89": 268435456,
+ "14:89": 402653184,
+ "15:89": 268435456,
+ "16:89": 402653184,
+ "17:89": 268435456,
+ "18:89": 402653184,
+ "19:89": 268435456,
+ "20:89": 402653184,
+ "21:89": 268435456,
+ "22:89": -9288933,
+ "23:89": -9288933,
+ "24:89": -9288933,
+ "25:89": -9288933,
+ "26:89": -9288933,
+ "27:89": -9288933,
+ "28:89": -9288933,
+ "29:89": -1,
+ "30:89": -1,
+ "31:89": -1,
+ "32:89": -9288933,
+ "33:89": -9288933,
+ "34:89": -9288933,
+ "35:89": -9288933,
+ "36:89": -9288933,
+ "37:89": -9288933,
+ "38:89": -9288933,
+ "39:89": -9288933,
+ "40:89": -9288933,
+ "41:89": -9288933,
+ "42:89": -9288933,
+ "43:89": -9288933,
+ "44:89": -9288933,
+ "45:89": -9288933,
+ "46:89": -9288933,
+ "47:89": -9288933,
+ "48:89": -9288933,
+ "49:89": -9288933,
+ "50:89": -9288933,
+ "51:89": -9288933,
+ "52:89": -9288933,
+ "53:89": -9288933,
+ "54:89": -9288933,
+ "55:89": -9288933,
+ "56:89": -9288933,
+ "57:89": -9288933,
+ "58:89": -9288933,
+ "59:89": -9288933,
+ "60:89": -9288933,
+ "61:89": -9288933,
+ "62:89": -9288933,
+ "63:89": -9288933,
+ "64:89": -9288933,
+ "65:89": -9288933,
+ "66:89": -9288933,
+ "67:89": -9288933,
+ "68:89": -9288933,
+ "69:89": -9288933,
+ "70:89": -9288933,
+ "71:89": -9288933,
+ "72:89": -9288933,
+ "73:89": -16745472,
+ "74:89": -16745472,
+ "75:89": -16745472,
+ "76:89": -9288933,
+ "77:89": -9288933,
+ "78:89": -9288933,
+ "79:89": -9288933,
+ "80:89": -9288933,
+ "81:89": -9288933,
+ "82:89": -9288933,
+ "83:89": -9288933,
+ "84:89": 402653184,
+ "85:89": 268435456,
+ "86:89": 402653184,
+ "87:89": 268435456,
+ "88:89": -65536,
+ "89:89": -65536,
+ "90:89": -65536,
+ "91:89": -65536,
+ "92:89": -65536,
+ "93:89": -65536,
+ "94:89": -65536,
+ "95:89": -65536,
+ "96:89": -65536,
+ "97:89": -65536,
+ "98:89": -65536,
+ "99:89": -65536,
+ "100:89": -65536,
+ "101:89": -65536,
+ "102:89": -65536,
+ "103:89": -65536,
+ "104:89": -65536,
+ "105:89": -65536,
+ "106:89": 402653184,
+ "107:89": 268435456,
+ "108:89": 402653184,
+ "109:89": 268435456,
+ "110:89": 402653184,
+ "111:89": 268435456,
+ "112:89": 402653184,
+ "113:89": 268435456,
+ "114:89": 402653184,
+ "115:89": 268435456,
+ "116:89": 402653184,
+ "117:89": 268435456,
+ "118:89": 402653184,
+ "119:89": 268435456,
+ "120:89": 402653184,
+ "121:89": 268435456,
+ "122:89": 402653184,
+ "123:89": 268435456,
+ "124:89": 402653184,
+ "125:89": 268435456,
+ "126:89": 402653184,
+ "127:89": 268435456,
+ "0:90": 268435456,
+ "1:90": 402653184,
+ "2:90": 268435456,
+ "3:90": 402653184,
+ "4:90": 268435456,
+ "5:90": 402653184,
+ "6:90": 268435456,
+ "7:90": 402653184,
+ "8:90": 268435456,
+ "9:90": 402653184,
+ "10:90": 268435456,
+ "11:90": 402653184,
+ "12:90": 268435456,
+ "13:90": 402653184,
+ "14:90": 268435456,
+ "15:90": 402653184,
+ "16:90": 268435456,
+ "17:90": 402653184,
+ "18:90": 268435456,
+ "19:90": 402653184,
+ "20:90": 268435456,
+ "21:90": 402653184,
+ "22:90": -9288933,
+ "23:90": -9288933,
+ "24:90": -9288933,
+ "25:90": -9288933,
+ "26:90": -9288933,
+ "27:90": -9288933,
+ "28:90": -9288933,
+ "29:90": -9288933,
+ "30:90": -9288933,
+ "31:90": -9288933,
+ "32:90": -9288933,
+ "33:90": -9288933,
+ "34:90": -9288933,
+ "35:90": -9288933,
+ "36:90": -9288933,
+ "37:90": -9288933,
+ "38:90": -9288933,
+ "39:90": -9288933,
+ "40:90": -9288933,
+ "41:90": -9288933,
+ "42:90": -9288933,
+ "43:90": -9288933,
+ "44:90": -9288933,
+ "45:90": -9288933,
+ "46:90": -9288933,
+ "47:90": -9288933,
+ "48:90": -9288933,
+ "49:90": -9288933,
+ "50:90": -9288933,
+ "51:90": -9288933,
+ "52:90": -9288933,
+ "53:90": -9288933,
+ "54:90": -9288933,
+ "55:90": -9288933,
+ "56:90": -9288933,
+ "57:90": -9288933,
+ "58:90": -9288933,
+ "59:90": -9288933,
+ "60:90": -9288933,
+ "61:90": -9288933,
+ "62:90": 268435456,
+ "63:90": 402653184,
+ "64:90": 268435456,
+ "65:90": 402653184,
+ "66:90": -9288933,
+ "67:90": -9288933,
+ "68:90": -9288933,
+ "69:90": -9288933,
+ "70:90": -9288933,
+ "71:90": -9288933,
+ "72:90": -9288933,
+ "73:90": -9288933,
+ "74:90": -9288933,
+ "75:90": -9288933,
+ "76:90": -9288933,
+ "77:90": -9288933,
+ "78:90": -9288933,
+ "79:90": -9288933,
+ "80:90": -9288933,
+ "81:90": -9288933,
+ "82:90": -9288933,
+ "83:90": -9288933,
+ "84:90": 268435456,
+ "85:90": 402653184,
+ "86:90": 268435456,
+ "87:90": 402653184,
+ "88:90": -65536,
+ "89:90": -65536,
+ "90:90": -65536,
+ "91:90": -65536,
+ "92:90": -65536,
+ "93:90": -65536,
+ "94:90": -65536,
+ "95:90": -65536,
+ "96:90": -65536,
+ "97:90": -65536,
+ "98:90": -65536,
+ "99:90": -65536,
+ "100:90": -65536,
+ "101:90": -65536,
+ "102:90": -65536,
+ "103:90": -65536,
+ "104:90": -65536,
+ "105:90": -65536,
+ "106:90": 268435456,
+ "107:90": 402653184,
+ "108:90": 268435456,
+ "109:90": 402653184,
+ "110:90": 268435456,
+ "111:90": 402653184,
+ "112:90": 268435456,
+ "113:90": 402653184,
+ "114:90": 268435456,
+ "115:90": 402653184,
+ "116:90": 268435456,
+ "117:90": 402653184,
+ "118:90": 268435456,
+ "119:90": 402653184,
+ "120:90": 268435456,
+ "121:90": 402653184,
+ "122:90": 268435456,
+ "123:90": 402653184,
+ "124:90": 268435456,
+ "125:90": 402653184,
+ "126:90": 268435456,
+ "127:90": 402653184,
+ "0:91": 402653184,
+ "1:91": 268435456,
+ "2:91": 402653184,
+ "3:91": 268435456,
+ "4:91": 402653184,
+ "5:91": 268435456,
+ "6:91": 402653184,
+ "7:91": 268435456,
+ "8:91": 402653184,
+ "9:91": 268435456,
+ "10:91": 402653184,
+ "11:91": 268435456,
+ "12:91": 402653184,
+ "13:91": 268435456,
+ "14:91": 402653184,
+ "15:91": 268435456,
+ "16:91": 402653184,
+ "17:91": 268435456,
+ "18:91": 402653184,
+ "19:91": 268435456,
+ "20:91": 402653184,
+ "21:91": 268435456,
+ "22:91": -9288933,
+ "23:91": -9288933,
+ "24:91": -9288933,
+ "25:91": -9288933,
+ "26:91": -9288933,
+ "27:91": -9288933,
+ "28:91": -9288933,
+ "29:91": -9288933,
+ "30:91": -9288933,
+ "31:91": -9288933,
+ "32:91": -9288933,
+ "33:91": -9288933,
+ "34:91": -9288933,
+ "35:91": -9288933,
+ "36:91": -9288933,
+ "37:91": -9288933,
+ "38:91": -9288933,
+ "39:91": -9288933,
+ "40:91": -9288933,
+ "41:91": -9288933,
+ "42:91": -9288933,
+ "43:91": -9288933,
+ "44:91": -9288933,
+ "45:91": -9288933,
+ "46:91": -9288933,
+ "47:91": -9288933,
+ "48:91": -9288933,
+ "49:91": -9288933,
+ "50:91": -9288933,
+ "51:91": -9288933,
+ "52:91": -9288933,
+ "53:91": -9288933,
+ "54:91": -9288933,
+ "55:91": -9288933,
+ "56:91": -9288933,
+ "57:91": -9288933,
+ "58:91": -9288933,
+ "59:91": -9288933,
+ "60:91": -9288933,
+ "61:91": -9288933,
+ "62:91": 402653184,
+ "63:91": 268435456,
+ "64:91": 402653184,
+ "65:91": 268435456,
+ "66:91": -9288933,
+ "67:91": -9288933,
+ "68:91": -9288933,
+ "69:91": -9288933,
+ "70:91": -9288933,
+ "71:91": -9288933,
+ "72:91": -9288933,
+ "73:91": -9288933,
+ "74:91": -9288933,
+ "75:91": -9288933,
+ "76:91": -9288933,
+ "77:91": -9288933,
+ "78:91": -9288933,
+ "79:91": -9288933,
+ "80:91": -9288933,
+ "81:91": -9288933,
+ "82:91": -9288933,
+ "83:91": -9288933,
+ "84:91": 402653184,
+ "85:91": 268435456,
+ "86:91": 402653184,
+ "87:91": 268435456,
+ "88:91": -65536,
+ "89:91": -65536,
+ "90:91": -65536,
+ "91:91": -65536,
+ "92:91": -65536,
+ "93:91": -65536,
+ "94:91": -65536,
+ "95:91": -65536,
+ "96:91": -65536,
+ "97:91": -65536,
+ "98:91": -65536,
+ "99:91": -65536,
+ "100:91": -65536,
+ "101:91": -65536,
+ "102:91": -65536,
+ "103:91": -65536,
+ "104:91": -65536,
+ "105:91": -65536,
+ "106:91": 402653184,
+ "107:91": 268435456,
+ "108:91": 402653184,
+ "109:91": 268435456,
+ "110:91": 402653184,
+ "111:91": 268435456,
+ "112:91": 402653184,
+ "113:91": 268435456,
+ "114:91": 402653184,
+ "115:91": 268435456,
+ "116:91": 402653184,
+ "117:91": 268435456,
+ "118:91": 402653184,
+ "119:91": 268435456,
+ "120:91": 402653184,
+ "121:91": 268435456,
+ "122:91": 402653184,
+ "123:91": 268435456,
+ "124:91": 402653184,
+ "125:91": 268435456,
+ "126:91": 402653184,
+ "127:91": 268435456,
+ "0:92": 268435456,
+ "1:92": 402653184,
+ "2:92": 268435456,
+ "3:92": 402653184,
+ "4:92": 268435456,
+ "5:92": 402653184,
+ "6:92": 268435456,
+ "7:92": 402653184,
+ "8:92": 268435456,
+ "9:92": 402653184,
+ "10:92": 268435456,
+ "11:92": 402653184,
+ "12:92": 268435456,
+ "13:92": 402653184,
+ "14:92": 268435456,
+ "15:92": 402653184,
+ "16:92": 268435456,
+ "17:92": 402653184,
+ "18:92": 268435456,
+ "19:92": 402653184,
+ "20:92": 268435456,
+ "21:92": 402653184,
+ "22:92": -9288933,
+ "23:92": -9288933,
+ "24:92": -9288933,
+ "25:92": -9288933,
+ "26:92": -9288933,
+ "27:92": -9288933,
+ "28:92": -9288933,
+ "29:92": -9288933,
+ "30:92": -9288933,
+ "31:92": -9288933,
+ "32:92": -9288933,
+ "33:92": -9288933,
+ "34:92": -9288933,
+ "35:92": -9288933,
+ "36:92": -9288933,
+ "37:92": -9288933,
+ "38:92": -9288933,
+ "39:92": -9288933,
+ "40:92": -9288933,
+ "41:92": -9288933,
+ "42:92": -9288933,
+ "43:92": -9288933,
+ "44:92": -9288933,
+ "45:92": -9288933,
+ "46:92": -9288933,
+ "47:92": -9288933,
+ "48:92": -9288933,
+ "49:92": -9288933,
+ "50:92": -9288933,
+ "51:92": -9288933,
+ "52:92": -9288933,
+ "53:92": -9288933,
+ "54:92": -9288933,
+ "55:92": -9288933,
+ "56:92": -9288933,
+ "57:92": -9288933,
+ "58:92": -9288933,
+ "59:92": -9288933,
+ "60:92": -9288933,
+ "61:92": -9288933,
+ "62:92": 268435456,
+ "63:92": 402653184,
+ "64:92": 268435456,
+ "65:92": 402653184,
+ "66:92": -9288933,
+ "67:92": -9288933,
+ "68:92": -9288933,
+ "69:92": -9288933,
+ "70:92": -9288933,
+ "71:92": -9288933,
+ "72:92": -9288933,
+ "73:92": -9288933,
+ "74:92": -9288933,
+ "75:92": -9288933,
+ "76:92": -9288933,
+ "77:92": -9288933,
+ "78:92": -9288933,
+ "79:92": -9288933,
+ "80:92": -9288933,
+ "81:92": -9288933,
+ "82:92": -9288933,
+ "83:92": -9288933,
+ "84:92": 268435456,
+ "85:92": 402653184,
+ "86:92": 268435456,
+ "87:92": 402653184,
+ "88:92": -65536,
+ "89:92": -65536,
+ "90:92": -65536,
+ "91:92": -65536,
+ "92:92": -65536,
+ "93:92": -65536,
+ "94:92": -65536,
+ "95:92": -65536,
+ "96:92": -65536,
+ "97:92": -65536,
+ "98:92": -65536,
+ "99:92": -65536,
+ "100:92": -65536,
+ "101:92": -65536,
+ "102:92": -65536,
+ "103:92": -65536,
+ "104:92": -65536,
+ "105:92": -65536,
+ "106:92": 268435456,
+ "107:92": 402653184,
+ "108:92": 268435456,
+ "109:92": 402653184,
+ "110:92": 268435456,
+ "111:92": 402653184,
+ "112:92": 268435456,
+ "113:92": 402653184,
+ "114:92": 268435456,
+ "115:92": 402653184,
+ "116:92": 268435456,
+ "117:92": 402653184,
+ "118:92": 268435456,
+ "119:92": 402653184,
+ "120:92": 268435456,
+ "121:92": 402653184,
+ "122:92": 268435456,
+ "123:92": 402653184,
+ "124:92": 268435456,
+ "125:92": 402653184,
+ "126:92": 268435456,
+ "127:92": 402653184,
+ "0:93": 402653184,
+ "1:93": 268435456,
+ "2:93": 402653184,
+ "3:93": 268435456,
+ "4:93": 402653184,
+ "5:93": 268435456,
+ "6:93": 402653184,
+ "7:93": 268435456,
+ "8:93": 402653184,
+ "9:93": 268435456,
+ "10:93": 402653184,
+ "11:93": 268435456,
+ "12:93": 402653184,
+ "13:93": 268435456,
+ "14:93": 402653184,
+ "15:93": 268435456,
+ "16:93": 402653184,
+ "17:93": 268435456,
+ "18:93": 402653184,
+ "19:93": 268435456,
+ "20:93": 402653184,
+ "21:93": 268435456,
+ "22:93": -9288933,
+ "23:93": -9288933,
+ "24:93": -9288933,
+ "25:93": -9288933,
+ "26:93": -9288933,
+ "27:93": -9288933,
+ "28:93": -9288933,
+ "29:93": -9288933,
+ "30:93": -9288933,
+ "31:93": -9288933,
+ "32:93": -9288933,
+ "33:93": -9288933,
+ "34:93": -9288933,
+ "35:93": -9288933,
+ "36:93": -9288933,
+ "37:93": -9288933,
+ "38:93": -9288933,
+ "39:93": -9288933,
+ "40:93": -9288933,
+ "41:93": -9288933,
+ "42:93": -9288933,
+ "43:93": -9288933,
+ "44:93": -9288933,
+ "45:93": -9288933,
+ "46:93": -9288933,
+ "47:93": -9288933,
+ "48:93": -9288933,
+ "49:93": -9288933,
+ "50:93": -9288933,
+ "51:93": -9288933,
+ "52:93": -9288933,
+ "53:93": -9288933,
+ "54:93": -9288933,
+ "55:93": -9288933,
+ "56:93": -9288933,
+ "57:93": -9288933,
+ "58:93": -9288933,
+ "59:93": -9288933,
+ "60:93": -9288933,
+ "61:93": -9288933,
+ "62:93": 402653184,
+ "63:93": 268435456,
+ "64:93": 402653184,
+ "65:93": 268435456,
+ "66:93": -9288933,
+ "67:93": -9288933,
+ "68:93": -9288933,
+ "69:93": -9288933,
+ "70:93": -9288933,
+ "71:93": -9288933,
+ "72:93": -9288933,
+ "73:93": -9288933,
+ "74:93": -9288933,
+ "75:93": -9288933,
+ "76:93": -9288933,
+ "77:93": -9288933,
+ "78:93": -9288933,
+ "79:93": -9288933,
+ "80:93": -9288933,
+ "81:93": -9288933,
+ "82:93": -9288933,
+ "83:93": -9288933,
+ "84:93": 402653184,
+ "85:93": 268435456,
+ "86:93": 402653184,
+ "87:93": 268435456,
+ "88:93": -65536,
+ "89:93": -65536,
+ "90:93": -65536,
+ "91:93": -65536,
+ "92:93": -65536,
+ "93:93": -65536,
+ "94:93": -65536,
+ "95:93": -65536,
+ "96:93": -65536,
+ "97:93": -65536,
+ "98:93": -65536,
+ "99:93": -65536,
+ "100:93": -65536,
+ "101:93": -65536,
+ "102:93": -65536,
+ "103:93": -65536,
+ "104:93": -65536,
+ "105:93": -65536,
+ "106:93": 402653184,
+ "107:93": 268435456,
+ "108:93": 402653184,
+ "109:93": 268435456,
+ "110:93": 402653184,
+ "111:93": 268435456,
+ "112:93": 402653184,
+ "113:93": 268435456,
+ "114:93": 402653184,
+ "115:93": 268435456,
+ "116:93": 402653184,
+ "117:93": 268435456,
+ "118:93": 402653184,
+ "119:93": 268435456,
+ "120:93": 402653184,
+ "121:93": 268435456,
+ "122:93": 402653184,
+ "123:93": 268435456,
+ "124:93": 402653184,
+ "125:93": 268435456,
+ "126:93": 402653184,
+ "127:93": 268435456,
+ "0:94": 268435456,
+ "1:94": 402653184,
+ "2:94": 268435456,
+ "3:94": 402653184,
+ "4:94": 268435456,
+ "5:94": 402653184,
+ "6:94": 268435456,
+ "7:94": 402653184,
+ "8:94": 268435456,
+ "9:94": 402653184,
+ "10:94": 268435456,
+ "11:94": 402653184,
+ "12:94": 268435456,
+ "13:94": 402653184,
+ "14:94": 268435456,
+ "15:94": 402653184,
+ "16:94": 268435456,
+ "17:94": 402653184,
+ "18:94": 268435456,
+ "19:94": 402653184,
+ "20:94": 268435456,
+ "21:94": 402653184,
+ "22:94": -9288933,
+ "23:94": -9288933,
+ "24:94": -9288933,
+ "25:94": -9288933,
+ "26:94": -9288933,
+ "27:94": -9288933,
+ "28:94": -9288933,
+ "29:94": -9288933,
+ "30:94": -9288933,
+ "31:94": -9288933,
+ "32:94": -9288933,
+ "33:94": -9288933,
+ "34:94": -9288933,
+ "35:94": -9288933,
+ "36:94": -9288933,
+ "37:94": -9288933,
+ "38:94": -9288933,
+ "39:94": -9288933,
+ "40:94": -9288933,
+ "41:94": -9288933,
+ "42:94": -9288933,
+ "43:94": -9288933,
+ "44:94": -9288933,
+ "45:94": -9288933,
+ "46:94": -9288933,
+ "47:94": -9288933,
+ "48:94": -9288933,
+ "49:94": -9288933,
+ "50:94": -9288933,
+ "51:94": -9288933,
+ "52:94": -9288933,
+ "53:94": -9288933,
+ "54:94": -9288933,
+ "55:94": -9288933,
+ "56:94": -9288933,
+ "57:94": -9288933,
+ "58:94": -9288933,
+ "59:94": -9288933,
+ "60:94": -9288933,
+ "61:94": -9288933,
+ "62:94": 268435456,
+ "63:94": 402653184,
+ "64:94": 268435456,
+ "65:94": 402653184,
+ "66:94": -9288933,
+ "67:94": -9288933,
+ "68:94": -9288933,
+ "69:94": -9288933,
+ "70:94": -9288933,
+ "71:94": -9288933,
+ "72:94": -9288933,
+ "73:94": -9288933,
+ "74:94": -9288933,
+ "75:94": -9288933,
+ "76:94": -9288933,
+ "77:94": -9288933,
+ "78:94": -9288933,
+ "79:94": -9288933,
+ "80:94": -9288933,
+ "81:94": -9288933,
+ "82:94": -9288933,
+ "83:94": -9288933,
+ "84:94": 268435456,
+ "85:94": 402653184,
+ "86:94": 268435456,
+ "87:94": 402653184,
+ "88:94": -65536,
+ "89:94": -65536,
+ "90:94": -65536,
+ "91:94": -65536,
+ "92:94": -65536,
+ "93:94": -65536,
+ "94:94": -65536,
+ "95:94": -65536,
+ "96:94": -65536,
+ "97:94": -65536,
+ "98:94": -65536,
+ "99:94": -65536,
+ "100:94": -65536,
+ "101:94": -65536,
+ "102:94": -65536,
+ "103:94": -65536,
+ "104:94": -65536,
+ "105:94": -65536,
+ "106:94": 268435456,
+ "107:94": 402653184,
+ "108:94": 268435456,
+ "109:94": 402653184,
+ "110:94": 268435456,
+ "111:94": 402653184,
+ "112:94": 268435456,
+ "113:94": 402653184,
+ "114:94": 268435456,
+ "115:94": 402653184,
+ "116:94": 268435456,
+ "117:94": 402653184,
+ "118:94": 268435456,
+ "119:94": 402653184,
+ "120:94": 268435456,
+ "121:94": 402653184,
+ "122:94": 268435456,
+ "123:94": 402653184,
+ "124:94": 268435456,
+ "125:94": 402653184,
+ "126:94": 268435456,
+ "127:94": 402653184,
+ "0:95": 402653184,
+ "1:95": 268435456,
+ "2:95": 402653184,
+ "3:95": 268435456,
+ "4:95": 402653184,
+ "5:95": 268435456,
+ "6:95": 402653184,
+ "7:95": 268435456,
+ "8:95": 402653184,
+ "9:95": 268435456,
+ "10:95": 402653184,
+ "11:95": 268435456,
+ "12:95": 402653184,
+ "13:95": 268435456,
+ "14:95": 402653184,
+ "15:95": 268435456,
+ "16:95": 402653184,
+ "17:95": 268435456,
+ "18:95": 402653184,
+ "19:95": 268435456,
+ "20:95": 402653184,
+ "21:95": 268435456,
+ "22:95": -9288933,
+ "23:95": -9288933,
+ "24:95": -9288933,
+ "25:95": -9288933,
+ "26:95": -9288933,
+ "27:95": -9288933,
+ "28:95": -9288933,
+ "29:95": -9288933,
+ "30:95": -9288933,
+ "31:95": -9288933,
+ "32:95": -9288933,
+ "33:95": -9288933,
+ "34:95": -9288933,
+ "35:95": -9288933,
+ "36:95": -9288933,
+ "37:95": -9288933,
+ "38:95": -9288933,
+ "39:95": -9288933,
+ "40:95": 402653184,
+ "41:95": 268435456,
+ "42:95": 402653184,
+ "43:95": 268435456,
+ "44:95": 402653184,
+ "45:95": 268435456,
+ "46:95": 402653184,
+ "47:95": 268435456,
+ "48:95": 402653184,
+ "49:95": 268435456,
+ "50:95": -1710797,
+ "51:95": -1710797,
+ "52:95": -1710797,
+ "53:95": -1710797,
+ "54:95": -1710797,
+ "55:95": -1710797,
+ "56:95": -1710797,
+ "57:95": 268435456,
+ "58:95": 402653184,
+ "59:95": 268435456,
+ "60:95": 402653184,
+ "61:95": 268435456,
+ "62:95": 402653184,
+ "63:95": 268435456,
+ "64:95": 402653184,
+ "65:95": 268435456,
+ "66:95": 402653184,
+ "67:95": 268435456,
+ "68:95": 402653184,
+ "69:95": 268435456,
+ "70:95": 402653184,
+ "71:95": 268435456,
+ "72:95": -9288933,
+ "73:95": -9288933,
+ "74:95": -9288933,
+ "75:95": -9288933,
+ "76:95": -9288933,
+ "77:95": -9288933,
+ "78:95": -9288933,
+ "79:95": 268435456,
+ "80:95": 402653184,
+ "81:95": 268435456,
+ "82:95": 402653184,
+ "83:95": 268435456,
+ "84:95": 402653184,
+ "85:95": 268435456,
+ "86:95": 402653184,
+ "87:95": 268435456,
+ "88:95": 402653184,
+ "89:95": 268435456,
+ "90:95": 402653184,
+ "91:95": 268435456,
+ "92:95": 402653184,
+ "93:95": 268435456,
+ "94:95": 402653184,
+ "95:95": 268435456,
+ "96:95": 402653184,
+ "97:95": 268435456,
+ "98:95": 402653184,
+ "99:95": 268435456,
+ "100:95": 402653184,
+ "101:95": 268435456,
+ "102:95": 402653184,
+ "103:95": 268435456,
+ "104:95": 402653184,
+ "105:95": 268435456,
+ "106:95": 402653184,
+ "107:95": 268435456,
+ "108:95": 402653184,
+ "109:95": 268435456,
+ "110:95": 402653184,
+ "111:95": 268435456,
+ "112:95": 402653184,
+ "113:95": 268435456,
+ "114:95": 402653184,
+ "115:95": 268435456,
+ "116:95": 402653184,
+ "117:95": 268435456,
+ "118:95": 402653184,
+ "119:95": 268435456,
+ "120:95": 402653184,
+ "121:95": 268435456,
+ "122:95": 402653184,
+ "123:95": 268435456,
+ "124:95": 402653184,
+ "125:95": 268435456,
+ "126:95": 402653184,
+ "127:95": 268435456,
+ "0:96": 268435456,
+ "1:96": 402653184,
+ "2:96": 268435456,
+ "3:96": 402653184,
+ "4:96": 268435456,
+ "5:96": 402653184,
+ "6:96": 268435456,
+ "7:96": 402653184,
+ "8:96": 268435456,
+ "9:96": 402653184,
+ "10:96": 268435456,
+ "11:96": 402653184,
+ "12:96": 268435456,
+ "13:96": 402653184,
+ "14:96": 268435456,
+ "15:96": 402653184,
+ "16:96": 268435456,
+ "17:96": 402653184,
+ "18:96": 268435456,
+ "19:96": 402653184,
+ "20:96": 268435456,
+ "21:96": 402653184,
+ "22:96": -9288933,
+ "23:96": -9288933,
+ "24:96": -9288933,
+ "25:96": -9288933,
+ "26:96": -9288933,
+ "27:96": -9288933,
+ "28:96": -9288933,
+ "29:96": -9288933,
+ "30:96": -9288933,
+ "31:96": -9288933,
+ "32:96": -9288933,
+ "33:96": -9288933,
+ "34:96": -9288933,
+ "35:96": -9288933,
+ "36:96": -9288933,
+ "37:96": -9288933,
+ "38:96": -9288933,
+ "39:96": -9288933,
+ "40:96": 268435456,
+ "41:96": 402653184,
+ "42:96": 268435456,
+ "43:96": 402653184,
+ "44:96": 268435456,
+ "45:96": 402653184,
+ "46:96": 268435456,
+ "47:96": 402653184,
+ "48:96": 268435456,
+ "49:96": 402653184,
+ "50:96": -1710797,
+ "51:96": -1710797,
+ "52:96": -1710797,
+ "53:96": -1710797,
+ "54:96": -1710797,
+ "55:96": -1710797,
+ "56:96": -1710797,
+ "57:96": 402653184,
+ "58:96": 268435456,
+ "59:96": 402653184,
+ "60:96": 268435456,
+ "61:96": 402653184,
+ "62:96": 268435456,
+ "63:96": 402653184,
+ "64:96": 268435456,
+ "65:96": 402653184,
+ "66:96": 268435456,
+ "67:96": 402653184,
+ "68:96": 268435456,
+ "69:96": 402653184,
+ "70:96": 268435456,
+ "71:96": 402653184,
+ "72:96": -9288933,
+ "73:96": -9288933,
+ "74:96": -9288933,
+ "75:96": -9288933,
+ "76:96": -9288933,
+ "77:96": -9288933,
+ "78:96": -9288933,
+ "79:96": 402653184,
+ "80:96": 268435456,
+ "81:96": 402653184,
+ "82:96": 268435456,
+ "83:96": 402653184,
+ "84:96": 268435456,
+ "85:96": 402653184,
+ "86:96": 268435456,
+ "87:96": 402653184,
+ "88:96": 268435456,
+ "89:96": 402653184,
+ "90:96": 268435456,
+ "91:96": 402653184,
+ "92:96": 268435456,
+ "93:96": 402653184,
+ "94:96": 268435456,
+ "95:96": 402653184,
+ "96:96": 268435456,
+ "97:96": 402653184,
+ "98:96": 268435456,
+ "99:96": 402653184,
+ "100:96": 268435456,
+ "101:96": 402653184,
+ "102:96": 268435456,
+ "103:96": 402653184,
+ "104:96": 268435456,
+ "105:96": 402653184,
+ "106:96": 268435456,
+ "107:96": 402653184,
+ "108:96": 268435456,
+ "109:96": 402653184,
+ "110:96": 268435456,
+ "111:96": 402653184,
+ "112:96": 268435456,
+ "113:96": 402653184,
+ "114:96": 268435456,
+ "115:96": 402653184,
+ "116:96": 268435456,
+ "117:96": 402653184,
+ "118:96": 268435456,
+ "119:96": 402653184,
+ "120:96": 268435456,
+ "121:96": 402653184,
+ "122:96": 268435456,
+ "123:96": 402653184,
+ "124:96": 268435456,
+ "125:96": 402653184,
+ "126:96": 268435456,
+ "127:96": 402653184,
+ "0:97": 402653184,
+ "1:97": 268435456,
+ "2:97": 402653184,
+ "3:97": 268435456,
+ "4:97": 402653184,
+ "5:97": 268435456,
+ "6:97": 402653184,
+ "7:97": 268435456,
+ "8:97": 402653184,
+ "9:97": 268435456,
+ "10:97": 402653184,
+ "11:97": 268435456,
+ "12:97": 402653184,
+ "13:97": 268435456,
+ "14:97": 402653184,
+ "15:97": 268435456,
+ "16:97": 402653184,
+ "17:97": 268435456,
+ "18:97": 402653184,
+ "19:97": 268435456,
+ "20:97": 402653184,
+ "21:97": 268435456,
+ "22:97": -9288933,
+ "23:97": -9288933,
+ "24:97": -9288933,
+ "25:97": -9288933,
+ "26:97": -9288933,
+ "27:97": -9288933,
+ "28:97": -9288933,
+ "29:97": -9288933,
+ "30:97": -9288933,
+ "31:97": -9288933,
+ "32:97": -9288933,
+ "33:97": -9288933,
+ "34:97": -9288933,
+ "35:97": -9288933,
+ "36:97": -9288933,
+ "37:97": -9288933,
+ "38:97": -9288933,
+ "39:97": -9288933,
+ "40:97": 402653184,
+ "41:97": 268435456,
+ "42:97": 402653184,
+ "43:97": 268435456,
+ "44:97": 402653184,
+ "45:97": 268435456,
+ "46:97": 402653184,
+ "47:97": 268435456,
+ "48:97": 402653184,
+ "49:97": 268435456,
+ "50:97": -1710797,
+ "51:97": -1710797,
+ "52:97": -1710797,
+ "53:97": -1710797,
+ "54:97": -1710797,
+ "55:97": -1710797,
+ "56:97": -1710797,
+ "57:97": 268435456,
+ "58:97": 402653184,
+ "59:97": 268435456,
+ "60:97": 402653184,
+ "61:97": 268435456,
+ "62:97": 402653184,
+ "63:97": 268435456,
+ "64:97": 402653184,
+ "65:97": 268435456,
+ "66:97": 402653184,
+ "67:97": 268435456,
+ "68:97": 402653184,
+ "69:97": 268435456,
+ "70:97": 402653184,
+ "71:97": 268435456,
+ "72:97": -9288933,
+ "73:97": -9288933,
+ "74:97": -9288933,
+ "75:97": -9288933,
+ "76:97": -9288933,
+ "77:97": -9288933,
+ "78:97": -9288933,
+ "79:97": 268435456,
+ "80:97": 402653184,
+ "81:97": 268435456,
+ "82:97": 402653184,
+ "83:97": 268435456,
+ "84:97": 402653184,
+ "85:97": 268435456,
+ "86:97": 402653184,
+ "87:97": 268435456,
+ "88:97": 402653184,
+ "89:97": 268435456,
+ "90:97": 402653184,
+ "91:97": 268435456,
+ "92:97": 402653184,
+ "93:97": 268435456,
+ "94:97": 402653184,
+ "95:97": 268435456,
+ "96:97": 402653184,
+ "97:97": 268435456,
+ "98:97": 402653184,
+ "99:97": 268435456,
+ "100:97": 402653184,
+ "101:97": 268435456,
+ "102:97": 402653184,
+ "103:97": 268435456,
+ "104:97": 402653184,
+ "105:97": 268435456,
+ "106:97": 402653184,
+ "107:97": 268435456,
+ "108:97": 402653184,
+ "109:97": 268435456,
+ "110:97": 402653184,
+ "111:97": 268435456,
+ "112:97": 402653184,
+ "113:97": 268435456,
+ "114:97": 402653184,
+ "115:97": 268435456,
+ "116:97": 402653184,
+ "117:97": 268435456,
+ "118:97": 402653184,
+ "119:97": 268435456,
+ "120:97": 402653184,
+ "121:97": 268435456,
+ "122:97": 402653184,
+ "123:97": 268435456,
+ "124:97": 402653184,
+ "125:97": 268435456,
+ "126:97": 402653184,
+ "127:97": 268435456,
+ "0:98": 268435456,
+ "1:98": 402653184,
+ "2:98": 268435456,
+ "3:98": 402653184,
+ "4:98": 268435456,
+ "5:98": 402653184,
+ "6:98": 268435456,
+ "7:98": 402653184,
+ "8:98": 268435456,
+ "9:98": 402653184,
+ "10:98": 268435456,
+ "11:98": 402653184,
+ "12:98": 268435456,
+ "13:98": 402653184,
+ "14:98": 268435456,
+ "15:98": 402653184,
+ "16:98": 268435456,
+ "17:98": 402653184,
+ "18:98": 268435456,
+ "19:98": 402653184,
+ "20:98": 268435456,
+ "21:98": 402653184,
+ "22:98": -9288933,
+ "23:98": -9288933,
+ "24:98": -9288933,
+ "25:98": -9288933,
+ "26:98": -9288933,
+ "27:98": -9288933,
+ "28:98": -9288933,
+ "29:98": -9288933,
+ "30:98": -9288933,
+ "31:98": -9288933,
+ "32:98": -9288933,
+ "33:98": -9288933,
+ "34:98": -9288933,
+ "35:98": -9288933,
+ "36:98": -9288933,
+ "37:98": -9288933,
+ "38:98": -9288933,
+ "39:98": -9288933,
+ "40:98": 268435456,
+ "41:98": 402653184,
+ "42:98": 268435456,
+ "43:98": 402653184,
+ "44:98": 268435456,
+ "45:98": 402653184,
+ "46:98": 268435456,
+ "47:98": 402653184,
+ "48:98": 268435456,
+ "49:98": 402653184,
+ "50:98": -1710797,
+ "51:98": -1710797,
+ "52:98": -1710797,
+ "53:98": -1710797,
+ "54:98": -1710797,
+ "55:98": -1710797,
+ "56:98": -1710797,
+ "57:98": 402653184,
+ "58:98": 268435456,
+ "59:98": 402653184,
+ "60:98": 268435456,
+ "61:98": 402653184,
+ "62:98": 268435456,
+ "63:98": 402653184,
+ "64:98": 268435456,
+ "65:98": 402653184,
+ "66:98": 268435456,
+ "67:98": 402653184,
+ "68:98": 268435456,
+ "69:98": 402653184,
+ "70:98": 268435456,
+ "71:98": 402653184,
+ "72:98": -9288933,
+ "73:98": -9288933,
+ "74:98": -9288933,
+ "75:98": -9288933,
+ "76:98": -9288933,
+ "77:98": -9288933,
+ "78:98": -9288933,
+ "79:98": 402653184,
+ "80:98": 268435456,
+ "81:98": 402653184,
+ "82:98": 268435456,
+ "83:98": 402653184,
+ "84:98": 268435456,
+ "85:98": 402653184,
+ "86:98": 268435456,
+ "87:98": 402653184,
+ "88:98": 268435456,
+ "89:98": 402653184,
+ "90:98": 268435456,
+ "91:98": 402653184,
+ "92:98": 268435456,
+ "93:98": 402653184,
+ "94:98": 268435456,
+ "95:98": 402653184,
+ "96:98": 268435456,
+ "97:98": 402653184,
+ "98:98": 268435456,
+ "99:98": 402653184,
+ "100:98": 268435456,
+ "101:98": 402653184,
+ "102:98": 268435456,
+ "103:98": 402653184,
+ "104:98": 268435456,
+ "105:98": 402653184,
+ "106:98": 268435456,
+ "107:98": 402653184,
+ "108:98": 268435456,
+ "109:98": 402653184,
+ "110:98": 268435456,
+ "111:98": 402653184,
+ "112:98": 268435456,
+ "113:98": 402653184,
+ "114:98": 268435456,
+ "115:98": 402653184,
+ "116:98": 268435456,
+ "117:98": 402653184,
+ "118:98": 268435456,
+ "119:98": 402653184,
+ "120:98": 268435456,
+ "121:98": 402653184,
+ "122:98": 268435456,
+ "123:98": 402653184,
+ "124:98": 268435456,
+ "125:98": 402653184,
+ "126:98": 268435456,
+ "127:98": 402653184,
+ "0:99": 402653184,
+ "1:99": 268435456,
+ "2:99": 402653184,
+ "3:99": 268435456,
+ "4:99": 402653184,
+ "5:99": 268435456,
+ "6:99": 402653184,
+ "7:99": 268435456,
+ "8:99": 402653184,
+ "9:99": 268435456,
+ "10:99": 402653184,
+ "11:99": 268435456,
+ "12:99": 402653184,
+ "13:99": 268435456,
+ "14:99": 402653184,
+ "15:99": 268435456,
+ "16:99": 402653184,
+ "17:99": 268435456,
+ "18:99": 402653184,
+ "19:99": 268435456,
+ "20:99": 402653184,
+ "21:99": 268435456,
+ "22:99": -9288933,
+ "23:99": -9288933,
+ "24:99": -9288933,
+ "25:99": -9288933,
+ "26:99": -9288933,
+ "27:99": -9288933,
+ "28:99": -9288933,
+ "29:99": -9288933,
+ "30:99": -9288933,
+ "31:99": -9288933,
+ "32:99": -9288933,
+ "33:99": -9288933,
+ "34:99": -9288933,
+ "35:99": -9288933,
+ "36:99": -9288933,
+ "37:99": -9288933,
+ "38:99": -9288933,
+ "39:99": -9288933,
+ "40:99": 402653184,
+ "41:99": 268435456,
+ "42:99": 402653184,
+ "43:99": 268435456,
+ "44:99": -1710797,
+ "45:99": -1710797,
+ "46:99": -1710797,
+ "47:99": -1710797,
+ "48:99": -1710797,
+ "49:99": -1710797,
+ "50:99": -1710797,
+ "51:99": -1710797,
+ "52:99": -1710797,
+ "53:99": -1710797,
+ "54:99": -1710797,
+ "55:99": -1710797,
+ "56:99": -1710797,
+ "57:99": -1710797,
+ "58:99": -1710797,
+ "59:99": -1710797,
+ "60:99": -1710797,
+ "61:99": -1710797,
+ "62:99": 402653184,
+ "63:99": 268435456,
+ "64:99": 402653184,
+ "65:99": 268435456,
+ "66:99": -9288933,
+ "67:99": -9288933,
+ "68:99": -9288933,
+ "69:99": -9288933,
+ "70:99": -9288933,
+ "71:99": -9288933,
+ "72:99": -9288933,
+ "73:99": -9288933,
+ "74:99": -9288933,
+ "75:99": -9288933,
+ "76:99": -9288933,
+ "77:99": -9288933,
+ "78:99": -9288933,
+ "79:99": -9288933,
+ "80:99": -9288933,
+ "81:99": -9288933,
+ "82:99": -9288933,
+ "83:99": -9288933,
+ "84:99": 402653184,
+ "85:99": 268435456,
+ "86:99": 402653184,
+ "87:99": 268435456,
+ "88:99": -5092136,
+ "89:99": -5092136,
+ "90:99": -5092136,
+ "91:99": -5092136,
+ "92:99": -5092136,
+ "93:99": -5092136,
+ "94:99": -5092136,
+ "95:99": -5092136,
+ "96:99": -5092136,
+ "97:99": -5092136,
+ "98:99": -5092136,
+ "99:99": -5092136,
+ "100:99": -5092136,
+ "101:99": -5092136,
+ "102:99": -5092136,
+ "103:99": -5092136,
+ "104:99": -5092136,
+ "105:99": -5092136,
+ "106:99": 402653184,
+ "107:99": 268435456,
+ "108:99": 402653184,
+ "109:99": 268435456,
+ "110:99": 402653184,
+ "111:99": 268435456,
+ "112:99": 402653184,
+ "113:99": 268435456,
+ "114:99": 402653184,
+ "115:99": 268435456,
+ "116:99": 402653184,
+ "117:99": 268435456,
+ "118:99": 402653184,
+ "119:99": 268435456,
+ "120:99": 402653184,
+ "121:99": 268435456,
+ "122:99": 402653184,
+ "123:99": 268435456,
+ "124:99": 402653184,
+ "125:99": 268435456,
+ "126:99": 402653184,
+ "127:99": 268435456,
+ "0:100": 268435456,
+ "1:100": 402653184,
+ "2:100": 268435456,
+ "3:100": 402653184,
+ "4:100": 268435456,
+ "5:100": 402653184,
+ "6:100": 268435456,
+ "7:100": 402653184,
+ "8:100": 268435456,
+ "9:100": 402653184,
+ "10:100": 268435456,
+ "11:100": 402653184,
+ "12:100": 268435456,
+ "13:100": 402653184,
+ "14:100": 268435456,
+ "15:100": 402653184,
+ "16:100": 268435456,
+ "17:100": 402653184,
+ "18:100": 268435456,
+ "19:100": 402653184,
+ "20:100": 268435456,
+ "21:100": 402653184,
+ "22:100": -9288933,
+ "23:100": -9288933,
+ "24:100": -9288933,
+ "25:100": -9288933,
+ "26:100": -9288933,
+ "27:100": -9288933,
+ "28:100": -9288933,
+ "29:100": -9288933,
+ "30:100": -9288933,
+ "31:100": -9288933,
+ "32:100": -9288933,
+ "33:100": -9288933,
+ "34:100": -9288933,
+ "35:100": -9288933,
+ "36:100": -9288933,
+ "37:100": -9288933,
+ "38:100": -9288933,
+ "39:100": -9288933,
+ "40:100": 268435456,
+ "41:100": 402653184,
+ "42:100": 268435456,
+ "43:100": 402653184,
+ "44:100": -1710797,
+ "45:100": -1710797,
+ "46:100": -1710797,
+ "47:100": -1710797,
+ "48:100": -1710797,
+ "49:100": -1710797,
+ "50:100": -1710797,
+ "51:100": -1710797,
+ "52:100": -1710797,
+ "53:100": -1710797,
+ "54:100": -1710797,
+ "55:100": -1710797,
+ "56:100": -1710797,
+ "57:100": -1710797,
+ "58:100": -1710797,
+ "59:100": -1710797,
+ "60:100": -1710797,
+ "61:100": -1710797,
+ "62:100": 268435456,
+ "63:100": 402653184,
+ "64:100": 268435456,
+ "65:100": 402653184,
+ "66:100": -9288933,
+ "67:100": -9288933,
+ "68:100": -9288933,
+ "69:100": -9288933,
+ "70:100": -9288933,
+ "71:100": -9288933,
+ "72:100": -9288933,
+ "73:100": -9288933,
+ "74:100": -9288933,
+ "75:100": -9288933,
+ "76:100": -9288933,
+ "77:100": -9288933,
+ "78:100": -9288933,
+ "79:100": -9288933,
+ "80:100": -9288933,
+ "81:100": -9288933,
+ "82:100": -9288933,
+ "83:100": -9288933,
+ "84:100": 268435456,
+ "85:100": 402653184,
+ "86:100": 268435456,
+ "87:100": 402653184,
+ "88:100": -5092136,
+ "89:100": -5092136,
+ "90:100": -5092136,
+ "91:100": -5092136,
+ "92:100": -5092136,
+ "93:100": -5092136,
+ "94:100": -5092136,
+ "95:100": -5092136,
+ "96:100": -5092136,
+ "97:100": -5092136,
+ "98:100": -5092136,
+ "99:100": -5092136,
+ "100:100": -5092136,
+ "101:100": -5092136,
+ "102:100": -5092136,
+ "103:100": -5092136,
+ "104:100": -5092136,
+ "105:100": -5092136,
+ "106:100": 268435456,
+ "107:100": 402653184,
+ "108:100": 268435456,
+ "109:100": 402653184,
+ "110:100": 268435456,
+ "111:100": 402653184,
+ "112:100": 268435456,
+ "113:100": 402653184,
+ "114:100": 268435456,
+ "115:100": 402653184,
+ "116:100": 268435456,
+ "117:100": 402653184,
+ "118:100": 268435456,
+ "119:100": 402653184,
+ "120:100": 268435456,
+ "121:100": 402653184,
+ "122:100": 268435456,
+ "123:100": 402653184,
+ "124:100": 268435456,
+ "125:100": 402653184,
+ "126:100": 268435456,
+ "127:100": 402653184,
+ "0:101": 402653184,
+ "1:101": 268435456,
+ "2:101": 402653184,
+ "3:101": 268435456,
+ "4:101": 402653184,
+ "5:101": 268435456,
+ "6:101": 402653184,
+ "7:101": 268435456,
+ "8:101": 402653184,
+ "9:101": 268435456,
+ "10:101": 402653184,
+ "11:101": 268435456,
+ "12:101": 402653184,
+ "13:101": 268435456,
+ "14:101": 402653184,
+ "15:101": 268435456,
+ "16:101": 402653184,
+ "17:101": 268435456,
+ "18:101": 402653184,
+ "19:101": 268435456,
+ "20:101": 402653184,
+ "21:101": 268435456,
+ "22:101": -9288933,
+ "23:101": -9288933,
+ "24:101": -9288933,
+ "25:101": -9288933,
+ "26:101": -9288933,
+ "27:101": -9288933,
+ "28:101": -9288933,
+ "29:101": -9288933,
+ "30:101": -9288933,
+ "31:101": -9288933,
+ "32:101": -9288933,
+ "33:101": -9288933,
+ "34:101": -9288933,
+ "35:101": -9288933,
+ "36:101": -9288933,
+ "37:101": -9288933,
+ "38:101": -9288933,
+ "39:101": -9288933,
+ "40:101": 402653184,
+ "41:101": 268435456,
+ "42:101": 402653184,
+ "43:101": 268435456,
+ "44:101": -1710797,
+ "45:101": -1710797,
+ "46:101": -1710797,
+ "47:101": -1710797,
+ "48:101": -1710797,
+ "49:101": -1710797,
+ "50:101": -1710797,
+ "51:101": -1710797,
+ "52:101": -1710797,
+ "53:101": -1710797,
+ "54:101": -1710797,
+ "55:101": -1710797,
+ "56:101": -1710797,
+ "57:101": -1710797,
+ "58:101": -1710797,
+ "59:101": -1710797,
+ "60:101": -1710797,
+ "61:101": -1710797,
+ "62:101": 402653184,
+ "63:101": 268435456,
+ "64:101": 402653184,
+ "65:101": 268435456,
+ "66:101": -9288933,
+ "67:101": -9288933,
+ "68:101": -9288933,
+ "69:101": -9288933,
+ "70:101": -9288933,
+ "71:101": -9288933,
+ "72:101": -9288933,
+ "73:101": -9288933,
+ "74:101": -9288933,
+ "75:101": -9288933,
+ "76:101": -9288933,
+ "77:101": -9288933,
+ "78:101": -9288933,
+ "79:101": -9288933,
+ "80:101": -9288933,
+ "81:101": -9288933,
+ "82:101": -9288933,
+ "83:101": -9288933,
+ "84:101": 402653184,
+ "85:101": 268435456,
+ "86:101": 402653184,
+ "87:101": 268435456,
+ "88:101": -5092136,
+ "89:101": -5092136,
+ "90:101": -5092136,
+ "91:101": -5092136,
+ "92:101": -5092136,
+ "93:101": -5092136,
+ "94:101": -5092136,
+ "95:101": -5092136,
+ "96:101": -5092136,
+ "97:101": -5092136,
+ "98:101": -5092136,
+ "99:101": -5092136,
+ "100:101": -5092136,
+ "101:101": -5092136,
+ "102:101": -5092136,
+ "103:101": -5092136,
+ "104:101": -5092136,
+ "105:101": -5092136,
+ "106:101": 402653184,
+ "107:101": 268435456,
+ "108:101": 402653184,
+ "109:101": 268435456,
+ "110:101": 402653184,
+ "111:101": 268435456,
+ "112:101": 402653184,
+ "113:101": 268435456,
+ "114:101": 402653184,
+ "115:101": 268435456,
+ "116:101": 402653184,
+ "117:101": 268435456,
+ "118:101": 402653184,
+ "119:101": 268435456,
+ "120:101": 402653184,
+ "121:101": 268435456,
+ "122:101": 402653184,
+ "123:101": 268435456,
+ "124:101": 402653184,
+ "125:101": 268435456,
+ "126:101": 402653184,
+ "127:101": 268435456,
+ "0:102": 268435456,
+ "1:102": 402653184,
+ "2:102": 268435456,
+ "3:102": 402653184,
+ "4:102": 268435456,
+ "5:102": 402653184,
+ "6:102": 268435456,
+ "7:102": 402653184,
+ "8:102": 268435456,
+ "9:102": 402653184,
+ "10:102": 268435456,
+ "11:102": 402653184,
+ "12:102": 268435456,
+ "13:102": 402653184,
+ "14:102": 268435456,
+ "15:102": 402653184,
+ "16:102": 268435456,
+ "17:102": 402653184,
+ "18:102": 268435456,
+ "19:102": 402653184,
+ "20:102": 268435456,
+ "21:102": 402653184,
+ "22:102": -9288933,
+ "23:102": -9288933,
+ "24:102": -9288933,
+ "25:102": -9288933,
+ "26:102": -9288933,
+ "27:102": -9288933,
+ "28:102": -9288933,
+ "29:102": -9288933,
+ "30:102": -9288933,
+ "31:102": -9288933,
+ "32:102": -9288933,
+ "33:102": -9288933,
+ "34:102": -9288933,
+ "35:102": -9288933,
+ "36:102": -9288933,
+ "37:102": -9288933,
+ "38:102": -9288933,
+ "39:102": -9288933,
+ "40:102": 268435456,
+ "41:102": 402653184,
+ "42:102": 268435456,
+ "43:102": 402653184,
+ "44:102": -1710797,
+ "45:102": -1710797,
+ "46:102": -1710797,
+ "47:102": -1710797,
+ "48:102": -1710797,
+ "49:102": -1710797,
+ "50:102": -1710797,
+ "51:102": -1710797,
+ "52:102": -1710797,
+ "53:102": -1710797,
+ "54:102": -1710797,
+ "55:102": -1710797,
+ "56:102": -1710797,
+ "57:102": -1710797,
+ "58:102": -1710797,
+ "59:102": -1710797,
+ "60:102": -1710797,
+ "61:102": -1710797,
+ "62:102": 268435456,
+ "63:102": 402653184,
+ "64:102": 268435456,
+ "65:102": 402653184,
+ "66:102": -9288933,
+ "67:102": -9288933,
+ "68:102": -9288933,
+ "69:102": -9288933,
+ "70:102": -9288933,
+ "71:102": -9288933,
+ "72:102": -9288933,
+ "73:102": -9288933,
+ "74:102": -9288933,
+ "75:102": -9288933,
+ "76:102": -9288933,
+ "77:102": -9288933,
+ "78:102": -9288933,
+ "79:102": -9288933,
+ "80:102": -9288933,
+ "81:102": -9288933,
+ "82:102": -9288933,
+ "83:102": -9288933,
+ "84:102": 268435456,
+ "85:102": 402653184,
+ "86:102": 268435456,
+ "87:102": 402653184,
+ "88:102": -5092136,
+ "89:102": -5092136,
+ "90:102": -5092136,
+ "91:102": -5092136,
+ "92:102": -5092136,
+ "93:102": -5092136,
+ "94:102": -5092136,
+ "95:102": -5092136,
+ "96:102": -5092136,
+ "97:102": -5092136,
+ "98:102": -5092136,
+ "99:102": -5092136,
+ "100:102": -5092136,
+ "101:102": -5092136,
+ "102:102": -5092136,
+ "103:102": -5092136,
+ "104:102": -5092136,
+ "105:102": -5092136,
+ "106:102": 268435456,
+ "107:102": 402653184,
+ "108:102": 268435456,
+ "109:102": 402653184,
+ "110:102": 268435456,
+ "111:102": 402653184,
+ "112:102": 268435456,
+ "113:102": 402653184,
+ "114:102": 268435456,
+ "115:102": 402653184,
+ "116:102": 268435456,
+ "117:102": 402653184,
+ "118:102": 268435456,
+ "119:102": 402653184,
+ "120:102": 268435456,
+ "121:102": 402653184,
+ "122:102": 268435456,
+ "123:102": 402653184,
+ "124:102": 268435456,
+ "125:102": 402653184,
+ "126:102": 268435456,
+ "127:102": 402653184,
+ "0:103": 402653184,
+ "1:103": 268435456,
+ "2:103": 402653184,
+ "3:103": 268435456,
+ "4:103": 402653184,
+ "5:103": 268435456,
+ "6:103": 402653184,
+ "7:103": 268435456,
+ "8:103": 402653184,
+ "9:103": 268435456,
+ "10:103": 402653184,
+ "11:103": 268435456,
+ "12:103": 402653184,
+ "13:103": 268435456,
+ "14:103": 402653184,
+ "15:103": 268435456,
+ "16:103": 402653184,
+ "17:103": 268435456,
+ "18:103": 402653184,
+ "19:103": 268435456,
+ "20:103": 402653184,
+ "21:103": 268435456,
+ "22:103": -9288933,
+ "23:103": -9288933,
+ "24:103": -9288933,
+ "25:103": -9288933,
+ "26:103": -9288933,
+ "27:103": -9288933,
+ "28:103": -9288933,
+ "29:103": -9288933,
+ "30:103": -9288933,
+ "31:103": -9288933,
+ "32:103": -9288933,
+ "33:103": -9288933,
+ "34:103": -9288933,
+ "35:103": -9288933,
+ "36:103": -9288933,
+ "37:103": -9288933,
+ "38:103": -9288933,
+ "39:103": -9288933,
+ "40:103": 402653184,
+ "41:103": 268435456,
+ "42:103": 402653184,
+ "43:103": 268435456,
+ "44:103": -1710797,
+ "45:103": -1710797,
+ "46:103": -1710797,
+ "47:103": -1710797,
+ "48:103": -1710797,
+ "49:103": -1710797,
+ "50:103": -1710797,
+ "51:103": -1710797,
+ "52:103": -1710797,
+ "53:103": -1710797,
+ "54:103": -1710797,
+ "55:103": -1710797,
+ "56:103": -1710797,
+ "57:103": -1710797,
+ "58:103": -1710797,
+ "59:103": -1710797,
+ "60:103": -1710797,
+ "61:103": -1710797,
+ "62:103": 402653184,
+ "63:103": 268435456,
+ "64:103": 402653184,
+ "65:103": 268435456,
+ "66:103": -9288933,
+ "67:103": -9288933,
+ "68:103": -9288933,
+ "69:103": -9288933,
+ "70:103": -9288933,
+ "71:103": -9288933,
+ "72:103": -9288933,
+ "73:103": -9288933,
+ "74:103": -9288933,
+ "75:103": -9288933,
+ "76:103": -9288933,
+ "77:103": -9288933,
+ "78:103": -9288933,
+ "79:103": -9288933,
+ "80:103": -9288933,
+ "81:103": -9288933,
+ "82:103": -9288933,
+ "83:103": -9288933,
+ "84:103": 402653184,
+ "85:103": 268435456,
+ "86:103": 402653184,
+ "87:103": 268435456,
+ "88:103": -5092136,
+ "89:103": -5092136,
+ "90:103": -5092136,
+ "91:103": -5092136,
+ "92:103": -5092136,
+ "93:103": -5092136,
+ "94:103": -5092136,
+ "95:103": -5092136,
+ "96:103": -5092136,
+ "97:103": -5092136,
+ "98:103": -5092136,
+ "99:103": -5092136,
+ "100:103": -5092136,
+ "101:103": -5092136,
+ "102:103": -5092136,
+ "103:103": -5092136,
+ "104:103": -5092136,
+ "105:103": -5092136,
+ "106:103": 402653184,
+ "107:103": 268435456,
+ "108:103": 402653184,
+ "109:103": 268435456,
+ "110:103": 402653184,
+ "111:103": 268435456,
+ "112:103": 402653184,
+ "113:103": 268435456,
+ "114:103": 402653184,
+ "115:103": 268435456,
+ "116:103": 402653184,
+ "117:103": 268435456,
+ "118:103": 402653184,
+ "119:103": 268435456,
+ "120:103": 402653184,
+ "121:103": 268435456,
+ "122:103": 402653184,
+ "123:103": 268435456,
+ "124:103": 402653184,
+ "125:103": 268435456,
+ "126:103": 402653184,
+ "127:103": 268435456,
+ "0:104": 268435456,
+ "1:104": 402653184,
+ "2:104": 268435456,
+ "3:104": 402653184,
+ "4:104": 268435456,
+ "5:104": 402653184,
+ "6:104": 268435456,
+ "7:104": 402653184,
+ "8:104": 268435456,
+ "9:104": 402653184,
+ "10:104": 268435456,
+ "11:104": 402653184,
+ "12:104": 268435456,
+ "13:104": 402653184,
+ "14:104": 268435456,
+ "15:104": 402653184,
+ "16:104": 268435456,
+ "17:104": 402653184,
+ "18:104": 268435456,
+ "19:104": 402653184,
+ "20:104": 268435456,
+ "21:104": 402653184,
+ "22:104": -9288933,
+ "23:104": -9288933,
+ "24:104": -9288933,
+ "25:104": -9288933,
+ "26:104": -9288933,
+ "27:104": -9288933,
+ "28:104": -9288933,
+ "29:104": -9288933,
+ "30:104": -9288933,
+ "31:104": -9288933,
+ "32:104": -9288933,
+ "33:104": -9288933,
+ "34:104": -9288933,
+ "35:104": -9288933,
+ "36:104": -9288933,
+ "37:104": -9288933,
+ "38:104": -9288933,
+ "39:104": -9288933,
+ "40:104": 268435456,
+ "41:104": 402653184,
+ "42:104": 268435456,
+ "43:104": 402653184,
+ "44:104": -1710797,
+ "45:104": -1710797,
+ "46:104": -1710797,
+ "47:104": -1710797,
+ "48:104": -1710797,
+ "49:104": -1710797,
+ "50:104": -1710797,
+ "51:104": -1710797,
+ "52:104": -1710797,
+ "53:104": -1710797,
+ "54:104": -1710797,
+ "55:104": -1710797,
+ "56:104": -1710797,
+ "57:104": -1710797,
+ "58:104": -1710797,
+ "59:104": -1710797,
+ "60:104": -1710797,
+ "61:104": -1710797,
+ "62:104": 268435456,
+ "63:104": 402653184,
+ "64:104": 268435456,
+ "65:104": 402653184,
+ "66:104": -9288933,
+ "67:104": -9288933,
+ "68:104": -9288933,
+ "69:104": -9288933,
+ "70:104": -9288933,
+ "71:104": -9288933,
+ "72:104": -9288933,
+ "73:104": -9288933,
+ "74:104": -9288933,
+ "75:104": -9288933,
+ "76:104": -9288933,
+ "77:104": -9288933,
+ "78:104": -9288933,
+ "79:104": -9288933,
+ "80:104": -9288933,
+ "81:104": -9288933,
+ "82:104": -9288933,
+ "83:104": -9288933,
+ "84:104": 268435456,
+ "85:104": 402653184,
+ "86:104": 268435456,
+ "87:104": 402653184,
+ "88:104": -5092136,
+ "89:104": -5092136,
+ "90:104": -5092136,
+ "91:104": -5092136,
+ "92:104": -5092136,
+ "93:104": -5092136,
+ "94:104": -5092136,
+ "95:104": -5092136,
+ "96:104": -5092136,
+ "97:104": -5092136,
+ "98:104": -5092136,
+ "99:104": -5092136,
+ "100:104": -5092136,
+ "101:104": -5092136,
+ "102:104": -5092136,
+ "103:104": -5092136,
+ "104:104": -5092136,
+ "105:104": -5092136,
+ "106:104": 268435456,
+ "107:104": 402653184,
+ "108:104": 268435456,
+ "109:104": 402653184,
+ "110:104": 268435456,
+ "111:104": 402653184,
+ "112:104": 268435456,
+ "113:104": 402653184,
+ "114:104": 268435456,
+ "115:104": 402653184,
+ "116:104": 268435456,
+ "117:104": 402653184,
+ "118:104": 268435456,
+ "119:104": 402653184,
+ "120:104": 268435456,
+ "121:104": 402653184,
+ "122:104": 268435456,
+ "123:104": 402653184,
+ "124:104": 268435456,
+ "125:104": 402653184,
+ "126:104": 268435456,
+ "127:104": 402653184,
+ "0:105": 402653184,
+ "1:105": 268435456,
+ "2:105": 402653184,
+ "3:105": 268435456,
+ "4:105": 402653184,
+ "5:105": 268435456,
+ "6:105": 402653184,
+ "7:105": 268435456,
+ "8:105": 402653184,
+ "9:105": 268435456,
+ "10:105": 402653184,
+ "11:105": 268435456,
+ "12:105": 402653184,
+ "13:105": 268435456,
+ "14:105": 402653184,
+ "15:105": 268435456,
+ "16:105": 402653184,
+ "17:105": 268435456,
+ "18:105": 402653184,
+ "19:105": 268435456,
+ "20:105": 402653184,
+ "21:105": 268435456,
+ "22:105": -9288933,
+ "23:105": -9288933,
+ "24:105": -9288933,
+ "25:105": -9288933,
+ "26:105": -9288933,
+ "27:105": -9288933,
+ "28:105": -9288933,
+ "29:105": -9288933,
+ "30:105": -9288933,
+ "31:105": -9288933,
+ "32:105": -9288933,
+ "33:105": -9288933,
+ "34:105": -9288933,
+ "35:105": -9288933,
+ "36:105": -9288933,
+ "37:105": -9288933,
+ "38:105": -9288933,
+ "39:105": -9288933,
+ "40:105": 402653184,
+ "41:105": 268435456,
+ "42:105": 402653184,
+ "43:105": 268435456,
+ "44:105": -1710797,
+ "45:105": -1710797,
+ "46:105": -1710797,
+ "47:105": -1710797,
+ "48:105": -1710797,
+ "49:105": -1710797,
+ "50:105": -1710797,
+ "51:105": -1710797,
+ "52:105": -1710797,
+ "53:105": -1710797,
+ "54:105": -1710797,
+ "55:105": -1710797,
+ "56:105": -1710797,
+ "57:105": -1710797,
+ "58:105": -1710797,
+ "59:105": -1710797,
+ "60:105": -1710797,
+ "61:105": -1710797,
+ "62:105": 402653184,
+ "63:105": 268435456,
+ "64:105": 402653184,
+ "65:105": 268435456,
+ "66:105": -9288933,
+ "67:105": -9288933,
+ "68:105": -9288933,
+ "69:105": -9288933,
+ "70:105": -9288933,
+ "71:105": -9288933,
+ "72:105": -9288933,
+ "73:105": -9288933,
+ "74:105": -9288933,
+ "75:105": -9288933,
+ "76:105": -9288933,
+ "77:105": -9288933,
+ "78:105": -9288933,
+ "79:105": -9288933,
+ "80:105": -9288933,
+ "81:105": -9288933,
+ "82:105": -9288933,
+ "83:105": -9288933,
+ "84:105": -5092136,
+ "85:105": -5092136,
+ "86:105": -5092136,
+ "87:105": -5092136,
+ "88:105": -5092136,
+ "89:105": -5092136,
+ "90:105": -5092136,
+ "91:105": -5092136,
+ "92:105": -5092136,
+ "93:105": -5092136,
+ "94:105": -5092136,
+ "95:105": -5092136,
+ "96:105": -5092136,
+ "97:105": -5092136,
+ "98:105": -5092136,
+ "99:105": -5092136,
+ "100:105": -5092136,
+ "101:105": -5092136,
+ "102:105": -5092136,
+ "103:105": -5092136,
+ "104:105": -5092136,
+ "105:105": -5092136,
+ "106:105": 402653184,
+ "107:105": 268435456,
+ "108:105": 402653184,
+ "109:105": 268435456,
+ "110:105": 402653184,
+ "111:105": 268435456,
+ "112:105": 402653184,
+ "113:105": 268435456,
+ "114:105": 402653184,
+ "115:105": 268435456,
+ "116:105": 402653184,
+ "117:105": 268435456,
+ "118:105": 402653184,
+ "119:105": 268435456,
+ "120:105": 402653184,
+ "121:105": 268435456,
+ "122:105": 402653184,
+ "123:105": 268435456,
+ "124:105": 402653184,
+ "125:105": 268435456,
+ "126:105": 402653184,
+ "127:105": 268435456,
+ "0:106": 268435456,
+ "1:106": 402653184,
+ "2:106": 268435456,
+ "3:106": 402653184,
+ "4:106": 268435456,
+ "5:106": 402653184,
+ "6:106": 268435456,
+ "7:106": 402653184,
+ "8:106": 268435456,
+ "9:106": 402653184,
+ "10:106": 268435456,
+ "11:106": 402653184,
+ "12:106": 268435456,
+ "13:106": 402653184,
+ "14:106": 268435456,
+ "15:106": 402653184,
+ "16:106": 268435456,
+ "17:106": 402653184,
+ "18:106": 268435456,
+ "19:106": 402653184,
+ "20:106": 268435456,
+ "21:106": 402653184,
+ "22:106": -9288933,
+ "23:106": -9288933,
+ "24:106": -9288933,
+ "25:106": -9288933,
+ "26:106": -9288933,
+ "27:106": -9288933,
+ "28:106": -9288933,
+ "29:106": -9288933,
+ "30:106": -9288933,
+ "31:106": -9288933,
+ "32:106": -9288933,
+ "33:106": -9288933,
+ "34:106": -9288933,
+ "35:106": -9288933,
+ "36:106": -9288933,
+ "37:106": -9288933,
+ "38:106": -9288933,
+ "39:106": -9288933,
+ "40:106": 268435456,
+ "41:106": 402653184,
+ "42:106": 268435456,
+ "43:106": 402653184,
+ "44:106": -1710797,
+ "45:106": -1710797,
+ "46:106": -1710797,
+ "47:106": -1710797,
+ "48:106": -1710797,
+ "49:106": -1710797,
+ "50:106": -1710797,
+ "51:106": -1710797,
+ "52:106": -1710797,
+ "53:106": -1710797,
+ "54:106": -16745472,
+ "55:106": -16745472,
+ "56:106": -16745472,
+ "57:106": -1710797,
+ "58:106": -1710797,
+ "59:106": -1710797,
+ "60:106": -1710797,
+ "61:106": -1710797,
+ "62:106": 268435456,
+ "63:106": 402653184,
+ "64:106": 268435456,
+ "65:106": 402653184,
+ "66:106": -9288933,
+ "67:106": -9288933,
+ "68:106": -9288933,
+ "69:106": -9288933,
+ "70:106": -9288933,
+ "71:106": -9288933,
+ "72:106": -9288933,
+ "73:106": -9288933,
+ "74:106": -9288933,
+ "75:106": -9288933,
+ "76:106": -16745472,
+ "77:106": -16745472,
+ "78:106": -16745472,
+ "79:106": -9288933,
+ "80:106": -9288933,
+ "81:106": -9288933,
+ "82:106": -9288933,
+ "83:106": -9288933,
+ "84:106": -5092136,
+ "85:106": -5092136,
+ "86:106": -5092136,
+ "87:106": -5092136,
+ "88:106": -5092136,
+ "89:106": -5092136,
+ "90:106": -5092136,
+ "91:106": -5092136,
+ "92:106": -5092136,
+ "93:106": -5092136,
+ "94:106": -5092136,
+ "95:106": -5092136,
+ "96:106": -5092136,
+ "97:106": -5092136,
+ "98:106": -16745472,
+ "99:106": -16745472,
+ "100:106": -16745472,
+ "101:106": -5092136,
+ "102:106": -5092136,
+ "103:106": -5092136,
+ "104:106": -5092136,
+ "105:106": -5092136,
+ "106:106": 268435456,
+ "107:106": 402653184,
+ "108:106": 268435456,
+ "109:106": 402653184,
+ "110:106": 268435456,
+ "111:106": 402653184,
+ "112:106": 268435456,
+ "113:106": 402653184,
+ "114:106": 268435456,
+ "115:106": 402653184,
+ "116:106": 268435456,
+ "117:106": 402653184,
+ "118:106": 268435456,
+ "119:106": 402653184,
+ "120:106": 268435456,
+ "121:106": 402653184,
+ "122:106": 268435456,
+ "123:106": 402653184,
+ "124:106": 268435456,
+ "125:106": 402653184,
+ "126:106": 268435456,
+ "127:106": 402653184,
+ "0:107": 402653184,
+ "1:107": 268435456,
+ "2:107": 402653184,
+ "3:107": 268435456,
+ "4:107": 402653184,
+ "5:107": 268435456,
+ "6:107": 402653184,
+ "7:107": 268435456,
+ "8:107": 402653184,
+ "9:107": 268435456,
+ "10:107": 402653184,
+ "11:107": 268435456,
+ "12:107": 402653184,
+ "13:107": 268435456,
+ "14:107": 402653184,
+ "15:107": 268435456,
+ "16:107": 402653184,
+ "17:107": 268435456,
+ "18:107": 402653184,
+ "19:107": 268435456,
+ "20:107": 402653184,
+ "21:107": 268435456,
+ "22:107": -9288933,
+ "23:107": -9288933,
+ "24:107": -9288933,
+ "25:107": -9288933,
+ "26:107": -9288933,
+ "27:107": -9288933,
+ "28:107": -9288933,
+ "29:107": -9288933,
+ "30:107": -9288933,
+ "31:107": -9288933,
+ "32:107": -9288933,
+ "33:107": -9288933,
+ "34:107": -9288933,
+ "35:107": -9288933,
+ "36:107": -9288933,
+ "37:107": -9288933,
+ "38:107": -9288933,
+ "39:107": -9288933,
+ "40:107": 402653184,
+ "41:107": 268435456,
+ "42:107": 402653184,
+ "43:107": 268435456,
+ "44:107": -1710797,
+ "45:107": -1710797,
+ "46:107": -1710797,
+ "47:107": -1710797,
+ "48:107": -1710797,
+ "49:107": -1710797,
+ "50:107": -1710797,
+ "51:107": -1710797,
+ "52:107": -1710797,
+ "53:107": -16745472,
+ "54:107": -16745472,
+ "55:107": -16745472,
+ "56:107": -1710797,
+ "57:107": -1710797,
+ "58:107": -1710797,
+ "59:107": -1710797,
+ "60:107": -1710797,
+ "61:107": -1710797,
+ "62:107": 402653184,
+ "63:107": 268435456,
+ "64:107": 402653184,
+ "65:107": 268435456,
+ "66:107": -9288933,
+ "67:107": -9288933,
+ "68:107": -9288933,
+ "69:107": -9288933,
+ "70:107": -9288933,
+ "71:107": -9288933,
+ "72:107": -9288933,
+ "73:107": -9288933,
+ "74:107": -9288933,
+ "75:107": -16745472,
+ "76:107": -16745472,
+ "77:107": -16745472,
+ "78:107": -9288933,
+ "79:107": -9288933,
+ "80:107": -9288933,
+ "81:107": -9288933,
+ "82:107": -9288933,
+ "83:107": -9288933,
+ "84:107": -5092136,
+ "85:107": -5092136,
+ "86:107": -5092136,
+ "87:107": -5092136,
+ "88:107": -5092136,
+ "89:107": -5092136,
+ "90:107": -5092136,
+ "91:107": -5092136,
+ "92:107": -5092136,
+ "93:107": -5092136,
+ "94:107": -5092136,
+ "95:107": -5092136,
+ "96:107": -5092136,
+ "97:107": -16745472,
+ "98:107": -16745472,
+ "99:107": -16745472,
+ "100:107": -5092136,
+ "101:107": -5092136,
+ "102:107": -5092136,
+ "103:107": -5092136,
+ "104:107": -5092136,
+ "105:107": -5092136,
+ "106:107": 402653184,
+ "107:107": 268435456,
+ "108:107": 402653184,
+ "109:107": 268435456,
+ "110:107": 402653184,
+ "111:107": 268435456,
+ "112:107": 402653184,
+ "113:107": 268435456,
+ "114:107": 402653184,
+ "115:107": 268435456,
+ "116:107": 402653184,
+ "117:107": 268435456,
+ "118:107": 402653184,
+ "119:107": 268435456,
+ "120:107": 402653184,
+ "121:107": 268435456,
+ "122:107": 402653184,
+ "123:107": 268435456,
+ "124:107": 402653184,
+ "125:107": 268435456,
+ "126:107": 402653184,
+ "127:107": 268435456,
+ "0:108": 268435456,
+ "1:108": 402653184,
+ "2:108": 268435456,
+ "3:108": 402653184,
+ "4:108": 268435456,
+ "5:108": 402653184,
+ "6:108": 268435456,
+ "7:108": 402653184,
+ "8:108": 268435456,
+ "9:108": 402653184,
+ "10:108": 268435456,
+ "11:108": 402653184,
+ "12:108": 268435456,
+ "13:108": 402653184,
+ "14:108": 268435456,
+ "15:108": 402653184,
+ "16:108": 268435456,
+ "17:108": 402653184,
+ "18:108": 268435456,
+ "19:108": 402653184,
+ "20:108": 268435456,
+ "21:108": 402653184,
+ "22:108": -9288933,
+ "23:108": -9288933,
+ "24:108": -9288933,
+ "25:108": -9288933,
+ "26:108": -9288933,
+ "27:108": -9288933,
+ "28:108": -9288933,
+ "29:108": -9288933,
+ "30:108": -9288933,
+ "31:108": -9288933,
+ "32:108": -9288933,
+ "33:108": -9288933,
+ "34:108": -9288933,
+ "35:108": -9288933,
+ "36:108": -9288933,
+ "37:108": -9288933,
+ "38:108": -9288933,
+ "39:108": -9288933,
+ "40:108": 268435456,
+ "41:108": 402653184,
+ "42:108": 268435456,
+ "43:108": 402653184,
+ "44:108": -1710797,
+ "45:108": -1710797,
+ "46:108": -1710797,
+ "47:108": -1710797,
+ "48:108": -1710797,
+ "49:108": -1710797,
+ "50:108": -1710797,
+ "51:108": -1710797,
+ "52:108": -1710797,
+ "53:108": -16745472,
+ "54:108": -16745472,
+ "55:108": -1710797,
+ "56:108": -1710797,
+ "57:108": -1710797,
+ "58:108": -1710797,
+ "59:108": -1710797,
+ "60:108": -1710797,
+ "61:108": -1710797,
+ "62:108": 268435456,
+ "63:108": 402653184,
+ "64:108": 268435456,
+ "65:108": 402653184,
+ "66:108": -9288933,
+ "67:108": -9288933,
+ "68:108": -9288933,
+ "69:108": -9288933,
+ "70:108": -9288933,
+ "71:108": -9288933,
+ "72:108": -9288933,
+ "73:108": -9288933,
+ "74:108": -9288933,
+ "75:108": -16745472,
+ "76:108": -16745472,
+ "77:108": -9288933,
+ "78:108": -9288933,
+ "79:108": -9288933,
+ "80:108": -9288933,
+ "81:108": -9288933,
+ "82:108": -9288933,
+ "83:108": -9288933,
+ "84:108": -5092136,
+ "85:108": -5092136,
+ "86:108": -5092136,
+ "87:108": -5092136,
+ "88:108": -5092136,
+ "89:108": -5092136,
+ "90:108": -5092136,
+ "91:108": -5092136,
+ "92:108": -5092136,
+ "93:108": -5092136,
+ "94:108": -5092136,
+ "95:108": -5092136,
+ "96:108": -5092136,
+ "97:108": -16745472,
+ "98:108": -16745472,
+ "99:108": -5092136,
+ "100:108": -5092136,
+ "101:108": -5092136,
+ "102:108": -5092136,
+ "103:108": -5092136,
+ "104:108": -5092136,
+ "105:108": -5092136,
+ "106:108": 268435456,
+ "107:108": 402653184,
+ "108:108": 268435456,
+ "109:108": 402653184,
+ "110:108": 268435456,
+ "111:108": 402653184,
+ "112:108": 268435456,
+ "113:108": 402653184,
+ "114:108": 268435456,
+ "115:108": 402653184,
+ "116:108": 268435456,
+ "117:108": 402653184,
+ "118:108": 268435456,
+ "119:108": 402653184,
+ "120:108": 268435456,
+ "121:108": 402653184,
+ "122:108": 268435456,
+ "123:108": 402653184,
+ "124:108": 268435456,
+ "125:108": 402653184,
+ "126:108": 268435456,
+ "127:108": 402653184,
+ "0:109": 402653184,
+ "1:109": 268435456,
+ "2:109": 402653184,
+ "3:109": 268435456,
+ "4:109": 402653184,
+ "5:109": 268435456,
+ "6:109": 402653184,
+ "7:109": 268435456,
+ "8:109": 402653184,
+ "9:109": 268435456,
+ "10:109": 402653184,
+ "11:109": 268435456,
+ "12:109": 402653184,
+ "13:109": 268435456,
+ "14:109": 402653184,
+ "15:109": 268435456,
+ "16:109": 402653184,
+ "17:109": 268435456,
+ "18:109": 402653184,
+ "19:109": 268435456,
+ "20:109": 402653184,
+ "21:109": 268435456,
+ "22:109": -9288933,
+ "23:109": -9288933,
+ "24:109": -9288933,
+ "25:109": -9288933,
+ "26:109": -9288933,
+ "27:109": -9288933,
+ "28:109": -9288933,
+ "29:109": -9288933,
+ "30:109": -9288933,
+ "31:109": -9288933,
+ "32:109": -9288933,
+ "33:109": -9288933,
+ "34:109": -9288933,
+ "35:109": -9288933,
+ "36:109": -9288933,
+ "37:109": -9288933,
+ "38:109": -9288933,
+ "39:109": -9288933,
+ "40:109": 402653184,
+ "41:109": 268435456,
+ "42:109": 402653184,
+ "43:109": 268435456,
+ "44:109": -1710797,
+ "45:109": -1710797,
+ "46:109": -1710797,
+ "47:109": -1710797,
+ "48:109": -1710797,
+ "49:109": -1710797,
+ "50:109": -16745472,
+ "51:109": -16745472,
+ "52:109": -1710797,
+ "53:109": -16745472,
+ "54:109": -16745472,
+ "55:109": -1710797,
+ "56:109": -1710797,
+ "57:109": -1710797,
+ "58:109": -1710797,
+ "59:109": -1710797,
+ "60:109": -1710797,
+ "61:109": -1710797,
+ "62:109": 402653184,
+ "63:109": 268435456,
+ "64:109": 402653184,
+ "65:109": 268435456,
+ "66:109": -9288933,
+ "67:109": -9288933,
+ "68:109": -9288933,
+ "69:109": -9288933,
+ "70:109": -9288933,
+ "71:109": -9288933,
+ "72:109": -16745472,
+ "73:109": -16745472,
+ "74:109": -9288933,
+ "75:109": -16745472,
+ "76:109": -16745472,
+ "77:109": -9288933,
+ "78:109": -9288933,
+ "79:109": -9288933,
+ "80:109": -9288933,
+ "81:109": -9288933,
+ "82:109": -9288933,
+ "83:109": -9288933,
+ "84:109": -5092136,
+ "85:109": -5092136,
+ "86:109": -5092136,
+ "87:109": -5092136,
+ "88:109": -5092136,
+ "89:109": -5092136,
+ "90:109": -5092136,
+ "91:109": -5092136,
+ "92:109": -5092136,
+ "93:109": -5092136,
+ "94:109": -16745472,
+ "95:109": -16745472,
+ "96:109": -5092136,
+ "97:109": -16745472,
+ "98:109": -16745472,
+ "99:109": -5092136,
+ "100:109": -5092136,
+ "101:109": -5092136,
+ "102:109": -5092136,
+ "103:109": -5092136,
+ "104:109": -5092136,
+ "105:109": -5092136,
+ "106:109": 402653184,
+ "107:109": 268435456,
+ "108:109": 402653184,
+ "109:109": 268435456,
+ "110:109": 402653184,
+ "111:109": 268435456,
+ "112:109": 402653184,
+ "113:109": 268435456,
+ "114:109": 402653184,
+ "115:109": 268435456,
+ "116:109": 402653184,
+ "117:109": 268435456,
+ "118:109": 402653184,
+ "119:109": 268435456,
+ "120:109": 402653184,
+ "121:109": 268435456,
+ "122:109": 402653184,
+ "123:109": 268435456,
+ "124:109": 402653184,
+ "125:109": 268435456,
+ "126:109": 402653184,
+ "127:109": 268435456,
+ "0:110": 268435456,
+ "1:110": 402653184,
+ "2:110": 268435456,
+ "3:110": 402653184,
+ "4:110": 268435456,
+ "5:110": 402653184,
+ "6:110": 268435456,
+ "7:110": 402653184,
+ "8:110": 268435456,
+ "9:110": 402653184,
+ "10:110": 268435456,
+ "11:110": 402653184,
+ "12:110": 268435456,
+ "13:110": 402653184,
+ "14:110": 268435456,
+ "15:110": 402653184,
+ "16:110": 268435456,
+ "17:110": 402653184,
+ "18:110": 268435456,
+ "19:110": 402653184,
+ "20:110": 268435456,
+ "21:110": 402653184,
+ "22:110": -9288933,
+ "23:110": -9288933,
+ "24:110": -9288933,
+ "25:110": -9288933,
+ "26:110": -9288933,
+ "27:110": -9288933,
+ "28:110": -9288933,
+ "29:110": -9288933,
+ "30:110": -9288933,
+ "31:110": -9288933,
+ "32:110": -9288933,
+ "33:110": -9288933,
+ "34:110": -9288933,
+ "35:110": -9288933,
+ "36:110": -9288933,
+ "37:110": -9288933,
+ "38:110": -9288933,
+ "39:110": -9288933,
+ "40:110": 268435456,
+ "41:110": 402653184,
+ "42:110": 268435456,
+ "43:110": 402653184,
+ "44:110": -1710797,
+ "45:110": -1710797,
+ "46:110": -1710797,
+ "47:110": -1710797,
+ "48:110": -1710797,
+ "49:110": -1710797,
+ "50:110": -1710797,
+ "51:110": -16745472,
+ "52:110": -16745472,
+ "53:110": -16745472,
+ "54:110": -1710797,
+ "55:110": -1710797,
+ "56:110": -1710797,
+ "57:110": -1710797,
+ "58:110": -1710797,
+ "59:110": -1710797,
+ "60:110": -1710797,
+ "61:110": -1710797,
+ "62:110": 268435456,
+ "63:110": 402653184,
+ "64:110": 268435456,
+ "65:110": 402653184,
+ "66:110": -9288933,
+ "67:110": -9288933,
+ "68:110": -9288933,
+ "69:110": -9288933,
+ "70:110": -9288933,
+ "71:110": -9288933,
+ "72:110": -9288933,
+ "73:110": -16745472,
+ "74:110": -16745472,
+ "75:110": -16745472,
+ "76:110": -9288933,
+ "77:110": -9288933,
+ "78:110": -9288933,
+ "79:110": -9288933,
+ "80:110": -9288933,
+ "81:110": -9288933,
+ "82:110": -9288933,
+ "83:110": -9288933,
+ "84:110": -5092136,
+ "85:110": -5092136,
+ "86:110": -5092136,
+ "87:110": -5092136,
+ "88:110": -5092136,
+ "89:110": -5092136,
+ "90:110": -5092136,
+ "91:110": -5092136,
+ "92:110": -5092136,
+ "93:110": -5092136,
+ "94:110": -5092136,
+ "95:110": -16745472,
+ "96:110": -16745472,
+ "97:110": -16745472,
+ "98:110": -5092136,
+ "99:110": -5092136,
+ "100:110": -5092136,
+ "101:110": -5092136,
+ "102:110": -5092136,
+ "103:110": -5092136,
+ "104:110": -5092136,
+ "105:110": -5092136,
+ "106:110": 268435456,
+ "107:110": 402653184,
+ "108:110": 268435456,
+ "109:110": 402653184,
+ "110:110": 268435456,
+ "111:110": 402653184,
+ "112:110": 268435456,
+ "113:110": 402653184,
+ "114:110": 268435456,
+ "115:110": 402653184,
+ "116:110": 268435456,
+ "117:110": 402653184,
+ "118:110": 268435456,
+ "119:110": 402653184,
+ "120:110": 268435456,
+ "121:110": 402653184,
+ "122:110": 268435456,
+ "123:110": 402653184,
+ "124:110": 268435456,
+ "125:110": 402653184,
+ "126:110": 268435456,
+ "127:110": 402653184,
+ "0:111": 402653184,
+ "1:111": 268435456,
+ "2:111": 402653184,
+ "3:111": 268435456,
+ "4:111": 402653184,
+ "5:111": 268435456,
+ "6:111": 402653184,
+ "7:111": 268435456,
+ "8:111": 402653184,
+ "9:111": 268435456,
+ "10:111": 402653184,
+ "11:111": 268435456,
+ "12:111": 402653184,
+ "13:111": 268435456,
+ "14:111": 402653184,
+ "15:111": 268435456,
+ "16:111": 402653184,
+ "17:111": 268435456,
+ "18:111": 402653184,
+ "19:111": 268435456,
+ "20:111": 402653184,
+ "21:111": 268435456,
+ "22:111": -9288933,
+ "23:111": -9288933,
+ "24:111": -9288933,
+ "25:111": -9288933,
+ "26:111": -9288933,
+ "27:111": -9288933,
+ "28:111": -9288933,
+ "29:111": -9288933,
+ "30:111": -9288933,
+ "31:111": -9288933,
+ "32:111": -9288933,
+ "33:111": -9288933,
+ "34:111": -9288933,
+ "35:111": -9288933,
+ "36:111": -9288933,
+ "37:111": -9288933,
+ "38:111": -9288933,
+ "39:111": -9288933,
+ "40:111": 402653184,
+ "41:111": 268435456,
+ "42:111": 402653184,
+ "43:111": 268435456,
+ "44:111": -1710797,
+ "45:111": -1710797,
+ "46:111": -1710797,
+ "47:111": -1710797,
+ "48:111": -1710797,
+ "49:111": -1710797,
+ "50:111": -1710797,
+ "51:111": -16745472,
+ "52:111": -16745472,
+ "53:111": -16745472,
+ "54:111": -1710797,
+ "55:111": -1710797,
+ "56:111": -1710797,
+ "57:111": -1710797,
+ "58:111": -1710797,
+ "59:111": -1710797,
+ "60:111": -1710797,
+ "61:111": -1710797,
+ "62:111": 402653184,
+ "63:111": 268435456,
+ "64:111": 402653184,
+ "65:111": 268435456,
+ "66:111": -9288933,
+ "67:111": -9288933,
+ "68:111": -9288933,
+ "69:111": -9288933,
+ "70:111": -9288933,
+ "71:111": -9288933,
+ "72:111": -9288933,
+ "73:111": -16745472,
+ "74:111": -16745472,
+ "75:111": -16745472,
+ "76:111": -9288933,
+ "77:111": -9288933,
+ "78:111": -9288933,
+ "79:111": -9288933,
+ "80:111": -9288933,
+ "81:111": -9288933,
+ "82:111": -9288933,
+ "83:111": -9288933,
+ "84:111": -5092136,
+ "85:111": -5092136,
+ "86:111": -5092136,
+ "87:111": -5092136,
+ "88:111": -5092136,
+ "89:111": -5092136,
+ "90:111": -5092136,
+ "91:111": -5092136,
+ "92:111": -5092136,
+ "93:111": -5092136,
+ "94:111": -5092136,
+ "95:111": -16745472,
+ "96:111": -16745472,
+ "97:111": -16745472,
+ "98:111": -5092136,
+ "99:111": -5092136,
+ "100:111": -5092136,
+ "101:111": -5092136,
+ "102:111": -5092136,
+ "103:111": -5092136,
+ "104:111": -5092136,
+ "105:111": -5092136,
+ "106:111": 402653184,
+ "107:111": 268435456,
+ "108:111": 402653184,
+ "109:111": 268435456,
+ "110:111": 402653184,
+ "111:111": 268435456,
+ "112:111": 402653184,
+ "113:111": 268435456,
+ "114:111": 402653184,
+ "115:111": 268435456,
+ "116:111": 402653184,
+ "117:111": 268435456,
+ "118:111": 402653184,
+ "119:111": 268435456,
+ "120:111": 402653184,
+ "121:111": 268435456,
+ "122:111": 402653184,
+ "123:111": 268435456,
+ "124:111": 402653184,
+ "125:111": 268435456,
+ "126:111": 402653184,
+ "127:111": 268435456,
+ "0:112": 268435456,
+ "1:112": 402653184,
+ "2:112": 268435456,
+ "3:112": 402653184,
+ "4:112": 268435456,
+ "5:112": 402653184,
+ "6:112": 268435456,
+ "7:112": 402653184,
+ "8:112": 268435456,
+ "9:112": 402653184,
+ "10:112": 268435456,
+ "11:112": 402653184,
+ "12:112": 268435456,
+ "13:112": 402653184,
+ "14:112": 268435456,
+ "15:112": 402653184,
+ "16:112": 268435456,
+ "17:112": 402653184,
+ "18:112": 268435456,
+ "19:112": 402653184,
+ "20:112": 268435456,
+ "21:112": 402653184,
+ "22:112": -9288933,
+ "23:112": -9288933,
+ "24:112": -9288933,
+ "25:112": -9288933,
+ "26:112": -9288933,
+ "27:112": -9288933,
+ "28:112": -9288933,
+ "29:112": -9288933,
+ "30:112": -9288933,
+ "31:112": -9288933,
+ "32:112": -9288933,
+ "33:112": -9288933,
+ "34:112": -9288933,
+ "35:112": -9288933,
+ "36:112": -9288933,
+ "37:112": -9288933,
+ "38:112": -9288933,
+ "39:112": -9288933,
+ "40:112": 268435456,
+ "41:112": 402653184,
+ "42:112": 268435456,
+ "43:112": 402653184,
+ "44:112": -1710797,
+ "45:112": -1710797,
+ "46:112": -1710797,
+ "47:112": -1710797,
+ "48:112": -1710797,
+ "49:112": -1710797,
+ "50:112": -1710797,
+ "51:112": -1710797,
+ "52:112": -1710797,
+ "53:112": -1710797,
+ "54:112": -1710797,
+ "55:112": -1710797,
+ "56:112": -1710797,
+ "57:112": -1710797,
+ "58:112": -1710797,
+ "59:112": -1710797,
+ "60:112": -1710797,
+ "61:112": -1710797,
+ "62:112": 268435456,
+ "63:112": 402653184,
+ "64:112": 268435456,
+ "65:112": 402653184,
+ "66:112": -9288933,
+ "67:112": -9288933,
+ "68:112": -9288933,
+ "69:112": -9288933,
+ "70:112": -9288933,
+ "71:112": -9288933,
+ "72:112": -9288933,
+ "73:112": -9288933,
+ "74:112": -9288933,
+ "75:112": -9288933,
+ "76:112": -9288933,
+ "77:112": -9288933,
+ "78:112": -9288933,
+ "79:112": -9288933,
+ "80:112": -9288933,
+ "81:112": -9288933,
+ "82:112": -9288933,
+ "83:112": -9288933,
+ "84:112": 268435456,
+ "85:112": 402653184,
+ "86:112": 268435456,
+ "87:112": 402653184,
+ "88:112": -5092136,
+ "89:112": -5092136,
+ "90:112": -5092136,
+ "91:112": -5092136,
+ "92:112": -5092136,
+ "93:112": -5092136,
+ "94:112": -5092136,
+ "95:112": -5092136,
+ "96:112": -5092136,
+ "97:112": -5092136,
+ "98:112": -5092136,
+ "99:112": -5092136,
+ "100:112": -5092136,
+ "101:112": -5092136,
+ "102:112": -5092136,
+ "103:112": -5092136,
+ "104:112": -5092136,
+ "105:112": -5092136,
+ "106:112": 268435456,
+ "107:112": 402653184,
+ "108:112": 268435456,
+ "109:112": 402653184,
+ "110:112": 268435456,
+ "111:112": 402653184,
+ "112:112": 268435456,
+ "113:112": 402653184,
+ "114:112": 268435456,
+ "115:112": 402653184,
+ "116:112": 268435456,
+ "117:112": 402653184,
+ "118:112": 268435456,
+ "119:112": 402653184,
+ "120:112": 268435456,
+ "121:112": 402653184,
+ "122:112": 268435456,
+ "123:112": 402653184,
+ "124:112": 268435456,
+ "125:112": 402653184,
+ "126:112": 268435456,
+ "127:112": 402653184,
+ "0:113": 402653184,
+ "1:113": 268435456,
+ "2:113": 402653184,
+ "3:113": 268435456,
+ "4:113": 402653184,
+ "5:113": 268435456,
+ "6:113": 402653184,
+ "7:113": 268435456,
+ "8:113": 402653184,
+ "9:113": 268435456,
+ "10:113": 402653184,
+ "11:113": 268435456,
+ "12:113": 402653184,
+ "13:113": 268435456,
+ "14:113": 402653184,
+ "15:113": 268435456,
+ "16:113": 402653184,
+ "17:113": 268435456,
+ "18:113": 402653184,
+ "19:113": 268435456,
+ "20:113": 402653184,
+ "21:113": 268435456,
+ "22:113": -9288933,
+ "23:113": -9288933,
+ "24:113": -9288933,
+ "25:113": -9288933,
+ "26:113": -9288933,
+ "27:113": -9288933,
+ "28:113": -9288933,
+ "29:113": -9288933,
+ "30:113": -9288933,
+ "31:113": -9288933,
+ "32:113": -9288933,
+ "33:113": -9288933,
+ "34:113": -9288933,
+ "35:113": -9288933,
+ "36:113": -9288933,
+ "37:113": -9288933,
+ "38:113": -9288933,
+ "39:113": -9288933,
+ "40:113": 402653184,
+ "41:113": 268435456,
+ "42:113": 402653184,
+ "43:113": 268435456,
+ "44:113": -1710797,
+ "45:113": -1710797,
+ "46:113": -1710797,
+ "47:113": -1710797,
+ "48:113": -1710797,
+ "49:113": -1710797,
+ "50:113": -1710797,
+ "51:113": -1710797,
+ "52:113": -1710797,
+ "53:113": -1710797,
+ "54:113": -1710797,
+ "55:113": -1710797,
+ "56:113": -1710797,
+ "57:113": -1710797,
+ "58:113": -1710797,
+ "59:113": -1710797,
+ "60:113": -1710797,
+ "61:113": -1710797,
+ "62:113": 402653184,
+ "63:113": 268435456,
+ "64:113": 402653184,
+ "65:113": 268435456,
+ "66:113": -9288933,
+ "67:113": -9288933,
+ "68:113": -9288933,
+ "69:113": -9288933,
+ "70:113": -9288933,
+ "71:113": -9288933,
+ "72:113": -9288933,
+ "73:113": -9288933,
+ "74:113": -9288933,
+ "75:113": -9288933,
+ "76:113": -9288933,
+ "77:113": -9288933,
+ "78:113": -9288933,
+ "79:113": -9288933,
+ "80:113": -9288933,
+ "81:113": -9288933,
+ "82:113": -9288933,
+ "83:113": -9288933,
+ "84:113": 402653184,
+ "85:113": 268435456,
+ "86:113": 402653184,
+ "87:113": 268435456,
+ "88:113": -5092136,
+ "89:113": -5092136,
+ "90:113": -5092136,
+ "91:113": -5092136,
+ "92:113": -5092136,
+ "93:113": -5092136,
+ "94:113": -5092136,
+ "95:113": -5092136,
+ "96:113": -5092136,
+ "97:113": -5092136,
+ "98:113": -5092136,
+ "99:113": -5092136,
+ "100:113": -5092136,
+ "101:113": -5092136,
+ "102:113": -5092136,
+ "103:113": -5092136,
+ "104:113": -5092136,
+ "105:113": -5092136,
+ "106:113": 402653184,
+ "107:113": 268435456,
+ "108:113": 402653184,
+ "109:113": 268435456,
+ "110:113": 402653184,
+ "111:113": 268435456,
+ "112:113": 402653184,
+ "113:113": 268435456,
+ "114:113": 402653184,
+ "115:113": 268435456,
+ "116:113": 402653184,
+ "117:113": 268435456,
+ "118:113": 402653184,
+ "119:113": 268435456,
+ "120:113": 402653184,
+ "121:113": 268435456,
+ "122:113": 402653184,
+ "123:113": 268435456,
+ "124:113": 402653184,
+ "125:113": 268435456,
+ "126:113": 402653184,
+ "127:113": 268435456,
+ "0:114": 268435456,
+ "1:114": 402653184,
+ "2:114": 268435456,
+ "3:114": 402653184,
+ "4:114": 268435456,
+ "5:114": 402653184,
+ "6:114": 268435456,
+ "7:114": 402653184,
+ "8:114": 268435456,
+ "9:114": 402653184,
+ "10:114": 268435456,
+ "11:114": 402653184,
+ "12:114": 268435456,
+ "13:114": 402653184,
+ "14:114": 268435456,
+ "15:114": 402653184,
+ "16:114": 268435456,
+ "17:114": 402653184,
+ "18:114": 268435456,
+ "19:114": 402653184,
+ "20:114": 268435456,
+ "21:114": 402653184,
+ "22:114": -9288933,
+ "23:114": -9288933,
+ "24:114": -9288933,
+ "25:114": -9288933,
+ "26:114": -9288933,
+ "27:114": -9288933,
+ "28:114": -9288933,
+ "29:114": -9288933,
+ "30:114": -9288933,
+ "31:114": -9288933,
+ "32:114": -9288933,
+ "33:114": -9288933,
+ "34:114": -9288933,
+ "35:114": -9288933,
+ "36:114": -9288933,
+ "37:114": -9288933,
+ "38:114": -9288933,
+ "39:114": -9288933,
+ "40:114": 268435456,
+ "41:114": 402653184,
+ "42:114": 268435456,
+ "43:114": 402653184,
+ "44:114": -1710797,
+ "45:114": -1710797,
+ "46:114": -1710797,
+ "47:114": -1710797,
+ "48:114": -1710797,
+ "49:114": -1710797,
+ "50:114": -1710797,
+ "51:114": -1710797,
+ "52:114": -1710797,
+ "53:114": -1710797,
+ "54:114": -1710797,
+ "55:114": -1710797,
+ "56:114": -1710797,
+ "57:114": -1710797,
+ "58:114": -1710797,
+ "59:114": -1710797,
+ "60:114": -1710797,
+ "61:114": -1710797,
+ "62:114": 268435456,
+ "63:114": 402653184,
+ "64:114": 268435456,
+ "65:114": 402653184,
+ "66:114": -9288933,
+ "67:114": -9288933,
+ "68:114": -9288933,
+ "69:114": -9288933,
+ "70:114": -9288933,
+ "71:114": -9288933,
+ "72:114": -9288933,
+ "73:114": -9288933,
+ "74:114": -9288933,
+ "75:114": -9288933,
+ "76:114": -9288933,
+ "77:114": -9288933,
+ "78:114": -9288933,
+ "79:114": -9288933,
+ "80:114": -9288933,
+ "81:114": -9288933,
+ "82:114": -9288933,
+ "83:114": -9288933,
+ "84:114": 268435456,
+ "85:114": 402653184,
+ "86:114": 268435456,
+ "87:114": 402653184,
+ "88:114": -5092136,
+ "89:114": -5092136,
+ "90:114": -5092136,
+ "91:114": -5092136,
+ "92:114": -5092136,
+ "93:114": -5092136,
+ "94:114": -5092136,
+ "95:114": -5092136,
+ "96:114": -5092136,
+ "97:114": -5092136,
+ "98:114": -5092136,
+ "99:114": -5092136,
+ "100:114": -5092136,
+ "101:114": -5092136,
+ "102:114": -5092136,
+ "103:114": -5092136,
+ "104:114": -5092136,
+ "105:114": -5092136,
+ "106:114": 268435456,
+ "107:114": 402653184,
+ "108:114": 268435456,
+ "109:114": 402653184,
+ "110:114": 268435456,
+ "111:114": 402653184,
+ "112:114": 268435456,
+ "113:114": 402653184,
+ "114:114": 268435456,
+ "115:114": 402653184,
+ "116:114": 268435456,
+ "117:114": 402653184,
+ "118:114": 268435456,
+ "119:114": 402653184,
+ "120:114": 268435456,
+ "121:114": 402653184,
+ "122:114": 268435456,
+ "123:114": 402653184,
+ "124:114": 268435456,
+ "125:114": 402653184,
+ "126:114": 268435456,
+ "127:114": 402653184,
+ "0:115": 402653184,
+ "1:115": 268435456,
+ "2:115": 402653184,
+ "3:115": 268435456,
+ "4:115": 402653184,
+ "5:115": 268435456,
+ "6:115": 402653184,
+ "7:115": 268435456,
+ "8:115": 402653184,
+ "9:115": 268435456,
+ "10:115": 402653184,
+ "11:115": 268435456,
+ "12:115": 402653184,
+ "13:115": 268435456,
+ "14:115": 402653184,
+ "15:115": 268435456,
+ "16:115": 402653184,
+ "17:115": 268435456,
+ "18:115": 402653184,
+ "19:115": 268435456,
+ "20:115": 402653184,
+ "21:115": 268435456,
+ "22:115": -9288933,
+ "23:115": -9288933,
+ "24:115": -9288933,
+ "25:115": -9288933,
+ "26:115": -9288933,
+ "27:115": -9288933,
+ "28:115": -9288933,
+ "29:115": -9288933,
+ "30:115": -9288933,
+ "31:115": -9288933,
+ "32:115": -9288933,
+ "33:115": -9288933,
+ "34:115": -9288933,
+ "35:115": -9288933,
+ "36:115": -9288933,
+ "37:115": -9288933,
+ "38:115": -9288933,
+ "39:115": -9288933,
+ "40:115": 402653184,
+ "41:115": 268435456,
+ "42:115": 402653184,
+ "43:115": 268435456,
+ "44:115": -1710797,
+ "45:115": -1710797,
+ "46:115": -1710797,
+ "47:115": -1710797,
+ "48:115": -1710797,
+ "49:115": -1710797,
+ "50:115": -1710797,
+ "51:115": -1710797,
+ "52:115": -1710797,
+ "53:115": -1710797,
+ "54:115": -1710797,
+ "55:115": -1710797,
+ "56:115": -1710797,
+ "57:115": -1710797,
+ "58:115": -1710797,
+ "59:115": -1710797,
+ "60:115": -1710797,
+ "61:115": -1710797,
+ "62:115": 402653184,
+ "63:115": 268435456,
+ "64:115": 402653184,
+ "65:115": 268435456,
+ "66:115": -9288933,
+ "67:115": -9288933,
+ "68:115": -9288933,
+ "69:115": -9288933,
+ "70:115": -9288933,
+ "71:115": -9288933,
+ "72:115": -9288933,
+ "73:115": -9288933,
+ "74:115": -9288933,
+ "75:115": -9288933,
+ "76:115": -9288933,
+ "77:115": -9288933,
+ "78:115": -9288933,
+ "79:115": -9288933,
+ "80:115": -9288933,
+ "81:115": -9288933,
+ "82:115": -9288933,
+ "83:115": -9288933,
+ "84:115": 402653184,
+ "85:115": 268435456,
+ "86:115": 402653184,
+ "87:115": 268435456,
+ "88:115": -5092136,
+ "89:115": -5092136,
+ "90:115": -5092136,
+ "91:115": -5092136,
+ "92:115": -5092136,
+ "93:115": -5092136,
+ "94:115": -5092136,
+ "95:115": -5092136,
+ "96:115": -5092136,
+ "97:115": -5092136,
+ "98:115": -5092136,
+ "99:115": -5092136,
+ "100:115": -5092136,
+ "101:115": -5092136,
+ "102:115": -5092136,
+ "103:115": -5092136,
+ "104:115": -5092136,
+ "105:115": -5092136,
+ "106:115": 402653184,
+ "107:115": 268435456,
+ "108:115": 402653184,
+ "109:115": 268435456,
+ "110:115": 402653184,
+ "111:115": 268435456,
+ "112:115": 402653184,
+ "113:115": 268435456,
+ "114:115": 402653184,
+ "115:115": 268435456,
+ "116:115": 402653184,
+ "117:115": 268435456,
+ "118:115": 402653184,
+ "119:115": 268435456,
+ "120:115": 402653184,
+ "121:115": 268435456,
+ "122:115": 402653184,
+ "123:115": 268435456,
+ "124:115": 402653184,
+ "125:115": 268435456,
+ "126:115": 402653184,
+ "127:115": 268435456,
+ "0:116": 268435456,
+ "1:116": 402653184,
+ "2:116": 268435456,
+ "3:116": 402653184,
+ "4:116": 268435456,
+ "5:116": 402653184,
+ "6:116": 268435456,
+ "7:116": 402653184,
+ "8:116": 268435456,
+ "9:116": 402653184,
+ "10:116": 268435456,
+ "11:116": 402653184,
+ "12:116": 268435456,
+ "13:116": 402653184,
+ "14:116": 268435456,
+ "15:116": 402653184,
+ "16:116": 268435456,
+ "17:116": 402653184,
+ "18:116": 268435456,
+ "19:116": 402653184,
+ "20:116": 268435456,
+ "21:116": 402653184,
+ "22:116": -9288933,
+ "23:116": -9288933,
+ "24:116": -9288933,
+ "25:116": -9288933,
+ "26:116": -9288933,
+ "27:116": -9288933,
+ "28:116": -9288933,
+ "29:116": -9288933,
+ "30:116": -9288933,
+ "31:116": -9288933,
+ "32:116": -9288933,
+ "33:116": -9288933,
+ "34:116": -9288933,
+ "35:116": -9288933,
+ "36:116": -9288933,
+ "37:116": -9288933,
+ "38:116": -9288933,
+ "39:116": -9288933,
+ "40:116": 268435456,
+ "41:116": 402653184,
+ "42:116": 268435456,
+ "43:116": 402653184,
+ "44:116": -1710797,
+ "45:116": -1710797,
+ "46:116": -1710797,
+ "47:116": -1710797,
+ "48:116": -1710797,
+ "49:116": -1710797,
+ "50:116": -1710797,
+ "51:116": -1710797,
+ "52:116": -1710797,
+ "53:116": -1710797,
+ "54:116": -1710797,
+ "55:116": -1710797,
+ "56:116": -1710797,
+ "57:116": -1710797,
+ "58:116": -1710797,
+ "59:116": -1710797,
+ "60:116": -1710797,
+ "61:116": -1710797,
+ "62:116": 268435456,
+ "63:116": 402653184,
+ "64:116": 268435456,
+ "65:116": 402653184,
+ "66:116": -9288933,
+ "67:116": -9288933,
+ "68:116": -9288933,
+ "69:116": -9288933,
+ "70:116": -9288933,
+ "71:116": -9288933,
+ "72:116": -9288933,
+ "73:116": -9288933,
+ "74:116": -9288933,
+ "75:116": -9288933,
+ "76:116": -9288933,
+ "77:116": -9288933,
+ "78:116": -9288933,
+ "79:116": -9288933,
+ "80:116": -9288933,
+ "81:116": -9288933,
+ "82:116": -9288933,
+ "83:116": -9288933,
+ "84:116": 268435456,
+ "85:116": 402653184,
+ "86:116": 268435456,
+ "87:116": 402653184,
+ "88:116": -5092136,
+ "89:116": -5092136,
+ "90:116": -5092136,
+ "91:116": -5092136,
+ "92:116": -5092136,
+ "93:116": -5092136,
+ "94:116": -5092136,
+ "95:116": -5092136,
+ "96:116": -5092136,
+ "97:116": -5092136,
+ "98:116": -5092136,
+ "99:116": -5092136,
+ "100:116": -5092136,
+ "101:116": -5092136,
+ "102:116": -5092136,
+ "103:116": -5092136,
+ "104:116": -5092136,
+ "105:116": -5092136,
+ "106:116": 268435456,
+ "107:116": 402653184,
+ "108:116": 268435456,
+ "109:116": 402653184,
+ "110:116": 268435456,
+ "111:116": 402653184,
+ "112:116": 268435456,
+ "113:116": 402653184,
+ "114:116": 268435456,
+ "115:116": 402653184,
+ "116:116": 268435456,
+ "117:116": 402653184,
+ "118:116": 268435456,
+ "119:116": 402653184,
+ "120:116": 268435456,
+ "121:116": 402653184,
+ "122:116": 268435456,
+ "123:116": 402653184,
+ "124:116": 268435456,
+ "125:116": 402653184,
+ "126:116": 268435456,
+ "127:116": 402653184,
+ "0:117": 402653184,
+ "1:117": 268435456,
+ "2:117": 402653184,
+ "3:117": 268435456,
+ "4:117": 402653184,
+ "5:117": 268435456,
+ "6:117": 402653184,
+ "7:117": 268435456,
+ "8:117": 402653184,
+ "9:117": 268435456,
+ "10:117": 402653184,
+ "11:117": 268435456,
+ "12:117": 402653184,
+ "13:117": 268435456,
+ "14:117": 402653184,
+ "15:117": 268435456,
+ "16:117": 402653184,
+ "17:117": 268435456,
+ "18:117": 402653184,
+ "19:117": 268435456,
+ "20:117": 402653184,
+ "21:117": 268435456,
+ "22:117": 402653184,
+ "23:117": 268435456,
+ "24:117": 402653184,
+ "25:117": 268435456,
+ "26:117": 402653184,
+ "27:117": 268435456,
+ "28:117": 402653184,
+ "29:117": 268435456,
+ "30:117": 402653184,
+ "31:117": 268435456,
+ "32:117": 402653184,
+ "33:117": 268435456,
+ "34:117": 402653184,
+ "35:117": 268435456,
+ "36:117": 402653184,
+ "37:117": 268435456,
+ "38:117": 402653184,
+ "39:117": 268435456,
+ "40:117": 402653184,
+ "41:117": 268435456,
+ "42:117": 402653184,
+ "43:117": 268435456,
+ "44:117": 402653184,
+ "45:117": 268435456,
+ "46:117": 402653184,
+ "47:117": 268435456,
+ "48:117": 402653184,
+ "49:117": 268435456,
+ "50:117": 402653184,
+ "51:117": 268435456,
+ "52:117": 402653184,
+ "53:117": 268435456,
+ "54:117": 402653184,
+ "55:117": 268435456,
+ "56:117": 402653184,
+ "57:117": 268435456,
+ "58:117": 402653184,
+ "59:117": 268435456,
+ "60:117": 402653184,
+ "61:117": 268435456,
+ "62:117": 402653184,
+ "63:117": 268435456,
+ "64:117": 402653184,
+ "65:117": 268435456,
+ "66:117": 402653184,
+ "67:117": 268435456,
+ "68:117": 402653184,
+ "69:117": 268435456,
+ "70:117": 402653184,
+ "71:117": 268435456,
+ "72:117": 402653184,
+ "73:117": 268435456,
+ "74:117": 402653184,
+ "75:117": 268435456,
+ "76:117": 402653184,
+ "77:117": 268435456,
+ "78:117": 402653184,
+ "79:117": 268435456,
+ "80:117": 402653184,
+ "81:117": 268435456,
+ "82:117": 402653184,
+ "83:117": 268435456,
+ "84:117": 402653184,
+ "85:117": 268435456,
+ "86:117": 402653184,
+ "87:117": 268435456,
+ "88:117": 402653184,
+ "89:117": 268435456,
+ "90:117": 402653184,
+ "91:117": 268435456,
+ "92:117": 402653184,
+ "93:117": 268435456,
+ "94:117": 402653184,
+ "95:117": 268435456,
+ "96:117": 402653184,
+ "97:117": 268435456,
+ "98:117": 402653184,
+ "99:117": 268435456,
+ "100:117": 402653184,
+ "101:117": 268435456,
+ "102:117": 402653184,
+ "103:117": 268435456,
+ "104:117": 402653184,
+ "105:117": 268435456,
+ "106:117": 402653184,
+ "107:117": 268435456,
+ "108:117": 402653184,
+ "109:117": 268435456,
+ "110:117": 402653184,
+ "111:117": 268435456,
+ "112:117": 402653184,
+ "113:117": 268435456,
+ "114:117": 402653184,
+ "115:117": 268435456,
+ "116:117": 402653184,
+ "117:117": 268435456,
+ "118:117": 402653184,
+ "119:117": 268435456,
+ "120:117": 402653184,
+ "121:117": 268435456,
+ "122:117": 402653184,
+ "123:117": 268435456,
+ "124:117": 402653184,
+ "125:117": 268435456,
+ "126:117": 402653184,
+ "127:117": 268435456,
+ "0:118": 268435456,
+ "1:118": 402653184,
+ "2:118": 268435456,
+ "3:118": 402653184,
+ "4:118": 268435456,
+ "5:118": 402653184,
+ "6:118": 268435456,
+ "7:118": 402653184,
+ "8:118": 268435456,
+ "9:118": 402653184,
+ "10:118": 268435456,
+ "11:118": 402653184,
+ "12:118": 268435456,
+ "13:118": 402653184,
+ "14:118": 268435456,
+ "15:118": 402653184,
+ "16:118": 268435456,
+ "17:118": 402653184,
+ "18:118": 268435456,
+ "19:118": 402653184,
+ "20:118": 268435456,
+ "21:118": 402653184,
+ "22:118": 268435456,
+ "23:118": 402653184,
+ "24:118": 268435456,
+ "25:118": 402653184,
+ "26:118": 268435456,
+ "27:118": 402653184,
+ "28:118": 268435456,
+ "29:118": 402653184,
+ "30:118": 268435456,
+ "31:118": 402653184,
+ "32:118": 268435456,
+ "33:118": 402653184,
+ "34:118": 268435456,
+ "35:118": 402653184,
+ "36:118": 268435456,
+ "37:118": 402653184,
+ "38:118": 268435456,
+ "39:118": 402653184,
+ "40:118": 268435456,
+ "41:118": 402653184,
+ "42:118": 268435456,
+ "43:118": 402653184,
+ "44:118": 268435456,
+ "45:118": 402653184,
+ "46:118": 268435456,
+ "47:118": 402653184,
+ "48:118": 268435456,
+ "49:118": 402653184,
+ "50:118": 268435456,
+ "51:118": 402653184,
+ "52:118": 268435456,
+ "53:118": 402653184,
+ "54:118": 268435456,
+ "55:118": 402653184,
+ "56:118": 268435456,
+ "57:118": 402653184,
+ "58:118": 268435456,
+ "59:118": 402653184,
+ "60:118": 268435456,
+ "61:118": 402653184,
+ "62:118": 268435456,
+ "63:118": 402653184,
+ "64:118": 268435456,
+ "65:118": 402653184,
+ "66:118": 268435456,
+ "67:118": 402653184,
+ "68:118": 268435456,
+ "69:118": 402653184,
+ "70:118": 268435456,
+ "71:118": 402653184,
+ "72:118": 268435456,
+ "73:118": 402653184,
+ "74:118": 268435456,
+ "75:118": 402653184,
+ "76:118": 268435456,
+ "77:118": 402653184,
+ "78:118": 268435456,
+ "79:118": 402653184,
+ "80:118": 268435456,
+ "81:118": 402653184,
+ "82:118": 268435456,
+ "83:118": 402653184,
+ "84:118": 268435456,
+ "85:118": 402653184,
+ "86:118": 268435456,
+ "87:118": 402653184,
+ "88:118": 268435456,
+ "89:118": 402653184,
+ "90:118": 268435456,
+ "91:118": 402653184,
+ "92:118": 268435456,
+ "93:118": 402653184,
+ "94:118": 268435456,
+ "95:118": 402653184,
+ "96:118": 268435456,
+ "97:118": 402653184,
+ "98:118": 268435456,
+ "99:118": 402653184,
+ "100:118": 268435456,
+ "101:118": 402653184,
+ "102:118": 268435456,
+ "103:118": 402653184,
+ "104:118": 268435456,
+ "105:118": 402653184,
+ "106:118": 268435456,
+ "107:118": 402653184,
+ "108:118": 268435456,
+ "109:118": 402653184,
+ "110:118": 268435456,
+ "111:118": 402653184,
+ "112:118": 268435456,
+ "113:118": 402653184,
+ "114:118": 268435456,
+ "115:118": 402653184,
+ "116:118": 268435456,
+ "117:118": 402653184,
+ "118:118": 268435456,
+ "119:118": 402653184,
+ "120:118": 268435456,
+ "121:118": 402653184,
+ "122:118": 268435456,
+ "123:118": 402653184,
+ "124:118": 268435456,
+ "125:118": 402653184,
+ "126:118": 268435456,
+ "127:118": 402653184,
+ "0:119": 402653184,
+ "1:119": 268435456,
+ "2:119": 402653184,
+ "3:119": 268435456,
+ "4:119": 402653184,
+ "5:119": 268435456,
+ "6:119": 402653184,
+ "7:119": 268435456,
+ "8:119": 402653184,
+ "9:119": 268435456,
+ "10:119": 402653184,
+ "11:119": 268435456,
+ "12:119": 402653184,
+ "13:119": 268435456,
+ "14:119": 402653184,
+ "15:119": 268435456,
+ "16:119": 402653184,
+ "17:119": 268435456,
+ "18:119": 402653184,
+ "19:119": 268435456,
+ "20:119": 402653184,
+ "21:119": 268435456,
+ "22:119": 402653184,
+ "23:119": 268435456,
+ "24:119": 402653184,
+ "25:119": 268435456,
+ "26:119": 402653184,
+ "27:119": 268435456,
+ "28:119": 402653184,
+ "29:119": 268435456,
+ "30:119": 402653184,
+ "31:119": 268435456,
+ "32:119": 402653184,
+ "33:119": 268435456,
+ "34:119": 402653184,
+ "35:119": 268435456,
+ "36:119": 402653184,
+ "37:119": 268435456,
+ "38:119": 402653184,
+ "39:119": 268435456,
+ "40:119": 402653184,
+ "41:119": 268435456,
+ "42:119": 402653184,
+ "43:119": 268435456,
+ "44:119": 402653184,
+ "45:119": 268435456,
+ "46:119": 402653184,
+ "47:119": 268435456,
+ "48:119": 402653184,
+ "49:119": 268435456,
+ "50:119": 402653184,
+ "51:119": 268435456,
+ "52:119": 402653184,
+ "53:119": 268435456,
+ "54:119": 402653184,
+ "55:119": 268435456,
+ "56:119": 402653184,
+ "57:119": 268435456,
+ "58:119": 402653184,
+ "59:119": 268435456,
+ "60:119": 402653184,
+ "61:119": 268435456,
+ "62:119": 402653184,
+ "63:119": 268435456,
+ "64:119": 402653184,
+ "65:119": 268435456,
+ "66:119": 402653184,
+ "67:119": 268435456,
+ "68:119": 402653184,
+ "69:119": 268435456,
+ "70:119": 402653184,
+ "71:119": 268435456,
+ "72:119": 402653184,
+ "73:119": 268435456,
+ "74:119": 402653184,
+ "75:119": 268435456,
+ "76:119": 402653184,
+ "77:119": 268435456,
+ "78:119": 402653184,
+ "79:119": 268435456,
+ "80:119": 402653184,
+ "81:119": 268435456,
+ "82:119": 402653184,
+ "83:119": 268435456,
+ "84:119": 402653184,
+ "85:119": 268435456,
+ "86:119": 402653184,
+ "87:119": 268435456,
+ "88:119": 402653184,
+ "89:119": 268435456,
+ "90:119": 402653184,
+ "91:119": 268435456,
+ "92:119": 402653184,
+ "93:119": 268435456,
+ "94:119": 402653184,
+ "95:119": 268435456,
+ "96:119": 402653184,
+ "97:119": 268435456,
+ "98:119": 402653184,
+ "99:119": 268435456,
+ "100:119": 402653184,
+ "101:119": 268435456,
+ "102:119": 402653184,
+ "103:119": 268435456,
+ "104:119": 402653184,
+ "105:119": 268435456,
+ "106:119": 402653184,
+ "107:119": 268435456,
+ "108:119": 402653184,
+ "109:119": 268435456,
+ "110:119": 402653184,
+ "111:119": 268435456,
+ "112:119": 402653184,
+ "113:119": 268435456,
+ "114:119": 402653184,
+ "115:119": 268435456,
+ "116:119": 402653184,
+ "117:119": 268435456,
+ "118:119": 402653184,
+ "119:119": 268435456,
+ "120:119": 402653184,
+ "121:119": 268435456,
+ "122:119": 402653184,
+ "123:119": 268435456,
+ "124:119": 402653184,
+ "125:119": 268435456,
+ "126:119": 402653184,
+ "127:119": 268435456,
+ "0:120": 268435456,
+ "1:120": 402653184,
+ "2:120": 268435456,
+ "3:120": 402653184,
+ "4:120": 268435456,
+ "5:120": 402653184,
+ "6:120": 268435456,
+ "7:120": 402653184,
+ "8:120": 268435456,
+ "9:120": 402653184,
+ "10:120": 268435456,
+ "11:120": 402653184,
+ "12:120": 268435456,
+ "13:120": 402653184,
+ "14:120": 268435456,
+ "15:120": 402653184,
+ "16:120": 268435456,
+ "17:120": 402653184,
+ "18:120": 268435456,
+ "19:120": 402653184,
+ "20:120": 268435456,
+ "21:120": 402653184,
+ "22:120": 268435456,
+ "23:120": 402653184,
+ "24:120": 268435456,
+ "25:120": 402653184,
+ "26:120": 268435456,
+ "27:120": 402653184,
+ "28:120": 268435456,
+ "29:120": 402653184,
+ "30:120": 268435456,
+ "31:120": 402653184,
+ "32:120": 268435456,
+ "33:120": 402653184,
+ "34:120": 268435456,
+ "35:120": 402653184,
+ "36:120": 268435456,
+ "37:120": 402653184,
+ "38:120": 268435456,
+ "39:120": 402653184,
+ "40:120": 268435456,
+ "41:120": 402653184,
+ "42:120": 268435456,
+ "43:120": 402653184,
+ "44:120": 268435456,
+ "45:120": 402653184,
+ "46:120": 268435456,
+ "47:120": 402653184,
+ "48:120": 268435456,
+ "49:120": 402653184,
+ "50:120": 268435456,
+ "51:120": 402653184,
+ "52:120": 268435456,
+ "53:120": 402653184,
+ "54:120": 268435456,
+ "55:120": 402653184,
+ "56:120": 268435456,
+ "57:120": 402653184,
+ "58:120": 268435456,
+ "59:120": 402653184,
+ "60:120": 268435456,
+ "61:120": 402653184,
+ "62:120": 268435456,
+ "63:120": 402653184,
+ "64:120": 268435456,
+ "65:120": 402653184,
+ "66:120": 268435456,
+ "67:120": 402653184,
+ "68:120": 268435456,
+ "69:120": 402653184,
+ "70:120": 268435456,
+ "71:120": 402653184,
+ "72:120": 268435456,
+ "73:120": 402653184,
+ "74:120": 268435456,
+ "75:120": 402653184,
+ "76:120": 268435456,
+ "77:120": 402653184,
+ "78:120": 268435456,
+ "79:120": 402653184,
+ "80:120": 268435456,
+ "81:120": 402653184,
+ "82:120": 268435456,
+ "83:120": 402653184,
+ "84:120": 268435456,
+ "85:120": 402653184,
+ "86:120": 268435456,
+ "87:120": 402653184,
+ "88:120": 268435456,
+ "89:120": 402653184,
+ "90:120": 268435456,
+ "91:120": 402653184,
+ "92:120": 268435456,
+ "93:120": 402653184,
+ "94:120": 268435456,
+ "95:120": 402653184,
+ "96:120": 268435456,
+ "97:120": 402653184,
+ "98:120": 268435456,
+ "99:120": 402653184,
+ "100:120": 268435456,
+ "101:120": 402653184,
+ "102:120": 268435456,
+ "103:120": 402653184,
+ "104:120": 268435456,
+ "105:120": 402653184,
+ "106:120": 268435456,
+ "107:120": 402653184,
+ "108:120": 268435456,
+ "109:120": 402653184,
+ "110:120": 268435456,
+ "111:120": 402653184,
+ "112:120": 268435456,
+ "113:120": 402653184,
+ "114:120": 268435456,
+ "115:120": 402653184,
+ "116:120": 268435456,
+ "117:120": 402653184,
+ "118:120": 268435456,
+ "119:120": 402653184,
+ "120:120": 268435456,
+ "121:120": 402653184,
+ "122:120": 268435456,
+ "123:120": 402653184,
+ "124:120": 268435456,
+ "125:120": 402653184,
+ "126:120": 268435456,
+ "127:120": 402653184,
+ "0:121": 402653184,
+ "1:121": 268435456,
+ "2:121": 402653184,
+ "3:121": 268435456,
+ "4:121": 402653184,
+ "5:121": 268435456,
+ "6:121": 402653184,
+ "7:121": 268435456,
+ "8:121": 402653184,
+ "9:121": 268435456,
+ "10:121": 402653184,
+ "11:121": 268435456,
+ "12:121": 402653184,
+ "13:121": 268435456,
+ "14:121": 402653184,
+ "15:121": 268435456,
+ "16:121": 402653184,
+ "17:121": 268435456,
+ "18:121": 402653184,
+ "19:121": 268435456,
+ "20:121": 402653184,
+ "21:121": 268435456,
+ "22:121": 402653184,
+ "23:121": 268435456,
+ "24:121": 402653184,
+ "25:121": 268435456,
+ "26:121": 402653184,
+ "27:121": 268435456,
+ "28:121": 402653184,
+ "29:121": 268435456,
+ "30:121": 402653184,
+ "31:121": 268435456,
+ "32:121": 402653184,
+ "33:121": 268435456,
+ "34:121": 402653184,
+ "35:121": 268435456,
+ "36:121": 402653184,
+ "37:121": 268435456,
+ "38:121": 402653184,
+ "39:121": 268435456,
+ "40:121": 402653184,
+ "41:121": 268435456,
+ "42:121": 402653184,
+ "43:121": 268435456,
+ "44:121": 402653184,
+ "45:121": 268435456,
+ "46:121": 402653184,
+ "47:121": 268435456,
+ "48:121": 402653184,
+ "49:121": 268435456,
+ "50:121": 402653184,
+ "51:121": 268435456,
+ "52:121": 402653184,
+ "53:121": 268435456,
+ "54:121": 402653184,
+ "55:121": 268435456,
+ "56:121": 402653184,
+ "57:121": 268435456,
+ "58:121": 402653184,
+ "59:121": 268435456,
+ "60:121": 402653184,
+ "61:121": 268435456,
+ "62:121": 402653184,
+ "63:121": 268435456,
+ "64:121": 402653184,
+ "65:121": 268435456,
+ "66:121": 402653184,
+ "67:121": 268435456,
+ "68:121": 402653184,
+ "69:121": 268435456,
+ "70:121": 402653184,
+ "71:121": 268435456,
+ "72:121": 402653184,
+ "73:121": 268435456,
+ "74:121": 402653184,
+ "75:121": 268435456,
+ "76:121": 402653184,
+ "77:121": 268435456,
+ "78:121": 402653184,
+ "79:121": 268435456,
+ "80:121": 402653184,
+ "81:121": 268435456,
+ "82:121": 402653184,
+ "83:121": 268435456,
+ "84:121": 402653184,
+ "85:121": 268435456,
+ "86:121": 402653184,
+ "87:121": 268435456,
+ "88:121": 402653184,
+ "89:121": 268435456,
+ "90:121": 402653184,
+ "91:121": 268435456,
+ "92:121": 402653184,
+ "93:121": 268435456,
+ "94:121": 402653184,
+ "95:121": 268435456,
+ "96:121": 402653184,
+ "97:121": 268435456,
+ "98:121": 402653184,
+ "99:121": 268435456,
+ "100:121": 402653184,
+ "101:121": 268435456,
+ "102:121": 402653184,
+ "103:121": 268435456,
+ "104:121": 402653184,
+ "105:121": 268435456,
+ "106:121": 402653184,
+ "107:121": 268435456,
+ "108:121": 402653184,
+ "109:121": 268435456,
+ "110:121": 402653184,
+ "111:121": 268435456,
+ "112:121": 402653184,
+ "113:121": 268435456,
+ "114:121": 402653184,
+ "115:121": 268435456,
+ "116:121": 402653184,
+ "117:121": 268435456,
+ "118:121": 402653184,
+ "119:121": 268435456,
+ "120:121": 402653184,
+ "121:121": 268435456,
+ "122:121": 402653184,
+ "123:121": 268435456,
+ "124:121": 402653184,
+ "125:121": 268435456,
+ "126:121": 402653184,
+ "127:121": 268435456,
+ "0:122": 268435456,
+ "1:122": 402653184,
+ "2:122": 268435456,
+ "3:122": 402653184,
+ "4:122": 268435456,
+ "5:122": 402653184,
+ "6:122": 268435456,
+ "7:122": 402653184,
+ "8:122": 268435456,
+ "9:122": 402653184,
+ "10:122": 268435456,
+ "11:122": 402653184,
+ "12:122": 268435456,
+ "13:122": 402653184,
+ "14:122": 268435456,
+ "15:122": 402653184,
+ "16:122": 268435456,
+ "17:122": 402653184,
+ "18:122": 268435456,
+ "19:122": 402653184,
+ "20:122": 268435456,
+ "21:122": 402653184,
+ "22:122": 268435456,
+ "23:122": 402653184,
+ "24:122": 268435456,
+ "25:122": 402653184,
+ "26:122": 268435456,
+ "27:122": 402653184,
+ "28:122": 268435456,
+ "29:122": 402653184,
+ "30:122": 268435456,
+ "31:122": 402653184,
+ "32:122": 268435456,
+ "33:122": 402653184,
+ "34:122": 268435456,
+ "35:122": 402653184,
+ "36:122": 268435456,
+ "37:122": 402653184,
+ "38:122": 268435456,
+ "39:122": 402653184,
+ "40:122": 268435456,
+ "41:122": 402653184,
+ "42:122": 268435456,
+ "43:122": 402653184,
+ "44:122": 268435456,
+ "45:122": 402653184,
+ "46:122": 268435456,
+ "47:122": 402653184,
+ "48:122": 268435456,
+ "49:122": 402653184,
+ "50:122": 268435456,
+ "51:122": 402653184,
+ "52:122": 268435456,
+ "53:122": 402653184,
+ "54:122": 268435456,
+ "55:122": 402653184,
+ "56:122": 268435456,
+ "57:122": 402653184,
+ "58:122": 268435456,
+ "59:122": 402653184,
+ "60:122": 268435456,
+ "61:122": 402653184,
+ "62:122": 268435456,
+ "63:122": 402653184,
+ "64:122": 268435456,
+ "65:122": 402653184,
+ "66:122": 268435456,
+ "67:122": 402653184,
+ "68:122": 268435456,
+ "69:122": 402653184,
+ "70:122": 268435456,
+ "71:122": 402653184,
+ "72:122": 268435456,
+ "73:122": 402653184,
+ "74:122": 268435456,
+ "75:122": 402653184,
+ "76:122": 268435456,
+ "77:122": 402653184,
+ "78:122": 268435456,
+ "79:122": 402653184,
+ "80:122": 268435456,
+ "81:122": 402653184,
+ "82:122": 268435456,
+ "83:122": 402653184,
+ "84:122": 268435456,
+ "85:122": 402653184,
+ "86:122": 268435456,
+ "87:122": 402653184,
+ "88:122": 268435456,
+ "89:122": 402653184,
+ "90:122": 268435456,
+ "91:122": 402653184,
+ "92:122": 268435456,
+ "93:122": 402653184,
+ "94:122": 268435456,
+ "95:122": 402653184,
+ "96:122": 268435456,
+ "97:122": 402653184,
+ "98:122": 268435456,
+ "99:122": 402653184,
+ "100:122": 268435456,
+ "101:122": 402653184,
+ "102:122": 268435456,
+ "103:122": 402653184,
+ "104:122": 268435456,
+ "105:122": 402653184,
+ "106:122": 268435456,
+ "107:122": 402653184,
+ "108:122": 268435456,
+ "109:122": 402653184,
+ "110:122": 268435456,
+ "111:122": 402653184,
+ "112:122": 268435456,
+ "113:122": 402653184,
+ "114:122": 268435456,
+ "115:122": 402653184,
+ "116:122": 268435456,
+ "117:122": 402653184,
+ "118:122": 268435456,
+ "119:122": 402653184,
+ "120:122": 268435456,
+ "121:122": 402653184,
+ "122:122": 268435456,
+ "123:122": 402653184,
+ "124:122": 268435456,
+ "125:122": 402653184,
+ "126:122": 268435456,
+ "127:122": 402653184,
+ "0:123": 402653184,
+ "1:123": 268435456,
+ "2:123": 402653184,
+ "3:123": 268435456,
+ "4:123": 402653184,
+ "5:123": 268435456,
+ "6:123": 402653184,
+ "7:123": 268435456,
+ "8:123": 402653184,
+ "9:123": 268435456,
+ "10:123": 402653184,
+ "11:123": 268435456,
+ "12:123": 402653184,
+ "13:123": 268435456,
+ "14:123": 402653184,
+ "15:123": 268435456,
+ "16:123": 402653184,
+ "17:123": 268435456,
+ "18:123": 402653184,
+ "19:123": 268435456,
+ "20:123": 402653184,
+ "21:123": 268435456,
+ "22:123": 402653184,
+ "23:123": 268435456,
+ "24:123": 402653184,
+ "25:123": 268435456,
+ "26:123": 402653184,
+ "27:123": 268435456,
+ "28:123": 402653184,
+ "29:123": 268435456,
+ "30:123": 402653184,
+ "31:123": 268435456,
+ "32:123": 402653184,
+ "33:123": 268435456,
+ "34:123": 402653184,
+ "35:123": 268435456,
+ "36:123": 402653184,
+ "37:123": 268435456,
+ "38:123": 402653184,
+ "39:123": 268435456,
+ "40:123": 402653184,
+ "41:123": 268435456,
+ "42:123": 402653184,
+ "43:123": 268435456,
+ "44:123": 402653184,
+ "45:123": 268435456,
+ "46:123": 402653184,
+ "47:123": 268435456,
+ "48:123": 402653184,
+ "49:123": 268435456,
+ "50:123": 402653184,
+ "51:123": 268435456,
+ "52:123": 402653184,
+ "53:123": 268435456,
+ "54:123": 402653184,
+ "55:123": 268435456,
+ "56:123": 402653184,
+ "57:123": 268435456,
+ "58:123": 402653184,
+ "59:123": 268435456,
+ "60:123": 402653184,
+ "61:123": 268435456,
+ "62:123": 402653184,
+ "63:123": 268435456,
+ "64:123": 402653184,
+ "65:123": 268435456,
+ "66:123": 402653184,
+ "67:123": 268435456,
+ "68:123": 402653184,
+ "69:123": 268435456,
+ "70:123": 402653184,
+ "71:123": 268435456,
+ "72:123": 402653184,
+ "73:123": 268435456,
+ "74:123": 402653184,
+ "75:123": 268435456,
+ "76:123": 402653184,
+ "77:123": 268435456,
+ "78:123": 402653184,
+ "79:123": 268435456,
+ "80:123": 402653184,
+ "81:123": 268435456,
+ "82:123": 402653184,
+ "83:123": 268435456,
+ "84:123": 402653184,
+ "85:123": 268435456,
+ "86:123": 402653184,
+ "87:123": 268435456,
+ "88:123": 402653184,
+ "89:123": 268435456,
+ "90:123": 402653184,
+ "91:123": 268435456,
+ "92:123": 402653184,
+ "93:123": 268435456,
+ "94:123": 402653184,
+ "95:123": 268435456,
+ "96:123": 402653184,
+ "97:123": 268435456,
+ "98:123": 402653184,
+ "99:123": 268435456,
+ "100:123": 402653184,
+ "101:123": 268435456,
+ "102:123": 402653184,
+ "103:123": 268435456,
+ "104:123": 402653184,
+ "105:123": 268435456,
+ "106:123": 402653184,
+ "107:123": 268435456,
+ "108:123": 402653184,
+ "109:123": 268435456,
+ "110:123": 402653184,
+ "111:123": 268435456,
+ "112:123": 402653184,
+ "113:123": 268435456,
+ "114:123": 402653184,
+ "115:123": 268435456,
+ "116:123": 402653184,
+ "117:123": 268435456,
+ "118:123": 402653184,
+ "119:123": 268435456,
+ "120:123": 402653184,
+ "121:123": 268435456,
+ "122:123": 402653184,
+ "123:123": 268435456,
+ "124:123": 402653184,
+ "125:123": 268435456,
+ "126:123": 402653184,
+ "127:123": 268435456,
+ "0:124": 268435456,
+ "1:124": 402653184,
+ "2:124": 268435456,
+ "3:124": 402653184,
+ "4:124": 268435456,
+ "5:124": 402653184,
+ "6:124": 268435456,
+ "7:124": 402653184,
+ "8:124": 268435456,
+ "9:124": 402653184,
+ "10:124": 268435456,
+ "11:124": 402653184,
+ "12:124": 268435456,
+ "13:124": 402653184,
+ "14:124": 268435456,
+ "15:124": 402653184,
+ "16:124": 268435456,
+ "17:124": 402653184,
+ "18:124": 268435456,
+ "19:124": 402653184,
+ "20:124": 268435456,
+ "21:124": 402653184,
+ "22:124": 268435456,
+ "23:124": 402653184,
+ "24:124": 268435456,
+ "25:124": 402653184,
+ "26:124": 268435456,
+ "27:124": 402653184,
+ "28:124": 268435456,
+ "29:124": 402653184,
+ "30:124": 268435456,
+ "31:124": 402653184,
+ "32:124": 268435456,
+ "33:124": 402653184,
+ "34:124": 268435456,
+ "35:124": 402653184,
+ "36:124": 268435456,
+ "37:124": 402653184,
+ "38:124": 268435456,
+ "39:124": 402653184,
+ "40:124": 268435456,
+ "41:124": 402653184,
+ "42:124": 268435456,
+ "43:124": 402653184,
+ "44:124": 268435456,
+ "45:124": 402653184,
+ "46:124": 268435456,
+ "47:124": 402653184,
+ "48:124": 268435456,
+ "49:124": 402653184,
+ "50:124": 268435456,
+ "51:124": 402653184,
+ "52:124": 268435456,
+ "53:124": 402653184,
+ "54:124": 268435456,
+ "55:124": 402653184,
+ "56:124": 268435456,
+ "57:124": 402653184,
+ "58:124": 268435456,
+ "59:124": 402653184,
+ "60:124": 268435456,
+ "61:124": 402653184,
+ "62:124": 268435456,
+ "63:124": 402653184,
+ "64:124": 268435456,
+ "65:124": 402653184,
+ "66:124": 268435456,
+ "67:124": 402653184,
+ "68:124": 268435456,
+ "69:124": 402653184,
+ "70:124": 268435456,
+ "71:124": 402653184,
+ "72:124": 268435456,
+ "73:124": 402653184,
+ "74:124": 268435456,
+ "75:124": 402653184,
+ "76:124": 268435456,
+ "77:124": 402653184,
+ "78:124": 268435456,
+ "79:124": 402653184,
+ "80:124": 268435456,
+ "81:124": 402653184,
+ "82:124": 268435456,
+ "83:124": 402653184,
+ "84:124": 268435456,
+ "85:124": 402653184,
+ "86:124": 268435456,
+ "87:124": 402653184,
+ "88:124": 268435456,
+ "89:124": 402653184,
+ "90:124": 268435456,
+ "91:124": 402653184,
+ "92:124": 268435456,
+ "93:124": 402653184,
+ "94:124": 268435456,
+ "95:124": 402653184,
+ "96:124": 268435456,
+ "97:124": 402653184,
+ "98:124": 268435456,
+ "99:124": 402653184,
+ "100:124": 268435456,
+ "101:124": 402653184,
+ "102:124": 268435456,
+ "103:124": 402653184,
+ "104:124": 268435456,
+ "105:124": 402653184,
+ "106:124": 268435456,
+ "107:124": 402653184,
+ "108:124": 268435456,
+ "109:124": 402653184,
+ "110:124": 268435456,
+ "111:124": 402653184,
+ "112:124": 268435456,
+ "113:124": 402653184,
+ "114:124": 268435456,
+ "115:124": 402653184,
+ "116:124": 268435456,
+ "117:124": 402653184,
+ "118:124": 268435456,
+ "119:124": 402653184,
+ "120:124": 268435456,
+ "121:124": 402653184,
+ "122:124": 268435456,
+ "123:124": 402653184,
+ "124:124": 268435456,
+ "125:124": 402653184,
+ "126:124": 268435456,
+ "127:124": 402653184,
+ "0:125": 402653184,
+ "1:125": 268435456,
+ "2:125": 402653184,
+ "3:125": 268435456,
+ "4:125": 402653184,
+ "5:125": 268435456,
+ "6:125": 402653184,
+ "7:125": 268435456,
+ "8:125": 402653184,
+ "9:125": 268435456,
+ "10:125": 402653184,
+ "11:125": 268435456,
+ "12:125": 402653184,
+ "13:125": 268435456,
+ "14:125": 402653184,
+ "15:125": 268435456,
+ "16:125": 402653184,
+ "17:125": 268435456,
+ "18:125": 402653184,
+ "19:125": 268435456,
+ "20:125": 402653184,
+ "21:125": 268435456,
+ "22:125": 402653184,
+ "23:125": 268435456,
+ "24:125": 402653184,
+ "25:125": 268435456,
+ "26:125": 402653184,
+ "27:125": 268435456,
+ "28:125": 402653184,
+ "29:125": 268435456,
+ "30:125": 402653184,
+ "31:125": 268435456,
+ "32:125": 402653184,
+ "33:125": 268435456,
+ "34:125": 402653184,
+ "35:125": 268435456,
+ "36:125": 402653184,
+ "37:125": 268435456,
+ "38:125": 402653184,
+ "39:125": 268435456,
+ "40:125": 402653184,
+ "41:125": 268435456,
+ "42:125": 402653184,
+ "43:125": 268435456,
+ "44:125": 402653184,
+ "45:125": 268435456,
+ "46:125": 402653184,
+ "47:125": 268435456,
+ "48:125": 402653184,
+ "49:125": 268435456,
+ "50:125": 402653184,
+ "51:125": 268435456,
+ "52:125": 402653184,
+ "53:125": 268435456,
+ "54:125": 402653184,
+ "55:125": 268435456,
+ "56:125": 402653184,
+ "57:125": 268435456,
+ "58:125": 402653184,
+ "59:125": 268435456,
+ "60:125": 402653184,
+ "61:125": 268435456,
+ "62:125": 402653184,
+ "63:125": 268435456,
+ "64:125": 402653184,
+ "65:125": 268435456,
+ "66:125": 402653184,
+ "67:125": 268435456,
+ "68:125": 402653184,
+ "69:125": 268435456,
+ "70:125": 402653184,
+ "71:125": 268435456,
+ "72:125": 402653184,
+ "73:125": 268435456,
+ "74:125": 402653184,
+ "75:125": 268435456,
+ "76:125": 402653184,
+ "77:125": 268435456,
+ "78:125": 402653184,
+ "79:125": 268435456,
+ "80:125": 402653184,
+ "81:125": 268435456,
+ "82:125": 402653184,
+ "83:125": 268435456,
+ "84:125": 402653184,
+ "85:125": 268435456,
+ "86:125": 402653184,
+ "87:125": 268435456,
+ "88:125": 402653184,
+ "89:125": 268435456,
+ "90:125": 402653184,
+ "91:125": 268435456,
+ "92:125": 402653184,
+ "93:125": 268435456,
+ "94:125": 402653184,
+ "95:125": 268435456,
+ "96:125": 402653184,
+ "97:125": 268435456,
+ "98:125": 402653184,
+ "99:125": 268435456,
+ "100:125": 402653184,
+ "101:125": 268435456,
+ "102:125": 402653184,
+ "103:125": 268435456,
+ "104:125": 402653184,
+ "105:125": 268435456,
+ "106:125": 402653184,
+ "107:125": 268435456,
+ "108:125": 402653184,
+ "109:125": 268435456,
+ "110:125": 402653184,
+ "111:125": 268435456,
+ "112:125": 402653184,
+ "113:125": 268435456,
+ "114:125": 402653184,
+ "115:125": 268435456,
+ "116:125": 402653184,
+ "117:125": 268435456,
+ "118:125": 402653184,
+ "119:125": 268435456,
+ "120:125": 402653184,
+ "121:125": 268435456,
+ "122:125": 402653184,
+ "123:125": 268435456,
+ "124:125": 402653184,
+ "125:125": 268435456,
+ "126:125": 402653184,
+ "127:125": 268435456,
+ "0:126": 268435456,
+ "1:126": 402653184,
+ "2:126": 268435456,
+ "3:126": 402653184,
+ "4:126": 268435456,
+ "5:126": 402653184,
+ "6:126": 268435456,
+ "7:126": 402653184,
+ "8:126": 268435456,
+ "9:126": 402653184,
+ "10:126": 268435456,
+ "11:126": 402653184,
+ "12:126": 268435456,
+ "13:126": 402653184,
+ "14:126": 268435456,
+ "15:126": 402653184,
+ "16:126": 268435456,
+ "17:126": 402653184,
+ "18:126": 268435456,
+ "19:126": 402653184,
+ "20:126": 268435456,
+ "21:126": 402653184,
+ "22:126": 268435456,
+ "23:126": 402653184,
+ "24:126": 268435456,
+ "25:126": 402653184,
+ "26:126": 268435456,
+ "27:126": 402653184,
+ "28:126": 268435456,
+ "29:126": 402653184,
+ "30:126": 268435456,
+ "31:126": 402653184,
+ "32:126": 268435456,
+ "33:126": 402653184,
+ "34:126": 268435456,
+ "35:126": 402653184,
+ "36:126": 268435456,
+ "37:126": 402653184,
+ "38:126": 268435456,
+ "39:126": 402653184,
+ "40:126": 268435456,
+ "41:126": 402653184,
+ "42:126": 268435456,
+ "43:126": 402653184,
+ "44:126": 268435456,
+ "45:126": 402653184,
+ "46:126": 268435456,
+ "47:126": 402653184,
+ "48:126": 268435456,
+ "49:126": 402653184,
+ "50:126": 268435456,
+ "51:126": 402653184,
+ "52:126": 268435456,
+ "53:126": 402653184,
+ "54:126": 268435456,
+ "55:126": 402653184,
+ "56:126": 268435456,
+ "57:126": 402653184,
+ "58:126": 268435456,
+ "59:126": 402653184,
+ "60:126": 268435456,
+ "61:126": 402653184,
+ "62:126": 268435456,
+ "63:126": 402653184,
+ "64:126": 268435456,
+ "65:126": 402653184,
+ "66:126": 268435456,
+ "67:126": 402653184,
+ "68:126": 268435456,
+ "69:126": 402653184,
+ "70:126": 268435456,
+ "71:126": 402653184,
+ "72:126": 268435456,
+ "73:126": 402653184,
+ "74:126": 268435456,
+ "75:126": 402653184,
+ "76:126": 268435456,
+ "77:126": 402653184,
+ "78:126": 268435456,
+ "79:126": 402653184,
+ "80:126": 268435456,
+ "81:126": 402653184,
+ "82:126": 268435456,
+ "83:126": 402653184,
+ "84:126": 268435456,
+ "85:126": 402653184,
+ "86:126": 268435456,
+ "87:126": 402653184,
+ "88:126": 268435456,
+ "89:126": 402653184,
+ "90:126": 268435456,
+ "91:126": 402653184,
+ "92:126": 268435456,
+ "93:126": 402653184,
+ "94:126": 268435456,
+ "95:126": 402653184,
+ "96:126": 268435456,
+ "97:126": 402653184,
+ "98:126": 268435456,
+ "99:126": 402653184,
+ "100:126": 268435456,
+ "101:126": 402653184,
+ "102:126": 268435456,
+ "103:126": 402653184,
+ "104:126": 268435456,
+ "105:126": 402653184,
+ "106:126": 268435456,
+ "107:126": 402653184,
+ "108:126": 268435456,
+ "109:126": 402653184,
+ "110:126": 268435456,
+ "111:126": 402653184,
+ "112:126": 268435456,
+ "113:126": 402653184,
+ "114:126": 268435456,
+ "115:126": 402653184,
+ "116:126": 268435456,
+ "117:126": 402653184,
+ "118:126": 268435456,
+ "119:126": 402653184,
+ "120:126": 268435456,
+ "121:126": 402653184,
+ "122:126": 268435456,
+ "123:126": 402653184,
+ "124:126": 268435456,
+ "125:126": 402653184,
+ "126:126": 268435456,
+ "127:126": 402653184,
+ "0:127": 402653184,
+ "1:127": 268435456,
+ "2:127": 402653184,
+ "3:127": 268435456,
+ "4:127": 402653184,
+ "5:127": 268435456,
+ "6:127": 402653184,
+ "7:127": 268435456,
+ "8:127": 402653184,
+ "9:127": 268435456,
+ "10:127": 402653184,
+ "11:127": 268435456,
+ "12:127": 402653184,
+ "13:127": 268435456,
+ "14:127": 402653184,
+ "15:127": 268435456,
+ "16:127": 402653184,
+ "17:127": 268435456,
+ "18:127": 402653184,
+ "19:127": 268435456,
+ "20:127": 402653184,
+ "21:127": 268435456,
+ "22:127": 402653184,
+ "23:127": 268435456,
+ "24:127": 402653184,
+ "25:127": 268435456,
+ "26:127": 402653184,
+ "27:127": 268435456,
+ "28:127": 402653184,
+ "29:127": 268435456,
+ "30:127": 402653184,
+ "31:127": 268435456,
+ "32:127": 402653184,
+ "33:127": 268435456,
+ "34:127": 402653184,
+ "35:127": 268435456,
+ "36:127": 402653184,
+ "37:127": 268435456,
+ "38:127": 402653184,
+ "39:127": 268435456,
+ "40:127": 402653184,
+ "41:127": 268435456,
+ "42:127": 402653184,
+ "43:127": 268435456,
+ "44:127": 402653184,
+ "45:127": 268435456,
+ "46:127": 402653184,
+ "47:127": 268435456,
+ "48:127": 402653184,
+ "49:127": 268435456,
+ "50:127": 402653184,
+ "51:127": 268435456,
+ "52:127": 402653184,
+ "53:127": 268435456,
+ "54:127": 402653184,
+ "55:127": 268435456,
+ "56:127": 402653184,
+ "57:127": 268435456,
+ "58:127": 402653184,
+ "59:127": 268435456,
+ "60:127": 402653184,
+ "61:127": 268435456,
+ "62:127": 402653184,
+ "63:127": 268435456,
+ "64:127": 402653184,
+ "65:127": 268435456,
+ "66:127": 402653184,
+ "67:127": 268435456,
+ "68:127": 402653184,
+ "69:127": 268435456,
+ "70:127": 402653184,
+ "71:127": 268435456,
+ "72:127": 402653184,
+ "73:127": 268435456,
+ "74:127": 402653184,
+ "75:127": 268435456,
+ "76:127": 402653184,
+ "77:127": 268435456,
+ "78:127": 402653184,
+ "79:127": 268435456,
+ "80:127": 402653184,
+ "81:127": 268435456,
+ "82:127": 402653184,
+ "83:127": 268435456,
+ "84:127": 402653184,
+ "85:127": 268435456,
+ "86:127": 402653184,
+ "87:127": 268435456,
+ "88:127": 402653184,
+ "89:127": 268435456,
+ "90:127": 402653184,
+ "91:127": 268435456,
+ "92:127": 402653184,
+ "93:127": 268435456,
+ "94:127": 402653184,
+ "95:127": 268435456,
+ "96:127": 402653184,
+ "97:127": 268435456,
+ "98:127": 402653184,
+ "99:127": 268435456,
+ "100:127": 402653184,
+ "101:127": 268435456,
+ "102:127": 402653184,
+ "103:127": 268435456,
+ "104:127": 402653184,
+ "105:127": 268435456,
+ "106:127": 402653184,
+ "107:127": 268435456,
+ "108:127": 402653184,
+ "109:127": 268435456,
+ "110:127": 402653184,
+ "111:127": 268435456,
+ "112:127": 402653184,
+ "113:127": 268435456,
+ "114:127": 402653184,
+ "115:127": 268435456,
+ "116:127": 402653184,
+ "117:127": 268435456,
+ "118:127": 402653184,
+ "119:127": 268435456,
+ "120:127": 402653184,
+ "121:127": 268435456,
+ "122:127": 402653184,
+ "123:127": 268435456,
+ "124:127": 402653184,
+ "125:127": 268435456,
+ "126:127": 402653184,
+ "127:127": 268435456
+} \ No newline at end of file
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/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..d742301e
--- /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/quickcommand_background.png b/src/main/resources/assets/notenoughupdates/quickcommand_background.png
new file mode 100644
index 00000000..d3c2a3ad
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/quickcommand_background.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/radial_circle_off.png b/src/main/resources/assets/notenoughupdates/radial_circle_off.png
new file mode 100644
index 00000000..300cbcfb
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/radial_circle_off.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/radial_circle_on.png b/src/main/resources/assets/notenoughupdates/radial_circle_on.png
new file mode 100644
index 00000000..4d5cc862
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/radial_circle_on.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/radial_square_off.png b/src/main/resources/assets/notenoughupdates/radial_square_off.png
new file mode 100644
index 00000000..97fbf27e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/radial_square_off.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/radial_square_on.png b/src/main/resources/assets/notenoughupdates/radial_square_on.png
new file mode 100644
index 00000000..5116df80
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/radial_square_on.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/setting_border.png b/src/main/resources/assets/notenoughupdates/setting_border.png
new file mode 100644
index 00000000..e5dff747
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/setting_border.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/lava_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/lava_cape.frag
new file mode 100644
index 00000000..9fb35990
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/lava_cape.frag
@@ -0,0 +1,32 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+uniform sampler2D textureIn;
+
+uniform int millis;
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ float t = gl_TexCoord[0].t;
+ t = clamp(t, 10.0f/1024.0f, 410.0f/1024.0f);
+
+ float index = mod(millis/30.0f-t*1024.0f, 1024.0f);
+ float xIndex = mod(index, 1024.0f);
+ float yIndex = mod(gl_TexCoord[0].s*1024.0f+millis/500.0f, 421.0f)+421.0f;
+ vec3 lava = texture2D(textureIn, vec2(xIndex/1024.0f, yIndex/1024.0f)).xyz;
+
+ float factor = (lava.r / 0.65f)*(lava.r / 0.65f);
+ lava.r += sin(mod(millis/2000.0f, 6.28f))*factor*0.15f+sin(mod(millis/500.0f, 6.28f))*factor*0.15f;
+ lava.g += sin(mod(millis/2000.0f, 6.28f))*factor*0.15f;
+ lava.b += sin(mod(millis/2000.0f, 6.28f))*factor*0.15f;
+
+ gl_FragColor = vec4(texture.rgb*texture.a + lava*(1.0f-texture.a), 1.0f) * passColour;
+
+ 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);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/lava_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/lava_cape.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/lava_cape.vert
@@ -0,0 +1,12 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.frag
new file mode 100644
index 00000000..c4472679
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.frag
@@ -0,0 +1,13 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+uniform sampler2D textureIn;
+
+uniform int millis;
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ gl_FragColor = vec4(texture.rgb*shading, gl_FragColor.a);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/lightning_cape.vert
@@ -0,0 +1,12 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+} \ 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/mcworld_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag
new file mode 100644
index 00000000..1dc5e1c8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.frag
@@ -0,0 +1,129 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+uniform sampler2D textureIn;
+
+uniform int millis;
+
+//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);
+}
+
+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);
+}
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ float t = gl_TexCoord[0].t;
+ t = clamp(t, 10.0f/1024.0f, 410.0f/1024.0f);
+
+ float start = 56.0f - 44.0f*t/(420.0f/1024.0f);
+ float width = 182.0f + 90.0f*t/(420.0f/1024.0f);
+ float scaleFactor = 1.0f/(width/1024.0f)*112.0f;
+
+ float index = mod(millis/20.0f+t*scaleFactor, 2820.0f);
+ float yIndex = floor(index/1024.0f)*112.0f-(gl_TexCoord[0].s-start/1024.0f)*scaleFactor+532.0f;
+ float xIndex = mod(index, 1024.0f);
+ vec3 world = texture2D(textureIn, vec2(xIndex/1024.0f, yIndex/1024.0f)).xyz;
+
+ float hue = 0.0f;
+ float saturation = 1.0f;
+ float value = 1.0f;
+ if(index < 208) { //sky
+ float blurFactor = clamp((index-158)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 1.0f - blurFactor;
+ value = 0.9f - 0.6f*blurFactor;
+ } else if(index < 800) { //underground
+ if(index < 400) {
+ float blurFactor = clamp((258-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 0.0f + blurFactor;
+ value = 0.3f + 0.6f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-750)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.0f + 0.5f*blurFactor;
+ value = 0.3f - 0.1f*blurFactor;
+ }
+ } else if(index < 1762) { //nether
+ if(index < 1200) {
+ float blurFactor = clamp((850-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.5f - 0.5f*blurFactor;
+ value = 0.2f + 0.1f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-1712)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.5f - 0.5f*blurFactor;
+ value = 0.2f + 0.1f*blurFactor;
+ }
+ } else if(index < 2200) { //underground
+ if(index < 1900) {
+ float blurFactor = clamp((1812-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 350.0f;
+ saturation = 0.0f + 0.5f*blurFactor;
+ value = 0.3f - 0.1f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-2150)/100.0f, 0.0f, 0.5f);
+
+ hue = 0.0f;
+ saturation = 0.0f;
+ value = 0.3f - 0.3f*blurFactor;
+ }
+ } else if(index < 2600) { //end
+ if(index < 2400) {
+ float blurFactor = clamp((2250-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 0.0f;
+ saturation = 0.0f;
+ value = 0.0f + 0.3f*blurFactor;
+ } else {
+ float blurFactor = clamp((index-2550)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 0.0f + blurFactor;
+ value = 0.0f + 0.9f*blurFactor;
+ }
+ } else { //sky
+ float blurFactor = clamp((2650-index)/100.0f, 0.0f, 0.5f);
+
+ hue = 200.0f;
+ saturation = 1.0f - blurFactor;
+ value = 0.9f - 0.9f*blurFactor;
+ }
+ hue = mod(hue, 360.0f);
+ saturation = max(0.0f, min(1.0f, saturation));
+ value = max(0.0f, min(1.0f, value));
+
+ vec3 hsv = rgb2hsv(texture.rgb);
+ hsv.x = hue/360.0f;
+ hsv.y *= saturation;
+ hsv.z *= value;
+
+ gl_FragColor = vec4(hsv2rgb(hsv)*texture.a + world*(1.0f-texture.a), 1.0f) * passColour;
+
+ 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);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/mcworld_cape.vert
@@ -0,0 +1,12 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+} \ 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/dungeonmap.fsh b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.fsh
new file mode 100644
index 00000000..c7bcfb0f
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.fsh
@@ -0,0 +1,32 @@
+#version 120
+
+uniform sampler2D DiffuseSampler;
+
+uniform float radiusSq = 0.5f;
+
+uniform vec2 InSize;
+uniform vec2 OutSize;
+
+varying vec2 texCoord;
+
+void main() {
+ if(radiusSq < 0.5 && (texCoord.s-0.5)*(texCoord.s-0.5)+(texCoord.t-0.5)*(texCoord.t-0.5) > radiusSq) {
+ discard;
+ }
+
+ /*float totalAlpha = 0.0f;
+ vec3 accum = vec3(0.0);
+
+ for(int x = -1; x<3; x++) {
+ for(int y = -1; y<3; y++) {
+ vec4 pixel = texture2D(DiffuseSampler, texCoord+vec2(x, y)/InSize);
+
+ accum += pixel.rgb * pixel.a;
+ totalAlpha += pixel.a;
+ }
+ }
+ gl_FragColor.a = totalAlpha/4*4;
+ gl_FragColor.rgb = accum/4*4;*/
+
+ gl_FragColor = texture2D(DiffuseSampler, texCoord);
+} \ No newline at end of file
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.json b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.json
new file mode 100644
index 00000000..bb41ffd5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.json
@@ -0,0 +1,19 @@
+{
+ "blend": {
+ "func": "add",
+ "srcrgb": "srcalpha",
+ "dstrgb": "1-srcalpha"
+ },
+ "vertex": "dungeonmap",
+ "fragment": "dungeonmap",
+ "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 ] },
+ { "name": "InSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] },
+ { "name": "radiusSq", "type": "float", "count": 1, "values": [ 1.0 ] }
+ ]
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.vsh b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.vsh
new file mode 100644
index 00000000..01a16db5
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/program/dungeonmap.vsh
@@ -0,0 +1,16 @@
+#version 120
+
+attribute vec4 Position;
+
+uniform mat4 ProjMat;
+uniform vec2 OutSize;
+
+varying vec2 texCoord;
+
+void main(){
+ vec4 outPos = ProjMat * vec4(Position.xy, 0.0, 1.0);
+ gl_Position = vec4(outPos.xy, 0.2, 1.0);
+
+ texCoord = Position.xy / OutSize;
+ texCoord.y = 1.0 - texCoord.y;
+}
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/shaders/space_cape.frag b/src/main/resources/assets/notenoughupdates/shaders/space_cape.frag
new file mode 100644
index 00000000..e3e5d56e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/space_cape.frag
@@ -0,0 +1,60 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+uniform sampler2D textureIn;
+
+uniform int millis;
+uniform int eventMillis;
+uniform float eventRand; //0-1
+
+void main() {
+ vec4 texture = texture2D(textureIn, gl_TexCoord[0].st);
+
+ vec2 texCoord = gl_TexCoord[0].st + vec2(mod(millis/100.0f,1024.0f)/1024.0f, 421.0f/1024.0f);
+
+ vec4 extra = vec4(0,0,0,0);
+ if(eventRand < 0.4f) {
+ vec2 extraPos = vec2(45.0f+eventRand/0.4f*250.0f, eventMillis/300.0f*550.0f)/1024.0f;
+ vec2 extraTexCoord = vec2(48.0f/1024.0f-(gl_TexCoord[0].t-extraPos.y), gl_TexCoord[0].s-extraPos.x+894.0f/1024.0f);
+ if(extraTexCoord.x > 0.0f && extraTexCoord.x < 200.0f/1024.0f) {
+ if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) {
+ extra = texture2D(textureIn, extraTexCoord);
+ }
+ }
+ } else if(eventRand < 0.45f) {
+ vec2 extraPos = vec2(-30.0f+eventMillis/2000.0f*370.0f, 50.0f+(eventRand-0.4f)/0.05f*300.0f)/1024.0f;
+ vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+248.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f);
+ if(extraTexCoord.x > 200.0f/1024.0f && extraTexCoord.x < 300.0f/1024.0f) {
+ if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) {
+ extra = texture2D(textureIn, extraTexCoord);
+ }
+ }
+ } else if(eventRand < 0.47f) {
+ vec2 extraPos = vec2(-30.0f+eventMillis/2000.0f*370.0f, 50.0f+(eventRand-0.45f)/0.02f*300.0f)/1024.0f;
+ vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+348.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f);
+ if(extraTexCoord.x > 300.0f/1024.0f && extraTexCoord.x < 400.0f/1024.0f) {
+ if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) {
+ extra = texture2D(textureIn, extraTexCoord);
+ }
+ }
+ } else if(eventRand < 0.48f) {
+ vec2 extraPos = vec2(-30.0f+eventMillis/2000.0f*370.0f, 50.0f+(eventRand-0.47f)/0.01f*300.0f)/1024.0f;
+ vec2 extraTexCoord = vec2(gl_TexCoord[0].s-extraPos.x+448.0f/1024.0f, gl_TexCoord[0].t-extraPos.y+894.0f/1024.0f);
+ if(extraTexCoord.x > 400.0f/1024.0f && extraTexCoord.x < 500.0f/1024.0f) {
+ if(extraTexCoord.y > 843.0f/1024.0f && extraTexCoord.y < 943.0f/1024.0f) {
+ extra = texture2D(textureIn, extraTexCoord);
+ }
+ }
+ }
+
+ vec3 space = texture2D(textureIn, texCoord).rgb;
+
+ gl_FragColor = vec4(texture.rgb*texture.a + extra.rgb*extra.a*(1.0f-texture.a) + space*(1.0f-texture.a)*(1.0f-extra.a), 1.0f) * passColour;
+
+ 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);
+}
diff --git a/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert b/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert
new file mode 100644
index 00000000..2b5c48f8
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/shaders/space_cape.vert
@@ -0,0 +1,12 @@
+#version 120
+
+varying vec4 passColour;
+varying vec3 passNormal;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ gl_TexCoord[0] = gl_MultiTexCoord0;
+
+ passColour = gl_Color;
+ passNormal = normalize(gl_Normal);
+} \ No newline at end of file
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/supersecretassets/bald.png b/src/main/resources/assets/notenoughupdates/supersecretassets/bald.png
new file mode 100644
index 00000000..4f730a44
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/supersecretassets/bald.png
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..a90fbb8d 100644
--- a/src/main/resources/mixins.notenoughupdates.json
+++ b/src/main/resources/mixins.notenoughupdates.json
@@ -5,6 +5,18 @@
"mixins": [
"MixinItemStack",
"MixinInventoryEffectRenderer",
- "MixinGuiIngame"
+ "MixinGuiIngame",
+ "MixinRenderItem",
+ "MixinEntityRenderer",
+ "MixinRenderGlobal",
+ "MixinNetHandlerPlayClient",
+ "MixinGuiChest",
+ "MixinGuiContainer",
+ "MixinVboRenderList",
+ "MixinRenderList",
+ "MixinEntityPlayer",
+ "MixinTileEntitySpecialRenderer",
+ "MixinRender",
+ "MixinRenderFish"
]
} \ No newline at end of file