aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/moe')
-rw-r--r--src/main/kotlin/moe/nea/firmament/Firmament.kt148
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Profiles.kt194
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/Routes.kt95
-rw-r--r--src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt72
-rw-r--r--src/main/kotlin/moe/nea/firmament/commands/CaseInsensitiveLiteralCommandNode.kt75
-rw-r--r--src/main/kotlin/moe/nea/firmament/commands/RestArgumentType.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/commands/dsl.kt118
-rw-r--r--src/main/kotlin/moe/nea/firmament/commands/rome.kt230
-rw-r--r--src/main/kotlin/moe/nea/firmament/compat/SodiumChunkReloader.kt12
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt16
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/BakeExtraModelsEvent.kt21
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ClientStartedEvent.kt6
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/CommandEvent.kt45
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/CustomItemModelEvent.kt43
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/EarlyResourceReloadEvent.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/EntityDespawnEvent.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/EntityInteractionEvent.kt29
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/EntityUpdateEvent.kt31
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/FeaturesInitializedEvent.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/FinalizeResourceManagerEvent.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/FirmamentEvent.kt38
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt52
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HandledScreenClickEvent.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HandledScreenForegroundEvent.kt16
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HandledScreenKeyPressedEvent.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HandledScreenPushREIEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HotbarItemRenderEvent.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/HudRenderEvent.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/IsSlotProtectedEvent.kt46
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ItemTooltipEvent.kt14
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt21
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/OutgoingPacketEvent.kt9
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ParticleSpawnEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/PlayerInventoryUpdate.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt28
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ScreenChangeEvent.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ScreenRenderPostEvent.kt16
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/ServerConnectedEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/SkyblockServerUpdateEvent.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/SlotClickEvent.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/SlotRenderEvents.kt34
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/SoundReceiveEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/TickEvent.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/TooltipEvent.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/WorldKeyboardEvent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/WorldReadyEvent.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt27
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt54
-rw-r--r--src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt16
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt120
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt23
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt57
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt161
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt100
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/DebugLogger.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/DebugView.kt38
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt55
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt27
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt193
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt131
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt35
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt144
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/events/anniversity/AnniversaryFeatures.kt224
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/events/carnival/CarnivalFeatures.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/events/carnival/MinesweeperHelper.kt276
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt51
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt71
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt85
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt51
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt203
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButton.kt85
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonEditor.kt184
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonTemplates.kt35
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt88
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageBackingHandle.kt53
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageData.kt21
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt154
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayCustom.kt98
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayScreen.kt296
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverviewScreen.kt123
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StoragePageSlot.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/VirtualInventory.kt65
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt81
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt176
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt133
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/notifications/Notifications.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/AndPredicate.kt26
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/BakedModelExtra.kt9
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/BakedOverrideData.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt296
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt106
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt167
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt74
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt114
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/DisplayNamePredicate.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/ExtraAttributesPredicate.kt268
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/ItemPredicate.kt32
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/JsonUnbakedModelFirmExtra.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/LorePredicate.kt19
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideData.kt7
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideFilterSet.kt19
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/NumberMatcher.kt125
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/OrPredicate.kt26
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/PetPredicate.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/RarityMatcher.kt69
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt159
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt131
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt40
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt121
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt68
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt297
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/BarComponent.kt125
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt81
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt59
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/FixedComponent.kt38
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt33
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt18
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/AllConfigsGui.kt46
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/BooleanHandler.kt37
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/DurationHandler.kt58
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt40
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt39
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/IntegerHandler.kt54
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt48
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt149
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt181
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfigElement.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/ManagedOption.kt62
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/config/StringHandler.kt36
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/EntityModifier.kt9
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/EntityRenderer.kt197
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/EntityWidget.kt35
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/FakeWorld.kt488
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/GuiPlayer.kt54
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyAge.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyCharged.kt14
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyEquipment.kt55
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyHorse.kt61
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyInvisible.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyName.kt14
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyPlayerSkin.kt47
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyRiding.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/entity/ModifyWither.kt20
-rw-r--r--src/main/kotlin/moe/nea/firmament/gui/hud/MoulConfigHud.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt64
-rw-r--r--src/main/kotlin/moe/nea/firmament/keybindings/FirmamentKeyBindings.kt26
-rw-r--r--src/main/kotlin/moe/nea/firmament/keybindings/IKeyBinding.kt29
-rw-r--r--src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt106
-rw-r--r--src/main/kotlin/moe/nea/firmament/modmenu/FirmamentModMenuPlugin.kt14
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt128
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt186
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt29
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt254
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt64
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/math.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBCraftingRecipe.kt55
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBEssenceUpgradeRecipe.kt62
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBForgeRecipe.kt71
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt224
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBMobDropRecipe.kt108
-rw-r--r--src/main/kotlin/moe/nea/firmament/rei/recipes/SBRecipe.kt31
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/BetterRepoRecipeCache.kt28
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/EssenceRecipeProvider.kt50
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt94
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt107
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt215
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/ItemNameLookup.kt98
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/RepoDownloadManager.kt128
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt145
-rw-r--r--src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt126
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/Base64Util.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/BazaarPriceStrategy.kt19
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/ClipboardUtils.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/CommonSoundEffects.kt26
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/DurabilityBarEvent.kt20
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/ErrorBoundary.kt10
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/FirmFormatters.kt59
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/FragmentGuiScreen.kt93
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/GetRectangle.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/HoveredItemStack.kt31
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/IdentifierSerializer.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/IdentityCharacteristics.kt15
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt26
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/LegacyFormattingCode.kt35
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/LegacyTagParser.kt245
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/LoadResource.kt20
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/Locraw.kt12
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/LogIfNull.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MC.kt94
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MinecraftDispatcher.kt8
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MoulConfigFragment.kt44
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt230
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt38
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SBData.kt66
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/ScoreboardUtil.kt45
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/ScreenUtil.kt38
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SequenceUtil.kt11
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SkyBlockIsland.kt42
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt149
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/SortedMapSerializer.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/TemplateUtil.kt85
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/TimeMark.kt44
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/Timer.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt75
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/assertions.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/async/input.kt47
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/colorconversion.kt13
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/customgui/CoordRememberingSlot.kt14
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/customgui/CustomGui.kt72
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/customgui/HasCustomGui.kt17
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/data/DataHolder.kt62
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/data/IDataHolder.kt77
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/data/ProfileSpecificDataHolder.kt84
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/filter/IteratorFilterSet.kt33
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/item/NbtItemData.kt24
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt90
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/BlockPosSerializer.kt25
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt29
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/json/SingletonSerializableList.kt31
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/listutil.kt9
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/propertyutil.kt9
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/regex.kt55
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt101
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/LerpUtils.kt33
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/RenderCircleProgress.kt95
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/RenderContextDSL.kt6
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt294
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/render/TranslatedScissors.kt22
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/stringutil.kt6
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/textutil.kt117
-rw-r--r--src/main/kotlin/moe/nea/firmament/util/uuid.kt12
245 files changed, 0 insertions, 15933 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/Firmament.kt b/src/main/kotlin/moe/nea/firmament/Firmament.kt
deleted file mode 100644
index c1801f4..0000000
--- a/src/main/kotlin/moe/nea/firmament/Firmament.kt
+++ /dev/null
@@ -1,148 +0,0 @@
-
-
-package moe.nea.firmament
-
-import com.mojang.brigadier.CommandDispatcher
-import io.ktor.client.HttpClient
-import io.ktor.client.plugins.UserAgent
-import io.ktor.client.plugins.cache.HttpCache
-import io.ktor.client.plugins.compression.ContentEncoding
-import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
-import io.ktor.client.plugins.logging.LogLevel
-import io.ktor.client.plugins.logging.Logging
-import io.ktor.serialization.kotlinx.json.json
-import java.io.InputStream
-import java.nio.file.Files
-import java.nio.file.Path
-import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
-import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback
-import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents
-import net.fabricmc.loader.api.FabricLoader
-import net.fabricmc.loader.api.Version
-import net.fabricmc.loader.api.metadata.ModMetadata
-import org.apache.logging.log4j.LogManager
-import org.apache.logging.log4j.Logger
-import kotlinx.coroutines.CoroutineName
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.SupervisorJob
-import kotlinx.coroutines.plus
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.decodeFromStream
-import kotlin.coroutines.EmptyCoroutineContext
-import net.minecraft.client.render.chunk.SectionBuilder
-import net.minecraft.command.CommandRegistryAccess
-import net.minecraft.util.Identifier
-import moe.nea.firmament.commands.registerFirmamentCommand
-import moe.nea.firmament.events.ClientStartedEvent
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.ItemTooltipEvent
-import moe.nea.firmament.events.ScreenRenderPostEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.events.registration.registerFirmamentEvents
-import moe.nea.firmament.features.FeatureManager
-import moe.nea.firmament.repo.HypixelStaticData
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.data.IDataHolder
-
-object Firmament {
- const val MOD_ID = "firmament"
-
- val DEBUG = System.getProperty("firmament.debug") == "true"
- val DATA_DIR: Path = Path.of(".firmament").also { Files.createDirectories(it) }
- val CONFIG_DIR: Path = Path.of("config/firmament").also { Files.createDirectories(it) }
- val logger: Logger = LogManager.getLogger("Firmament")
- private val metadata: ModMetadata by lazy {
- FabricLoader.getInstance().getModContainer(MOD_ID).orElseThrow().metadata
- }
- val version: Version by lazy { metadata.version }
-
- val json = Json {
- prettyPrint = DEBUG
- isLenient = true
- ignoreUnknownKeys = true
- encodeDefaults = true
- }
-
- val httpClient by lazy {
- HttpClient {
- install(ContentNegotiation) {
- json(json)
- }
- install(ContentEncoding) {
- gzip()
- deflate()
- }
- install(UserAgent) {
- agent = "Firmament/$version"
- }
- if (DEBUG)
- install(Logging) {
- level = LogLevel.INFO
- }
- install(HttpCache)
- }
- }
-
- val globalJob = Job()
- val coroutineScope =
- CoroutineScope(EmptyCoroutineContext + CoroutineName("Firmament")) + SupervisorJob(globalJob)
-
- private fun registerCommands(
- dispatcher: CommandDispatcher<FabricClientCommandSource>,
- @Suppress("UNUSED_PARAMETER")
- ctx: CommandRegistryAccess
- ) {
- registerFirmamentCommand(dispatcher)
- CommandEvent.publish(CommandEvent(dispatcher, ctx, MC.networkHandler?.commandDispatcher))
- }
-
- @JvmStatic
- fun onInitialize() {
- }
-
- @JvmStatic
- fun onClientInitialize() {
- FeatureManager.subscribeEvents()
- var tick = 0
- ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { instance ->
- TickEvent.publish(TickEvent(tick++))
- })
- IDataHolder.registerEvents()
- RepoManager.initialize()
- SBData.init()
- FeatureManager.autoload()
- HypixelStaticData.spawnDataCollectionLoop()
- ClientCommandRegistrationCallback.EVENT.register(this::registerCommands)
- ClientLifecycleEvents.CLIENT_STARTED.register(ClientLifecycleEvents.ClientStarted {
- ClientStartedEvent.publish(ClientStartedEvent())
- })
- ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
- logger.info("Shutting down Firmament coroutines")
- globalJob.cancel()
- })
- registerFirmamentEvents()
- ItemTooltipCallback.EVENT.register { stack, context, type, lines ->
- ItemTooltipEvent.publish(ItemTooltipEvent(stack, context, type, lines))
- }
- ScreenEvents.AFTER_INIT.register(ScreenEvents.AfterInit { client, screen, scaledWidth, scaledHeight ->
- ScreenEvents.afterRender(screen)
- .register(ScreenEvents.AfterRender { screen, drawContext, mouseX, mouseY, tickDelta ->
- ScreenRenderPostEvent.publish(ScreenRenderPostEvent(screen, mouseX, mouseY, tickDelta, drawContext))
- })
- })
- }
-
-
- fun identifier(path: String) = Identifier.of(MOD_ID, path)
- inline fun <reified T : Any> tryDecodeJsonFromStream(inputStream: InputStream): Result<T> {
- return runCatching {
- json.decodeFromStream<T>(inputStream)
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt b/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
deleted file mode 100644
index 789364a..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/Profiles.kt
+++ /dev/null
@@ -1,194 +0,0 @@
-
-
-@file:UseSerializers(DashlessUUIDSerializer::class, InstantAsLongSerializer::class)
-
-package moe.nea.firmament.apis
-
-import io.github.moulberry.repo.constants.Leveling
-import io.github.moulberry.repo.data.Rarity
-import kotlinx.datetime.Instant
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.LegacyFormattingCode
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.assertNotNullOr
-import moe.nea.firmament.util.json.DashlessUUIDSerializer
-import moe.nea.firmament.util.json.InstantAsLongSerializer
-import net.minecraft.util.DyeColor
-import net.minecraft.util.Formatting
-import java.util.*
-import kotlin.reflect.KProperty1
-
-
-@Serializable
-data class CollectionSkillData(
- val items: Map<CollectionType, CollectionInfo>
-)
-
-@Serializable
-data class CollectionResponse(
- val success: Boolean,
- val collections: Map<String, CollectionSkillData>
-)
-
-@Serializable
-data class CollectionInfo(
- val name: String,
- val maxTiers: Int,
- val tiers: List<CollectionTier>
-)
-
-@Serializable
-data class CollectionTier(
- val tier: Int,
- val amountRequired: Long,
- val unlocks: List<String>,
-)
-
-
-@Serializable
-data class Profiles(
- val success: Boolean,
- val profiles: List<Profile>?
-)
-
-@Serializable
-data class Profile(
- @SerialName("profile_id")
- val profileId: UUID,
- @SerialName("cute_name")
- val cuteName: String,
- val selected: Boolean = false,
- val members: Map<UUID, Member>,
-)
-
-enum class Skill(val accessor: KProperty1<Member, Double>, val color: DyeColor, val icon: SkyblockId) {
- FARMING(Member::experienceSkillFarming, DyeColor.YELLOW, SkyblockId("ROOKIE_HOE")),
- FORAGING(Member::experienceSkillForaging, DyeColor.BROWN, SkyblockId("TREECAPITATOR_AXE")),
- MINING(Member::experienceSkillMining, DyeColor.LIGHT_GRAY, SkyblockId("DIAMOND_PICKAXE")),
- ALCHEMY(Member::experienceSkillAlchemy, DyeColor.PURPLE, SkyblockId("BREWING_STAND")),
- TAMING(Member::experienceSkillTaming, DyeColor.GREEN, SkyblockId("SUPER_EGG")),
- FISHING(Member::experienceSkillFishing, DyeColor.BLUE, SkyblockId("FARMER_ROD")),
- RUNECRAFTING(Member::experienceSkillRunecrafting, DyeColor.PINK, SkyblockId("MUSIC_RUNE;1")),
- CARPENTRY(Member::experienceSkillCarpentry, DyeColor.ORANGE, SkyblockId("WORKBENCH")),
- COMBAT(Member::experienceSkillCombat, DyeColor.RED, SkyblockId("UNDEAD_SWORD")),
- SOCIAL(Member::experienceSkillSocial, DyeColor.WHITE, SkyblockId("EGG_HUNT")),
- ENCHANTING(Member::experienceSkillEnchanting, DyeColor.MAGENTA, SkyblockId("ENCHANTMENT_TABLE")),
- ;
-
- fun getMaximumLevel(leveling: Leveling) = assertNotNullOr(leveling.maximumLevels[name.lowercase()]) { 50 }
-
- fun getLadder(leveling: Leveling): List<Int> {
- if (this == SOCIAL) return leveling.socialExperienceRequiredPerLevel
- if (this == RUNECRAFTING) return leveling.runecraftingExperienceRequiredPerLevel
- return leveling.skillExperienceRequiredPerLevel
- }
-}
-
-enum class CollectionCategory(val skill: Skill?, val color: DyeColor, val icon: SkyblockId) {
- FARMING(Skill.FARMING, DyeColor.YELLOW, SkyblockId("ROOKIE_HOE")),
- FORAGING(Skill.FORAGING, DyeColor.BROWN, SkyblockId("TREECAPITATOR_AXE")),
- MINING(Skill.MINING, DyeColor.LIGHT_GRAY, SkyblockId("DIAMOND_PICKAXE")),
- FISHING(Skill.FISHING, DyeColor.BLUE, SkyblockId("FARMER_ROD")),
- COMBAT(Skill.COMBAT, DyeColor.RED, SkyblockId("UNDEAD_SWORD")),
- RIFT(null, DyeColor.PURPLE, SkyblockId("SKYBLOCK_MOTE")),
-}
-
-@Serializable
-@JvmInline
-value class CollectionType(val string: String) {
- val skyblockId get() = SkyblockId(string.replace(":", "-").replace("MUSHROOM_COLLECTION", "HUGE_MUSHROOM_2"))
-}
-
-@Serializable
-data class Member(
- val pets: List<Pet> = listOf(),
- @SerialName("coop_invitation")
- val coopInvitation: CoopInvitation? = null,
- @SerialName("experience_skill_farming")
- val experienceSkillFarming: Double = 0.0,
- @SerialName("experience_skill_alchemy")
- val experienceSkillAlchemy: Double = 0.0,
- @SerialName("experience_skill_combat")
- val experienceSkillCombat: Double = 0.0,
- @SerialName("experience_skill_taming")
- val experienceSkillTaming: Double = 0.0,
- @SerialName("experience_skill_social2")
- val experienceSkillSocial: Double = 0.0,
- @SerialName("experience_skill_enchanting")
- val experienceSkillEnchanting: Double = 0.0,
- @SerialName("experience_skill_fishing")
- val experienceSkillFishing: Double = 0.0,
- @SerialName("experience_skill_foraging")
- val experienceSkillForaging: Double = 0.0,
- @SerialName("experience_skill_mining")
- val experienceSkillMining: Double = 0.0,
- @SerialName("experience_skill_runecrafting")
- val experienceSkillRunecrafting: Double = 0.0,
- @SerialName("experience_skill_carpentry")
- val experienceSkillCarpentry: Double = 0.0,
- val collection: Map<CollectionType, Long> = mapOf()
-)
-
-@Serializable
-data class CoopInvitation(
- val timestamp: Instant,
- @SerialName("invited_by")
- val invitedBy: UUID? = null,
- val confirmed: Boolean,
-)
-
-@JvmInline
-@Serializable
-value class PetType(val name: String)
-
-@Serializable
-data class Pet(
- val uuid: UUID? = null,
- val type: PetType,
- val exp: Double = 0.0,
- val active: Boolean = false,
- val tier: Rarity,
- val candyUsed: Int = 0,
- val heldItem: String? = null,
- val skin: String? = null,
-) {
- val itemId get() = SkyblockId("${type.name};${tier.ordinal}")
-}
-
-@Serializable
-data class PlayerResponse(
- val success: Boolean,
- val player: PlayerData,
-)
-
-@Serializable
-data class PlayerData(
- val uuid: UUID,
- val firstLogin: Instant,
- val lastLogin: Instant? = null,
- @SerialName("playername")
- val playerName: String,
- val achievementsOneTime: List<String> = listOf(),
- @SerialName("newPackageRank")
- val packageRank: String? = null,
- val monthlyPackageRank: String? = null,
- val rankPlusColor: String = "GOLD"
-) {
- val rankPlusDyeColor = LegacyFormattingCode.values().find { it.name == rankPlusColor } ?: LegacyFormattingCode.GOLD
- val rankData get() = RepoManager.neuRepo.constants.misc.ranks[if (monthlyPackageRank == "NONE" || monthlyPackageRank == null) packageRank else monthlyPackageRank]
- fun getDisplayName(name: String = playerName) = rankData?.let {
- ("§${it.color}[${it.tag}${rankPlusDyeColor.modern}" +
- "${it.plus ?: ""}§${it.color}] $name")
- } ?: "${Formatting.GRAY}$name"
-
-
-}
-
-@Serializable
-data class AshconNameLookup(
- val username: String,
- val uuid: UUID,
-)
diff --git a/src/main/kotlin/moe/nea/firmament/apis/Routes.kt b/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
deleted file mode 100644
index bf55a2d..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/Routes.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-
-
-package moe.nea.firmament.apis
-
-import io.ktor.client.call.*
-import io.ktor.client.request.*
-import io.ktor.http.*
-import io.ktor.util.*
-import java.util.*
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.async
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import kotlin.collections.MutableMap
-import kotlin.collections.listOf
-import kotlin.collections.mutableMapOf
-import kotlin.collections.set
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.MinecraftDispatcher
-
-object Routes {
- private val nameToUUID: MutableMap<String, Deferred<UUID?>> = CaseInsensitiveMap()
- private val profiles: MutableMap<UUID, Deferred<Profiles?>> = mutableMapOf()
- private val accounts: MutableMap<UUID, Deferred<PlayerData?>> = mutableMapOf()
- private val UUIDToName: MutableMap<UUID, Deferred<String?>> = mutableMapOf()
-
- suspend fun getPlayerNameForUUID(uuid: UUID): String? {
- return withContext(MinecraftDispatcher) {
- UUIDToName.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$uuid")
- if (!response.status.isSuccess()) return@async null
- val data = response.body<AshconNameLookup>()
- launch(MinecraftDispatcher) {
- nameToUUID[data.username] = async { data.uuid }
- }
- data.username
- }
- }
- }.await()
- }
-
- suspend fun getUUIDForPlayerName(name: String): UUID? {
- return withContext(MinecraftDispatcher) {
- nameToUUID.computeIfAbsent(name) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = Firmament.httpClient.get("https://api.ashcon.app/mojang/v2/user/$name")
- if (!response.status.isSuccess()) return@async null
- val data = response.body<AshconNameLookup>()
- launch(MinecraftDispatcher) {
- UUIDToName[data.uuid] = async { data.username }
- }
- data.uuid
- }
- }
- }.await()
- }
-
- suspend fun getAccountData(uuid: UUID): PlayerData? {
- return withContext(MinecraftDispatcher) {
- accounts.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = UrsaManager.request(listOf("v1", "hypixel","player", uuid.toString()))
- if (!response.status.isSuccess()) {
- launch(MinecraftDispatcher) {
- @Suppress("DeferredResultUnused")
- accounts.remove(uuid)
- }
- return@async null
- }
- response.body<PlayerResponse>().player
- }
- }
- }.await()
- }
-
- suspend fun getProfiles(uuid: UUID): Profiles? {
- return withContext(MinecraftDispatcher) {
- profiles.computeIfAbsent(uuid) {
- async(Firmament.coroutineScope.coroutineContext) {
- val response = UrsaManager.request(listOf("v1", "hypixel","profiles", uuid.toString()))
- if (!response.status.isSuccess()) {
- launch(MinecraftDispatcher) {
- @Suppress("DeferredResultUnused")
- profiles.remove(uuid)
- }
- return@async null
- }
- response.body<Profiles>()
- }
- }
- }.await()
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt b/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt
deleted file mode 100644
index 13f7aef..0000000
--- a/src/main/kotlin/moe/nea/firmament/apis/UrsaManager.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-package moe.nea.firmament.apis
-
-import io.ktor.client.request.*
-import io.ktor.client.statement.*
-import io.ktor.http.*
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.sync.Mutex
-import kotlinx.coroutines.withContext
-import moe.nea.firmament.Firmament
-import net.minecraft.client.MinecraftClient
-import java.time.Duration
-import java.time.Instant
-import java.util.*
-
-object UrsaManager {
- private data class Token(
- val validUntil: Instant,
- val token: String,
- val obtainedFrom: String,
- ) {
- fun isValid(host: String) = Instant.now().plusSeconds(60) < validUntil && obtainedFrom == host
- }
-
- private var currentToken: Token? = null
- private val lock = Mutex()
- private fun getToken(host: String) = currentToken?.takeIf { it.isValid(host) }
-
- suspend fun request(path: List<String>): HttpResponse {
- var didLock = false
- try {
- val host = "ursa.notenoughupdates.org"
- var token = getToken(host)
- if (token == null) {
- lock.lock()
- didLock = true
- token = getToken(host)
- }
- val response = Firmament.httpClient.get {
- url {
- this.host = host
- appendPathSegments(path, encodeSlash = true)
- }
- if (token == null) {
- withContext(Dispatchers.IO) {
- val mc = MinecraftClient.getInstance()
- val serverId = UUID.randomUUID().toString()
- mc.sessionService.joinServer(mc.session.uuidOrNull, mc.session.accessToken, serverId)
- header("x-ursa-username", mc.session.username)
- header("x-ursa-serverid", serverId)
- }
- } else {
- header("x-ursa-token", token.token)
- }
- }
- val savedToken = response.headers["x-ursa-token"]
- if (savedToken != null) {
- val validUntil = response.headers["x-ursa-expires"]?.toLongOrNull()?.let { Instant.ofEpochMilli(it) }
- ?: (Instant.now() + Duration.ofMinutes(55))
- currentToken = Token(validUntil, savedToken, host)
- }
- if (response.status.value != 200) {
- Firmament.logger.error("Failed to contact ursa minor: ${response.bodyAsText()}")
- }
- return response
- } finally {
- if (didLock)
- lock.unlock()
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/commands/CaseInsensitiveLiteralCommandNode.kt b/src/main/kotlin/moe/nea/firmament/commands/CaseInsensitiveLiteralCommandNode.kt
deleted file mode 100644
index 10772b0..0000000
--- a/src/main/kotlin/moe/nea/firmament/commands/CaseInsensitiveLiteralCommandNode.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-package moe.nea.firmament.commands
-
-import com.mojang.brigadier.Command
-import com.mojang.brigadier.RedirectModifier
-import com.mojang.brigadier.StringReader
-import com.mojang.brigadier.builder.LiteralArgumentBuilder
-import com.mojang.brigadier.context.CommandContextBuilder
-import com.mojang.brigadier.context.StringRange
-import com.mojang.brigadier.exceptions.CommandSyntaxException
-import com.mojang.brigadier.tree.CommandNode
-import com.mojang.brigadier.tree.LiteralCommandNode
-import java.util.function.Predicate
-
-class CaseInsensitiveLiteralCommandNode<S>(
- literal: String, command: Command<S>?, requirement: Predicate<S>?,
- redirect: CommandNode<S>?, modifier: RedirectModifier<S>?, forks: Boolean
-) : LiteralCommandNode<S>(
- literal.lowercase(), command, requirement, redirect, modifier, forks
-) {
- class Builder<S>(literal: String) : LiteralArgumentBuilder<S>(literal) {
- override fun build(): LiteralCommandNode<S> {
- val result = CaseInsensitiveLiteralCommandNode(
- literal,
- command, requirement, redirect, redirectModifier, isFork
- )
- for (argument in arguments) {
- result.addChild(argument)
- }
- return result
- }
- }
-
- override fun createBuilder(): LiteralArgumentBuilder<S> {
- return Builder<S>(literal).also {
- it.requires(requirement)
- it.forward(redirect, redirectModifier, isFork)
- if (command != null)
- it.executes(command)
- }
- }
-
- override fun parse(reader: StringReader, contextBuilder: CommandContextBuilder<S>) {
- val start = reader.cursor
- val end = parse0(reader)
- if (end > -1) {
- contextBuilder.withNode(this, StringRange.between(start, end))
- return
- }
-
- throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.literalIncorrect().createWithContext(reader, literal)
- }
-
- override fun toString(): String {
- return "<iliteral $literal>"
- }
-
- private fun parse0(reader: StringReader): Int {
- val start = reader.cursor
- if (reader.canRead(literal.length)) {
- val end = start + literal.length
- if (reader.string.substring(start, end).equals(literal, true)) {
- reader.cursor = end
- if (!reader.canRead() || reader.peek() == ' ') {
- return end
- } else {
- reader.cursor = start
- }
- }
- }
- return -1
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/commands/RestArgumentType.kt b/src/main/kotlin/moe/nea/firmament/commands/RestArgumentType.kt
deleted file mode 100644
index 361907f..0000000
--- a/src/main/kotlin/moe/nea/firmament/commands/RestArgumentType.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-package moe.nea.firmament.commands
-
-import com.mojang.brigadier.StringReader
-import com.mojang.brigadier.arguments.ArgumentType
-
-object RestArgumentType : ArgumentType<String> {
- override fun parse(reader: StringReader): String {
- val remaining = reader.remaining
- reader.cursor += remaining.length
- return remaining
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/commands/dsl.kt b/src/main/kotlin/moe/nea/firmament/commands/dsl.kt
deleted file mode 100644
index d1f0d8c..0000000
--- a/src/main/kotlin/moe/nea/firmament/commands/dsl.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-
-
-package moe.nea.firmament.commands
-
-import com.mojang.brigadier.arguments.ArgumentType
-import com.mojang.brigadier.builder.ArgumentBuilder
-import com.mojang.brigadier.builder.RequiredArgumentBuilder
-import com.mojang.brigadier.context.CommandContext
-import com.mojang.brigadier.suggestion.SuggestionProvider
-import kotlinx.coroutines.launch
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.MinecraftDispatcher
-import moe.nea.firmament.util.iterate
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
-import java.lang.reflect.ParameterizedType
-import java.lang.reflect.Type
-import java.lang.reflect.TypeVariable
-
-
-typealias DefaultSource = FabricClientCommandSource
-
-
-inline val <T : CommandContext<*>> T.context get() = this
-operator fun <T : Any, C : CommandContext<*>> C.get(arg: TypeSafeArg<T>): T {
- return arg.get(this)
-}
-
-fun literal(
- name: String,
- block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
-): CaseInsensitiveLiteralCommandNode.Builder<DefaultSource> =
- CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>(name).also(block)
-
-
-private fun normalizeGeneric(argument: Type): Class<*> {
- return when (argument) {
- is Class<*> -> argument
- is TypeVariable<*> -> normalizeGeneric(argument.bounds[0])
- is ParameterizedType -> normalizeGeneric(argument.rawType)
- else -> Any::class.java
- }
-}
-
-data class TypeSafeArg<T : Any>(val name: String, val argument: ArgumentType<T>) {
- val argClass by lazy {
- argument.javaClass
- .iterate<Class<in ArgumentType<T>>> {
- it.superclass
- }
- .flatMap {
- it.genericInterfaces.toList()
- }
- .filterIsInstance<ParameterizedType>()
- .find { it.rawType == ArgumentType::class.java }!!
- .let { normalizeGeneric(it.actualTypeArguments[0]) }
- }
-
- @JvmName("getWithThis")
- fun <S> CommandContext<S>.get(): T =
- get(this)
-
-
- fun <S> get(ctx: CommandContext<S>): T {
- try {
- return ctx.getArgument(name, argClass) as T
- } catch (e: Exception) {
- if (ctx.child != null) {
- return get(ctx.child)
- }
- throw e
- }
- }
-}
-
-
-fun <T : Any> argument(
- name: String,
- argument: ArgumentType<T>,
- block: RequiredArgumentBuilder<DefaultSource, T>.(TypeSafeArg<T>) -> Unit
-): RequiredArgumentBuilder<DefaultSource, T> =
- RequiredArgumentBuilder.argument<DefaultSource, T>(name, argument).also { block(it, TypeSafeArg(name, argument)) }
-
-fun <T : ArgumentBuilder<DefaultSource, T>, AT : Any> T.thenArgument(
- name: String,
- argument: ArgumentType<AT>,
- block: RequiredArgumentBuilder<DefaultSource, AT>.(TypeSafeArg<AT>) -> Unit
-): T = then(argument(name, argument, block))
-
-fun <T : RequiredArgumentBuilder<DefaultSource, String>> T.suggestsList(provider: CommandContext<DefaultSource>.() -> Iterable<String>) {
- suggests(SuggestionProvider<DefaultSource> { context, builder ->
- provider(context)
- .asSequence()
- .filter { it.startsWith(builder.remaining, ignoreCase = true) }
- .forEach {
- builder.suggest(it)
- }
- builder.buildFuture()
- })
-}
-
-fun <T : ArgumentBuilder<DefaultSource, T>> T.thenLiteral(
- name: String,
- block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
-): T =
- then(literal(name, block))
-
-fun <T : ArgumentBuilder<DefaultSource, T>> T.then(node: ArgumentBuilder<DefaultSource, *>, block: T.() -> Unit): T =
- then(node).also(block)
-
-fun <T : ArgumentBuilder<DefaultSource, T>> T.thenExecute(block: suspend CommandContext<DefaultSource>.() -> Unit): T =
- executes {
- Firmament.coroutineScope.launch(MinecraftDispatcher) {
- block(it)
- }
- 1
- }
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/commands/rome.kt b/src/main/kotlin/moe/nea/firmament/commands/rome.kt
deleted file mode 100644
index 015512d..0000000
--- a/src/main/kotlin/moe/nea/firmament/commands/rome.kt
+++ /dev/null
@@ -1,230 +0,0 @@
-
-
-package moe.nea.firmament.commands
-
-import com.mojang.brigadier.CommandDispatcher
-import com.mojang.brigadier.arguments.StringArgumentType.string
-import io.ktor.client.statement.bodyAsText
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
-import net.minecraft.text.Text
-import moe.nea.firmament.apis.UrsaManager
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.features.debug.PowerUserTools
-import moe.nea.firmament.features.inventory.buttons.InventoryButtons
-import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
-import moe.nea.firmament.features.inventory.storageoverlay.StorageOverviewScreen
-import moe.nea.firmament.gui.config.AllConfigsGui
-import moe.nea.firmament.gui.config.BooleanHandler
-import moe.nea.firmament.gui.config.ManagedOption
-import moe.nea.firmament.repo.HypixelStaticData
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.ScreenUtil
-import moe.nea.firmament.util.SkyblockId
-
-
-fun firmamentCommand() = literal("firmament") {
- thenLiteral("config") {
- thenExecute {
- AllConfigsGui.showAllGuis()
- }
- thenLiteral("toggle") {
- thenArgument("config", string()) { config ->
- suggestsList {
- AllConfigsGui.allConfigs.asSequence().map { it.name }.asIterable()
- }
- thenArgument("property", string()) { property ->
- suggestsList {
- (AllConfigsGui.allConfigs.find { it.name == this[config] } ?: return@suggestsList listOf())
- .allOptions.entries.asSequence().filter { it.value.handler is BooleanHandler }
- .map { it.key }
- .asIterable()
- }
- thenExecute {
- val config = this[config]
- val property = this[property]
-
- val configObj = AllConfigsGui.allConfigs.find { it.name == config }
- if (configObj == null) {
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.toggle.no-config-found",
- config
- )
- )
- return@thenExecute
- }
- val propertyObj = configObj.allOptions[property]
- if (propertyObj == null) {
- source.sendFeedback(
- Text.stringifiedTranslatable("firmament.command.toggle.no-property-found", property)
- )
- return@thenExecute
- }
- if (propertyObj.handler !is BooleanHandler) {
- source.sendFeedback(
- Text.stringifiedTranslatable("firmament.command.toggle.not-a-toggle", property)
- )
- return@thenExecute
- }
- propertyObj as ManagedOption<Boolean>
- propertyObj.value = !propertyObj.value
- configObj.save()
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.toggle.toggled", configObj.labelText,
- propertyObj.labelText,
- Text.translatable("firmament.toggle.${propertyObj.value}")
- )
- )
- }
- }
- }
- }
- }
- thenLiteral("buttons") {
- thenExecute {
- InventoryButtons.openEditor()
- }
- }
- thenLiteral("sendcoords") {
- thenExecute {
- val p = MC.player ?: return@thenExecute
- MC.sendServerChat("x: ${p.blockX}, y: ${p.blockY}, z: ${p.blockZ}")
- }
- thenArgument("rest", RestArgumentType) { rest ->
- thenExecute {
- val p = MC.player ?: return@thenExecute
- MC.sendServerChat("x: ${p.blockX}, y: ${p.blockY}, z: ${p.blockZ} ${this[rest]}")
- }
- }
- }
- thenLiteral("storageoverview") {
- thenExecute {
- ScreenUtil.setScreenLater(StorageOverviewScreen())
- MC.player?.networkHandler?.sendChatCommand("storage")
- }
- }
- thenLiteral("storage") {
- thenExecute {
- ScreenUtil.setScreenLater(StorageOverlayScreen())
- MC.player?.networkHandler?.sendChatCommand("storage")
- }
- }
- thenLiteral("repo") {
- thenLiteral("reload") {
- thenLiteral("fetch") {
- thenExecute {
- source.sendFeedback(Text.translatable("firmament.repo.reload.network")) // TODO better reporting
- RepoManager.launchAsyncUpdate()
- }
- }
- thenExecute {
- source.sendFeedback(Text.translatable("firmament.repo.reload.disk"))
- RepoManager.reload()
- }
- }
- }
- thenLiteral("price") {
- thenArgument("item", string()) { item ->
- suggestsList { RepoManager.neuRepo.items.items.keys }
- thenExecute {
- val itemName = SkyblockId(get(item))
- source.sendFeedback(Text.stringifiedTranslatable("firmament.price", itemName.neuItem))
- val bazaarData = HypixelStaticData.bazaarData[itemName]
- if (bazaarData != null) {
- source.sendFeedback(Text.translatable("firmament.price.bazaar"))
- source.sendFeedback(
- Text.stringifiedTranslatable("firmament.price.bazaar.productid", bazaarData.productId.bazaarId)
- )
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.price.bazaar.buy.price",
- FirmFormatters.formatCommas(bazaarData.quickStatus.buyPrice, 1)
- )
- )
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.price.bazaar.buy.order",
- bazaarData.quickStatus.buyOrders
- )
- )
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.price.bazaar.sell.price",
- FirmFormatters.formatCommas(bazaarData.quickStatus.sellPrice, 1)
- )
- )
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.price.bazaar.sell.order",
- bazaarData.quickStatus.sellOrders
- )
- )
- }
- val lowestBin = HypixelStaticData.lowestBin[itemName]
- if (lowestBin != null) {
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.price.lowestbin",
- FirmFormatters.formatCommas(lowestBin, 1)
- )
- )
- }
- }
- }
- }
- thenLiteral("dev") {
- thenLiteral("simulate") {
- thenArgument("message", RestArgumentType) { message ->
- thenExecute {
- MC.instance.messageHandler.onGameMessage(Text.literal(get(message)), false)
- }
- }
- }
- thenLiteral("sbdata") {
- thenExecute {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.profile", SBData.profileId))
- val locrawInfo = SBData.locraw
- if (locrawInfo == null) {
- source.sendFeedback(Text.translatable("firmament.sbinfo.nolocraw"))
- } else {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.server", locrawInfo.server))
- source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.gametype", locrawInfo.gametype))
- source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.mode", locrawInfo.mode))
- source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.map", locrawInfo.map))
- }
- }
- }
- thenLiteral("copyEntities") {
- thenExecute {
- val player = MC.player ?: return@thenExecute
- player.world.getOtherEntities(player, player.boundingBox.expand(12.0)).forEach(PowerUserTools::showEntity)
- }
- }
- thenLiteral("callUrsa") {
- thenArgument("path", string()) { path ->
- thenExecute {
- source.sendFeedback(Text.translatable("firmament.ursa.debugrequest.start"))
- val text = UrsaManager.request(this[path].split("/")).bodyAsText()
- source.sendFeedback(Text.stringifiedTranslatable("firmament.ursa.debugrequest.result", text))
- }
- }
- }
- }
- CommandEvent.SubCommand.publish(CommandEvent.SubCommand(this@literal))
-}
-
-
-fun registerFirmamentCommand(dispatcher: CommandDispatcher<FabricClientCommandSource>) {
- val firmament = dispatcher.register(firmamentCommand())
- dispatcher.register(literal("firm") {
- redirect(firmament)
- })
-}
-
-
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/compat/SodiumChunkReloader.kt b/src/main/kotlin/moe/nea/firmament/compat/SodiumChunkReloader.kt
deleted file mode 100644
index 4bb231a..0000000
--- a/src/main/kotlin/moe/nea/firmament/compat/SodiumChunkReloader.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package moe.nea.firmament.compat
-
-import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer
-import moe.nea.firmament.mixins.accessor.sodium.AccessorSodiumWorldRenderer
-
-class SodiumChunkReloader : Runnable {
- override fun run() {
- (SodiumWorldRenderer.instanceNullable() as AccessorSodiumWorldRenderer)
- .renderSectionManager_firmament
- .updateChunks(false)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt
deleted file mode 100644
index 3069843..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/AllowChatEvent.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import moe.nea.firmament.util.unformattedString
-import net.minecraft.text.Text
-
-/**
- * Filter whether the user should see a chat message altogether. May or may not be called for every chat packet sent by
- * the server. When that quality is desired, consider [ProcessChatEvent] instead.
- */
-data class AllowChatEvent(val text: Text) : FirmamentEvent.Cancellable() {
- val unformattedString = text.unformattedString
-
- companion object : FirmamentEventBus<AllowChatEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt b/src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt
deleted file mode 100644
index bbaa81d..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/AttackBlockEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.util.Hand
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Direction
-import net.minecraft.world.World
-
-data class AttackBlockEvent(
- val player: PlayerEntity,
- val world: World,
- val hand: Hand,
- val blockPos: BlockPos,
- val direction: Direction
-) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<AttackBlockEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/BakeExtraModelsEvent.kt b/src/main/kotlin/moe/nea/firmament/events/BakeExtraModelsEvent.kt
deleted file mode 100644
index f75bedc..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/BakeExtraModelsEvent.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-
-package moe.nea.firmament.events
-
-import java.util.function.Consumer
-import net.minecraft.client.util.ModelIdentifier
-
-class BakeExtraModelsEvent(
- private val addItemModel: Consumer<ModelIdentifier>,
- private val addAnyModel: Consumer<ModelIdentifier>,
-) : FirmamentEvent() {
-
- fun addNonItemModel(modelIdentifier: ModelIdentifier) {
- this.addAnyModel.accept(modelIdentifier)
- }
-
- fun addItemModel(modelIdentifier: ModelIdentifier) {
- this.addItemModel.accept(modelIdentifier)
- }
-
- companion object : FirmamentEventBus<BakeExtraModelsEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ClientStartedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ClientStartedEvent.kt
deleted file mode 100644
index 637916d..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ClientStartedEvent.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-package moe.nea.firmament.events
-
-class ClientStartedEvent : FirmamentEvent() {
- companion object : FirmamentEventBus<ClientStartedEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/CommandEvent.kt b/src/main/kotlin/moe/nea/firmament/events/CommandEvent.kt
deleted file mode 100644
index cc9cf45..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/CommandEvent.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import com.mojang.brigadier.CommandDispatcher
-import com.mojang.brigadier.tree.LiteralCommandNode
-import net.minecraft.command.CommandRegistryAccess
-import moe.nea.firmament.commands.CaseInsensitiveLiteralCommandNode
-import moe.nea.firmament.commands.DefaultSource
-import moe.nea.firmament.commands.literal
-import moe.nea.firmament.commands.thenLiteral
-
-data class CommandEvent(
- val dispatcher: CommandDispatcher<DefaultSource>,
- val ctx: CommandRegistryAccess,
- val serverCommands: CommandDispatcher<*>?,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<CommandEvent>()
-
- /**
- * Register subcommands to `/firm`. For new top level commands use [CommandEvent]. Cannot be used to register
- * subcommands to other commands.
- */
- data class SubCommand(
- val builder: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>,
- ) : FirmamentEvent() {
- companion object : FirmamentEventBus<SubCommand>()
-
- fun subcommand(name: String, block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit) {
- builder.thenLiteral(name, block)
- }
- }
-
- fun deleteCommand(name: String) {
- dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = false) }
- serverCommands?.root?.children?.removeIf { it.name.equals(name, ignoreCase = false) }
- }
-
- fun register(
- name: String,
- block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
- ): LiteralCommandNode<DefaultSource> {
- return dispatcher.register(literal(name, block))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/CustomItemModelEvent.kt b/src/main/kotlin/moe/nea/firmament/events/CustomItemModelEvent.kt
deleted file mode 100644
index 27524a9..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/CustomItemModelEvent.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import java.util.*
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.render.model.BakedModelManager
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.item.ItemStack
-
-data class CustomItemModelEvent(
- val itemStack: ItemStack,
- var overrideModel: ModelIdentifier? = null,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<CustomItemModelEvent>() {
- private val cache = IdentityHashMap<ItemStack?, Any>()
- private val sentinelNull = Object()
-
- fun clearCache() {
- cache.clear()
- }
-
- @JvmStatic
- fun getModelIdentifier(itemStack: ItemStack?): ModelIdentifier? {
- if (itemStack == null) return null
- return publish(CustomItemModelEvent(itemStack)).overrideModel
- }
-
- @JvmStatic
- fun getModel(itemStack: ItemStack?, thing: BakedModelManager): BakedModel? {
- if (itemStack == null) return null
- val cachedValue = cache.getOrPut(itemStack) {
- val modelId = getModelIdentifier(itemStack) ?: return@getOrPut sentinelNull
- val bakedModel = thing.getModel(modelId)
- if (bakedModel === thing.missingModel) return@getOrPut sentinelNull
- bakedModel
- }
- if (cachedValue === sentinelNull)
- return null
- return cachedValue as BakedModel
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/EarlyResourceReloadEvent.kt b/src/main/kotlin/moe/nea/firmament/events/EarlyResourceReloadEvent.kt
deleted file mode 100644
index ec8377a..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/EarlyResourceReloadEvent.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-package moe.nea.firmament.events
-
-import java.util.concurrent.Executor
-import net.minecraft.resource.ResourceManager
-
-data class EarlyResourceReloadEvent(val resourceManager: ResourceManager, val preparationExecutor: Executor) :
- FirmamentEvent() {
- companion object : FirmamentEventBus<EarlyResourceReloadEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/EntityDespawnEvent.kt b/src/main/kotlin/moe/nea/firmament/events/EntityDespawnEvent.kt
deleted file mode 100644
index 93dc477..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/EntityDespawnEvent.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.entity.Entity
-
-data class EntityDespawnEvent(
- val entity: Entity?, val entityId: Int,
- val reason: Entity.RemovalReason,
-) : FirmamentEvent() {
- companion object: FirmamentEventBus<EntityDespawnEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/EntityInteractionEvent.kt b/src/main/kotlin/moe/nea/firmament/events/EntityInteractionEvent.kt
deleted file mode 100644
index 123ea39..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/EntityInteractionEvent.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.entity.Entity
-import net.minecraft.util.Hand
-
-data class EntityInteractionEvent(
- val kind: InteractionKind,
- val entity: Entity,
- val hand: Hand,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<EntityInteractionEvent>()
- enum class InteractionKind {
- /**
- * Is sent when left-clicking an entity
- */
- ATTACK,
-
- /**
- * Is a fallback when [INTERACT_AT_LOCATION] fails
- */
- INTERACT,
-
- /**
- * Is tried first on right click
- */
- INTERACT_AT_LOCATION,
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/EntityUpdateEvent.kt b/src/main/kotlin/moe/nea/firmament/events/EntityUpdateEvent.kt
deleted file mode 100644
index d091984..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/EntityUpdateEvent.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.entity.Entity
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.data.DataTracker
-import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket
-
-/**
- * This event is fired when some entity properties are updated.
- * It is not fired for common changes like position, but is for less common ones,
- * like health, tracked data, names, equipment. It is always fired
- * *after* the values have been applied to the entity.
- */
-sealed class EntityUpdateEvent : FirmamentEvent() {
- companion object : FirmamentEventBus<EntityUpdateEvent>()
-
- abstract val entity: Entity
-
- data class AttributeUpdate(
- override val entity: LivingEntity,
- val attributes: List<EntityAttributesS2CPacket.Entry>,
- ) : EntityUpdateEvent()
-
- data class TrackedDataUpdate(
- override val entity: Entity,
- val trackedValues: List<DataTracker.SerializedEntry<*>>,
- ) : EntityUpdateEvent()
-
-// TODO: onEntityPassengersSet, onEntityAttach?, onEntityEquipmentUpdate, onEntityStatusEffect
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/FeaturesInitializedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/FeaturesInitializedEvent.kt
deleted file mode 100644
index ad2ad8a..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/FeaturesInitializedEvent.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package moe.nea.firmament.events
-
-import moe.nea.firmament.features.FirmamentFeature
-
-data class FeaturesInitializedEvent(val features: List<FirmamentFeature>) : FirmamentEvent() {
- companion object : FirmamentEventBus<FeaturesInitializedEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/FinalizeResourceManagerEvent.kt b/src/main/kotlin/moe/nea/firmament/events/FinalizeResourceManagerEvent.kt
deleted file mode 100644
index c43ad3b..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/FinalizeResourceManagerEvent.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.resource.ReloadableResourceManagerImpl
-
-data class FinalizeResourceManagerEvent(
- val resourceManager: ReloadableResourceManagerImpl,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<FinalizeResourceManagerEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/FirmamentEvent.kt b/src/main/kotlin/moe/nea/firmament/events/FirmamentEvent.kt
deleted file mode 100644
index 1a93ef5..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/FirmamentEvent.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-/**
- * An event that can be fired by a [FirmamentEventBus].
- *
- * Typically, that event bus is implemented as a companion object
- *
- * ```
- * class SomeEvent : FirmamentEvent() {
- * companion object : FirmamentEventBus<SomeEvent>()
- * }
- * ```
- */
-abstract class FirmamentEvent {
- /**
- * A [FirmamentEvent] that can be [cancelled]
- */
- abstract class Cancellable : FirmamentEvent() {
- /**
- * Cancels this is event.
- *
- * @see cancelled
- */
- fun cancel() {
- cancelled = true
- }
-
- /**
- * Whether this event is cancelled.
- *
- * Cancelled events will bypass handlers unless otherwise specified and will prevent the action that this
- * event was originally fired for.
- */
- var cancelled: Boolean = false
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt b/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt
deleted file mode 100644
index ee9e6c8..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/FirmamentEventBus.kt
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import java.util.concurrent.CopyOnWriteArrayList
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.MC
-
-/**
- * A pubsub event bus.
- *
- * [subscribe] to events [publish]ed on this event bus.
- * Subscriptions may not necessarily be delivered in the order of registering.
- */
-open class FirmamentEventBus<T : FirmamentEvent> {
- data class Handler<T>(
- val invocation: (T) -> Unit, val receivesCancelled: Boolean,
- var knownErrors: MutableSet<Class<*>> = mutableSetOf(),
- )
-
- private val toHandle: MutableList<Handler<T>> = CopyOnWriteArrayList()
- fun subscribe(handle: (T) -> Unit) {
- subscribe(false, handle)
- }
-
- fun subscribe(receivesCancelled: Boolean, handle: (T) -> Unit) {
- toHandle.add(Handler(handle, receivesCancelled))
- }
-
- fun publish(event: T): T {
- for (function in toHandle) {
- if (function.receivesCancelled || event !is FirmamentEvent.Cancellable || !event.cancelled) {
- try {
- function.invocation(event)
- } catch (e: Exception) {
- val klass = e.javaClass
- if (!function.knownErrors.contains(klass) || Firmament.DEBUG) {
- function.knownErrors.add(klass)
- Firmament.logger.error("Caught exception during processing event $event by $function", e)
- }
- }
- }
- }
- return event
- }
-
- fun publishSync(event: T) {
- MC.onMainThread {
- publish(event)
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HandledScreenClickEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HandledScreenClickEvent.kt
deleted file mode 100644
index 4c3003c..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HandledScreenClickEvent.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-
-data class HandledScreenClickEvent(val screen: HandledScreen<*>, val mouseX: Double, val mouseY: Double, val button: Int) :
- FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<HandledScreenClickEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HandledScreenForegroundEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HandledScreenForegroundEvent.kt
deleted file mode 100644
index f16d30e..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HandledScreenForegroundEvent.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-
-data class HandledScreenForegroundEvent(
- val screen: HandledScreen<*>,
- val context: DrawContext,
- val mouseX: Int,
- val mouseY: Int,
- val delta: Float
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<HandledScreenForegroundEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HandledScreenKeyPressedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HandledScreenKeyPressedEvent.kt
deleted file mode 100644
index 7ec2abb..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HandledScreenKeyPressedEvent.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.client.option.KeyBinding
-import moe.nea.firmament.keybindings.IKeyBinding
-
-data class HandledScreenKeyPressedEvent(
- val screen: HandledScreen<*>,
- val keyCode: Int,
- val scanCode: Int,
- val modifiers: Int
-) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<HandledScreenKeyPressedEvent>()
-
- fun matches(keyBinding: KeyBinding): Boolean {
- return matches(IKeyBinding.minecraft(keyBinding))
- }
-
- fun matches(keyBinding: IKeyBinding): Boolean {
- return keyBinding.matches(keyCode, scanCode, modifiers)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HandledScreenPushREIEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HandledScreenPushREIEvent.kt
deleted file mode 100644
index 1bb495a..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HandledScreenPushREIEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import me.shedaniel.math.Rectangle
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-
-data class HandledScreenPushREIEvent(
- val screen: HandledScreen<*>,
- val rectangles: MutableList<Rectangle> = mutableListOf()
-) : FirmamentEvent() {
-
- fun block(rectangle: Rectangle) {
- rectangles.add(rectangle)
- }
-
- companion object : FirmamentEventBus<HandledScreenPushREIEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HotbarItemRenderEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HotbarItemRenderEvent.kt
deleted file mode 100644
index a1940e6..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HotbarItemRenderEvent.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.RenderTickCounter
-import net.minecraft.item.ItemStack
-
-data class HotbarItemRenderEvent(
- val item: ItemStack,
- val context: DrawContext,
- val x: Int,
- val y: Int,
- val tickDelta: RenderTickCounter,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<HotbarItemRenderEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/HudRenderEvent.kt b/src/main/kotlin/moe/nea/firmament/events/HudRenderEvent.kt
deleted file mode 100644
index 555b3c8..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/HudRenderEvent.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.RenderTickCounter
-
-/**
- * Called when hud elements should be rendered, before the screen, but after the world.
- */
-data class HudRenderEvent(val context: DrawContext, val tickDelta: RenderTickCounter) : FirmamentEvent() {
- companion object : FirmamentEventBus<HudRenderEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/IsSlotProtectedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/IsSlotProtectedEvent.kt
deleted file mode 100644
index cd431f7..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/IsSlotProtectedEvent.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.item.ItemStack
-import net.minecraft.screen.slot.Slot
-import net.minecraft.screen.slot.SlotActionType
-import net.minecraft.text.Text
-import moe.nea.firmament.util.CommonSoundEffects
-import moe.nea.firmament.util.MC
-
-data class IsSlotProtectedEvent(
- val slot: Slot?,
- val actionType: SlotActionType,
- var isProtected: Boolean,
- val itemStackOverride: ItemStack?,
- var silent: Boolean = false,
-) : FirmamentEvent() {
- val itemStack get() = itemStackOverride ?: slot!!.stack
-
- fun protect() {
- isProtected = true
- }
-
- fun protectSilent() {
- if (!isProtected) {
- silent = true
- }
- isProtected = true
- }
-
- companion object : FirmamentEventBus<IsSlotProtectedEvent>() {
- @JvmStatic
- @JvmOverloads
- fun shouldBlockInteraction(slot: Slot?, action: SlotActionType, itemStackOverride: ItemStack? = null): Boolean {
- if (slot == null && itemStackOverride == null) return false
- val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride)
- publish(event)
- if (event.isProtected && !event.silent) {
- MC.player?.sendMessage(Text.translatable("firmament.protectitem").append(event.itemStack.name))
- CommonSoundEffects.playFailure()
- }
- return event.isProtected
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ItemTooltipEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ItemTooltipEvent.kt
deleted file mode 100644
index d86e06f..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ItemTooltipEvent.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.item.Item.TooltipContext
-import net.minecraft.item.ItemStack
-import net.minecraft.item.tooltip.TooltipType
-import net.minecraft.text.Text
-
-data class ItemTooltipEvent(
- val stack: ItemStack, val context: TooltipContext, val type: TooltipType, val lines: MutableList<Text>
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<ItemTooltipEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt b/src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt
deleted file mode 100644
index 35aade0..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import com.mojang.brigadier.CommandDispatcher
-
-data class MaskCommands(val dispatcher: CommandDispatcher<*>) : FirmamentEvent() {
- companion object : FirmamentEventBus<MaskCommands>()
-
- fun mask(name: String) {
- dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = true) }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt
deleted file mode 100644
index a5868e8..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ModifyChatEvent.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import moe.nea.firmament.util.unformattedString
-import net.minecraft.text.Text
-
-/**
- * Allow modification of a chat message before it is sent off to the user. Intended for display purposes.
- */
-data class ModifyChatEvent(val originalText: Text) : FirmamentEvent() {
- var unformattedString = originalText.unformattedString
- private set
- var replaceWith: Text = originalText
- set(value) {
- field = value
- unformattedString = value.unformattedString
- }
-
- companion object : FirmamentEventBus<ModifyChatEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/OutgoingPacketEvent.kt b/src/main/kotlin/moe/nea/firmament/events/OutgoingPacketEvent.kt
deleted file mode 100644
index 93890ea..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/OutgoingPacketEvent.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.network.packet.Packet
-
-data class OutgoingPacketEvent(val packet: Packet<*>) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<OutgoingPacketEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ParticleSpawnEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ParticleSpawnEvent.kt
deleted file mode 100644
index 9359e4b..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ParticleSpawnEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import org.joml.Vector3f
-import net.minecraft.particle.ParticleEffect
-import net.minecraft.util.math.Vec3d
-
-data class ParticleSpawnEvent(
- val particleEffect: ParticleEffect,
- val position: Vec3d,
- val offset: Vector3f,
- val longDistance: Boolean,
- val count: Int,
- val speed: Float,
-) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<ParticleSpawnEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/PlayerInventoryUpdate.kt b/src/main/kotlin/moe/nea/firmament/events/PlayerInventoryUpdate.kt
deleted file mode 100644
index 6e8203a..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/PlayerInventoryUpdate.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.item.ItemStack
-
-sealed class PlayerInventoryUpdate : FirmamentEvent() {
- companion object : FirmamentEventBus<PlayerInventoryUpdate>()
- data class Single(val slot: Int, val stack: ItemStack) : PlayerInventoryUpdate()
- data class Multi(val contents: List<ItemStack>) : PlayerInventoryUpdate()
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt
deleted file mode 100644
index 76c0b27..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ProcessChatEvent.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.text.Text
-import moe.nea.firmament.util.unformattedString
-
-/**
- * Behaves like [AllowChatEvent], but is triggered even when cancelled by other mods. Intended for data collection.
- * Make sure to subscribe to cancellable events as well when using.
- */
-data class ProcessChatEvent(val text: Text, val wasExternallyCancelled: Boolean) : FirmamentEvent.Cancellable() {
- val unformattedString = text.unformattedString
-
- val nameHeuristic: String? = run {
- val firstColon = unformattedString.indexOf(':')
- if (firstColon < 0) return@run null
- val firstSpace = unformattedString.lastIndexOf(' ', firstColon)
- unformattedString.substring(firstSpace + 1 until firstColon).takeIf { it.isNotEmpty() }
- }
-
- init {
- if (wasExternallyCancelled)
- cancelled = true
- }
-
- companion object : FirmamentEventBus<ProcessChatEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt
deleted file mode 100644
index 4c3083e..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ReloadRegistrationEvent.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package moe.nea.firmament.events
-
-import io.github.moulberry.repo.NEURepository
-
-data class ReloadRegistrationEvent(val repo: NEURepository) : FirmamentEvent() {
- companion object : FirmamentEventBus<ReloadRegistrationEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ScreenChangeEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ScreenChangeEvent.kt
deleted file mode 100644
index 489e487..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ScreenChangeEvent.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.screen.Screen
-
-data class ScreenChangeEvent(val old: Screen?, val new: Screen?) : FirmamentEvent.Cancellable() {
- var overrideScreen: Screen? = null
- companion object : FirmamentEventBus<ScreenChangeEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ScreenRenderPostEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ScreenRenderPostEvent.kt
deleted file mode 100644
index 79f4913..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ScreenRenderPostEvent.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.Screen
-
-data class ScreenRenderPostEvent(
- val screen: Screen,
- val mouseX: Int,
- val mouseY: Int,
- val tickDelta: Float,
- val drawContext: DrawContext
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<ScreenRenderPostEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/ServerConnectedEvent.kt b/src/main/kotlin/moe/nea/firmament/events/ServerConnectedEvent.kt
deleted file mode 100644
index 26897f2..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/ServerConnectedEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package moe.nea.firmament.events
-
-import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.network.ClientPlayNetworkHandler
-import net.minecraft.network.ClientConnection
-
-data class ServerConnectedEvent(
- val connection: ClientConnection
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<ServerConnectedEvent>() {
- init {
- ClientPlayConnectionEvents.INIT.register(ClientPlayConnectionEvents.Init { clientPlayNetworkHandler: ClientPlayNetworkHandler, minecraftClient: MinecraftClient ->
- publishSync(ServerConnectedEvent(clientPlayNetworkHandler.connection))
- })
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/SkyblockServerUpdateEvent.kt b/src/main/kotlin/moe/nea/firmament/events/SkyblockServerUpdateEvent.kt
deleted file mode 100644
index 0bc5143..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/SkyblockServerUpdateEvent.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import moe.nea.firmament.util.Locraw
-
-/**
- * This event gets published whenever `/locraw` is queried and HyPixel returns a location different to the old one.
- *
- * **N.B.:** This event may get fired multiple times while on the server (for example, first to null, then to the
- * correct location).
- */
-data class SkyblockServerUpdateEvent(val oldLocraw: Locraw?, val newLocraw: Locraw?) : FirmamentEvent() {
- companion object : FirmamentEventBus<SkyblockServerUpdateEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/SlotClickEvent.kt b/src/main/kotlin/moe/nea/firmament/events/SlotClickEvent.kt
deleted file mode 100644
index d4abfb0..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/SlotClickEvent.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.item.ItemStack
-import net.minecraft.screen.slot.Slot
-import net.minecraft.screen.slot.SlotActionType
-
-data class SlotClickEvent(
- val slot: Slot,
- val stack: ItemStack,
- val button: Int,
- val actionType: SlotActionType,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<SlotClickEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/SlotRenderEvents.kt b/src/main/kotlin/moe/nea/firmament/events/SlotRenderEvents.kt
deleted file mode 100644
index 8352581..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/SlotRenderEvents.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.screen.slot.Slot
-
-interface SlotRenderEvents {
- val context: DrawContext
- val slot: Slot
- val mouseX: Int
- val mouseY: Int
- val delta: Float
-
- data class Before(
- override val context: DrawContext, override val slot: Slot,
- override val mouseX: Int,
- override val mouseY: Int,
- override val delta: Float
- ) : FirmamentEvent(),
- SlotRenderEvents {
- companion object : FirmamentEventBus<Before>()
- }
-
- data class After(
- override val context: DrawContext, override val slot: Slot,
- override val mouseX: Int,
- override val mouseY: Int,
- override val delta: Float
- ) : FirmamentEvent(),
- SlotRenderEvents {
- companion object : FirmamentEventBus<After>()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/SoundReceiveEvent.kt b/src/main/kotlin/moe/nea/firmament/events/SoundReceiveEvent.kt
deleted file mode 100644
index d1b85b6..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/SoundReceiveEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.registry.entry.RegistryEntry
-import net.minecraft.sound.SoundCategory
-import net.minecraft.sound.SoundEvent
-import net.minecraft.util.math.Vec3d
-
-data class SoundReceiveEvent(
- val sound: RegistryEntry<SoundEvent>,
- val category: SoundCategory,
- val position: Vec3d,
- val pitch: Float,
- val volume: Float,
- val seed: Long
-) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<SoundReceiveEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/TickEvent.kt b/src/main/kotlin/moe/nea/firmament/events/TickEvent.kt
deleted file mode 100644
index 18007f8..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/TickEvent.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-data class TickEvent(val tickCount: Int) : FirmamentEvent() {
- companion object : FirmamentEventBus<TickEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/TooltipEvent.kt b/src/main/kotlin/moe/nea/firmament/events/TooltipEvent.kt
deleted file mode 100644
index 630ba56..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/TooltipEvent.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.gui.tooltip.Tooltip
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-
-data class TooltipEvent(
- val itemStack: ItemStack,
- val tooltip: Tooltip,
- val tooltipContext: Item.TooltipContext,
- val player: PlayerEntity?
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<TooltipEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt b/src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt
deleted file mode 100644
index 8bbe0de..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/UseBlockEvent.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-package moe.nea.firmament.events
-
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.util.Hand
-import net.minecraft.util.hit.BlockHitResult
-import net.minecraft.world.World
-
-data class UseBlockEvent(val player: PlayerEntity, val world: World, val hand: Hand, val hitResult: BlockHitResult) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<UseBlockEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/WorldKeyboardEvent.kt b/src/main/kotlin/moe/nea/firmament/events/WorldKeyboardEvent.kt
deleted file mode 100644
index e8566fd..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/WorldKeyboardEvent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.option.KeyBinding
-import moe.nea.firmament.keybindings.IKeyBinding
-
-data class WorldKeyboardEvent(val keyCode: Int, val scanCode: Int, val modifiers: Int) : FirmamentEvent.Cancellable() {
- companion object : FirmamentEventBus<WorldKeyboardEvent>()
-
- fun matches(keyBinding: KeyBinding): Boolean {
- return matches(IKeyBinding.minecraft(keyBinding))
- }
-
- fun matches(keyBinding: IKeyBinding): Boolean {
- return keyBinding.matches(keyCode, scanCode, modifiers)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/WorldReadyEvent.kt b/src/main/kotlin/moe/nea/firmament/events/WorldReadyEvent.kt
deleted file mode 100644
index 2c76c44..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/WorldReadyEvent.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-class WorldReadyEvent : FirmamentEvent() {
- companion object : FirmamentEventBus<WorldReadyEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt b/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt
deleted file mode 100644
index 21a670d..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-package moe.nea.firmament.events
-
-import net.minecraft.client.render.Camera
-import net.minecraft.client.render.GameRenderer
-import net.minecraft.client.render.LightmapTextureManager
-import net.minecraft.client.render.RenderTickCounter
-import net.minecraft.client.render.VertexConsumerProvider
-import net.minecraft.client.util.math.MatrixStack
-import net.minecraft.util.math.Position
-import net.minecraft.util.math.Vec3d
-
-/**
- * This event is called after all world rendering is done, but before any GUI rendering (including hand) has been done.
- */
-data class WorldRenderLastEvent(
- val matrices: MatrixStack,
- val tickCounter: RenderTickCounter,
- val renderBlockOutline: Boolean,
- val camera: Camera,
- val gameRenderer: GameRenderer,
- val lightmapTextureManager: LightmapTextureManager,
- val vertexConsumers: VertexConsumerProvider.Immediate,
-) : FirmamentEvent() {
- companion object : FirmamentEventBus<WorldRenderLastEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt b/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt
deleted file mode 100644
index 4c1c63f..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/registration/ChatEvents.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-package moe.nea.firmament.events.registration
-
-import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents
-import net.fabricmc.fabric.api.event.player.AttackBlockCallback
-import net.fabricmc.fabric.api.event.player.UseBlockCallback
-import net.minecraft.text.Text
-import net.minecraft.util.ActionResult
-import moe.nea.firmament.events.AllowChatEvent
-import moe.nea.firmament.events.AttackBlockEvent
-import moe.nea.firmament.events.ModifyChatEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.UseBlockEvent
-
-private var lastReceivedMessage: Text? = null
-
-fun registerFirmamentEvents() {
- ClientReceiveMessageEvents.ALLOW_CHAT.register(ClientReceiveMessageEvents.AllowChat { message, signedMessage, sender, params, receptionTimestamp ->
- lastReceivedMessage = message
- !ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled
- && !AllowChatEvent.publish(AllowChatEvent(message)).cancelled
- })
- ClientReceiveMessageEvents.ALLOW_GAME.register(ClientReceiveMessageEvents.AllowGame { message, overlay ->
- lastReceivedMessage = message
- overlay || (!ProcessChatEvent.publish(ProcessChatEvent(message, false)).cancelled &&
- !AllowChatEvent.publish(AllowChatEvent(message)).cancelled)
- })
- ClientReceiveMessageEvents.MODIFY_GAME.register(ClientReceiveMessageEvents.ModifyGame { message, overlay ->
- if (overlay) message
- else ModifyChatEvent.publish(ModifyChatEvent(message)).replaceWith
- })
- ClientReceiveMessageEvents.GAME_CANCELED.register(ClientReceiveMessageEvents.GameCanceled { message, overlay ->
- if (!overlay && lastReceivedMessage !== message) {
- ProcessChatEvent.publish(ProcessChatEvent(message, true))
- }
- })
- ClientReceiveMessageEvents.CHAT_CANCELED.register(ClientReceiveMessageEvents.ChatCanceled { message, signedMessage, sender, params, receptionTimestamp ->
- if (lastReceivedMessage !== message) {
- ProcessChatEvent.publish(ProcessChatEvent(message, true))
- }
- })
-
- AttackBlockCallback.EVENT.register(AttackBlockCallback { player, world, hand, pos, direction ->
- if (AttackBlockEvent.publish(AttackBlockEvent(player, world, hand, pos, direction)).cancelled)
- ActionResult.CONSUME
- else ActionResult.PASS
- })
- UseBlockCallback.EVENT.register(UseBlockCallback { player, world, hand, hitResult ->
- if (UseBlockEvent.publish(UseBlockEvent(player, world, hand, hitResult)).cancelled)
- ActionResult.CONSUME
- else ActionResult.PASS
- })
-}
diff --git a/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt b/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt
deleted file mode 100644
index 83b91c9..0000000
--- a/src/main/kotlin/moe/nea/firmament/events/subscription/Subscription.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-
-package moe.nea.firmament.events.subscription
-
-import moe.nea.firmament.events.FirmamentEvent
-import moe.nea.firmament.events.FirmamentEventBus
-import moe.nea.firmament.features.FirmamentFeature
-
-interface SubscriptionOwner {
- val delegateFeature: FirmamentFeature
-}
-
-data class Subscription<T : FirmamentEvent>(
- val owner: Any,
- val invoke: (T) -> Unit,
- val eventBus: FirmamentEventBus<T>,
-)
diff --git a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt b/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt
deleted file mode 100644
index 19b91de..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/FeatureManager.kt
+++ /dev/null
@@ -1,120 +0,0 @@
-
-
-package moe.nea.firmament.features
-
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.generated.AllSubscriptions
-import moe.nea.firmament.events.FeaturesInitializedEvent
-import moe.nea.firmament.events.FirmamentEvent
-import moe.nea.firmament.events.subscription.Subscription
-import moe.nea.firmament.features.chat.AutoCompletions
-import moe.nea.firmament.features.chat.ChatLinks
-import moe.nea.firmament.features.chat.QuickCommands
-import moe.nea.firmament.features.debug.DebugView
-import moe.nea.firmament.features.debug.DeveloperFeatures
-import moe.nea.firmament.features.debug.MinorTrolling
-import moe.nea.firmament.features.debug.PowerUserTools
-import moe.nea.firmament.features.diana.DianaWaypoints
-import moe.nea.firmament.features.events.anniversity.AnniversaryFeatures
-import moe.nea.firmament.features.events.carnival.CarnivalFeatures
-import moe.nea.firmament.features.fixes.CompatibliltyFeatures
-import moe.nea.firmament.features.fixes.Fixes
-import moe.nea.firmament.features.inventory.CraftingOverlay
-import moe.nea.firmament.features.inventory.ItemRarityCosmetics
-import moe.nea.firmament.features.inventory.PriceData
-import moe.nea.firmament.features.inventory.SaveCursorPosition
-import moe.nea.firmament.features.inventory.SlotLocking
-import moe.nea.firmament.features.inventory.buttons.InventoryButtons
-import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay
-import moe.nea.firmament.features.mining.PickaxeAbility
-import moe.nea.firmament.features.mining.PristineProfitTracker
-import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures
-import moe.nea.firmament.features.world.FairySouls
-import moe.nea.firmament.features.world.Waypoints
-import moe.nea.firmament.util.data.DataHolder
-
-object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "features", ::Config) {
- @Serializable
- data class Config(
- val enabledFeatures: MutableMap<String, Boolean> = mutableMapOf()
- )
-
- private val features = mutableMapOf<String, FirmamentFeature>()
-
- val allFeatures: Collection<FirmamentFeature> get() = features.values
-
- private var hasAutoloaded = false
-
- init {
- autoload()
- }
-
- fun autoload() {
- synchronized(this) {
- if (hasAutoloaded) return
- loadFeature(MinorTrolling)
- loadFeature(FairySouls)
- loadFeature(AutoCompletions)
- // TODO: loadFeature(FishingWarning)
- loadFeature(SlotLocking)
- loadFeature(StorageOverlay)
- loadFeature(PristineProfitTracker)
- loadFeature(CraftingOverlay)
- loadFeature(PowerUserTools)
- loadFeature(Waypoints)
- loadFeature(ChatLinks)
- loadFeature(InventoryButtons)
- loadFeature(CompatibliltyFeatures)
- loadFeature(AnniversaryFeatures)
- loadFeature(QuickCommands)
- loadFeature(SaveCursorPosition)
- loadFeature(CustomSkyBlockTextures)
- loadFeature(PriceData)
- loadFeature(Fixes)
- loadFeature(DianaWaypoints)
- loadFeature(ItemRarityCosmetics)
- loadFeature(PickaxeAbility)
- loadFeature(CarnivalFeatures)
- if (Firmament.DEBUG) {
- loadFeature(DeveloperFeatures)
- loadFeature(DebugView)
- }
- allFeatures.forEach { it.config }
- FeaturesInitializedEvent.publish(FeaturesInitializedEvent(allFeatures.toList()))
- hasAutoloaded = true
- }
- }
-
- fun subscribeEvents() {
- AllSubscriptions.provideSubscriptions {
- subscribeSingleEvent(it)
- }
- }
-
- private fun <T : FirmamentEvent> subscribeSingleEvent(it: Subscription<T>) {
- it.eventBus.subscribe(false, it.invoke)
- }
-
- fun loadFeature(feature: FirmamentFeature) {
- synchronized(features) {
- if (feature.identifier in features) {
- Firmament.logger.error("Double registering feature ${feature.identifier}. Ignoring second instance $feature")
- return
- }
- features[feature.identifier] = feature
- feature.onLoad()
- }
- }
-
- fun isEnabled(identifier: String): Boolean? =
- data.enabledFeatures[identifier]
-
-
- fun setEnabled(identifier: String, value: Boolean) {
- data.enabledFeatures[identifier] = value
- markDirty()
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt b/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt
deleted file mode 100644
index 2cfc4fd..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/FirmamentFeature.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-package moe.nea.firmament.features
-
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.gui.config.ManagedConfig
-
-// TODO: remove this entire feature system and revamp config
-interface FirmamentFeature : SubscriptionOwner {
- val identifier: String
- val defaultEnabled: Boolean
- get() = true
- var isEnabled: Boolean
- get() = FeatureManager.isEnabled(identifier) ?: defaultEnabled
- set(value) {
- FeatureManager.setEnabled(identifier, value)
- }
- override val delegateFeature: FirmamentFeature
- get() = this
- val config: ManagedConfig? get() = null
- fun onLoad() {}
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt b/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt
deleted file mode 100644
index 9144898..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/chat/AutoCompletions.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-package moe.nea.firmament.features.chat
-
-import com.mojang.brigadier.arguments.StringArgumentType.string
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.commands.get
-import moe.nea.firmament.commands.suggestsList
-import moe.nea.firmament.commands.thenArgument
-import moe.nea.firmament.commands.thenExecute
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.MaskCommands
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-
-object AutoCompletions : FirmamentFeature {
-
- object TConfig : ManagedConfig(identifier) {
- val provideWarpTabCompletion by toggle("warp-complete") { true }
- val replaceWarpIsByWarpIsland by toggle("warp-is") { true }
- }
-
- override val config: ManagedConfig?
- get() = TConfig
- override val identifier: String
- get() = "auto-completions"
-
- @Subscribe
- fun onMaskCommands(event: MaskCommands) {
- if (TConfig.provideWarpTabCompletion) {
- event.mask("warp")
- }
- }
-
- @Subscribe
- fun onCommandEvent(event: CommandEvent) {
- if (!TConfig.provideWarpTabCompletion) return
- event.deleteCommand("warp")
- event.register("warp") {
- thenArgument("to", string()) { toArg ->
- suggestsList {
- RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf()
- }
- thenExecute {
- val warpName = get(toArg)
- if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) {
- MC.sendServerCommand("warp island")
- } else {
- MC.sendServerCommand("warp $warpName")
- }
- }
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt b/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt
deleted file mode 100644
index f2cb78a..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/chat/ChatLinks.kt
+++ /dev/null
@@ -1,161 +0,0 @@
-
-
-package moe.nea.firmament.features.chat
-
-import io.ktor.client.request.get
-import io.ktor.client.statement.bodyAsChannel
-import io.ktor.utils.io.jvm.javaio.toInputStream
-import java.net.URL
-import java.util.Collections
-import moe.nea.jarvis.api.Point
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.async
-import kotlin.math.min
-import net.minecraft.client.gui.screen.ChatScreen
-import net.minecraft.client.texture.NativeImage
-import net.minecraft.client.texture.NativeImageBackedTexture
-import net.minecraft.text.ClickEvent
-import net.minecraft.text.HoverEvent
-import net.minecraft.text.Style
-import net.minecraft.text.Text
-import net.minecraft.util.Formatting
-import net.minecraft.util.Identifier
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ModifyChatEvent
-import moe.nea.firmament.events.ScreenRenderPostEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.transformEachRecursively
-import moe.nea.firmament.util.unformattedString
-
-object ChatLinks : FirmamentFeature {
- override val identifier: String
- get() = "chat-links"
-
- object TConfig : ManagedConfig(identifier) {
- val enableLinks by toggle("links-enabled") { true }
- val imageEnabled by toggle("image-enabled") { true }
- val allowAllHosts by toggle("allow-all-hosts") { false }
- val allowedHosts by string("allowed-hosts") { "cdn.discordapp.com,media.discordapp.com,media.discordapp.net,i.imgur.com" }
- val actualAllowedHosts get() = allowedHosts.split(",").map { it.trim() }
- val position by position("position", 16 * 20, 9 * 20) { Point(0.0, 0.0) }
- }
-
- private fun isHostAllowed(host: String) =
- TConfig.allowAllHosts || TConfig.actualAllowedHosts.any { it.equals(host, ignoreCase = true) }
-
- private fun isUrlAllowed(url: String) = isHostAllowed(url.removePrefix("https://").substringBefore("/"))
-
- override val config get() = TConfig
- val urlRegex = "https://[^. ]+\\.[^ ]+(\\.?( |$))".toRegex()
-
- data class Image(
- val texture: Identifier,
- val width: Int,
- val height: Int,
- )
-
- val imageCache: MutableMap<String, Deferred<Image?>> =
- Collections.synchronizedMap(mutableMapOf<String, Deferred<Image?>>())
-
- private fun tryCacheUrl(url: String) {
- if (!isUrlAllowed(url)) {
- return
- }
- if (url in imageCache) {
- return
- }
- imageCache[url] = Firmament.coroutineScope.async {
- try {
- val response = Firmament.httpClient.get(URL(url))
- if (response.status.value == 200) {
- val inputStream = response.bodyAsChannel().toInputStream(Firmament.globalJob)
- val image = NativeImage.read(inputStream)
- val texture = MC.textureManager.registerDynamicTexture(
- "dynamic_image_preview",
- NativeImageBackedTexture(image)
- )
- Image(texture, image.width, image.height)
- } else
- null
- } catch (exc: Exception) {
- exc.printStackTrace()
- null
- }
- }
- }
-
- val imageExtensions = listOf("jpg", "png", "gif", "jpeg")
- fun isImageUrl(url: String): Boolean {
- return (url.substringAfterLast('.').lowercase() in imageExtensions)
- }
-
- @Subscribe
- @OptIn(ExperimentalCoroutinesApi::class)
- fun onRender(it: ScreenRenderPostEvent) {
- if (!TConfig.imageEnabled) return
- if (it.screen !is ChatScreen) return
- val hoveredComponent =
- MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return
- val hoverEvent = hoveredComponent.hoverEvent ?: return
- val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return
- val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return
- if (!isImageUrl(url)) return
- val imageFuture = imageCache[url] ?: return
- if (!imageFuture.isCompleted) return
- val image = imageFuture.getCompleted() ?: return
- it.drawContext.matrices.push()
- val pos = TConfig.position
- pos.applyTransformations(it.drawContext.matrices)
- val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width))
- it.drawContext.matrices.scale(scale, scale, 1F)
- it.drawContext.drawTexture(
- image.texture,
- 0,
- 0,
- 1F,
- 1F,
- image.width,
- image.height,
- image.width,
- image.height,
- )
- it.drawContext.matrices.pop()
- }
-
- @Subscribe
- fun onModifyChat(it: ModifyChatEvent) {
- if (!TConfig.enableLinks) return
- it.replaceWith = it.replaceWith.transformEachRecursively { child ->
- val text = child.string
- if ("://" !in text) return@transformEachRecursively child
- val s = Text.empty().setStyle(child.style)
- var index = 0
- while (index < text.length) {
- val nextMatch = urlRegex.find(text, index)
- if (nextMatch == null) {
- s.append(Text.literal(text.substring(index, text.length)))
- break
- }
- val range = nextMatch.groups[0]!!.range
- val url = nextMatch.groupValues[0]
- s.append(Text.literal(text.substring(index, range.first)))
- s.append(
- Text.literal(url).setStyle(
- Style.EMPTY.withUnderline(true).withColor(
- Formatting.AQUA
- ).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url)))
- .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url))
- )
- )
- if (isImageUrl(url))
- tryCacheUrl(url)
- index = range.last + 1
- }
- s
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt b/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt
deleted file mode 100644
index 5944b92..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/chat/QuickCommands.kt
+++ /dev/null
@@ -1,100 +0,0 @@
-
-
-package moe.nea.firmament.features.chat
-
-import com.mojang.brigadier.context.CommandContext
-import net.minecraft.text.Text
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.commands.DefaultSource
-import moe.nea.firmament.commands.RestArgumentType
-import moe.nea.firmament.commands.get
-import moe.nea.firmament.commands.thenArgument
-import moe.nea.firmament.commands.thenExecute
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-
-object QuickCommands : FirmamentFeature {
- override val identifier: String
- get() = "quick-commands"
-
- fun removePartialPrefix(text: String, prefix: String): String? {
- var lf: String? = null
- for (i in 1..prefix.length) {
- if (text.startsWith(prefix.substring(0, i))) {
- lf = text.substring(i)
- }
- }
- return lf
- }
-
- val kuudraLevelNames = listOf("NORMAL", "HOT", "BURNING", "FIERY", "INFERNAL")
- val dungeonLevelNames = listOf("ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN")
-
- @Subscribe
- fun onCommands(it: CommandEvent) {
- it.register("join") {
- thenArgument("what", RestArgumentType) { what ->
- thenExecute {
- val what = this[what]
- if (!SBData.isOnSkyblock) {
- MC.sendCommand("join $what")
- return@thenExecute
- }
- val joinName = getNameForFloor(what.replace(" ", "").lowercase())
- if (joinName == null) {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown", what))
- } else {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.success",
- joinName))
- MC.sendCommand("joininstance $joinName")
- }
- }
- }
- thenExecute {
- source.sendFeedback(Text.translatable("firmament.quick-commands.join.explain"))
- }
- }
- }
-
- fun CommandContext<DefaultSource>.getNameForFloor(w: String): String? {
- val kuudraLevel = removePartialPrefix(w, "kuudratier") ?: removePartialPrefix(w, "tier")
- if (kuudraLevel != null) {
- val l = kuudraLevel.toIntOrNull()?.let { it - 1 } ?: kuudraLevelNames.indexOfFirst {
- it.startsWith(
- kuudraLevel,
- true
- )
- }
- if (l !in kuudraLevelNames.indices) {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-kuudra",
- kuudraLevel))
- return null
- }
- return "KUUDRA_${kuudraLevelNames[l]}"
- }
- val masterLevel = removePartialPrefix(w, "master")
- val normalLevel =
- removePartialPrefix(w, "floor") ?: removePartialPrefix(w, "catacombs") ?: removePartialPrefix(w, "dungeons")
- val dungeonLevel = masterLevel ?: normalLevel
- if (dungeonLevel != null) {
- val l = dungeonLevel.toIntOrNull()?.let { it - 1 } ?: dungeonLevelNames.indexOfFirst {
- it.startsWith(
- dungeonLevel,
- true
- )
- }
- if (masterLevel == null && (l == -1 || null != removePartialPrefix(w, "entrance"))) {
- return "CATACOMBS_ENTRANCE"
- }
- if (l !in dungeonLevelNames.indices) {
- source.sendFeedback(Text.stringifiedTranslatable("firmament.quick-commands.join.unknown-catacombs",
- kuudraLevel))
- return null
- }
- return "${if (masterLevel != null) "MASTER_" else ""}CATACOMBS_FLOOR_${dungeonLevelNames[l]}"
- }
- return null
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/DebugLogger.kt b/src/main/kotlin/moe/nea/firmament/features/debug/DebugLogger.kt
deleted file mode 100644
index ab06030..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/debug/DebugLogger.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-package moe.nea.firmament.features.debug
-
-import net.minecraft.text.Text
-import moe.nea.firmament.util.MC
-
-class DebugLogger(val tag: String) {
- fun isEnabled() = DeveloperFeatures.isEnabled // TODO: allow filtering by tag
- fun log(text: () -> String) {
- if (!isEnabled()) return
- MC.sendChat(Text.literal(text()))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/DebugView.kt b/src/main/kotlin/moe/nea/firmament/features/debug/DebugView.kt
deleted file mode 100644
index 7e1b8ec..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/debug/DebugView.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-package moe.nea.firmament.features.debug
-
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.TimeMark
-
-object DebugView : FirmamentFeature {
- private data class StoredVariable<T>(
- val obj: T,
- val timer: TimeMark,
- )
-
- private val storedVariables: MutableMap<String, StoredVariable<*>> = sortedMapOf()
- override val identifier: String
- get() = "debug-view"
- override val defaultEnabled: Boolean
- get() = Firmament.DEBUG
-
- fun <T : Any?> showVariable(label: String, obj: T) {
- synchronized(this) {
- storedVariables[label] = StoredVariable(obj, TimeMark.now())
- }
- }
-
- fun recalculateDebugWidget() {
- }
-
- override fun onLoad() {
- TickEvent.subscribe {
- synchronized(this) {
- recalculateDebugWidget()
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt
deleted file mode 100644
index 20c0cfd..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/debug/DeveloperFeatures.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-package moe.nea.firmament.features.debug
-
-import java.nio.file.Path
-import java.util.concurrent.CompletableFuture
-import kotlin.io.path.absolute
-import kotlin.io.path.exists
-import net.minecraft.client.MinecraftClient
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.errorBoundary
-import moe.nea.firmament.util.iterate
-
-object DeveloperFeatures : FirmamentFeature {
- override val identifier: String
- get() = "developer"
- override val config: TConfig
- get() = TConfig
- override val defaultEnabled: Boolean
- get() = Firmament.DEBUG
-
- val gradleDir =
- Path.of(".").absolute()
- .iterate { it.parent }
- .find { it.resolve("settings.gradle.kts").exists() }
-
- object TConfig : ManagedConfig("developer") {
- val autoRebuildResources by toggle("auto-rebuild") { false }
- }
-
- @JvmStatic
- fun hookOnBeforeResourceReload(client: MinecraftClient): CompletableFuture<Void> {
- val reloadFuture = if (TConfig.autoRebuildResources && isEnabled && gradleDir != null) {
- val builder = ProcessBuilder("./gradlew", ":processResources")
- builder.directory(gradleDir.toFile())
- builder.inheritIO()
- val process = builder.start()
- MC.player?.sendMessage(Text.translatable("firmament.dev.resourcerebuild.start"))
- val startTime = TimeMark.now()
- process.toHandle().onExit().thenApply {
- MC.player?.sendMessage(Text.stringifiedTranslatable("firmament.dev.resourcerebuild.done", startTime.passedTime()))
- Unit
- }
- } else {
- CompletableFuture.completedFuture(Unit)
- }
- return reloadFuture.thenCompose { client.reloadResources() }
- }
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt b/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt
deleted file mode 100644
index 32035a6..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/debug/MinorTrolling.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-package moe.nea.firmament.features.debug
-
-import net.minecraft.text.Text
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ModifyChatEvent
-import moe.nea.firmament.features.FirmamentFeature
-
-
-// In memorian Dulkir
-object MinorTrolling : FirmamentFeature {
- override val identifier: String
- get() = "minor-trolling"
-
- val trollers = listOf("nea89o", "lrg89")
- val t = "From(?: \\[[^\\]]+])? ([^:]+): (.*)".toRegex()
-
- @Subscribe
- fun onTroll(it: ModifyChatEvent) {
- val m = t.matchEntire(it.unformattedString) ?: return
- val (_, name, text) = m.groupValues
- if (name !in trollers) return
- if (!text.startsWith("c:")) return
- it.replaceWith = Text.literal(text.substring(2).replace("&", "§"))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt b/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt
deleted file mode 100644
index 7893eff..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/debug/PowerUserTools.kt
+++ /dev/null
@@ -1,193 +0,0 @@
-
-
-package moe.nea.firmament.features.debug
-
-import net.minecraft.block.SkullBlock
-import net.minecraft.block.entity.SkullBlockEntity
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.entity.Entity
-import net.minecraft.entity.LivingEntity
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import net.minecraft.util.hit.BlockHitResult
-import net.minecraft.util.hit.EntityHitResult
-import net.minecraft.util.hit.HitResult
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.CustomItemModelEvent
-import moe.nea.firmament.events.HandledScreenKeyPressedEvent
-import moe.nea.firmament.events.ItemTooltipEvent
-import moe.nea.firmament.events.ScreenChangeEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.events.WorldKeyboardEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import moe.nea.firmament.util.ClipboardUtils
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.focusedItemStack
-import moe.nea.firmament.util.skyBlockId
-
-object PowerUserTools : FirmamentFeature {
- override val identifier: String
- get() = "power-user"
-
- object TConfig : ManagedConfig(identifier) {
- val showItemIds by toggle("show-item-id") { false }
- val copyItemId by keyBindingWithDefaultUnbound("copy-item-id")
- val copyTexturePackId by keyBindingWithDefaultUnbound("copy-texture-pack-id")
- val copyNbtData by keyBindingWithDefaultUnbound("copy-nbt-data")
- val copySkullTexture by keyBindingWithDefaultUnbound("copy-skull-texture")
- val copyEntityData by keyBindingWithDefaultUnbound("entity-data")
- }
-
- override val config
- get() = TConfig
-
- var lastCopiedStack: Pair<ItemStack, Text>? = null
- set(value) {
- field = value
- if (value != null)
- lastCopiedStackViewTime = true
- }
- var lastCopiedStackViewTime = false
-
- override fun onLoad() {
- TickEvent.subscribe {
- if (!lastCopiedStackViewTime)
- lastCopiedStack = null
- lastCopiedStackViewTime = false
- }
- ScreenChangeEvent.subscribe {
- lastCopiedStack = null
- }
- }
-
- fun debugFormat(itemStack: ItemStack): Text {
- return Text.literal(itemStack.skyBlockId?.toString() ?: itemStack.toString())
- }
-
- @Subscribe
- fun onEntityInfo(event: WorldKeyboardEvent) {
- if (!event.matches(TConfig.copyEntityData)) return
- val target = (MC.instance.crosshairTarget as? EntityHitResult)?.entity
- if (target == null) {
- MC.sendChat(Text.translatable("firmament.poweruser.entity.fail"))
- return
- }
- showEntity(target)
- }
-
- fun showEntity(target: Entity) {
- MC.sendChat(Text.translatable("firmament.poweruser.entity.type", target.type))
- MC.sendChat(Text.translatable("firmament.poweruser.entity.name", target.name))
- MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.position", target.pos))
- if (target is LivingEntity) {
- MC.sendChat(Text.translatable("firmament.poweruser.entity.armor"))
- for (armorItem in target.armorItems) {
- MC.sendChat(Text.translatable("firmament.poweruser.entity.armor.item", debugFormat(armorItem)))
- }
- }
- MC.sendChat(Text.stringifiedTranslatable("firmament.poweruser.entity.passengers", target.passengerList.size))
- target.passengerList.forEach {
- showEntity(it)
- }
- }
-
-
- @Subscribe
- fun copyInventoryInfo(it: HandledScreenKeyPressedEvent) {
- if (it.screen !is AccessorHandledScreen) return
- val item = it.screen.focusedItemStack ?: return
- if (it.matches(TConfig.copyItemId)) {
- val sbId = item.skyBlockId
- if (sbId == null) {
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skyblockid.fail"))
- return
- }
- ClipboardUtils.setTextContent(sbId.neuItem)
- lastCopiedStack =
- Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.skyblockid", sbId.neuItem))
- } else if (it.matches(TConfig.copyTexturePackId)) {
- val model = CustomItemModelEvent.getModelIdentifier(item)
- if (model == null) {
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.modelid.fail"))
- return
- }
- ClipboardUtils.setTextContent(model.toString())
- lastCopiedStack =
- Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.modelid", model.toString()))
- } else if (it.matches(TConfig.copyNbtData)) {
- // TODO: copy full nbt
- val nbt = item.get(DataComponentTypes.CUSTOM_DATA)?.nbt?.toString() ?: "<empty>"
- ClipboardUtils.setTextContent(nbt)
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.nbt"))
- } else if (it.matches(TConfig.copySkullTexture)) {
- if (item.item != Items.PLAYER_HEAD) {
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-skull"))
- return
- }
- val profile = item.get(DataComponentTypes.PROFILE)
- if (profile == null) {
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-profile"))
- return
- }
- val skullTexture = CustomSkyBlockTextures.getSkullTexture(profile)
- if (skullTexture == null) {
- lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-texture"))
- return
- }
- ClipboardUtils.setTextContent(skullTexture.toString())
- lastCopiedStack =
- Pair(
- item,
- Text.stringifiedTranslatable("firmament.tooltip.copied.skull-id", skullTexture.toString())
- )
- println("Copied skull id: $skullTexture")
- }
- }
-
- @Subscribe
- fun onCopyWorldInfo(it: WorldKeyboardEvent) {
- if (it.matches(TConfig.copySkullTexture)) {
- val p = MC.camera ?: return
- val blockHit = p.raycast(20.0, 0.0f, false) ?: return
- if (blockHit.type != HitResult.Type.BLOCK || blockHit !is BlockHitResult) {
- MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail"))
- return
- }
- val blockAt = p.world.getBlockState(blockHit.blockPos)?.block
- val entity = p.world.getBlockEntity(blockHit.blockPos)
- if (blockAt !is SkullBlock || entity !is SkullBlockEntity || entity.owner == null) {
- MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail"))
- return
- }
- val id = CustomSkyBlockTextures.getSkullTexture(entity.owner!!)
- if (id == null) {
- MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail"))
- } else {
- ClipboardUtils.setTextContent(id.toString())
- MC.sendChat(Text.stringifiedTranslatable("firmament.tooltip.copied.skull", id.toString()))
- }
- }
- }
-
- @Subscribe
- fun addItemId(it: ItemTooltipEvent) {
- if (TConfig.showItemIds) {
- val id = it.stack.skyBlockId ?: return
- it.lines.add(Text.stringifiedTranslatable("firmament.tooltip.skyblockid", id.neuItem))
- }
- val (item, text) = lastCopiedStack ?: return
- if (!ItemStack.areEqual(item, it.stack)) {
- lastCopiedStack = null
- return
- }
- lastCopiedStackViewTime = true
- it.lines.add(text)
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt b/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt
deleted file mode 100644
index 39ca6d3..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/diana/AncestralSpadeSolver.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-
-package moe.nea.firmament.features.diana
-
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.particle.ParticleTypes
-import net.minecraft.sound.SoundEvents
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ParticleSpawnEvent
-import moe.nea.firmament.events.SoundReceiveEvent
-import moe.nea.firmament.events.WorldKeyboardEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.WarpUtil
-import moe.nea.firmament.util.render.RenderInWorldContext
-import moe.nea.firmament.util.skyBlockId
-
-object AncestralSpadeSolver : SubscriptionOwner {
- var lastDing = TimeMark.farPast()
- private set
- private val pitches = mutableListOf<Float>()
- val particlePositions = mutableListOf<Vec3d>()
- var nextGuess: Vec3d? = null
- private set
-
- val ancestralSpadeId = SkyblockId("ANCESTRAL_SPADE")
- private var lastTeleportAttempt = TimeMark.farPast()
-
- fun isEnabled() =
- DianaWaypoints.TConfig.ancestralSpadeSolver
- && SBData.skyblockLocation == SkyBlockIsland.HUB
- && MC.player?.inventory?.containsAny { it.skyBlockId == ancestralSpadeId } == true // TODO: add a reactive property here
-
- @Subscribe
- fun onKeyBind(event: WorldKeyboardEvent) {
- if (!isEnabled()) return
- if (!event.matches(DianaWaypoints.TConfig.ancestralSpadeTeleport)) return
-
- if (lastTeleportAttempt.passedTime() < 3.seconds) return
- WarpUtil.teleportToNearestWarp(SkyBlockIsland.HUB, nextGuess ?: return)
- lastTeleportAttempt = TimeMark.now()
- }
-
- @Subscribe
- fun onParticleSpawn(event: ParticleSpawnEvent) {
- if (!isEnabled()) return
- if (event.particleEffect != ParticleTypes.DRIPPING_LAVA) return
- if (event.offset.x != 0.0F || event.offset.y != 0F || event.offset.z != 0F)
- return
- particlePositions.add(event.position)
- if (particlePositions.size > 20) {
- particlePositions.removeFirst()
- }
- }
-
- @Subscribe
- fun onPlaySound(event: SoundReceiveEvent) {
- if (!isEnabled()) return
- if (!SoundEvents.BLOCK_NOTE_BLOCK_HARP.matchesId(event.sound.value().id)) return
-
- if (lastDing.passedTime() > 1.seconds) {
- particlePositions.clear()
- pitches.clear()
- }
- lastDing = TimeMark.now()
-
- pitches.add(event.pitch)
- if (pitches.size > 20) {
- pitches.removeFirst()
- }
-
- if (particlePositions.size < 3) {
- return
- }
-
- val averagePitchDelta =
- if (pitches.isEmpty()) return
- else pitches
- .zipWithNext { a, b -> b - a }
- .average()
-
- val soundDistanceEstimate = (Math.E / averagePitchDelta) - particlePositions.first().distanceTo(event.position)
-
- if (soundDistanceEstimate > 1000) {
- return
- }
-
- val lastParticleDirection = particlePositions
- .takeLast(3)
- .let { (a, _, b) -> b.subtract(a) }
- .normalize()
-
- nextGuess = event.position.add(lastParticleDirection.multiply(soundDistanceEstimate))
- }
-
- @Subscribe
- fun onWorldRender(event: WorldRenderLastEvent) {
- if (!isEnabled()) return
- RenderInWorldContext.renderInWorld(event) {
- nextGuess?.let {
- color(1f, 1f, 0f, 0.5f)
- tinyBlock(it, 1f)
- color(1f, 1f, 0f, 1f)
- tracer(it, lineWidth = 3f)
- }
- if (particlePositions.size > 2 && lastDing.passedTime() < 10.seconds && nextGuess != null) {
- color(0f, 1f, 0f, 0.7f)
- line(particlePositions)
- }
- }
- }
-
- @Subscribe
- fun onSwapWorld(event: WorldReadyEvent) {
- nextGuess = null
- particlePositions.clear()
- pitches.clear()
- lastDing = TimeMark.farPast()
- }
-
- override val delegateFeature: FirmamentFeature
- get() = DianaWaypoints
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt b/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt
deleted file mode 100644
index 0a34eaa..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/diana/DianaWaypoints.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-package moe.nea.firmament.features.diana
-
-import moe.nea.firmament.events.AttackBlockEvent
-import moe.nea.firmament.events.ParticleSpawnEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.SoundReceiveEvent
-import moe.nea.firmament.events.UseBlockEvent
-import moe.nea.firmament.events.WorldKeyboardEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-
-object DianaWaypoints : FirmamentFeature {
- override val identifier get() = "diana"
- override val config get() = TConfig
-
- object TConfig : ManagedConfig(identifier) {
- val ancestralSpadeSolver by toggle("ancestral-spade") { true }
- val ancestralSpadeTeleport by keyBindingWithDefaultUnbound("ancestral-teleport")
- val nearbyWaypoints by toggle("nearby-waypoints") { true }
- }
-
- override fun onLoad() {
- UseBlockEvent.subscribe {
- NearbyBurrowsSolver.onBlockClick(it.hitResult.blockPos)
- }
- AttackBlockEvent.subscribe {
- NearbyBurrowsSolver.onBlockClick(it.blockPos)
- }
- }
-}
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt b/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt
deleted file mode 100644
index 7158bb9..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/diana/NearbyBurrowsSolver.kt
+++ /dev/null
@@ -1,144 +0,0 @@
-
-package moe.nea.firmament.features.diana
-
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.particle.ParticleTypes
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.MathHelper
-import net.minecraft.util.math.Position
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ParticleSpawnEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.mutableMapWithMaxSize
-import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld
-
-object NearbyBurrowsSolver : SubscriptionOwner {
-
-
- private val recentlyDugBurrows: MutableMap<BlockPos, TimeMark> = mutableMapWithMaxSize(20)
- private val recentEnchantParticles: MutableMap<BlockPos, TimeMark> = mutableMapWithMaxSize(500)
- private var lastBlockClick: BlockPos? = null
-
- enum class BurrowType {
- START, MOB, TREASURE
- }
-
- val burrows = mutableMapOf<BlockPos, BurrowType>()
-
- @Subscribe
- fun onChatEvent(event: ProcessChatEvent) {
- val lastClickedBurrow = lastBlockClick ?: return
- if (event.unformattedString.startsWith("You dug out a Griffin Burrow!") ||
- event.unformattedString.startsWith(" ☠ You were killed by") ||
- event.unformattedString.startsWith("You finished the Griffin burrow chain!")
- ) {
- markAsDug(lastClickedBurrow)
- burrows.remove(lastClickedBurrow)
- }
- }
-
-
- fun wasRecentlyDug(blockPos: BlockPos): Boolean {
- val lastDigTime = recentlyDugBurrows[blockPos] ?: TimeMark.farPast()
- return lastDigTime.passedTime() < 10.seconds
- }
-
- fun markAsDug(blockPos: BlockPos) {
- recentlyDugBurrows[blockPos] = TimeMark.now()
- }
-
- fun wasRecentlyEnchanted(blockPos: BlockPos): Boolean {
- val lastEnchantTime = recentEnchantParticles[blockPos] ?: TimeMark.farPast()
- return lastEnchantTime.passedTime() < 4.seconds
- }
-
- fun markAsEnchanted(blockPos: BlockPos) {
- recentEnchantParticles[blockPos] = TimeMark.now()
- }
-
- @Subscribe
- fun onParticles(event: ParticleSpawnEvent) {
- if (!DianaWaypoints.TConfig.nearbyWaypoints) return
-
- val position: BlockPos = event.position.toBlockPos().down()
-
- if (wasRecentlyDug(position)) return
-
- val isEven50Spread = (event.offset.x == 0.5f && event.offset.z == 0.5f)
-
- if (event.particleEffect.type == ParticleTypes.ENCHANT) {
- if (event.count == 5 && event.speed == 0.05F && event.offset.y == 0.4F && isEven50Spread) {
- markAsEnchanted(position)
- }
- return
- }
-
- if (!wasRecentlyEnchanted(position)) return
-
- if (event.particleEffect.type == ParticleTypes.ENCHANTED_HIT
- && event.count == 4
- && event.speed == 0.01F
- && event.offset.y == 0.1f
- && isEven50Spread
- ) {
- burrows[position] = BurrowType.START
- }
- if (event.particleEffect.type == ParticleTypes.CRIT
- && event.count == 3
- && event.speed == 0.01F
- && event.offset.y == 0.1F
- && isEven50Spread
- ) {
- burrows[position] = BurrowType.MOB
- }
- if (event.particleEffect.type == ParticleTypes.DRIPPING_LAVA
- && event.count == 2
- && event.speed == 0.01F
- && event.offset.y == 0.1F
- && event.offset.x == 0.35F && event.offset.z == 0.35f
- ) {
- burrows[position] = BurrowType.TREASURE
- }
- }
-
- @Subscribe
- fun onRender(event: WorldRenderLastEvent) {
- if (!DianaWaypoints.TConfig.nearbyWaypoints) return
- renderInWorld(event) {
- for ((location, burrow) in burrows) {
- when (burrow) {
- BurrowType.START -> color(.2f, .8f, .2f, 0.4f)
- BurrowType.MOB -> color(0.3f, 0.4f, 0.9f, 0.4f)
- BurrowType.TREASURE -> color(1f, 0.7f, 0.2f, 0.4f)
- }
- block(location)
- }
- }
- }
-
- @Subscribe
- fun onSwapWorld(worldReadyEvent: WorldReadyEvent) {
- burrows.clear()
- recentEnchantParticles.clear()
- recentlyDugBurrows.clear()
- lastBlockClick = null
- }
-
- fun onBlockClick(blockPos: BlockPos) {
- if (!DianaWaypoints.TConfig.nearbyWaypoints) return
- burrows.remove(blockPos)
- lastBlockClick = blockPos
- }
-
- override val delegateFeature: FirmamentFeature
- get() = DianaWaypoints
-}
-
-fun Position.toBlockPos(): BlockPos {
- return BlockPos(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z))
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/events/anniversity/AnniversaryFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/events/anniversity/AnniversaryFeatures.kt
deleted file mode 100644
index 8926a95..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/events/anniversity/AnniversaryFeatures.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-
-package moe.nea.firmament.features.events.anniversity
-
-import io.github.notenoughupdates.moulconfig.observer.ObservableList
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import moe.nea.jarvis.api.Point
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.entity.passive.PigEntity
-import net.minecraft.util.math.BlockPos
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.EntityInteractionEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.gui.hud.MoulConfigHud
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.repo.ItemNameLookup
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SHORT_NUMBER_FORMAT
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.parseShortNumber
-import moe.nea.firmament.util.useMatch
-
-object AnniversaryFeatures : FirmamentFeature {
- override val identifier: String
- get() = "anniversary"
-
- object TConfig : ManagedConfig(identifier) {
- val enableShinyPigTracker by toggle("shiny-pigs") {true}
- val trackPigCooldown by position("pig-hud", 200, 300) { Point(0.1, 0.2) }
- }
-
- override val config: ManagedConfig?
- get() = TConfig
-
- data class ClickedPig(
- val clickedAt: TimeMark,
- val startLocation: BlockPos,
- val pigEntity: PigEntity
- ) {
- @Bind("timeLeft")
- fun getTimeLeft(): Double = 1 - clickedAt.passedTime() / pigDuration
- }
-
- val clickedPigs = ObservableList<ClickedPig>(mutableListOf())
- var lastClickedPig: PigEntity? = null
-
- val pigDuration = 90.seconds
-
- @Subscribe
- fun onTick(event: TickEvent) {
- clickedPigs.removeIf { it.clickedAt.passedTime() > pigDuration }
- }
-
- val pattern = "SHINY! You extracted (?<reward>.*) from the piglet's orb!".toPattern()
-
- @Subscribe
- fun onChat(event: ProcessChatEvent) {
- if(!TConfig.enableShinyPigTracker)return
- if (event.unformattedString == "Oink! Bring the pig back to the Shiny Orb!") {
- val pig = lastClickedPig ?: return
- // TODO: store proper location based on the orb location, maybe
- val startLocation = pig.blockPos ?: return
- clickedPigs.add(ClickedPig(TimeMark.now(), startLocation, pig))
- lastClickedPig = null
- }
- if (event.unformattedString == "SHINY! The orb is charged! Click on it for loot!") {
- val player = MC.player ?: return
- val lowest =
- clickedPigs.minByOrNull { it.startLocation.getSquaredDistance(player.pos) } ?: return
- clickedPigs.remove(lowest)
- }
- pattern.useMatch(event.unformattedString) {
- val reward = group("reward")
- val parsedReward = parseReward(reward)
- addReward(parsedReward)
- PigCooldown.rewards.atOnce {
- PigCooldown.rewards.clear()
- rewards.mapTo(PigCooldown.rewards) { PigCooldown.DisplayReward(it) }
- }
- }
- }
-
- fun addReward(reward: Reward) {
- val it = rewards.listIterator()
- while (it.hasNext()) {
- val merged = reward.mergeWith(it.next()) ?: continue
- it.set(merged)
- return
- }
- rewards.add(reward)
- }
-
- val rewards = mutableListOf<Reward>()
-
- fun <T> ObservableList<T>.atOnce(block: () -> Unit) {
- val oldObserver = observer
- observer = null
- block()
- observer = oldObserver
- update()
- }
-
- sealed interface Reward {
- fun mergeWith(other: Reward): Reward?
- data class EXP(val amount: Double, val skill: String) : Reward {
- override fun mergeWith(other: Reward): Reward? {
- if (other is EXP && other.skill == skill)
- return EXP(amount + other.amount, skill)
- return null
- }
- }
-
- data class Coins(val amount: Double) : Reward {
- override fun mergeWith(other: Reward): Reward? {
- if (other is Coins)
- return Coins(other.amount + amount)
- return null
- }
- }
-
- data class Items(val amount: Int, val item: SkyblockId) : Reward {
- override fun mergeWith(other: Reward): Reward? {
- if (other is Items && other.item == item)
- return Items(amount + other.amount, item)
- return null
- }
- }
-
- data class Unknown(val text: String) : Reward {
- override fun mergeWith(other: Reward): Reward? {
- return null
- }
- }
- }
-
- val expReward = "\\+(?<exp>$SHORT_NUMBER_FORMAT) (?<kind>[^ ]+) XP".toPattern()
- val coinReward = "\\+(?<amount>$SHORT_NUMBER_FORMAT) coins".toPattern()
- val itemReward = "(?:(?<amount>[0-9]+)x )?(?<name>.*)".toPattern()
- fun parseReward(string: String): Reward {
- expReward.useMatch<Unit>(string) {
- val exp = parseShortNumber(group("exp"))
- val kind = group("kind")
- return Reward.EXP(exp, kind)
- }
- coinReward.useMatch<Unit>(string) {
- val coins = parseShortNumber(group("amount"))
- return Reward.Coins(coins)
- }
- itemReward.useMatch(string) {
- val amount = group("amount")?.toIntOrNull() ?: 1
- val name = group("name")
- val item = ItemNameLookup.guessItemByName(name, false) ?: return@useMatch
- return Reward.Items(amount, item)
- }
- return Reward.Unknown(string)
- }
-
- @Subscribe
- fun onWorldClear(event: WorldReadyEvent) {
- lastClickedPig = null
- clickedPigs.clear()
- }
-
- @Subscribe
- fun onEntityClick(event: EntityInteractionEvent) {
- if (event.entity is PigEntity) {
- lastClickedPig = event.entity
- }
- }
-
- @Subscribe
- fun init(event: WorldReadyEvent) {
- PigCooldown.forceInit()
- }
-
- object PigCooldown : MoulConfigHud("anniversary_pig", TConfig.trackPigCooldown) {
- override fun shouldRender(): Boolean {
- return clickedPigs.isNotEmpty() && TConfig.enableShinyPigTracker
- }
-
- @Bind("pigs")
- fun getPigs() = clickedPigs
-
- class DisplayReward(val backedBy: Reward) {
- @Bind
- fun count(): String {
- return when (backedBy) {
- is Reward.Coins -> backedBy.amount
- is Reward.EXP -> backedBy.amount
- is Reward.Items -> backedBy.amount
- is Reward.Unknown -> 0
- }.toString()
- }
-
- val itemStack = if (backedBy is Reward.Items) {
- SBItemEntryDefinition.getEntry(backedBy.item, backedBy.amount)
- } else {
- SBItemEntryDefinition.getEntry(SkyblockId.NULL)
- }
-
- @Bind
- fun name(): String {
- return when (backedBy) {
- is Reward.Coins -> "Coins"
- is Reward.EXP -> backedBy.skill
- is Reward.Items -> itemStack.value.asItemStack().name.string
- is Reward.Unknown -> backedBy.text
- }
- }
-
- @Bind
- fun isKnown() = backedBy !is Reward.Unknown
- }
-
- @get:Bind("rewards")
- val rewards = ObservableList<DisplayReward>(mutableListOf())
-
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/events/carnival/CarnivalFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/events/carnival/CarnivalFeatures.kt
deleted file mode 100644
index 1e6d97a..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/events/carnival/CarnivalFeatures.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-package moe.nea.firmament.features.events.carnival
-
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-
-object CarnivalFeatures : FirmamentFeature {
- object TConfig : ManagedConfig(identifier) {
- val enableBombSolver by toggle("bombs-solver") { true }
- val displayTutorials by toggle("tutorials") { true }
- }
-
- override val config: ManagedConfig?
- get() = TConfig
- override val identifier: String
- get() = "carnival"
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/events/carnival/MinesweeperHelper.kt b/src/main/kotlin/moe/nea/firmament/features/events/carnival/MinesweeperHelper.kt
deleted file mode 100644
index 06caf86..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/events/carnival/MinesweeperHelper.kt
+++ /dev/null
@@ -1,276 +0,0 @@
-
-package moe.nea.firmament.features.events.carnival
-
-import io.github.notenoughupdates.moulconfig.observer.ObservableList
-import io.github.notenoughupdates.moulconfig.platform.ModernItemStack
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import java.util.UUID
-import net.minecraft.block.Blocks
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import net.minecraft.text.ClickEvent
-import net.minecraft.text.Text
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.WorldAccess
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.commands.thenExecute
-import moe.nea.firmament.events.AttackBlockEvent
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.EntityUpdateEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.features.debug.DebugLogger
-import moe.nea.firmament.util.LegacyFormattingCode
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.MoulConfigUtils
-import moe.nea.firmament.util.ScreenUtil
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.item.createSkullItem
-import moe.nea.firmament.util.render.RenderInWorldContext
-import moe.nea.firmament.util.setSkyBlockFirmamentUiId
-import moe.nea.firmament.util.skyBlockId
-import moe.nea.firmament.util.useMatch
-
-object MinesweeperHelper {
- val sandBoxLow = BlockPos(-112, 72, -11)
- val sandBoxHigh = BlockPos(-106, 72, -5)
- val boardSize = Pair(sandBoxHigh.x - sandBoxLow.x, sandBoxHigh.z - sandBoxLow.z)
-
- val gameStartMessage = "[NPC] Carnival Pirateman: Good luck, matey!"
- val gameEndMessage = "Fruit Digging"
- val bombPattern = "MINES! There (are|is) (?<bombCount>[0-8]) bombs? hidden nearby\\.".toPattern()
- val startGameQuestion = "[NPC] Carnival Pirateman: Would ye like to do some Fruit Digging?"
-
-
- enum class Piece(
- @get:Bind("fruitName")
- val fruitName: String,
- val points: Int,
- val specialAbility: String,
- val totalPerBoard: Int,
- val textureHash: String,
- val fruitColor: LegacyFormattingCode,
- ) {
- COCONUT("Coconut",
- 200,
- "Prevents a bomb from exploding next turn",
- 3,
- "10ceb1455b471d016a9f06d25f6e468df9fcf223e2c1e4795b16e84fcca264ee",
- LegacyFormattingCode.DARK_PURPLE),
- APPLE("Apple",
- 100,
- "Gains 100 points for each apple dug up",
- 8,
- "17ea278d6225c447c5943d652798d0bbbd1418434ce8c54c54fdac79994ddd6c",
- LegacyFormattingCode.GREEN),
- WATERMELON("Watermelon",
- 100,
- "Blows up an adjacent fruit for half the points",
- 4,
- "efe4ef83baf105e8dee6cf03dfe7407f1911b3b9952c891ae34139560f2931d6",
- LegacyFormattingCode.DARK_BLUE),
- DURIAN("Durian",
- 800,
- "Halves the points earned in the next turn",
- 2,
- "ac268d36c2c6047ffeec00124096376b56dbb4d756a55329363a1b27fcd659cd",
- LegacyFormattingCode.DARK_PURPLE),
- MANGO("Mango",
- 300,
- "Just an ordinary fruit",
- 10,
- "f363a62126a35537f8189343a22660de75e810c6ac004a7d3da65f1c040a839",
- LegacyFormattingCode.GREEN),
- DRAGON_FRUIT("Dragonfruit",
- 1200,
- "Halves the points earned in the next turn",
- 1,
- "3cc761bcb0579763d9b8ab6b7b96fa77eb6d9605a804d838fec39e7b25f95591",
- LegacyFormattingCode.LIGHT_PURPLE),
- POMEGRANATE("Pomegranate",
- 200,
- "Grants an extra 50% more points in the next turn",
- 4,
- "40824d18079042d5769f264f44394b95b9b99ce689688cc10c9eec3f882ccc08",
- LegacyFormattingCode.DARK_BLUE),
- CHERRY("Cherry",
- 200,
- "The second cherry grants 300 bonus points",
- 2,
- "c92b099a62cd2fbf8ada09dec145c75d7fda4dc57b968bea3a8fa11e37aa48b2",
- LegacyFormattingCode.DARK_PURPLE),
- BOMB("Bomb",
- -1,
- "Destroys nearby fruit",
- 15,
- "a76a2811d1e176a07b6d0a657b910f134896ce30850f6e80c7c83732d85381ea",
- LegacyFormattingCode.DARK_RED),
- RUM("Rum",
- -1,
- "Stops your dowsing ability for one turn",
- 5,
- "407b275d28b927b1bf7f6dd9f45fbdad2af8571c54c8f027d1bff6956fbf3c16",
- LegacyFormattingCode.YELLOW),
- ;
-
- val textureUrl = "http://textures.minecraft.net/texture/$textureHash"
- val itemStack = createSkullItem(UUID.randomUUID(), textureUrl)
- .setSkyBlockFirmamentUiId("MINESWEEPER_$name")
-
- @Bind
- fun getIcon() = ModernItemStack.of(itemStack)
-
- @Bind
- fun pieceLabel() = fruitColor.formattingCode + fruitName
-
- @Bind
- fun boardLabel() = "§a$totalPerBoard§7/§rboard"
-
- @Bind("description")
- fun getDescription() = buildString {
- append(specialAbility)
- if (points >= 0) {
- append(" Default points: $points.")
- }
- }
- }
-
- object TutorialScreen {
- @get:Bind("pieces")
- val pieces = ObservableList(Piece.entries.toList().reversed())
-
- @get:Bind("modes")
- val modes = ObservableList(DowsingMode.entries.toList())
- }
-
- enum class DowsingMode(
- val itemType: Item,
- @get:Bind("feature")
- val feature: String,
- @get:Bind("description")
- val description: String,
- ) {
- MINES(Items.IRON_SHOVEL, "Bomb detection", "Tells you how many bombs are near the block"),
- ANCHOR(Items.DIAMOND_SHOVEL, "Lowest fruit", "Shows you which block nearby contains the lowest scoring fruit"),
- TREASURE(Items.GOLDEN_SHOVEL, "Highest fruit", "Tells you which kind of fruit is the highest scoring nearby"),
- ;
-
- @Bind("itemType")
- fun getItemStack() = ModernItemStack.of(ItemStack(itemType))
-
- companion object {
- val id = SkyblockId("CARNIVAL_SHOVEL")
- fun fromItem(itemStack: ItemStack): DowsingMode? {
- if (itemStack.skyBlockId != id) return null
- return DowsingMode.entries.find { it.itemType == itemStack.item }
- }
- }
- }
-
- data class BoardPosition(
- val x: Int,
- val y: Int
- ) {
- fun toBlockPos() = BlockPos(sandBoxLow.x + x, sandBoxLow.y, sandBoxLow.z + y)
-
- fun getBlock(world: WorldAccess) = world.getBlockState(toBlockPos()).block
- fun isUnopened(world: WorldAccess) = getBlock(world) == Blocks.SAND
- fun isOpened(world: WorldAccess) = getBlock(world) == Blocks.SANDSTONE
- fun isScorched(world: WorldAccess) = getBlock(world) == Blocks.SANDSTONE_STAIRS
-
- companion object {
- fun fromBlockPos(blockPos: BlockPos): BoardPosition? {
- if (blockPos.y != sandBoxLow.y) return null
- val x = blockPos.x - sandBoxLow.x
- val y = blockPos.z - sandBoxLow.z
- if (x < 0 || x >= boardSize.first) return null
- if (y < 0 || y >= boardSize.second) return null
- return BoardPosition(x, y)
- }
- }
- }
-
- data class GameState(
- val nearbyBombs: MutableMap<BoardPosition, Int> = mutableMapOf(),
- val knownBombPositions: MutableSet<BoardPosition> = mutableSetOf(),
- var lastClickedPosition: BoardPosition? = null,
- var lastDowsingMode: DowsingMode? = null,
- )
-
- var gameState: GameState? = null
- val log = DebugLogger("minesweeper")
-
- @Subscribe
- fun onCommand(event: CommandEvent.SubCommand) {
- event.subcommand("minesweepertutorial") {
- thenExecute {
- ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen("carnival/minesweeper_tutorial",
- TutorialScreen,
- null))
- }
- }
- }
-
- @Subscribe
- fun onWorldChange(event: WorldReadyEvent) {
- gameState = null
- }
-
- @Subscribe
- fun onChat(event: ProcessChatEvent) {
- if (CarnivalFeatures.TConfig.displayTutorials && event.unformattedString == startGameQuestion) {
- MC.sendChat(Text.translatable("firmament.carnival.tutorial.minesweeper").styled {
- it.withClickEvent(ClickEvent(ClickEvent.Action.RUN_COMMAND, "/firm minesweepertutorial"))
- })
- }
- if (!CarnivalFeatures.TConfig.enableBombSolver) {
- gameState = null // TODO: replace this which a watchable property
- return
- }
- if (event.unformattedString == gameStartMessage) {
- gameState = GameState()
- log.log { "Game started" }
- }
- if (event.unformattedString.trim() == gameEndMessage) {
- gameState = null // TODO: add a loot tracker maybe? probably not, i dont think people care
- log.log { "Finished game" }
- }
- val gs = gameState ?: return
- bombPattern.useMatch(event.unformattedString) {
- val bombCount = group("bombCount").toInt()
- log.log { "Marking ${gs.lastClickedPosition} as having $bombCount nearby" }
- val pos = gs.lastClickedPosition ?: return
- gs.nearbyBombs[pos] = bombCount
- }
- }
-
- @Subscribe
- fun onMobChange(event: EntityUpdateEvent) {
- val gs = gameState ?: return
- if (event !is EntityUpdateEvent.TrackedDataUpdate) return
- // TODO: listen to state
- }
-
- @Subscribe
- fun onBlockClick(event: AttackBlockEvent) {
- val gs = gameState ?: return
- val boardPosition = BoardPosition.fromBlockPos(event.blockPos)
- log.log { "Breaking block at ${event.blockPos} ($boardPosition)" }
- gs.lastClickedPosition = boardPosition
- gs.lastDowsingMode = DowsingMode.fromItem(event.player.inventory.mainHandStack)
- }
-
- @Subscribe
- fun onRender(event: WorldRenderLastEvent) {
- val gs = gameState ?: return
- RenderInWorldContext.renderInWorld(event) {
- for ((pos, bombCount) in gs.nearbyBombs) {
- this.text(pos.toBlockPos().up().toCenterPos(), Text.literal("§a$bombCount \uD83D\uDCA3"))
- }
- }
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt b/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt
deleted file mode 100644
index 7c43cf6..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/fixes/CompatibliltyFeatures.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-package moe.nea.firmament.features.fixes
-
-import net.fabricmc.loader.api.FabricLoader
-import net.superkat.explosiveenhancement.api.ExplosiveApi
-import net.minecraft.particle.ParticleTypes
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ParticleSpawnEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-
-object CompatibliltyFeatures : FirmamentFeature {
- override val identifier: String
- get() = "compatibility"
-
- object TConfig : ManagedConfig(identifier) {
- val enhancedExplosions by toggle("explosion-enabled") { false }
- val explosionSize by integer("explosion-power", 10, 50) { 1 }
- }
-
- override val config: ManagedConfig?
- get() = TConfig
-
- interface ExplosiveApiWrapper {
- fun spawnParticle(vec3d: Vec3d, power: Float)
- }
-
- class ExplosiveApiWrapperImpl : ExplosiveApiWrapper {
- override fun spawnParticle(vec3d: Vec3d, power: Float) {
- ExplosiveApi.spawnParticles(MC.world, vec3d.x, vec3d.y, vec3d.z, TConfig.explosionSize / 10F)
- }
- }
-
- val explosiveApiWrapper = if (FabricLoader.getInstance().isModLoaded("explosiveenhancement")) {
- ExplosiveApiWrapperImpl()
- } else null
-
- @Subscribe
- fun onExplosion(it: ParticleSpawnEvent) {
- if (TConfig.enhancedExplosions &&
- it.particleEffect.type == ParticleTypes.EXPLOSION_EMITTER &&
- explosiveApiWrapper != null
- ) {
- it.cancel()
- explosiveApiWrapper.spawnParticle(it.position, 2F)
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt b/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt
deleted file mode 100644
index d7b7a1c..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/fixes/Fixes.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-package moe.nea.firmament.features.fixes
-
-import moe.nea.jarvis.api.Point
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.option.KeyBinding
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.text.Text
-import net.minecraft.util.Arm
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HudRenderEvent
-import moe.nea.firmament.events.WorldKeyboardEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.errorBoundary
-
-object Fixes : FirmamentFeature {
- override val identifier: String
- get() = "fixes"
-
- object TConfig : ManagedConfig(identifier) {
- val fixUnsignedPlayerSkins by toggle("player-skins") { true }
- var autoSprint by toggle("auto-sprint") { false }
- val autoSprintKeyBinding by keyBindingWithDefaultUnbound("auto-sprint-keybinding")
- val autoSprintHud by position("auto-sprint-hud", 80, 10) { Point(0.0, 1.0) }
- val peekChat by keyBindingWithDefaultUnbound("peek-chat")
- }
-
- override val config: ManagedConfig
- get() = TConfig
-
- fun handleIsPressed(
- keyBinding: KeyBinding,
- cir: CallbackInfoReturnable<Boolean>
- ) {
- if (keyBinding === MinecraftClient.getInstance().options.sprintKey && TConfig.autoSprint && MC.player?.isSprinting != true)
- cir.returnValue = true
- }
-
- @Subscribe
- fun onRenderHud(it: HudRenderEvent) {
- if (!TConfig.autoSprintKeyBinding.isBound) return
- it.context.matrices.push()
- TConfig.autoSprintHud.applyTransformations(it.context.matrices)
- it.context.drawText(
- MC.font, Text.translatable(
- if (TConfig.autoSprint)
- "firmament.fixes.auto-sprint.on"
- else if (MC.player?.isSprinting == true)
- "firmament.fixes.auto-sprint.sprinting"
- else
- "firmament.fixes.auto-sprint.not-sprinting"
- ), 0, 0, -1, false
- )
- it.context.matrices.pop()
- }
-
- @Subscribe
- fun onWorldKeyboard(it: WorldKeyboardEvent) {
- if (it.matches(TConfig.autoSprintKeyBinding)) {
- TConfig.autoSprint = !TConfig.autoSprint
- }
- }
-
- fun shouldPeekChat(): Boolean {
- return TConfig.peekChat.isPressed(atLeast = true)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt
deleted file mode 100644
index 031ef78..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/CraftingOverlay.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory
-
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.item.ItemStack
-import net.minecraft.util.Formatting
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.SlotRenderEvents
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.util.MC
-
-object CraftingOverlay : FirmamentFeature {
-
- private var screen: GenericContainerScreen? = null
- private var recipe: SBCraftingRecipe? = null
- private val craftingOverlayIndices = listOf(
- 10, 11, 12,
- 19, 20, 21,
- 28, 29, 30,
- )
-
-
- fun setOverlay(screen: GenericContainerScreen, recipe: SBCraftingRecipe) {
- this.screen = screen
- this.recipe = recipe
- }
-
- override val identifier: String
- get() = "crafting-overlay"
-
- @Subscribe
- fun onSlotRender(event: SlotRenderEvents.After) {
- val slot = event.slot
- val recipe = this.recipe ?: return
- if (slot.inventory != screen?.screenHandler?.inventory) return
- val recipeIndex = craftingOverlayIndices.indexOf(slot.index)
- if (recipeIndex < 0) return
- val expectedItem = recipe.neuRecipe.inputs[recipeIndex]
- val actualStack = slot.stack ?: ItemStack.EMPTY!!
- val actualEntry = SBItemEntryDefinition.getEntry(actualStack).value
- if ((actualEntry.skyblockId.neuItem != expectedItem.itemId || actualEntry.getStackSize() < expectedItem.amount) && expectedItem.amount.toInt() != 0) {
- event.context.fill(
- event.slot.x,
- event.slot.y,
- event.slot.x + 16,
- event.slot.y + 16,
- 0x80FF0000.toInt()
- )
- }
- if (!slot.hasStack()) {
- val itemStack = SBItemEntryDefinition.getEntry(expectedItem).asItemEntry().value
- event.context.drawItem(itemStack, event.slot.x, event.slot.y)
- event.context.drawItemInSlot(
- MC.font,
- itemStack,
- event.slot.x,
- event.slot.y,
- "${Formatting.RED}${expectedItem.amount.toInt()}"
- )
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt
deleted file mode 100644
index 566a813..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/ItemRarityCosmetics.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory
-
-import java.awt.Color
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.item.ItemStack
-import net.minecraft.util.Formatting
-import net.minecraft.util.Identifier
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HotbarItemRenderEvent
-import moe.nea.firmament.events.SlotRenderEvents
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.item.loreAccordingToNbt
-import moe.nea.firmament.util.lastNotNullOfOrNull
-import moe.nea.firmament.util.memoize
-import moe.nea.firmament.util.memoizeIdentity
-import moe.nea.firmament.util.unformattedString
-
-object ItemRarityCosmetics : FirmamentFeature {
- override val identifier: String
- get() = "item-rarity-cosmetics"
-
- object TConfig : ManagedConfig(identifier) {
- val showItemRarityBackground by toggle("background") { false }
- val showItemRarityInHotbar by toggle("background-hotbar") { false }
- }
-
- override val config: ManagedConfig
- get() = TConfig
-
- private val rarityToColor = mapOf(
- "UNCOMMON" to Formatting.GREEN,
- "COMMON" to Formatting.WHITE,
- "RARE" to Formatting.DARK_BLUE,
- "EPIC" to Formatting.DARK_PURPLE,
- "LEGENDARY" to Formatting.GOLD,
- "LEGENJERRY" to Formatting.GOLD,
- "MYTHIC" to Formatting.LIGHT_PURPLE,
- "DIVINE" to Formatting.BLUE,
- "SPECIAL" to Formatting.DARK_RED,
- "SUPREME" to Formatting.DARK_RED,
- ).mapValues {
- val c = Color(it.value.colorValue!!)
- Triple(c.red / 255F, c.green / 255F, c.blue / 255F)
- }
-
- private fun getSkyblockRarity0(itemStack: ItemStack): Triple<Float, Float, Float>? {
- return itemStack.loreAccordingToNbt.lastNotNullOfOrNull {
- val entry = it.unformattedString
- rarityToColor.entries.find { (k, v) -> k in entry }?.value
- }
- }
-
- val getSkyblockRarity = ::getSkyblockRarity0.memoizeIdentity(100)
-
-
- fun drawItemStackRarity(drawContext: DrawContext, x: Int, y: Int, item: ItemStack) {
- val (r, g, b) = getSkyblockRarity(item) ?: return
- drawContext.drawSprite(
- x, y,
- 0,
- 16, 16,
- MC.guiAtlasManager.getSprite(Identifier.of("firmament:item_rarity_background")),
- r, g, b, 1F
- )
- }
-
-
- @Subscribe
- fun onRenderSlot(it: SlotRenderEvents.Before) {
- if (!TConfig.showItemRarityBackground) return
- val stack = it.slot.stack ?: return
- drawItemStackRarity(it.context, it.slot.x, it.slot.y, stack)
- }
-
- @Subscribe
- fun onRenderHotbarItem(it: HotbarItemRenderEvent) {
- if (!TConfig.showItemRarityInHotbar) return
- val stack = it.item
- drawItemStackRarity(it.context, it.x, it.y, stack)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt
deleted file mode 100644
index c61f8e8..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/PriceData.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory
-
-import net.minecraft.text.Text
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ItemTooltipEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.repo.HypixelStaticData
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.skyBlockId
-
-object PriceData : FirmamentFeature {
- override val identifier: String
- get() = "price-data"
-
- object TConfig : ManagedConfig(identifier) {
- val tooltipEnabled by toggle("enable-always") { true }
- val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind")
- }
-
- override val config get() = TConfig
-
- @Subscribe
- fun onItemTooltip(it: ItemTooltipEvent) {
- if (!TConfig.tooltipEnabled && !TConfig.enableKeybinding.isPressed()) {
- return
- }
- val sbId = it.stack.skyBlockId
- val bazaarData = HypixelStaticData.bazaarData[sbId]
- val lowestBin = HypixelStaticData.lowestBin[sbId]
- if (bazaarData != null) {
- it.lines.add(Text.literal(""))
- it.lines.add(
- Text.stringifiedTranslatable("firmament.tooltip.bazaar.sell-order",
- FirmFormatters.formatCommas(bazaarData.quickStatus.sellPrice, 1))
- )
- it.lines.add(
- Text.stringifiedTranslatable("firmament.tooltip.bazaar.buy-order",
- FirmFormatters.formatCommas(bazaarData.quickStatus.buyPrice, 1))
- )
- } else if (lowestBin != null) {
- it.lines.add(Text.literal(""))
- it.lines.add(
- Text.stringifiedTranslatable("firmament.tooltip.ah.lowestbin",
- FirmFormatters.formatCommas(lowestBin, 1))
- )
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt
deleted file mode 100644
index 1c55753..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/SaveCursorPosition.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory
-
-import kotlin.math.absoluteValue
-import kotlin.time.Duration.Companion.milliseconds
-import net.minecraft.client.util.InputUtil
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.assertNotNullOr
-
-object SaveCursorPosition : FirmamentFeature {
- override val identifier: String
- get() = "save-cursor-position"
-
- object TConfig : ManagedConfig(identifier) {
- val enable by toggle("enable") { true }
- val tolerance by duration("tolerance", 10.milliseconds, 5000.milliseconds) { 500.milliseconds }
- }
-
- override val config: TConfig
- get() = TConfig
-
- var savedPositionedP1: Pair<Double, Double>? = null
- var savedPosition: SavedPosition? = null
-
- data class SavedPosition(
- val middle: Pair<Double, Double>,
- val cursor: Pair<Double, Double>,
- val savedAt: TimeMark = TimeMark.now()
- )
-
- @JvmStatic
- fun saveCursorOriginal(positionedX: Double, positionedY: Double) {
- savedPositionedP1 = Pair(positionedX, positionedY)
- }
-
- @JvmStatic
- fun loadCursor(middleX: Double, middleY: Double): Pair<Double, Double>? {
- if (!TConfig.enable) return null
- val lastPosition = savedPosition?.takeIf { it.savedAt.passedTime() < TConfig.tolerance }
- savedPosition = null
- if (lastPosition != null &&
- (lastPosition.middle.first - middleX).absoluteValue < 1 &&
- (lastPosition.middle.second - middleY).absoluteValue < 1
- ) {
- InputUtil.setCursorParameters(
- MC.window.handle,
- InputUtil.GLFW_CURSOR_NORMAL,
- lastPosition.cursor.first,
- lastPosition.cursor.second
- )
- return lastPosition.cursor
- }
- return null
- }
-
- @JvmStatic
- fun saveCursorMiddle(middleX: Double, middleY: Double) {
- if (!TConfig.enable) return
- val cursorPos = assertNotNullOr(savedPositionedP1) { return }
- savedPosition = SavedPosition(Pair(middleX, middleY), cursorPos)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt
deleted file mode 100644
index a50d8fb..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/SlotLocking.kt
+++ /dev/null
@@ -1,203 +0,0 @@
-
-
-@file:UseSerializers(DashlessUUIDSerializer::class)
-
-package moe.nea.firmament.features.inventory
-
-import com.mojang.blaze3d.systems.RenderSystem
-import java.util.UUID
-import org.lwjgl.glfw.GLFW
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import kotlinx.serialization.serializer
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.entity.player.PlayerInventory
-import net.minecraft.screen.GenericContainerScreenHandler
-import net.minecraft.screen.slot.SlotActionType
-import net.minecraft.util.Identifier
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HandledScreenKeyPressedEvent
-import moe.nea.firmament.events.IsSlotProtectedEvent
-import moe.nea.firmament.events.SlotRenderEvents
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.keybindings.SavedKeyBinding
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import moe.nea.firmament.util.CommonSoundEffects
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-import moe.nea.firmament.util.item.displayNameAccordingToNbt
-import moe.nea.firmament.util.item.loreAccordingToNbt
-import moe.nea.firmament.util.json.DashlessUUIDSerializer
-import moe.nea.firmament.util.skyblockUUID
-import moe.nea.firmament.util.unformattedString
-
-object SlotLocking : FirmamentFeature {
- override val identifier: String
- get() = "slot-locking"
-
- @Serializable
- data class Data(
- val lockedSlots: MutableSet<Int> = mutableSetOf(),
- val lockedSlotsRift: MutableSet<Int> = mutableSetOf(),
-
- val lockedUUIDs: MutableSet<UUID> = mutableSetOf(),
- )
-
- object TConfig : ManagedConfig(identifier) {
- val lockSlot by keyBinding("lock") { GLFW.GLFW_KEY_L }
- val lockUUID by keyBindingWithOutDefaultModifiers("lock-uuid") {
- SavedKeyBinding(GLFW.GLFW_KEY_L, shift = true)
- }
- }
-
- override val config: TConfig
- get() = TConfig
-
- object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "locked-slots", ::Data)
-
- val lockedUUIDs get() = DConfig.data?.lockedUUIDs
-
- val lockedSlots
- get() = when (SBData.skyblockLocation) {
- SkyBlockIsland.RIFT -> DConfig.data?.lockedSlotsRift
- null -> null
- else -> DConfig.data?.lockedSlots
- }
-
- fun isSalvageScreen(screen: HandledScreen<*>?): Boolean {
- if (screen == null) return false
- return screen.title.unformattedString.contains("Salvage Item")
- }
-
- fun isTradeScreen(screen: HandledScreen<*>?): Boolean {
- if (screen == null) return false
- val handler = screen.screenHandler as? GenericContainerScreenHandler ?: return false
- if (handler.inventory.size() < 9) return false
- val middlePane = handler.inventory.getStack(handler.inventory.size() - 5)
- if (middlePane == null) return false
- return middlePane.displayNameAccordingToNbt?.unformattedString == "⇦ Your stuff"
- }
-
- fun isNpcShop(screen: HandledScreen<*>?): Boolean {
- if (screen == null) return false
- val handler = screen.screenHandler as? GenericContainerScreenHandler ?: return false
- if (handler.inventory.size() < 9) return false
- val sellItem = handler.inventory.getStack(handler.inventory.size() - 5)
- if (sellItem == null) return false
- if (sellItem.displayNameAccordingToNbt?.unformattedString == "Sell Item") return true
- val lore = sellItem.loreAccordingToNbt
- return (lore.lastOrNull() ?: return false).unformattedString == "Click to buyback!"
- }
-
- @Subscribe
- fun onSalvageProtect(event: IsSlotProtectedEvent) {
- if (event.slot == null) return
- if (!event.slot.hasStack()) return
- if (event.slot.stack.displayNameAccordingToNbt?.unformattedString != "Salvage Items") return
- val inv = event.slot.inventory
- var anyBlocked = false
- for (i in 0 until event.slot.index) {
- val stack = inv.getStack(i)
- if (IsSlotProtectedEvent.shouldBlockInteraction(null, SlotActionType.THROW, stack))
- anyBlocked = true
- }
- if (anyBlocked) {
- event.protectSilent()
- }
- }
-
- @Subscribe
- fun onProtectUuidItems(event: IsSlotProtectedEvent) {
- val doesNotDeleteItem = event.actionType == SlotActionType.SWAP
- || event.actionType == SlotActionType.PICKUP
- || event.actionType == SlotActionType.QUICK_MOVE
- || event.actionType == SlotActionType.QUICK_CRAFT
- || event.actionType == SlotActionType.CLONE
- || event.actionType == SlotActionType.PICKUP_ALL
- val isSellOrTradeScreen =
- isNpcShop(MC.handledScreen) || isTradeScreen(MC.handledScreen) || isSalvageScreen(MC.handledScreen)
- if ((!isSellOrTradeScreen || event.slot?.inventory !is PlayerInventory)
- && doesNotDeleteItem
- ) return
- val stack = event.itemStack ?: return
- val uuid = stack.skyblockUUID ?: return
- if (uuid in (lockedUUIDs ?: return)) {
- event.protect()
- }
- }
-
- @Subscribe
- fun onProtectSlot(it: IsSlotProtectedEvent) {
- if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) {
- it.protect()
- }
- }
-
- @Subscribe
- fun onLockUUID(it: HandledScreenKeyPressedEvent) {
- if (!it.matches(TConfig.lockUUID)) return
- val inventory = MC.handledScreen ?: return
- inventory as AccessorHandledScreen
-
- val slot = inventory.focusedSlot_Firmament ?: return
- val stack = slot.stack ?: return
- val uuid = stack.skyblockUUID ?: return
- val lockedUUIDs = lockedUUIDs ?: return
- if (uuid in lockedUUIDs) {
- lockedUUIDs.remove(uuid)
- } else {
- lockedUUIDs.add(uuid)
- }
- DConfig.markDirty()
- CommonSoundEffects.playSuccess()
- it.cancel()
- }
-
- @Subscribe
- fun onLockSlot(it: HandledScreenKeyPressedEvent) {
- if (!it.matches(TConfig.lockSlot)) return
- val inventory = MC.handledScreen ?: return
- inventory as AccessorHandledScreen
-
- val slot = inventory.focusedSlot_Firmament ?: return
- val lockedSlots = lockedSlots ?: return
- if (slot.inventory is PlayerInventory) {
- if (slot.index in lockedSlots) {
- lockedSlots.remove(slot.index)
- } else {
- lockedSlots.add(slot.index)
- }
- DConfig.markDirty()
- CommonSoundEffects.playSuccess()
- }
- }
-
- @Subscribe
- fun onRenderSlotOverlay(it: SlotRenderEvents.After) {
- val isSlotLocked = it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())
- val isUUIDLocked = (it.slot.stack?.skyblockUUID) in (lockedUUIDs ?: setOf())
- if (isSlotLocked || isUUIDLocked) {
- RenderSystem.disableDepthTest()
- it.context.drawSprite(
- it.slot.x, it.slot.y, 0,
- 16, 16,
- MC.guiAtlasManager.getSprite(
- when {
- isSlotLocked ->
- (Identifier.of("firmament:slot_locked"))
-
- isUUIDLocked ->
- (Identifier.of("firmament:uuid_locked"))
-
- else ->
- error("unreachable")
- }
- )
- )
- RenderSystem.enableDepthTest()
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButton.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButton.kt
deleted file mode 100644
index 539edf2..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButton.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.buttons
-
-import com.mojang.brigadier.StringReader
-import me.shedaniel.math.Dimension
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import kotlinx.serialization.Serializable
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.command.CommandRegistryAccess
-import net.minecraft.command.argument.ItemStackArgumentType
-import net.minecraft.item.ItemStack
-import net.minecraft.resource.featuretoggle.FeatureFlags
-import net.minecraft.util.Identifier
-import moe.nea.firmament.repo.ItemCache.asItemStack
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.memoize
-
-@Serializable
-data class InventoryButton(
- var x: Int,
- var y: Int,
- var anchorRight: Boolean,
- var anchorBottom: Boolean,
- var icon: String? = "",
- var command: String? = "",
-) {
- companion object {
- val itemStackParser by lazy {
- ItemStackArgumentType.itemStack(CommandRegistryAccess.of(MC.defaultRegistries,
- FeatureFlags.VANILLA_FEATURES))
- }
- val dimensions = Dimension(18, 18)
- val getItemForName = ::getItemForName0.memoize(1024)
- fun getItemForName0(icon: String): ItemStack {
- val repoItem = RepoManager.getNEUItem(SkyblockId(icon))
- var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon))
- if (repoItem == null) {
- val giveSyntaxItem = if (icon.startsWith("/give") || icon.startsWith("give"))
- icon.split(" ", limit = 3).getOrNull(2) ?: icon
- else icon
- val componentItem =
- runCatching {
- itemStackParser.parse(StringReader(giveSyntaxItem)).createStack(1, false)
- }.getOrNull()
- if (componentItem != null)
- itemStack = componentItem
- }
- return itemStack
- }
- }
-
- fun render(context: DrawContext) {
- context.drawSprite(
- 0,
- 0,
- 0,
- dimensions.width,
- dimensions.height,
- MC.guiAtlasManager.getSprite(Identifier.of("firmament:inventory_button_background"))
- )
- context.drawItem(getItem(), 1, 1)
- }
-
- fun isValid() = !icon.isNullOrBlank() && !command.isNullOrBlank()
-
- fun getPosition(guiRect: Rectangle): Point {
- return Point(
- (if (anchorRight) guiRect.maxX else guiRect.minX) + x,
- (if (anchorBottom) guiRect.maxY else guiRect.minY) + y,
- )
- }
-
- fun getBounds(guiRect: Rectangle): Rectangle {
- return Rectangle(getPosition(guiRect), dimensions)
- }
-
- fun getItem(): ItemStack {
- return getItemForName(icon ?: "")
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonEditor.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonEditor.kt
deleted file mode 100644
index c57563e..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonEditor.kt
+++ /dev/null
@@ -1,184 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.buttons
-
-import io.github.notenoughupdates.moulconfig.common.IItemStack
-import io.github.notenoughupdates.moulconfig.platform.ModernItemStack
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import org.lwjgl.glfw.GLFW
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.widget.ButtonWidget
-import net.minecraft.client.util.InputUtil
-import net.minecraft.text.Text
-import net.minecraft.util.math.MathHelper
-import net.minecraft.util.math.Vec2f
-import moe.nea.firmament.util.ClipboardUtils
-import moe.nea.firmament.util.FragmentGuiScreen
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.MoulConfigUtils
-
-class InventoryButtonEditor(
- val lastGuiRect: Rectangle,
-) : FragmentGuiScreen() {
- inner class Editor(val originalButton: InventoryButton) {
- @field:Bind
- var command: String = originalButton.command ?: ""
-
- @field:Bind
- var icon: String = originalButton.icon ?: ""
-
- @Bind
- fun getItemIcon(): IItemStack {
- save()
- return ModernItemStack.of(InventoryButton.getItemForName(icon))
- }
-
- @Bind
- fun delete() {
- buttons.removeIf { it === originalButton }
- popup = null
- }
-
- fun save() {
- originalButton.icon = icon
- originalButton.command = command
- }
- }
-
- var buttons: MutableList<InventoryButton> =
- InventoryButtons.DConfig.data.buttons.map { it.copy() }.toMutableList()
-
- override fun close() {
- InventoryButtons.DConfig.data.buttons = buttons
- InventoryButtons.DConfig.markDirty()
- super.close()
- }
-
- override fun init() {
- super.init()
- addDrawableChild(
- ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.load-preset")) {
- val t = ClipboardUtils.getTextContents()
- val newButtons = InventoryButtonTemplates.loadTemplate(t)
- if (newButtons != null)
- buttons = newButtons.toMutableList()
- }
- .position(lastGuiRect.minX + 10, lastGuiRect.minY + 35)
- .width(lastGuiRect.width - 20)
- .build()
- )
- addDrawableChild(
- ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.save-preset")) {
- ClipboardUtils.setTextContent(InventoryButtonTemplates.saveTemplate(buttons))
- }
- .position(lastGuiRect.minX + 10, lastGuiRect.minY + 60)
- .width(lastGuiRect.width - 20)
- .build()
- )
- }
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- super.render(context, mouseX, mouseY, delta)
- context.matrices.push()
- context.matrices.translate(0f, 0f, -10f)
- context.fill(lastGuiRect.minX, lastGuiRect.minY, lastGuiRect.maxX, lastGuiRect.maxY, -1)
- context.setShaderColor(1f, 1f, 1f, 1f)
- context.matrices.pop()
- for (button in buttons) {
- val buttonPosition = button.getBounds(lastGuiRect)
- context.matrices.push()
- context.matrices.translate(buttonPosition.minX.toFloat(), buttonPosition.minY.toFloat(), 0F)
- button.render(context)
- context.matrices.pop()
- }
- }
-
- override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- if (super.keyPressed(keyCode, scanCode, modifiers)) return true
- if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
- close()
- return true
- }
- return false
- }
-
- override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
- if (super.mouseReleased(mouseX, mouseY, button)) return true
- val clickedButton = buttons.firstOrNull { it.getBounds(lastGuiRect).contains(Point(mouseX, mouseY)) }
- if (clickedButton != null && !justPerformedAClickAction) {
- createPopup(MoulConfigUtils.loadGui("button_editor_fragment", Editor(clickedButton)), Point(mouseX, mouseY))
- return true
- }
- justPerformedAClickAction = false
- lastDraggedButton = null
- return false
- }
-
- override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
- if (super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) return true
-
- if (initialDragMousePosition.distanceSquared(Vec2f(mouseX.toFloat(), mouseY.toFloat())) >= 4 * 4) {
- initialDragMousePosition = Vec2f(-10F, -10F)
- lastDraggedButton?.let { dragging ->
- justPerformedAClickAction = true
- val (anchorRight, anchorBottom, offsetX, offsetY) = getCoordsForMouse(mouseX.toInt(), mouseY.toInt())
- ?: return true
- dragging.x = offsetX
- dragging.y = offsetY
- dragging.anchorRight = anchorRight
- dragging.anchorBottom = anchorBottom
- }
- }
- return false
- }
-
- var lastDraggedButton: InventoryButton? = null
- var justPerformedAClickAction = false
- var initialDragMousePosition = Vec2f(-10F, -10F)
-
- data class AnchoredCoords(
- val anchorRight: Boolean,
- val anchorBottom: Boolean,
- val offsetX: Int,
- val offsetY: Int,
- )
-
- fun getCoordsForMouse(mx: Int, my: Int): AnchoredCoords? {
- if (lastGuiRect.contains(mx, my) || lastGuiRect.contains(
- Point(
- mx + InventoryButton.dimensions.width,
- my + InventoryButton.dimensions.height,
- )
- )
- ) return null
-
- val anchorRight = mx > lastGuiRect.maxX
- val anchorBottom = my > lastGuiRect.maxY
- var offsetX = mx - if (anchorRight) lastGuiRect.maxX else lastGuiRect.minX
- var offsetY = my - if (anchorBottom) lastGuiRect.maxY else lastGuiRect.minY
- if (InputUtil.isKeyPressed(MC.window.handle, InputUtil.GLFW_KEY_LEFT_SHIFT)) {
- offsetX = MathHelper.floor(offsetX / 20F) * 20
- offsetY = MathHelper.floor(offsetY / 20F) * 20
- }
- return AnchoredCoords(anchorRight, anchorBottom, offsetX, offsetY)
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- if (super.mouseClicked(mouseX, mouseY, button)) return true
- val clickedButton = buttons.firstOrNull { it.getBounds(lastGuiRect).contains(Point(mouseX, mouseY)) }
- if (clickedButton != null) {
- lastDraggedButton = clickedButton
- initialDragMousePosition = Vec2f(mouseX.toFloat(), mouseY.toFloat())
- return true
- }
- val mx = mouseX.toInt()
- val my = mouseY.toInt()
- val (anchorRight, anchorBottom, offsetX, offsetY) = getCoordsForMouse(mx, my) ?: return true
- buttons.add(InventoryButton(offsetX, offsetY, anchorRight, anchorBottom, null, null))
- justPerformedAClickAction = true
- return true
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonTemplates.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonTemplates.kt
deleted file mode 100644
index 99b544b..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtonTemplates.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.buttons
-
-import kotlinx.serialization.decodeFromString
-import kotlinx.serialization.encodeToString
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.TemplateUtil
-
-object InventoryButtonTemplates {
-
- val legacyPrefix = "NEUBUTTONS/"
- val modernPrefix = "MAYBEONEDAYIWILLHAVEMYOWNFORMAT"
-
- fun loadTemplate(t: String): List<InventoryButton>? {
- val buttons = TemplateUtil.maybeDecodeTemplate<List<String>>(legacyPrefix, t) ?: return null
- return buttons.mapNotNull {
- try {
- Firmament.json.decodeFromString<InventoryButton>(it).also {
- if (it.icon?.startsWith("extra:") == true || it.command?.any { it.isLowerCase() } == true) {
- MC.sendChat(Text.translatable("firmament.inventory-buttons.import-failed"))
- }
- }
- } catch (e: Exception) {
- null
- }
- }
- }
-
- fun saveTemplate(buttons: List<InventoryButton>): String {
- return TemplateUtil.encodeTemplate(legacyPrefix, buttons.map { Firmament.json.encodeToString(it) })
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt
deleted file mode 100644
index fa90d21..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/buttons/InventoryButtons.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.buttons
-
-import me.shedaniel.math.Rectangle
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HandledScreenClickEvent
-import moe.nea.firmament.events.HandledScreenForegroundEvent
-import moe.nea.firmament.events.HandledScreenPushREIEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.ScreenUtil
-import moe.nea.firmament.util.data.DataHolder
-import moe.nea.firmament.util.getRectangle
-
-object InventoryButtons : FirmamentFeature {
- override val identifier: String
- get() = "inventory-buttons"
-
- object TConfig : ManagedConfig(identifier) {
- val _openEditor by button("open-editor") {
- openEditor()
- }
- }
-
- object DConfig : DataHolder<Data>(serializer(), identifier, ::Data)
-
- @Serializable
- data class Data(
- var buttons: MutableList<InventoryButton> = mutableListOf()
- )
-
-
- override val config: ManagedConfig
- get() = TConfig
-
- fun getValidButtons() = DConfig.data.buttons.asSequence().filter { it.isValid() }
-
- @Subscribe
- fun onRectangles(it: HandledScreenPushREIEvent) {
- val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
- val buttonBounds = button.getBounds(bounds)
- it.block(buttonBounds)
- }
- }
-
- @Subscribe
- fun onClickScreen(it: HandledScreenClickEvent) {
- val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
- val buttonBounds = button.getBounds(bounds)
- if (buttonBounds.contains(it.mouseX, it.mouseY)) {
- MC.sendCommand(button.command!! /* non null invariant covered by getValidButtons */)
- break
- }
- }
- }
-
- @Subscribe
- fun onRenderForeground(it: HandledScreenForegroundEvent) {
- val bounds = it.screen.getRectangle()
- for (button in getValidButtons()) {
- val buttonBounds = button.getBounds(bounds)
- it.context.matrices.push()
- it.context.matrices.translate(buttonBounds.minX.toFloat(), buttonBounds.minY.toFloat(), 0F)
- button.render(it.context)
- it.context.matrices.pop()
- }
- lastRectangle = bounds
- }
-
- var lastRectangle: Rectangle? = null
- fun openEditor() {
- ScreenUtil.setScreenLater(
- InventoryButtonEditor(
- lastRectangle ?: Rectangle(
- MC.window.scaledWidth / 2 - 100,
- MC.window.scaledHeight / 2 - 100,
- 200, 200,
- )
- )
- )
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageBackingHandle.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageBackingHandle.kt
deleted file mode 100644
index 1015578..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageBackingHandle.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.screen.GenericContainerScreenHandler
-import moe.nea.firmament.util.ifMatches
-import moe.nea.firmament.util.unformattedString
-
-/**
- * A handle representing the state of the "server side" screens.
- */
-sealed interface StorageBackingHandle {
-
- sealed interface HasBackingScreen {
- val handler: GenericContainerScreenHandler
- }
-
- /**
- * The main storage overview is open. Clicking on a slot will open that page. This page is accessible via `/storage`
- */
- data class Overview(override val handler: GenericContainerScreenHandler) : StorageBackingHandle, HasBackingScreen
-
- /**
- * An individual storage page is open. This may be a backpack or an enderchest page. This page is accessible via
- * the [Overview] or via `/ec <index + 1>` for enderchest pages.
- */
- data class Page(override val handler: GenericContainerScreenHandler, val storagePageSlot: StoragePageSlot) :
- StorageBackingHandle, HasBackingScreen
-
- companion object {
- private val enderChestName = "^Ender Chest \\(([1-9])/[1-9]\\)$".toRegex()
- private val backPackName = "^.+Backpack \\(Slot #([0-9]+)\\)$".toRegex()
-
- /**
- * Parse a screen into a [StorageBackingHandle]. If this returns null it means that the screen is not
- * representable as a [StorageBackingHandle], meaning another screen is open, for example the enderchest icon
- * selection screen.
- */
- fun fromScreen(screen: Screen?): StorageBackingHandle? {
- if (screen == null) return null
- if (screen !is GenericContainerScreen) return null
- val title = screen.title.unformattedString
- if (title == "Storage") return Overview(screen.screenHandler)
- return title.ifMatches(enderChestName) {
- Page(screen.screenHandler, StoragePageSlot.ofEnderChestPage(it.groupValues[1].toInt()))
- } ?: title.ifMatches(backPackName) {
- Page(screen.screenHandler, StoragePageSlot.ofBackPackPage(it.groupValues[1].toInt()))
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageData.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageData.kt
deleted file mode 100644
index 7555c56..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageData.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-@file:UseSerializers(SortedMapSerializer::class)
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import java.util.SortedMap
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import moe.nea.firmament.util.SortedMapSerializer
-
-@Serializable
-data class StorageData(
- val storageInventories: SortedMap<StoragePageSlot, StorageInventory> = sortedMapOf()
-) {
- @Serializable
- data class StorageInventory(
- var title: String,
- val slot: StoragePageSlot,
- var inventory: VirtualInventory?,
- )
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt
deleted file mode 100644
index b615c73..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlay.kt
+++ /dev/null
@@ -1,154 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import java.util.SortedMap
-import kotlinx.serialization.serializer
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.entity.player.PlayerInventory
-import net.minecraft.item.Items
-import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ScreenChangeEvent
-import moe.nea.firmament.events.SlotClickEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.customgui.customGui
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-
-object StorageOverlay : FirmamentFeature {
-
-
- object Data : ProfileSpecificDataHolder<StorageData>(serializer(), "storage-data", ::StorageData)
-
- override val identifier: String
- get() = "storage-overlay"
-
- object TConfig : ManagedConfig(identifier) {
- val alwaysReplace by toggle("always-replace") { true }
- val columns by integer("rows", 1, 10) { 3 }
- val scrollSpeed by integer("scroll-speed", 1, 50) { 10 }
- val inverseScroll by toggle("inverse-scroll") { false }
- val padding by integer("padding", 1, 20) { 5 }
- val margin by integer("margin", 1, 60) { 20 }
- }
-
- fun adjustScrollSpeed(amount: Double): Double {
- return amount * TConfig.scrollSpeed * (if (TConfig.inverseScroll) 1 else -1)
- }
-
- override val config: TConfig
- get() = TConfig
-
- var lastStorageOverlay: StorageOverviewScreen? = null
- var skipNextStorageOverlayBackflip = false
- var currentHandler: StorageBackingHandle? = null
-
- @Subscribe
- fun onTick(event: TickEvent) {
- rememberContent(currentHandler ?: return)
- }
-
- @Subscribe
- fun onClick(event: SlotClickEvent) {
- if (lastStorageOverlay != null && event.slot.inventory !is PlayerInventory && event.slot.index < 9
- && event.stack.item != Items.BLACK_STAINED_GLASS_PANE
- ) {
- skipNextStorageOverlayBackflip = true
- }
- }
-
- @Subscribe
- fun onScreenChange(it: ScreenChangeEvent) {
- if (it.old == null && it.new == null) return
- val storageOverlayScreen = it.old as? StorageOverlayScreen
- ?: ((it.old as? HandledScreen<*>)?.customGui as? StorageOverlayCustom)?.overview
- var storageOverviewScreen = it.old as? StorageOverviewScreen
- val screen = it.new as? GenericContainerScreen
- val oldHandler = currentHandler
- currentHandler = StorageBackingHandle.fromScreen(screen)
- rememberContent(currentHandler)
- if (storageOverviewScreen != null && oldHandler is StorageBackingHandle.HasBackingScreen) {
- val player = MC.player
- assert(player != null)
- player?.networkHandler?.sendPacket(CloseHandledScreenC2SPacket(oldHandler.handler.syncId))
- if (player?.currentScreenHandler === oldHandler.handler) {
- player.currentScreenHandler = player.playerScreenHandler
- }
- }
- storageOverviewScreen = storageOverviewScreen ?: lastStorageOverlay
- if (it.new == null && storageOverlayScreen != null && !storageOverlayScreen.isExiting) {
- it.overrideScreen = storageOverlayScreen
- return
- }
- if (storageOverviewScreen != null
- && !storageOverviewScreen.isClosing
- && (currentHandler is StorageBackingHandle.Overview || currentHandler == null)
- ) {
- if (skipNextStorageOverlayBackflip) {
- skipNextStorageOverlayBackflip = false
- } else {
- it.overrideScreen = storageOverviewScreen
- lastStorageOverlay = null
- }
- return
- }
- screen ?: return
- screen.customGui = StorageOverlayCustom(
- currentHandler ?: return,
- screen,
- storageOverlayScreen ?: (if (TConfig.alwaysReplace) StorageOverlayScreen() else return))
- }
-
- fun rememberContent(handler: StorageBackingHandle?) {
- handler ?: return
- // TODO: Make all of these functions work on deltas / updates instead of the entire contents
- val data = Data.data?.storageInventories ?: return
- when (handler) {
- is StorageBackingHandle.Overview -> rememberStorageOverview(handler, data)
- is StorageBackingHandle.Page -> rememberPage(handler, data)
- }
- Data.markDirty()
- }
-
- private fun rememberStorageOverview(
- handler: StorageBackingHandle.Overview,
- data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
- ) {
- for ((index, stack) in handler.handler.stacks.withIndex()) {
- // Ignore unloaded item stacks
- if (stack.isEmpty) continue
- val slot = StoragePageSlot.fromOverviewSlotIndex(index) ?: continue
- val isEmpty = stack.item in StorageOverviewScreen.emptyStorageSlotItems
- if (slot in data) {
- if (isEmpty)
- data.remove(slot)
- continue
- }
- if (!isEmpty) {
- data[slot] = StorageData.StorageInventory(slot.defaultName(), slot, null)
- }
- }
- }
-
- private fun rememberPage(
- handler: StorageBackingHandle.Page,
- data: SortedMap<StoragePageSlot, StorageData.StorageInventory>
- ) {
- // TODO: FIXME: FIXME NOW: Definitely don't copy all of this every tick into persistence
- val newStacks =
- VirtualInventory(handler.handler.stacks.take(handler.handler.rows * 9).drop(9).map { it.copy() })
- data.compute(handler.storagePageSlot) { slot, existingInventory ->
- (existingInventory ?: StorageData.StorageInventory(
- slot.defaultName(),
- slot,
- null
- )).also {
- it.inventory = newStacks
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayCustom.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayCustom.kt
deleted file mode 100644
index d0d9114..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayCustom.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.entity.player.PlayerInventory
-import net.minecraft.screen.slot.Slot
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import moe.nea.firmament.util.customgui.CustomGui
-
-class StorageOverlayCustom(
- val handler: StorageBackingHandle,
- val screen: GenericContainerScreen,
- val overview: StorageOverlayScreen,
-) : CustomGui() {
- override fun onVoluntaryExit(): Boolean {
- overview.isExiting = true
- return super.onVoluntaryExit()
- }
-
- override fun getBounds(): List<Rectangle> {
- return overview.getBounds()
- }
-
- override fun afterSlotRender(context: DrawContext, slot: Slot) {
- if (slot.inventory !is PlayerInventory)
- context.disableScissor()
- }
-
- override fun beforeSlotRender(context: DrawContext, slot: Slot) {
- if (slot.inventory !is PlayerInventory)
- overview.createScissors(context)
- }
-
- override fun onInit() {
- overview.init(MinecraftClient.getInstance(), screen.width, screen.height)
- overview.init()
- screen as AccessorHandledScreen
- screen.x_Firmament = overview.measurements.x
- screen.y_Firmament = overview.measurements.y
- screen.backgroundWidth_Firmament = overview.measurements.totalWidth
- screen.backgroundHeight_Firmament = overview.measurements.totalHeight
- }
-
- override fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean {
- if (!super.isPointOverSlot(slot, xOffset, yOffset, pointX, pointY))
- return false
- if (slot.inventory !is PlayerInventory) {
- if (!overview.getScrollPanelInner().contains(pointX, pointY))
- return false
- }
- return true
- }
-
- override fun shouldDrawForeground(): Boolean {
- return false
- }
-
- override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean {
- return overview.mouseClicked(mouseX, mouseY, button, (handler as? StorageBackingHandle.Page)?.storagePageSlot)
- }
-
- override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) {
- overview.drawBackgrounds(drawContext)
- overview.drawPages(drawContext,
- mouseX,
- mouseY,
- delta,
- (handler as? StorageBackingHandle.Page)?.storagePageSlot,
- screen.screenHandler.slots.take(screen.screenHandler.rows * 9).drop(9),
- Point((screen as AccessorHandledScreen).x_Firmament, screen.y_Firmament))
- overview.drawScrollBar(drawContext)
- }
-
- override fun moveSlot(slot: Slot) {
- val index = slot.index
- if (index in 0..<36) {
- val (x, y) = overview.getPlayerInventorySlotPosition(index)
- slot.x = x - (screen as AccessorHandledScreen).x_Firmament
- slot.y = y - screen.y_Firmament
- } else {
- slot.x = -100000
- slot.y = -100000
- }
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- return overview.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayScreen.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayScreen.kt
deleted file mode 100644
index 13c6974..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverlayScreen.kt
+++ /dev/null
@@ -1,296 +0,0 @@
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.screen.slot.Slot
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.ScreenUtil
-import moe.nea.firmament.util.assertTrueOr
-
-class StorageOverlayScreen : Screen(Text.literal("")) {
-
- companion object {
- val PLAYER_WIDTH = 184
- val PLAYER_HEIGHT = 91
- val PLAYER_Y_INSET = 3
- val SLOT_SIZE = 18
- val PADDING = 10
- val PAGE_WIDTH = SLOT_SIZE * 9
- val HOTBAR_X = 12
- val HOTBAR_Y = 67
- val MAIN_INVENTORY_Y = 9
- val SCROLL_BAR_WIDTH = 8
- val SCROLL_BAR_HEIGHT = 16
- }
-
- var isExiting: Boolean = false
- var scroll: Float = 0F
- var pageWidthCount = StorageOverlay.TConfig.columns
-
- inner class Measurements {
- val innerScrollPanelWidth = PAGE_WIDTH * pageWidthCount + (pageWidthCount - 1) * PADDING
- val overviewWidth = innerScrollPanelWidth + 3 * PADDING + SCROLL_BAR_WIDTH
- val x = width / 2 - overviewWidth / 2
- val overviewHeight = minOf(3 * 18 * 6, height - PLAYER_HEIGHT - minOf(80, height / 10))
- val innerScrollPanelHeight = overviewHeight - PADDING * 2
- val y = height / 2 - (overviewHeight + PLAYER_HEIGHT) / 2
- val playerX = width / 2 - PLAYER_WIDTH / 2
- val playerY = y + overviewHeight - PLAYER_Y_INSET
- val totalWidth = overviewWidth
- val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT
- }
-
- var measurements = Measurements()
-
- var lastRenderedInnerHeight = 0
- public override fun init() {
- super.init()
- pageWidthCount = StorageOverlay.TConfig.columns
- .coerceAtMost((width - PADDING) / (PAGE_WIDTH + PADDING))
- .coerceAtLeast(1)
- measurements = Measurements()
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- scroll = (scroll + StorageOverlay.adjustScrollSpeed(verticalAmount)).toFloat()
- .coerceAtMost(getMaxScroll())
- .coerceAtLeast(0F)
- return true
- }
-
- fun getMaxScroll() = lastRenderedInnerHeight.toFloat() - getScrollPanelInner().height
-
- val playerInventorySprite = Identifier.of("firmament:storageoverlay/player_inventory")
- val upperBackgroundSprite = Identifier.of("firmament:storageoverlay/upper_background")
- val slotRowSprite = Identifier.of("firmament:storageoverlay/storage_row")
- val scrollbarBackground = Identifier.of("firmament:storageoverlay/scroll_bar_background")
- val scrollbarKnob = Identifier.of("firmament:storageoverlay/scroll_bar_knob")
-
- override fun close() {
- isExiting = true
- super.close()
- }
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- super.render(context, mouseX, mouseY, delta)
- drawBackgrounds(context)
- drawPages(context, mouseX, mouseY, delta, null, null, Point())
- drawScrollBar(context)
- drawPlayerInventory(context, mouseX, mouseY, delta)
- }
-
- fun getScrollbarPercentage(): Float {
- return scroll / getMaxScroll()
- }
-
- fun drawScrollBar(context: DrawContext) {
- val sbRect = getScrollBarRect()
- context.drawGuiTexture(
- scrollbarBackground,
- sbRect.minX, sbRect.minY,
- sbRect.width, sbRect.height,
- )
- context.drawGuiTexture(
- scrollbarKnob,
- sbRect.minX, sbRect.minY + (getScrollbarPercentage() * (sbRect.height - SCROLL_BAR_HEIGHT)).toInt(),
- SCROLL_BAR_WIDTH, SCROLL_BAR_HEIGHT
- )
- }
-
- fun drawBackgrounds(context: DrawContext) {
- context.drawGuiTexture(upperBackgroundSprite,
- measurements.x,
- measurements.y,
- 0,
- measurements.overviewWidth,
- measurements.overviewHeight)
- context.drawGuiTexture(playerInventorySprite,
- measurements.playerX,
- measurements.playerY,
- 0,
- PLAYER_WIDTH,
- PLAYER_HEIGHT)
- }
-
- fun getPlayerInventorySlotPosition(int: Int): Pair<Int, Int> {
- if (int < 9) {
- return Pair(measurements.playerX + int * SLOT_SIZE + HOTBAR_X, HOTBAR_Y + measurements.playerY)
- }
- return Pair(
- measurements.playerX + (int % 9) * SLOT_SIZE + HOTBAR_X,
- measurements.playerY + (int / 9 - 1) * SLOT_SIZE + MAIN_INVENTORY_Y
- )
- }
-
- fun drawPlayerInventory(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- val items = MC.player?.inventory?.main ?: return
- items.withIndex().forEach { (index, item) ->
- val (x, y) = getPlayerInventorySlotPosition(index)
- context.drawItem(item, x, y, 0)
- context.drawItemInSlot(textRenderer, item, x, y)
- }
- }
-
- fun getScrollBarRect(): Rectangle {
- return Rectangle(measurements.x + PADDING + measurements.innerScrollPanelWidth + PADDING,
- measurements.y + PADDING,
- SCROLL_BAR_WIDTH,
- measurements.innerScrollPanelHeight)
- }
-
- fun getScrollPanelInner(): Rectangle {
- return Rectangle(measurements.x + PADDING,
- measurements.y + PADDING,
- measurements.innerScrollPanelWidth,
- measurements.innerScrollPanelHeight)
- }
-
- fun createScissors(context: DrawContext) {
- val rect = getScrollPanelInner()
- context.enableScissor(
- rect.minX, rect.minY,
- rect.maxX, rect.maxY
- )
- }
-
- fun drawPages(
- context: DrawContext, mouseX: Int, mouseY: Int, delta: Float,
- excluding: StoragePageSlot?,
- slots: List<Slot>?,
- slotOffset: Point
- ) {
- createScissors(context)
- val data = StorageOverlay.Data.data ?: StorageData()
- layoutedForEach(data) { rect, page, inventory ->
- drawPage(context,
- rect.x,
- rect.y,
- page, inventory,
- if (excluding == page) slots else null,
- slotOffset
- )
- }
- context.disableScissor()
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- return mouseClicked(mouseX, mouseY, button, null)
- }
-
- fun mouseClicked(mouseX: Double, mouseY: Double, button: Int, activePage: StoragePageSlot?): Boolean {
- if (getScrollPanelInner().contains(mouseX, mouseY)) {
- val data = StorageOverlay.Data.data ?: StorageData()
- layoutedForEach(data) { rect, page, _ ->
- if (rect.contains(mouseX, mouseY) && activePage != page && button == 0) {
- page.navigateTo()
- return true
- }
- }
- return false
- }
- val sbRect = getScrollBarRect()
- if (sbRect.contains(mouseX, mouseY)) {
- // TODO: support dragging of the mouse and such
- val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight()
- scroll = (getMaxScroll() * percentage).toFloat()
- mouseScrolled(0.0, 0.0, 0.0, 0.0)
- return true
- }
- return false
- }
-
- private inline fun layoutedForEach(
- data: StorageData,
- func: (
- rectangle: Rectangle,
- page: StoragePageSlot, inventory: StorageData.StorageInventory,
- ) -> Unit
- ) {
- var yOffset = -scroll.toInt()
- var xOffset = 0
- var maxHeight = 0
- for ((page, inventory) in data.storageInventories.entries) {
- val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 4 + textRenderer.fontHeight }
- ?: 18
- maxHeight = maxOf(maxHeight, currentHeight)
- val rect = Rectangle(
- measurements.x + PADDING + (PAGE_WIDTH + PADDING) * xOffset,
- yOffset + measurements.y + PADDING,
- PAGE_WIDTH,
- currentHeight
- )
- func(rect, page, inventory)
- xOffset++
- if (xOffset >= pageWidthCount) {
- yOffset += maxHeight
- xOffset = 0
- maxHeight = 0
- }
- }
- lastRenderedInnerHeight = maxHeight + yOffset + scroll.toInt()
- }
-
- fun drawPage(
- context: DrawContext,
- x: Int,
- y: Int,
- page: StoragePageSlot,
- inventory: StorageData.StorageInventory,
- slots: List<Slot>?,
- slotOffset: Point,
- ): Int {
- val inv = inventory.inventory
- if (inv == null) {
- context.drawGuiTexture(upperBackgroundSprite, x, y, PAGE_WIDTH, 18)
- context.drawText(textRenderer,
- Text.literal("TODO: open this page"),
- x + 4,
- y + 4,
- -1,
- true)
- return 18
- }
- assertTrueOr(slots == null || slots.size == inv.stacks.size) { return 0 }
- val name = page.defaultName()
- context.drawText(textRenderer, Text.literal(name), x + 4, y + 2,
- if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true)
- context.drawGuiTexture(slotRowSprite, x, y + 4 + textRenderer.fontHeight, PAGE_WIDTH, inv.rows * SLOT_SIZE)
- inv.stacks.forEachIndexed { index, stack ->
- val slotX = (index % 9) * SLOT_SIZE + x + 1
- val slotY = (index / 9) * SLOT_SIZE + y + 4 + textRenderer.fontHeight + 1
- if (slots == null) {
- context.drawItem(stack, slotX, slotY)
- context.drawItemInSlot(textRenderer, stack, slotX, slotY)
- } else {
- val slot = slots[index]
- slot.x = slotX - slotOffset.x
- slot.y = slotY - slotOffset.y
- }
- }
- return inv.rows * SLOT_SIZE + 4 + textRenderer.fontHeight
- }
-
- fun getBounds(): List<Rectangle> {
- return listOf(
- Rectangle(measurements.x,
- measurements.y,
- measurements.overviewWidth,
- measurements.overviewHeight),
- Rectangle(measurements.playerX,
- measurements.playerY,
- PLAYER_WIDTH,
- PLAYER_HEIGHT))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverviewScreen.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverviewScreen.kt
deleted file mode 100644
index 2cbd54e..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StorageOverviewScreen.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import org.lwjgl.glfw.GLFW
-import kotlin.math.max
-import net.minecraft.block.Blocks
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.item.Item
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import net.minecraft.util.DyeColor
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.toShedaniel
-
-class StorageOverviewScreen() : Screen(Text.empty()) {
- companion object {
- val emptyStorageSlotItems = listOf<Item>(
- Blocks.RED_STAINED_GLASS_PANE.asItem(),
- Blocks.BROWN_STAINED_GLASS_PANE.asItem(),
- Items.GRAY_DYE
- )
- val pageWidth get() = 19 * 9
- }
-
- val content = StorageOverlay.Data.data ?: StorageData()
- var isClosing = false
-
- var scroll = 0
- var lastRenderedHeight = 0
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- super.render(context, mouseX, mouseY, delta)
- context.fill(0, 0, width, height, 0x90000000.toInt())
- layoutedForEach { (key, value), offsetX, offsetY ->
- context.matrices.push()
- context.matrices.translate(offsetX.toFloat(), offsetY.toFloat(), 0F)
- renderStoragePage(context, value, mouseX - offsetX, mouseY - offsetY)
- context.matrices.pop()
- }
- }
-
- inline fun layoutedForEach(onEach: (data: Pair<StoragePageSlot, StorageData.StorageInventory>, offsetX: Int, offsetY: Int) -> Unit) {
- var offsetY = 0
- var currentMaxHeight = StorageOverlay.config.margin - StorageOverlay.config.padding - scroll
- var totalHeight = -currentMaxHeight
- content.storageInventories.onEachIndexed { index, (key, value) ->
- val pageX = (index % StorageOverlay.config.columns)
- if (pageX == 0) {
- currentMaxHeight += StorageOverlay.config.padding
- offsetY += currentMaxHeight
- totalHeight += currentMaxHeight
- currentMaxHeight = 0
- }
- val xPosition =
- width / 2 - (StorageOverlay.config.columns * (pageWidth + StorageOverlay.config.padding) - StorageOverlay.config.padding) / 2 + pageX * (pageWidth + StorageOverlay.config.padding)
- onEach(Pair(key, value), xPosition, offsetY)
- val height = getStorePageHeight(value)
- currentMaxHeight = max(currentMaxHeight, height)
- }
- lastRenderedHeight = totalHeight + currentMaxHeight
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- layoutedForEach { (k, p), x, y ->
- val rx = mouseX - x
- val ry = mouseY - y
- if (rx in (0.0..pageWidth.toDouble()) && ry in (0.0..getStorePageHeight(p).toDouble())) {
- close()
- StorageOverlay.lastStorageOverlay = this
- k.navigateTo()
- return true
- }
- }
- return super.mouseClicked(mouseX, mouseY, button)
- }
-
- fun getStorePageHeight(page: StorageData.StorageInventory): Int {
- return page.inventory?.rows?.let { it * 19 + MC.font.fontHeight + 2 } ?: 60
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- scroll =
- (scroll + StorageOverlay.adjustScrollSpeed(verticalAmount)).toInt()
- .coerceAtMost(lastRenderedHeight - height + 2 * StorageOverlay.config.margin).coerceAtLeast(0)
- return true
- }
-
- private fun renderStoragePage(context: DrawContext, page: StorageData.StorageInventory, mouseX: Int, mouseY: Int) {
- context.drawText(MC.font, page.title, 2, 2, -1, true)
- val inventory = page.inventory
- if (inventory == null) {
- // TODO: Missing texture
- context.fill(0, 0, pageWidth, 60, DyeColor.RED.toShedaniel().darker(4.0).color)
- context.drawCenteredTextWithShadow(MC.font, Text.literal("Not loaded yet"), pageWidth / 2, 30, -1)
- return
- }
-
- for ((index, stack) in inventory.stacks.withIndex()) {
- val x = (index % 9) * 19
- val y = (index / 9) * 19 + MC.font.fontHeight + 2
- if (((mouseX - x) in 0 until 18) && ((mouseY - y) in 0 until 18)) {
- context.fill(x, y, x + 18, y + 18, 0x80808080.toInt())
- } else {
- context.fill(x, y, x + 18, y + 18, 0x40808080.toInt())
- }
- context.drawItem(stack, x + 1, y + 1)
- context.drawItemInSlot(MC.font, stack, x + 1, y + 1)
- }
- }
-
- override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- if (keyCode == GLFW.GLFW_KEY_ESCAPE)
- isClosing = true
- return super.keyPressed(keyCode, scanCode, modifiers)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StoragePageSlot.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StoragePageSlot.kt
deleted file mode 100644
index 9259415..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/StoragePageSlot.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import moe.nea.firmament.util.MC
-
-@Serializable(with = StoragePageSlot.Serializer::class)
-data class StoragePageSlot(val index: Int) : Comparable<StoragePageSlot> {
- object Serializer : KSerializer<StoragePageSlot> {
- override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("StoragePageSlot", PrimitiveKind.INT)
-
- override fun deserialize(decoder: Decoder): StoragePageSlot {
- return StoragePageSlot(decoder.decodeInt())
- }
-
- override fun serialize(encoder: Encoder, value: StoragePageSlot) {
- encoder.encodeInt(value.index)
- }
- }
-
- init {
- assert(index in 0 until (3 * 9))
- }
-
- val isEnderChest get() = index < 9
- val isBackPack get() = !isEnderChest
- val slotIndexInOverviewPage get() = if (isEnderChest) index + 9 else index + 18
- fun defaultName(): String = if (isEnderChest) "Ender Chest #${index + 1}" else "Backpack #${index - 9 + 1}"
-
- fun navigateTo() {
- if (isBackPack) {
- MC.sendCommand("backpack ${index - 9 + 1}")
- } else {
- MC.sendCommand("enderchest ${index + 1}")
- }
- }
-
- companion object {
- fun fromOverviewSlotIndex(slot: Int): StoragePageSlot? {
- if (slot in 9 until 18) return StoragePageSlot(slot - 9)
- if (slot in 27 until 45) return StoragePageSlot(slot - 27 + 9)
- return null
- }
-
- fun ofEnderChestPage(slot: Int): StoragePageSlot {
- assert(slot in 1..9)
- return StoragePageSlot(slot - 1)
- }
-
- fun ofBackPackPage(slot: Int): StoragePageSlot {
- assert(slot in 1..18)
- return StoragePageSlot(slot - 1 + 9)
- }
- }
-
- override fun compareTo(other: StoragePageSlot): Int {
- return this.index - other.index
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/VirtualInventory.kt b/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/VirtualInventory.kt
deleted file mode 100644
index e07df8a..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/inventory/storageoverlay/VirtualInventory.kt
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-package moe.nea.firmament.features.inventory.storageoverlay
-
-import io.ktor.util.decodeBase64Bytes
-import io.ktor.util.encodeBase64
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.nbt.NbtIo
-import net.minecraft.nbt.NbtList
-import net.minecraft.nbt.NbtOps
-import net.minecraft.nbt.NbtSizeTracker
-
-@Serializable(with = VirtualInventory.Serializer::class)
-data class VirtualInventory(
- val stacks: List<ItemStack>
-) {
- val rows = stacks.size / 9
-
- init {
- assert(stacks.size % 9 == 0)
- assert(stacks.size / 9 in 1..5)
- }
-
-
- object Serializer : KSerializer<VirtualInventory> {
- const val INVENTORY = "INVENTORY"
- override val descriptor: SerialDescriptor
- get() = PrimitiveSerialDescriptor("VirtualInventory", PrimitiveKind.STRING)
-
- override fun deserialize(decoder: Decoder): VirtualInventory {
- val s = decoder.decodeString()
- val n = NbtIo.readCompressed(ByteArrayInputStream(s.decodeBase64Bytes()), NbtSizeTracker.of(100_000_000))
- val items = n.getList(INVENTORY, NbtCompound.COMPOUND_TYPE.toInt())
- return VirtualInventory(items.map {
- it as NbtCompound
- if (it.isEmpty) ItemStack.EMPTY
- else runCatching {
- ItemStack.CODEC.parse(NbtOps.INSTANCE, it).orThrow
- }.getOrElse { ItemStack.EMPTY }
- })
- }
-
- override fun serialize(encoder: Encoder, value: VirtualInventory) {
- val list = NbtList()
- value.stacks.forEach {
- if (it.isEmpty) list.add(NbtCompound())
- else list.add(runCatching { ItemStack.CODEC.encode(it, NbtOps.INSTANCE, NbtCompound()).orThrow }
- .getOrElse { NbtCompound() })
- }
- val baos = ByteArrayOutputStream()
- NbtIo.writeCompressed(NbtCompound().also { it.put(INVENTORY, list) }, baos)
- encoder.encodeString(baos.toByteArray().encodeBase64())
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt b/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt
deleted file mode 100644
index ed48437..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import java.util.*
-import kotlin.time.Duration
-import moe.nea.firmament.util.TimeMark
-
-class Histogram<T>(
- val maxSize: Int,
- val maxDuration: Duration,
-) {
-
- data class OrderedTimestamp(val timestamp: TimeMark, val order: Int) : Comparable<OrderedTimestamp> {
- override fun compareTo(other: OrderedTimestamp): Int {
- val o = timestamp.compareTo(other.timestamp)
- if (o != 0) return o
- return order.compareTo(other.order)
- }
- }
-
- val size: Int get() = dataPoints.size
- private val dataPoints: NavigableMap<OrderedTimestamp, T> = TreeMap()
-
- private var order = Int.MIN_VALUE
-
- fun record(entry: T, timestamp: TimeMark = TimeMark.now()) {
- dataPoints[OrderedTimestamp(timestamp, order++)] = entry
- trim()
- }
-
- fun oldestUpdate(): TimeMark {
- trim()
- return if (dataPoints.isEmpty()) TimeMark.now() else dataPoints.firstKey().timestamp
- }
-
- fun latestUpdate(): TimeMark {
- trim()
- return if (dataPoints.isEmpty()) TimeMark.farPast() else dataPoints.lastKey().timestamp
- }
-
- fun averagePer(valueExtractor: (T) -> Double, perDuration: Duration): Double? {
- return aggregate(
- seed = 0.0,
- operator = { accumulator, entry, _ -> accumulator + valueExtractor(entry) },
- finish = { sum, beginning, end ->
- val timespan = end - beginning
- if (timespan > perDuration)
- sum / (timespan / perDuration)
- else null
- })
- }
-
- fun <V, R> aggregate(
- seed: V,
- operator: (V, T, TimeMark) -> V,
- finish: (V, TimeMark, TimeMark) -> R
- ): R? {
- trim()
- var accumulator = seed
- var min: TimeMark? = null
- var max: TimeMark? = null
- dataPoints.forEach { (key, value) ->
- max = key.timestamp
- if (min == null)
- min = key.timestamp
- accumulator = operator(accumulator, value, key.timestamp)
- }
- if (min == null)
- return null
- return finish(accumulator, min!!, max!!)
- }
-
- private fun trim() {
- while (maxSize < dataPoints.size) {
- dataPoints.pollFirstEntry()
- }
- dataPoints.headMap(OrderedTimestamp(TimeMark.ago(maxDuration), Int.MAX_VALUE)).clear()
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt
deleted file mode 100644
index 7879f2d..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import java.util.regex.Pattern
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.item.ItemStack
-import net.minecraft.util.DyeColor
-import net.minecraft.util.Hand
-import net.minecraft.util.Identifier
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HudRenderEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.SlotClickEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.DurabilityBarEvent
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SHORT_NUMBER_FORMAT
-import moe.nea.firmament.util.TIME_PATTERN
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.extraAttributes
-import moe.nea.firmament.util.item.displayNameAccordingToNbt
-import moe.nea.firmament.util.item.loreAccordingToNbt
-import moe.nea.firmament.util.parseShortNumber
-import moe.nea.firmament.util.parseTimePattern
-import moe.nea.firmament.util.render.RenderCircleProgress
-import moe.nea.firmament.util.render.lerp
-import moe.nea.firmament.util.toShedaniel
-import moe.nea.firmament.util.unformattedString
-import moe.nea.firmament.util.useMatch
-
-object PickaxeAbility : FirmamentFeature {
- override val identifier: String
- get() = "pickaxe-info"
-
-
- object TConfig : ManagedConfig(identifier) {
- val cooldownEnabled by toggle("ability-cooldown") { true }
- val cooldownScale by integer("ability-scale", 16, 64) { 16 }
- val drillFuelBar by toggle("fuel-bar") { true }
- }
-
- var lobbyJoinTime = TimeMark.farPast()
- var lastUsage = mutableMapOf<String, TimeMark>()
- var abilityOverride: String? = null
- var defaultAbilityDurations = mutableMapOf<String, Duration>(
- "Mining Speed Boost" to 120.seconds,
- "Pickobulus" to 110.seconds,
- "Gemstone Infusion" to 140.seconds,
- "Hazardous Miner" to 140.seconds,
- "Maniac Miner" to 59.seconds,
- "Vein Seeker" to 60.seconds
- )
-
- override val config: ManagedConfig
- get() = TConfig
-
- fun getCooldownPercentage(name: String, cooldown: Duration): Double {
- val sinceLastUsage = lastUsage[name]?.passedTime() ?: Duration.INFINITE
- if (sinceLastUsage < cooldown)
- return sinceLastUsage / cooldown
- val sinceLobbyJoin = lobbyJoinTime.passedTime()
- val halfCooldown = cooldown / 2
- if (sinceLobbyJoin < halfCooldown) {
- return (sinceLobbyJoin / halfCooldown)
- }
- return 1.0
- }
-
- @Subscribe
- fun onSlotClick(it: SlotClickEvent) {
- if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
- val name = it.stack.displayNameAccordingToNbt?.unformattedString ?: return
- val cooldown = it.stack.loreAccordingToNbt.firstNotNullOfOrNull {
- cooldownPattern.useMatch(it.unformattedString) {
- parseTimePattern(group("cooldown"))
- }
- } ?: return
- defaultAbilityDurations[name] = cooldown
- }
- }
-
- @Subscribe
- fun onDurabilityBar(it: DurabilityBarEvent) {
- if (!TConfig.drillFuelBar) return
- val lore = it.item.loreAccordingToNbt
- if (lore.lastOrNull()?.unformattedString?.contains("DRILL") != true) return
- val maxFuel = lore.firstNotNullOfOrNull {
- fuelPattern.useMatch(it.unformattedString) {
- parseShortNumber(group("maxFuel"))
- }
- } ?: return
- val extra = it.item.extraAttributes
- if (!extra.contains("drill_fuel")) return
- val fuel = extra.getInt("drill_fuel")
- val percentage = fuel / maxFuel.toFloat()
- it.barOverride = DurabilityBarEvent.DurabilityBar(
- lerp(
- DyeColor.RED.toShedaniel(),
- DyeColor.GREEN.toShedaniel(),
- percentage
- ), percentage
- )
- }
-
- @Subscribe
- fun onChatMessage(it: ProcessChatEvent) {
- abilityUsePattern.useMatch(it.unformattedString) {
- lastUsage[group("name")] = TimeMark.now()
- }
- abilitySwitchPattern.useMatch(it.unformattedString) {
- abilityOverride = group("ability")
- }
- }
-
- @Subscribe
- fun onWorldReady(event: WorldReadyEvent) {
- lastUsage.clear()
- lobbyJoinTime = TimeMark.now()
- abilityOverride = null
- }
-
- val abilityUsePattern = Pattern.compile("You used your (?<name>.*) Pickaxe Ability!")
- val fuelPattern = Pattern.compile("Fuel: .*/(?<maxFuel>$SHORT_NUMBER_FORMAT)")
-
- data class PickaxeAbilityData(
- val name: String,
- val cooldown: Duration,
- )
-
- fun getCooldownFromLore(itemStack: ItemStack): PickaxeAbilityData? {
- val lore = itemStack.loreAccordingToNbt
- if (!lore.any { it.unformattedString.contains("Breaking Power") == true })
- return null
- val cooldown = lore.firstNotNullOfOrNull {
- cooldownPattern.useMatch(it.unformattedString) {
- parseTimePattern(group("cooldown"))
- }
- } ?: return null
- val name = lore.firstNotNullOfOrNull {
- abilityPattern.useMatch(it.unformattedString) {
- group("name")
- }
- } ?: return null
- return PickaxeAbilityData(name, cooldown)
- }
-
-
- val cooldownPattern = Pattern.compile("Cooldown: (?<cooldown>$TIME_PATTERN)")
- val abilityPattern = Pattern.compile("Ability: (?<name>.*) {2}RIGHT CLICK")
- val abilitySwitchPattern =
- Pattern.compile("You selected (?<ability>.*) as your Pickaxe Ability\\. This ability will apply to all of your pickaxes!")
-
-
- @Subscribe
- fun renderHud(event: HudRenderEvent) {
- if (!TConfig.cooldownEnabled) return
- var ability = getCooldownFromLore(MC.player?.getStackInHand(Hand.MAIN_HAND) ?: return) ?: return
- defaultAbilityDurations[ability.name] = ability.cooldown
- val ao = abilityOverride
- if (ao != ability.name && ao != null) {
- ability = PickaxeAbilityData(ao, defaultAbilityDurations[ao] ?: 120.seconds)
- }
- event.context.matrices.push()
- event.context.matrices.translate(MC.window.scaledWidth / 2F, MC.window.scaledHeight / 2F, 0F)
- event.context.matrices.scale(TConfig.cooldownScale.toFloat(), TConfig.cooldownScale.toFloat(), 1F)
- RenderCircleProgress.renderCircle(
- event.context, Identifier.of("firmament", "textures/gui/circle.png"),
- getCooldownPercentage(ability.name, ability.cooldown).toFloat(),
- 0f, 1f, 0f, 1f
- )
- event.context.matrices.pop()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
deleted file mode 100644
index f1bc7e5..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import moe.nea.jarvis.api.Point
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.text.Text
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.gui.hud.MoulConfigHud
-import moe.nea.firmament.util.BazaarPriceStrategy
-import moe.nea.firmament.util.FirmFormatters.formatCommas
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-import moe.nea.firmament.util.formattedString
-import moe.nea.firmament.util.parseIntWithComma
-import moe.nea.firmament.util.useMatch
-
-object PristineProfitTracker : FirmamentFeature {
- override val identifier: String
- get() = "pristine-profit"
-
- enum class GemstoneKind(
- val label: String,
- val flawedId: SkyblockId,
- ) {
- SAPPHIRE("Sapphire", SkyblockId("FLAWED_SAPPHIRE_GEM")),
- RUBY("Ruby", SkyblockId("FLAWED_RUBY_GEM")),
- AMETHYST("Amethyst", SkyblockId("FLAWED_AMETHYST_GEM")),
- AMBER("Amber", SkyblockId("FLAWED_AMBER_GEM")),
- TOPAZ("Topaz", SkyblockId("FLAWED_TOPAZ_GEM")),
- JADE("Jade", SkyblockId("FLAWED_JADE_GEM")),
- JASPER("Jasper", SkyblockId("FLAWED_JASPER_GEM")),
- OPAL("Opal", SkyblockId("FLAWED_OPAL_GEM")),
- }
-
- @Serializable
- data class Data(
- var maxMoneyPerSecond: Double = 1.0,
- var maxCollectionPerSecond: Double = 1.0,
- )
-
- object DConfig : ProfileSpecificDataHolder<Data>(serializer(), identifier, ::Data)
-
- override val config: ManagedConfig?
- get() = TConfig
-
- object TConfig : ManagedConfig(identifier) {
- val timeout by duration("timeout", 0.seconds, 120.seconds) { 30.seconds }
- val gui by position("position", 80, 30) { Point(0.05, 0.2) }
- }
-
- val sellingStrategy = BazaarPriceStrategy.SELL_ORDER
-
- val pristineRegex =
- "PRISTINE! You found . Flawed (?<kind>${
- GemstoneKind.entries.joinToString("|") { it.label }
- }) Gemstone x(?<count>[0-9,]+)!".toPattern()
-
- val collectionHistogram = Histogram<Double>(10000, 180.seconds)
- val moneyHistogram = Histogram<Double>(10000, 180.seconds)
-
- object ProfitHud : MoulConfigHud("pristine_profit", TConfig.gui) {
- @field:Bind
- var moneyCurrent: Double = 0.0
-
- @field:Bind
- var moneyMax: Double = 1.0
-
- @field:Bind
- var moneyText = ""
-
- @field:Bind
- var collectionCurrent = 0.0
-
- @field:Bind
- var collectionMax = 1.0
-
- @field:Bind
- var collectionText = ""
- override fun shouldRender(): Boolean = collectionHistogram.latestUpdate().passedTime() < TConfig.timeout
- }
-
- val SECONDS_PER_HOUR = 3600
- val ROUGHS_PER_FLAWED = 80
-
- fun updateUi() {
- val collectionPerSecond = collectionHistogram.averagePer({ it }, 1.seconds)
- val moneyPerSecond = moneyHistogram.averagePer({ it }, 1.seconds)
- if (collectionPerSecond == null || moneyPerSecond == null) return
- ProfitHud.collectionCurrent = collectionPerSecond
- ProfitHud.collectionText = Text.stringifiedTranslatable("firmament.pristine-profit.collection",
- formatCommas(collectionPerSecond * SECONDS_PER_HOUR,
- 1)).formattedString()
- ProfitHud.moneyCurrent = moneyPerSecond
- ProfitHud.moneyText = Text.stringifiedTranslatable("firmament.pristine-profit.money",
- formatCommas(moneyPerSecond * SECONDS_PER_HOUR, 1))
- .formattedString()
- val data = DConfig.data
- if (data != null) {
- if (data.maxCollectionPerSecond < collectionPerSecond && collectionHistogram.oldestUpdate()
- .passedTime() > 30.seconds
- ) {
- data.maxCollectionPerSecond = collectionPerSecond
- DConfig.markDirty()
- }
- if (data.maxMoneyPerSecond < moneyPerSecond && moneyHistogram.oldestUpdate().passedTime() > 30.seconds) {
- data.maxMoneyPerSecond = moneyPerSecond
- DConfig.markDirty()
- }
- ProfitHud.collectionMax = maxOf(data.maxCollectionPerSecond, collectionPerSecond)
- ProfitHud.moneyMax = maxOf(data.maxMoneyPerSecond, moneyPerSecond)
- }
- }
-
-
- @Subscribe
- fun onMessage(it: ProcessChatEvent) {
- pristineRegex.useMatch(it.unformattedString) {
- val gemstoneKind = GemstoneKind.valueOf(group("kind").uppercase())
- val flawedCount = parseIntWithComma(group("count"))
- val moneyAmount = sellingStrategy.getSellPrice(gemstoneKind.flawedId) * flawedCount
- moneyHistogram.record(moneyAmount)
- val collectionAmount = flawedCount * ROUGHS_PER_FLAWED
- collectionHistogram.record(collectionAmount.toDouble())
- updateUi()
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/notifications/Notifications.kt b/src/main/kotlin/moe/nea/firmament/features/notifications/Notifications.kt
deleted file mode 100644
index 8d912d1..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/notifications/Notifications.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-package moe.nea.firmament.features.notifications
-
-import moe.nea.firmament.features.FirmamentFeature
-
-object Notifications {
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt
deleted file mode 100644
index 4dd28df..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/AlwaysPredicate.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import net.minecraft.item.ItemStack
-
-object AlwaysPredicate : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return true
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- return AlwaysPredicate
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/AndPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/AndPredicate.kt
deleted file mode 100644
index 55a4f32..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/AndPredicate.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import net.minecraft.item.ItemStack
-
-class AndPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return children.all { it.test(stack) }
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- val children =
- (jsonElement as JsonArray)
- .flatMap {
- CustomModelOverrideParser.parsePredicates(it as JsonObject)
- }
- .toTypedArray()
- return AndPredicate(children)
- }
-
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedModelExtra.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedModelExtra.kt
deleted file mode 100644
index ae1f6d5..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedModelExtra.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import net.minecraft.client.render.model.BakedModel
-
-interface BakedModelExtra {
- fun getHeadModel_firmament(): BakedModel?
- fun setHeadModel_firmament(headModel: BakedModel?)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedOverrideData.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedOverrideData.kt
deleted file mode 100644
index c012883..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/BakedOverrideData.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-interface BakedOverrideData {
- fun getFirmamentOverrides(): Array<FirmamentModelPredicate>?
- fun setFirmamentOverrides(overrides: Array<FirmamentModelPredicate>?)
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt
deleted file mode 100644
index 18da54c..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt
+++ /dev/null
@@ -1,296 +0,0 @@
-@file:UseSerializers(BlockPosSerializer::class, IdentifierSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-import java.util.concurrent.CompletableFuture
-import net.fabricmc.loader.api.FabricLoader
-import kotlinx.serialization.ExperimentalSerializationApi
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
-import kotlinx.serialization.UseSerializers
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import kotlinx.serialization.json.JsonDecoder
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.serializer
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.block.Block
-import net.minecraft.block.BlockState
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.registry.RegistryKey
-import net.minecraft.registry.RegistryKeys
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.util.Identifier
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.compat.SodiumChunkReloader
-import moe.nea.firmament.events.BakeExtraModelsEvent
-import moe.nea.firmament.events.EarlyResourceReloadEvent
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.SkyblockServerUpdateEvent
-import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.json.BlockPosSerializer
-import moe.nea.firmament.util.json.SingletonSerializableList
-
-
-object CustomBlockTextures {
- @Serializable
- data class CustomBlockOverride(
- val modes: @Serializable(SingletonSerializableList::class) List<String>,
- val area: List<Area>? = null,
- val replacements: Map<Identifier, Replacement>,
- )
-
- @Serializable(with = Replacement.Serializer::class)
- data class Replacement(
- val block: Identifier,
- val sound: Identifier?,
- ) {
-
- @Transient
- val blockModelIdentifier get() = ModelIdentifier(block.withPrefixedPath("block/"), "firmament")
-
- @Transient
- val bakedModel: BakedModel by lazy(LazyThreadSafetyMode.NONE) {
- MC.instance.bakedModelManager.getModel(blockModelIdentifier)
- }
-
- @OptIn(ExperimentalSerializationApi::class)
- @kotlinx.serialization.Serializer(Replacement::class)
- object DefaultSerializer : KSerializer<Replacement>
-
- object Serializer : KSerializer<Replacement> {
- val delegate = serializer<JsonElement>()
- override val descriptor: SerialDescriptor
- get() = delegate.descriptor
-
- override fun deserialize(decoder: Decoder): Replacement {
- val jsonElement = decoder.decodeSerializableValue(delegate)
- if (jsonElement is JsonPrimitive) {
- require(jsonElement.isString)
- return Replacement(Identifier.tryParse(jsonElement.content)!!, null)
- }
- return (decoder as JsonDecoder).json.decodeFromJsonElement(DefaultSerializer, jsonElement)
- }
-
- override fun serialize(encoder: Encoder, value: Replacement) {
- encoder.encodeSerializableValue(DefaultSerializer, value)
- }
- }
- }
-
- @Serializable
- data class Area(
- val min: BlockPos,
- val max: BlockPos,
- ) {
- @Transient
- val realMin = BlockPos(
- minOf(min.x, max.x),
- minOf(min.y, max.y),
- minOf(min.z, max.z),
- )
-
- @Transient
- val realMax = BlockPos(
- maxOf(min.x, max.x),
- maxOf(min.y, max.y),
- maxOf(min.z, max.z),
- )
-
- fun roughJoin(other: Area): Area {
- return Area(
- BlockPos(
- minOf(realMin.x, other.realMin.x),
- minOf(realMin.y, other.realMin.y),
- minOf(realMin.z, other.realMin.z),
- ),
- BlockPos(
- maxOf(realMax.x, other.realMax.x),
- maxOf(realMax.y, other.realMax.y),
- maxOf(realMax.z, other.realMax.z),
- )
- )
- }
-
- fun contains(blockPos: BlockPos): Boolean {
- return (blockPos.x in realMin.x..realMax.x) &&
- (blockPos.y in realMin.y..realMax.y) &&
- (blockPos.z in realMin.z..realMax.z)
- }
- }
-
- data class LocationReplacements(
- val lookup: Map<Block, List<BlockReplacement>>
- )
-
- data class BlockReplacement(
- val checks: List<Area>?,
- val replacement: Replacement,
- ) {
- val roughCheck by lazy(LazyThreadSafetyMode.NONE) {
- if (checks == null || checks.size < 3) return@lazy null
- checks.reduce { acc, next -> acc.roughJoin(next) }
- }
- }
-
- data class BakedReplacements(val data: Map<SkyBlockIsland, LocationReplacements>)
-
- var allLocationReplacements: BakedReplacements = BakedReplacements(mapOf())
- var currentIslandReplacements: LocationReplacements? = null
-
- fun refreshReplacements() {
- val location = SBData.skyblockLocation
- val replacements =
- if (CustomSkyBlockTextures.TConfig.enableBlockOverrides) location?.let(allLocationReplacements.data::get)
- else null
- val lastReplacements = currentIslandReplacements
- currentIslandReplacements = replacements
- if (lastReplacements != replacements) {
- MC.nextTick {
- MC.worldRenderer.chunks?.chunks?.forEach {
- // false schedules rebuilds outside a 27 block radius to happen async
- it.scheduleRebuild(false)
- }
- sodiumReloadTask?.run()
- }
- }
- }
-
- private val sodiumReloadTask = runCatching {
- SodiumChunkReloader()
- }.getOrElse {
- if (FabricLoader.getInstance().isModLoaded("sodium"))
- logger.error("Could not create sodium chunk reloader")
- null
- }
-
-
- fun matchesPosition(replacement: BlockReplacement, blockPos: BlockPos?): Boolean {
- if (blockPos == null) return true
- val rc = replacement.roughCheck
- if (rc != null && !rc.contains(blockPos)) return false
- val areas = replacement.checks
- if (areas != null && !areas.any { it.contains(blockPos) }) return false
- return true
- }
-
- @JvmStatic
- fun getReplacementModel(block: BlockState, blockPos: BlockPos?): BakedModel? {
- return getReplacement(block, blockPos)?.bakedModel
- }
-
- @JvmStatic
- fun getReplacement(block: BlockState, blockPos: BlockPos?): Replacement? {
- if (isInFallback() && blockPos == null) return null
- val replacements = currentIslandReplacements?.lookup?.get(block.block) ?: return null
- for (replacement in replacements) {
- if (replacement.checks == null || matchesPosition(replacement, blockPos))
- return replacement.replacement
- }
- return null
- }
-
-
- @Subscribe
- fun onLocation(event: SkyblockServerUpdateEvent) {
- refreshReplacements()
- }
-
- @Volatile
- var preparationFuture: CompletableFuture<BakedReplacements> = CompletableFuture.completedFuture(BakedReplacements(
- mapOf()))
-
- val insideFallbackCall = ThreadLocal.withInitial { 0 }
-
- @JvmStatic
- fun enterFallbackCall() {
- insideFallbackCall.set(insideFallbackCall.get() + 1)
- }
-
- fun isInFallback() = insideFallbackCall.get() > 0
-
- @JvmStatic
- fun exitFallbackCall() {
- insideFallbackCall.set(insideFallbackCall.get() - 1)
- }
-
- @Subscribe
- fun onEarlyReload(event: EarlyResourceReloadEvent) {
- preparationFuture = CompletableFuture
- .supplyAsync(
- { prepare(event.resourceManager) }, event.preparationExecutor)
- }
-
- @Subscribe
- fun bakeExtraModels(event: BakeExtraModelsEvent) {
- preparationFuture.join().data.values
- .flatMap { it.lookup.values }
- .flatten()
- .mapTo(mutableSetOf()) { it.replacement.blockModelIdentifier }
- .forEach { event.addNonItemModel(it) }
- }
-
- private fun prepare(manager: ResourceManager): BakedReplacements {
- val resources = manager.findResources("overrides/blocks") {
- it.namespace == "firmskyblock" && it.path.endsWith(".json")
- }
- val map = mutableMapOf<SkyBlockIsland, MutableMap<Block, MutableList<BlockReplacement>>>()
- for ((file, resource) in resources) {
- val json =
- Firmament.tryDecodeJsonFromStream<CustomBlockOverride>(resource.inputStream)
- .getOrElse { ex ->
- logger.error("Failed to load block texture override at $file", ex)
- continue
- }
- for (mode in json.modes) {
- val island = SkyBlockIsland.forMode(mode)
- val islandMpa = map.getOrPut(island, ::mutableMapOf)
- for ((blockId, replacement) in json.replacements) {
- val block = MC.defaultRegistries.getWrapperOrThrow(RegistryKeys.BLOCK)
- .getOptional(RegistryKey.of(RegistryKeys.BLOCK, blockId))
- .getOrNull()
- if (block == null) {
- logger.error("Failed to load block texture override at ${file}: unknown block '$blockId'")
- continue
- }
- val replacements = islandMpa.getOrPut(block.value(), ::mutableListOf)
- replacements.add(BlockReplacement(json.area, replacement))
- }
- }
- }
-
- return BakedReplacements(map.mapValues { LocationReplacements(it.value) })
- }
-
- @JvmStatic
- fun patchIndigo(orig: BakedModel, pos: BlockPos, state: BlockState): BakedModel {
- return getReplacementModel(state, pos) ?: orig
- }
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- event.resourceManager.registerReloader(object :
- SinglePreparationResourceReloader<BakedReplacements>() {
- override fun prepare(manager: ResourceManager, profiler: Profiler): BakedReplacements {
- return preparationFuture.join()
- }
-
- override fun apply(prepared: BakedReplacements, manager: ResourceManager, profiler: Profiler?) {
- allLocationReplacements = prepared
- refreshReplacements()
- }
- })
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt
deleted file mode 100644
index 23577ee..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-
-@file:UseSerializers(IdentifierSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
-import kotlinx.serialization.UseSerializers
-import net.minecraft.item.ArmorMaterial
-import net.minecraft.item.ItemStack
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.util.Identifier
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.IdentityCharacteristics
-import moe.nea.firmament.util.computeNullableFunction
-import moe.nea.firmament.util.skyBlockId
-
-object CustomGlobalArmorOverrides : SubscriptionOwner {
- @Serializable
- data class ArmorOverride(
- @SerialName("item_ids")
- val itemIds: List<String>,
- val layers: List<ArmorOverrideLayer>,
- val overrides: List<ArmorOverrideOverride> = listOf(),
- ) {
- @Transient
- val bakedLayers = bakeLayers(layers)
- }
-
- fun bakeLayers(layers: List<ArmorOverrideLayer>): List<ArmorMaterial.Layer> {
- return layers.map { ArmorMaterial.Layer(it.identifier, it.suffix, it.tint) }
- }
-
- @Serializable
- data class ArmorOverrideLayer(
- val tint: Boolean = false,
- val identifier: Identifier,
- val suffix: String = "",
- )
-
- @Serializable
- data class ArmorOverrideOverride(
- val predicate: FirmamentModelPredicate,
- val layers: List<ArmorOverrideLayer>,
- ) {
- @Transient
- val bakedLayers = bakeLayers(layers)
- }
-
- override val delegateFeature: FirmamentFeature
- get() = CustomSkyBlockTextures
-
- val overrideCache = mutableMapOf<IdentityCharacteristics<ItemStack>, Any>()
-
- @JvmStatic
- fun overrideArmor(stack: ItemStack): List<ArmorMaterial.Layer>? {
- if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return null
- return overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) {
- val id = stack.skyBlockId ?: return@computeNullableFunction null
- val override = overrides[id.neuItem] ?: return@computeNullableFunction null
- for (suboverride in override.overrides) {
- if (suboverride.predicate.test(stack)) {
- return@computeNullableFunction suboverride.bakedLayers
- }
- }
- return@computeNullableFunction override.bakedLayers
- }
- }
-
- var overrides: Map<String, ArmorOverride> = mapOf()
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- event.resourceManager.registerReloader(object :
- SinglePreparationResourceReloader<Map<String, ArmorOverride>>() {
- override fun prepare(manager: ResourceManager, profiler: Profiler): Map<String, ArmorOverride> {
- val overrideFiles = manager.findResources("overrides/armor_models") {
- it.namespace == "firmskyblock" && it.path.endsWith(".json")
- }
- val overrides = overrideFiles.mapNotNull {
- Firmament.tryDecodeJsonFromStream<ArmorOverride>(it.value.inputStream).getOrElse { ex ->
- logger.error("Failed to load armor texture override at ${it.key}", ex)
- null
- }
- }
- val associatedMap = overrides.flatMap { obj -> obj.itemIds.map { it to obj } }
- .toMap()
- return associatedMap
- }
-
- override fun apply(prepared: Map<String, ArmorOverride>, manager: ResourceManager, profiler: Profiler) {
- overrides = prepared
- }
- })
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt
deleted file mode 100644
index d64c844..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt
+++ /dev/null
@@ -1,167 +0,0 @@
-
-@file:UseSerializers(IdentifierSerializer::class, CustomModelOverrideParser.FirmamentRootPredicateSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-
-import java.util.concurrent.CompletableFuture
-import org.slf4j.LoggerFactory
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.client.render.item.ItemModels
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.item.ItemStack
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.BakeExtraModelsEvent
-import moe.nea.firmament.events.EarlyResourceReloadEvent
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.ScreenChangeEvent
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.IdentityCharacteristics
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.computeNullableFunction
-import moe.nea.firmament.util.json.SingletonSerializableList
-import moe.nea.firmament.util.runNull
-
-object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalTextures.CustomGuiTextureOverride>(),
- SubscriptionOwner {
- override val delegateFeature: FirmamentFeature
- get() = CustomSkyBlockTextures
-
- class CustomGuiTextureOverride(
- val classes: List<ItemOverrideCollection>
- )
-
- @Serializable
- data class GlobalItemOverride(
- val screen: @Serializable(SingletonSerializableList::class) List<Identifier>,
- val model: Identifier,
- val predicate: FirmamentModelPredicate,
- )
-
- @Serializable
- data class ScreenFilter(
- val title: StringMatcher,
- )
-
- data class ItemOverrideCollection(
- val screenFilter: ScreenFilter,
- val overrides: List<GlobalItemOverride>,
- )
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- MC.resourceManager.registerReloader(this)
- }
-
- @Subscribe
- fun onEarlyReload(event: EarlyResourceReloadEvent) {
- preparationFuture = CompletableFuture
- .supplyAsync(
- {
- prepare(event.resourceManager)
- }, event.preparationExecutor)
- }
-
- @Subscribe
- fun onBakeModels(event: BakeExtraModelsEvent) {
- for (guiClassOverride in preparationFuture.join().classes) {
- for (override in guiClassOverride.overrides) {
- event.addItemModel(ModelIdentifier(override.model, "inventory"))
- }
- }
- }
-
- @Volatile
- var preparationFuture: CompletableFuture<CustomGuiTextureOverride> = CompletableFuture.completedFuture(
- CustomGuiTextureOverride(listOf()))
-
- override fun prepare(manager: ResourceManager?, profiler: Profiler?): CustomGuiTextureOverride {
- return preparationFuture.join()
- }
-
- override fun apply(prepared: CustomGuiTextureOverride, manager: ResourceManager?, profiler: Profiler?) {
- this.guiClassOverrides = prepared
- }
-
- val logger = LoggerFactory.getLogger(CustomGlobalTextures::class.java)
- fun prepare(manager: ResourceManager): CustomGuiTextureOverride {
- val overrideResources =
- manager.findResources("overrides/item") { it.namespace == "firmskyblock" && it.path.endsWith(".json") }
- .mapNotNull {
- Firmament.tryDecodeJsonFromStream<GlobalItemOverride>(it.value.inputStream).getOrElse { ex ->
- logger.error("Failed to load global item override at ${it.key}", ex)
- null
- }
- }
-
- val byGuiClass = overrideResources.flatMap { override -> override.screen.toSet().map { it to override } }
- .groupBy { it.first }
- val guiClasses = byGuiClass.entries
- .mapNotNull {
- val key = it.key
- val guiClassResource =
- manager.getResource(Identifier.of(key.namespace, "filters/screen/${key.path}.json"))
- .getOrNull()
- ?: return@mapNotNull runNull {
- logger.error("Failed to locate screen filter at $key")
- }
- val screenFilter =
- Firmament.tryDecodeJsonFromStream<ScreenFilter>(guiClassResource.inputStream)
- .getOrElse { ex ->
- logger.error("Failed to load screen filter at $key", ex)
- return@mapNotNull null
- }
- ItemOverrideCollection(screenFilter, it.value.map { it.second })
- }
- logger.info("Loaded ${overrideResources.size} global item overrides")
- return CustomGuiTextureOverride(guiClasses)
- }
-
- var guiClassOverrides = CustomGuiTextureOverride(listOf())
-
- var matchingOverrides: Set<ItemOverrideCollection> = setOf()
-
- @Subscribe
- fun onOpenGui(event: ScreenChangeEvent) {
- val newTitle = event.new?.title ?: Text.empty()
- matchingOverrides = guiClassOverrides.classes
- .filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) }
- }
-
- val overrideCache = mutableMapOf<IdentityCharacteristics<ItemStack>, Any>()
-
- @JvmStatic
- fun replaceGlobalModel(
- models: ItemModels,
- stack: ItemStack,
- cir: CallbackInfoReturnable<BakedModel>
- ) {
- val value = overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) {
- for (guiClassOverride in matchingOverrides) {
- for (override in guiClassOverride.overrides) {
- if (override.predicate.test(stack)) {
- return@computeNullableFunction models.modelManager.getModel(
- ModelIdentifier(override.model, "inventory"))
- }
- }
- }
- null
- }
- if (value != null)
- cir.returnValue = value
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
deleted file mode 100644
index a4e7c02..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonObject
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import net.minecraft.item.ItemStack
-import net.minecraft.util.Identifier
-
-object CustomModelOverrideParser {
- object FirmamentRootPredicateSerializer : KSerializer<FirmamentModelPredicate> {
- val delegateSerializer = kotlinx.serialization.json.JsonObject.serializer()
- override val descriptor: SerialDescriptor
- get() = SerialDescriptor("FirmamentModelRootPredicate", delegateSerializer.descriptor)
-
- override fun deserialize(decoder: Decoder): FirmamentModelPredicate {
- val json = decoder.decodeSerializableValue(delegateSerializer).intoGson() as JsonObject
- return AndPredicate(parsePredicates(json).toTypedArray())
- }
-
- override fun serialize(encoder: Encoder, value: FirmamentModelPredicate) {
- TODO("Cannot serialize firmament predicates")
- }
- }
-
- val predicateParsers = mutableMapOf<Identifier, FirmamentModelPredicateParser>()
-
-
- fun registerPredicateParser(name: String, parser: FirmamentModelPredicateParser) {
- predicateParsers[Identifier.of("firmament", name)] = parser
- }
-
- init {
- registerPredicateParser("display_name", DisplayNamePredicate.Parser)
- registerPredicateParser("lore", LorePredicate.Parser)
- registerPredicateParser("all", AndPredicate.Parser)
- registerPredicateParser("any", OrPredicate.Parser)
- registerPredicateParser("not", NotPredicate.Parser)
- registerPredicateParser("item", ItemPredicate.Parser)
- registerPredicateParser("extra_attributes", ExtraAttributesPredicate.Parser)
- registerPredicateParser("pet", PetPredicate.Parser)
- }
-
- private val neverPredicate = listOf(
- object : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return false
- }
- }
- )
-
- fun parsePredicates(predicates: JsonObject): List<FirmamentModelPredicate> {
- val parsedPredicates = mutableListOf<FirmamentModelPredicate>()
- for (predicateName in predicates.keySet()) {
- if (!predicateName.startsWith("firmament:")) continue
- val identifier = Identifier.of(predicateName)
- val parser = predicateParsers[identifier] ?: return neverPredicate
- val parsedPredicate = parser.parse(predicates[predicateName]) ?: return neverPredicate
- parsedPredicates.add(parsedPredicate)
- }
- return parsedPredicates
- }
-
- @JvmStatic
- fun parseCustomModelOverrides(jsonObject: JsonObject): Array<FirmamentModelPredicate>? {
- val predicates = (jsonObject["predicate"] as? JsonObject) ?: return null
- val parsedPredicates = parsePredicates(predicates)
- if (parsedPredicates.isEmpty())
- return null
- return parsedPredicates.toTypedArray()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt
deleted file mode 100644
index dec6046..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt
+++ /dev/null
@@ -1,114 +0,0 @@
-package moe.nea.firmament.features.texturepack
-
-import com.mojang.authlib.minecraft.MinecraftProfileTexture
-import com.mojang.authlib.properties.Property
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
-import net.minecraft.block.SkullBlock
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.component.type.ProfileComponent
-import net.minecraft.util.Identifier
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.BakeExtraModelsEvent
-import moe.nea.firmament.events.CustomItemModelEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.IdentityCharacteristics
-import moe.nea.firmament.util.item.decodeProfileTextureProperty
-import moe.nea.firmament.util.skyBlockId
-
-object CustomSkyBlockTextures : FirmamentFeature {
- override val identifier: String
- get() = "custom-skyblock-textures"
-
- object TConfig : ManagedConfig(identifier) {
- val enabled by toggle("enabled") { true }
- val skullsEnabled by toggle("skulls-enabled") { true }
- val cacheDuration by integer("cache-duration", 0, 20) { 1 }
- val enableModelOverrides by toggle("model-overrides") { true }
- val enableArmorOverrides by toggle("armor-overrides") { true }
- val enableBlockOverrides by toggle("block-overrides") { true }
- }
-
- override val config: ManagedConfig
- get() = TConfig
-
- @Subscribe
- fun onTick(it: TickEvent) {
- if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) {
- // TODO: unify all of those caches somehow
- CustomItemModelEvent.clearCache()
- skullTextureCache.clear()
- CustomGlobalTextures.overrideCache.clear()
- CustomGlobalArmorOverrides.overrideCache.clear()
- }
- }
-
- @Subscribe
- fun bakeCustomFirmModels(event: BakeExtraModelsEvent) {
- val resources =
- MinecraftClient.getInstance().resourceManager.findResources("models/item"
- ) { it: Identifier ->
- "firmskyblock" == it.namespace && it.path
- .endsWith(".json")
- }
- for (identifier in resources.keys) {
- val modelId = ModelIdentifier.ofInventoryVariant(
- Identifier.of(
- "firmskyblock",
- identifier.path.substring(
- "models/item/".length,
- identifier.path.length - ".json".length),
- ))
- event.addItemModel(modelId)
- }
- }
-
- @Subscribe
- fun onCustomModelId(it: CustomItemModelEvent) {
- if (!TConfig.enabled) return
- val id = it.itemStack.skyBlockId ?: return
- it.overrideModel = ModelIdentifier.ofInventoryVariant(Identifier.of("firmskyblock", id.identifier.path))
- }
-
- private val skullTextureCache = mutableMapOf<IdentityCharacteristics<ProfileComponent>, Any>()
- private val sentinelPresentInvalid = Object()
-
- private val mcUrlRegex = "https?://textures.minecraft.net/texture/([a-fA-F0-9]+)".toRegex()
-
- fun getSkullId(textureProperty: Property): String? {
- val texture = decodeProfileTextureProperty(textureProperty) ?: return null
- val textureUrl =
- texture.textures[MinecraftProfileTexture.Type.SKIN]?.url ?: return null
- val mcUrlData = mcUrlRegex.matchEntire(textureUrl) ?: return null
- return mcUrlData.groupValues[1]
- }
-
- fun getSkullTexture(profile: ProfileComponent): Identifier? {
- val id = getSkullId(profile.properties["textures"].firstOrNull() ?: return null) ?: return null
- return Identifier.of("firmskyblock", "textures/placedskull/$id.png")
- }
-
- fun modifySkullTexture(
- type: SkullBlock.SkullType?,
- component: ProfileComponent?,
- cir: CallbackInfoReturnable<RenderLayer>
- ) {
- if (type != SkullBlock.Type.PLAYER) return
- if (!TConfig.skullsEnabled) return
- if (component == null) return
- val ic = IdentityCharacteristics(component)
-
- val n = skullTextureCache.getOrPut(ic) {
- val id = getSkullTexture(component) ?: return@getOrPut sentinelPresentInvalid
- if (!MinecraftClient.getInstance().resourceManager.getResource(id).isPresent) {
- return@getOrPut sentinelPresentInvalid
- }
- return@getOrPut id
- }
- if (n === sentinelPresentInvalid) return
- cir.returnValue = RenderLayer.getEntityTranslucent(n as Identifier)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/DisplayNamePredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/DisplayNamePredicate.kt
deleted file mode 100644
index c89931e..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/DisplayNamePredicate.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NbtElement
-import net.minecraft.nbt.NbtString
-import moe.nea.firmament.util.item.displayNameAccordingToNbt
-import moe.nea.firmament.util.item.loreAccordingToNbt
-
-data class DisplayNamePredicate(val stringMatcher: StringMatcher) : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- val display = stack.displayNameAccordingToNbt
- return stringMatcher.matches(display)
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- return DisplayNamePredicate(StringMatcher.parse(jsonElement))
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/ExtraAttributesPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/ExtraAttributesPredicate.kt
deleted file mode 100644
index 4114f45..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/ExtraAttributesPredicate.kt
+++ /dev/null
@@ -1,268 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import com.google.gson.JsonPrimitive
-import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NbtByte
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.nbt.NbtDouble
-import net.minecraft.nbt.NbtElement
-import net.minecraft.nbt.NbtFloat
-import net.minecraft.nbt.NbtInt
-import net.minecraft.nbt.NbtList
-import net.minecraft.nbt.NbtLong
-import net.minecraft.nbt.NbtShort
-import net.minecraft.nbt.NbtString
-import moe.nea.firmament.util.extraAttributes
-
-fun interface NbtMatcher {
- fun matches(nbt: NbtElement): Boolean
-
- object Parser {
- fun parse(jsonElement: JsonElement): NbtMatcher? {
- if (jsonElement is JsonPrimitive) {
- if (jsonElement.isString) {
- val string = jsonElement.asString
- return MatchStringExact(string)
- }
- if (jsonElement.isNumber) {
- return MatchNumberExact(jsonElement.asLong) //TODO: parse generic number
- }
- }
- if (jsonElement is JsonObject) {
- var encounteredParser: NbtMatcher? = null
- for (entry in ExclusiveParserType.entries) {
- val data = jsonElement[entry.key] ?: continue
- if (encounteredParser != null) {
- // TODO: warn
- return null
- }
- encounteredParser = entry.parse(data) ?: return null
- }
- return encounteredParser
- }
- return null
- }
-
- enum class ExclusiveParserType(val key: String) {
- STRING("string") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return MatchString(StringMatcher.parse(element))
- }
- },
- INT("int") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asInt },
- { (it as? NbtInt)?.intValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- FLOAT("float") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asFloat },
- { (it as? NbtFloat)?.floatValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- DOUBLE("double") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asDouble },
- { (it as? NbtDouble)?.doubleValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- LONG("long") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asLong },
- { (it as? NbtLong)?.longValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- SHORT("short") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asShort },
- { (it as? NbtShort)?.shortValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- BYTE("byte") {
- override fun parse(element: JsonElement): NbtMatcher? {
- return parseGenericNumber(element,
- { it.asByte },
- { (it as? NbtByte)?.byteValue() },
- { a, b ->
- if (a == b) Comparison.EQUAL
- else if (a < b) Comparison.LESS_THAN
- else Comparison.GREATER
- })
- }
- },
- ;
-
- abstract fun parse(element: JsonElement): NbtMatcher?
- }
-
- enum class Comparison {
- LESS_THAN, EQUAL, GREATER
- }
-
- inline fun <T : Any> parseGenericNumber(
- jsonElement: JsonElement,
- primitiveExtractor: (JsonPrimitive) -> T?,
- crossinline nbtExtractor: (NbtElement) -> T?,
- crossinline compare: (T, T) -> Comparison
- ): NbtMatcher? {
- if (jsonElement is JsonPrimitive) {
- val expected = primitiveExtractor(jsonElement) ?: return null
- return NbtMatcher {
- val actual = nbtExtractor(it) ?: return@NbtMatcher false
- compare(actual, expected) == Comparison.EQUAL
- }
- }
- if (jsonElement is JsonObject) {
- val minElement = jsonElement.getAsJsonPrimitive("min")
- val min = if (minElement != null) primitiveExtractor(minElement) ?: return null else null
- val minExclusive = jsonElement.get("minExclusive")?.asBoolean ?: false
- val maxElement = jsonElement.getAsJsonPrimitive("max")
- val max = if (maxElement != null) primitiveExtractor(maxElement) ?: return null else null
- val maxExclusive = jsonElement.get("maxExclusive")?.asBoolean ?: true
- if (min == null && max == null) return null
- return NbtMatcher {
- val actual = nbtExtractor(it) ?: return@NbtMatcher false
- if (max != null) {
- val comp = compare(actual, max)
- if (comp == Comparison.GREATER) return@NbtMatcher false
- if (comp == Comparison.EQUAL && maxExclusive) return@NbtMatcher false
- }
- if (min != null) {
- val comp = compare(actual, min)
- if (comp == Comparison.LESS_THAN) return@NbtMatcher false
- if (comp == Comparison.EQUAL && minExclusive) return@NbtMatcher false
- }
- return@NbtMatcher true
- }
- }
- return null
-
- }
- }
-
- class MatchNumberExact(val number: Long) : NbtMatcher {
- override fun matches(nbt: NbtElement): Boolean {
- return when (nbt) {
- is NbtByte -> nbt.byteValue().toLong() == number
- is NbtInt -> nbt.intValue().toLong() == number
- is NbtShort -> nbt.shortValue().toLong() == number
- is NbtLong -> nbt.longValue().toLong() == number
- else -> false
- }
- }
-
- }
-
- class MatchStringExact(val string: String) : NbtMatcher {
- override fun matches(nbt: NbtElement): Boolean {
- return nbt is NbtString && nbt.asString() == string
- }
-
- override fun toString(): String {
- return "MatchNbtStringExactly($string)"
- }
- }
-
- class MatchString(val string: StringMatcher) : NbtMatcher {
- override fun matches(nbt: NbtElement): Boolean {
- return nbt is NbtString && string.matches(nbt.asString())
- }
-
- override fun toString(): String {
- return "MatchNbtString($string)"
- }
- }
-}
-
-data class ExtraAttributesPredicate(
- val path: NbtPrism,
- val matcher: NbtMatcher,
-) : FirmamentModelPredicate {
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? {
- if (jsonElement !is JsonObject) return null
- val path = jsonElement.get("path") ?: return null
- val pathSegments = if (path is JsonArray) {
- path.map { (it as JsonPrimitive).asString }
- } else if (path is JsonPrimitive && path.isString) {
- path.asString.split(".")
- } else return null
- val matcher = NbtMatcher.Parser.parse(jsonElement.get("match") ?: jsonElement)
- ?: return null
- return ExtraAttributesPredicate(NbtPrism(pathSegments), matcher)
- }
- }
-
- override fun test(stack: ItemStack): Boolean {
- return path.access(stack.extraAttributes)
- .any { matcher.matches(it) }
- }
-}
-
-class NbtPrism(val path: List<String>) {
- override fun toString(): String {
- return "Prism($path)"
- }
- fun access(root: NbtElement): Collection<NbtElement> {
- var rootSet = mutableListOf(root)
- var switch = mutableListOf<NbtElement>()
- for (pathSegment in path) {
- if (pathSegment == ".") continue
- for (element in rootSet) {
- if (element is NbtList) {
- if (pathSegment == "*")
- switch.addAll(element)
- val index = pathSegment.toIntOrNull() ?: continue
- if (index !in element.indices) continue
- switch.add(element[index])
- }
- if (element is NbtCompound) {
- if (pathSegment == "*")
- element.keys.mapTo(switch) { element.get(it)!! }
- switch.add(element.get(pathSegment) ?: continue)
- }
- }
- val temp = switch
- switch = rootSet
- rootSet = temp
- switch.clear()
- }
- return rootSet
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt
deleted file mode 100644
index d11fec0..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import net.minecraft.item.ItemStack
-
-interface FirmamentModelPredicate {
- fun test(stack: ItemStack): Boolean
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt
deleted file mode 100644
index 3ed0c67..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-
-interface FirmamentModelPredicateParser {
- fun parse(jsonElement: JsonElement): FirmamentModelPredicate?
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/ItemPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/ItemPredicate.kt
deleted file mode 100644
index 4302b53..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/ItemPredicate.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import com.google.gson.JsonPrimitive
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.registry.RegistryKey
-import net.minecraft.registry.RegistryKeys
-import net.minecraft.util.Identifier
-import moe.nea.firmament.util.MC
-
-class ItemPredicate(
- val item: Item
-) : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return stack.item == item
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): ItemPredicate? {
- if (jsonElement is JsonPrimitive && jsonElement.isString) {
- val itemKey = RegistryKey.of(RegistryKeys.ITEM,
- Identifier.tryParse(jsonElement.asString)
- ?: return null)
- return ItemPredicate(MC.defaultItems.getOptional(itemKey).getOrNull()?.value() ?: return null)
- }
- return null
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/JsonUnbakedModelFirmExtra.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/JsonUnbakedModelFirmExtra.kt
deleted file mode 100644
index ab9e27d..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/JsonUnbakedModelFirmExtra.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import net.minecraft.util.Identifier
-
-interface JsonUnbakedModelFirmExtra {
-
- fun setHeadModel_firmament(identifier: Identifier?)
- fun getHeadModel_firmament(): Identifier?
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/LorePredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/LorePredicate.kt
deleted file mode 100644
index 13e3974..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/LorePredicate.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import net.minecraft.item.ItemStack
-import moe.nea.firmament.util.item.loreAccordingToNbt
-
-class LorePredicate(val matcher: StringMatcher) : FirmamentModelPredicate {
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- return LorePredicate(StringMatcher.parse(jsonElement))
- }
- }
-
- override fun test(stack: ItemStack): Boolean {
- val lore = stack.loreAccordingToNbt
- return lore.any { matcher.matches(it) }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideData.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideData.kt
deleted file mode 100644
index 1585bd7..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideData.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-interface ModelOverrideData {
- fun getFirmamentOverrides(): Array<FirmamentModelPredicate>?
- fun setFirmamentOverrides(overrides: Array<FirmamentModelPredicate>?)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideFilterSet.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideFilterSet.kt
deleted file mode 100644
index 4ef8d06..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/ModelOverrideFilterSet.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import moe.nea.firmament.util.filter.IteratorFilterSet
-
-class ModelOverrideFilterSet(original: java.util.Set<Map.Entry<String, JsonElement>>) :
- IteratorFilterSet<Map.Entry<String, JsonElement>>(original) {
- companion object {
- @JvmStatic
- fun createFilterSet(set: java.util.Set<*>): java.util.Set<*> {
- return ModelOverrideFilterSet(set as java.util.Set<Map.Entry<String, JsonElement>>) as java.util.Set<*>
- }
- }
-
- override fun shouldKeepElement(element: Map.Entry<String, JsonElement>): Boolean {
- return !element.key.startsWith("firmament:")
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt
deleted file mode 100644
index ecd67c3..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/NotPredicate.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import net.minecraft.item.ItemStack
-
-class NotPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return children.none { it.test(stack) }
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- return NotPredicate(CustomModelOverrideParser.parsePredicates(jsonElement as JsonObject).toTypedArray())
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/NumberMatcher.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/NumberMatcher.kt
deleted file mode 100644
index 7e6665f..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/NumberMatcher.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import com.google.gson.JsonPrimitive
-import moe.nea.firmament.util.useMatch
-
-abstract class NumberMatcher {
- abstract fun test(number: Number): Boolean
-
-
- companion object {
- fun parse(jsonElement: JsonElement): NumberMatcher? {
- if (jsonElement is JsonPrimitive) {
- if (jsonElement.isString) {
- val string = jsonElement.asString
- return parseRange(string) ?: parseOperator(string)
- }
- if (jsonElement.isNumber) {
- val number = jsonElement.asNumber
- val hasDecimals = (number.toString().contains("."))
- return MatchNumberExact(if (hasDecimals) number.toLong() else number.toDouble())
- }
- }
- return null
- }
-
- private val intervalSpec =
- "(?<beginningOpen>[\\[\\(])(?<beginning>[0-9.]+)?,(?<ending>[0-9.]+)?(?<endingOpen>[\\]\\)])"
- .toPattern()
-
- fun parseRange(string: String): RangeMatcher? {
- intervalSpec.useMatch<Nothing>(string) {
- // Open in the set-theory sense, meaning does not include its end.
- val beginningOpen = group("beginningOpen") == "("
- val endingOpen = group("endingOpen") == ")"
- val beginning = group("beginning")?.toDouble()
- val ending = group("ending")?.toDouble()
- return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
- }
- return null
- }
-
- enum class Operator(val operator: String) {
- LESS("<") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult < 0
- }
- },
- LESS_EQUALS("<=") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult <= 0
- }
- },
- GREATER(">") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult > 0
- }
- },
- GREATER_EQUALS(">=") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult >= 0
- }
- },
- ;
-
- abstract fun matches(comparisonResult: Int): Boolean
- }
-
- private val operatorPattern = "(?<operator>${Operator.entries.joinToString("|") {it.operator}})(?<value>[0-9.]+)".toPattern()
-
- fun parseOperator(string: String): OperatorMatcher? {
- operatorPattern.useMatch<Nothing>(string) {
- val operatorName = group("operator")
- val operator = Operator.entries.find { it.operator == operatorName }!!
- val value = group("value").toDouble()
- return OperatorMatcher(operator, value)
- }
- return null
- }
-
- data class OperatorMatcher(val operator: Operator, val value: Double) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- return operator.matches(number.toDouble().compareTo(value))
- }
- }
-
-
- data class MatchNumberExact(val number: Number) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- return when (this.number) {
- is Double -> number.toDouble() == this.number.toDouble()
- else -> number.toLong() == this.number.toLong()
- }
- }
- }
-
- data class RangeMatcher(
- val beginning: Double?,
- val beginningInclusive: Boolean,
- val ending: Double?,
- val endingInclusive: Boolean,
- ) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- val value = number.toDouble()
- if (beginning != null) {
- if (beginningInclusive) {
- if (value < beginning) return false
- } else {
- if (value <= beginning) return false
- }
- }
- if (ending != null) {
- if (endingInclusive) {
- if (value > ending) return false
- } else {
- if (value >= ending) return false
- }
- }
- return true
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/OrPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/OrPredicate.kt
deleted file mode 100644
index 32f556b..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/OrPredicate.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import net.minecraft.item.ItemStack
-
-class OrPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
- override fun test(stack: ItemStack): Boolean {
- return children.any { it.test(stack) }
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate {
- val children =
- (jsonElement as JsonArray)
- .flatMap {
- CustomModelOverrideParser.parsePredicates(it as JsonObject)
- }
- .toTypedArray()
- return OrPredicate(children)
- }
-
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/PetPredicate.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/PetPredicate.kt
deleted file mode 100644
index 5e5d750..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/PetPredicate.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-import net.minecraft.item.ItemStack
-import moe.nea.firmament.repo.ExpLadders
-import moe.nea.firmament.util.petData
-
-class PetPredicate(
- val petId: StringMatcher?,
- val tier: RarityMatcher?,
- val exp: NumberMatcher?,
- val candyUsed: NumberMatcher?,
- val level: NumberMatcher?,
-) : FirmamentModelPredicate {
-
- override fun test(stack: ItemStack): Boolean {
- val petData = stack.petData ?: return false
- if (petId != null) {
- if (!petId.matches(petData.type)) return false
- }
- if (exp != null) {
- if (!exp.test(petData.exp)) return false
- }
- if (candyUsed != null) {
- if (!candyUsed.test(petData.candyUsed)) return false
- }
- if (tier != null) {
- if (!tier.match(petData.tier)) return false
- }
- val levelData by lazy(LazyThreadSafetyMode.NONE) {
- ExpLadders.getExpLadder(petData.type, petData.tier)
- .getPetLevel(petData.exp)
- }
- if (level != null) {
- if (!level.test(levelData.currentLevel)) return false
- }
- return true
- }
-
- object Parser : FirmamentModelPredicateParser {
- override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? {
- if (jsonElement.isJsonPrimitive) {
- return PetPredicate(StringMatcher.Equals(jsonElement.asString, false), null, null, null, null)
- }
- if (jsonElement !is JsonObject) return null
- val idMatcher = jsonElement["id"]?.let(StringMatcher::parse)
- val expMatcher = jsonElement["exp"]?.let(NumberMatcher::parse)
- val levelMatcher = jsonElement["level"]?.let(NumberMatcher::parse)
- val candyMatcher = jsonElement["candyUsed"]?.let(NumberMatcher::parse)
- val tierMatcher = jsonElement["tier"]?.let(RarityMatcher::parse)
- return PetPredicate(
- idMatcher,
- tierMatcher,
- expMatcher,
- candyMatcher,
- levelMatcher,
- )
- }
- }
-
- override fun toString(): String {
- return super.toString()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/RarityMatcher.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/RarityMatcher.kt
deleted file mode 100644
index 634a171..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/RarityMatcher.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonElement
-import io.github.moulberry.repo.data.Rarity
-import moe.nea.firmament.util.useMatch
-
-abstract class RarityMatcher {
- abstract fun match(rarity: Rarity): Boolean
-
- companion object {
- fun parse(jsonElement: JsonElement): RarityMatcher {
- val string = jsonElement.asString
- val range = parseRange(string)
- if (range != null) return range
- return Exact(Rarity.valueOf(string))
- }
-
- private val allRarities = Rarity.entries.joinToString("|", "(?:", ")")
- private val intervalSpec =
- "(?<beginningOpen>[\\[\\(])(?<beginning>$allRarities)?,(?<ending>$allRarities)?(?<endingOpen>[\\]\\)])"
- .toPattern()
-
- fun parseRange(string: String): RangeMatcher? {
- intervalSpec.useMatch<Nothing>(string) {
- // Open in the set-theory sense, meaning does not include its end.
- val beginningOpen = group("beginningOpen") == "("
- val endingOpen = group("endingOpen") == ")"
- val beginning = group("beginning")?.let(Rarity::valueOf)
- val ending = group("ending")?.let(Rarity::valueOf)
- return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
- }
- return null
- }
-
- }
-
- data class Exact(val expected: Rarity) : RarityMatcher() {
- override fun match(rarity: Rarity): Boolean {
- return rarity == expected
- }
- }
-
- data class RangeMatcher(
- val beginning: Rarity?,
- val beginningInclusive: Boolean,
- val ending: Rarity?,
- val endingInclusive: Boolean,
- ) : RarityMatcher() {
- override fun match(rarity: Rarity): Boolean {
- if (beginning != null) {
- if (beginningInclusive) {
- if (rarity < beginning) return false
- } else {
- if (rarity <= beginning) return false
- }
- }
- if (ending != null) {
- if (endingInclusive) {
- if (rarity > ending) return false
- } else {
- if (rarity >= ending) return false
- }
- }
- return true
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt
deleted file mode 100644
index 5eb86ac..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/texturepack/StringMatcher.kt
+++ /dev/null
@@ -1,159 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonArray
-import com.google.gson.JsonElement
-import com.google.gson.JsonNull
-import com.google.gson.JsonObject
-import com.google.gson.JsonPrimitive
-import com.google.gson.internal.LazilyParsedNumber
-import java.util.function.Predicate
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import net.minecraft.nbt.NbtString
-import net.minecraft.text.Text
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.removeColorCodes
-
-@Serializable(with = StringMatcher.Serializer::class)
-interface StringMatcher {
- fun matches(string: String): Boolean
- fun matches(text: Text): Boolean {
- return matches(text.string)
- }
-
- fun matches(nbt: NbtString): Boolean {
- val string = nbt.asString()
- val jsonStart = string.indexOf('{')
- val stringStart = string.indexOf('"')
- val isString = stringStart >= 0 && string.subSequence(0, stringStart).isBlank()
- val isJson = jsonStart >= 0 && string.subSequence(0, jsonStart).isBlank()
- if (isString || isJson)
- return matches(Text.Serialization.fromJson(string, MC.defaultRegistries) ?: return false)
- return matches(string)
- }
-
- class Equals(input: String, val stripColorCodes: Boolean) : StringMatcher {
- private val expected = if (stripColorCodes) input.removeColorCodes() else input
- override fun matches(string: String): Boolean {
- return expected == (if (stripColorCodes) string.removeColorCodes() else string)
- }
-
- override fun toString(): String {
- return "Equals($expected, stripColorCodes = $stripColorCodes)"
- }
- }
-
- class Pattern(val patternWithColorCodes: String, val stripColorCodes: Boolean) : StringMatcher {
- private val regex: Predicate<String> = patternWithColorCodes.toPattern().asMatchPredicate()
- override fun matches(string: String): Boolean {
- return regex.test(if (stripColorCodes) string.removeColorCodes() else string)
- }
-
- override fun toString(): String {
- return "Pattern($patternWithColorCodes, stripColorCodes = $stripColorCodes)"
- }
- }
-
- object Serializer : KSerializer<StringMatcher> {
- val delegateSerializer = kotlinx.serialization.json.JsonElement.serializer()
- override val descriptor: SerialDescriptor
- get() = SerialDescriptor("StringMatcher", delegateSerializer.descriptor)
-
- override fun deserialize(decoder: Decoder): StringMatcher {
- val delegate = decoder.decodeSerializableValue(delegateSerializer)
- val gsonDelegate = delegate.intoGson()
- return parse(gsonDelegate)
- }
-
- override fun serialize(encoder: Encoder, value: StringMatcher) {
- encoder.encodeSerializableValue(delegateSerializer, Companion.serialize(value).intoKotlinJson())
- }
-
- }
-
- companion object {
- fun serialize(stringMatcher: StringMatcher): JsonElement {
- TODO("Cannot serialize string matchers rn")
- }
-
- fun parse(jsonElement: JsonElement): StringMatcher {
- if (jsonElement is JsonPrimitive) {
- return Equals(jsonElement.asString, true)
- }
- if (jsonElement is JsonObject) {
- val regex = jsonElement["regex"] as JsonPrimitive?
- val text = jsonElement["equals"] as JsonPrimitive?
- val shouldStripColor = when (val color = (jsonElement["color"] as JsonPrimitive?)?.asString) {
- "preserve" -> false
- "strip", null -> true
- else -> error("Unknown color preservation mode: $color")
- }
- if ((regex == null) == (text == null)) error("Could not parse $jsonElement as string matcher")
- if (regex != null)
- return Pattern(regex.asString, shouldStripColor)
- if (text != null)
- return Equals(text.asString, shouldStripColor)
- }
- error("Could not parse $jsonElement as a string matcher")
- }
- }
-}
-
-fun JsonElement.intoKotlinJson(): kotlinx.serialization.json.JsonElement {
- when (this) {
- is JsonNull -> return kotlinx.serialization.json.JsonNull
- is JsonObject -> {
- return kotlinx.serialization.json.JsonObject(this.entrySet()
- .associate { it.key to it.value.intoKotlinJson() })
- }
-
- is JsonArray -> {
- return kotlinx.serialization.json.JsonArray(this.map { it.intoKotlinJson() })
- }
-
- is JsonPrimitive -> {
- if (this.isString)
- return kotlinx.serialization.json.JsonPrimitive(this.asString)
- if (this.isBoolean)
- return kotlinx.serialization.json.JsonPrimitive(this.asBoolean)
- return kotlinx.serialization.json.JsonPrimitive(this.asNumber)
- }
-
- else -> error("Unknown json variant $this")
- }
-}
-
-fun kotlinx.serialization.json.JsonElement.intoGson(): JsonElement {
- when (this) {
- is kotlinx.serialization.json.JsonNull -> return JsonNull.INSTANCE
- is kotlinx.serialization.json.JsonPrimitive -> {
- if (this.isString)
- return JsonPrimitive(this.content)
- if (this.content == "true")
- return JsonPrimitive(true)
- if (this.content == "false")
- return JsonPrimitive(false)
- return JsonPrimitive(LazilyParsedNumber(this.content))
- }
-
- is kotlinx.serialization.json.JsonObject -> {
- val obj = JsonObject()
- for ((k, v) in this) {
- obj.add(k, v.intoGson())
- }
- return obj
- }
-
- is kotlinx.serialization.json.JsonArray -> {
- val arr = JsonArray()
- for (v in this) {
- arr.add(v.intoGson())
- }
- return arr
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt b/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt
deleted file mode 100644
index 8a8291a..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/FairySouls.kt
+++ /dev/null
@@ -1,131 +0,0 @@
-
-
-package moe.nea.firmament.features.world
-
-import io.github.moulberry.repo.data.Coordinate
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import net.minecraft.text.Text
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.SkyblockServerUpdateEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.blockPos
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-import moe.nea.firmament.util.render.RenderInWorldContext
-import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld
-import moe.nea.firmament.util.unformattedString
-
-
-object FairySouls : FirmamentFeature {
-
-
- @Serializable
- data class Data(
- val foundSouls: MutableMap<SkyBlockIsland, MutableSet<Int>> = mutableMapOf()
- )
-
- override val config: ManagedConfig
- get() = TConfig
-
- object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "found-fairysouls", ::Data)
-
-
- object TConfig : ManagedConfig("fairy-souls") {
- val displaySouls by toggle("show") { false }
- val resetSouls by button("reset") {
- DConfig.data?.foundSouls?.clear() != null
- updateMissingSouls()
- }
- }
-
-
- override val identifier: String get() = "fairy-souls"
-
- val playerReach = 5
- val playerReachSquared = playerReach * playerReach
-
- var currentLocationName: SkyBlockIsland? = null
- var currentLocationSouls: List<Coordinate> = emptyList()
- var currentMissingSouls: List<Coordinate> = emptyList()
-
- fun updateMissingSouls() {
- currentMissingSouls = emptyList()
- val c = DConfig.data ?: return
- val fi = c.foundSouls[currentLocationName] ?: setOf()
- val cms = currentLocationSouls.toMutableList()
- fi.asSequence().sortedDescending().filter { it in cms.indices }.forEach { cms.removeAt(it) }
- currentMissingSouls = cms
- }
-
- fun updateWorldSouls() {
- currentLocationSouls = emptyList()
- val loc = currentLocationName ?: return
- currentLocationSouls = RepoManager.neuRepo.constants.fairySouls.soulLocations[loc.locrawMode] ?: return
- }
-
- fun findNearestClickableSoul(): Coordinate? {
- val player = MC.player ?: return null
- val pos = player.pos
- val location = SBData.skyblockLocation ?: return null
- val soulLocations: List<Coordinate> =
- RepoManager.neuRepo.constants.fairySouls.soulLocations[location.locrawMode] ?: return null
- return soulLocations
- .map { it to it.blockPos.getSquaredDistance(pos) }
- .filter { it.second < playerReachSquared }
- .minByOrNull { it.second }
- ?.first
- }
-
- private fun markNearestSoul() {
- val nearestSoul = findNearestClickableSoul() ?: return
- val c = DConfig.data ?: return
- val loc = currentLocationName ?: return
- val idx = currentLocationSouls.indexOf(nearestSoul)
- c.foundSouls.computeIfAbsent(loc) { mutableSetOf() }.add(idx)
- DConfig.markDirty()
- updateMissingSouls()
- }
-
- @Subscribe
- fun onWorldRender(it: WorldRenderLastEvent) {
- if (!TConfig.displaySouls) return
- renderInWorld(it) {
- color(1F, 1F, 0F, 0.8F)
- currentMissingSouls.forEach {
- block(it.blockPos)
- }
- color(1f, 0f, 1f, 1f)
- currentLocationSouls.forEach {
- wireframeCube(it.blockPos)
- }
- }
- }
-
- @Subscribe
- fun onProcessChat(it: ProcessChatEvent) {
- when (it.text.unformattedString) {
- "You have already found that Fairy Soul!" -> {
- markNearestSoul()
- }
-
- "SOUL! You found a Fairy Soul!" -> {
- markNearestSoul()
- }
- }
- }
-
- @Subscribe
- fun onLocationChange(it: SkyblockServerUpdateEvent) {
- currentLocationName = it.newLocraw?.skyblockLocation
- updateWorldSouls()
- updateMissingSouls()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt b/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
deleted file mode 100644
index 592b8fa..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/NPCWaypoints.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package moe.nea.firmament.features.world
-
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.commands.thenExecute
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.ReloadRegistrationEvent
-import moe.nea.firmament.util.MoulConfigUtils
-import moe.nea.firmament.util.ScreenUtil
-
-object NPCWaypoints {
-
- var allNpcWaypoints = listOf<NavigableWaypoint>()
-
- @Subscribe
- fun onRepoReloadRegistration(event: ReloadRegistrationEvent) {
- event.repo.registerReloadListener {
- allNpcWaypoints = it.items.items.values
- .asSequence()
- .filter { !it.island.isNullOrBlank() }
- .map {
- NavigableWaypoint.NPCWaypoint(it)
- }
- .toList()
- }
- }
-
- @Subscribe
- fun onOpenGui(event: CommandEvent.SubCommand) {
- event.subcommand("npcs") {
- thenExecute {
- ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen(
- "npc_waypoints",
- NpcWaypointGui(allNpcWaypoints),
- null))
- }
- }
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
deleted file mode 100644
index 28a517f..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/NavigableWaypoint.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package moe.nea.firmament.features.world
-
-import io.github.moulberry.repo.data.NEUItem
-import net.minecraft.util.math.BlockPos
-import moe.nea.firmament.util.SkyBlockIsland
-
-abstract class NavigableWaypoint {
- abstract val name: String
- abstract val position: BlockPos
- abstract val island: SkyBlockIsland
-
- data class NPCWaypoint(
- val item: NEUItem,
- ) : NavigableWaypoint() {
- override val name: String
- get() = item.displayName
- override val position: BlockPos
- get() = BlockPos(item.x, item.y, item.z)
- override val island: SkyBlockIsland
- get() = SkyBlockIsland.forMode(item.island)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt b/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
deleted file mode 100644
index acdfb86..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/NavigationHelper.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-package moe.nea.firmament.features.world
-
-import io.github.moulberry.repo.constants.Islands
-import net.minecraft.text.Text
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Position
-import net.minecraft.util.math.Vec3i
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.SkyblockServerUpdateEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.WarpUtil
-import moe.nea.firmament.util.render.RenderInWorldContext
-
-object NavigationHelper {
- var targetWaypoint: NavigableWaypoint? = null
- set(value) {
- field = value
- recalculateRoute()
- }
-
- var nextTeleporter: Islands.Teleporter? = null
- private set
-
- val Islands.Teleporter.toIsland get() = SkyBlockIsland.forMode(this.getTo())
- val Islands.Teleporter.fromIsland get() = SkyBlockIsland.forMode(this.getFrom())
- val Islands.Teleporter.blockPos get() = BlockPos(x.toInt(), y.toInt(), z.toInt())
-
- @Subscribe
- fun onWorldSwitch(event: SkyblockServerUpdateEvent) {
- recalculateRoute()
- }
-
- fun recalculateRoute() {
- val tp = targetWaypoint
- val currentIsland = SBData.skyblockLocation
- if (tp == null || currentIsland == null) {
- nextTeleporter = null
- return
- }
- val route = findRoute(currentIsland, tp.island, mutableSetOf())
- nextTeleporter = route?.get(0)
- }
-
- private fun findRoute(
- fromIsland: SkyBlockIsland,
- targetIsland: SkyBlockIsland,
- visitedIslands: MutableSet<SkyBlockIsland>
- ): MutableList<Islands.Teleporter>? {
- var shortestChain: MutableList<Islands.Teleporter>? = null
- for (it in RepoManager.neuRepo.constants.islands.teleporters) {
- if (it.toIsland in visitedIslands) continue
- if (it.fromIsland != fromIsland) continue
- if (it.toIsland == targetIsland) return mutableListOf(it)
- visitedIslands.add(fromIsland)
- val nextRoute = findRoute(it.toIsland, targetIsland, visitedIslands) ?: continue
- nextRoute.add(0, it)
- if (shortestChain == null || shortestChain.size > nextRoute.size) {
- shortestChain = nextRoute
- }
- visitedIslands.remove(fromIsland)
- }
- return shortestChain
- }
-
-
- @Subscribe
- fun onMovement(event: TickEvent) { // TODO: add a movement tick event maybe?
- val tp = targetWaypoint ?: return
- val p = MC.player ?: return
- if (p.squaredDistanceTo(tp.position.toCenterPos()) < 5 * 5) {
- targetWaypoint = null
- }
- }
-
- @Subscribe
- fun drawWaypoint(event: WorldRenderLastEvent) {
- val tp = targetWaypoint ?: return
- val nt = nextTeleporter
- RenderInWorldContext.renderInWorld(event) {
- if (nt != null) {
- waypoint(nt.blockPos,
- Text.literal("Teleporter to " + nt.toIsland.userFriendlyName),
- Text.literal("(towards " + tp.name + "§f)"))
- } else if (tp.island == SBData.skyblockLocation) {
- waypoint(tp.position,
- Text.literal(tp.name))
- }
- }
- }
-
- fun tryWarpNear() {
- val tp = targetWaypoint
- if (tp == null) {
- MC.sendChat(Text.literal("Could not find a waypoint to warp you to. Select one first."))
- return
- }
- WarpUtil.teleportToNearestWarp(tp.island, tp.position.asPositionView())
- }
-
-}
-
-fun Vec3i.asPositionView(): Position {
- return object : Position {
- override fun getX(): Double {
- return this@asPositionView.x.toDouble()
- }
-
- override fun getY(): Double {
- return this@asPositionView.y.toDouble()
- }
-
- override fun getZ(): Double {
- return this@asPositionView.z.toDouble()
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt b/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
deleted file mode 100644
index 6146e50..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/NpcWaypointGui.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-package moe.nea.firmament.features.world
-
-import io.github.notenoughupdates.moulconfig.observer.ObservableList
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import moe.nea.firmament.features.events.anniversity.AnniversaryFeatures.atOnce
-import moe.nea.firmament.keybindings.SavedKeyBinding
-
-class NpcWaypointGui(
- val allWaypoints: List<NavigableWaypoint>,
-) {
-
- data class NavigableWaypointW(val waypoint: NavigableWaypoint) {
- @Bind
- fun name() = waypoint.name
-
- @Bind
- fun isSelected() = NavigationHelper.targetWaypoint == waypoint
-
- @Bind
- fun click() {
- if (SavedKeyBinding.isShiftDown()) {
- NavigationHelper.targetWaypoint = waypoint
- NavigationHelper.tryWarpNear()
- } else if (isSelected()) {
- NavigationHelper.targetWaypoint = null
- } else {
- NavigationHelper.targetWaypoint = waypoint
- }
- }
- }
-
- @JvmField
- @field:Bind
- var search: String = ""
- var lastSearch: String? = null
-
- @Bind("results")
- fun results(): ObservableList<NavigableWaypointW> {
- return results
- }
-
- @Bind
- fun tick() {
- if (search != lastSearch) {
- updateSearch()
- lastSearch = search
- }
- }
-
- val results: ObservableList<NavigableWaypointW> = ObservableList(mutableListOf())
-
- fun updateSearch() {
- val split = search.split(" +".toRegex())
- results.atOnce {
- results.clear()
- allWaypoints.filter { waypoint ->
- if (search.isBlank()) {
- true
- } else {
- split.all { waypoint.name.contains(it, ignoreCase = true) }
- }
- }.mapTo(results) {
- NavigableWaypointW(it)
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt b/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt
deleted file mode 100644
index 91a06da..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/world/Waypoints.kt
+++ /dev/null
@@ -1,297 +0,0 @@
-
-
-package moe.nea.firmament.features.world
-
-import com.mojang.brigadier.arguments.IntegerArgumentType
-import me.shedaniel.math.Color
-import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource
-import kotlinx.serialization.Serializable
-import kotlin.collections.component1
-import kotlin.collections.component2
-import kotlin.collections.set
-import kotlin.time.Duration.Companion.hours
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.command.argument.BlockPosArgumentType
-import net.minecraft.server.command.ServerCommandSource
-import net.minecraft.text.Text
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.commands.get
-import moe.nea.firmament.commands.thenArgument
-import moe.nea.firmament.commands.thenExecute
-import moe.nea.firmament.commands.thenLiteral
-import moe.nea.firmament.events.CommandEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.TickEvent
-import moe.nea.firmament.events.WorldReadyEvent
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.util.ClipboardUtils
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.TimeMark
-import moe.nea.firmament.util.render.RenderInWorldContext
-
-object Waypoints : FirmamentFeature {
- override val identifier: String
- get() = "waypoints"
-
- object TConfig : ManagedConfig(identifier) {
- val tempWaypointDuration by duration("temp-waypoint-duration", 0.seconds, 1.hours) { 30.seconds }
- val showIndex by toggle("show-index") { true }
- val skipToNearest by toggle("skip-to-nearest") { false }
- // TODO: look ahead size
- }
-
- data class TemporaryWaypoint(
- val pos: BlockPos,
- val postedAt: TimeMark,
- )
-
- override val config get() = TConfig
-
- val temporaryPlayerWaypointList = mutableMapOf<String, TemporaryWaypoint>()
- val temporaryPlayerWaypointMatcher = "(?i)x: (-?[0-9]+),? y: (-?[0-9]+),? z: (-?[0-9]+)".toPattern()
-
- val waypoints = mutableListOf<BlockPos>()
- var ordered = false
- var orderedIndex = 0
-
- @Serializable
- data class ColeWeightWaypoint(
- val x: Int,
- val y: Int,
- val z: Int,
- val r: Int = 0,
- val g: Int = 0,
- val b: Int = 0,
- )
-
- @Subscribe
- fun onRenderOrderedWaypoints(event: WorldRenderLastEvent) {
- if (waypoints.isEmpty()) return
- RenderInWorldContext.renderInWorld(event) {
- if (!ordered) {
- waypoints.withIndex().forEach {
- color(0f, 0.3f, 0.7f, 0.5f)
- block(it.value)
- color(1f, 1f, 1f, 1f)
- if (TConfig.showIndex)
- withFacingThePlayer(it.value.toCenterPos()) {
- text(Text.literal(it.index.toString()))
- }
- }
- } else {
- orderedIndex %= waypoints.size
- val firstColor = Color.ofRGBA(0, 200, 40, 180)
- color(firstColor)
- tracer(waypoints[orderedIndex].toCenterPos(), lineWidth = 3f)
- waypoints.withIndex().toList()
- .wrappingWindow(orderedIndex, 3)
- .zip(
- listOf(
- firstColor,
- Color.ofRGBA(180, 200, 40, 150),
- Color.ofRGBA(180, 80, 20, 140),
- )
- )
- .reversed()
- .forEach { (waypoint, col) ->
- val (index, pos) = waypoint
- color(col)
- block(pos)
- color(1f, 1f, 1f, 1f)
- if (TConfig.showIndex)
- withFacingThePlayer(pos.toCenterPos()) {
- text(Text.literal(index.toString()))
- }
- }
- }
- }
- }
-
- @Subscribe
- fun onTick(event: TickEvent) {
- if (waypoints.isEmpty() || !ordered) return
- orderedIndex %= waypoints.size
- val p = MC.player?.pos ?: return
- if (TConfig.skipToNearest) {
- orderedIndex =
- (waypoints.withIndex().minBy { it.value.getSquaredDistance(p) }.index + 1) % waypoints.size
- } else {
- if (waypoints[orderedIndex].isWithinDistance(p, 3.0)) {
- orderedIndex = (orderedIndex + 1) % waypoints.size
- }
- }
- }
-
- @Subscribe
- fun onProcessChat(it: ProcessChatEvent) {
- val matcher = temporaryPlayerWaypointMatcher.matcher(it.unformattedString)
- if (it.nameHeuristic != null && TConfig.tempWaypointDuration > 0.seconds && matcher.find()) {
- temporaryPlayerWaypointList[it.nameHeuristic] = TemporaryWaypoint(
- BlockPos(
- matcher.group(1).toInt(),
- matcher.group(2).toInt(),
- matcher.group(3).toInt(),
- ),
- TimeMark.now()
- )
- }
- }
-
- @Subscribe
- fun onCommand(event: CommandEvent.SubCommand) {
- event.subcommand("waypoint") {
- thenArgument("pos", BlockPosArgumentType.blockPos()) { pos ->
- thenExecute {
- val position = pos.get(this).toAbsoluteBlockPos(source.asFakeServer())
- waypoints.add(position)
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.waypoint.added",
- position.x,
- position.y,
- position.z
- )
- )
- }
- }
- }
- event.subcommand("waypoints") {
- thenLiteral("clear") {
- thenExecute {
- waypoints.clear()
- source.sendFeedback(Text.translatable("firmament.command.waypoint.clear"))
- }
- }
- thenLiteral("toggleordered") {
- thenExecute {
- ordered = !ordered
- if (ordered) {
- val p = MC.player?.pos ?: Vec3d.ZERO
- orderedIndex =
- waypoints.withIndex().minByOrNull { it.value.getSquaredDistance(p) }?.index ?: 0
- }
- source.sendFeedback(Text.translatable("firmament.command.waypoint.ordered.toggle.$ordered"))
- }
- }
- thenLiteral("skip") {
- thenExecute {
- if (ordered && waypoints.isNotEmpty()) {
- orderedIndex = (orderedIndex + 1) % waypoints.size
- source.sendFeedback(Text.translatable("firmament.command.waypoint.skip"))
- } else {
- source.sendError(Text.translatable("firmament.command.waypoint.skip.error"))
- }
- }
- }
- thenLiteral("remove") {
- thenArgument("index", IntegerArgumentType.integer(0)) { indexArg ->
- thenExecute {
- val index = get(indexArg)
- if (index in waypoints.indices) {
- waypoints.removeAt(index)
- source.sendFeedback(Text.stringifiedTranslatable(
- "firmament.command.waypoint.remove",
- index))
- } else {
- source.sendError(Text.stringifiedTranslatable("firmament.command.waypoint.remove.error"))
- }
- }
- }
- }
- thenLiteral("import") {
- thenExecute {
- val contents = ClipboardUtils.getTextContents()
- val data = try {
- Firmament.json.decodeFromString<List<ColeWeightWaypoint>>(contents)
- } catch (ex: Exception) {
- Firmament.logger.error("Could not load waypoints from clipboard", ex)
- source.sendError(Text.translatable("firmament.command.waypoint.import.error"))
- return@thenExecute
- }
- waypoints.clear()
- data.mapTo(waypoints) { BlockPos(it.x, it.y, it.z) }
- source.sendFeedback(
- Text.stringifiedTranslatable(
- "firmament.command.waypoint.import",
- data.size
- )
- )
- }
- }
- }
- }
-
- @Subscribe
- fun onRenderTemporaryWaypoints(event: WorldRenderLastEvent) {
- temporaryPlayerWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration }
- if (temporaryPlayerWaypointList.isEmpty()) return
- RenderInWorldContext.renderInWorld(event) {
- color(1f, 1f, 0f, 1f)
- temporaryPlayerWaypointList.forEach { (player, waypoint) ->
- block(waypoint.pos)
- }
- color(1f, 1f, 1f, 1f)
- temporaryPlayerWaypointList.forEach { (player, waypoint) ->
- val skin =
- MC.networkHandler?.listedPlayerListEntries?.find { it.profile.name == player }
- ?.skinTextures
- ?.texture
- withFacingThePlayer(waypoint.pos.toCenterPos()) {
- waypoint(waypoint.pos, Text.stringifiedTranslatable("firmament.waypoint.temporary", player))
- if (skin != null) {
- matrixStack.translate(0F, -20F, 0F)
- // Head front
- texture(
- skin, 16, 16,
- 1 / 8f, 1 / 8f,
- 2 / 8f, 2 / 8f,
- )
- // Head overlay
- texture(
- skin, 16, 16,
- 5 / 8f, 1 / 8f,
- 6 / 8f, 2 / 8f,
- )
- }
- }
- }
- }
- }
-
- @Subscribe
- fun onWorldReady(event: WorldReadyEvent) {
- temporaryPlayerWaypointList.clear()
- }
-}
-
-fun <E> List<E>.wrappingWindow(startIndex: Int, windowSize: Int): List<E> {
- val result = ArrayList<E>(windowSize)
- if (startIndex + windowSize < size) {
- result.addAll(subList(startIndex, startIndex + windowSize))
- } else {
- result.addAll(subList(startIndex, size))
- result.addAll(subList(0, minOf(windowSize - (size - startIndex), startIndex)))
- }
- return result
-}
-
-
-fun FabricClientCommandSource.asFakeServer(): ServerCommandSource {
- val source = this
- return ServerCommandSource(
- source.player,
- source.position,
- source.rotation,
- null,
- 0,
- "FakeServerCommandSource",
- Text.literal("FakeServerCommandSource"),
- null,
- source.player
- )
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/BarComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/BarComponent.kt
deleted file mode 100644
index 8ef0753..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/BarComponent.kt
+++ /dev/null
@@ -1,125 +0,0 @@
-
-package moe.nea.firmament.gui
-
-import com.mojang.blaze3d.systems.RenderSystem
-import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
-import io.github.notenoughupdates.moulconfig.common.RenderContext
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
-import me.shedaniel.math.Color
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.util.Identifier
-import moe.nea.firmament.Firmament
-
-class BarComponent(
- val progress: GetSetter<Double>, val total: GetSetter<Double>,
- val fillColor: Color,
- val emptyColor: Color,
-) : GuiComponent() {
- override fun getWidth(): Int {
- return 80
- }
-
- override fun getHeight(): Int {
- return 8
- }
-
- data class Texture(
- val identifier: Identifier,
- val u1: Float, val v1: Float,
- val u2: Float, val v2: Float,
- ) {
- fun draw(context: DrawContext, x: Int, y: Int, width: Int, height: Int, color: Color) {
- context.drawTexturedQuad(
- identifier,
- x, y, x + width, x + height, 0,
- u1, u2, v1, v2,
- color.red / 255F,
- color.green / 255F,
- color.blue / 255F,
- color.alpha / 255F,
- )
- }
- }
-
- companion object {
- val resource = Firmament.identifier("textures/gui/bar.png")
- val left = Texture(resource, 0 / 64F, 0 / 64F, 4 / 64F, 8 / 64F)
- val middle = Texture(resource, 4 / 64F, 0 / 64F, 8 / 64F, 8 / 64F)
- val right = Texture(resource, 8 / 64F, 0 / 64F, 12 / 64F, 8 / 64F)
- val segmentOverlay = Texture(resource, 12 / 64F, 0 / 64F, 15 / 64F, 8 / 64F)
- }
-
- private fun drawSection(
- context: DrawContext,
- texture: Texture,
- x: Int,
- y: Int,
- width: Int,
- sectionStart: Double,
- sectionEnd: Double
- ) {
- if (sectionEnd < progress.get() && width == 4) {
- texture.draw(context, x, y, 4, 8, fillColor)
- return
- }
- if (sectionStart > progress.get() && width == 4) {
- texture.draw(context, x, y, 4, 8, emptyColor)
- return
- }
- val increasePerPixel = (sectionEnd - sectionStart) / width
- var valueAtPixel = sectionStart
- for (i in (0 until width)) {
- val newTex =
- Texture(texture.identifier, texture.u1 + i / 64F, texture.v1, texture.u1 + (i + 1) / 64F, texture.v2)
- newTex.draw(
- context, x + i, y, 1, 8,
- if (valueAtPixel < progress.get()) fillColor else emptyColor
- )
- valueAtPixel += increasePerPixel
- }
- }
-
- override fun render(context: GuiImmediateContext) {
- val renderContext = (context.renderContext as ModernRenderContext).drawContext
- var i = 0
- val x = 0
- val y = 0
- while (i < context.width - 4) {
- drawSection(
- renderContext,
- if (i == 0) left else middle,
- x + i, y,
- (context.width - (i + 4)).coerceAtMost(4),
- i * total.get() / context.width, (i + 4) * total.get() / context.width
- )
- i += 4
- }
- drawSection(
- renderContext,
- right,
- x + context.width - 4,
- y,
- 4,
- (context.width - 4) * total.get() / context.width,
- total.get()
- )
- RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
-
- }
-
-}
-
-fun Identifier.toMoulConfig(): MyResourceLocation {
- return MyResourceLocation(this.namespace, this.path)
-}
-
-fun RenderContext.color(color: Color) {
- color(color.red, color.green, color.blue, color.alpha)
-}
-
-fun RenderContext.color(red: Int, green: Int, blue: Int, alpha: Int) {
- color(red / 255f, green / 255f, blue / 255f, alpha / 255f)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt
deleted file mode 100644
index 82e5b05..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/FirmButtonComponent.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-
-package moe.nea.firmament.gui
-
-import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
-import io.github.notenoughupdates.moulconfig.deps.libninepatch.NinePatch
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.MouseEvent
-import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-
-
-open class FirmButtonComponent(
- child: GuiComponent,
- val isEnabled: GetSetter<Boolean> = GetSetter.constant(true),
- val noBackground: Boolean = false,
- val action: Runnable,
-) : PanelComponent(child, if (noBackground) 0 else 2, DefaultBackgroundRenderer.TRANSPARENT) {
-
- /* TODO: make use of vanillas built in nine slicer */
- val hoveredBg =
- NinePatch.builder(MyResourceLocation("minecraft", "textures/gui/sprites/widget/button_highlighted.png"))
- .cornerSize(5)
- .cornerUv(5 / 200F, 5 / 20F)
- .mode(NinePatch.Mode.STRETCHING)
- .build()
- val unhoveredBg = NinePatch.builder(MyResourceLocation("minecraft", "textures/gui/sprites/widget/button.png"))
- .cornerSize(5)
- .cornerUv(5 / 200F, 5 / 20F)
- .mode(NinePatch.Mode.STRETCHING)
- .build()
- val disabledBg =
- NinePatch.builder(MyResourceLocation("minecraft", "textures/gui/sprites/widget/button_disabled.png"))
- .cornerSize(5)
- .cornerUv(5 / 200F, 5 / 20F)
- .mode(NinePatch.Mode.STRETCHING)
- .build()
- val activeBg = NinePatch.builder(MyResourceLocation("firmament", "textures/gui/sprites/widget/button_active.png"))
- .cornerSize(5)
- .cornerUv(5 / 200F, 5 / 20F)
- .mode(NinePatch.Mode.STRETCHING)
- .build()
- var isClicking = false
- override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
- if (!isEnabled.get()) return false
- if (isClicking) {
- if (mouseEvent is MouseEvent.Click && !mouseEvent.mouseState && mouseEvent.mouseButton == 0) {
- isClicking = false
- if (context.isHovered) {
- action.run()
- }
- return true
- }
- }
- if (!context.isHovered) return false
- if (mouseEvent !is MouseEvent.Click) return false
- if (mouseEvent.mouseState && mouseEvent.mouseButton == 0) {
- requestFocus()
- isClicking = true
- return true
- }
- return false
- }
-
- open fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> =
- if (!isEnabled.get()) disabledBg
- else if (context.isHovered || isClicking) hoveredBg
- else unhoveredBg
-
- override fun render(context: GuiImmediateContext) {
- context.renderContext.pushMatrix()
- if (!noBackground)
- context.renderContext.drawNinePatch(
- getBackground(context),
- 0f, 0f, context.width, context.height
- )
- context.renderContext.translate(insets.toFloat(), insets.toFloat(), 0f)
- element.render(getChildContext(context))
- context.renderContext.popMatrix()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
deleted file mode 100644
index b1792ce..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/FirmHoverComponent.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-package moe.nea.firmament.gui
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
-import io.github.notenoughupdates.moulconfig.gui.MouseEvent
-import java.util.function.BiFunction
-import java.util.function.Supplier
-import kotlin.time.Duration
-import moe.nea.firmament.util.TimeMark
-
-class FirmHoverComponent(
- val child: GuiComponent,
- val hoverLines: Supplier<List<String>>,
- val hoverDelay: Duration,
-) : GuiComponent() {
- override fun getWidth(): Int {
- return child.width
- }
-
- override fun getHeight(): Int {
- return child.height
- }
-
- override fun <T : Any?> foldChildren(
- initial: T,
- visitor: BiFunction<GuiComponent, T, T>
- ): T {
- return visitor.apply(child, initial)
- }
-
- override fun render(context: GuiImmediateContext) {
- if (context.isHovered && (permaHover || lastMouseMove.passedTime() > hoverDelay)) {
- context.renderContext.scheduleDrawTooltip(hoverLines.get())
- permaHover = true
- } else {
- permaHover = false
- }
- if (!context.isHovered) {
- lastMouseMove = TimeMark.now()
- }
- child.render(context)
-
- }
-
- var permaHover = false
- var lastMouseMove = TimeMark.farPast()
-
- override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
- if (mouseEvent is MouseEvent.Move) {
- lastMouseMove = TimeMark.now()
- }
- return child.mouseEvent(mouseEvent, context)
- }
-
- override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
- return child.keyboardEvent(event, context)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/FixedComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/FixedComponent.kt
deleted file mode 100644
index ae1da2d..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/FixedComponent.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-package moe.nea.firmament.gui
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
-import io.github.notenoughupdates.moulconfig.gui.MouseEvent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import java.util.function.BiFunction
-
-class FixedComponent(
- val fixedWidth: GetSetter<Int>?,
- val fixedHeight: GetSetter<Int>?,
- val component: GuiComponent,
-) : GuiComponent() {
- override fun getWidth(): Int = fixedWidth?.get() ?: component.width
-
- override fun getHeight(): Int = fixedHeight?.get() ?: component.height
-
- override fun <T : Any?> foldChildren(initial: T, visitor: BiFunction<GuiComponent, T, T>): T {
- return visitor.apply(component, initial)
- }
-
- fun fixContext(context: GuiImmediateContext): GuiImmediateContext =
- context.translated(0, 0, width, height)
-
- override fun render(context: GuiImmediateContext) {
- component.render(fixContext(context))
- }
-
- override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean {
- return component.mouseEvent(mouseEvent, fixContext(context))
- }
-
- override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
- return component.keyboardEvent(event, fixContext(context))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
deleted file mode 100644
index bba7dee..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/ImageComponent.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package moe.nea.firmament.gui
-
-import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import java.util.function.Supplier
-
-class ImageComponent(
- private val width: Int,
- private val height: Int,
- val resourceLocation: Supplier<MyResourceLocation>,
- val u1: Float,
- val u2: Float,
- val v1: Float,
- val v2: Float,
-) : GuiComponent() {
- override fun getWidth(): Int {
- return width
- }
-
- override fun getHeight(): Int {
- return height
- }
-
- override fun render(context: GuiImmediateContext) {
- context.renderContext.bindTexture(resourceLocation.get())
- context.renderContext.drawTexturedRect(
- 0f, 0f,
- context.width.toFloat(), context.height.toFloat(),
- u1, v1, u2, v2
- )
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt b/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
deleted file mode 100644
index d1879b1..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/TickComponent.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package moe.nea.firmament.gui
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-
-class TickComponent(val onTick: Runnable) : GuiComponent() {
- override fun getWidth(): Int {
- return 0
- }
-
- override fun getHeight(): Int {
- return 0
- }
-
- override fun render(context: GuiImmediateContext) {
- onTick.run()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/AllConfigsGui.kt b/src/main/kotlin/moe/nea/firmament/gui/config/AllConfigsGui.kt
deleted file mode 100644
index 4f7731c..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/AllConfigsGui.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.observer.ObservableList
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
-import moe.nea.firmament.features.FeatureManager
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.MoulConfigUtils
-import moe.nea.firmament.util.ScreenUtil.setScreenLater
-
-object AllConfigsGui {
-
- val allConfigs
- get() = listOf(
- RepoManager.Config
- ) + FeatureManager.allFeatures.mapNotNull { it.config }
-
- fun <T> List<T>.toObservableList(): ObservableList<T> = ObservableList(this)
-
- class MainMapping(val allConfigs: List<ManagedConfig>) {
- @get:Bind("configs")
- val configs = allConfigs.map { EntryMapping(it) }.toObservableList()
-
- class EntryMapping(val config: ManagedConfig) {
- @Bind
- fun name() = Text.translatable("firmament.config.${config.name}").string
-
- @Bind
- fun openEditor() {
- config.showConfigEditor(MC.screen)
- }
- }
- }
-
- fun makeScreen(parent: Screen? = null): Screen {
- return MoulConfigUtils.loadScreen("config/main", MainMapping(allConfigs), parent)
- }
-
- fun showAllGuis() {
- setScreenLater(makeScreen())
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/BooleanHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/BooleanHandler.kt
deleted file mode 100644
index 8592777..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/BooleanHandler.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.component.CenterComponent
-import io.github.notenoughupdates.moulconfig.gui.component.SwitchComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.boolean
-import kotlinx.serialization.json.jsonPrimitive
-
-class BooleanHandler(val config: ManagedConfig) : ManagedConfig.OptionHandler<Boolean> {
- override fun toJson(element: Boolean): JsonElement? {
- return JsonPrimitive(element)
- }
-
- override fun fromJson(element: JsonElement): Boolean {
- return element.jsonPrimitive.boolean
- }
-
- override fun emitGuiElements(opt: ManagedOption<Boolean>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- CenterComponent(SwitchComponent(object : GetSetter<Boolean> {
- override fun get(): Boolean {
- return opt.get()
- }
-
- override fun set(newValue: Boolean) {
- opt.set(newValue)
- config.save()
- }
- }, 200)
- ))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt
deleted file mode 100644
index fa1c621..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/ClickHandler.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import kotlinx.serialization.json.JsonElement
-import moe.nea.firmament.gui.FirmButtonComponent
-
-class ClickHandler(val config: ManagedConfig, val runnable: () -> Unit) : ManagedConfig.OptionHandler<Unit> {
- override fun toJson(element: Unit): JsonElement? {
- return null
- }
-
- override fun fromJson(element: JsonElement) {}
-
- override fun emitGuiElements(opt: ManagedOption<Unit>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- FirmButtonComponent(
- TextComponent(opt.labelText.string),
- action = runnable),
- )
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/DurationHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/DurationHandler.kt
deleted file mode 100644
index 8d485b1..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/DurationHandler.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.common.IMinecraft
-import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
-import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.jsonPrimitive
-import kotlinx.serialization.json.long
-import kotlin.time.Duration
-import kotlin.time.DurationUnit
-import kotlin.time.toDuration
-import net.minecraft.text.Text
-import moe.nea.firmament.util.FirmFormatters
-
-class DurationHandler(val config: ManagedConfig, val min: Duration, val max: Duration) :
- ManagedConfig.OptionHandler<Duration> {
- override fun toJson(element: Duration): JsonElement? {
- return JsonPrimitive(element.inWholeMilliseconds)
- }
-
- override fun fromJson(element: JsonElement): Duration {
- return element.jsonPrimitive.long.toDuration(DurationUnit.MILLISECONDS)
- }
-
- override fun emitGuiElements(opt: ManagedOption<Duration>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- RowComponent(
- TextComponent(IMinecraft.instance.defaultFontRenderer,
- { FirmFormatters.formatTimespan(opt.value) },
- 40,
- TextComponent.TextAlignment.CENTER,
- true,
- false),
- SliderComponent(
- object : GetSetter<Float> {
- override fun get(): Float {
- return opt.value.toDouble(DurationUnit.SECONDS).toFloat()
- }
-
- override fun set(newValue: Float) {
- opt.value = newValue.toDouble().toDuration(DurationUnit.SECONDS)
- }
- },
- min.toDouble(DurationUnit.SECONDS).toFloat(),
- max.toDouble(DurationUnit.SECONDS).toFloat(),
- 0.1F,
- 130
- )
- ))
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt b/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
deleted file mode 100644
index 329319d..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/GuiAppender.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.FixedComponent
-
-class GuiAppender(val width: Int, val screenAccessor: () -> Screen) {
- val panel = mutableListOf<GuiComponent>()
- internal val reloadables = mutableListOf<(() -> Unit)>()
-
- fun onReload(reloadable: () -> Unit) {
- reloadables.add(reloadable)
- }
-
- fun appendLabeledRow(label: Text, right: GuiComponent) {
- appendSplitRow(
- TextComponent(label.string),
- right
- )
- }
-
- fun appendSplitRow(left: GuiComponent, right: GuiComponent) {
- // TODO: make this more dynamic
- // i could just make a component that allows for using half the available size
- appendFullRow(RowComponent(
- FixedComponent(GetSetter.constant(width / 2), null, left),
- FixedComponent(GetSetter.constant(width / 2), null, right),
- ))
- }
-
- fun appendFullRow(widget: GuiComponent) {
- panel.add(widget)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt
deleted file mode 100644
index 35c9d51..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/HudMetaHandler.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.decodeFromJsonElement
-import kotlinx.serialization.json.encodeToJsonElement
-import net.minecraft.text.MutableText
-import net.minecraft.text.Text
-import moe.nea.firmament.gui.FirmButtonComponent
-import moe.nea.firmament.jarvis.JarvisIntegration
-import moe.nea.firmament.util.MC
-
-class HudMetaHandler(val config: ManagedConfig, val label: MutableText, val width: Int, val height: Int) :
- ManagedConfig.OptionHandler<HudMeta> {
- override fun toJson(element: HudMeta): JsonElement? {
- return Json.encodeToJsonElement(element.position)
- }
-
- override fun fromJson(element: JsonElement): HudMeta {
- return HudMeta(Json.decodeFromJsonElement(element), label, width, height)
- }
-
- override fun emitGuiElements(opt: ManagedOption<HudMeta>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- FirmButtonComponent(
- TextComponent(
- Text.stringifiedTranslatable("firmament.hud.edit", label).string),
- ) {
- MC.screen = JarvisIntegration.jarvis.getHudEditor(
- guiAppender.screenAccessor.invoke(),
- listOf(opt.value)
- )
- })
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/IntegerHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/IntegerHandler.kt
deleted file mode 100644
index 31ce90f..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/IntegerHandler.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.common.IMinecraft
-import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
-import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.int
-import kotlinx.serialization.json.jsonPrimitive
-import moe.nea.firmament.util.FirmFormatters
-
-class IntegerHandler(val config: ManagedConfig, val min: Int, val max: Int) : ManagedConfig.OptionHandler<Int> {
- override fun toJson(element: Int): JsonElement? {
- return JsonPrimitive(element)
- }
-
- override fun fromJson(element: JsonElement): Int {
- return element.jsonPrimitive.int
- }
-
- override fun emitGuiElements(opt: ManagedOption<Int>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- RowComponent(
- TextComponent(IMinecraft.instance.defaultFontRenderer,
- { FirmFormatters.formatCommas(opt.value, 0) },
- 40,
- TextComponent.TextAlignment.CENTER,
- true,
- false),
- SliderComponent(
- object : GetSetter<Float> {
- override fun get(): Float {
- return opt.value.toFloat()
- }
-
- override fun set(newValue: Float) {
- opt.value = newValue.toInt()
- }
- },
- min.toFloat(),
- max.toFloat(),
- 0.1F,
- 130
- )
- ))
-
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt b/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt
deleted file mode 100644
index 35c4eb2..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/JAnyHud.kt
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import moe.nea.jarvis.api.JarvisHud
-import moe.nea.jarvis.api.JarvisScalable
-import kotlinx.serialization.Serializable
-import net.minecraft.text.Text
-
-@Serializable
-data class HudPosition(
- var x: Double,
- var y: Double,
- var scale: Float,
-)
-
-
-data class HudMeta(
- val position: HudPosition,
- private val label: Text,
- private val width: Int,
- private val height: Int,
-) : JarvisScalable, JarvisHud {
- override fun getX(): Double = position.x
-
- override fun setX(newX: Double) {
- position.x = newX
- }
-
- override fun getY(): Double = position.y
-
- override fun setY(newY: Double) {
- position.y = newY
- }
-
- override fun getLabel(): Text = label
-
- override fun getWidth(): Int = width
-
- override fun getHeight(): Int = height
-
- override fun getScale(): Float = position.scale
-
- override fun setScale(newScale: Float) {
- position.scale = newScale
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt
deleted file mode 100644
index c389cc9..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/KeyBindingHandler.kt
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.common.IMinecraft
-import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
-import io.github.notenoughupdates.moulconfig.deps.libninepatch.NinePatch
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import org.lwjgl.glfw.GLFW
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.decodeFromJsonElement
-import kotlinx.serialization.json.encodeToJsonElement
-import net.minecraft.text.Text
-import net.minecraft.util.Formatting
-import moe.nea.firmament.gui.FirmButtonComponent
-import moe.nea.firmament.keybindings.FirmamentKeyBindings
-import moe.nea.firmament.keybindings.SavedKeyBinding
-
-class KeyBindingHandler(val name: String, val managedConfig: ManagedConfig) :
- ManagedConfig.OptionHandler<SavedKeyBinding> {
-
- override fun initOption(opt: ManagedOption<SavedKeyBinding>) {
- FirmamentKeyBindings.registerKeyBinding(name, opt)
- }
-
- override fun toJson(element: SavedKeyBinding): JsonElement? {
- return Json.encodeToJsonElement(element)
- }
-
- override fun fromJson(element: JsonElement): SavedKeyBinding {
- return Json.decodeFromJsonElement(element)
- }
-
- override fun emitGuiElements(opt: ManagedOption<SavedKeyBinding>, guiAppender: GuiAppender) {
- var editing = false
- var lastPressed = 0
- var lastPressedNonModifier = 0
- var label: String = ""
- var button: FirmButtonComponent? = null
- fun updateLabel() {
- var stroke = opt.value.format()
- if (editing) {
- stroke = Text.literal("")
- val (shift, alt, ctrl) = SavedKeyBinding.getMods(SavedKeyBinding.getModInt())
- if (shift) {
- stroke.append("SHIFT + ")
- }
- if (alt) {
- stroke.append("ALT + ")
- }
- if (ctrl) {
- stroke.append("CTRL + ")
- }
- stroke.append("???")
- stroke.styled { it.withColor(Formatting.YELLOW) }
- }
- label = (stroke).string
- managedConfig.save()
- }
- button = object : FirmButtonComponent(
- TextComponent(
- IMinecraft.instance.defaultFontRenderer,
- { label },
- 130,
- TextComponent.TextAlignment.LEFT,
- false,
- false
- ), action = {
- if (editing) {
- button!!.blur()
- } else {
- editing = true
- button!!.requestFocus()
- updateLabel()
- }
- }) {
- override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean {
- if (event is KeyboardEvent.KeyPressed) {
- return if (event.pressed) onKeyPressed(event.keycode, SavedKeyBinding.getModInt())
- else onKeyReleased(event.keycode, SavedKeyBinding.getModInt())
- }
- return super.keyboardEvent(event, context)
- }
-
- override fun getBackground(context: GuiImmediateContext): NinePatch<MyResourceLocation> {
- if (editing) return activeBg
- return super.getBackground(context)
- }
-
- fun onKeyPressed(ch: Int, modifiers: Int): Boolean {
- if (!editing) {
- return false
- }
- if (ch == GLFW.GLFW_KEY_ESCAPE) {
- lastPressedNonModifier = 0
- editing = false
- lastPressed = 0
- opt.value = SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN)
- updateLabel()
- blur()
- return true
- }
- if (ch == GLFW.GLFW_KEY_LEFT_SHIFT || ch == GLFW.GLFW_KEY_RIGHT_SHIFT
- || ch == GLFW.GLFW_KEY_LEFT_ALT || ch == GLFW.GLFW_KEY_RIGHT_ALT
- || ch == GLFW.GLFW_KEY_LEFT_CONTROL || ch == GLFW.GLFW_KEY_RIGHT_CONTROL
- ) {
- lastPressed = ch
- } else {
- opt.value = SavedKeyBinding(
- ch, modifiers
- )
- editing = false
- blur()
- lastPressed = 0
- lastPressedNonModifier = 0
- }
- updateLabel()
- return true
- }
-
- override fun onLostFocus() {
- lastPressedNonModifier = 0
- editing = false
- lastPressed = 0
- updateLabel()
- }
-
- fun onKeyReleased(ch: Int, modifiers: Int): Boolean {
- if (!editing)
- return false
- if (lastPressedNonModifier == ch || (lastPressedNonModifier == 0 && ch == lastPressed)) {
- opt.value = SavedKeyBinding(ch, modifiers)
- editing = false
- blur()
- lastPressed = 0
- lastPressedNonModifier = 0
- }
- updateLabel()
- return true
- }
- }
- updateLabel()
- guiAppender.appendLabeledRow(opt.labelText, button)
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt
deleted file mode 100644
index aa6e3c8..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfig.kt
+++ /dev/null
@@ -1,181 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
-import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
-import io.github.notenoughupdates.moulconfig.gui.GuiContext
-import io.github.notenoughupdates.moulconfig.gui.component.CenterComponent
-import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent
-import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent
-import io.github.notenoughupdates.moulconfig.gui.component.RowComponent
-import io.github.notenoughupdates.moulconfig.gui.component.ScrollPanelComponent
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import moe.nea.jarvis.api.Point
-import org.lwjgl.glfw.GLFW
-import kotlinx.serialization.encodeToString
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonObject
-import kotlin.io.path.createDirectories
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-import kotlin.time.Duration
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.FirmButtonComponent
-import moe.nea.firmament.keybindings.SavedKeyBinding
-import moe.nea.firmament.util.ScreenUtil.setScreenLater
-
-abstract class ManagedConfig(override val name: String) : ManagedConfigElement() {
-
- interface OptionHandler<T : Any> {
- fun initOption(opt: ManagedOption<T>) {}
- fun toJson(element: T): JsonElement?
- fun fromJson(element: JsonElement): T
- fun emitGuiElements(opt: ManagedOption<T>, guiAppender: GuiAppender)
- }
-
- val file = Firmament.CONFIG_DIR.resolve("$name.json")
- val data: JsonObject by lazy {
- try {
- Firmament.json.decodeFromString(
- file.readText()
- )
- } catch (e: Exception) {
- Firmament.logger.info("Could not read config $name. Loading empty config.")
- JsonObject(mutableMapOf())
- }
- }
-
- fun save() {
- val data = JsonObject(allOptions.mapNotNull { (key, value) ->
- value.toJson()?.let {
- key to it
- }
- }.toMap())
- file.parent.createDirectories()
- file.writeText(Firmament.json.encodeToString(data))
- }
-
-
- val allOptions = mutableMapOf<String, ManagedOption<*>>()
- val sortedOptions = mutableListOf<ManagedOption<*>>()
-
- private var latestGuiAppender: GuiAppender? = null
-
- protected fun <T : Any> option(
- propertyName: String,
- default: () -> T,
- handler: OptionHandler<T>
- ): ManagedOption<T> {
- if (propertyName in allOptions) error("Cannot register the same name twice")
- return ManagedOption(this, propertyName, default, handler).also {
- it.handler.initOption(it)
- it.load(data)
- allOptions[propertyName] = it
- sortedOptions.add(it)
- }
- }
-
- protected fun toggle(propertyName: String, default: () -> Boolean): ManagedOption<Boolean> {
- return option(propertyName, default, BooleanHandler(this))
- }
-
- protected fun duration(
- propertyName: String,
- min: Duration,
- max: Duration,
- default: () -> Duration,
- ): ManagedOption<Duration> {
- return option(propertyName, default, DurationHandler(this, min, max))
- }
-
-
- protected fun position(
- propertyName: String,
- width: Int,
- height: Int,
- default: () -> Point,
- ): ManagedOption<HudMeta> {
- val label = Text.translatable("firmament.config.${name}.${propertyName}")
- return option(propertyName, {
- val p = default()
- HudMeta(HudPosition(p.x, p.y, 1F), label, width, height)
- }, HudMetaHandler(this, label, width, height))
- }
-
- protected fun keyBinding(
- propertyName: String,
- default: () -> Int,
- ): ManagedOption<SavedKeyBinding> = keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(default()) }
-
- protected fun keyBindingWithOutDefaultModifiers(
- propertyName: String,
- default: () -> SavedKeyBinding,
- ): ManagedOption<SavedKeyBinding> {
- return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this))
- }
-
- protected fun keyBindingWithDefaultUnbound(
- propertyName: String,
- ): ManagedOption<SavedKeyBinding> {
- return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) }
- }
-
- protected fun integer(
- propertyName: String,
- min: Int,
- max: Int,
- default: () -> Int,
- ): ManagedOption<Int> {
- return option(propertyName, default, IntegerHandler(this, min, max))
- }
-
- protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption<Unit> {
- return option(propertyName, { }, ClickHandler(this, runnable))
- }
-
- protected fun string(propertyName: String, default: () -> String): ManagedOption<String> {
- return option(propertyName, default, StringHandler(this))
- }
-
-
- fun reloadGui() {
- latestGuiAppender?.reloadables?.forEach { it() }
- }
-
- val labelText = Text.translatable("firmament.config.${name}")
-
- fun getConfigEditor(parent: Screen? = null): Screen {
- var screen: Screen? = null
- val guiapp = GuiAppender(400) { requireNotNull(screen) { "Screen Accessor called too early" } }
- latestGuiAppender = guiapp
- guiapp.appendFullRow(RowComponent(
- FirmButtonComponent(TextComponent("←")) {
- if (parent != null) {
- save()
- setScreenLater(parent)
- } else {
- AllConfigsGui.showAllGuis()
- }
- }
- ))
- sortedOptions.forEach { it.appendToGui(guiapp) }
- guiapp.reloadables.forEach { it() }
- val component = CenterComponent(PanelComponent(ScrollPanelComponent(400, 300, ColumnComponent(guiapp.panel)), 10, PanelComponent.DefaultBackgroundRenderer.VANILLA))
- screen = object : GuiComponentWrapper(GuiContext(component)) {
- override fun close() {
- if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
- client!!.setScreen(parent)
- }
- }
- }
- return screen
- }
-
- fun showConfigEditor(parent: Screen? = null) {
- setScreenLater(getConfigEditor(parent))
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfigElement.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfigElement.kt
deleted file mode 100644
index 28cd6b8..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedConfigElement.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-abstract class ManagedConfigElement {
- abstract val name: String
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedOption.kt b/src/main/kotlin/moe/nea/firmament/gui/config/ManagedOption.kt
deleted file mode 100644
index b7264e8..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/ManagedOption.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonObject
-import kotlin.properties.ReadWriteProperty
-import kotlin.reflect.KProperty
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-
-class ManagedOption<T : Any>(
- val element: ManagedConfigElement,
- val propertyName: String,
- val default: () -> T,
- val handler: ManagedConfig.OptionHandler<T>
-) : ReadWriteProperty<Any?, T>, GetSetter<T> {
- override fun set(newValue: T) {
- this.value = newValue
- }
-
- override fun get(): T {
- return this.value
- }
-
- val rawLabelText = "firmament.config.${element.name}.${propertyName}"
- val labelText = Text.translatable(rawLabelText)
-
- lateinit var value: T
-
- override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
- this.value = value
- }
-
- override fun getValue(thisRef: Any?, property: KProperty<*>): T {
- return value
- }
-
- fun load(root: JsonElement) {
- if (root is JsonObject && root.containsKey(propertyName)) {
- try {
- value = handler.fromJson(root[propertyName]!!)
- return
- } catch (e: Exception) {
- Firmament.logger.error(
- "Exception during loading of config file ${element.name}. This will reset this config.",
- e
- )
- }
- }
- value = default()
- }
-
- fun toJson(): JsonElement? {
- return handler.toJson(value)
- }
-
- fun appendToGui(guiapp: GuiAppender) {
- handler.emitGuiElements(this, guiapp)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/config/StringHandler.kt b/src/main/kotlin/moe/nea/firmament/gui/config/StringHandler.kt
deleted file mode 100644
index a326abb..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/config/StringHandler.kt
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-package moe.nea.firmament.gui.config
-
-import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.json.jsonPrimitive
-import net.minecraft.text.Text
-
-class StringHandler(val config: ManagedConfig) : ManagedConfig.OptionHandler<String> {
- override fun toJson(element: String): JsonElement? {
- return JsonPrimitive(element)
- }
-
- override fun fromJson(element: JsonElement): String {
- return element.jsonPrimitive.content
- }
-
- override fun emitGuiElements(opt: ManagedOption<String>, guiAppender: GuiAppender) {
- guiAppender.appendLabeledRow(
- opt.labelText,
- TextFieldComponent(
- object : GetSetter<String> by opt {
- override fun set(newValue: String) {
- opt.set(newValue)
- config.save()
- }
- },
- 130,
- suggestion = Text.translatableWithFallback(opt.rawLabelText + ".hint", "").string
- ),
- )
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityModifier.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/EntityModifier.kt
deleted file mode 100644
index 9623070..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityModifier.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-
-fun interface EntityModifier {
- fun apply(entity: LivingEntity, info: JsonObject): LivingEntity
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityRenderer.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/EntityRenderer.kt
deleted file mode 100644
index 8c7428d..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityRenderer.kt
+++ /dev/null
@@ -1,197 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.Gson
-import com.google.gson.JsonArray
-import com.google.gson.JsonObject
-import org.apache.logging.log4j.LogManager
-import org.joml.Quaternionf
-import org.joml.Vector3f
-import kotlin.math.atan
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.ingame.InventoryScreen
-import net.minecraft.entity.Entity
-import net.minecraft.entity.EntityType
-import net.minecraft.entity.LivingEntity
-import net.minecraft.util.Identifier
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.assertNotNullOr
-import moe.nea.firmament.util.iterate
-import moe.nea.firmament.util.openFirmamentResource
-import moe.nea.firmament.util.render.enableScissorWithTranslation
-
-object EntityRenderer {
- val fakeWorld = FakeWorld()
- private fun <T : Entity> t(entityType: EntityType<T>): () -> T {
- return { entityType.create(fakeWorld)!! }
- }
-
- val entityIds: Map<String, () -> LivingEntity> = mapOf(
- "Zombie" to t(EntityType.ZOMBIE),
- "Chicken" to t(EntityType.CHICKEN),
- "Slime" to t(EntityType.SLIME),
- "Wolf" to t(EntityType.WOLF),
- "Skeleton" to t(EntityType.SKELETON),
- "Creeper" to t(EntityType.CREEPER),
- "Ocelot" to t(EntityType.OCELOT),
- "Blaze" to t(EntityType.BLAZE),
- "Rabbit" to t(EntityType.RABBIT),
- "Sheep" to t(EntityType.SHEEP),
- "Horse" to t(EntityType.HORSE),
- "Eisengolem" to t(EntityType.IRON_GOLEM),
- "Silverfish" to t(EntityType.SILVERFISH),
- "Witch" to t(EntityType.WITCH),
- "Endermite" to t(EntityType.ENDERMITE),
- "Snowman" to t(EntityType.SNOW_GOLEM),
- "Villager" to t(EntityType.VILLAGER),
- "Guardian" to t(EntityType.GUARDIAN),
- "ArmorStand" to t(EntityType.ARMOR_STAND),
- "Squid" to t(EntityType.SQUID),
- "Bat" to t(EntityType.BAT),
- "Spider" to t(EntityType.SPIDER),
- "CaveSpider" to t(EntityType.CAVE_SPIDER),
- "Pigman" to t(EntityType.ZOMBIFIED_PIGLIN),
- "Ghast" to t(EntityType.GHAST),
- "MagmaCube" to t(EntityType.MAGMA_CUBE),
- "Wither" to t(EntityType.WITHER),
- "Enderman" to t(EntityType.ENDERMAN),
- "Mooshroom" to t(EntityType.MOOSHROOM),
- "WitherSkeleton" to t(EntityType.WITHER_SKELETON),
- "Cow" to t(EntityType.COW),
- "Dragon" to t(EntityType.ENDER_DRAGON),
- "Player" to { makeGuiPlayer(fakeWorld) },
- "Pig" to t(EntityType.PIG),
- "Giant" to t(EntityType.GIANT),
- )
- val entityModifiers: Map<String, EntityModifier> = mapOf(
- "playerdata" to ModifyPlayerSkin,
- "equipment" to ModifyEquipment,
- "riding" to ModifyRiding,
- "charged" to ModifyCharged,
- "witherdata" to ModifyWither,
- "invisible" to ModifyInvisible,
- "age" to ModifyAge,
- "horse" to ModifyHorse,
- "name" to ModifyName,
- )
-
- val logger = LogManager.getLogger("Firmament.Entity")
- fun applyModifiers(entityId: String, modifiers: List<JsonObject>): LivingEntity? {
- val entityType = assertNotNullOr(entityIds[entityId]) {
- logger.error("Could not create entity with id $entityId")
- return null
- }
- var entity = entityType()
- for (modifierJson in modifiers) {
- val modifier = assertNotNullOr(modifierJson["type"]?.asString?.let(entityModifiers::get)) {
- logger.error("Unknown modifier $modifierJson")
- return null
- }
- entity = modifier.apply(entity, modifierJson)
- }
- return entity
- }
-
- fun constructEntity(info: JsonObject): LivingEntity? {
- val modifiers = (info["modifiers"] as JsonArray?)?.map { it.asJsonObject } ?: emptyList()
- val entityType = assertNotNullOr(info["entity"]?.asString) {
- logger.error("Missing entity type on entity object")
- return null
- }
- return applyModifiers(entityType, modifiers)
- }
-
- private val gson = Gson()
- fun constructEntity(location: Identifier): LivingEntity? {
- return constructEntity(
- gson.fromJson(
- location.openFirmamentResource().bufferedReader(), JsonObject::class.java
- )
- )
- }
-
- fun renderEntity(
- entity: LivingEntity,
- renderContext: DrawContext,
- posX: Int,
- posY: Int,
- mouseX: Float,
- mouseY: Float
- ) {
- var bottomOffset = 0.0F
- var currentEntity = entity
- val maxSize = entity.iterate { it.firstPassenger as? LivingEntity }
- .map { it.height }
- .sum()
- while (true) {
- currentEntity.age = MC.player?.age ?: 0
- drawEntity(
- renderContext,
- posX,
- posY,
- posX + 50,
- posY + 80,
- minOf(2F / maxSize, 1F) * 30,
- -bottomOffset,
- mouseX,
- mouseY,
- currentEntity
- )
- val next = currentEntity.firstPassenger as? LivingEntity ?: break
- bottomOffset += currentEntity.getPassengerRidingPos(next).y.toFloat() * 0.75F
- currentEntity = next
- }
- }
-
-
- fun drawEntity(
- context: DrawContext,
- x1: Int,
- y1: Int,
- x2: Int,
- y2: Int,
- size: Float,
- bottomOffset: Float,
- mouseX: Float,
- mouseY: Float,
- entity: LivingEntity
- ) {
- context.enableScissorWithTranslation(x1.toFloat(), y1.toFloat(), x2.toFloat(), y2.toFloat())
- val centerX = (x1 + x2) / 2f
- val centerY = (y1 + y2) / 2f
- val targetYaw = atan(((centerX - mouseX) / 40.0f).toDouble()).toFloat()
- val targetPitch = atan(((centerY - mouseY) / 40.0f).toDouble()).toFloat()
- val rotateToFaceTheFront = Quaternionf().rotateZ(Math.PI.toFloat())
- val rotateToFaceTheCamera = Quaternionf().rotateX(targetPitch * 20.0f * (Math.PI.toFloat() / 180))
- rotateToFaceTheFront.mul(rotateToFaceTheCamera)
- val oldBodyYaw = entity.bodyYaw
- val oldYaw = entity.yaw
- val oldPitch = entity.pitch
- val oldPrevHeadYaw = entity.prevHeadYaw
- val oldHeadYaw = entity.headYaw
- entity.bodyYaw = 180.0f + targetYaw * 20.0f
- entity.yaw = 180.0f + targetYaw * 40.0f
- entity.pitch = -targetPitch * 20.0f
- entity.headYaw = entity.yaw
- entity.prevHeadYaw = entity.yaw
- val vector3f = Vector3f(0.0f, entity.height / 2.0f + bottomOffset, 0.0f)
- InventoryScreen.drawEntity(
- context,
- centerX,
- centerY,
- size,
- vector3f,
- rotateToFaceTheFront,
- rotateToFaceTheCamera,
- entity
- )
- entity.bodyYaw = oldBodyYaw
- entity.yaw = oldYaw
- entity.pitch = oldPitch
- entity.prevHeadYaw = oldPrevHeadYaw
- entity.headYaw = oldHeadYaw
- context.disableScissor()
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityWidget.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/EntityWidget.kt
deleted file mode 100644
index 2e49072..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/EntityWidget.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import me.shedaniel.math.Dimension
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Element
-import net.minecraft.entity.LivingEntity
-
-class EntityWidget(val entity: LivingEntity, val point: Point) : WidgetWithBounds() {
- override fun children(): List<Element> {
- return emptyList()
- }
-
- var hasErrored = false
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- try {
- if (!hasErrored)
- EntityRenderer.renderEntity(entity, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat())
- } catch (ex: Exception) {
- EntityRenderer.logger.error("Failed to render constructed entity: $entity", ex)
- hasErrored = true
- }
- if (hasErrored) {
- context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt())
- }
- }
-
- override fun getBounds(): Rectangle {
- return Rectangle(point, Dimension(50, 80))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/FakeWorld.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/FakeWorld.kt
deleted file mode 100644
index f354d5a..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/FakeWorld.kt
+++ /dev/null
@@ -1,488 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.mojang.datafixers.util.Pair
-import com.mojang.serialization.Lifecycle
-import java.util.*
-import java.util.function.BooleanSupplier
-import java.util.function.Consumer
-import java.util.stream.Stream
-import kotlin.jvm.optionals.getOrNull
-import kotlin.streams.asSequence
-import net.minecraft.block.Block
-import net.minecraft.block.BlockState
-import net.minecraft.component.type.MapIdComponent
-import net.minecraft.entity.Entity
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.fluid.Fluid
-import net.minecraft.item.map.MapState
-import net.minecraft.recipe.BrewingRecipeRegistry
-import net.minecraft.recipe.Ingredient
-import net.minecraft.recipe.RecipeManager
-import net.minecraft.registry.BuiltinRegistries
-import net.minecraft.registry.DynamicRegistryManager
-import net.minecraft.registry.Registry
-import net.minecraft.registry.RegistryKey
-import net.minecraft.registry.RegistryKeys
-import net.minecraft.registry.RegistryWrapper
-import net.minecraft.registry.entry.RegistryEntry
-import net.minecraft.registry.entry.RegistryEntryInfo
-import net.minecraft.registry.entry.RegistryEntryList
-import net.minecraft.registry.entry.RegistryEntryOwner
-import net.minecraft.registry.tag.TagKey
-import net.minecraft.resource.featuretoggle.FeatureFlags
-import net.minecraft.resource.featuretoggle.FeatureSet
-import net.minecraft.scoreboard.Scoreboard
-import net.minecraft.sound.SoundCategory
-import net.minecraft.sound.SoundEvent
-import net.minecraft.util.Identifier
-import net.minecraft.util.TypeFilter
-import net.minecraft.util.function.LazyIterationConsumer
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Box
-import net.minecraft.util.math.ChunkPos
-import net.minecraft.util.math.Direction
-import net.minecraft.util.math.Vec3d
-import net.minecraft.util.math.random.Random
-import net.minecraft.util.profiler.DummyProfiler
-import net.minecraft.world.BlockView
-import net.minecraft.world.Difficulty
-import net.minecraft.world.GameRules
-import net.minecraft.world.MutableWorldProperties
-import net.minecraft.world.World
-import net.minecraft.world.biome.Biome
-import net.minecraft.world.biome.BiomeKeys
-import net.minecraft.world.chunk.Chunk
-import net.minecraft.world.chunk.ChunkManager
-import net.minecraft.world.chunk.ChunkStatus
-import net.minecraft.world.chunk.EmptyChunk
-import net.minecraft.world.chunk.light.LightingProvider
-import net.minecraft.world.entity.EntityLookup
-import net.minecraft.world.event.GameEvent
-import net.minecraft.world.tick.OrderedTick
-import net.minecraft.world.tick.QueryableTickScheduler
-import net.minecraft.world.tick.TickManager
-
-fun <T> makeRegistry(registryWrapper: RegistryWrapper.Impl<T>, key: RegistryKey<out Registry<T>>): Registry<T> {
- val inverseLookup = registryWrapper.streamEntries()
- .asSequence().map { it.value() to it.registryKey() }
- .toMap()
- val idLookup = registryWrapper.streamEntries()
- .asSequence()
- .map { it.registryKey() }
- .withIndex()
- .associate { it.value to it.index }
- val map = registryWrapper.streamEntries().asSequence().map { it.registryKey() to it.value() }.toMap(mutableMapOf())
- val inverseIdLookup = idLookup.asIterable().associate { (k, v) -> v to k }
- return object : Registry<T> {
- override fun get(key: RegistryKey<T>?): T? {
- return registryWrapper.getOptional(key).getOrNull()?.value()
- }
-
- override fun iterator(): MutableIterator<T> {
- return object : MutableIterator<T> {
- val iterator = registryWrapper.streamEntries().iterator()
- override fun hasNext(): Boolean {
- return iterator.hasNext()
- }
-
- override fun next(): T {
- return iterator.next().value()
- }
-
- override fun remove() {
- TODO("Not yet implemented")
- }
- }
- }
-
- override fun getRawId(value: T?): Int {
- return idLookup[inverseLookup[value ?: return -1] ?: return -1] ?: return -1
- }
-
- override fun get(id: Identifier?): T? {
- return get(RegistryKey.of(key, id))
- }
-
- override fun get(index: Int): T? {
- return get(inverseIdLookup[index] ?: return null)
- }
-
- override fun size(): Int {
- return idLookup.size
- }
-
- override fun getKey(): RegistryKey<out Registry<T>> {
- return key
- }
-
- override fun getEntryInfo(key: RegistryKey<T>?): Optional<RegistryEntryInfo> {
- TODO("Not yet implemented")
- }
-
- override fun getLifecycle(): Lifecycle {
- return Lifecycle.stable()
- }
-
- override fun getDefaultEntry(): Optional<RegistryEntry.Reference<T>> {
- return Optional.empty()
- }
-
- override fun getIds(): MutableSet<Identifier> {
- return idLookup.keys.mapTo(mutableSetOf()) { it.value }
- }
-
- override fun getEntrySet(): MutableSet<MutableMap.MutableEntry<RegistryKey<T>, T>> {
- return map.entries
- }
-
- override fun getKeys(): MutableSet<RegistryKey<T>> {
- return map.keys
- }
-
- override fun getRandom(random: Random?): Optional<RegistryEntry.Reference<T>> {
- return registryWrapper.streamEntries().findFirst()
- }
-
- override fun containsId(id: Identifier?): Boolean {
- return idLookup.containsKey(RegistryKey.of(key, id ?: return false))
- }
-
- override fun freeze(): Registry<T> {
- return this
- }
-
- override fun getEntry(rawId: Int): Optional<RegistryEntry.Reference<T>> {
- val x = inverseIdLookup[rawId] ?: return Optional.empty()
- return Optional.of(RegistryEntry.Reference.standAlone(registryWrapper, x))
- }
-
- override fun streamEntries(): Stream<RegistryEntry.Reference<T>> {
- return registryWrapper.streamEntries()
- }
-
- override fun streamTagsAndEntries(): Stream<Pair<TagKey<T>, RegistryEntryList.Named<T>>> {
- return streamTags().map { Pair(it, getOrCreateEntryList(it)) }
- }
-
- override fun streamTags(): Stream<TagKey<T>> {
- return registryWrapper.streamTagKeys()
- }
-
- override fun clearTags() {
- }
-
- override fun getEntryOwner(): RegistryEntryOwner<T> {
- return registryWrapper
- }
-
- override fun getReadOnlyWrapper(): RegistryWrapper.Impl<T> {
- return registryWrapper
- }
-
- override fun populateTags(tagEntries: MutableMap<TagKey<T>, MutableList<RegistryEntry<T>>>?) {
- }
-
- override fun getOrCreateEntryList(tag: TagKey<T>?): RegistryEntryList.Named<T> {
- return getEntryList(tag).orElseGet { RegistryEntryList.of(registryWrapper, tag) }
- }
-
- override fun getEntryList(tag: TagKey<T>?): Optional<RegistryEntryList.Named<T>> {
- return registryWrapper.getOptional(tag ?: return Optional.empty())
- }
-
- override fun getEntry(value: T): RegistryEntry<T> {
- return registryWrapper.getOptional(inverseLookup[value]!!).get()
- }
-
- override fun getEntry(key: RegistryKey<T>?): Optional<RegistryEntry.Reference<T>> {
- return registryWrapper.getOptional(key ?: return Optional.empty())
- }
-
- override fun getEntry(id: Identifier?): Optional<RegistryEntry.Reference<T>> {
- TODO("Not yet implemented")
- }
-
- override fun createEntry(value: T): RegistryEntry.Reference<T> {
- TODO("Not yet implemented")
- }
-
- override fun contains(key: RegistryKey<T>?): Boolean {
- return getEntry(key).isPresent
- }
-
- override fun getId(value: T): Identifier? {
- return (inverseLookup[value] ?: return null).value
- }
-
- override fun getKey(entry: T): Optional<RegistryKey<T>> {
- return Optional.ofNullable(inverseLookup[entry ?: return Optional.empty()])
- }
- }
-}
-
-fun createDynamicRegistry(): DynamicRegistryManager.Immutable {
- val wrapperLookup = BuiltinRegistries.createWrapperLookup()
- return object : DynamicRegistryManager.Immutable {
- override fun <E : Any?> getOptional(key: RegistryKey<out Registry<out E>>): Optional<Registry<E>> {
- val lookup = wrapperLookup.getOptionalWrapper(key).getOrNull() ?: return Optional.empty()
- val registry = makeRegistry(lookup, key as RegistryKey<out Registry<E>>)
- return Optional.of(registry)
- }
-
- fun <T> entry(reg: RegistryKey<out Registry<T>>): DynamicRegistryManager.Entry<T> {
- return DynamicRegistryManager.Entry(reg, getOptional(reg).get())
- }
-
- override fun streamAllRegistries(): Stream<DynamicRegistryManager.Entry<*>> {
- return wrapperLookup.streamAllRegistryKeys()
- .map { entry(it as RegistryKey<out Registry<Any>>) }
- }
- }
-}
-
-class FakeWorld(
- registries: DynamicRegistryManager.Immutable = createDynamicRegistry(),
-) : World(
- Properties,
- RegistryKey.of(RegistryKeys.WORLD, Identifier.of("firmament", "fakeworld")),
- registries,
- registries[RegistryKeys.DIMENSION_TYPE].entryOf(
- RegistryKey.of(
- RegistryKeys.DIMENSION_TYPE,
- Identifier.of("minecraft", "overworld")
- )
- ),
- { DummyProfiler.INSTANCE },
- true,
- false,
- 0, 0
-) {
- object Properties : MutableWorldProperties {
- override fun getSpawnPos(): BlockPos {
- return BlockPos.ORIGIN
- }
-
- override fun getSpawnAngle(): Float {
- return 0F
- }
-
- override fun getTime(): Long {
- return 0
- }
-
- override fun getTimeOfDay(): Long {
- return 0
- }
-
- override fun isThundering(): Boolean {
- return false
- }
-
- override fun isRaining(): Boolean {
- return false
- }
-
- override fun setRaining(raining: Boolean) {
- }
-
- override fun isHardcore(): Boolean {
- return false
- }
-
- override fun getGameRules(): GameRules {
- return GameRules()
- }
-
- override fun getDifficulty(): Difficulty {
- return Difficulty.HARD
- }
-
- override fun isDifficultyLocked(): Boolean {
- return false
- }
-
- override fun setSpawnPos(pos: BlockPos?, angle: Float) {}
- }
-
- override fun getPlayers(): List<PlayerEntity> {
- return emptyList()
- }
-
- override fun getBrightness(direction: Direction?, shaded: Boolean): Float {
- return 1f
- }
-
- override fun getGeneratorStoredBiome(biomeX: Int, biomeY: Int, biomeZ: Int): RegistryEntry<Biome> {
- return registryManager.get(RegistryKeys.BIOME).entryOf(BiomeKeys.PLAINS)
- }
-
- override fun getEnabledFeatures(): FeatureSet {
- return FeatureFlags.VANILLA_FEATURES
- }
-
- class FakeTickScheduler<T> : QueryableTickScheduler<T> {
- override fun scheduleTick(orderedTick: OrderedTick<T>?) {
- }
-
- override fun isQueued(pos: BlockPos?, type: T): Boolean {
- return true
- }
-
- override fun getTickCount(): Int {
- return 0
- }
-
- override fun isTicking(pos: BlockPos?, type: T): Boolean {
- return true
- }
-
- }
-
- override fun getBlockTickScheduler(): QueryableTickScheduler<Block> {
- return FakeTickScheduler()
- }
-
- override fun getFluidTickScheduler(): QueryableTickScheduler<Fluid> {
- return FakeTickScheduler()
- }
-
-
- class FakeChunkManager(val world: FakeWorld) : ChunkManager() {
- override fun getChunk(x: Int, z: Int, leastStatus: ChunkStatus?, create: Boolean): Chunk {
- return EmptyChunk(
- world,
- ChunkPos(x, z),
- world.registryManager.get(RegistryKeys.BIOME).entryOf(BiomeKeys.PLAINS)
- )
- }
-
- override fun getWorld(): BlockView {
- return world
- }
-
- override fun tick(shouldKeepTicking: BooleanSupplier?, tickChunks: Boolean) {
- }
-
- override fun getDebugString(): String {
- return "FakeChunkManager"
- }
-
- override fun getLoadedChunkCount(): Int {
- return 0
- }
-
- override fun getLightingProvider(): LightingProvider {
- return FakeLightingProvider(this)
- }
- }
-
- class FakeLightingProvider(chunkManager: FakeChunkManager) : LightingProvider(chunkManager, false, false)
-
- override fun getChunkManager(): ChunkManager {
- return FakeChunkManager(this)
- }
-
- override fun playSound(
- source: PlayerEntity?,
- x: Double,
- y: Double,
- z: Double,
- sound: RegistryEntry<SoundEvent>?,
- category: SoundCategory?,
- volume: Float,
- pitch: Float,
- seed: Long
- ) {
- }
-
- override fun syncWorldEvent(player: PlayerEntity?, eventId: Int, pos: BlockPos?, data: Int) {
- }
-
- override fun emitGameEvent(event: RegistryEntry<GameEvent>?, emitterPos: Vec3d?, emitter: GameEvent.Emitter?) {
- }
-
- override fun updateListeners(pos: BlockPos?, oldState: BlockState?, newState: BlockState?, flags: Int) {
- }
-
- override fun playSoundFromEntity(
- source: PlayerEntity?,
- entity: Entity?,
- sound: RegistryEntry<SoundEvent>?,
- category: SoundCategory?,
- volume: Float,
- pitch: Float,
- seed: Long
- ) {
- }
-
- override fun asString(): String {
- return "FakeWorld"
- }
-
- override fun getEntityById(id: Int): Entity? {
- return null
- }
-
- override fun getTickManager(): TickManager {
- return TickManager()
- }
-
- override fun getMapState(id: MapIdComponent?): MapState? {
- return null
- }
-
- override fun putMapState(id: MapIdComponent?, state: MapState?) {
- }
-
- override fun increaseAndGetMapId(): MapIdComponent {
- return MapIdComponent(0)
- }
-
- override fun setBlockBreakingInfo(entityId: Int, pos: BlockPos?, progress: Int) {
- }
-
- override fun getScoreboard(): Scoreboard {
- return Scoreboard()
- }
-
- override fun getRecipeManager(): RecipeManager {
- return RecipeManager(registryManager)
- }
-
- object FakeEntityLookup : EntityLookup<Entity> {
- override fun get(id: Int): Entity? {
- return null
- }
-
- override fun get(uuid: UUID?): Entity? {
- return null
- }
-
- override fun iterate(): MutableIterable<Entity> {
- return mutableListOf()
- }
-
- override fun <U : Entity?> forEachIntersects(
- filter: TypeFilter<Entity, U>?,
- box: Box?,
- consumer: LazyIterationConsumer<U>?
- ) {
- }
-
- override fun forEachIntersects(box: Box?, action: Consumer<Entity>?) {
- }
-
- override fun <U : Entity?> forEach(filter: TypeFilter<Entity, U>?, consumer: LazyIterationConsumer<U>?) {
- }
-
- }
-
- override fun getEntityLookup(): EntityLookup<Entity> {
- return FakeEntityLookup
- }
-
- override fun getBrewingRecipeRegistry(): BrewingRecipeRegistry {
- return BrewingRecipeRegistry.EMPTY
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/GuiPlayer.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/GuiPlayer.kt
deleted file mode 100644
index d00b44d..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/GuiPlayer.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.mojang.authlib.GameProfile
-import java.util.*
-import net.minecraft.client.network.AbstractClientPlayerEntity
-import net.minecraft.client.util.DefaultSkinHelper
-import net.minecraft.client.util.SkinTextures
-import net.minecraft.client.util.SkinTextures.Model
-import net.minecraft.client.world.ClientWorld
-import net.minecraft.util.Identifier
-import net.minecraft.util.math.BlockPos
-import net.minecraft.world.World
-
-/**
- * @see moe.nea.firmament.init.EarlyRiser
- */
-fun makeGuiPlayer(world: FakeWorld): GuiPlayer {
- val constructor = GuiPlayer::class.java.getDeclaredConstructor(
- World::class.java,
- BlockPos::class.java,
- Float::class.javaPrimitiveType,
- GameProfile::class.java
- )
- return constructor.newInstance(world, BlockPos.ORIGIN, 0F, GameProfile(UUID.randomUUID(), "Linnea"))
-}
-
-class GuiPlayer(world: ClientWorld?, profile: GameProfile?) : AbstractClientPlayerEntity(world, profile) {
- override fun isSpectator(): Boolean {
- return false
- }
-
- override fun isCreative(): Boolean {
- return false
- }
-
- override fun shouldRenderName(): Boolean {
- return false
- }
-
- var skinTexture: Identifier = DefaultSkinHelper.getSkinTextures(this.getUuid()).texture
- var capeTexture: Identifier? = null
- var model: Model = Model.WIDE
- override fun getSkinTextures(): SkinTextures {
- return SkinTextures(
- skinTexture,
- null,
- capeTexture,
- null,
- model,
- true
- )
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyAge.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyAge.kt
deleted file mode 100644
index a65c368..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyAge.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.decoration.ArmorStandEntity
-import net.minecraft.entity.mob.ZombieEntity
-import net.minecraft.entity.passive.PassiveEntity
-
-object ModifyAge : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- val isBaby = info["baby"]?.asBoolean ?: false
- if (entity is PassiveEntity) {
- entity.breedingAge = if (isBaby) -1 else 1
- } else if (entity is ZombieEntity) {
- entity.isBaby = isBaby
- } else if (entity is ArmorStandEntity) {
- entity.isSmall = isBaby
- } else {
- error("Cannot set age for $entity")
- }
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyCharged.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyCharged.kt
deleted file mode 100644
index d22f6e3..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyCharged.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.mob.CreeperEntity
-
-object ModifyCharged : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- require(entity is CreeperEntity)
- entity.dataTracker.set(CreeperEntity.CHARGED, true)
- return entity
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyEquipment.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyEquipment.kt
deleted file mode 100644
index 73e450e..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyEquipment.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.component.type.DyedColorComponent
-import net.minecraft.entity.EquipmentSlot
-import net.minecraft.entity.LivingEntity
-import net.minecraft.item.ArmorItem
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import moe.nea.firmament.rei.SBItemStack
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.item.setEncodedSkullOwner
-import moe.nea.firmament.util.item.zeroUUID
-
-object ModifyEquipment : EntityModifier {
- val names = mapOf(
- "hand" to EquipmentSlot.MAINHAND,
- "helmet" to EquipmentSlot.HEAD,
- "chestplate" to EquipmentSlot.CHEST,
- "leggings" to EquipmentSlot.LEGS,
- "feet" to EquipmentSlot.FEET,
- )
-
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- names.forEach { (key, slot) ->
- info[key]?.let {
- entity.equipStack(slot, createItem(it.asString))
- }
- }
- return entity
- }
-
- private fun createItem(item: String): ItemStack {
- val split = item.split("#")
- if (split.size != 2) return SBItemStack(SkyblockId(item)).asImmutableItemStack()
- val (type, data) = split
- return when (type) {
- "SKULL" -> ItemStack(Items.PLAYER_HEAD).also { it.setEncodedSkullOwner(zeroUUID, data) }
- "LEATHER_LEGGINGS" -> coloredLeatherArmor(Items.LEATHER_LEGGINGS, data)
- "LEATHER_BOOTS" -> coloredLeatherArmor(Items.LEATHER_BOOTS, data)
- "LEATHER_HELMET" -> coloredLeatherArmor(Items.LEATHER_HELMET, data)
- "LEATHER_CHESTPLATE" -> coloredLeatherArmor(Items.LEATHER_CHESTPLATE, data)
- else -> error("Unknown leather piece: $type")
- }
- }
-
- private fun coloredLeatherArmor(leatherArmor: Item, data: String): ItemStack {
- val stack = ItemStack(leatherArmor)
- stack.set(DataComponentTypes.DYED_COLOR, DyedColorComponent(data.toInt(16), false))
- return stack
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyHorse.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyHorse.kt
deleted file mode 100644
index 8ac011b..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyHorse.kt
+++ /dev/null
@@ -1,61 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonNull
-import com.google.gson.JsonObject
-import kotlin.experimental.and
-import kotlin.experimental.inv
-import kotlin.experimental.or
-import net.minecraft.entity.EntityType
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.passive.AbstractHorseEntity
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import moe.nea.firmament.gui.entity.EntityRenderer.fakeWorld
-
-object ModifyHorse : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- require(entity is AbstractHorseEntity)
- var entity: AbstractHorseEntity = entity
- info["kind"]?.let {
- entity = when (it.asString) {
- "skeleton" -> EntityType.SKELETON_HORSE.create(fakeWorld)!!
- "zombie" -> EntityType.ZOMBIE_HORSE.create(fakeWorld)!!
- "mule" -> EntityType.MULE.create(fakeWorld)!!
- "donkey" -> EntityType.DONKEY.create(fakeWorld)!!
- "horse" -> EntityType.HORSE.create(fakeWorld)!!
- else -> error("Unknown horse kind $it")
- }
- }
- info["armor"]?.let {
- if (it is JsonNull) {
- entity.setHorseArmor(ItemStack.EMPTY)
- } else {
- when (it.asString) {
- "iron" -> entity.setHorseArmor(ItemStack(Items.IRON_HORSE_ARMOR))
- "golden" -> entity.setHorseArmor(ItemStack(Items.GOLDEN_HORSE_ARMOR))
- "diamond" -> entity.setHorseArmor(ItemStack(Items.DIAMOND_HORSE_ARMOR))
- else -> error("Unknown horse armor $it")
- }
- }
- }
- info["saddled"]?.let {
- entity.setIsSaddled(it.asBoolean)
- }
- return entity
- }
-
-}
-
-fun AbstractHorseEntity.setIsSaddled(shouldBeSaddled: Boolean) {
- val oldFlag = dataTracker.get(AbstractHorseEntity.HORSE_FLAGS)
- dataTracker.set(
- AbstractHorseEntity.HORSE_FLAGS,
- if (shouldBeSaddled) oldFlag or AbstractHorseEntity.SADDLED_FLAG.toByte()
- else oldFlag and AbstractHorseEntity.SADDLED_FLAG.toByte().inv()
- )
-}
-
-fun AbstractHorseEntity.setHorseArmor(itemStack: ItemStack) {
- items.setStack(1, itemStack)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyInvisible.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyInvisible.kt
deleted file mode 100644
index 8d36991..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyInvisible.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-
-object ModifyInvisible : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- entity.isInvisible = info.get("invisible")?.asBoolean ?: true
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyName.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyName.kt
deleted file mode 100644
index a03da96..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyName.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-import net.minecraft.text.Text
-
-object ModifyName : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- entity.customName = Text.literal(info.get("name").asString)
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyPlayerSkin.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyPlayerSkin.kt
deleted file mode 100644
index 28f0070..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyPlayerSkin.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import com.google.gson.JsonPrimitive
-import kotlin.experimental.and
-import kotlin.experimental.or
-import net.minecraft.client.util.SkinTextures
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.player.PlayerEntity
-import net.minecraft.entity.player.PlayerModelPart
-import net.minecraft.util.Identifier
-
-object ModifyPlayerSkin : EntityModifier {
- val playerModelPartIndex = PlayerModelPart.entries.associateBy { it.getName() }
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- require(entity is GuiPlayer)
- info["cape"]?.let {
- entity.capeTexture = Identifier.of(it.asString)
- }
- info["skin"]?.let {
- entity.skinTexture = Identifier.of(it.asString)
- }
- info["slim"]?.let {
- entity.model = if (it.asBoolean) SkinTextures.Model.SLIM else SkinTextures.Model.WIDE
- }
- info["parts"]?.let {
- var trackedData = entity.dataTracker.get(PlayerEntity.PLAYER_MODEL_PARTS)
- if (it is JsonPrimitive && it.isBoolean) {
- trackedData = (if (it.asBoolean) -1 else 0).toByte()
- } else {
- val obj = it.asJsonObject
- for ((k, v) in obj.entrySet()) {
- val part = playerModelPartIndex[k]!!
- trackedData = if (v.asBoolean) {
- trackedData and (part.bitFlag.inv().toByte())
- } else {
- trackedData or (part.bitFlag.toByte())
- }
- }
- }
- entity.dataTracker.set(PlayerEntity.PLAYER_MODEL_PARTS, trackedData)
- }
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyRiding.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyRiding.kt
deleted file mode 100644
index 5c4c78d..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyRiding.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-
-object ModifyRiding : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- val newEntity = EntityRenderer.constructEntity(info)
- require(newEntity != null)
- newEntity.startRiding(entity, true)
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyWither.kt b/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyWither.kt
deleted file mode 100644
index 6083d88..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/entity/ModifyWither.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-package moe.nea.firmament.gui.entity
-
-import com.google.gson.JsonObject
-import net.minecraft.entity.LivingEntity
-import net.minecraft.entity.boss.WitherEntity
-
-object ModifyWither : EntityModifier {
- override fun apply(entity: LivingEntity, info: JsonObject): LivingEntity {
- require(entity is WitherEntity)
- info["tiny"]?.let {
- entity.setInvulTimer(if (it.asBoolean) 800 else 0)
- }
- info["armored"]?.let {
- entity.health = if (it.asBoolean) 1F else entity.maxHealth
- }
- return entity
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/gui/hud/MoulConfigHud.kt b/src/main/kotlin/moe/nea/firmament/gui/hud/MoulConfigHud.kt
deleted file mode 100644
index e77d9af..0000000
--- a/src/main/kotlin/moe/nea/firmament/gui/hud/MoulConfigHud.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-
-package moe.nea.firmament.gui.hud
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
-import io.github.notenoughupdates.moulconfig.gui.GuiContext
-import io.github.notenoughupdates.moulconfig.gui.component.TextComponent
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SynchronousResourceReloader
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.HudRenderEvent
-import moe.nea.firmament.gui.config.HudMeta
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.MoulConfigUtils
-
-abstract class MoulConfigHud(
- val name: String,
- val hudMeta: HudMeta,
-) {
- companion object {
- private val componentWrapper by lazy {
- object : GuiComponentWrapper(GuiContext(TextComponent("§cERROR"))) {
- init {
- this.client = MC.instance
- }
- }
- }
- }
-
- private var fragment: GuiContext? = null
-
- fun forceInit() {
- }
-
- open fun shouldRender(): Boolean {
- return true
- }
-
- init {
- require(name.matches("^[a-z_/]+$".toRegex()))
- HudRenderEvent.subscribe {
- if (!shouldRender()) return@subscribe
- val renderContext = componentWrapper.createContext(it.context)
- if (fragment == null)
- loadFragment()
- it.context.matrices.push()
- hudMeta.applyTransformations(it.context.matrices)
- val renderContextTranslated =
- renderContext.translated(hudMeta.absoluteX, hudMeta.absoluteY, hudMeta.width, hudMeta.height)
- .scaled(hudMeta.scale)
- fragment!!.root.render(renderContextTranslated)
- it.context.matrices.pop()
- }
- FinalizeResourceManagerEvent.subscribe {
- MC.resourceManager.registerReloader(object : SynchronousResourceReloader {
- override fun reload(manager: ResourceManager?) {
- fragment = null
- }
- })
- }
- }
-
- fun loadFragment() {
- fragment = MoulConfigUtils.loadGui(name, this)
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt b/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt
deleted file mode 100644
index 96f47f7..0000000
--- a/src/main/kotlin/moe/nea/firmament/jarvis/JarvisIntegration.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-package moe.nea.firmament.jarvis
-
-import moe.nea.jarvis.api.Jarvis
-import moe.nea.jarvis.api.JarvisConfigOption
-import moe.nea.jarvis.api.JarvisHud
-import moe.nea.jarvis.api.JarvisPlugin
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.features.FeatureManager
-import moe.nea.firmament.gui.config.HudMeta
-import moe.nea.firmament.gui.config.HudMetaHandler
-import moe.nea.firmament.repo.RepoManager
-
-class JarvisIntegration : JarvisPlugin {
- override fun getModId(): String =
- Firmament.MOD_ID
-
- companion object {
- lateinit var jarvis: Jarvis
- }
-
- override fun onInitialize(jarvis: Jarvis) {
- Companion.jarvis = jarvis
- }
-
- val configs
- get() = listOf(
- RepoManager.Config
- ) + FeatureManager.allFeatures.mapNotNull { it.config }
-
-
- override fun getAllHuds(): List<JarvisHud> {
- return configs.flatMap { config ->
- config.sortedOptions.mapNotNull { if (it.handler is HudMetaHandler) it.value as HudMeta else null }
- }
- }
-
- override fun onHudEditorClosed() {
- configs.forEach { it.save() }
- }
-
- override fun getAllConfigOptions(): List<JarvisConfigOption> {
- return configs.flatMap { config ->
- config.sortedOptions.map {
- object : JarvisConfigOption {
- override fun title(): Text {
- return it.labelText
- }
-
- override fun description(): List<Text> {
- return emptyList()
- }
-
- override fun jumpTo(parentScreen: Screen?): Screen {
- return config.getConfigEditor(parentScreen)
- }
- }
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/keybindings/FirmamentKeyBindings.kt b/src/main/kotlin/moe/nea/firmament/keybindings/FirmamentKeyBindings.kt
deleted file mode 100644
index e2bed8d..0000000
--- a/src/main/kotlin/moe/nea/firmament/keybindings/FirmamentKeyBindings.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-package moe.nea.firmament.keybindings
-
-import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper
-import net.minecraft.client.option.KeyBinding
-import net.minecraft.client.util.InputUtil
-import moe.nea.firmament.gui.config.KeyBindingHandler
-import moe.nea.firmament.gui.config.ManagedOption
-
-object FirmamentKeyBindings {
- fun registerKeyBinding(name: String, config: ManagedOption<SavedKeyBinding>) {
- val vanillaKeyBinding = KeyBindingHelper.registerKeyBinding(
- KeyBinding(
- name,
- InputUtil.Type.KEYSYM,
- -1,
- "firmament.key.category"
- )
- )
- keyBindings[vanillaKeyBinding] = config
- }
-
- val keyBindings = mutableMapOf<KeyBinding, ManagedOption<SavedKeyBinding>>()
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/keybindings/IKeyBinding.kt b/src/main/kotlin/moe/nea/firmament/keybindings/IKeyBinding.kt
deleted file mode 100644
index 1975361..0000000
--- a/src/main/kotlin/moe/nea/firmament/keybindings/IKeyBinding.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-package moe.nea.firmament.keybindings
-
-import net.minecraft.client.option.KeyBinding
-
-interface IKeyBinding {
- fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean
-
- fun withModifiers(wantedModifiers: Int): IKeyBinding {
- val old = this
- return object : IKeyBinding {
- override fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- return old.matches(keyCode, scanCode, modifiers) && (modifiers and wantedModifiers) == wantedModifiers
- }
- }
- }
-
- companion object {
- fun minecraft(keyBinding: KeyBinding) = object : IKeyBinding {
- override fun matches(keyCode: Int, scanCode: Int, modifiers: Int) =
- keyBinding.matchesKey(keyCode, scanCode)
- }
-
- fun ofKeyCode(wantedKeyCode: Int) = object : IKeyBinding {
- override fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean = keyCode == wantedKeyCode
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt b/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt
deleted file mode 100644
index 8607fd0..0000000
--- a/src/main/kotlin/moe/nea/firmament/keybindings/SavedKeyBinding.kt
+++ /dev/null
@@ -1,106 +0,0 @@
-
-
-package moe.nea.firmament.keybindings
-
-import org.lwjgl.glfw.GLFW
-import kotlinx.serialization.Serializable
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.util.InputUtil
-import net.minecraft.text.Text
-import moe.nea.firmament.util.MC
-
-@Serializable
-data class SavedKeyBinding(
- val keyCode: Int,
- val shift: Boolean = false,
- val ctrl: Boolean = false,
- val alt: Boolean = false,
-) : IKeyBinding {
- val isBound: Boolean get() = keyCode != GLFW.GLFW_KEY_UNKNOWN
-
- constructor(keyCode: Int, mods: Triple<Boolean, Boolean, Boolean>) : this(
- keyCode,
- mods.first && keyCode != GLFW.GLFW_KEY_LEFT_SHIFT && keyCode != GLFW.GLFW_KEY_RIGHT_SHIFT,
- mods.second && keyCode != GLFW.GLFW_KEY_LEFT_CONTROL && keyCode != GLFW.GLFW_KEY_RIGHT_CONTROL,
- mods.third && keyCode != GLFW.GLFW_KEY_LEFT_ALT && keyCode != GLFW.GLFW_KEY_RIGHT_ALT,
- )
-
- constructor(keyCode: Int, mods: Int) : this(keyCode, getMods(mods))
-
- companion object {
- fun getMods(modifiers: Int): Triple<Boolean, Boolean, Boolean> {
- return Triple(
- modifiers and GLFW.GLFW_MOD_SHIFT != 0,
- modifiers and GLFW.GLFW_MOD_CONTROL != 0,
- modifiers and GLFW.GLFW_MOD_ALT != 0
- )
- }
-
- fun getModInt(): Int {
- val h = MC.window.handle
- val ctrl = if (MinecraftClient.IS_SYSTEM_MAC) {
- InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SUPER)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SUPER)
- } else InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_CONTROL)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_CONTROL)
- val shift = isShiftDown()
- val alt = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_ALT)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_ALT)
- var mods = 0
- if (ctrl) mods = mods or GLFW.GLFW_MOD_CONTROL
- if (shift) mods = mods or GLFW.GLFW_MOD_SHIFT
- if (alt) mods = mods or GLFW.GLFW_MOD_ALT
- return mods
- }
-
- private val h get() = MC.window.handle
- fun isShiftDown() = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SHIFT)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SHIFT)
-
- }
-
- fun isPressed(atLeast: Boolean = false): Boolean {
- if (!isBound) return false
- val h = MC.window.handle
- if (!InputUtil.isKeyPressed(h, keyCode)) return false
-
- val ctrl = if (MinecraftClient.IS_SYSTEM_MAC) {
- InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_SUPER)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_SUPER)
- } else InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_CONTROL)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_CONTROL)
- val shift = isShiftDown()
- val alt = InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_LEFT_ALT)
- || InputUtil.isKeyPressed(h, GLFW.GLFW_KEY_RIGHT_ALT)
- if (atLeast)
- return (ctrl >= this.ctrl) &&
- (alt >= this.alt) &&
- (shift >= this.shift)
-
- return (ctrl == this.ctrl) &&
- (alt == this.alt) &&
- (shift == this.shift)
- }
-
- override fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- if (this.keyCode == GLFW.GLFW_KEY_UNKNOWN) return false
- return keyCode == this.keyCode && getMods(modifiers) == Triple(shift, ctrl, alt)
- }
-
- fun format(): Text {
- val stroke = Text.literal("")
- if (ctrl) {
- stroke.append("CTRL + ")
- }
- if (alt) {
- stroke.append("ALT + ")
- }
- if (shift) {
- stroke.append("SHIFT + ") // TODO: translations?
- }
-
- stroke.append(InputUtil.Type.KEYSYM.createFromCode(keyCode).localizedText)
- return stroke
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/modmenu/FirmamentModMenuPlugin.kt b/src/main/kotlin/moe/nea/firmament/modmenu/FirmamentModMenuPlugin.kt
deleted file mode 100644
index f889bf3..0000000
--- a/src/main/kotlin/moe/nea/firmament/modmenu/FirmamentModMenuPlugin.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-package moe.nea.firmament.modmenu
-
-import com.terraformersmc.modmenu.api.ConfigScreenFactory
-import com.terraformersmc.modmenu.api.ModMenuApi
-import moe.nea.firmament.gui.config.AllConfigsGui
-
-class FirmamentModMenuPlugin : ModMenuApi {
- override fun getModConfigScreenFactory(): ConfigScreenFactory<*> {
- return ConfigScreenFactory { AllConfigsGui.makeScreen(it) }
- }
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt b/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt
deleted file mode 100644
index b585336..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/FirmamentReiPlugin.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import me.shedaniel.rei.api.client.plugins.REIClientPlugin
-import me.shedaniel.rei.api.client.registry.category.CategoryRegistry
-import me.shedaniel.rei.api.client.registry.display.DisplayRegistry
-import me.shedaniel.rei.api.client.registry.entry.CollapsibleEntryRegistry
-import me.shedaniel.rei.api.client.registry.entry.EntryRegistry
-import me.shedaniel.rei.api.client.registry.screen.ExclusionZones
-import me.shedaniel.rei.api.client.registry.screen.OverlayDecider
-import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
-import me.shedaniel.rei.api.client.registry.transfer.TransferHandler
-import me.shedaniel.rei.api.client.registry.transfer.TransferHandlerRegistry
-import me.shedaniel.rei.api.common.entry.EntryStack
-import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry
-import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.GenericContainerScreen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.item.ItemStack
-import net.minecraft.text.Text
-import net.minecraft.util.ActionResult
-import net.minecraft.util.Identifier
-import moe.nea.firmament.events.HandledScreenPushREIEvent
-import moe.nea.firmament.features.inventory.CraftingOverlay
-import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
-import moe.nea.firmament.rei.recipes.SBForgeRecipe
-import moe.nea.firmament.rei.recipes.SBKatRecipe
-import moe.nea.firmament.rei.recipes.SBMobDropRecipe
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.skyblockId
-import moe.nea.firmament.util.unformattedString
-
-
-class FirmamentReiPlugin : REIClientPlugin {
-
- companion object {
- fun EntryStack<SBItemStack>.asItemEntry(): EntryStack<ItemStack> {
- return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack())
- }
-
- val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems")
- }
-
- override fun registerTransferHandlers(registry: TransferHandlerRegistry) {
- registry.register(TransferHandler { context ->
- val screen = context.containerScreen
- val display = context.display
- if (display !is SBCraftingRecipe || screen !is GenericContainerScreen || screen.title?.unformattedString != "Craft Item") {
- return@TransferHandler TransferHandler.Result.createNotApplicable()
- }
- if (context.isActuallyCrafting)
- CraftingOverlay.setOverlay(screen, display)
- return@TransferHandler TransferHandler.Result.createSuccessful().blocksFurtherHandling(true)
- })
- }
-
- override fun registerEntryTypes(registry: EntryTypeRegistry) {
- registry.register(SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition)
- }
-
- override fun registerCategories(registry: CategoryRegistry) {
- registry.add(SBCraftingRecipe.Category)
- registry.add(SBForgeRecipe.Category)
- registry.add(SBMobDropRecipe.Category)
- registry.add(SBKatRecipe.Category)
- registry.add(SBEssenceUpgradeRecipe.Category)
- }
-
- override fun registerExclusionZones(zones: ExclusionZones) {
- zones.register(HandledScreen::class.java) { HandledScreenPushREIEvent.publish(HandledScreenPushREIEvent(it)).rectangles }
- zones.register(StorageOverlayScreen::class.java) { it.getBounds() }
- }
-
- override fun registerDisplays(registry: DisplayRegistry) {
- registry.registerDisplayGenerator(
- SBCraftingRecipe.Category.catIdentifier,
- SkyblockCraftingRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBForgeRecipe.Category.categoryIdentifier,
- SkyblockForgeRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBMobDropRecipe.Category.categoryIdentifier,
- SkyblockMobDropRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBKatRecipe.Category.categoryIdentifier,
- SkyblockKatRecipeDynamicGenerator)
- registry.registerDisplayGenerator(
- SBEssenceUpgradeRecipe.Category.categoryIdentifier,
- SkyblockEssenceRecipeDynamicGenerator
- )
- }
-
- override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) {
- if (!RepoManager.Config.disableItemGroups)
- RepoManager.neuRepo.constants.parents.parents
- .forEach { (parent, children) ->
- registry.group(
- SkyblockId(parent).identifier,
- Text.literal(RepoManager.getNEUItem(SkyblockId(parent))?.displayName ?: parent),
- (children + parent).map { SBItemEntryDefinition.getEntry(SkyblockId(it)) })
- }
- }
-
- override fun registerScreens(registry: ScreenRegistry) {
- registry.registerDecider(object : OverlayDecider {
- override fun <R : Screen?> isHandingScreen(screen: Class<R>?): Boolean {
- return screen == StorageOverlayScreen::class.java
- }
-
- override fun <R : Screen?> shouldScreenBeOverlaid(screen: R): ActionResult {
- return ActionResult.SUCCESS
- }
- })
- registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider)
- }
-
- override fun registerEntries(registry: EntryRegistry) {
- registry.removeEntryIf { true }
- RepoManager.neuRepo.items?.items?.values?.forEach { neuItem ->
- registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId))
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt
deleted file mode 100644
index ba99b30..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntryRenderer.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * SPDX-FileCopyrightText: 2018-2023 shedaniel <daniel@shedaniel.me>
- * SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
- * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- * SPDX-License-Identifier: MIT
- */
-
-package moe.nea.firmament.rei
-
-import com.mojang.blaze3d.platform.GlStateManager.DstFactor
-import com.mojang.blaze3d.platform.GlStateManager.SrcFactor
-import com.mojang.blaze3d.systems.RenderSystem
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.entry.renderer.BatchedEntryRenderer
-import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
-import me.shedaniel.rei.api.client.gui.widgets.Tooltip
-import me.shedaniel.rei.api.client.gui.widgets.TooltipContext
-import me.shedaniel.rei.api.common.entry.EntryStack
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.DiffuseLighting
-import net.minecraft.client.render.LightmapTextureManager
-import net.minecraft.client.render.OverlayTexture
-import net.minecraft.client.render.VertexConsumerProvider
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.render.model.json.ModelTransformationMode
-import net.minecraft.client.texture.SpriteAtlasTexture
-import net.minecraft.item.Item
-import net.minecraft.item.ItemStack
-import net.minecraft.item.tooltip.TooltipType
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-
-object NEUItemEntryRenderer : EntryRenderer<SBItemStack>, BatchedEntryRenderer<SBItemStack, BakedModel> {
- override fun render(
- entry: EntryStack<SBItemStack>,
- context: DrawContext,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- entry.asItemEntry().render(context, bounds, mouseX, mouseY, delta)
- }
-
- val minecraft = MinecraftClient.getInstance()
-
- override fun getTooltip(entry: EntryStack<SBItemStack>, tooltipContext: TooltipContext): Tooltip? {
- val stack = entry.value.asImmutableItemStack()
- val lore = stack.getTooltip(
- Item.TooltipContext.DEFAULT,
- null,
- TooltipType.BASIC
- )
- return Tooltip.create(lore)
- }
-
- override fun getExtraData(entry: EntryStack<SBItemStack>): BakedModel {
- return minecraft.itemRenderer.getModel(entry.asItemEntry().value, minecraft.world, minecraft.player, 0)
- }
-
- override fun getBatchIdentifier(entry: EntryStack<SBItemStack>?, bounds: Rectangle?, extraData: BakedModel): Int {
- return 1738923 + if (extraData.isSideLit) 1 else 0
- }
-
- override fun startBatch(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- delta: Float
- ) {
- val modelViewStack = RenderSystem.getModelViewStack()
- modelViewStack.pushMatrix()
- modelViewStack.scale(20.0f, 20.0f, 1.0f)
- RenderSystem.applyModelViewMatrix()
- setupGL(model)
- }
-
- fun setupGL(model: BakedModel) {
- minecraft.textureManager.getTexture(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
- .setFilter(false, false)
- RenderSystem.setShaderTexture(0, SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE)
- RenderSystem.enableBlend()
- RenderSystem.blendFunc(SrcFactor.SRC_ALPHA, DstFactor.ONE_MINUS_SRC_ALPHA)
- RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
- val sideLit = model.isSideLit
- if (!sideLit) {
- DiffuseLighting.disableGuiDepthLighting()
- }
- }
-
- override fun renderBase(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- immediate: VertexConsumerProvider.Immediate,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- if (entry.isEmpty) return
- val value = entry.asItemEntry().value
- graphics.matrices.push()
- graphics.matrices.translate(bounds.centerX.toFloat() / 20.0f, bounds.centerY.toFloat() / 20.0f, 0.0f)
- graphics.matrices.scale(
- bounds.getWidth().toFloat() / 20.0f,
- -(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 20.0f,
- 1.0f
- )
- minecraft
- .itemRenderer
- .renderItem(
- value,
- ModelTransformationMode.GUI,
- false,
- graphics.matrices,
- immediate,
- LightmapTextureManager.MAX_LIGHT_COORDINATE,
- OverlayTexture.DEFAULT_UV,
- model
- )
- graphics.matrices.pop()
-
- }
-
- override fun afterBase(
- entry: EntryStack<SBItemStack>,
- model: BakedModel,
- graphics: DrawContext,
- delta: Float
- ) {
- RenderSystem.getModelViewStack().popMatrix()
- RenderSystem.applyModelViewMatrix()
- this.endGL(model)
- }
-
- fun endGL(model: BakedModel) {
- RenderSystem.enableDepthTest()
- val sideLit = model.isSideLit
- if (!sideLit) {
- DiffuseLighting.enableGuiDepthLighting()
- }
- }
-
- override fun renderOverlay(
- entry: EntryStack<SBItemStack>,
- extraData: BakedModel,
- graphics: DrawContext,
- immediate: VertexConsumerProvider.Immediate,
- bounds: Rectangle,
- mouseX: Int,
- mouseY: Int,
- delta: Float
- ) {
- val modelViewStack = RenderSystem.getModelViewStack()
- modelViewStack.pushMatrix()
- modelViewStack.mul(graphics.matrices.peek().positionMatrix)
- modelViewStack.translate(bounds.x.toFloat(), bounds.y.toFloat(), 0.0f)
- modelViewStack.scale(
- bounds.width.toFloat() / 16.0f,
- -(bounds.getWidth() + bounds.getHeight()).toFloat() / 2.0f / 16.0f,
- 1.0f
- )
- RenderSystem.applyModelViewMatrix()
- renderOverlay(DrawContext(minecraft, graphics.vertexConsumers), entry.asItemEntry())
- modelViewStack.popMatrix()
- RenderSystem.applyModelViewMatrix()
- }
-
- fun renderOverlay(graphics: DrawContext, entry: EntryStack<ItemStack>) {
- if (!entry.isEmpty) {
- graphics.drawItemInSlot(MinecraftClient.getInstance().textRenderer, entry.value, 0, 0, null)
- }
- }
-
- override fun endBatch(
- entry: EntryStack<SBItemStack>?,
- extraData: BakedModel?,
- graphics: DrawContext?,
- delta: Float
- ) {
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt b/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt
deleted file mode 100644
index a35d75f..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/NEUItemEntrySerializer.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import me.shedaniel.rei.api.common.entry.EntrySerializer
-import me.shedaniel.rei.api.common.entry.EntryStack
-import net.minecraft.nbt.NbtCompound
-import moe.nea.firmament.util.SkyblockId
-
-object NEUItemEntrySerializer : EntrySerializer<SBItemStack> {
- const val SKYBLOCK_ID_ENTRY = "SKYBLOCK_ID"
- const val SKYBLOCK_ITEM_COUNT = "SKYBLOCK_ITEM_COUNT"
-
- override fun supportSaving(): Boolean = true
- override fun supportReading(): Boolean = true
-
- override fun read(tag: NbtCompound): SBItemStack {
- val id = SkyblockId(tag.getString(SKYBLOCK_ID_ENTRY))
- val count = if (tag.contains(SKYBLOCK_ITEM_COUNT)) tag.getInt(SKYBLOCK_ITEM_COUNT) else 1
- return SBItemStack(id, count)
- }
-
- override fun save(entry: EntryStack<SBItemStack>, value: SBItemStack): NbtCompound {
- return NbtCompound().apply {
- putString(SKYBLOCK_ID_ENTRY, value.skyblockId.neuItem)
- putInt(SKYBLOCK_ITEM_COUNT, value.getStackSize())
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt b/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt
deleted file mode 100644
index 5c6740e..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/SBItemEntryDefinition.kt
+++ /dev/null
@@ -1,254 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import io.github.moulberry.repo.constants.PetNumbers
-import io.github.moulberry.repo.data.NEUIngredient
-import io.github.moulberry.repo.data.NEUItem
-import io.github.moulberry.repo.data.Rarity
-import java.util.stream.Stream
-import me.shedaniel.rei.api.client.entry.renderer.EntryRenderer
-import me.shedaniel.rei.api.common.entry.EntrySerializer
-import me.shedaniel.rei.api.common.entry.EntryStack
-import me.shedaniel.rei.api.common.entry.comparison.ComparisonContext
-import me.shedaniel.rei.api.common.entry.type.EntryDefinition
-import me.shedaniel.rei.api.common.entry.type.EntryType
-import me.shedaniel.rei.api.common.entry.type.VanillaEntryTypes
-import net.minecraft.item.ItemStack
-import net.minecraft.registry.tag.TagKey
-import net.minecraft.text.Text
-import net.minecraft.util.Formatting
-import net.minecraft.util.Identifier
-import moe.nea.firmament.rei.FirmamentReiPlugin.Companion.asItemEntry
-import moe.nea.firmament.repo.ExpLadders
-import moe.nea.firmament.repo.ItemCache
-import moe.nea.firmament.repo.ItemCache.asItemStack
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.HypixelPetInfo
-import moe.nea.firmament.util.LegacyFormattingCode
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.appendLore
-import moe.nea.firmament.util.item.displayNameAccordingToNbt
-import moe.nea.firmament.util.petData
-import moe.nea.firmament.util.skyBlockId
-import moe.nea.firmament.util.withColor
-
-// TODO: add in extra data like pet info, into this structure
-data class PetData(
- val rarity: Rarity,
- val petId: String,
- val exp: Double,
- val isStub: Boolean = false,
-) {
- companion object {
- fun fromHypixel(petInfo: HypixelPetInfo) = PetData(
- petInfo.tier, petInfo.type, petInfo.exp,
- )
-
- fun forLevel(petId: String, rarity: Rarity, level: Int) = PetData(
- rarity, petId, ExpLadders.getExpLadder(petId, rarity).getPetExpForLevel(level).toDouble()
- )
- }
-
- val levelData by lazy { ExpLadders.getExpLadder(petId, rarity).getPetLevel(exp) }
-}
-
-data class SBItemStack constructor(
- val skyblockId: SkyblockId,
- val neuItem: NEUItem?,
- private var stackSize: Int,
- private var petData: PetData?,
- val extraLore: List<Text> = emptyList(),
- // TODO: grab this star data from nbt if possible
- val stars: Int = 0,
-) {
-
- fun getStackSize() = stackSize
- fun setStackSize(newSize: Int) {
- this.stackSize = newSize
- this.itemStack_ = null
- }
-
- fun getPetData() = petData
- fun setPetData(petData: PetData?) {
- this.petData = petData
- this.itemStack_ = null
- }
-
- constructor(skyblockId: SkyblockId, petData: PetData) : this(
- skyblockId,
- RepoManager.getNEUItem(skyblockId),
- 1,
- petData
- )
-
- constructor(skyblockId: SkyblockId, stackSize: Int = 1) : this(
- skyblockId,
- RepoManager.getNEUItem(skyblockId),
- stackSize,
- RepoManager.getPotentialStubPetData(skyblockId)
- )
-
- private fun injectReplacementDataForPetLevel(
- petInfo: PetNumbers,
- level: Int,
- replacementData: MutableMap<String, String>
- ) {
- val stats = petInfo.interpolatedStatsAtLevel(level) ?: return
- stats.otherNumbers.forEachIndexed { index, it ->
- replacementData[index.toString()] = FirmFormatters.formatCommas(it, 1)
- }
- stats.statNumbers.forEach { (t, u) ->
- replacementData[t] = FirmFormatters.formatCommas(u, 1)
- }
- }
-
- private fun injectReplacementDataForPets(replacementData: MutableMap<String, String>) {
- val petData = this.petData ?: return
- val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return
- if (petData.isStub) {
- val mapLow = mutableMapOf<String, String>()
- injectReplacementDataForPetLevel(petInfo, petInfo.lowLevel, mapLow)
- val mapHigh = mutableMapOf<String, String>()
- injectReplacementDataForPetLevel(petInfo, petInfo.highLevel, mapHigh)
- mapHigh.forEach { (key, highValue) ->
- mapLow.merge(key, highValue) { a, b -> "$a → $b" }
- }
- replacementData.putAll(mapLow)
- replacementData["LVL"] = "${petInfo.lowLevel} → ${petInfo.highLevel}"
- } else {
- injectReplacementDataForPetLevel(petInfo, petData.levelData.currentLevel, replacementData)
- replacementData["LVL"] = petData.levelData.currentLevel.toString()
- }
- }
-
-
- private var itemStack_: ItemStack? = null
-
- private val itemStack: ItemStack
- get() {
- val itemStack = itemStack_ ?: run {
- if (skyblockId == SkyblockId.COINS)
- return@run ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) }
- val replacementData = mutableMapOf<String, String>()
- injectReplacementDataForPets(replacementData)
- return@run neuItem.asItemStack(idHint = skyblockId, replacementData)
- .copyWithCount(stackSize)
- .also { it.appendLore(extraLore) }
- .also { enhanceStatsByStars(it, stars) }
- }
- if (itemStack_ == null)
- itemStack_ = itemStack
- return itemStack
- }
-
-
- private fun starString(stars: Int): Text {
- if (stars <= 0) return Text.empty()
- val tiers = listOf(
- LegacyFormattingCode.GOLD,
- LegacyFormattingCode.LIGHT_PURPLE,
- LegacyFormattingCode.AQUA,
- )
- val maxStars = 5
- if (stars > tiers.size * maxStars) return Text.literal(" ${stars}✪").withColor(Formatting.RED)
- val starBaseTier = (stars - 1) / maxStars
- val starBaseColor = tiers[starBaseTier]
- val starsInCurrentTier = stars - starBaseTier * maxStars
- val starString = Text.literal(" " + "✪".repeat(starsInCurrentTier)).withColor(starBaseColor.modern)
- if (starBaseTier > 0) {
- val starLastTier = tiers[starBaseTier - 1]
- val starsInLastTier = 5 - starsInCurrentTier
- starString.append(Text.literal("✪".repeat(starsInLastTier)).withColor(starLastTier.modern))
- }
- return starString
- }
-
- private fun enhanceStatsByStars(itemStack: ItemStack, stars: Int) {
- if (stars == 0) return
- // TODO: increase stats and add the star level into the nbt data so star displays work
- itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy()
- .append(starString(stars))
- }
-
- fun asImmutableItemStack(): ItemStack {
- return itemStack
- }
-
- fun asItemStack(): ItemStack {
- return itemStack.copy()
- }
-}
-
-object SBItemEntryDefinition : EntryDefinition<SBItemStack> {
- override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean {
- return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize()
- }
-
- override fun cheatsAs(entry: EntryStack<SBItemStack>?, value: SBItemStack): ItemStack {
- return value.asItemStack()
- }
-
- override fun getValueType(): Class<SBItemStack> = SBItemStack::class.java
- override fun getType(): EntryType<SBItemStack> = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID)
-
- override fun getRenderer(): EntryRenderer<SBItemStack> = NEUItemEntryRenderer
-
- override fun getSerializer(): EntrySerializer<SBItemStack> {
- return NEUItemEntrySerializer
- }
-
- override fun getTagsFor(entry: EntryStack<SBItemStack>?, value: SBItemStack?): Stream<out TagKey<*>>? {
- return Stream.empty()
- }
-
- override fun asFormattedText(entry: EntryStack<SBItemStack>, value: SBItemStack): Text {
- return VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asItemStack())
- }
-
- override fun hash(entry: EntryStack<SBItemStack>, value: SBItemStack, context: ComparisonContext): Long {
- // Repo items are immutable, and get replaced entirely when loaded from disk
- return value.skyblockId.hashCode() * 31L
- }
-
- override fun wildcard(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return value.copy(stackSize = 1, petData = RepoManager.getPotentialStubPetData(value.skyblockId),
- stars = 0, extraLore = listOf())
- }
-
- override fun normalize(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return wildcard(entry, value)
- }
-
- override fun copy(entry: EntryStack<SBItemStack>?, value: SBItemStack): SBItemStack {
- return value
- }
-
- override fun isEmpty(entry: EntryStack<SBItemStack>?, value: SBItemStack): Boolean {
- return value.getStackSize() == 0
- }
-
- override fun getIdentifier(entry: EntryStack<SBItemStack>?, value: SBItemStack): Identifier {
- return value.skyblockId.identifier
- }
-
- fun getEntry(sbItemStack: SBItemStack): EntryStack<SBItemStack> =
- EntryStack.of(this, sbItemStack)
-
- fun getEntry(skyblockId: SkyblockId, count: Int = 1): EntryStack<SBItemStack> =
- getEntry(SBItemStack(skyblockId, count))
-
- fun getEntry(ingredient: NEUIngredient): EntryStack<SBItemStack> =
- getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt())
-
- fun getEntry(stack: ItemStack): EntryStack<SBItemStack> =
- getEntry(
- SBItemStack(
- stack.skyBlockId ?: SkyblockId.NULL,
- RepoManager.getNEUItem(stack.skyBlockId ?: SkyblockId.NULL),
- stack.count,
- petData = stack.petData?.let { PetData.fromHypixel(it) }
- )
- )
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt b/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt
deleted file mode 100644
index 5136902..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/SkyblockCraftingRecipeDynamicGenerator.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import io.github.moulberry.repo.data.NEUCraftingRecipe
-import io.github.moulberry.repo.data.NEUForgeRecipe
-import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
-import io.github.moulberry.repo.data.NEUMobDropRecipe
-import io.github.moulberry.repo.data.NEURecipe
-import java.util.Optional
-import me.shedaniel.rei.api.client.registry.display.DynamicDisplayGenerator
-import me.shedaniel.rei.api.client.view.ViewSearchBuilder
-import me.shedaniel.rei.api.common.display.Display
-import me.shedaniel.rei.api.common.entry.EntryStack
-import moe.nea.firmament.rei.recipes.SBCraftingRecipe
-import moe.nea.firmament.rei.recipes.SBEssenceUpgradeRecipe
-import moe.nea.firmament.rei.recipes.SBForgeRecipe
-import moe.nea.firmament.rei.recipes.SBKatRecipe
-import moe.nea.firmament.rei.recipes.SBMobDropRecipe
-import moe.nea.firmament.repo.EssenceRecipeProvider
-import moe.nea.firmament.repo.RepoManager
-
-
-val SkyblockCraftingRecipeDynamicGenerator =
- neuDisplayGenerator<SBCraftingRecipe, NEUCraftingRecipe> { SBCraftingRecipe(it) }
-
-val SkyblockForgeRecipeDynamicGenerator =
- neuDisplayGenerator<SBForgeRecipe, NEUForgeRecipe> { SBForgeRecipe(it) }
-
-val SkyblockMobDropRecipeDynamicGenerator =
- neuDisplayGenerator<SBMobDropRecipe, NEUMobDropRecipe> { SBMobDropRecipe(it) }
-
-val SkyblockKatRecipeDynamicGenerator =
- neuDisplayGenerator<SBKatRecipe, NEUKatUpgradeRecipe> { SBKatRecipe(it) }
-val SkyblockEssenceRecipeDynamicGenerator =
- neuDisplayGenerator<SBEssenceUpgradeRecipe, EssenceRecipeProvider.EssenceUpgradeRecipe> { SBEssenceUpgradeRecipe(it) }
-
-inline fun <D : Display, reified T : NEURecipe> neuDisplayGenerator(crossinline mapper: (T) -> D) =
- object : DynamicDisplayGenerator<D> {
- override fun getRecipeFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getRecipesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
- }
-
- override fun generate(builder: ViewSearchBuilder): Optional<List<D>> {
- if (SBCraftingRecipe.Category.catIdentifier !in builder.categories) return Optional.empty()
- return Optional.of(
- RepoManager.getAllRecipes().filterIsInstance<T>().map { mapper(it) }
- .toList()
- )
- }
-
- override fun getUsageFor(entry: EntryStack<*>): Optional<List<D>> {
- if (entry.type != SBItemEntryDefinition.type) return Optional.empty()
- val item = entry.castValue<SBItemStack>()
- val recipes = RepoManager.getUsagesFor(item.skyblockId)
- val craftingRecipes = recipes.filterIsInstance<T>()
- return Optional.of(craftingRecipes.map(mapper))
-
- }
- }
diff --git a/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt b/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt
deleted file mode 100644
index bb0a5a5..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/SkyblockItemIdFocusedStackProvider.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import dev.architectury.event.CompoundEventResult
-import me.shedaniel.math.Point
-import me.shedaniel.rei.api.client.registry.screen.FocusedStackProvider
-import me.shedaniel.rei.api.common.entry.EntryStack
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import moe.nea.firmament.util.skyBlockId
-
-object SkyblockItemIdFocusedStackProvider : FocusedStackProvider {
- override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult<EntryStack<*>> {
- if (screen !is HandledScreen<*>) return CompoundEventResult.pass()
- screen as AccessorHandledScreen
- val focusedSlot = screen.focusedSlot_Firmament ?: return CompoundEventResult.pass()
- val item = focusedSlot.stack ?: return CompoundEventResult.pass()
- val skyblockId = item.skyBlockId ?: return CompoundEventResult.pass()
- return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(skyblockId))
- }
-
- override fun getPriority(): Double = 1_000_000.0
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/math.kt b/src/main/kotlin/moe/nea/firmament/rei/math.kt
deleted file mode 100644
index 1318beb..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/math.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-package moe.nea.firmament.rei
-
-import me.shedaniel.math.Point
-
-operator fun Point.plus(other: Point): Point = Point(
- this.x + other.x,
- this.y + other.y,
-)
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBCraftingRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBCraftingRecipe.kt
deleted file mode 100644
index d6bbf0c..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBCraftingRecipe.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUCraftingRecipe
-import io.github.moulberry.repo.data.NEUIngredient
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-
-class SBCraftingRecipe(override val neuRecipe: NEUCraftingRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier
-
- object Category : DisplayCategory<SBCraftingRecipe> {
- val catIdentifier = CategoryIdentifier.of<SBCraftingRecipe>(Firmament.MOD_ID, "crafing_recipe")
- override fun getCategoryIdentifier(): CategoryIdentifier<out SBCraftingRecipe> = catIdentifier
-
- override fun getTitle(): Text = Text.literal("SkyBlock Crafting")
-
- override fun getIcon(): Renderer = EntryStacks.of(Blocks.CRAFTING_TABLE)
- override fun setupDisplay(display: SBCraftingRecipe, bounds: Rectangle): List<Widget> {
- val point = Point(bounds.centerX - 58, bounds.centerY - 27)
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createArrow(Point(point.x + 60, point.y + 18)))
- add(Widgets.createResultSlotBackground(Point(point.x + 95, point.y + 19)))
- for (i in 0 until 3) {
- for (j in 0 until 3) {
- val slot = Widgets.createSlot(Point(point.x + 1 + i * 18, point.y + 1 + j * 18)).markInput()
- add(slot)
- val item = display.neuRecipe.inputs[i + j * 3]
- if (item == NEUIngredient.SENTINEL_EMPTY) continue
- slot.entry(SBItemEntryDefinition.getEntry(item)) // TODO: make use of stackable item entries
- }
- }
- add(
- Widgets.createSlot(Point(point.x + 95, point.y + 19))
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.output))
- .disableBackground().markOutput()
- )
- }
- }
-
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBEssenceUpgradeRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBEssenceUpgradeRecipe.kt
deleted file mode 100644
index 80bc2b7..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBEssenceUpgradeRecipe.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.SBItemStack
-import moe.nea.firmament.repo.EssenceRecipeProvider
-import moe.nea.firmament.util.SkyblockId
-
-class SBEssenceUpgradeRecipe(override val neuRecipe: EssenceRecipeProvider.EssenceUpgradeRecipe) : SBRecipe() {
- object Category : DisplayCategory<SBEssenceUpgradeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBEssenceUpgradeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "essence_upgrade")
-
- override fun getTitle(): Text {
- return Text.literal("Essence Upgrades")
- }
-
- override fun getIcon(): Renderer {
- return SBItemEntryDefinition.getEntry(SkyblockId("ESSENCE_WITHER"))
- }
-
- override fun setupDisplay(display: SBEssenceUpgradeRecipe, bounds: Rectangle): List<Widget> {
- val recipe = display.neuRecipe
- val list = mutableListOf<Widget>()
- list.add(Widgets.createRecipeBase(bounds))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter - 1))))
- list.add(Widgets.createSlot(Point(bounds.minX + 12, bounds.centerY - 8 + 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(recipe.essenceIngredient)))
- list.add(Widgets.createSlot(Point(bounds.maxX - 12 - 16, bounds.centerY - 8))
- .markOutput()
- .entry(SBItemEntryDefinition.getEntry(SBItemStack(recipe.itemId).copy(stars = recipe.starCountAfter))))
- val extraItems = recipe.extraItems
- list.add(Widgets.createArrow(Point(bounds.centerX - 24 / 2,
- if (extraItems.isEmpty()) bounds.centerY - 17 / 2
- else bounds.centerY + 18 / 2)))
- for ((index, item) in extraItems.withIndex()) {
- list.add(Widgets.createSlot(
- Point(bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18,
- bounds.centerY - 18 / 2))
- .markInput()
- .entry(SBItemEntryDefinition.getEntry(item)))
- }
- return list
- }
- }
-
- override fun getCategoryIdentifier(): CategoryIdentifier<*> {
- return Category.categoryIdentifier
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBForgeRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBForgeRecipe.kt
deleted file mode 100644
index 569f4a0..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBForgeRecipe.kt
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUForgeRecipe
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import kotlin.math.cos
-import kotlin.math.sin
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.block.Blocks
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.plus
-
-class SBForgeRecipe(override val neuRecipe: NEUForgeRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBForgeRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBForgeRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "forge_recipe")
-
- override fun getTitle(): Text = Text.literal("Forge Recipes")
- override fun getDisplayHeight(): Int {
- return 104
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Blocks.ANVIL)
- override fun setupDisplay(display: SBForgeRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- add(Widgets.createResultSlotBackground(Point(bounds.minX + 124, bounds.minY + 46)))
- val arrow = Widgets.createArrow(Point(bounds.minX + 90, bounds.minY + 54 - 18 / 2))
- add(arrow)
- add(Widgets.createTooltip(arrow.bounds, Text.stringifiedTranslatable("firmament.recipe.forge.time", display.neuRecipe.duration.seconds)))
- val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8)
- val count = display.neuRecipe.inputs.size
- if (count == 1) {
- add(
- Widgets.createSlot(Point(ingredientsCenter.x, ingredientsCenter.y)).markInput()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.inputs.single()))
- )
- } else {
- display.neuRecipe.inputs.forEachIndexed { idx, ingredient ->
- val rad = Math.PI * 2 * idx / count
- add(
- Widgets.createSlot(
- Point(
- cos(rad) * 30,
- sin(rad) * 30,
- ) + ingredientsCenter
- ).markInput().entry(SBItemEntryDefinition.getEntry(ingredient))
- )
- }
- }
- add(
- Widgets.createSlot(Point(bounds.minX + 124, bounds.minY + 46)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.outputStack))
- )
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt
deleted file mode 100644
index f906a43..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBKatRecipe.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUKatUpgradeRecipe
-import io.github.notenoughupdates.moulconfig.common.IMinecraft
-import io.github.notenoughupdates.moulconfig.gui.GuiComponent
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import io.github.notenoughupdates.moulconfig.gui.MouseEvent
-import io.github.notenoughupdates.moulconfig.gui.component.SliderComponent
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import io.github.notenoughupdates.moulconfig.observer.Property
-import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.block.Blocks
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.Element
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.rei.PetData
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.rei.SBItemStack
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SkyblockId
-
-class SBKatRecipe(override val neuRecipe: NEUKatUpgradeRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBKatRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBKatRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "kat_recipe")
-
- override fun getTitle(): Text = Text.literal("Kat Pet Upgrade")
- override fun getDisplayHeight(): Int {
- return 100
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Items.BONE)
- override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- val arrowWidth = 24
- val recipe = display.neuRecipe
- val levelValue = Property.upgrade(GetSetter.floating(0F))
- val slider = SliderComponent(levelValue, 1F, 100F, 1f, 100)
- val outputStack = SBItemStack(SkyblockId(recipe.output.itemId))
- val inputStack = SBItemStack(SkyblockId(recipe.input.itemId))
- val inputLevelLabelCenter = Point(bounds.minX + 30 - 18 + 5 + 8, bounds.minY + 25)
- val inputLevelLabel = Widgets.createLabel(
- inputLevelLabelCenter,
- Text.literal("")).centered()
- val outputLevelLabelCenter = Point(bounds.maxX - 30 + 8, bounds.minY + 25)
- val outputLevelLabel = Widgets.createLabel(
- outputLevelLabelCenter,
- Text.literal("")).centered()
- val coinStack = SBItemStack(SkyblockId.COINS, recipe.coins.toInt())
- levelValue.whenChanged { oldValue, newValue ->
- if (oldValue.toInt() == newValue.toInt()) return@whenChanged
- val oldInput = inputStack.getPetData() ?: return@whenChanged
- val newInput = PetData.forLevel(oldInput.petId, oldInput.rarity, newValue.toInt())
- inputStack.setPetData(newInput)
- val oldOutput = outputStack.getPetData() ?: return@whenChanged
- val newOutput = PetData(oldOutput.rarity, oldOutput.petId, newInput.exp)
- outputStack.setPetData(newOutput)
- inputLevelLabel.message = Text.literal(newInput.levelData.currentLevel.toString())
- inputLevelLabel.bounds.location = Point(
- inputLevelLabelCenter.x - MC.font.getWidth(inputLevelLabel.message) / 2,
- inputLevelLabelCenter.y)
- outputLevelLabel.message = Text.literal(newOutput.levelData.currentLevel.toString())
- outputLevelLabel.bounds.location = Point(
- outputLevelLabelCenter.x - MC.font.getWidth(outputLevelLabel.message) / 2,
- outputLevelLabelCenter.y)
- coinStack.setStackSize((recipe.coins * (1 - 0.3 * newValue / 100)).toInt())
- }
- levelValue.set(1F)
- add(Widgets.createRecipeBase(bounds))
- add(wrapWidget(Rectangle(bounds.centerX - slider.width / 2,
- bounds.maxY - 30,
- slider.width,
- slider.height),
- slider))
- add(Widgets.withTooltip(
- Widgets.createArrow(Point(bounds.centerX - arrowWidth / 2, bounds.minY + 40)),
- Text.literal("Upgrade time: " + FirmFormatters.formatTimespan(recipe.seconds.seconds))))
-
- add(Widgets.createResultSlotBackground(Point(bounds.maxX - 30, bounds.minY + 40)))
- add(inputLevelLabel)
- add(outputLevelLabel)
- add(Widgets.createSlot(Point(bounds.maxX - 30, bounds.minY + 40)).markOutput().disableBackground()
- .entry(SBItemEntryDefinition.getEntry(outputStack)))
- add(Widgets.createSlot(Point(bounds.minX + 30 - 18 + 5, bounds.minY + 40)).markInput()
- .entry(SBItemEntryDefinition.getEntry(inputStack)))
-
- val allInputs = recipe.items.map { SBItemEntryDefinition.getEntry(it) } +
- listOf(SBItemEntryDefinition.getEntry(coinStack))
- for ((index, item) in allInputs.withIndex()) {
- add(Widgets.createSlot(
- Point(bounds.centerX + index * 20 - allInputs.size * 18 / 2 - (allInputs.size - 1) * 2 / 2,
- bounds.minY + 20))
- .markInput()
- .entry(item))
- }
- }
- }
- }
-}
-
-fun wrapWidget(bounds: Rectangle, component: GuiComponent): Widget {
- return object : WidgetWithBounds() {
- override fun getBounds(): Rectangle {
- return bounds
- }
-
- override fun children(): List<Element> {
- return listOf()
- }
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- context.matrices.push()
- context.matrices.translate(bounds.minX.toFloat(), bounds.minY.toFloat(), 0F)
- component.render(
- GuiImmediateContext(
- ModernRenderContext(context),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseX - bounds.minX, mouseY - bounds.minY,
- mouseX, mouseY,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- context.matrices.pop()
- }
-
- override fun mouseMoved(mouseX: Double, mouseY: Double) {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- component.mouseEvent(MouseEvent.Move(0F, 0F),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, true),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Click(button, false),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
-
- override fun mouseDragged(
- mouseX: Double,
- mouseY: Double,
- button: Int,
- deltaX: Double,
- deltaY: Double
- ): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Move(deltaX.toFloat(), deltaY.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
-
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- val mouseXInt = mouseX.toInt()
- val mouseYInt = mouseY.toInt()
- return component.mouseEvent(MouseEvent.Scroll(verticalAmount.toFloat()),
- GuiImmediateContext(
- IMinecraft.instance.provideTopLevelRenderContext(),
- bounds.minX, bounds.minY,
- bounds.width, bounds.height,
- mouseXInt - bounds.minX, mouseYInt - bounds.minY,
- mouseXInt, mouseYInt,
- mouseX.toFloat(), mouseY.toFloat()
- ))
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBMobDropRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBMobDropRecipe.kt
deleted file mode 100644
index a02220f..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBMobDropRecipe.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUMobDropRecipe
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import me.shedaniel.rei.api.client.gui.Renderer
-import me.shedaniel.rei.api.client.gui.widgets.Widget
-import me.shedaniel.rei.api.client.gui.widgets.Widgets
-import me.shedaniel.rei.api.client.registry.display.DisplayCategory
-import me.shedaniel.rei.api.common.category.CategoryIdentifier
-import me.shedaniel.rei.api.common.util.EntryStacks
-import net.minecraft.item.Items
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.entity.EntityRenderer
-import moe.nea.firmament.gui.entity.EntityWidget
-import moe.nea.firmament.rei.SBItemEntryDefinition
-
-class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() {
- override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier
-
- object Category : DisplayCategory<SBMobDropRecipe> {
- override fun getCategoryIdentifier(): CategoryIdentifier<SBMobDropRecipe> =
- CategoryIdentifier.of(Firmament.MOD_ID, "mob_drop_recipe")
-
- override fun getTitle(): Text = Text.literal("Mob Drops")
- override fun getDisplayHeight(): Int {
- return 100
- }
-
- override fun getIcon(): Renderer = EntryStacks.of(Items.DIAMOND_SWORD)
- override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List<Widget> {
- return buildList {
- add(Widgets.createRecipeBase(bounds))
- val source = display.neuRecipe.render
- val entity = if (source.startsWith("@")) {
- EntityRenderer.constructEntity(Identifier.of(source.substring(1)))
- } else {
- EntityRenderer.applyModifiers(source, listOf())
- }
- if (entity != null) {
- val level = display.neuRecipe.level
- val fullMobName =
- if (level > 0) Text.translatable("firmament.recipe.mobs.name", level, display.neuRecipe.name)
- else Text.translatable("firmament.recipe.mobs.name.nolevel", display.neuRecipe.name)
- val tt = mutableListOf<Text>()
- tt.add((fullMobName))
- tt.add(Text.literal(""))
- if (display.neuRecipe.coins > 0) {
- tt.add(Text.stringifiedTranslatable("firmament.recipe.mobs.coins", display.neuRecipe.coins))
- }
- if (display.neuRecipe.combatExperience > 0) {
- tt.add(
- Text.stringifiedTranslatable(
- "firmament.recipe.mobs.combat",
- display.neuRecipe.combatExperience
- )
- )
- }
- if (display.neuRecipe.enchantingExperience > 0) {
- tt.add(
- Text.stringifiedTranslatable(
- "firmament.recipe.mobs.exp",
- display.neuRecipe.enchantingExperience
- )
- )
- }
- if (display.neuRecipe.extra != null)
- display.neuRecipe.extra.mapTo(tt) { Text.literal(it) }
- if (tt.size == 2)
- tt.removeAt(1)
- add(
- Widgets.withTooltip(
- EntityWidget(entity, Point(bounds.minX + 5, bounds.minY + 15)),
- tt
- )
- )
- }
- add(
- Widgets.createLabel(Point(bounds.minX + 15, bounds.minY + 5), Text.literal(display.neuRecipe.name))
- .leftAligned()
- )
- var x = bounds.minX + 60
- var y = bounds.minY + 20
- for (drop in display.neuRecipe.drops) {
- val lore = drop.extra.mapTo(mutableListOf()) { Text.literal(it) }
- if (drop.chance != null) {
- lore += listOf(Text.translatable("firmament.recipe.mobs.drops", drop.chance))
- }
- val item = SBItemEntryDefinition.getEntry(drop.dropItem)
- .value.copy(extraLore = lore)
- add(
- Widgets.createSlot(Point(x, y)).markOutput()
- .entries(listOf(SBItemEntryDefinition.getEntry(item)))
- )
- x += 18
- if (x > bounds.maxX - 30) {
- x = bounds.minX + 60
- y += 18
- }
- }
- }
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBRecipe.kt b/src/main/kotlin/moe/nea/firmament/rei/recipes/SBRecipe.kt
deleted file mode 100644
index 7872d83..0000000
--- a/src/main/kotlin/moe/nea/firmament/rei/recipes/SBRecipe.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-package moe.nea.firmament.rei.recipes
-
-import io.github.moulberry.repo.data.NEUIngredient
-import io.github.moulberry.repo.data.NEURecipe
-import me.shedaniel.rei.api.common.display.Display
-import me.shedaniel.rei.api.common.entry.EntryIngredient
-import moe.nea.firmament.rei.SBItemEntryDefinition
-import moe.nea.firmament.util.SkyblockId
-
-abstract class SBRecipe : Display {
- abstract val neuRecipe: NEURecipe
- override fun getInputEntries(): List<EntryIngredient> {
- return neuRecipe.allInputs
- .filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
- .map {
- val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
- EntryIngredient.of(entryStack)
- }
- }
-
- override fun getOutputEntries(): List<EntryIngredient> {
- return neuRecipe.allOutputs
- .filter { it.itemId != NEUIngredient.NEU_SENTINEL_EMPTY }
- .map {
- val entryStack = SBItemEntryDefinition.getEntry(SkyblockId(it.itemId))
- EntryIngredient.of(entryStack)
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/BetterRepoRecipeCache.kt b/src/main/kotlin/moe/nea/firmament/repo/BetterRepoRecipeCache.kt
deleted file mode 100644
index 91a6b50..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/BetterRepoRecipeCache.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-
-package moe.nea.firmament.repo
-
-import io.github.moulberry.repo.IReloadable
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.data.NEURecipe
-import moe.nea.firmament.util.SkyblockId
-
-class BetterRepoRecipeCache(val essenceRecipeProvider: EssenceRecipeProvider) : IReloadable {
- var usages: Map<SkyblockId, Set<NEURecipe>> = mapOf()
- var recipes: Map<SkyblockId, Set<NEURecipe>> = mapOf()
-
- override fun reload(repository: NEURepository) {
- val usages = mutableMapOf<SkyblockId, MutableSet<NEURecipe>>()
- val recipes = mutableMapOf<SkyblockId, MutableSet<NEURecipe>>()
- val baseRecipes = repository.items.items.values
- .asSequence()
- .flatMap { it.recipes }
- val extraRecipes = essenceRecipeProvider.recipes
- (baseRecipes + extraRecipes)
- .forEach { recipe ->
- recipe.allInputs.forEach { usages.getOrPut(SkyblockId(it.itemId), ::mutableSetOf).add(recipe) }
- recipe.allOutputs.forEach { recipes.getOrPut(SkyblockId(it.itemId), ::mutableSetOf).add(recipe) }
- }
- this.usages = usages
- this.recipes = recipes
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/EssenceRecipeProvider.kt b/src/main/kotlin/moe/nea/firmament/repo/EssenceRecipeProvider.kt
deleted file mode 100644
index 1833258..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/EssenceRecipeProvider.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-
-package moe.nea.firmament.repo
-
-import io.github.moulberry.repo.IReloadable
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.data.NEUIngredient
-import io.github.moulberry.repo.data.NEURecipe
-import moe.nea.firmament.util.SkyblockId
-
-class EssenceRecipeProvider : IReloadable {
- data class EssenceUpgradeRecipe(
- val itemId: SkyblockId,
- val starCountAfter: Int,
- val essenceCost: Int,
- val essenceType: String, // TODO: replace with proper type
- val extraItems: List<NEUIngredient>,
- ) : NEURecipe {
- val essenceIngredient= NEUIngredient.fromString("${essenceType}:$essenceCost")
- val allUpgradeComponents = listOf(essenceIngredient) + extraItems
-
- override fun getAllInputs(): Collection<NEUIngredient> {
- return listOf(NEUIngredient.fromString(itemId.neuItem + ":1")) + allUpgradeComponents
- }
-
- override fun getAllOutputs(): Collection<NEUIngredient> {
- return listOf(NEUIngredient.fromString(itemId.neuItem + ":1"))
- }
- }
-
- var recipes = listOf<EssenceUpgradeRecipe>()
- private set
-
- override fun reload(repository: NEURepository) {
- val recipes = mutableListOf<EssenceUpgradeRecipe>()
- for ((neuId, costs) in repository.constants.essenceCost.costs) {
- // TODO: add dungeonization costs. this is in repo, but not in the repo parser.
- for ((starCountAfter, essenceCost) in costs.essenceCosts.entries) {
- val items = costs.itemCosts[starCountAfter] ?: emptyList()
- recipes.add(
- EssenceUpgradeRecipe(
- SkyblockId(neuId),
- starCountAfter,
- essenceCost,
- "ESSENCE_" + costs.type.uppercase(), // how flimsy
- items.map { NEUIngredient.fromString(it) }))
- }
- }
- this.recipes = recipes
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt b/src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt
deleted file mode 100644
index fbc9eb8..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/ExpLadder.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-package moe.nea.firmament.repo
-
-import com.google.common.cache.CacheBuilder
-import com.google.common.cache.CacheLoader
-import io.github.moulberry.repo.IReloadable
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.constants.PetLevelingBehaviourOverride
-import io.github.moulberry.repo.data.Rarity
-
-object ExpLadders : IReloadable {
-
- data class PetLevel(
- val currentLevel: Int,
- val maxLevel: Int,
- val expRequiredForNextLevel: Long,
- val expRequiredForMaxLevel: Long,
- val expInCurrentLevel: Float,
- var expTotal: Float,
- ) {
- val percentageToNextLevel: Float = expInCurrentLevel / expRequiredForNextLevel
- }
-
- data class ExpLadder(
- val individualLevelCost: List<Long>,
- ) {
- val cumulativeLevelCost = individualLevelCost.runningFold(0F) { a, b -> a + b }.map { it.toLong() }
- fun getPetLevel(currentExp: Double): PetLevel {
- val currentOneIndexedLevel = cumulativeLevelCost.indexOfLast { it <= currentExp } + 1
- val expForNextLevel = if (currentOneIndexedLevel > individualLevelCost.size) { // Max leveled pet
- individualLevelCost.last()
- } else {
- individualLevelCost[currentOneIndexedLevel - 1]
- }
- val expInCurrentLevel =
- if (currentOneIndexedLevel >= cumulativeLevelCost.size)
- currentExp.toFloat() - cumulativeLevelCost.last()
- else
- (expForNextLevel - (cumulativeLevelCost[currentOneIndexedLevel] - currentExp.toFloat())).coerceAtLeast(
- 0F
- )
- return PetLevel(
- currentLevel = currentOneIndexedLevel,
- maxLevel = cumulativeLevelCost.size,
- expRequiredForNextLevel = expForNextLevel,
- expRequiredForMaxLevel = cumulativeLevelCost.last(),
- expInCurrentLevel = expInCurrentLevel,
- expTotal = currentExp.toFloat()
- )
- }
-
- fun getPetExpForLevel(level: Int): Long {
- if (level < 2) return 0L
- if (level >= cumulativeLevelCost.size) return cumulativeLevelCost.last()
- return cumulativeLevelCost[level - 1]
- }
- }
-
- private data class Key(val petIdWithoutRarity: String, val rarity: Rarity)
-
- private val expLadders = CacheBuilder.newBuilder()
- .build(object : CacheLoader<Key, ExpLadder>() {
- override fun load(key: Key): ExpLadder {
- val pld = RepoManager.neuRepo.constants.petLevelingData
- var exp = pld.petExpCostForLevel
- var offset = pld.petLevelStartOffset[key.rarity]!!
- var maxLevel = 100
- val override = pld.petLevelingBehaviourOverrides[key.petIdWithoutRarity]
- if (override != null) {
- maxLevel = override.maxLevel ?: maxLevel
- offset = override.petLevelStartOffset?.get(key.rarity) ?: offset
- when (override.petExpCostModifierType) {
- PetLevelingBehaviourOverride.PetExpModifierType.APPEND ->
- exp = exp + override.petExpCostModifier
-
- PetLevelingBehaviourOverride.PetExpModifierType.REPLACE ->
- exp = override.petExpCostModifier
-
- null -> {}
- }
- }
- return ExpLadder(exp.drop(offset).take(maxLevel - 1).map { it.toLong() })
- }
- })
-
- override fun reload(repository: NEURepository?) {
- expLadders.invalidateAll()
- }
-
- fun getExpLadder(petId: String, rarity: Rarity): ExpLadder {
- return expLadders.get(Key(petId, rarity))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt b/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt
deleted file mode 100644
index 5c2a2fc..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/HypixelStaticData.kt
+++ /dev/null
@@ -1,107 +0,0 @@
-
-
-package moe.nea.firmament.repo
-
-import io.ktor.client.call.body
-import io.ktor.client.request.get
-import org.apache.logging.log4j.LogManager
-import org.lwjgl.glfw.GLFW
-import kotlinx.coroutines.async
-import kotlinx.coroutines.awaitAll
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withTimeoutOrNull
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlin.time.Duration.Companion.minutes
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.apis.CollectionResponse
-import moe.nea.firmament.apis.CollectionSkillData
-import moe.nea.firmament.keybindings.IKeyBinding
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.async.waitForInput
-
-object HypixelStaticData {
- private val logger = LogManager.getLogger("Firmament.HypixelStaticData")
- private val moulberryBaseUrl = "https://moulberry.codes"
- private val hypixelApiBaseUrl = "https://api.hypixel.net"
- var lowestBin: Map<SkyblockId, Double> = mapOf()
- private set
- var bazaarData: Map<SkyblockId, BazaarData> = mapOf()
- private set
- var collectionData: Map<String, CollectionSkillData> = mapOf()
- private set
-
- @Serializable
- data class BazaarData(
- @SerialName("product_id")
- val productId: SkyblockId.BazaarStock,
- @SerialName("quick_status")
- val quickStatus: BazaarStatus,
- )
-
- @Serializable
- data class BazaarStatus(
- val sellPrice: Double,
- val sellVolume: Long,
- val sellMovingWeek: Long,
- val sellOrders: Long,
- val buyPrice: Double,
- val buyVolume: Long,
- val buyMovingWeek: Long,
- val buyOrders: Long
- )
-
- @Serializable
- private data class BazaarResponse(
- val success: Boolean,
- val products: Map<SkyblockId.BazaarStock, BazaarData> = mapOf(),
- )
-
- fun getPriceOfItem(item: SkyblockId): Double? = bazaarData[item]?.quickStatus?.buyPrice ?: lowestBin[item]
-
-
- fun spawnDataCollectionLoop() {
- Firmament.coroutineScope.launch {
- logger.info("Updating collection data")
- updateCollectionData()
- }
- Firmament.coroutineScope.launch {
- while (true) {
- logger.info("Updating NEU prices")
- updatePrices()
- withTimeoutOrNull(10.minutes) { waitForInput(IKeyBinding.ofKeyCode(GLFW.GLFW_KEY_U)) }
- }
- }
- }
-
- private suspend fun updatePrices() {
- awaitAll(
- Firmament.coroutineScope.async { fetchBazaarPrices() },
- Firmament.coroutineScope.async { fetchPricesFromMoulberry() },
- )
- }
-
- private suspend fun fetchPricesFromMoulberry() {
- lowestBin = Firmament.httpClient.get("$moulberryBaseUrl/lowestbin.json")
- .body<Map<SkyblockId, Double>>()
- }
-
- private suspend fun fetchBazaarPrices() {
- val response = Firmament.httpClient.get("$hypixelApiBaseUrl/skyblock/bazaar").body<BazaarResponse>()
- if (!response.success) {
- logger.warn("Retrieved unsuccessful bazaar data")
- }
- bazaarData = response.products.mapKeys { it.key.toRepoId() }
- }
-
- private suspend fun updateCollectionData() {
- val response =
- Firmament.httpClient.get("$hypixelApiBaseUrl/resources/skyblock/collections").body<CollectionResponse>()
- if (!response.success) {
- logger.warn("Retrieved unsuccessful collection data")
- }
- collectionData = response.collections
- logger.info("Downloaded ${collectionData.values.sumOf { it.items.values.size }} collections")
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt b/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt
deleted file mode 100644
index 08143be..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/ItemCache.kt
+++ /dev/null
@@ -1,215 +0,0 @@
-
-
-package moe.nea.firmament.repo
-
-import com.mojang.serialization.Dynamic
-import io.github.moulberry.repo.IReloadable
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.data.NEUItem
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import java.text.NumberFormat
-import java.util.UUID
-import java.util.concurrent.ConcurrentHashMap
-import org.apache.logging.log4j.LogManager
-import kotlinx.coroutines.Job
-import kotlinx.coroutines.launch
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.SharedConstants
-import net.minecraft.client.resource.language.I18n
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.component.type.NbtComponent
-import net.minecraft.datafixer.Schemas
-import net.minecraft.datafixer.TypeReferences
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.nbt.NbtElement
-import net.minecraft.nbt.NbtOps
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.gui.config.HudMeta
-import moe.nea.firmament.gui.config.HudPosition
-import moe.nea.firmament.gui.hud.MoulConfigHud
-import moe.nea.firmament.util.LegacyTagParser
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.appendLore
-import moe.nea.firmament.util.item.setCustomName
-import moe.nea.firmament.util.item.setSkullOwner
-import moe.nea.firmament.util.modifyLore
-import moe.nea.firmament.util.skyblockId
-
-object ItemCache : IReloadable {
- private val cache: MutableMap<String, ItemStack> = ConcurrentHashMap()
- private val df = Schemas.getFixer()
- val logger = LogManager.getLogger("${Firmament.logger.name}.ItemCache")
- var isFlawless = true
- private set
-
- private fun NEUItem.get10809CompoundTag(): NbtCompound = NbtCompound().apply {
- put("tag", LegacyTagParser.parse(nbttag))
- putString("id", minecraftItemId)
- putByte("Count", 1)
- putShort("Damage", damage.toShort())
- }
-
- private fun NbtCompound.transformFrom10809ToModern(): NbtCompound? =
- try {
- df.update(
- TypeReferences.ITEM_STACK,
- Dynamic(NbtOps.INSTANCE, this),
- -1,
- SharedConstants.getGameVersion().saveVersion.id
- ).value as NbtCompound
- } catch (e: Exception) {
- isFlawless = false
- logger.error("Could not data fix up $this", e)
- null
- }
-
- fun brokenItemStack(neuItem: NEUItem?, idHint: SkyblockId? = null): ItemStack {
- return ItemStack(Items.PAINTING).apply {
- setCustomName(Text.literal(neuItem?.displayName ?: idHint?.neuItem ?: "null"))
- appendLore(
- listOf(
- Text.stringifiedTranslatable(
- "firmament.repo.brokenitem",
- (neuItem?.skyblockItemId ?: idHint)
- )
- )
- )
- }
- }
-
- private fun NEUItem.asItemStackNow(): ItemStack {
- try {
- val oldItemTag = get10809CompoundTag()
- val modernItemTag = oldItemTag.transformFrom10809ToModern()
- ?: return brokenItemStack(this)
- val itemInstance =
- ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this)
- val extraAttributes = oldItemTag.getCompound("tag").getCompound("ExtraAttributes")
- if (extraAttributes != null)
- itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes))
- return itemInstance
- } catch (e: Exception) {
- e.printStackTrace()
- return brokenItemStack(this)
- }
- }
-
- fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map<String, String>? = null): ItemStack {
- if (this == null) return brokenItemStack(null, idHint)
- var s = cache[this.skyblockItemId]
- if (s == null) {
- s = asItemStackNow()
- cache[this.skyblockItemId] = s
- }
- if (!loreReplacements.isNullOrEmpty()) {
- s = s.copy()!!
- s.applyLoreReplacements(loreReplacements)
- s.setCustomName(s.name.applyLoreReplacements(loreReplacements))
- }
- return s
- }
-
- fun ItemStack.applyLoreReplacements(loreReplacements: Map<String, String>) {
- modifyLore { lore ->
- lore.map {
- it.applyLoreReplacements(loreReplacements)
- }
- }
- }
-
- fun Text.applyLoreReplacements(loreReplacements: Map<String, String>): Text {
- assert(this.siblings.isEmpty())
- var string = this.string
- loreReplacements.forEach { (find, replace) ->
- string = string.replace("{$find}", replace)
- }
- return Text.literal(string).styled { this.style }
- }
-
- fun NEUItem.getIdentifier() = skyblockId.identifier
-
- var job: Job? = null
- object ReloadProgressHud : MoulConfigHud(
- "repo_reload", HudMeta(HudPosition(0.0, 0.0, 1F), Text.literal("Repo Reload"), 180, 18)) {
-
-
- var isEnabled = false
- override fun shouldRender(): Boolean {
- return isEnabled
- }
-
- @get:Bind("current")
- var current: Double = 0.0
-
- @get:Bind("label")
- var label: String = ""
-
- @get:Bind("max")
- var max: Double = 0.0
-
- fun reportProgress(label: String, current: Int, max: Int) {
- this.label = label
- this.current = current.toDouble()
- this.max = max.toDouble()
- }
- }
-
- override fun reload(repository: NEURepository) {
- val j = job
- if (j != null && j.isActive) {
- j.cancel()
- }
- cache.clear()
- isFlawless = true
-
- job = Firmament.coroutineScope.launch {
- val items = repository.items?.items
- if (items == null) {
- ReloadProgressHud.isEnabled = false
- return@launch
- }
- val recacheItems = I18n.translate("firmament.repo.cache")
- ReloadProgressHud.reportProgress(recacheItems, 0, items.size)
- ReloadProgressHud.isEnabled = true
- var i = 0
- items.values.forEach {
- it.asItemStack() // Rebuild cache
- ReloadProgressHud.reportProgress(recacheItems, i++, items.size)
- }
- ReloadProgressHud.isEnabled = false
- }
- }
-
- fun coinItem(coinAmount: Int): ItemStack {
- var uuid = UUID.fromString("2070f6cb-f5db-367a-acd0-64d39a7e5d1b")
- var texture =
- "http://textures.minecraft.net/texture/538071721cc5b4cd406ce431a13f86083a8973e1064d2f8897869930ee6e5237"
- if (coinAmount >= 100000) {
- uuid = UUID.fromString("94fa2455-2881-31fe-bb4e-e3e24d58dbe3")
- texture =
- "http://textures.minecraft.net/texture/c9b77999fed3a2758bfeaf0793e52283817bea64044bf43ef29433f954bb52f6"
- }
- if (coinAmount >= 10000000) {
- uuid = UUID.fromString("0af8df1f-098c-3b72-ac6b-65d65fd0b668")
- texture =
- "http://textures.minecraft.net/texture/7b951fed6a7b2cbc2036916dec7a46c4a56481564d14f945b6ebc03382766d3b"
- }
- val itemStack = ItemStack(Items.PLAYER_HEAD)
- itemStack.setCustomName(Text.literal("§r§6" + NumberFormat.getInstance().format(coinAmount) + " Coins"))
- itemStack.setSkullOwner(uuid, texture)
- return itemStack
- }
-}
-
-
-operator fun NbtCompound.set(key: String, value: String) {
- putString(key, value)
-}
-
-operator fun NbtCompound.set(key: String, value: NbtElement) {
- put(key, value)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/ItemNameLookup.kt b/src/main/kotlin/moe/nea/firmament/repo/ItemNameLookup.kt
deleted file mode 100644
index 770de85..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/ItemNameLookup.kt
+++ /dev/null
@@ -1,98 +0,0 @@
-
-package moe.nea.firmament.repo
-
-import io.github.moulberry.repo.IReloadable
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.data.NEUItem
-import java.util.NavigableMap
-import java.util.TreeMap
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.removeColorCodes
-import moe.nea.firmament.util.skyblockId
-
-object ItemNameLookup : IReloadable {
-
- fun getItemNameChunks(name: String): Set<String> {
- return name.removeColorCodes().split(" ").filterTo(mutableSetOf()) { it.isNotBlank() }
- }
-
- var nameMap: NavigableMap<String, out Set<SkyblockId>> = TreeMap()
-
- override fun reload(repository: NEURepository) {
- val nameMap = TreeMap<String, MutableSet<SkyblockId>>()
- repository.items.items.values.forEach { item ->
- getAllNamesForItem(item).forEach { name ->
- val chunks = getItemNameChunks(name)
- chunks.forEach { chunk ->
- val set = nameMap.getOrPut(chunk, ::mutableSetOf)
- set.add(item.skyblockId)
- }
- }
- }
- this.nameMap = nameMap
- }
-
- fun getAllNamesForItem(item: NEUItem): Set<String> {
- val names = mutableSetOf<String>()
- names.add(item.displayName)
- if (item.displayName.contains("Enchanted Book")) {
- val enchantName = item.lore.firstOrNull()
- if (enchantName != null) {
- names.add(enchantName)
- }
- }
- return names
- }
-
- fun findItemCandidatesByName(name: String): MutableSet<SkyblockId> {
- val candidates = mutableSetOf<SkyblockId>()
- for (chunk in getItemNameChunks(name)) {
- val set = nameMap[chunk] ?: emptySet()
- candidates.addAll(set)
- }
- return candidates
- }
-
-
- fun guessItemByName(
- /**
- * The display name of the item. Color codes will be ignored.
- */
- name: String,
- /**
- * Whether the [name] may contain other text, such as reforges, master stars and such.
- */
- mayBeMangled: Boolean
- ): SkyblockId? {
- val cleanName = name.removeColorCodes()
- return findBestItemFromCandidates(
- findItemCandidatesByName(cleanName),
- cleanName,
- true
- )
- }
-
- fun findBestItemFromCandidates(
- candidates: Iterable<SkyblockId>,
- name: String, mayBeMangled: Boolean
- ): SkyblockId? {
- val expectedClean = name.removeColorCodes()
- var bestMatch: SkyblockId? = null
- var bestMatchLength = -1
- for (candidate in candidates) {
- val item = RepoManager.getNEUItem(candidate) ?: continue
- for (name in getAllNamesForItem(item)) {
- val actualClean = name.removeColorCodes()
- val matches = if (mayBeMangled) expectedClean == actualClean
- else expectedClean.contains(actualClean)
- if (!matches) continue
- if (actualClean.length > bestMatchLength) {
- bestMatch = candidate
- bestMatchLength = actualClean.length
- }
- }
- }
- return bestMatch
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/RepoDownloadManager.kt b/src/main/kotlin/moe/nea/firmament/repo/RepoDownloadManager.kt
deleted file mode 100644
index d674f23..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/RepoDownloadManager.kt
+++ /dev/null
@@ -1,128 +0,0 @@
-
-
-package moe.nea.firmament.repo
-
-import io.ktor.client.call.body
-import io.ktor.client.request.get
-import io.ktor.client.statement.bodyAsChannel
-import io.ktor.utils.io.jvm.nio.copyTo
-import java.io.IOException
-import java.nio.file.Files
-import java.nio.file.Path
-import java.nio.file.StandardOpenOption
-import java.util.zip.ZipInputStream
-import kotlinx.coroutines.CoroutineName
-import kotlinx.coroutines.Dispatchers.IO
-import kotlinx.coroutines.withContext
-import kotlinx.serialization.Serializable
-import kotlin.io.path.createDirectories
-import kotlin.io.path.exists
-import kotlin.io.path.inputStream
-import kotlin.io.path.outputStream
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.Firmament.logger
-import moe.nea.firmament.util.iterate
-
-
-object RepoDownloadManager {
-
- val repoSavedLocation = Firmament.DATA_DIR.resolve("repo-extracted")
- val repoMetadataLocation = Firmament.DATA_DIR.resolve("loaded-repo-sha.txt")
-
- private fun loadSavedVersionHash(): String? =
- if (repoSavedLocation.exists()) {
- if (repoMetadataLocation.exists()) {
- try {
- repoMetadataLocation.readText().trim()
- } catch (e: IOException) {
- null
- }
- } else {
- null
- }
- } else null
-
- private fun saveVersionHash(versionHash: String) {
- latestSavedVersionHash = versionHash
- repoMetadataLocation.writeText(versionHash)
- }
-
- var latestSavedVersionHash: String? = loadSavedVersionHash()
- private set
-
- @Serializable
- private class GithubCommitsResponse(val sha: String)
-
- private suspend fun requestLatestGithubSha(): String? {
- if (RepoManager.Config.branch == "prerelease") {
- RepoManager.Config.branch = "master"
- }
- val response =
- Firmament.httpClient.get("https://api.github.com/repos/${RepoManager.Config.username}/${RepoManager.Config.reponame}/commits/${RepoManager.Config.branch}")
- if (response.status.value != 200) {
- return null
- }
- return response.body<GithubCommitsResponse>().sha
- }
-
- private suspend fun downloadGithubArchive(url: String): Path = withContext(IO) {
- val response = Firmament.httpClient.get(url)
- val targetFile = Files.createTempFile("firmament-repo", ".zip")
- val outputChannel = Files.newByteChannel(targetFile, StandardOpenOption.CREATE, StandardOpenOption.WRITE)
- response.bodyAsChannel().copyTo(outputChannel)
- targetFile
- }
-
- /**
- * Downloads the latest repository from github, setting [latestSavedVersionHash].
- * @return true, if an update was performed, false, otherwise (no update needed, or wasn't able to complete update)
- */
- suspend fun downloadUpdate(force: Boolean): Boolean = withContext(CoroutineName("Repo Update Check")) {
- val latestSha = requestLatestGithubSha()
- if (latestSha == null) {
- logger.warn("Could not request github API to retrieve latest REPO sha.")
- return@withContext false
- }
- val currentSha = loadSavedVersionHash()
- if (latestSha != currentSha || force) {
- val requestUrl =
- "https://github.com/${RepoManager.Config.username}/${RepoManager.Config.reponame}/archive/$latestSha.zip"
- logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
- val zipFile = downloadGithubArchive(requestUrl)
- logger.info("Download repository zip file to $zipFile. Deleting old repository")
- withContext(IO) { repoSavedLocation.toFile().deleteRecursively() }
- logger.info("Extracting new repository")
- withContext(IO) { extractNewRepository(zipFile) }
- logger.info("Repository loaded on disk.")
- saveVersionHash(latestSha)
- return@withContext true
- } else {
- logger.debug("Repository on latest sha $currentSha. Not performing update")
- return@withContext false
- }
- }
-
- private fun extractNewRepository(zipFile: Path) {
- repoSavedLocation.createDirectories()
- ZipInputStream(zipFile.inputStream()).use { cis ->
- while (true) {
- val entry = cis.nextEntry ?: break
- if (entry.isDirectory) continue
- val extractedLocation =
- repoSavedLocation.resolve(
- entry.name.substringAfter('/', missingDelimiterValue = "")
- )
- if (repoSavedLocation !in extractedLocation.iterate { it.parent }) {
- logger.error("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
- throw RuntimeException("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
- }
- extractedLocation.parent.createDirectories()
- extractedLocation.outputStream().use { cis.copyTo(it) }
- }
- }
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt b/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt
deleted file mode 100644
index f0da397..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/RepoManager.kt
+++ /dev/null
@@ -1,145 +0,0 @@
-package moe.nea.firmament.repo
-
-import io.github.moulberry.repo.NEURepository
-import io.github.moulberry.repo.NEURepositoryException
-import io.github.moulberry.repo.data.NEUItem
-import io.github.moulberry.repo.data.NEURecipe
-import io.github.moulberry.repo.data.Rarity
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
-import kotlinx.coroutines.launch
-import net.minecraft.client.MinecraftClient
-import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.Firmament.logger
-import moe.nea.firmament.events.ReloadRegistrationEvent
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.rei.PetData
-import moe.nea.firmament.util.MinecraftDispatcher
-import moe.nea.firmament.util.SkyblockId
-
-object RepoManager {
- object Config : ManagedConfig("repo") {
- var username by string("username") { "NotEnoughUpdates" }
- var reponame by string("reponame") { "NotEnoughUpdates-REPO" }
- var branch by string("branch") { "master" }
- val autoUpdate by toggle("autoUpdate") { true }
- val reset by button("reset") {
- username = "NotEnoughUpdates"
- reponame = "NotEnoughUpdates-REPO"
- branch = "master"
- save()
- }
-
- val disableItemGroups by toggle("disable-item-groups") { true }
- val reload by button("reload") {
- save()
- RepoManager.reload()
- }
- val redownload by button("redownload") {
- save()
- RepoManager.launchAsyncUpdate(true)
- }
- }
-
- val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash
-
- var recentlyFailedToUpdateItemList = false
-
- val neuRepo: NEURepository = NEURepository.of(RepoDownloadManager.repoSavedLocation).apply {
- registerReloadListener(ItemCache)
- registerReloadListener(ExpLadders)
- registerReloadListener(ItemNameLookup)
- ReloadRegistrationEvent.publish(ReloadRegistrationEvent(this))
- registerReloadListener {
- Firmament.coroutineScope.launch(MinecraftDispatcher) {
- if (!trySendClientboundUpdateRecipesPacket()) {
- logger.warn("Failed to issue a ClientboundUpdateRecipesPacket (to reload REI). This may lead to an outdated item list.")
- recentlyFailedToUpdateItemList = true
- }
- }
- }
- }
-
- val essenceRecipeProvider = EssenceRecipeProvider()
- val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider)
-
- init {
- neuRepo.registerReloadListener(essenceRecipeProvider)
- neuRepo.registerReloadListener(recipeCache)
- }
-
- fun getAllRecipes() = neuRepo.items.items.values.asSequence().flatMap { it.recipes }
-
- fun getRecipesFor(skyblockId: SkyblockId): Set<NEURecipe> = recipeCache.recipes[skyblockId] ?: setOf()
- fun getUsagesFor(skyblockId: SkyblockId): Set<NEURecipe> = recipeCache.usages[skyblockId] ?: setOf()
-
- private fun trySendClientboundUpdateRecipesPacket(): Boolean {
- return MinecraftClient.getInstance().world != null && MinecraftClient.getInstance().networkHandler?.onSynchronizeRecipes(
- SynchronizeRecipesS2CPacket(mutableListOf())
- ) != null
- }
-
- init {
- ClientTickEvents.START_WORLD_TICK.register(ClientTickEvents.StartWorldTick {
- if (recentlyFailedToUpdateItemList && trySendClientboundUpdateRecipesPacket())
- recentlyFailedToUpdateItemList = false
- })
- }
-
- fun getNEUItem(skyblockId: SkyblockId): NEUItem? = neuRepo.items.getItemBySkyblockId(skyblockId.neuItem)
-
- fun launchAsyncUpdate(force: Boolean = false) {
- Firmament.coroutineScope.launch {
- ItemCache.ReloadProgressHud.reportProgress("Downloading", 0, -1) // TODO: replace with a proper boundy bar
- ItemCache.ReloadProgressHud.isEnabled = true
- try {
- RepoDownloadManager.downloadUpdate(force)
- ItemCache.ReloadProgressHud.reportProgress("Download complete", 1, 1)
- } finally {
- ItemCache.ReloadProgressHud.isEnabled = false
- }
- reload()
- }
- }
-
- fun reload() {
- try {
- ItemCache.ReloadProgressHud.reportProgress("Reloading from Disk",
- 0,
- -1) // TODO: replace with a proper boundy bar
- ItemCache.ReloadProgressHud.isEnabled = true
- neuRepo.reload()
- } catch (exc: NEURepositoryException) {
- MinecraftClient.getInstance().player?.sendMessage(
- Text.literal("Failed to reload repository. This will result in some mod features not working.")
- )
- ItemCache.ReloadProgressHud.isEnabled = false
- exc.printStackTrace()
- }
- }
-
- fun initialize() {
- if (Config.autoUpdate) {
- launchAsyncUpdate()
- } else {
- reload()
- }
- }
-
- fun getPotentialStubPetData(skyblockId: SkyblockId): PetData? {
- val parts = skyblockId.neuItem.split(";")
- if (parts.size != 2) {
- return null
- }
- val (petId, rarityIndex) = parts
- if (!rarityIndex.all { it.isDigit() }) {
- return null
- }
- val intIndex = rarityIndex.toInt()
- if (intIndex !in Rarity.values().indices) return null
- if (petId !in neuRepo.constants.petNumbers) return null
- return PetData(Rarity.values()[intIndex], petId, 0.0, true)
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt b/src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt
deleted file mode 100644
index f92fe4f..0000000
--- a/src/main/kotlin/moe/nea/firmament/repo/RepoModResourcePack.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-
-package moe.nea.firmament.repo
-
-import java.io.InputStream
-import java.nio.file.Files
-import java.nio.file.Path
-import java.util.*
-import net.fabricmc.fabric.api.resource.ModResourcePack
-import net.fabricmc.loader.api.FabricLoader
-import net.fabricmc.loader.api.metadata.ModMetadata
-import kotlin.io.path.exists
-import kotlin.io.path.isRegularFile
-import kotlin.io.path.relativeTo
-import kotlin.streams.asSequence
-import net.minecraft.resource.AbstractFileResourcePack
-import net.minecraft.resource.InputSupplier
-import net.minecraft.resource.NamespaceResourceManager
-import net.minecraft.resource.Resource
-import net.minecraft.resource.ResourcePack
-import net.minecraft.resource.ResourcePackInfo
-import net.minecraft.resource.ResourcePackSource
-import net.minecraft.resource.ResourceType
-import net.minecraft.resource.metadata.ResourceMetadata
-import net.minecraft.resource.metadata.ResourceMetadataReader
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import net.minecraft.util.PathUtil
-import moe.nea.firmament.Firmament
-
-class RepoModResourcePack(val basePath: Path) : ModResourcePack {
- companion object {
- fun append(packs: MutableList<in ModResourcePack>) {
- Firmament.logger.info("Registering mod resource pack")
- packs.add(RepoModResourcePack(RepoDownloadManager.repoSavedLocation))
- }
-
- fun createResourceDirectly(identifier: Identifier): Optional<Resource> {
- val pack = RepoModResourcePack(RepoDownloadManager.repoSavedLocation)
- return Optional.of(
- Resource(
- pack,
- pack.open(ResourceType.CLIENT_RESOURCES, identifier) ?: return Optional.empty()
- ) {
- val base =
- pack.open(ResourceType.CLIENT_RESOURCES, identifier.withPath(identifier.path + ".mcmeta"))
- if (base == null)
- ResourceMetadata.NONE
- else
- NamespaceResourceManager.loadMetadata(base)
- }
- )
- }
- }
-
- override fun close() {
- }
-
- override fun openRoot(vararg segments: String): InputSupplier<InputStream>? {
- return getFile(segments)?.let { InputSupplier.create(it) }
- }
-
- fun getFile(segments: Array<out String>): Path? {
- PathUtil.validatePath(*segments)
- val path = segments.fold(basePath, Path::resolve)
- if (!path.isRegularFile()) return null
- return path
- }
-
- override fun open(type: ResourceType?, id: Identifier): InputSupplier<InputStream>? {
- if (type != ResourceType.CLIENT_RESOURCES) return null
- if (id.namespace != "neurepo") return null
- val file = getFile(id.path.split("/").toTypedArray())
- return file?.let { InputSupplier.create(it) }
- }
-
- override fun findResources(
- type: ResourceType?,
- namespace: String,
- prefix: String,
- consumer: ResourcePack.ResultConsumer
- ) {
- if (namespace != "neurepo") return
- if (type != ResourceType.CLIENT_RESOURCES) return
-
- val prefixPath = basePath.resolve(prefix)
- if (!prefixPath.exists())
- return
- Files.walk(prefixPath)
- .asSequence()
- .map { it.relativeTo(basePath) }
- .forEach {
- consumer.accept(Identifier.of("neurepo", it.toString()), InputSupplier.create(it))
- }
- }
-
- override fun getNamespaces(type: ResourceType?): Set<String> {
- if (type != ResourceType.CLIENT_RESOURCES) return emptySet()
- return setOf("neurepo")
- }
-
- override fun <T> parseMetadata(metaReader: ResourceMetadataReader<T>): T? {
- return AbstractFileResourcePack.parseMetadata(
- metaReader, """
-{
- "pack": {
- "pack_format": 12,
- "description": "NEU Repo Resources"
- }
-}
-""".trimIndent().byteInputStream()
- )
- }
-
- override fun getInfo(): ResourcePackInfo {
- return ResourcePackInfo("neurepo", Text.literal("NEU Repo"), ResourcePackSource.BUILTIN, Optional.empty())
- }
-
- override fun getFabricModMetadata(): ModMetadata {
- return FabricLoader.getInstance().getModContainer("firmament")
- .get().metadata
- }
-
- override fun createOverlay(overlay: String): ModResourcePack {
- return RepoModResourcePack(basePath.resolve(overlay))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/Base64Util.kt b/src/main/kotlin/moe/nea/firmament/util/Base64Util.kt
deleted file mode 100644
index 44bcdfd..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/Base64Util.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-package moe.nea.firmament.util
-
-object Base64Util {
- fun String.padToValidBase64(): String {
- val align = this.length % 4
- if (align == 0) return this
- return this + "=".repeat(4 - align)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/BazaarPriceStrategy.kt b/src/main/kotlin/moe/nea/firmament/util/BazaarPriceStrategy.kt
deleted file mode 100644
index 002eedb..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/BazaarPriceStrategy.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-
-package moe.nea.firmament.util
-
-import moe.nea.firmament.repo.HypixelStaticData
-
-enum class BazaarPriceStrategy {
- BUY_ORDER,
- SELL_ORDER,
- NPC_SELL;
-
- fun getSellPrice(skyblockId: SkyblockId): Double {
- val bazaarEntry = HypixelStaticData.bazaarData[skyblockId] ?: return 0.0
- return when (this) {
- BUY_ORDER -> bazaarEntry.quickStatus.sellPrice
- SELL_ORDER -> bazaarEntry.quickStatus.buyPrice
- NPC_SELL -> TODO()
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/ClipboardUtils.kt b/src/main/kotlin/moe/nea/firmament/util/ClipboardUtils.kt
deleted file mode 100644
index 7b9b836..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/ClipboardUtils.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import moe.nea.firmament.Firmament
-
-object ClipboardUtils {
- fun setTextContent(string: String) {
- try {
- MC.keyboard.clipboard = string.ifEmpty { " " }
- } catch (e: Exception) {
- Firmament.logger.error("Could not write clipboard", e)
- }
- }
-
- fun getTextContents(): String {
- try {
- return MC.keyboard.clipboard ?: ""
- } catch (e: Exception) {
- Firmament.logger.error("Could not read clipboard", e)
- return ""
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/CommonSoundEffects.kt b/src/main/kotlin/moe/nea/firmament/util/CommonSoundEffects.kt
deleted file mode 100644
index a97a2cb..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/CommonSoundEffects.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.minecraft.client.sound.PositionedSoundInstance
-import net.minecraft.sound.SoundEvent
-import net.minecraft.util.Identifier
-
-// TODO: Replace these with custom sound events that just re use the vanilla ogg s
-object CommonSoundEffects {
- fun playSound(identifier: Identifier) {
- MC.soundManager.play(PositionedSoundInstance.master(SoundEvent.of(identifier), 1F))
- }
-
- fun playFailure() {
- playSound(Identifier.of("minecraft", "block.anvil.place"))
- }
-
- fun playSuccess() {
- playDing()
- }
-
- fun playDing() {
- playSound(Identifier.of("minecraft", "entity.arrow.hit_player"))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/DurabilityBarEvent.kt b/src/main/kotlin/moe/nea/firmament/util/DurabilityBarEvent.kt
deleted file mode 100644
index 993462c..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/DurabilityBarEvent.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-package moe.nea.firmament.util
-
-import me.shedaniel.math.Color
-import net.minecraft.item.ItemStack
-import moe.nea.firmament.events.FirmamentEvent
-import moe.nea.firmament.events.FirmamentEventBus
-
-data class DurabilityBarEvent(
- val item: ItemStack,
-) : FirmamentEvent() {
- data class DurabilityBar(
- val color: Color,
- val percentage: Float,
- )
-
- var barOverride: DurabilityBar? = null
-
- companion object : FirmamentEventBus<DurabilityBarEvent>()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/ErrorBoundary.kt b/src/main/kotlin/moe/nea/firmament/util/ErrorBoundary.kt
deleted file mode 100644
index fbc5b37..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/ErrorBoundary.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-
-fun <T> errorBoundary(block: () -> T): T? {
- // TODO: implement a proper error boundary here to avoid crashing minecraft code
- return block()
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/FirmFormatters.kt b/src/main/kotlin/moe/nea/firmament/util/FirmFormatters.kt
deleted file mode 100644
index c3bdd16..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/FirmFormatters.kt
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import com.google.common.math.IntMath.pow
-import kotlin.math.absoluteValue
-import kotlin.time.Duration
-
-object FirmFormatters {
- fun formatCommas(int: Int, segments: Int = 3): String = formatCommas(int.toLong(), segments)
- fun formatCommas(long: Long, segments: Int = 3): String {
- val α = long / 1000
- if (α != 0L) {
- return formatCommas(α, segments) + "," + (long - α * 1000).toString().padStart(3, '0')
- }
- return long.toString()
- }
-
- fun formatCommas(float: Float, fractionalDigits: Int): String = formatCommas(float.toDouble(), fractionalDigits)
- fun formatCommas(double: Double, fractionalDigits: Int): String {
- val long = double.toLong()
- val δ = (double - long).absoluteValue
- val μ = pow(10, fractionalDigits)
- val digits = (μ * δ).toInt().toString().padStart(fractionalDigits, '0').trimEnd('0')
- return formatCommas(long) + (if (digits.isEmpty()) "" else ".$digits")
- }
-
- fun formatDistance(distance: Double): String {
- if (distance < 10)
- return "%.1fm".format(distance)
- return "%dm".format(distance.toInt())
- }
-
- fun formatTimespan(duration: Duration, millis: Boolean = false): String {
- if (duration.isInfinite()) {
- return if (duration.isPositive()) "∞"
- else "-∞"
- }
- val sb = StringBuilder()
- if (duration.isNegative()) sb.append("-")
- duration.toComponents { days, hours, minutes, seconds, nanoseconds ->
- if (days > 0) {
- sb.append(days).append("d")
- }
- if (hours > 0) {
- sb.append(hours).append("h")
- }
- if (minutes > 0) {
- sb.append(minutes).append("m")
- }
- sb.append(seconds).append("s")
- if (millis) {
- sb.append(nanoseconds / 1_000_000).append("ms")
- }
- }
- return sb.toString()
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/FragmentGuiScreen.kt b/src/main/kotlin/moe/nea/firmament/util/FragmentGuiScreen.kt
deleted file mode 100644
index 5e13d51..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/FragmentGuiScreen.kt
+++ /dev/null
@@ -1,93 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import io.github.notenoughupdates.moulconfig.gui.GuiContext
-import me.shedaniel.math.Dimension
-import me.shedaniel.math.Point
-import me.shedaniel.math.Rectangle
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.gui.screen.Screen
-import net.minecraft.text.Text
-
-abstract class FragmentGuiScreen(
- val dismissOnOutOfBounds: Boolean = true
-) : Screen(Text.literal("")) {
- var popup: MoulConfigFragment? = null
-
- fun createPopup(context: GuiContext, position: Point) {
- popup = MoulConfigFragment(context, position) { popup = null }
- }
-
- override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) {
- super.render(context, mouseX, mouseY, delta)
- context.matrices.push()
- context.matrices.translate(0f, 0f, 1000f)
- popup?.render(context, mouseX, mouseY, delta)
- context.matrices.pop()
- }
-
- private inline fun ifPopup(ifYes: (MoulConfigFragment) -> Unit): Boolean {
- val p = popup ?: return false
- ifYes(p)
- return true
- }
-
- override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- return ifPopup {
- it.keyPressed(keyCode, scanCode, modifiers)
- }
- }
-
- override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean {
- return ifPopup {
- it.keyReleased(keyCode, scanCode, modifiers)
- }
- }
-
- override fun mouseMoved(mouseX: Double, mouseY: Double) {
- ifPopup { it.mouseMoved(mouseX, mouseY) }
- }
-
- override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
- return ifPopup {
- it.mouseReleased(mouseX, mouseY, button)
- }
- }
-
- override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean {
- return ifPopup {
- it.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)
- }
- }
-
- override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
- return ifPopup {
- if (!Rectangle(
- it.position,
- Dimension(it.context.root.width, it.context.root.height)
- ).contains(Point(mouseX, mouseY))
- && dismissOnOutOfBounds
- ) {
- popup = null
- } else {
- it.mouseClicked(mouseX, mouseY, button)
- }
- }|| super.mouseClicked(mouseX, mouseY, button)
- }
-
- override fun charTyped(chr: Char, modifiers: Int): Boolean {
- return ifPopup { it.charTyped(chr, modifiers) }
- }
-
- override fun mouseScrolled(
- mouseX: Double,
- mouseY: Double,
- horizontalAmount: Double,
- verticalAmount: Double
- ): Boolean {
- return ifPopup {
- it.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount)
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/GetRectangle.kt b/src/main/kotlin/moe/nea/firmament/util/GetRectangle.kt
deleted file mode 100644
index ec64f31..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/GetRectangle.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import me.shedaniel.math.Rectangle
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-
-fun HandledScreen<*>.getRectangle(): Rectangle {
- this as AccessorHandledScreen
- return Rectangle(
- getX_Firmament(),
- getY_Firmament(),
- getBackgroundWidth_Firmament(),
- getBackgroundHeight_Firmament()
- )
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/HoveredItemStack.kt b/src/main/kotlin/moe/nea/firmament/util/HoveredItemStack.kt
deleted file mode 100644
index 47a59d0..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/HoveredItemStack.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import me.shedaniel.math.impl.PointHelper
-import me.shedaniel.rei.api.client.REIRuntime
-import me.shedaniel.rei.api.client.gui.widgets.Slot
-import me.shedaniel.rei.api.client.registry.screen.ScreenRegistry
-import net.minecraft.client.gui.Element
-import net.minecraft.client.gui.ParentElement
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.item.ItemStack
-import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
-
-
-val HandledScreen<*>.focusedItemStack: ItemStack?
- get() {
- this as AccessorHandledScreen
- val vanillaSlot = this.focusedSlot_Firmament?.stack
- if (vanillaSlot != null) return vanillaSlot
- val focusedSlot = ScreenRegistry.getInstance().getFocusedStack(this, PointHelper.ofMouse())
- if (focusedSlot != null) return focusedSlot.cheatsAs().value
- var baseElement: Element? = REIRuntime.getInstance().overlay.orElse(null)
- val mx = PointHelper.getMouseFloatingX()
- val my = PointHelper.getMouseFloatingY()
- while (true) {
- if (baseElement is Slot) return baseElement.currentEntry.cheatsAs().value
- if (baseElement !is ParentElement) return null
- baseElement = baseElement.hoveredElement(mx, my).orElse(null)
- }
- }
diff --git a/src/main/kotlin/moe/nea/firmament/util/IdentifierSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/IdentifierSerializer.kt
deleted file mode 100644
index 65c5b1c..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/IdentifierSerializer.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-package moe.nea.firmament.util
-
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.builtins.serializer
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import net.minecraft.util.Identifier
-
-object IdentifierSerializer : KSerializer<Identifier> {
- val delegateSerializer = String.serializer()
- override val descriptor: SerialDescriptor
- get() = PrimitiveSerialDescriptor("Identifier", PrimitiveKind.STRING)
-
- override fun deserialize(decoder: Decoder): Identifier {
- return Identifier.of(decoder.decodeSerializableValue(delegateSerializer))
- }
-
- override fun serialize(encoder: Encoder, value: Identifier) {
- encoder.encodeSerializableValue(delegateSerializer, value.toString())
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/IdentityCharacteristics.kt b/src/main/kotlin/moe/nea/firmament/util/IdentityCharacteristics.kt
deleted file mode 100644
index f6054c4..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/IdentityCharacteristics.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-class IdentityCharacteristics<T>(val value: T) {
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (other !is IdentityCharacteristics<*>) return false
- return value === other.value
- }
-
- override fun hashCode(): Int {
- return System.identityHashCode(value)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt b/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt
deleted file mode 100644
index 40d6198..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/ItemUtil.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.nbt.NbtList
-import net.minecraft.text.Text
-import moe.nea.firmament.util.item.loreAccordingToNbt
-
-
-fun ItemStack.appendLore(args: List<Text>) {
- if (args.isEmpty()) return
- modifyLore {
- val loreList = loreAccordingToNbt.toMutableList()
- for (arg in args) {
- loreList.add(arg)
- }
- loreList
- }
-}
-
-fun ItemStack.modifyLore(update: (List<Text>) -> List<Text>) {
- val loreList = loreAccordingToNbt
- loreAccordingToNbt = update(loreList)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/LegacyFormattingCode.kt b/src/main/kotlin/moe/nea/firmament/util/LegacyFormattingCode.kt
deleted file mode 100644
index 44bacfc..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/LegacyFormattingCode.kt
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.minecraft.util.Formatting
-
-enum class LegacyFormattingCode(val label: String, val char: Char, val index: Int) {
- BLACK("BLACK", '0', 0),
- DARK_BLUE("DARK_BLUE", '1', 1),
- DARK_GREEN("DARK_GREEN", '2', 2),
- DARK_AQUA("DARK_AQUA", '3', 3),
- DARK_RED("DARK_RED", '4', 4),
- DARK_PURPLE("DARK_PURPLE", '5', 5),
- GOLD("GOLD", '6', 6),
- GRAY("GRAY", '7', 7),
- DARK_GRAY("DARK_GRAY", '8', 8),
- BLUE("BLUE", '9', 9),
- GREEN("GREEN", 'a', 10),
- AQUA("AQUA", 'b', 11),
- RED("RED", 'c', 12),
- LIGHT_PURPLE("LIGHT_PURPLE", 'd', 13),
- YELLOW("YELLOW", 'e', 14),
- WHITE("WHITE", 'f', 15),
- OBFUSCATED("OBFUSCATED", 'k', -1),
- BOLD("BOLD", 'l', -1),
- STRIKETHROUGH("STRIKETHROUGH", 'm', -1),
- UNDERLINE("UNDERLINE", 'n', -1),
- ITALIC("ITALIC", 'o', -1),
- RESET("RESET", 'r', -1);
-
- val modern = Formatting.byCode(char)!!
-
- val formattingCode = "§$char"
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/LegacyTagParser.kt b/src/main/kotlin/moe/nea/firmament/util/LegacyTagParser.kt
deleted file mode 100644
index 4e08da1..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/LegacyTagParser.kt
+++ /dev/null
@@ -1,245 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.util.*
-import net.minecraft.nbt.AbstractNbtNumber
-import net.minecraft.nbt.NbtByte
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.nbt.NbtDouble
-import net.minecraft.nbt.NbtElement
-import net.minecraft.nbt.NbtFloat
-import net.minecraft.nbt.NbtInt
-import net.minecraft.nbt.NbtList
-import net.minecraft.nbt.NbtLong
-import net.minecraft.nbt.NbtShort
-import net.minecraft.nbt.NbtString
-
-class LegacyTagParser private constructor(string: String) {
- data class TagParsingException(val baseString: String, val offset: Int, val mes0: String) :
- Exception("$mes0 at $offset in `$baseString`.")
-
- class StringRacer(val backing: String) {
- var idx = 0
- val stack = Stack<Int>()
-
- fun pushState() {
- stack.push(idx)
- }
-
- fun popState() {
- idx = stack.pop()
- }
-
- fun discardState() {
- stack.pop()
- }
-
- fun peek(count: Int): String {
- return backing.substring(minOf(idx, backing.length), minOf(idx + count, backing.length))
- }
-
- fun finished(): Boolean {
- return peek(1).isEmpty()
- }
-
- fun peekReq(count: Int): String? {
- val p = peek(count)
- if (p.length != count)
- return null
- return p
- }
-
- fun consumeCountReq(count: Int): String? {
- val p = peekReq(count)
- if (p != null)
- idx += count
- return p
- }
-
- fun tryConsume(string: String): Boolean {
- val p = peek(string.length)
- if (p != string)
- return false
- idx += p.length
- return true
- }
-
- fun consumeWhile(shouldConsumeThisString: (String) -> Boolean): String {
- var lastString: String = ""
- while (true) {
- val nextString = lastString + peek(1)
- if (!shouldConsumeThisString(nextString)) {
- return lastString
- }
- idx++
- lastString = nextString
- }
- }
-
- fun expect(search: String, errorMessage: String) {
- if (!tryConsume(search))
- error(errorMessage)
- }
-
- fun error(errorMessage: String): Nothing {
- throw TagParsingException(backing, idx, errorMessage)
- }
-
- }
-
- val racer = StringRacer(string)
- val baseTag = parseTag()
-
- companion object {
- val digitRange = "0123456789-"
- fun parse(string: String): NbtCompound {
- return LegacyTagParser(string).baseTag
- }
- }
-
- fun skipWhitespace() {
- racer.consumeWhile { Character.isWhitespace(it.last()) } // Only check last since other chars are always checked before.
- }
-
- fun parseTag(): NbtCompound {
- skipWhitespace()
- racer.expect("{", "Expected '{’ at start of tag")
- skipWhitespace()
- val tag = NbtCompound()
- while (!racer.tryConsume("}")) {
- skipWhitespace()
- val lhs = parseIdentifier()
- skipWhitespace()
- racer.expect(":", "Expected ':' after identifier in tag")
- skipWhitespace()
- val rhs = parseAny()
- tag.put(lhs, rhs)
- racer.tryConsume(",")
- skipWhitespace()
- }
- return tag
- }
-
- private fun parseAny(): NbtElement {
- skipWhitespace()
- val nextChar = racer.peekReq(1) ?: racer.error("Expected new object, found EOF")
- return when {
- nextChar == "{" -> parseTag()
- nextChar == "[" -> parseList()
- nextChar == "\"" -> parseStringTag()
- nextChar.first() in (digitRange) -> parseNumericTag()
- else -> racer.error("Unexpected token found. Expected start of new element")
- }
- }
-
- fun parseList(): NbtList {
- skipWhitespace()
- racer.expect("[", "Expected '[' at start of tag")
- skipWhitespace()
- val list = NbtList()
- while (!racer.tryConsume("]")) {
- skipWhitespace()
- racer.pushState()
- val lhs = racer.consumeWhile { it.all { it in digitRange } }
- skipWhitespace()
- if (!racer.tryConsume(":") || lhs.isEmpty()) { // No prefixed 0:
- racer.popState()
- list.add(parseAny()) // Reparse our number (or not a number) as actual tag
- } else {
- racer.discardState()
- skipWhitespace()
- list.add(parseAny()) // Ignore prefix indexes. They should not be generated out of order by any vanilla implementation (which is what NEU should export). Instead append where it appears in order.
- }
- skipWhitespace()
- racer.tryConsume(",")
- }
- return list
- }
-
- fun parseQuotedString(): String {
- skipWhitespace()
- racer.expect("\"", "Expected '\"' at string start")
- val sb = StringBuilder()
- while (true) {
- when (val peek = racer.consumeCountReq(1)) {
- "\"" -> break
- "\\" -> {
- val escaped = racer.consumeCountReq(1) ?: racer.error("Unfinished backslash escape")
- if (escaped != "\"" && escaped != "\\") {
- // Surprisingly i couldn't find unicode escapes to be generated by the original minecraft 1.8.9 implementation
- racer.idx--
- racer.error("Invalid backslash escape '$escaped'")
- }
- sb.append(escaped)
- }
-
- null -> racer.error("Unfinished string")
- else -> {
- sb.append(peek)
- }
- }
- }
- return sb.toString()
- }
-
- fun parseStringTag(): NbtString {
- return NbtString.of(parseQuotedString())
- }
-
- object Patterns {
- val DOUBLE = "([-+]?[0-9]*\\.?[0-9]+)[d|D]".toRegex()
- val FLOAT = "([-+]?[0-9]*\\.?[0-9]+)[f|F]".toRegex()
- val BYTE = "([-+]?[0-9]+)[b|B]".toRegex()
- val LONG = "([-+]?[0-9]+)[l|L]".toRegex()
- val SHORT = "([-+]?[0-9]+)[s|S]".toRegex()
- val INTEGER = "([-+]?[0-9]+)".toRegex()
- val DOUBLE_UNTYPED = "([-+]?[0-9]*\\.?[0-9]+)".toRegex()
- val ROUGH_PATTERN = "[-+]?[0-9]*\\.?[0-9]*[dDbBfFlLsS]?".toRegex()
- }
-
- fun parseNumericTag(): AbstractNbtNumber {
- skipWhitespace()
- val textForm = racer.consumeWhile { Patterns.ROUGH_PATTERN.matchEntire(it) != null }
- if (textForm.isEmpty()) {
- racer.error("Expected numeric tag (starting with either -, +, . or a digit")
- }
- val floatMatch = Patterns.FLOAT.matchEntire(textForm)
- if (floatMatch != null) {
- return NbtFloat.of(floatMatch.groups[1]!!.value.toFloat())
- }
- val byteMatch = Patterns.BYTE.matchEntire(textForm)
- if (byteMatch != null) {
- return NbtByte.of(byteMatch.groups[1]!!.value.toByte())
- }
- val longMatch = Patterns.LONG.matchEntire(textForm)
- if (longMatch != null) {
- return NbtLong.of(longMatch.groups[1]!!.value.toLong())
- }
- val shortMatch = Patterns.SHORT.matchEntire(textForm)
- if (shortMatch != null) {
- return NbtShort.of(shortMatch.groups[1]!!.value.toShort())
- }
- val integerMatch = Patterns.INTEGER.matchEntire(textForm)
- if (integerMatch != null) {
- return NbtInt.of(integerMatch.groups[1]!!.value.toInt())
- }
- val doubleMatch = Patterns.DOUBLE.matchEntire(textForm) ?: Patterns.DOUBLE_UNTYPED.matchEntire(textForm)
- if (doubleMatch != null) {
- return NbtDouble.of(doubleMatch.groups[1]!!.value.toDouble())
- }
- throw IllegalStateException("Could not properly parse numeric tag '$textForm', despite passing rough verification. This is a bug in the LegacyTagParser")
- }
-
- private fun parseIdentifier(): String {
- skipWhitespace()
- if (racer.peek(1) == "\"") {
- return parseQuotedString()
- }
- return racer.consumeWhile {
- val x = it.last()
- x != ':' && !Character.isWhitespace(x)
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/LoadResource.kt b/src/main/kotlin/moe/nea/firmament/util/LoadResource.kt
deleted file mode 100644
index 4bc8704..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/LoadResource.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-
-package moe.nea.firmament.util
-
-import java.io.InputStream
-import kotlin.io.path.inputStream
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.util.Identifier
-import moe.nea.firmament.repo.RepoDownloadManager
-
-
-fun Identifier.openFirmamentResource(): InputStream {
- val resource = MC.resourceManager.getResource(this).getOrNull()
- if (resource == null) {
- if (namespace == "neurepo")
- return RepoDownloadManager.repoSavedLocation.resolve(path).inputStream()
- error("Could not read resource $this")
- }
- return resource.inputStream
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/Locraw.kt b/src/main/kotlin/moe/nea/firmament/util/Locraw.kt
deleted file mode 100644
index 9778bc7..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/Locraw.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
-
-@Serializable
-data class Locraw(val server: String, val gametype: String? = null, val mode: String? = null, val map: String? = null) {
- @Transient
- val skyblockLocation = if (gametype == "SKYBLOCK") mode?.let(SkyBlockIsland::forMode) else null
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/LogIfNull.kt b/src/main/kotlin/moe/nea/firmament/util/LogIfNull.kt
deleted file mode 100644
index 600c5e6..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/LogIfNull.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-package moe.nea.firmament.util
-
-
-fun runNull(block: () -> Unit): Nothing? {
- block()
- return null
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/MC.kt b/src/main/kotlin/moe/nea/firmament/util/MC.kt
deleted file mode 100644
index b0d3056..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/MC.kt
+++ /dev/null
@@ -1,94 +0,0 @@
-package moe.nea.firmament.util
-
-import io.github.moulberry.repo.data.Coordinate
-import java.util.concurrent.ConcurrentLinkedQueue
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-import net.minecraft.client.render.WorldRenderer
-import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket
-import net.minecraft.registry.BuiltinRegistries
-import net.minecraft.registry.RegistryKeys
-import net.minecraft.registry.RegistryWrapper
-import net.minecraft.resource.ReloadableResourceManagerImpl
-import net.minecraft.text.Text
-import net.minecraft.util.math.BlockPos
-import moe.nea.firmament.events.TickEvent
-
-object MC {
-
- private val messageQueue = ConcurrentLinkedQueue<Text>()
-
- init {
- TickEvent.subscribe {
- while (true) {
- inGameHud.chatHud.addMessage(messageQueue.poll() ?: break)
- }
- while (true) {
- (nextTickTodos.poll() ?: break).invoke()
- }
- }
- }
-
- fun sendChat(text: Text) {
- if (instance.isOnThread)
- inGameHud.chatHud.addMessage(text)
- else
- messageQueue.add(text)
- }
-
- fun sendServerCommand(command: String) {
- val nh = player?.networkHandler ?: return
- nh.sendPacket(
- CommandExecutionC2SPacket(
- command,
- )
- )
- }
-
- fun sendServerChat(text: String) {
- player?.networkHandler?.sendChatMessage(text)
- }
-
- fun sendCommand(command: String) {
- player?.networkHandler?.sendCommand(command)
- }
-
- fun onMainThread(block: () -> Unit) {
- if (instance.isOnThread)
- block()
- else
- instance.send(block)
- }
-
- private val nextTickTodos = ConcurrentLinkedQueue<() -> Unit>()
- fun nextTick(function: () -> Unit) {
- nextTickTodos.add(function)
- }
-
-
- inline val resourceManager get() = (instance.resourceManager as ReloadableResourceManagerImpl)
- inline val worldRenderer: WorldRenderer get() = instance.worldRenderer
- inline val networkHandler get() = player?.networkHandler
- inline val instance get() = MinecraftClient.getInstance()
- inline val keyboard get() = instance.keyboard
- inline val textureManager get() = instance.textureManager
- inline val inGameHud get() = instance.inGameHud
- inline val font get() = instance.textRenderer
- inline val soundManager get() = instance.soundManager
- inline val player get() = instance.player
- inline val camera get() = instance.cameraEntity
- inline val guiAtlasManager get() = instance.guiAtlasManager
- inline val world get() = instance.world
- inline var screen
- get() = instance.currentScreen
- set(value) = instance.setScreen(value)
- inline val handledScreen: HandledScreen<*>? get() = instance.currentScreen as? HandledScreen<*>
- inline val window get() = instance.window
- inline val currentRegistries: RegistryWrapper.WrapperLookup? get() = world?.registryManager
- val defaultRegistries: RegistryWrapper.WrapperLookup = BuiltinRegistries.createWrapperLookup()
- val defaultItems = defaultRegistries.getWrapperOrThrow(RegistryKeys.ITEM)
-}
-
-
-val Coordinate.blockPos: BlockPos
- get() = BlockPos(x, y, z)
diff --git a/src/main/kotlin/moe/nea/firmament/util/MinecraftDispatcher.kt b/src/main/kotlin/moe/nea/firmament/util/MinecraftDispatcher.kt
deleted file mode 100644
index d1f22a9..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/MinecraftDispatcher.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import kotlinx.coroutines.asCoroutineDispatcher
-import net.minecraft.client.MinecraftClient
-
-val MinecraftDispatcher by lazy { MinecraftClient.getInstance().asCoroutineDispatcher() }
diff --git a/src/main/kotlin/moe/nea/firmament/util/MoulConfigFragment.kt b/src/main/kotlin/moe/nea/firmament/util/MoulConfigFragment.kt
deleted file mode 100644
index 36132cd..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/MoulConfigFragment.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
-import io.github.notenoughupdates.moulconfig.gui.GuiContext
-import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext
-import me.shedaniel.math.Point
-import net.minecraft.client.gui.DrawContext
-
-class MoulConfigFragment(
- context: GuiContext,
- val position: Point,
- val dismiss: () -> Unit
-) : GuiComponentWrapper(context) {
- init {
- this.init(MC.instance, MC.screen!!.width, MC.screen!!.height)
- }
-
- override fun createContext(drawContext: DrawContext?): GuiImmediateContext {
- val oldContext = super.createContext(drawContext)
- return oldContext.translated(
- position.x,
- position.y,
- context.root.width,
- context.root.height,
- )
- }
-
-
- override fun render(drawContext: DrawContext?, i: Int, j: Int, f: Float) {
- val ctx = createContext(drawContext)
- val m = drawContext!!.matrices
- m.push()
- m.translate(position.x.toFloat(), position.y.toFloat(), 0F)
- context.root.render(ctx)
- m.pop()
- ctx.renderContext.doDrawTooltip()
- }
-
- override fun close() {
- dismiss()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt b/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt
deleted file mode 100644
index 00561d1..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/MoulConfigUtils.kt
+++ /dev/null
@@ -1,230 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import io.github.notenoughupdates.moulconfig.common.MyResourceLocation
-import io.github.notenoughupdates.moulconfig.gui.CloseEventListener
-import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper
-import io.github.notenoughupdates.moulconfig.gui.GuiContext
-import io.github.notenoughupdates.moulconfig.observer.GetSetter
-import io.github.notenoughupdates.moulconfig.xml.ChildCount
-import io.github.notenoughupdates.moulconfig.xml.XMLContext
-import io.github.notenoughupdates.moulconfig.xml.XMLGuiLoader
-import io.github.notenoughupdates.moulconfig.xml.XMLUniverse
-import io.github.notenoughupdates.moulconfig.xml.XSDGenerator
-import java.io.File
-import java.util.function.Supplier
-import javax.xml.namespace.QName
-import me.shedaniel.math.Color
-import org.w3c.dom.Element
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.client.gui.screen.Screen
-import moe.nea.firmament.gui.BarComponent
-import moe.nea.firmament.gui.FirmButtonComponent
-import moe.nea.firmament.gui.FirmHoverComponent
-import moe.nea.firmament.gui.FixedComponent
-import moe.nea.firmament.gui.ImageComponent
-import moe.nea.firmament.gui.TickComponent
-
-object MoulConfigUtils {
- val firmUrl = "http://firmament.nea.moe/moulconfig"
- val universe = XMLUniverse.getDefaultUniverse().also { uni ->
- uni.registerMapper(java.awt.Color::class.java) {
- if (it.startsWith("#")) {
- val hexString = it.substring(1)
- val hex = hexString.toInt(16)
- if (hexString.length == 6) {
- return@registerMapper java.awt.Color(hex)
- }
- if (hexString.length == 8) {
- return@registerMapper java.awt.Color(hex, true)
- }
- error("Hexcolor $it needs to be exactly 6 or 8 hex digits long")
- }
- return@registerMapper java.awt.Color(it.toInt(), true)
- }
- uni.registerMapper(Color::class.java) {
- val color = uni.mapXMLObject(it, java.awt.Color::class.java)
- Color.ofRGBA(color.red, color.green, color.blue, color.alpha)
- }
- uni.registerLoader(object : XMLGuiLoader.Basic<BarComponent> {
- override fun getName(): QName {
- return QName(firmUrl, "Bar")
- }
-
- override fun createInstance(context: XMLContext<*>, element: Element): BarComponent {
- return BarComponent(
- context.getPropertyFromAttribute(element, QName("progress"), Double::class.java)!!,
- context.getPropertyFromAttribute(element, QName("total"), Double::class.java)!!,
- context.getPropertyFromAttribute(element, QName("fillColor"), Color::class.java)!!.get(),
- context.getPropertyFromAttribute(element, QName("emptyColor"), Color::class.java)!!.get(),
- )
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.NONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf("progress" to true, "total" to true, "emptyColor" to true, "fillColor" to true)
- }
- })
- uni.registerLoader(object : XMLGuiLoader.Basic<FirmHoverComponent> {
- override fun createInstance(context: XMLContext<*>, element: Element): FirmHoverComponent {
- return FirmHoverComponent(
- context.getChildFragment(element),
- context.getPropertyFromAttribute(element, QName("lines"), List::class.java) as Supplier<List<String>>,
- context.getPropertyFromAttribute(element, QName("delay"), Duration::class.java, 0.6.seconds),
- )
- }
-
- override fun getName(): QName {
- return QName(firmUrl, "Hover")
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.ONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf(
- "lines" to true,
- "delay" to false,
- )
- }
-
- })
- uni.registerLoader(object : XMLGuiLoader.Basic<FirmButtonComponent> {
- override fun getName(): QName {
- return QName(firmUrl, "Button")
- }
-
- override fun createInstance(context: XMLContext<*>, element: Element): FirmButtonComponent {
- return FirmButtonComponent(
- context.getChildFragment(element),
- context.getPropertyFromAttribute(element, QName("enabled"), Boolean::class.java)
- ?: GetSetter.constant(true),
- context.getPropertyFromAttribute(element, QName("noBackground"), Boolean::class.java, false),
- context.getMethodFromAttribute(element, QName("onClick")),
- )
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.ONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf("onClick" to true, "enabled" to false, "noBackground" to false)
- }
- })
- uni.registerLoader(object : XMLGuiLoader.Basic<ImageComponent> {
- override fun createInstance(context: XMLContext<*>, element: Element): ImageComponent {
- return ImageComponent(
- context.getPropertyFromAttribute(element, QName("width"), Int::class.java)!!.get(),
- context.getPropertyFromAttribute(element, QName("height"), Int::class.java)!!.get(),
- context.getPropertyFromAttribute(element, QName("resource"), MyResourceLocation::class.java)!!,
- context.getPropertyFromAttribute(element, QName("u1"), Float::class.java, 0f),
- context.getPropertyFromAttribute(element, QName("u2"), Float::class.java, 1f),
- context.getPropertyFromAttribute(element, QName("v1"), Float::class.java, 0f),
- context.getPropertyFromAttribute(element, QName("v2"), Float::class.java, 1f),
- )
- }
-
- override fun getName(): QName {
- return QName(firmUrl, "Image")
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.NONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf(
- "width" to true, "height" to true,
- "resource" to true,
- "u1" to false,
- "u2" to false,
- "v1" to false,
- "v2" to false,
- )
- }
- })
- uni.registerLoader(object : XMLGuiLoader.Basic<TickComponent> {
- override fun createInstance(context: XMLContext<*>, element: Element): TickComponent {
- return TickComponent(context.getMethodFromAttribute(element, QName("tick")))
- }
-
- override fun getName(): QName {
- return QName(firmUrl, "Tick")
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.NONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf("tick" to true)
- }
- })
- uni.registerLoader(object : XMLGuiLoader.Basic<FixedComponent> {
- override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent {
- return FixedComponent(
- context.getPropertyFromAttribute(element, QName("width"), Int::class.java)
- ?: error("Requires width specified"),
- context.getPropertyFromAttribute(element, QName("height"), Int::class.java)
- ?: error("Requires height specified"),
- context.getChildFragment(element)
- )
- }
-
- override fun getName(): QName {
- return QName(firmUrl, "Fixed")
- }
-
- override fun getChildCount(): ChildCount {
- return ChildCount.ONE
- }
-
- override fun getAttributeNames(): Map<String, Boolean> {
- return mapOf("width" to true, "height" to true)
- }
- })
- }
-
- fun generateXSD(
- file: File,
- namespace: String
- ) {
- val generator = XSDGenerator(universe, namespace)
- generator.writeAll()
- generator.dumpToFile(file)
- }
-
- @JvmStatic
- fun main(args: Array<out String>) {
- generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS)
- generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl)
- File("wrapper.xsd").writeText("""
-<?xml version="1.0" encoding="UTF-8" ?>
-<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
- <xs:import namespace="http://notenoughupdates.org/moulconfig" schemaLocation="MoulConfig.xsd"/>
- <xs:import namespace="http://firmament.nea.moe/moulconfig" schemaLocation="MoulConfig.Firmament.xsd"/>
-</xs:schema>
- """.trimIndent())
- }
-
- fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen {
- return object : GuiComponentWrapper(loadGui(name, bindTo)) {
- override fun close() {
- if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) {
- client!!.setScreen(parent)
- }
- }
- }
- }
-
- fun loadGui(name: String, bindTo: Any): GuiContext {
- return GuiContext(universe.load(bindTo, MyResourceLocation("firmament", "gui/$name.xml")))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt b/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt
deleted file mode 100644
index 067e652..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-package moe.nea.firmament.util
-
-fun <K, V> mutableMapWithMaxSize(maxSize: Int): MutableMap<K, V> = object : LinkedHashMap<K, V>() {
- override fun removeEldestEntry(eldest: MutableMap.MutableEntry<K, V>): Boolean {
- return size > maxSize
- }
-}
-
-fun <T, R> ((T) -> R).memoizeIdentity(maxCacheSize: Int): (T) -> R {
- val memoized = { it: IdentityCharacteristics<T> ->
- this(it.value)
- }.memoize(maxCacheSize)
- return { memoized(IdentityCharacteristics(it)) }
-}
-
-@PublishedApi
-internal val SENTINEL_NULL = java.lang.Object()
-
-/**
- * Requires the map to only contain values of type [R] or [SENTINEL_NULL]. This is ensured if the map is only ever
- * accessed via this function.
- */
-inline fun <T, R> MutableMap<T, Any>.computeNullableFunction(key: T, crossinline func: () -> R): R {
- val value = this.getOrPut(key) {
- func() ?: SENTINEL_NULL
- }
- @Suppress("UNCHECKED_CAST")
- return if (value === SENTINEL_NULL) null as R
- else value as R
-}
-
-fun <T, R> ((T) -> R).memoize(maxCacheSize: Int): (T) -> R {
- val map = mutableMapWithMaxSize<T, Any>(maxCacheSize)
- return {
- map.computeNullableFunction(it) { this@memoize(it) }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/SBData.kt b/src/main/kotlin/moe/nea/firmament/util/SBData.kt
deleted file mode 100644
index b30c6fb..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/SBData.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-package moe.nea.firmament.util
-
-import java.util.UUID
-import net.hypixel.modapi.HypixelModAPI
-import net.hypixel.modapi.packet.impl.clientbound.event.ClientboundLocationPacket
-import kotlin.jvm.optionals.getOrNull
-import kotlin.time.Duration.Companion.seconds
-import moe.nea.firmament.events.AllowChatEvent
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.events.ServerConnectedEvent
-import moe.nea.firmament.events.SkyblockServerUpdateEvent
-import moe.nea.firmament.events.WorldReadyEvent
-
-object SBData {
- private val profileRegex = "Profile ID: ([a-z0-9\\-]+)".toRegex()
- val profileSuggestTexts = listOf(
- "CLICK THIS TO SUGGEST IT IN CHAT [DASHES]",
- "CLICK THIS TO SUGGEST IT IN CHAT [NO DASHES]",
- )
- var profileId: UUID? = null
-
- private var hasReceivedProfile = false
- var locraw: Locraw? = null
- val skyblockLocation: SkyBlockIsland? get() = locraw?.skyblockLocation
- val hasValidLocraw get() = locraw?.server !in listOf("limbo", null)
- val isOnSkyblock get() = locraw?.gametype == "SKYBLOCK"
- var lastProfileIdRequest = TimeMark.farPast()
- fun init() {
- ServerConnectedEvent.subscribe {
- HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket::class.java)
- }
- HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket::class.java) {
- MC.onMainThread {
- val lastLocraw = locraw
- locraw = Locraw(it.serverName,
- it.serverType.getOrNull()?.name?.uppercase(),
- it.mode.getOrNull(),
- it.map.getOrNull())
- SkyblockServerUpdateEvent.publish(SkyblockServerUpdateEvent(lastLocraw, null))
- }
- }
- SkyblockServerUpdateEvent.subscribe {
- if (!hasReceivedProfile && isOnSkyblock && lastProfileIdRequest.passedTime() > 30.seconds) {
- lastProfileIdRequest = TimeMark.now()
- MC.sendServerCommand("profileid")
- }
- }
- AllowChatEvent.subscribe { event ->
- if (event.unformattedString in profileSuggestTexts && lastProfileIdRequest.passedTime() < 5.seconds) {
- event.cancel()
- }
- }
- ProcessChatEvent.subscribe(receivesCancelled = true) { event ->
- val profileMatch = profileRegex.matchEntire(event.unformattedString)
- if (profileMatch != null) {
- try {
- profileId = UUID.fromString(profileMatch.groupValues[1])
- hasReceivedProfile = true
- } catch (e: IllegalArgumentException) {
- profileId = null
- e.printStackTrace()
- }
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/ScoreboardUtil.kt b/src/main/kotlin/moe/nea/firmament/util/ScoreboardUtil.kt
deleted file mode 100644
index 4311971..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/ScoreboardUtil.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.util.*
-import net.minecraft.client.gui.hud.InGameHud
-import net.minecraft.scoreboard.ScoreboardDisplaySlot
-import net.minecraft.scoreboard.Team
-import net.minecraft.text.StringVisitable
-import net.minecraft.text.Style
-import net.minecraft.text.Text
-import net.minecraft.util.Formatting
-
-fun getScoreboardLines(): List<Text> {
- val scoreboard = MC.player?.scoreboard ?: return listOf()
- val activeObjective = scoreboard.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR) ?: return listOf()
- return scoreboard.getScoreboardEntries(activeObjective)
- .filter { !it.hidden() }
- .sortedWith(InGameHud.SCOREBOARD_ENTRY_COMPARATOR)
- .take(15).map {
- val team = scoreboard.getScoreHolderTeam(it.owner)
- val text = it.name()
- Team.decorateName(team, text)
- }
-}
-
-
-fun Text.formattedString(): String {
- val sb = StringBuilder()
- visit(StringVisitable.StyledVisitor<Unit> { style, string ->
- val c = Formatting.byName(style.color?.name)
- if (c != null) {
- sb.append("§${c.code}")
- }
- if (style.isUnderlined) {
- sb.append("§n")
- }
- if (style.isBold) {
- sb.append("§l")
- }
- sb.append(string)
- Optional.empty()
- }, Style.EMPTY)
- return sb.toString().replace("§[^a-f0-9]".toRegex(), "")
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/ScreenUtil.kt b/src/main/kotlin/moe/nea/firmament/util/ScreenUtil.kt
deleted file mode 100644
index 99d77fb..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/ScreenUtil.kt
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
-import net.minecraft.client.MinecraftClient
-import net.minecraft.client.gui.screen.Screen
-import moe.nea.firmament.Firmament
-
-object ScreenUtil {
- init {
- ClientTickEvents.START_CLIENT_TICK.register(::onTick)
- }
-
- private fun onTick(minecraft: MinecraftClient) {
- if (nextOpenedGui != null) {
- val p = minecraft.player
- if (p?.currentScreenHandler != null) {
- p.closeHandledScreen()
- }
- minecraft.setScreen(nextOpenedGui)
- nextOpenedGui = null
- }
- }
-
- private var nextOpenedGui: Screen? = null
-
- fun setScreenLater(nextScreen: Screen?) {
- val nog = nextOpenedGui
- if (nog != null) {
- Firmament.logger.warn("Setting screen ${if (nextScreen == null) "null" else nextScreen::class.qualifiedName} to be opened later, but ${nog::class.qualifiedName} is already queued.")
- return
- }
- nextOpenedGui = nextScreen
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/SequenceUtil.kt b/src/main/kotlin/moe/nea/firmament/util/SequenceUtil.kt
deleted file mode 100644
index 7b5bad0..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/SequenceUtil.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-fun <T : Any> T.iterate(iterator: (T) -> T?): Sequence<T> = sequence {
- var x: T? = this@iterate
- while (x != null) {
- yield(x)
- x = iterator(x)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/SkyBlockIsland.kt b/src/main/kotlin/moe/nea/firmament/util/SkyBlockIsland.kt
deleted file mode 100644
index bd0567d..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/SkyBlockIsland.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-
-package moe.nea.firmament.util
-
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import moe.nea.firmament.repo.RepoManager
-
-@Serializable(with = SkyBlockIsland.Serializer::class)
-class SkyBlockIsland
-private constructor(
- val locrawMode: String,
-) {
-
- object Serializer : KSerializer<SkyBlockIsland> {
- override val descriptor: SerialDescriptor
- get() = PrimitiveSerialDescriptor("SkyBlockIsland", PrimitiveKind.STRING)
-
- override fun deserialize(decoder: Decoder): SkyBlockIsland {
- return forMode(decoder.decodeString())
- }
-
- override fun serialize(encoder: Encoder, value: SkyBlockIsland) {
- encoder.encodeString(value.locrawMode)
- }
- }
- companion object {
- private val allIslands = mutableMapOf<String, SkyBlockIsland>()
- fun forMode(mode: String): SkyBlockIsland = allIslands.computeIfAbsent(mode, ::SkyBlockIsland)
- val HUB = forMode("hub")
- val PRIVATE_ISLAND = forMode("dynamic")
- val RIFT = forMode("rift")
- }
-
- val userFriendlyName
- get() = RepoManager.neuRepo.constants.islands.areaNames
- .getOrDefault(locrawMode, locrawMode)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt b/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt
deleted file mode 100644
index 59b1d2c..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/SkyblockId.kt
+++ /dev/null
@@ -1,149 +0,0 @@
-
-
-@file:UseSerializers(DashlessUUIDSerializer::class)
-
-package moe.nea.firmament.util
-
-import io.github.moulberry.repo.data.NEUItem
-import io.github.moulberry.repo.data.Rarity
-import java.util.UUID
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import kotlinx.serialization.json.Json
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.component.type.NbtComponent
-import net.minecraft.item.ItemStack
-import net.minecraft.nbt.NbtCompound
-import net.minecraft.util.Identifier
-import moe.nea.firmament.repo.set
-import moe.nea.firmament.util.json.DashlessUUIDSerializer
-
-/**
- * A skyblock item id, as used by the NEU repo.
- * This is not exactly the format used by HyPixel, but is mostly the same.
- * Usually this id splits an id used by HyPixel into more sub items. For example `PET` becomes `$PET_ID;$PET_RARITY`,
- * with those values extracted from other metadata.
- */
-@JvmInline
-@Serializable
-value class SkyblockId(val neuItem: String) {
- val identifier
- get() = Identifier.of("skyblockitem",
- neuItem.lowercase().replace(";", "__")
- .replace(":", "___")
- .replace(illlegalPathRegex) {
- it.value.toCharArray()
- .joinToString("") { "__" + it.code.toString(16).padStart(4, '0') }
- })
-
- override fun toString(): String {
- return neuItem
- }
-
- /**
- * A bazaar stock item id, as returned by the HyPixel bazaar api endpoint.
- * These are not equivalent to the in-game ids, or the NEU repo ids, and in fact, do not refer to items, but instead
- * to bazaar stocks. The main difference from [SkyblockId]s is concerning enchanted books. There are probably more,
- * but for now this holds.
- */
- @JvmInline
- @Serializable
- value class BazaarStock(val bazaarId: String) {
- fun toRepoId(): SkyblockId {
- bazaarEnchantmentRegex.matchEntire(bazaarId)?.let {
- return SkyblockId("${it.groupValues[1]};${it.groupValues[2]}")
- }
- return SkyblockId(bazaarId.replace(":", "-"))
- }
- }
-
- companion object {
- val COINS: SkyblockId = SkyblockId("SKYBLOCK_COIN")
- private val bazaarEnchantmentRegex = "ENCHANTMENT_(\\D*)_(\\d+)".toRegex()
- val NULL: SkyblockId = SkyblockId("null")
- val PET_NULL: SkyblockId = SkyblockId("null_pet")
- private val illlegalPathRegex = "[^a-z0-9_.-/]".toRegex()
- }
-}
-
-val NEUItem.skyblockId get() = SkyblockId(skyblockItemId)
-
-@Serializable
-data class HypixelPetInfo(
- val type: String,
- val tier: Rarity,
- val exp: Double = 0.0,
- val candyUsed: Int = 0,
- val uuid: UUID? = null,
-) {
- val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}")
-}
-
-private val jsonparser = Json { ignoreUnknownKeys = true }
-
-val ItemStack.extraAttributes: NbtCompound
- get() {
- val customData = get(DataComponentTypes.CUSTOM_DATA) ?: run {
- val component = NbtComponent.of(NbtCompound())
- set(DataComponentTypes.CUSTOM_DATA, component)
- component
- }
- return customData.nbt
- }
-
-val ItemStack.skyblockUUIDString: String?
- get() = extraAttributes.getString("uuid")?.takeIf { it.isNotBlank() }
-
-val ItemStack.skyblockUUID: UUID?
- get() = skyblockUUIDString?.let { UUID.fromString(it) }
-
-val ItemStack.petData: HypixelPetInfo?
- get() {
- val jsonString = extraAttributes.getString("petInfo")
- if (jsonString.isNullOrBlank()) return null
- return runCatching { jsonparser.decodeFromString<HypixelPetInfo>(jsonString) }
- .getOrElse { return null }
- }
-
-fun ItemStack.setSkyBlockFirmamentUiId(uiId: String) = setSkyBlockId(SkyblockId("FIRMAMENT_UI_$uiId"))
-fun ItemStack.setSkyBlockId(skyblockId: SkyblockId): ItemStack {
- this.extraAttributes["id"] = skyblockId.neuItem
- return this
-}
-
-val ItemStack.skyBlockId: SkyblockId?
- get() {
- return when (val id = extraAttributes.getString("id")) {
- "" -> {
- null
- }
-
- "PET" -> {
- petData?.skyblockId ?: SkyblockId.PET_NULL
- }
-
- "RUNE", "UNIQUE_RUNE" -> {
- val runeData = extraAttributes.getCompound("runes")
- val runeKind = runeData.keys.singleOrNull()
- if (runeKind == null) SkyblockId("RUNE")
- else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind)}")
- }
-
- "ABICASE" -> {
- SkyblockId("ABICASE_${extraAttributes.getString("model").uppercase()}")
- }
-
- "ENCHANTED_BOOK" -> {
- val enchantmentData = extraAttributes.getCompound("enchantments")
- val enchantName = enchantmentData.keys.singleOrNull()
- if (enchantName == null) SkyblockId("ENCHANTED_BOOK")
- else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName)}")
- }
-
- // TODO: PARTY_HAT_CRAB{,_ANIMATED,_SLOTH},POTION
- else -> {
- SkyblockId(id)
- }
- }
- }
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/SortedMapSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/SortedMapSerializer.kt
deleted file mode 100644
index baa10ad..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/SortedMapSerializer.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.util.SortedMap
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.builtins.MapSerializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-
-class SortedMapSerializer<K : Comparable<K>, V>(val keyDelegate: KSerializer<K>, val valueDelegate: KSerializer<V>) :
- KSerializer<SortedMap<K, V>> {
- val mapSerializer = MapSerializer(keyDelegate, valueDelegate)
- override val descriptor: SerialDescriptor
- get() = mapSerializer.descriptor
-
- override fun deserialize(decoder: Decoder): SortedMap<K, V> {
- return (mapSerializer.deserialize(decoder).toSortedMap(Comparator.naturalOrder()))
- }
-
- override fun serialize(encoder: Encoder, value: SortedMap<K, V>) {
- mapSerializer.serialize(encoder, value)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/TemplateUtil.kt b/src/main/kotlin/moe/nea/firmament/util/TemplateUtil.kt
deleted file mode 100644
index 11100e9..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/TemplateUtil.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.util.*
-import kotlinx.serialization.DeserializationStrategy
-import kotlinx.serialization.SerializationStrategy
-import kotlinx.serialization.serializer
-import moe.nea.firmament.Firmament
-
-object TemplateUtil {
-
- @JvmStatic
- fun getTemplatePrefix(data: String): String? {
- val decoded = maybeFromBase64Encoded(data) ?: return null
- return decoded.replaceAfter("/", "", "").ifBlank { null }
- }
-
- @JvmStatic
- fun intoBase64Encoded(raw: String): String {
- return Base64.getEncoder().encodeToString(raw.encodeToByteArray())
- }
-
- private val base64Alphabet = charArrayOf(
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
- 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '='
- )
-
- @JvmStatic
- fun maybeFromBase64Encoded(raw: String): String? {
- val raw = raw.trim()
- if (raw.any { it !in base64Alphabet }) {
- return null
- }
- return try {
- Base64.getDecoder().decode(raw).decodeToString()
- } catch (ex: Exception) {
- null
- }
- }
-
-
- /**
- * Returns a base64 encoded string, truncated such that for all `x`, `x.startsWith(prefix)` implies
- * `base64Encoded(x).startsWith(getPrefixComparisonSafeBase64Encoding(prefix))`
- * (however, the inverse may not always be true).
- */
- @JvmStatic
- fun getPrefixComparisonSafeBase64Encoding(prefix: String): String {
- val rawEncoded =
- Base64.getEncoder().encodeToString(prefix.encodeToByteArray())
- .replace("=", "")
- return rawEncoded.substring(0, rawEncoded.length - rawEncoded.length % 4)
- }
-
- inline fun <reified T> encodeTemplate(sharePrefix: String, data: T): String =
- encodeTemplate(sharePrefix, data, serializer())
-
- fun <T> encodeTemplate(sharePrefix: String, data: T, serializer: SerializationStrategy<T>): String {
- require(sharePrefix.endsWith("/"))
- return intoBase64Encoded(sharePrefix + Firmament.json.encodeToString(serializer, data))
- }
-
- inline fun <reified T : Any> maybeDecodeTemplate(sharePrefix: String, data: String): T? =
- maybeDecodeTemplate(sharePrefix, data, serializer())
-
- fun <T : Any> maybeDecodeTemplate(sharePrefix: String, data: String, serializer: DeserializationStrategy<T>): T? {
- require(sharePrefix.endsWith("/"))
- val data = data.trim()
- if (!data.startsWith(getPrefixComparisonSafeBase64Encoding(sharePrefix)))
- return null
- val decoded = maybeFromBase64Encoded(data) ?: return null
- if (!decoded.startsWith(sharePrefix))
- return null
- return try {
- Firmament.json.decodeFromString<T>(serializer, decoded.substring(sharePrefix.length))
- } catch (e: Exception) {
- null
- }
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/TimeMark.kt b/src/main/kotlin/moe/nea/firmament/util/TimeMark.kt
deleted file mode 100644
index 1264212..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/TimeMark.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.milliseconds
-
-class TimeMark private constructor(private val timeMark: Long) : Comparable<TimeMark> {
- fun passedTime() = if (timeMark == 0L) Duration.INFINITE else (System.currentTimeMillis() - timeMark).milliseconds
-
- operator fun minus(other: TimeMark): Duration {
- if (other.timeMark == timeMark)
- return 0.milliseconds
- if (other.timeMark == 0L)
- return Duration.INFINITE
- if (timeMark == 0L)
- return -Duration.INFINITE
- return (timeMark - other.timeMark).milliseconds
- }
-
- companion object {
- fun now() = TimeMark(System.currentTimeMillis())
- fun farPast() = TimeMark(0L)
- fun ago(timeDelta: Duration): TimeMark {
- if (timeDelta.isFinite()) {
- return TimeMark(System.currentTimeMillis() - timeDelta.inWholeMilliseconds)
- }
- require(timeDelta.isPositive())
- return farPast()
- }
- }
-
- override fun hashCode(): Int {
- return timeMark.hashCode()
- }
-
- override fun equals(other: Any?): Boolean {
- return other is TimeMark && other.timeMark == timeMark
- }
-
- override fun compareTo(other: TimeMark): Int {
- return this.timeMark.compareTo(other.timeMark)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/Timer.kt b/src/main/kotlin/moe/nea/firmament/util/Timer.kt
deleted file mode 100644
index 6e9b467..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/Timer.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import kotlin.time.Duration
-import kotlin.time.ExperimentalTime
-import kotlin.time.TimeSource
-
-@OptIn(ExperimentalTime::class)
-class Timer {
- private var mark: TimeSource.Monotonic.ValueTimeMark? = null
-
- fun timePassed(): Duration {
- return mark?.elapsedNow() ?: Duration.INFINITE
- }
-
- fun markNow() {
- mark = TimeSource.Monotonic.markNow()
- }
-
- fun markFarPast() {
- mark = null
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt b/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt
deleted file mode 100644
index 8fca6f3..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/WarpUtil.kt
+++ /dev/null
@@ -1,75 +0,0 @@
-
-package moe.nea.firmament.util
-
-import io.github.moulberry.repo.constants.Islands
-import io.github.moulberry.repo.constants.Islands.Warp
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import kotlin.math.sqrt
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.text.Text
-import net.minecraft.util.math.Position
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.repo.RepoManager
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-
-object WarpUtil {
- val warps: List<Islands.Warp> get() = RepoManager.neuRepo.constants.islands.warps
-
- @Serializable
- data class Data(
- val excludedWarps: MutableSet<String> = mutableSetOf(),
- )
-
- object DConfig : ProfileSpecificDataHolder<Data>(serializer(), "warp-util", ::Data)
-
- private var lastAttemptedWarp = ""
- private var lastWarpAttempt = TimeMark.farPast()
- fun findNearestWarp(island: SkyBlockIsland, pos: Position): Islands.Warp? {
- return warps.asSequence().filter { it.mode == island.locrawMode }.minByOrNull {
- if (DConfig.data?.excludedWarps?.contains(it.warp) == true) {
- return@minByOrNull Double.MAX_VALUE
- } else {
- return@minByOrNull squaredDist(pos, it)
- }
- }
- }
-
- private fun squaredDist(pos: Position, warp: Warp): Double {
- val dx = pos.x - warp.x
- val dy = pos.y - warp.y
- val dz = pos.z - warp.z
- return dx * dx + dy * dy + dz * dz
- }
-
- fun teleportToNearestWarp(island: SkyBlockIsland, pos: Position) {
- val nearestWarp = findNearestWarp(island, pos)
- if (nearestWarp == null) {
- MC.sendChat(Text.literal("Could not find an unlocked warp in ${island.userFriendlyName}"))
- return
- }
- if (island == SBData.skyblockLocation
- && sqrt(squaredDist(pos, nearestWarp)) > 1.1 * sqrt(squaredDist((MC.player ?: return).pos, nearestWarp))
- ) {
- return
- }
- MC.sendServerCommand("warp ${nearestWarp.warp}")
- }
-
- init {
- ProcessChatEvent.subscribe {
- if (it.unformattedString == "You haven't unlocked this fast travel destination!"
- && lastWarpAttempt.passedTime() < 2.seconds
- ) {
- DConfig.data?.excludedWarps?.add(lastAttemptedWarp)
- DConfig.markDirty()
- MC.sendChat(Text.stringifiedTranslatable("firmament.warp-util.mark-excluded", lastAttemptedWarp))
- lastWarpAttempt = TimeMark.farPast()
- }
- if (it.unformattedString == "You may now fast travel to") {
- DConfig.data?.excludedWarps?.clear()
- DConfig.markDirty()
- }
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/assertions.kt b/src/main/kotlin/moe/nea/firmament/util/assertions.kt
deleted file mode 100644
index 6f2ed19..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/assertions.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-/**
- * Less aggressive version of `require(obj != null)`, which fails in devenv but continues at runtime.
- */
-inline fun <T : Any> assertNotNullOr(obj: T?, message: String? = null, block: () -> T): T {
- if (message == null)
- assert(obj != null)
- else
- assert(obj != null) { message }
- return obj ?: block()
-}
-
-
-/**
- * Less aggressive version of `require(condition)`, which fails in devenv but continues at runtime.
- */
-inline fun assertTrueOr(condition: Boolean, block: () -> Unit) {
- assert(condition)
- if (!condition) block()
-}
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/async/input.kt b/src/main/kotlin/moe/nea/firmament/util/async/input.kt
deleted file mode 100644
index 9aab5cf..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/async/input.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-package moe.nea.firmament.util.async
-
-import kotlinx.coroutines.suspendCancellableCoroutine
-import kotlin.coroutines.resume
-import moe.nea.firmament.events.HandledScreenKeyPressedEvent
-import moe.nea.firmament.keybindings.IKeyBinding
-
-private object InputHandler {
- data class KeyInputContinuation(val keybind: IKeyBinding, val onContinue: () -> Unit)
-
- private val activeContinuations = mutableListOf<KeyInputContinuation>()
-
- fun registerContinuation(keyInputContinuation: KeyInputContinuation): () -> Unit {
- synchronized(InputHandler) {
- activeContinuations.add(keyInputContinuation)
- }
- return {
- synchronized(this) {
- activeContinuations.remove(keyInputContinuation)
- }
- }
- }
-
- init {
- HandledScreenKeyPressedEvent.subscribe { event ->
- synchronized(InputHandler) {
- val toRemove = activeContinuations.filter {
- event.matches(it.keybind)
- }
- toRemove.forEach { it.onContinue() }
- activeContinuations.removeAll(toRemove)
- }
- }
- }
-}
-
-suspend fun waitForInput(keybind: IKeyBinding): Unit = suspendCancellableCoroutine { cont ->
- val unregister =
- InputHandler.registerContinuation(InputHandler.KeyInputContinuation(keybind) { cont.resume(Unit) })
- cont.invokeOnCancellation {
- unregister()
- }
-}
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt b/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt
deleted file mode 100644
index d7a5dad..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/colorconversion.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.minecraft.text.TextColor
-import net.minecraft.util.DyeColor
-
-fun DyeColor.toShedaniel(): me.shedaniel.math.Color =
- me.shedaniel.math.Color.ofOpaque(this.signColor)
-
-fun DyeColor.toTextColor(): TextColor =
- TextColor.fromRgb(this.signColor)
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/customgui/CoordRememberingSlot.kt b/src/main/kotlin/moe/nea/firmament/util/customgui/CoordRememberingSlot.kt
deleted file mode 100644
index c61c711..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/customgui/CoordRememberingSlot.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package moe.nea.firmament.util.customgui
-
-import net.minecraft.screen.slot.Slot
-
-interface CoordRememberingSlot {
- fun rememberCoords_firmament()
- fun restoreCoords_firmament()
- fun getOriginalX_firmament(): Int
- fun getOriginalY_firmament(): Int
-}
-
-val Slot.originalX get() = (this as CoordRememberingSlot).getOriginalX_firmament()
-val Slot.originalY get() = (this as CoordRememberingSlot).getOriginalY_firmament()
diff --git a/src/main/kotlin/moe/nea/firmament/util/customgui/CustomGui.kt b/src/main/kotlin/moe/nea/firmament/util/customgui/CustomGui.kt
deleted file mode 100644
index f9094b2..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/customgui/CustomGui.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-
-package moe.nea.firmament.util.customgui
-
-import me.shedaniel.math.Rectangle
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.screen.slot.Slot
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.HandledScreenPushREIEvent
-
-abstract class CustomGui {
-
- abstract fun getBounds(): List<Rectangle>
-
- open fun moveSlot(slot: Slot) {
- // TODO: return a Pair maybe? worth an investigation
- }
-
- companion object {
- @Subscribe
- fun onExclusionZone(event: HandledScreenPushREIEvent) {
- val customGui = event.screen.customGui ?: return
- event.rectangles.addAll(customGui.getBounds())
- }
- }
-
- open fun render(
- drawContext: DrawContext,
- delta: Float,
- mouseX: Int,
- mouseY: Int
- ) {
- }
-
- open fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean {
- return false
- }
-
- open fun afterSlotRender(context: DrawContext, slot: Slot) {}
- open fun beforeSlotRender(context: DrawContext, slot: Slot) {}
- open fun mouseScrolled(mouseX: Double, mouseY: Double, horizontalAmount: Double, verticalAmount: Double): Boolean {
- return false
- }
-
- open fun isClickOutsideBounds(mouseX: Double, mouseY: Double): Boolean {
- return getBounds().none { it.contains(mouseX, mouseY) }
- }
-
- open fun isPointWithinBounds(
- x: Int,
- y: Int,
- width: Int,
- height: Int,
- pointX: Double,
- pointY: Double,
- ): Boolean {
- return getBounds().any { it.contains(pointX, pointY) } &&
- Rectangle(x, y, width, height).contains(pointX, pointY)
- }
-
- open fun isPointOverSlot(slot: Slot, xOffset: Int, yOffset: Int, pointX: Double, pointY: Double): Boolean {
- return isPointWithinBounds(slot.x + xOffset, slot.y + yOffset, 16, 16, pointX, pointY)
- }
-
- open fun onInit() {}
- open fun shouldDrawForeground(): Boolean {
- return true
- }
-
- open fun onVoluntaryExit(): Boolean {
- return true
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/customgui/HasCustomGui.kt b/src/main/kotlin/moe/nea/firmament/util/customgui/HasCustomGui.kt
deleted file mode 100644
index edead2e..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/customgui/HasCustomGui.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-
-package moe.nea.firmament.util.customgui
-
-import net.minecraft.client.gui.screen.ingame.HandledScreen
-
-@Suppress("FunctionName")
-interface HasCustomGui {
- fun getCustomGui_Firmament(): CustomGui?
- fun setCustomGui_Firmament(gui: CustomGui?)
-}
-
-var <T : HandledScreen<*>> T.customGui: CustomGui?
- get() = (this as HasCustomGui).getCustomGui_Firmament()
- set(value) {
- (this as HasCustomGui).setCustomGui_Firmament(value)
- }
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/data/DataHolder.kt b/src/main/kotlin/moe/nea/firmament/util/data/DataHolder.kt
deleted file mode 100644
index 21a6014..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/data/DataHolder.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-package moe.nea.firmament.util.data
-
-import java.nio.file.Path
-import kotlinx.serialization.KSerializer
-import kotlin.io.path.exists
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-import moe.nea.firmament.Firmament
-
-abstract class DataHolder<T>(
- val serializer: KSerializer<T>,
- val name: String,
- val default: () -> T
-) : IDataHolder<T> {
-
-
- final override var data: T
- private set
-
- init {
- data = readValueOrDefault()
- IDataHolder.putDataHolder(this::class, this)
- }
-
- private val file: Path get() = Firmament.CONFIG_DIR.resolve("$name.json")
-
- protected fun readValueOrDefault(): T {
- if (file.exists())
- try {
- return Firmament.json.decodeFromString(
- serializer,
- file.readText()
- )
- } catch (e: Exception) {/* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
- IDataHolder.badLoads.add(name)
- Firmament.logger.error(
- "Exception during loading of config file $name. This will reset this config.",
- e
- )
- }
- return default()
- }
-
- private fun writeValue(t: T) {
- file.writeText(Firmament.json.encodeToString(serializer, t))
- }
-
- override fun save() {
- writeValue(data)
- }
-
- override fun load() {
- data = readValueOrDefault()
- }
-
- override fun markDirty() {
- IDataHolder.markDirty(this::class)
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/data/IDataHolder.kt b/src/main/kotlin/moe/nea/firmament/util/data/IDataHolder.kt
deleted file mode 100644
index 5d09bcd..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/data/IDataHolder.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-package moe.nea.firmament.util.data
-
-import java.util.concurrent.CopyOnWriteArrayList
-import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
-import kotlin.reflect.KClass
-import net.minecraft.client.MinecraftClient
-import net.minecraft.server.command.CommandOutput
-import net.minecraft.text.Text
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.events.ScreenChangeEvent
-
-interface IDataHolder<T> {
- companion object {
- internal var badLoads: MutableList<String> = CopyOnWriteArrayList()
- private val allConfigs: MutableMap<KClass<out IDataHolder<*>>, IDataHolder<*>> = mutableMapOf()
- private val dirty: MutableSet<KClass<out IDataHolder<*>>> = mutableSetOf()
-
- internal fun <T : IDataHolder<K>, K> putDataHolder(kClass: KClass<T>, inst: IDataHolder<K>) {
- allConfigs[kClass] = inst
- }
-
- fun <T : IDataHolder<K>, K> markDirty(kClass: KClass<T>) {
- if (kClass !in allConfigs) {
- Firmament.logger.error("Tried to markDirty '${kClass.qualifiedName}', which isn't registered as 'IConfigHolder'")
- return
- }
- dirty.add(kClass)
- }
-
- private fun performSaves() {
- val toSave = dirty.toList().also {
- dirty.clear()
- }
- for (it in toSave) {
- val obj = allConfigs[it]
- if (obj == null) {
- Firmament.logger.error("Tried to save '${it}', which isn't registered as 'ConfigHolder'")
- continue
- }
- obj.save()
- }
- }
-
- private fun warnForResetConfigs(player: CommandOutput) {
- if (badLoads.isNotEmpty()) {
- player.sendMessage(
- Text.literal(
- "The following configs have been reset: ${badLoads.joinToString(", ")}. " +
- "This can be intentional, but probably isn't."
- )
- )
- badLoads.clear()
- }
- }
-
- fun registerEvents() {
- ScreenChangeEvent.subscribe { event ->
- performSaves()
- val p = MinecraftClient.getInstance().player
- if (p != null) {
- warnForResetConfigs(p)
- }
- }
- ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping {
- performSaves()
- })
- }
-
- }
-
- val data: T
- fun save()
- fun markDirty()
- fun load()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/data/ProfileSpecificDataHolder.kt b/src/main/kotlin/moe/nea/firmament/util/data/ProfileSpecificDataHolder.kt
deleted file mode 100644
index 1cd4f22..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/data/ProfileSpecificDataHolder.kt
+++ /dev/null
@@ -1,84 +0,0 @@
-
-
-package moe.nea.firmament.util.data
-
-import java.nio.file.Path
-import java.util.UUID
-import kotlinx.serialization.KSerializer
-import kotlin.io.path.createDirectories
-import kotlin.io.path.deleteExisting
-import kotlin.io.path.exists
-import kotlin.io.path.extension
-import kotlin.io.path.listDirectoryEntries
-import kotlin.io.path.nameWithoutExtension
-import kotlin.io.path.readText
-import kotlin.io.path.writeText
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.SBData
-
-abstract class ProfileSpecificDataHolder<S>(
- private val dataSerializer: KSerializer<S>,
- val configName: String,
- private val configDefault: () -> S
-) : IDataHolder<S?> {
-
- var allConfigs: MutableMap<UUID, S>
-
- override val data: S?
- get() = SBData.profileId?.let {
- allConfigs.computeIfAbsent(it) { configDefault() }
- }
-
- init {
- allConfigs = readValues()
- IDataHolder.putDataHolder(this::class, this)
- }
-
- private val configDirectory: Path get() = Firmament.CONFIG_DIR.resolve("profiles").resolve(configName)
-
- private fun readValues(): MutableMap<UUID, S> {
- if (!configDirectory.exists()) {
- configDirectory.createDirectories()
- }
- val profileFiles = configDirectory.listDirectoryEntries()
- return profileFiles
- .filter { it.extension == "json" }
- .mapNotNull {
- try {
- UUID.fromString(it.nameWithoutExtension) to Firmament.json.decodeFromString(dataSerializer, it.readText())
- } catch (e: Exception) { /* Expecting IOException and SerializationException, but Kotlin doesn't allow multi catches*/
- IDataHolder.badLoads.add(configName)
- Firmament.logger.error(
- "Exception during loading of profile specific config file $it ($configName). This will reset that profiles config.",
- e
- )
- null
- }
- }.toMap().toMutableMap()
- }
-
- override fun save() {
- if (!configDirectory.exists()) {
- configDirectory.createDirectories()
- }
- val c = allConfigs
- configDirectory.listDirectoryEntries().forEach {
- if (it.nameWithoutExtension !in c.mapKeys { it.toString() }) {
- it.deleteExisting()
- }
- }
- c.forEach { (name, value) ->
- val f = configDirectory.resolve("$name.json")
- f.writeText(Firmament.json.encodeToString(dataSerializer, value))
- }
- }
-
- override fun markDirty() {
- IDataHolder.markDirty(this::class)
- }
-
- override fun load() {
- allConfigs = readValues()
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/filter/IteratorFilterSet.kt b/src/main/kotlin/moe/nea/firmament/util/filter/IteratorFilterSet.kt
deleted file mode 100644
index 483b8d9..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/filter/IteratorFilterSet.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-
-package moe.nea.firmament.util.filter
-
-abstract class IteratorFilterSet<K>(val original: java.util.Set<K>) : java.util.Set<K> by original {
- abstract fun shouldKeepElement(element: K): Boolean
-
- override fun iterator(): MutableIterator<K> {
- val parentIterator = original.iterator()
- return object : MutableIterator<K> {
- var lastEntry: K? = null
- override fun hasNext(): Boolean {
- while (lastEntry == null) {
- if (!parentIterator.hasNext())
- break
- val element = parentIterator.next()
- if (!shouldKeepElement(element)) continue
- lastEntry = element
- }
- return lastEntry != null
- }
-
- override fun next(): K {
- if (!hasNext()) throw NoSuchElementException()
- return lastEntry ?: throw NoSuchElementException()
- }
-
- override fun remove() {
- TODO("Not yet implemented")
- }
- }
- }
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/item/NbtItemData.kt b/src/main/kotlin/moe/nea/firmament/util/item/NbtItemData.kt
deleted file mode 100644
index f7f259d..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/item/NbtItemData.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-package moe.nea.firmament.util.item
-
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.component.type.LoreComponent
-import net.minecraft.item.ItemStack
-import net.minecraft.text.Text
-
-var ItemStack.loreAccordingToNbt
- get() = get(DataComponentTypes.LORE)?.lines ?: listOf()
- set(value) {
- set(DataComponentTypes.LORE, LoreComponent(value))
- }
-
-var ItemStack.displayNameAccordingToNbt: Text
- get() = get(DataComponentTypes.CUSTOM_NAME) ?: get(DataComponentTypes.ITEM_NAME) ?: item.name
- set(value) {
- set(DataComponentTypes.CUSTOM_NAME, value)
- }
-
-fun ItemStack.setCustomName(text: Text) {
- set(DataComponentTypes.CUSTOM_NAME, text)
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt b/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
deleted file mode 100644
index ddab88e..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/item/SkullItemData.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-
-
-@file:UseSerializers(DashlessUUIDSerializer::class, InstantAsLongSerializer::class)
-
-package moe.nea.firmament.util.item
-
-import com.mojang.authlib.GameProfile
-import com.mojang.authlib.minecraft.MinecraftProfileTexture
-import com.mojang.authlib.properties.Property
-import java.util.UUID
-import kotlinx.datetime.Clock
-import kotlinx.datetime.Instant
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import kotlinx.serialization.encodeToString
-import net.minecraft.component.DataComponentTypes
-import net.minecraft.component.type.ProfileComponent
-import net.minecraft.item.ItemStack
-import net.minecraft.item.Items
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.util.Base64Util.padToValidBase64
-import moe.nea.firmament.util.assertTrueOr
-import moe.nea.firmament.util.json.DashlessUUIDSerializer
-import moe.nea.firmament.util.json.InstantAsLongSerializer
-
-@Serializable
-data class MinecraftProfileTextureKt(
- val url: String,
- val metadata: Map<String, String> = mapOf(),
-)
-
-@Serializable
-data class MinecraftTexturesPayloadKt(
- val textures: Map<MinecraftProfileTexture.Type, MinecraftProfileTextureKt> = mapOf(),
- val profileId: UUID? = null,
- val profileName: String? = null,
- val isPublic: Boolean = true,
- val timestamp: Instant = Clock.System.now(),
-)
-
-fun GameProfile.setTextures(textures: MinecraftTexturesPayloadKt) {
- val json = Firmament.json.encodeToString(textures)
- val encoded = java.util.Base64.getEncoder().encodeToString(json.encodeToByteArray())
- properties.put(propertyTextures, Property(propertyTextures, encoded))
-}
-
-private val propertyTextures = "textures"
-
-fun ItemStack.setEncodedSkullOwner(uuid: UUID, encodedData: String) {
- assert(this.item == Items.PLAYER_HEAD)
- val gameProfile = GameProfile(uuid, "LameGuy123")
- gameProfile.properties.put(propertyTextures, Property(propertyTextures, encodedData.padToValidBase64()))
- this.set(DataComponentTypes.PROFILE, ProfileComponent(gameProfile))
-}
-
-val zeroUUID = UUID.fromString("d3cb85e2-3075-48a1-b213-a9bfb62360c1")
-fun createSkullItem(uuid: UUID, url: String) = ItemStack(Items.PLAYER_HEAD)
- .also { it.setSkullOwner(uuid, url) }
-
-fun ItemStack.setSkullOwner(uuid: UUID, url: String) {
- assert(this.item == Items.PLAYER_HEAD)
- val gameProfile = GameProfile(uuid, "nea89")
- gameProfile.setTextures(
- MinecraftTexturesPayloadKt(
- textures = mapOf(MinecraftProfileTexture.Type.SKIN to MinecraftProfileTextureKt(url)),
- profileId = uuid,
- profileName = "nea89",
- )
- )
- this.set(DataComponentTypes.PROFILE, ProfileComponent(gameProfile))
-}
-
-
-fun decodeProfileTextureProperty(property: Property): MinecraftTexturesPayloadKt? {
- assertTrueOr(property.name == propertyTextures) { return null }
- return try {
- var encodedF: String = property.value
- while (encodedF.length % 4 != 0 && encodedF.last() == '=') {
- encodedF = encodedF.substring(0, encodedF.length - 1)
- }
- val json = java.util.Base64.getDecoder().decode(encodedF).decodeToString()
- Firmament.json.decodeFromString<MinecraftTexturesPayloadKt>(json)
- } catch (e: Exception) {
- // Malformed profile data
- if (Firmament.DEBUG)
- e.printStackTrace()
- null
- }
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/BlockPosSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/json/BlockPosSerializer.kt
deleted file mode 100644
index 144b0a0..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/json/BlockPosSerializer.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package moe.nea.firmament.util.json
-
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import kotlinx.serialization.serializer
-import net.minecraft.util.math.BlockPos
-
-object BlockPosSerializer : KSerializer<BlockPos> {
- val delegate = serializer<List<Int>>()
-
- override val descriptor: SerialDescriptor
- get() = SerialDescriptor("BlockPos", delegate.descriptor)
-
- override fun deserialize(decoder: Decoder): BlockPos {
- val list = decoder.decodeSerializableValue(delegate)
- require(list.size == 3)
- return BlockPos(list[0], list[1], list[2])
- }
-
- override fun serialize(encoder: Encoder, value: BlockPos) {
- encoder.encodeSerializableValue(delegate, listOf(value.x, value.y, value.z))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt
deleted file mode 100644
index acb1dc8..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/json/DashlessUUIDSerializer.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-package moe.nea.firmament.util.json
-
-import java.util.UUID
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import moe.nea.firmament.util.parseDashlessUUID
-
-object DashlessUUIDSerializer : KSerializer<UUID> {
- override val descriptor: SerialDescriptor =
- PrimitiveSerialDescriptor("DashlessUUIDSerializer", PrimitiveKind.STRING)
-
- override fun deserialize(decoder: Decoder): UUID {
- val str = decoder.decodeString()
- if ("-" in str) {
- return UUID.fromString(str)
- }
- return parseDashlessUUID(str)
- }
-
- override fun serialize(encoder: Encoder, value: UUID) {
- encoder.encodeString(value.toString().replace("-", ""))
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt b/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt
deleted file mode 100644
index ad738dc..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/json/InstantAsLongSerializer.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-package moe.nea.firmament.util.json
-
-import kotlinx.datetime.Instant
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.descriptors.PrimitiveKind
-import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-
-object InstantAsLongSerializer : KSerializer<Instant> {
- override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InstantAsLongSerializer", PrimitiveKind.LONG)
- override fun deserialize(decoder: Decoder): Instant {
- return Instant.fromEpochMilliseconds(decoder.decodeLong())
- }
-
- override fun serialize(encoder: Encoder, value: Instant) {
- encoder.encodeLong(value.toEpochMilliseconds())
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/json/SingletonSerializableList.kt b/src/main/kotlin/moe/nea/firmament/util/json/SingletonSerializableList.kt
deleted file mode 100644
index aa543d6..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/json/SingletonSerializableList.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-
-package moe.nea.firmament.util.json
-
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.builtins.ListSerializer
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import kotlinx.serialization.json.JsonArray
-import kotlinx.serialization.json.JsonDecoder
-import kotlinx.serialization.json.JsonElement
-
-class SingletonSerializableList<T>(val child: KSerializer<T>) : KSerializer<List<T>> {
- override val descriptor: SerialDescriptor
- get() = JsonElement.serializer().descriptor
-
- override fun deserialize(decoder: Decoder): List<T> {
- decoder as JsonDecoder
- val list = JsonElement.serializer().deserialize(decoder)
- if (list is JsonArray) {
- return list.map {
- decoder.json.decodeFromJsonElement(child, it)
- }
- }
- return listOf(decoder.json.decodeFromJsonElement(child, list))
- }
-
- override fun serialize(encoder: Encoder, value: List<T>) {
- ListSerializer(child).serialize(encoder, value)
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/listutil.kt b/src/main/kotlin/moe/nea/firmament/util/listutil.kt
deleted file mode 100644
index 73cb23e..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/listutil.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-package moe.nea.firmament.util
-
-fun <T, R> List<T>.lastNotNullOfOrNull(func: (T) -> R?): R? {
- for (i in indices.reversed()) {
- return func(this[i]) ?: continue
- }
- return null
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt b/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt
deleted file mode 100644
index 795a0d2..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/propertyutil.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import kotlin.properties.ReadOnlyProperty
-
-fun <T, V, M> ReadOnlyProperty<T, V>.map(mapper: (V) -> M): ReadOnlyProperty<T, M> {
- return ReadOnlyProperty { thisRef, property -> mapper(this@map.getValue(thisRef, property)) }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/regex.kt b/src/main/kotlin/moe/nea/firmament/util/regex.kt
deleted file mode 100644
index 3ce5bd8..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/regex.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.util.regex.Matcher
-import java.util.regex.Pattern
-import org.intellij.lang.annotations.Language
-import kotlin.time.Duration
-import kotlin.time.Duration.Companion.minutes
-import kotlin.time.Duration.Companion.seconds
-
-inline fun <T> String.ifMatches(regex: Regex, block: (MatchResult) -> T): T? =
- regex.matchEntire(this)?.let(block)
-
-inline fun <T> Pattern.useMatch(string: String, block: Matcher.() -> T): T? =
- matcher(string)
- .takeIf(Matcher::matches)
- ?.let(block)
-
-@Language("RegExp")
-val TIME_PATTERN = "[0-9]+[ms]"
-
-@Language("RegExp")
-val SHORT_NUMBER_FORMAT = "[0-9]+(?:,[0-9]+)*(?:\\.[0-9]+)?[kKmMbB]?"
-
-
-val siScalars = mapOf(
- 'k' to 1_000.0,
- 'K' to 1_000.0,
- 'm' to 1_000_000.0,
- 'M' to 1_000_000.0,
- 'b' to 1_000_000_000.0,
- 'B' to 1_000_000_000.0,
-)
-
-fun parseTimePattern(text: String): Duration {
- val length = text.dropLast(1).toInt()
- return when (text.last()) {
- 'm' -> length.minutes
- 's' -> length.seconds
- else -> error("Invalid pattern for time $text")
- }
-}
-
-fun parseShortNumber(string: String): Double {
- var k = string.replace(",", "")
- val scalar = k.last()
- var scalarMultiplier = siScalars[scalar]
- if (scalarMultiplier == null) {
- scalarMultiplier = 1.0
- } else {
- k = k.dropLast(1)
- }
- return k.toDouble() * scalarMultiplier
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt b/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt
deleted file mode 100644
index eb37e35..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/FacingThePlayerContext.kt
+++ /dev/null
@@ -1,101 +0,0 @@
-
-package moe.nea.firmament.util.render
-
-import com.mojang.blaze3d.systems.RenderSystem
-import io.github.notenoughupdates.moulconfig.platform.next
-import org.joml.Matrix4f
-import net.minecraft.client.font.TextRenderer
-import net.minecraft.client.render.BufferRenderer
-import net.minecraft.client.render.GameRenderer
-import net.minecraft.client.render.LightmapTextureManager
-import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.render.Tessellator
-import net.minecraft.client.render.VertexConsumer
-import net.minecraft.client.render.VertexFormat
-import net.minecraft.client.render.VertexFormats
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import net.minecraft.util.math.BlockPos
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.assertTrueOr
-
-@RenderContextDSL
-class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
- val matrixStack by worldContext::matrixStack
- fun waypoint(position: BlockPos, label: Text) {
- text(
- label,
- Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
- )
- }
-
- fun text(
- vararg texts: Text,
- verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER,
- background: Int = 0x70808080,
- ) {
- assertTrueOr(texts.isNotEmpty()) { return@text }
- for ((index, text) in texts.withIndex()) {
- worldContext.matrixStack.push()
- val width = MC.font.getWidth(text)
- worldContext.matrixStack.translate(-width / 2F, verticalAlign.align(index, texts.size), 0F)
- val vertexConsumer: VertexConsumer =
- worldContext.vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough())
- val matrix4f = worldContext.matrixStack.peek().positionMatrix
- vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(background)
- .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(background)
- .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f)
- .color(background)
- .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(background)
- .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
- worldContext.matrixStack.translate(0F, 0F, 0.01F)
-
- MC.font.draw(
- text,
- 0F,
- 0F,
- -1,
- false,
- worldContext.matrixStack.peek().positionMatrix,
- worldContext.vertexConsumers,
- TextRenderer.TextLayerType.SEE_THROUGH,
- 0,
- LightmapTextureManager.MAX_LIGHT_COORDINATE
- )
- worldContext.matrixStack.pop()
- }
- }
-
-
- fun texture(
- texture: Identifier, width: Int, height: Int,
- u1: Float, v1: Float,
- u2: Float, v2: Float,
- ) {
- RenderSystem.setShaderTexture(0, texture)
- RenderSystem.setShader(GameRenderer::getPositionTexColorProgram)
- val hw = width / 2F
- val hh = height / 2F
- val matrix4f: Matrix4f = worldContext.matrixStack.peek().positionMatrix
- val buf = Tessellator.getInstance()
- .begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR)
- buf.vertex(matrix4f, -hw, -hh, 0F)
- .color(-1)
- .texture(u1, v1).next()
- buf.vertex(matrix4f, -hw, +hh, 0F)
- .color(-1)
- .texture(u1, v2).next()
- buf.vertex(matrix4f, +hw, +hh, 0F)
- .color(-1)
- .texture(u2, v2).next()
- buf.vertex(matrix4f, +hw, -hh, 0F)
- .color(-1)
- .texture(u2, v1).next()
- BufferRenderer.drawWithGlobalProgram(buf.end())
- }
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/LerpUtils.kt b/src/main/kotlin/moe/nea/firmament/util/render/LerpUtils.kt
deleted file mode 100644
index f2c2f25..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/LerpUtils.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-
-package moe.nea.firmament.util.render
-
-import me.shedaniel.math.Color
-
-val pi = Math.PI
-val tau = Math.PI * 2
-fun lerpAngle(a: Float, b: Float, progress: Float): Float {
- // TODO: there is at least 10 mods to many in here lol
- val shortestAngle = ((((b.mod(tau) - a.mod(tau)).mod(tau)) + tau + pi).mod(tau)) - pi
- return ((a + (shortestAngle) * progress).mod(tau)).toFloat()
-}
-
-fun lerp(a: Float, b: Float, progress: Float): Float {
- return a + (b - a) * progress
-}
-fun lerp(a: Int, b: Int, progress: Float): Int {
- return (a + (b - a) * progress).toInt()
-}
-
-fun ilerp(a: Float, b: Float, value: Float): Float {
- return (value - a) / (b - a)
-}
-
-fun lerp(a: Color, b: Color, progress: Float): Color {
- return Color.ofRGBA(
- lerp(a.red, b.red, progress),
- lerp(a.green, b.green, progress),
- lerp(a.blue, b.blue, progress),
- lerp(a.alpha, b.alpha, progress),
- )
-}
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/RenderCircleProgress.kt b/src/main/kotlin/moe/nea/firmament/util/render/RenderCircleProgress.kt
deleted file mode 100644
index a2f42b5..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/RenderCircleProgress.kt
+++ /dev/null
@@ -1,95 +0,0 @@
-
-package moe.nea.firmament.util.render
-
-import com.mojang.blaze3d.systems.RenderSystem
-import io.github.notenoughupdates.moulconfig.platform.next
-import org.joml.Matrix4f
-import org.joml.Vector2f
-import kotlin.math.atan2
-import kotlin.math.tan
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.BufferRenderer
-import net.minecraft.client.render.GameRenderer
-import net.minecraft.client.render.Tessellator
-import net.minecraft.client.render.VertexFormat.DrawMode
-import net.minecraft.client.render.VertexFormats
-import net.minecraft.util.Identifier
-
-object RenderCircleProgress {
-
- fun renderCircle(
- drawContext: DrawContext,
- texture: Identifier,
- progress: Float,
- u1: Float,
- u2: Float,
- v1: Float,
- v2: Float,
- ) {
- RenderSystem.setShaderTexture(0, texture)
- RenderSystem.setShader(GameRenderer::getPositionTexColorProgram)
- RenderSystem.enableBlend()
- val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
- val bufferBuilder = Tessellator.getInstance().begin(DrawMode.TRIANGLES, VertexFormats.POSITION_TEXTURE_COLOR)
-
- val corners = listOf(
- Vector2f(0F, -1F),
- Vector2f(1F, -1F),
- Vector2f(1F, 0F),
- Vector2f(1F, 1F),
- Vector2f(0F, 1F),
- Vector2f(-1F, 1F),
- Vector2f(-1F, 0F),
- Vector2f(-1F, -1F),
- )
-
- for (i in (0 until 8)) {
- if (progress < i / 8F) {
- break
- }
- val second = corners[(i + 1) % 8]
- val first = corners[i]
- if (progress <= (i + 1) / 8F) {
- val internalProgress = 1 - (progress - i / 8F) * 8F
- val angle = lerpAngle(
- atan2(second.y, second.x),
- atan2(first.y, first.x),
- internalProgress
- )
- if (angle < tau / 8 || angle >= tau * 7 / 8) {
- second.set(1F, tan(angle))
- } else if (angle < tau * 3 / 8) {
- second.set(1 / tan(angle), 1F)
- } else if (angle < tau * 5 / 8) {
- second.set(-1F, -tan(angle))
- } else {
- second.set(-1 / tan(angle), -1F)
- }
- }
-
- fun ilerp(f: Float): Float =
- ilerp(-1f, 1f, f)
-
- bufferBuilder
- .vertex(matrix, second.x, second.y, 0F)
- .texture(lerp(u1, u2, ilerp(second.x)), lerp(v1, v2, ilerp(second.y)))
- .color(-1)
- .next()
- bufferBuilder
- .vertex(matrix, first.x, first.y, 0F)
- .texture(lerp(u1, u2, ilerp(first.x)), lerp(v1, v2, ilerp(first.y)))
- .color(-1)
- .next()
- bufferBuilder
- .vertex(matrix, 0F, 0F, 0F)
- .texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
- .color(-1)
- .next()
- }
- BufferRenderer.drawWithGlobalProgram(bufferBuilder.end())
- RenderSystem.disableBlend()
- }
-
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/RenderContextDSL.kt b/src/main/kotlin/moe/nea/firmament/util/render/RenderContextDSL.kt
deleted file mode 100644
index 9bb4431..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/RenderContextDSL.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-package moe.nea.firmament.util.render
-
-@DslMarker
-annotation class RenderContextDSL {
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt b/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt
deleted file mode 100644
index 7faa499..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt
+++ /dev/null
@@ -1,294 +0,0 @@
-
-
-package moe.nea.firmament.util.render
-
-import com.mojang.blaze3d.systems.RenderSystem
-import io.github.notenoughupdates.moulconfig.platform.next
-import java.lang.Math.pow
-import org.joml.Matrix4f
-import org.joml.Vector3f
-import net.minecraft.client.gl.VertexBuffer
-import net.minecraft.client.render.BufferBuilder
-import net.minecraft.client.render.BufferRenderer
-import net.minecraft.client.render.Camera
-import net.minecraft.client.render.GameRenderer
-import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.render.RenderPhase
-import net.minecraft.client.render.RenderTickCounter
-import net.minecraft.client.render.Tessellator
-import net.minecraft.client.render.VertexConsumerProvider
-import net.minecraft.client.render.VertexFormat
-import net.minecraft.client.render.VertexFormats
-import net.minecraft.client.texture.Sprite
-import net.minecraft.client.util.math.MatrixStack
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.math.Vec3d
-import moe.nea.firmament.events.WorldRenderLastEvent
-import moe.nea.firmament.util.FirmFormatters
-import moe.nea.firmament.util.MC
-
-@RenderContextDSL
-class RenderInWorldContext private constructor(
- private val tesselator: Tessellator,
- val matrixStack: MatrixStack,
- private val camera: Camera,
- private val tickCounter: RenderTickCounter,
- val vertexConsumers: VertexConsumerProvider.Immediate,
-) {
-
- object RenderLayers {
- val TRANSLUCENT_TRIS = RenderLayer.of("firmament_translucent_tris",
- VertexFormats.POSITION_COLOR,
- VertexFormat.DrawMode.TRIANGLES,
- RenderLayer.DEFAULT_BUFFER_SIZE,
- false, true,
- RenderLayer.MultiPhaseParameters.builder()
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
- .program(RenderPhase.COLOR_PROGRAM)
- .build(false))
- }
-
- fun color(color: me.shedaniel.math.Color) {
- color(color.red / 255F, color.green / 255f, color.blue / 255f, color.alpha / 255f)
- }
-
- fun color(red: Float, green: Float, blue: Float, alpha: Float) {
- RenderSystem.setShaderColor(red, green, blue, alpha)
- }
-
- fun block(blockPos: BlockPos) {
- matrixStack.push()
- matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat())
- buildCube(matrixStack.peek().positionMatrix, tesselator)
- matrixStack.pop()
- }
-
- enum class VerticalAlign {
- TOP, BOTTOM, CENTER;
-
- fun align(index: Int, count: Int): Float {
- return when (this) {
- CENTER -> (index - count / 2F) * (1 + MC.font.fontHeight.toFloat())
- BOTTOM -> (index - count) * (1 + MC.font.fontHeight.toFloat())
- TOP -> (index) * (1 + MC.font.fontHeight.toFloat())
- }
- }
- }
-
- fun waypoint(position: BlockPos, vararg label: Text) {
- text(
- position.toCenterPos(),
- *label,
- Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}"),
- background = 0xAA202020.toInt()
- )
- }
-
- fun withFacingThePlayer(position: Vec3d, block: FacingThePlayerContext.() -> Unit) {
- matrixStack.push()
- matrixStack.translate(position.x, position.y, position.z)
- val actualCameraDistance = position.distanceTo(camera.pos)
- val distanceToMoveTowardsCamera = if (actualCameraDistance < 10) 0.0 else -(actualCameraDistance - 10.0)
- val vec = position.subtract(camera.pos).multiply(distanceToMoveTowardsCamera / actualCameraDistance)
- matrixStack.translate(vec.x, vec.y, vec.z)
- matrixStack.multiply(camera.rotation)
- matrixStack.scale(0.025F, -0.025F, 1F)
-
- FacingThePlayerContext(this).run(block)
-
- matrixStack.pop()
- vertexConsumers.drawCurrentLayer()
- }
-
- fun sprite(position: Vec3d, sprite: Sprite, width: Int, height: Int) {
- texture(
- position, sprite.atlasId, width, height, sprite.minU, sprite.minV, sprite.maxU, sprite.maxV
- )
- }
-
- fun texture(
- position: Vec3d, texture: Identifier, width: Int, height: Int,
- u1: Float, v1: Float,
- u2: Float, v2: Float,
- ) {
- withFacingThePlayer(position) {
- texture(texture, width, height, u1, v1, u2, v2)
- }
- }
-
- fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER, background: Int = 0x70808080) {
- withFacingThePlayer(position) {
- text(*texts, verticalAlign = verticalAlign, background = background)
- }
- }
-
- fun tinyBlock(vec3d: Vec3d, size: Float) {
- RenderSystem.setShader(GameRenderer::getPositionColorProgram)
- matrixStack.push()
- matrixStack.translate(vec3d.x, vec3d.y, vec3d.z)
- matrixStack.scale(size, size, size)
- matrixStack.translate(-.5, -.5, -.5)
- buildCube(matrixStack.peek().positionMatrix, tesselator)
- matrixStack.pop()
- }
-
- fun wireframeCube(blockPos: BlockPos, lineWidth: Float = 10F) {
- RenderSystem.setShader(GameRenderer::getRenderTypeLinesProgram)
- matrixStack.push()
- RenderSystem.lineWidth(lineWidth / pow(camera.pos.squaredDistanceTo(blockPos.toCenterPos()), 0.25).toFloat())
- matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat())
- buildWireFrameCube(matrixStack.peek(), tesselator)
- matrixStack.pop()
- }
-
- fun line(vararg points: Vec3d, lineWidth: Float = 10F) {
- line(points.toList(), lineWidth)
- }
-
- fun tracer(toWhere: Vec3d, lineWidth: Float = 3f) {
- val cameraForward = Vector3f(0f, 0f, 1f).rotate(camera.rotation)
- line(camera.pos.add(Vec3d(cameraForward)), toWhere, lineWidth = lineWidth)
- }
-
- fun line(points: List<Vec3d>, lineWidth: Float = 10F) {
- RenderSystem.setShader(GameRenderer::getRenderTypeLinesProgram)
- RenderSystem.lineWidth(lineWidth)
- val buffer = tesselator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES)
-
- val matrix = matrixStack.peek()
- var lastNormal: Vector3f? = null
- points.zipWithNext().forEach { (a, b) ->
- val normal = Vector3f(b.x.toFloat(), b.y.toFloat(), b.z.toFloat())
- .sub(a.x.toFloat(), a.y.toFloat(), a.z.toFloat())
- .normalize()
- val lastNormal0 = lastNormal ?: normal
- lastNormal = normal
- buffer.vertex(matrix.positionMatrix, a.x.toFloat(), a.y.toFloat(), a.z.toFloat())
- .color(-1)
- .normal(matrix, lastNormal0.x, lastNormal0.y, lastNormal0.z)
- .next()
- buffer.vertex(matrix.positionMatrix, b.x.toFloat(), b.y.toFloat(), b.z.toFloat())
- .color(-1)
- .normal(matrix, normal.x, normal.y, normal.z)
- .next()
- }
-
- BufferRenderer.drawWithGlobalProgram(buffer.end())
- }
-
- companion object {
- private fun doLine(
- matrix: MatrixStack.Entry,
- buf: BufferBuilder,
- i: Float,
- j: Float,
- k: Float,
- x: Float,
- y: Float,
- z: Float
- ) {
- val normal = Vector3f(x, y, z)
- .sub(i, j, k)
- .normalize()
- buf.vertex(matrix.positionMatrix, i, j, k)
- .normal(matrix, normal.x, normal.y, normal.z)
- .color(-1)
- .next()
- buf.vertex(matrix.positionMatrix, x, y, z)
- .normal(matrix, normal.x, normal.y, normal.z)
- .color(-1)
- .next()
- }
-
-
- private fun buildWireFrameCube(matrix: MatrixStack.Entry, tessellator: Tessellator) {
- val buf = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES)
-
- for (i in 0..1) {
- for (j in 0..1) {
- val i = i.toFloat()
- val j = j.toFloat()
- doLine(matrix, buf, 0F, i, j, 1F, i, j)
- doLine(matrix, buf, i, 0F, j, i, 1F, j)
- doLine(matrix, buf, i, j, 0F, i, j, 1F)
- }
- }
- BufferRenderer.drawWithGlobalProgram(buf.end())
- }
-
- private fun buildCube(matrix: Matrix4f, tessellator: Tessellator) {
- val buf = tessellator.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR)
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next()
- buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next()
- RenderLayers.TRANSLUCENT_TRIS.draw(buf.end())
- }
-
-
- fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) {
- RenderSystem.disableDepthTest()
- RenderSystem.enableBlend()
- RenderSystem.defaultBlendFunc()
- RenderSystem.disableCull()
-
- event.matrices.push()
- event.matrices.translate(-event.camera.pos.x, -event.camera.pos.y, -event.camera.pos.z)
-
- val ctx = RenderInWorldContext(
- RenderSystem.renderThreadTesselator(),
- event.matrices,
- event.camera,
- event.tickCounter,
- event.vertexConsumers
- )
-
- block(ctx)
-
- event.matrices.pop()
-
- RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
- VertexBuffer.unbind()
- RenderSystem.enableDepthTest()
- RenderSystem.enableCull()
- RenderSystem.disableBlend()
- }
- }
-}
-
-
diff --git a/src/main/kotlin/moe/nea/firmament/util/render/TranslatedScissors.kt b/src/main/kotlin/moe/nea/firmament/util/render/TranslatedScissors.kt
deleted file mode 100644
index c1e6544..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/render/TranslatedScissors.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-
-package moe.nea.firmament.util.render
-
-import org.joml.Vector4f
-import net.minecraft.client.gui.DrawContext
-
-fun DrawContext.enableScissorWithTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
- val pMat = matrices.peek().positionMatrix
- val target = Vector4f()
-
- target.set(x1, y1, 0f, 1f)
- target.mul(pMat)
- val scissorX1 = target.x
- val scissorY1 = target.y
-
- target.set(x2, y2, 0f, 1f)
- target.mul(pMat)
- val scissorX2 = target.x
- val scissorY2 = target.y
-
- enableScissor(scissorX1.toInt(), scissorY1.toInt(), scissorX2.toInt(), scissorY2.toInt())
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/stringutil.kt b/src/main/kotlin/moe/nea/firmament/util/stringutil.kt
deleted file mode 100644
index 56f8dbe..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/stringutil.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-
-package moe.nea.firmament.util
-
-fun parseIntWithComma(string: String): Int {
- return string.replace(",", "").toInt()
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/textutil.kt b/src/main/kotlin/moe/nea/firmament/util/textutil.kt
deleted file mode 100644
index a05733c..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/textutil.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import net.minecraft.text.MutableText
-import net.minecraft.text.PlainTextContent
-import net.minecraft.text.Style
-import net.minecraft.text.Text
-import net.minecraft.text.TranslatableTextContent
-import net.minecraft.util.Formatting
-import moe.nea.firmament.Firmament
-
-
-class TextMatcher(text: Text) {
- data class State(
- var iterator: MutableList<Text>,
- var currentText: Text?,
- var offset: Int,
- var textContent: String,
- )
-
- var state = State(
- mutableListOf(text),
- null,
- 0,
- ""
- )
-
- fun pollChunk(): Boolean {
- val firstOrNull = state.iterator.removeFirstOrNull() ?: return false
- state.offset = 0
- state.currentText = firstOrNull
- state.textContent = when (val content = firstOrNull.content) {
- is PlainTextContent.Literal -> content.string
- else -> {
- Firmament.logger.warn("TextContent of type ${content.javaClass} not understood.")
- return false
- }
- }
- state.iterator.addAll(0, firstOrNull.siblings)
- return true
- }
-
- fun pollChunks(): Boolean {
- while (state.offset !in state.textContent.indices) {
- if (!pollChunk()) {
- return false
- }
- }
- return true
- }
-
- fun pollChar(): Char? {
- if (!pollChunks()) return null
- return state.textContent[state.offset++]
- }
-
-
- fun expectString(string: String): Boolean {
- var found = ""
- while (found.length < string.length) {
- if (!pollChunks()) return false
- val takeable = state.textContent.drop(state.offset).take(string.length - found.length)
- state.offset += takeable.length
- found += takeable
- }
- return found == string
- }
-}
-
-val formattingChars = "kmolnrKMOLNR".toSet()
-fun CharSequence.removeColorCodes(keepNonColorCodes: Boolean = false): String {
- var nextParagraph = indexOf('§')
- if (nextParagraph < 0) return this.toString()
- val stringBuffer = StringBuilder(this.length)
- var readIndex = 0
- while (nextParagraph >= 0) {
- stringBuffer.append(this, readIndex, nextParagraph)
- if (keepNonColorCodes && nextParagraph + 1 < length && this[nextParagraph + 1] in formattingChars) {
- readIndex = nextParagraph
- nextParagraph = indexOf('§', startIndex = readIndex + 1)
- } else {
- readIndex = nextParagraph + 2
- nextParagraph = indexOf('§', startIndex = readIndex)
- }
- if (readIndex > this.length)
- readIndex = this.length
- }
- stringBuffer.append(this, readIndex, this.length)
- return stringBuffer.toString()
-}
-
-val Text.unformattedString: String
- get() = string.removeColorCodes()
-
-
-fun MutableText.withColor(formatting: Formatting) = this.styled { it.withColor(formatting).withItalic(false) }
-
-fun Text.transformEachRecursively(function: (Text) -> Text): Text {
- val c = this.content
- if (c is TranslatableTextContent) {
- return Text.translatableWithFallback(c.key, c.fallback, *c.args.map {
- (if (it is Text) it else Text.literal(it.toString())).transformEachRecursively(function)
- }.toTypedArray()).also { new ->
- new.style = this.style
- new.siblings.clear()
- this.siblings.forEach { child ->
- new.siblings.add(child.transformEachRecursively(function))
- }
- }
- }
- return function(this.copy().also { it.siblings.clear() }).also { tt ->
- this.siblings.forEach {
- tt.siblings.add(it.transformEachRecursively(function))
- }
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/util/uuid.kt b/src/main/kotlin/moe/nea/firmament/util/uuid.kt
deleted file mode 100644
index 4aa0749..0000000
--- a/src/main/kotlin/moe/nea/firmament/util/uuid.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-package moe.nea.firmament.util
-
-import java.math.BigInteger
-import java.util.UUID
-
-fun parseDashlessUUID(dashlessUuid: String): UUID {
- val most = BigInteger(dashlessUuid.substring(0, 16), 16)
- val least = BigInteger(dashlessUuid.substring(16, 32), 16)
- return UUID(most.toLong(), least.toLong())
-}