From 934e511f25f661a31d9bd6d7bbc0a505839fe1da Mon Sep 17 00:00:00 2001 From: mcwuguodadi Date: Sun, 23 Nov 2025 02:03:41 +0800 Subject: [PATCH] upload something --- .editorconfig | 20 + .pre-commit-config.yaml | 16 + CONTRIBUTING.md | 52 + LICENSES/Apache-2.0.txt | 73 + LICENSES/CC-BY-4.0.txt | 156 + LICENSES/CC0-1.0.txt | 121 + LICENSES/GPL-3.0-or-later.txt | 232 + LICENSES/MIT.txt | 9 + REUSE.toml | 53 + build-logic/build.gradle.kts | 22 + build-logic/gradle/wrapper | 1 + build-logic/gradlew | 251 + build-logic/gradlew.bat | 94 + build-logic/settings.gradle.kts | 8 + build-logic/src/main/kotlin/EnvFile.kt | 13 + .../src/main/kotlin/FabricModTransform.kt | 80 + .../src/main/kotlin/InnerJarsUnpacker.kt | 70 + build-logic/src/main/kotlin/RepoDownload.kt | 41 + .../src/main/kotlin/firmament.base.gradle.kts | 1 + .../main/kotlin/firmament.common.gradle.kts | 2 + .../firmament.license-management.gradle.kts | 5 + .../kotlin/firmament.repositories.gradle.kts | 46 + build-logic/src/main/kotlin/licenseinfo.kt | 144 + build-logic/src/main/kotlin/lookupversion.kt | 25 + build.gradle.kts | 521 ++ check-translation-ordering.sh | 7 + docs/How to release.md | 19 + docs/firmament_logo.webp | Bin 0 -> 474 bytes docs/firmament_logo.webp.license | 3 + docs/firmament_logo_256.webp | Bin 0 -> 740 bytes docs/firmament_logo_256.webp.license | 3 + docs/firmament_logo_256_nobg.webp | Bin 0 -> 9840 bytes docs/firmament_logo_256_nobg.webp.license | 3 + docs/firmament_logo_256_trans.webp | Bin 0 -> 9972 bytes docs/firmament_logo_256_trans.webp.license | 3 + docs/firmament_logo_nobg.webp | Bin 0 -> 9632 bytes docs/firmament_logo_nobg.webp.license | 3 + docs/firmament_logo_trans.webp | Bin 0 -> 9706 bytes docs/firmament_logo_trans.webp.license | 3 + docs/release_script.sh | 225 + gradle.properties | 15 + gradle/libs.versions.toml | 168 + gradle/wrapper/gradle-wrapper.jar.license | 3 + gradle/wrapper/gradle-wrapper.properties | 9 + gradlew | 223 + gradlew.bat | 93 + javaplugin/build.gradle.kts | 17 + .../firmament/javaplugin/InitReplacer.java | 81 + .../IntermediaryMethodReplacer.java | 77 + .../IntermediaryNameResolutionPlugin.java | 25 + .../IntermediaryNameResolutionTask.java | 44 + .../nea/firmament/javaplugin/MappingTree.java | 51 + .../moe/nea/firmament/javaplugin/Utils.java | 121 + .../services/com.sun.source.util.Plugin | 1 + settings.gradle.kts | 42 + shell.nix | 42 + .../java/ConditionDirectAccessHelper.kt | 59 + .../citresewn/MixinConditionComponents.java | 123 + src/compat/configured/java/BaseConfigNode.kt | 40 + src/compat/configured/java/ConfigCategory.kt | 48 + src/compat/configured/java/ConfigNode.kt | 39 + src/compat/configured/java/ConfigValue.kt | 72 + src/compat/configured/java/ConfigValueNode.kt | 37 + .../configured/java/ConfiguredCompat.kt | 30 + .../java/ConfiguredConfigScreenProvider.kt | 22 + .../java/ExplosiveEnhancementSpawner.kt | 17 + .../moe/nea/firmament/compat/jade/Compat.kt | 12 + .../compat/jade/CustomFakeBlockProvider.kt | 41 + .../jade/CustomMiningHardnessProvider.kt | 97 + .../compat/jade/DrillToolProvider.kt | 77 + .../compat/jade/FirmamentJadePlugin.kt | 21 + .../firmament/compat/jade/JadeIntegration.kt | 50 + .../moe/nea/firmament/compat/jade/utils.kt | 6 + .../mixins/compat/jade/ElementAccessor.java | 12 + ...yForCustomBlocksInHarvestToolProvider.java | 33 + .../compat/jade/OnUpdateBreakProgress.java | 22 + .../jade/PatchBreakingBarSpeedJade.java | 25 + .../compat/modmenu/FirmamentModMenuPlugin.kt | 11 + .../java/MCConfigEditorIntegration.kt | 438 ++ .../moulconfig/java/ProcessedCategoryFirm.kt | 47 + .../java/ProcessedEditableOptionFirm.kt | 44 + .../moulconfig/java/ProcessedOptionFirm.kt | 42 + .../moe/nea/firmament/compat/rei/Compat.kt | 12 + .../nea/firmament/compat/rei/EntityWidget.kt | 54 + .../compat/rei/FirmamentReiCommonPlugin.kt | 12 + .../compat/rei/FirmamentReiPlugin.kt | 172 + .../compat/rei/HoveredItemStackProvider.kt | 38 + .../compat/rei/NEUItemEntryRenderer.kt | 123 + .../compat/rei/NEUItemEntrySerializer.kt | 17 + .../firmament/compat/rei/REIRecipeLayouter.kt | 62 + .../compat/rei/SBItemEntryDefinition.kt | 97 + .../SkyblockCraftingRecipeDynamicGenerator.kt | 56 + .../rei/SkyblockItemIdFocusedStackProvider.kt | 23 + .../java/moe/nea/firmament/compat/rei/math.kt | 8 + .../rei/recipes/GenericREIRecipeCategory.kt | 67 + .../compat/rei/recipes/SBKatRecipe.kt | 222 + .../compat/rei/recipes/SBMobDropRecipe.kt | 105 + .../firmament/compat/rei/recipes/SBRecipe.kt | 42 + .../compat/rei/recipes/SBReforgeRecipe.kt | 217 + .../compat/rei/recipes/SBShopRecipe.kt | 61 + .../mixins/compat/HideREIRecipeWarning.java | 20 + src/compat/sodium/java/SodiumChunkReloader.kt | 12 + .../sodium/AccessorSodiumWorldRenderer.java | 14 + ...PatchBlockModelInSodiumChunkGenerator.java | 29 + .../moe/nea/firmament/compat/gender/Compat.kt | 13 + .../PatchArmorTexturesInGenderMod.java | 23 + src/compat/yacl/java/KeybindingBuilder.kt | 16 + src/compat/yacl/java/KeybindingController.kt | 83 + src/compat/yacl/java/YaclIntegration.kt | 227 + .../firmament/init/AutoDiscoveryPlugin.java | 187 + .../nea/firmament/init/ClientPlayerRiser.java | 75 + .../moe/nea/firmament/init/EarlyRiser.java | 12 + .../firmament/init/HandledScreenRiser.java | 151 + .../moe/nea/firmament/init/Intermediary.java | 63 + .../nea/firmament/init/IntermediaryName.java | 21 + .../moe/nea/firmament/init/MixinPlugin.java | 76 + .../moe/nea/firmament/init/RiserUtils.java | 27 + .../firmament/init/SectionBuilderRiser.java | 118 + ...ysDisplayFirmamentClientCommandErrors.java | 18 + .../mixins/AppendRepoAsResourcePack.java | 34 + .../mixins/BandAidResourcePackPatch.java | 25 + .../CaseInsensitiveCommandMapPatch.java | 25 + .../firmament/mixins/ChatPeekingPatch.java | 25 + .../nea/firmament/mixins/CopyChatPatch.java | 44 + .../mixins/CustomDurabilityBarPatch.java | 53 + .../firmament/mixins/DFUEntityIdFixPatch.java | 35 + .../nea/firmament/mixins/DisableHurtCam.java | 18 + .../mixins/DispatchMouseInputEventsPatch.java | 17 + .../mixins/EarlyResourceReloadPatch.java | 25 + .../firmament/mixins/EntityDespawnPatch.java | 20 + .../mixins/EntityInteractEventPatch.java | 34 + .../mixins/EntityUpdateEventListener.java | 48 + .../FirmKeybindsInVanillaControlsPatch.java | 58 + .../mixins/HideStatusEffectsPatch.java | 29 + .../mixins/HudRenderEventsPatch.java | 36 + .../mixins/IncomingPacketListenerPatches.java | 41 + .../mixins/KeyPressInWorldEventPatch.java | 20 + .../mixins/MainWindowFirstLoadPatch.java | 31 + .../mixins/MinecraftInitLevelListener.java | 26 + .../firmament/mixins/MixinHandledScreen.java | 102 + .../mixins/MixinPlayerScreenHandler.java | 31 + .../mixins/MixinRecipeBookScreen.java | 16 + .../mixins/OutgoingPacketEventPatch.java | 21 + .../mixins/PlayerDropEventPatch.java | 28 + ...ropertySignatureIgnorePatchForSession.java | 24 + .../mixins/RedirectWithoutSubCommands.java | 42 + .../ResourceReloaderRegistrationPatch.java | 26 + .../mixins/SaveCursorPositionPatch.java | 40 + .../mixins/SaveOriginalCommandTreePacket.java | 17 + .../mixins/ScreenChangeEventPatch.java | 32 + .../firmament/mixins/SlotClickEventPatch.java | 41 + .../firmament/mixins/SlotUpdateListener.java | 54 + .../mixins/SoundReceiveEventPatch.java | 32 + .../mixins/TextureUnpackBase64PadPatch.java | 19 + .../firmament/mixins/ToggleSprintPatch.java | 18 + ...lerateFirmamentTolerateRegistryOwners.java | 18 + .../mixins/WorldReadyEventPatch.java | 19 + .../mixins/WorldRenderLastEventPatch.java | 45 + .../mixins/YggdrasilSignatureIgnorePatch.java | 21 + .../AccessorAbstractClientPlayerEntity.java | 13 + .../mixins/accessor/AccessorChatHud.java | 24 + .../accessor/AccessorHandledScreen.java | 39 + .../accessor/AccessorPlayerListHud.java | 31 + .../accessor/AccessorWorldRenderer.java | 17 + .../mixins/customgui/OriginalSlotCoords.java | 43 + .../mixins/customgui/PatchHandledScreen.java | 212 + .../devenv/DisableCommonPacketWarnings.java | 42 + .../devenv/DisableInvalidFishingHook.java | 17 + .../devenv/EarlyInstantiateTranslations.java | 19 + .../mixins/devenv/IdentifyCloser.java | 16 + .../mixins/devenv/IdentifyStopperPatch.java | 16 + .../mixins/devenv/MixinKeyboard.java | 20 + .../mixins/devenv/MixinScoreboard.java | 17 + .../WarnForUnknownCustomPayloadSends.java | 18 + .../devenv/WarnOnMissingTranslations.java | 38 + .../mixins/feature/DisableSlotHighlights.java | 25 + .../CustomCapeFeatureRenderer.java | 43 + .../devcosmetics/CustomCapeStorage.java | 23 + .../SaveCapeToPlayerEntityRenderState.java | 19 + .../ChangeColorOfLivingEntities.java | 62 + .../entitytints/EntityRenderStateTint.java | 55 + .../entitytints/InjectIntoRenderState.java | 30 + .../entitytints/ReplaceOverlayTexture.java | 24 + .../UseOverlayableEquipmentRenderer.java | 34 + .../UseOverlayableHeadFeatureRenderer.java | 25 + .../UseOverlayableItemRenderer.java | 25 + ...seOverlayableSkullBlockEntityRenderer.java | 25 + src/main/kotlin/Compat.kt | 11 + src/main/kotlin/Firmament.kt | 182 + src/main/kotlin/apis/Profiles.kt | 194 + src/main/kotlin/apis/Routes.kt | 95 + src/main/kotlin/apis/UrsaManager.kt | 72 + .../CaseInsensitiveLiteralCommandNode.kt | 75 + src/main/kotlin/commands/Duration.kt | 75 + src/main/kotlin/commands/RestArgumentType.kt | 15 + src/main/kotlin/commands/dsl.kt | 118 + src/main/kotlin/commands/rome.kt | 376 ++ src/main/kotlin/events/AllowChatEvent.kt | 16 + src/main/kotlin/events/AttackBlockEvent.kt | 18 + .../events/ChestInventoryUpdateEvent.kt | 11 + src/main/kotlin/events/ClientInitEvent.kt | 5 + src/main/kotlin/events/ClientStartedEvent.kt | 6 + src/main/kotlin/events/CommandEvent.kt | 45 + .../kotlin/events/CustomItemModelEvent.kt | 75 + .../kotlin/events/DebugInstantiateEvent.kt | 9 + .../kotlin/events/EarlyResourceReloadEvent.kt | 10 + src/main/kotlin/events/EntityDespawnEvent.kt | 11 + .../kotlin/events/EntityInteractionEvent.kt | 29 + .../kotlin/events/EntityRenderTintEvent.kt | 66 + src/main/kotlin/events/EntityUpdateEvent.kt | 60 + .../kotlin/events/FeaturesInitializedEvent.kt | 8 + .../events/FinalizeResourceManagerEvent.kt | 32 + src/main/kotlin/events/FirmamentEvent.kt | 38 + src/main/kotlin/events/FirmamentEventBus.kt | 65 + .../kotlin/events/HandledScreenClickEvent.kt | 10 + .../events/HandledScreenForegroundEvent.kt | 16 + .../events/HandledScreenKeyPressedEvent.kt | 38 + .../events/HandledScreenPushREIEvent.kt | 18 + .../kotlin/events/HotbarItemRenderEvent.kt | 17 + src/main/kotlin/events/HudRenderEvent.kt | 17 + .../kotlin/events/IsSlotProtectedEvent.kt | 65 + src/main/kotlin/events/ItemTooltipEvent.kt | 14 + src/main/kotlin/events/MaskCommands.kt | 13 + src/main/kotlin/events/ModifyChatEvent.kt | 21 + src/main/kotlin/events/OutgoingPacketEvent.kt | 9 + src/main/kotlin/events/ParticleSpawnEvent.kt | 18 + .../events/PartyMessageReceivedEvent.kt | 9 + .../kotlin/events/PlayerInventoryUpdate.kt | 22 + src/main/kotlin/events/ProcessChatEvent.kt | 28 + src/main/kotlin/events/ProfileSwitchEvent.kt | 7 + .../kotlin/events/ReloadRegistrationEvent.kt | 7 + src/main/kotlin/events/ScreenChangeEvent.kt | 10 + .../kotlin/events/ScreenRenderPostEvent.kt | 16 + .../kotlin/events/ServerConnectedEvent.kt | 18 + .../events/SkyblockServerUpdateEvent.kt | 15 + src/main/kotlin/events/SlotClickEvent.kt | 15 + src/main/kotlin/events/SlotRenderEvents.kt | 37 + src/main/kotlin/events/SoundReceiveEvent.kt | 18 + src/main/kotlin/events/TickEvent.kt | 7 + src/main/kotlin/events/UseBlockEvent.kt | 11 + src/main/kotlin/events/UseItemEvent.kt | 11 + src/main/kotlin/events/WorldKeyboardEvent.kt | 17 + src/main/kotlin/events/WorldMouseMoveEvent.kt | 5 + src/main/kotlin/events/WorldReadyEvent.kt | 10 + .../kotlin/events/WorldRenderLastEvent.kt | 24 + .../kotlin/events/registration/ChatEvents.kt | 63 + .../events/subscription/Subscription.kt | 17 + .../events/subscription/SubscriptionList.kt | 28 + src/main/kotlin/features/FeatureManager.kt | 133 + src/main/kotlin/features/FirmamentFeature.kt | 23 + .../kotlin/features/chat/AutoCompletions.kt | 55 + src/main/kotlin/features/chat/ChatLinks.kt | 165 + src/main/kotlin/features/chat/CopyChat.kt | 31 + .../kotlin/features/chat/PartyCommands.kt | 134 + .../kotlin/features/chat/QuickCommands.kt | 154 + .../features/debug/AnimatedClothingScanner.kt | 193 + src/main/kotlin/features/debug/DebugLogger.kt | 26 + src/main/kotlin/features/debug/DebugView.kt | 29 + .../features/debug/DeveloperFeatures.kt | 121 + .../debug/ExportedTestConstantMeta.kt | 27 + .../kotlin/features/debug/MinorTrolling.kt | 27 + .../kotlin/features/debug/PowerUserTools.kt | 245 + .../kotlin/features/debug/SoundVisualizer.kt | 65 + .../features/debug/itemeditor/ExportRecipe.kt | 255 + .../features/debug/itemeditor/ItemExporter.kt | 242 + .../debug/itemeditor/LegacyItemData.kt | 89 + .../debug/itemeditor/LegacyItemExporter.kt | 311 ++ .../features/debug/itemeditor/PromptScreen.kt | 15 + .../features/diana/AncestralSpadeSolver.kt | 131 + .../kotlin/features/diana/DianaWaypoints.kt | 31 + .../features/diana/NearbyBurrowsSolver.kt | 144 + .../events/anniversity/AnniversaryFeatures.kt | 226 + .../anniversity/CenturyRaffleFeatures.kt | 63 + .../events/carnival/CarnivalFeatures.kt | 17 + .../events/carnival/MinesweeperHelper.kt | 276 + .../features/fixes/CompatibliltyFeatures.kt | 41 + src/main/kotlin/features/fixes/Fixes.kt | 82 + .../features/garden/HideComposterNoises.kt | 32 + .../features/inventory/CraftingOverlay.kt | 83 + .../kotlin/features/inventory/ItemHotkeys.kt | 42 + .../features/inventory/ItemRarityCosmetics.kt | 63 + .../features/inventory/JunkHighlighter.kt | 29 + .../kotlin/features/inventory/PetFeatures.kt | 86 + .../kotlin/features/inventory/PriceData.kt | 120 + .../features/inventory/REIDependencyWarner.kt | 85 + .../features/inventory/SaveCursorPosition.kt | 66 + .../kotlin/features/inventory/SlotLocking.kt | 504 ++ .../kotlin/features/inventory/TimerInLore.kt | 150 + .../features/inventory/WardrobeKeybinds.kt | 80 + .../inventory/buttons/InventoryButton.kt | 103 + .../buttons/InventoryButtonEditor.kt | 300 ++ .../buttons/InventoryButtonTemplates.kt | 33 + .../inventory/buttons/InventoryButtons.kt | 114 + .../storageoverlay/StorageBackingHandle.kt | 59 + .../inventory/storageoverlay/StorageData.kt | 21 + .../storageoverlay/StorageOverlay.kt | 200 + .../storageoverlay/StorageOverlayCustom.kt | 122 + .../storageoverlay/StorageOverlayScreen.kt | 562 +++ .../storageoverlay/StorageOverviewScreen.kt | 135 + .../storageoverlay/StoragePageSlot.kt | 66 + .../storageoverlay/VirtualInventory.kt | 76 + .../features/items/BlockZapperOverlay.kt | 146 + .../features/items/BonemerangOverlay.kt | 101 + .../kotlin/features/items/EtherwarpOverlay.kt | 54 + .../kotlin/features/macros/ComboProcessor.kt | 114 + .../kotlin/features/macros/HotkeyAction.kt | 40 + .../kotlin/features/macros/KeyComboTrie.kt | 73 + src/main/kotlin/features/macros/MacroData.kt | 12 + src/main/kotlin/features/macros/MacroUI.kt | 285 ++ src/main/kotlin/features/macros/RadialMenu.kt | 153 + .../features/mining/CommissionFeatures.kt | 26 + src/main/kotlin/features/mining/Histogram.kt | 81 + .../kotlin/features/mining/HotmPresets.kt | 218 + .../features/mining/MiningBlockInfoUi.kt | 54 + .../kotlin/features/mining/PickaxeAbility.kt | 244 + .../features/mining/PristineProfitTracker.kt | 148 + src/main/kotlin/features/misc/CustomCapes.kt | 192 + src/main/kotlin/features/misc/Devs.kt | 38 + src/main/kotlin/features/misc/Hud.kt | 77 + .../kotlin/features/misc/LicenseViewer.kt | 128 + src/main/kotlin/features/misc/TimerFeature.kt | 124 + .../features/notifications/Notifications.kt | 7 + .../kotlin/features/world/ColeWeightCompat.kt | 125 + src/main/kotlin/features/world/FairySouls.kt | 132 + .../features/world/FirmWaypointManager.kt | 168 + .../kotlin/features/world/FirmWaypoints.kt | 37 + .../kotlin/features/world/NPCWaypoints.kt | 40 + .../features/world/NavigableWaypoint.kt | 22 + .../kotlin/features/world/NavigationHelper.kt | 121 + .../kotlin/features/world/NpcWaypointGui.kt | 68 + .../features/world/TemporaryWaypoints.kt | 74 + src/main/kotlin/features/world/Waypoints.kt | 234 + src/main/kotlin/gui/BarComponent.kt | 115 + src/main/kotlin/gui/CheckboxComponent.kt | 57 + src/main/kotlin/gui/EmptyComponent.kt | 17 + src/main/kotlin/gui/FirmButtonComponent.kt | 81 + src/main/kotlin/gui/FirmHoverComponent.kt | 59 + src/main/kotlin/gui/FixedComponent.kt | 38 + src/main/kotlin/gui/ImageComponent.kt | 35 + src/main/kotlin/gui/TickComponent.kt | 18 + src/main/kotlin/gui/config/AllConfigsGui.kt | 103 + src/main/kotlin/gui/config/BooleanHandler.kt | 37 + .../gui/config/BuiltInConfigScreenProvider.kt | 14 + src/main/kotlin/gui/config/ChoiceHandler.kt | 48 + src/main/kotlin/gui/config/ClickHandler.kt | 24 + src/main/kotlin/gui/config/ColourHandler.kt | 82 + src/main/kotlin/gui/config/DurationHandler.kt | 58 + src/main/kotlin/gui/config/EnumRenderer.kt | 15 + .../config/FirmamentConfigScreenProvider.kt | 24 + src/main/kotlin/gui/config/GuiAppender.kt | 40 + src/main/kotlin/gui/config/HudMetaHandler.kt | 42 + src/main/kotlin/gui/config/IntegerHandler.kt | 54 + src/main/kotlin/gui/config/JAnyHud.kt | 48 + .../kotlin/gui/config/KeyBindingHandler.kt | 52 + .../gui/config/KeyBindingStateManager.kt | 146 + src/main/kotlin/gui/config/ManagedConfig.kt | 260 + .../kotlin/gui/config/ManagedConfigElement.kt | 8 + src/main/kotlin/gui/config/ManagedOption.kt | 68 + src/main/kotlin/gui/config/StringHandler.kt | 36 + src/main/kotlin/gui/entity/EntityModifier.kt | 9 + src/main/kotlin/gui/entity/EntityRenderer.kt | 237 + src/main/kotlin/gui/entity/GuiPlayer.kt | 62 + src/main/kotlin/gui/entity/ModifyAge.kt | 25 + src/main/kotlin/gui/entity/ModifyCharged.kt | 14 + src/main/kotlin/gui/entity/ModifyEquipment.kt | 55 + src/main/kotlin/gui/entity/ModifyHorse.kt | 59 + src/main/kotlin/gui/entity/ModifyInvisible.kt | 13 + src/main/kotlin/gui/entity/ModifyName.kt | 14 + .../kotlin/gui/entity/ModifyPlayerSkin.kt | 47 + src/main/kotlin/gui/entity/ModifyRiding.kt | 15 + src/main/kotlin/gui/entity/ModifyWither.kt | 20 + src/main/kotlin/gui/hud/MoulConfigHud.kt | 66 + src/main/kotlin/jarvis/JarvisIntegration.kt | 64 + .../keybindings/FirmamentKeyBindings.kt | 25 + src/main/kotlin/keybindings/IKeyBinding.kt | 50 + .../kotlin/keybindings/SavedKeyBinding.kt | 125 + src/main/kotlin/repo/BetterRepoRecipeCache.kt | 31 + src/main/kotlin/repo/EssenceRecipeProvider.kt | 51 + src/main/kotlin/repo/ExpLadder.kt | 95 + src/main/kotlin/repo/ExpensiveItemCacheApi.kt | 8 + src/main/kotlin/repo/ExtraRecipeProvider.kt | 7 + src/main/kotlin/repo/HypixelStaticData.kt | 122 + src/main/kotlin/repo/ItemCache.kt | 312 ++ src/main/kotlin/repo/ItemNameLookup.kt | 101 + src/main/kotlin/repo/MiningRepoData.kt | 133 + src/main/kotlin/repo/ModernOverlaysData.kt | 41 + src/main/kotlin/repo/PetData.kt | 24 + src/main/kotlin/repo/Reforge.kt | 160 + src/main/kotlin/repo/ReforgeStore.kt | 125 + src/main/kotlin/repo/RepoDownloadManager.kt | 127 + src/main/kotlin/repo/RepoItemTypeCache.kt | 15 + src/main/kotlin/repo/RepoManager.kt | 211 + src/main/kotlin/repo/RepoModResourcePack.kt | 127 + src/main/kotlin/repo/SBItemStack.kt | 458 ++ .../repo/recipes/GenericRecipeRenderer.kt | 21 + .../kotlin/repo/recipes/RecipeLayouter.kt | 38 + .../repo/recipes/SBCraftingRecipeRenderer.kt | 60 + .../recipes/SBEssenceUpgradeRecipeRenderer.kt | 76 + .../repo/recipes/SBForgeRecipeRenderer.kt | 83 + src/main/kotlin/util/AprilFoolsUtil.kt | 10 + src/main/kotlin/util/Base64Util.kt | 17 + src/main/kotlin/util/BazaarPriceStrategy.kt | 19 + src/main/kotlin/util/ChromaColourUtil.kt | 10 + src/main/kotlin/util/ClipboardUtils.kt | 24 + src/main/kotlin/util/CommonSoundEffects.kt | 26 + src/main/kotlin/util/DurabilityBarEvent.kt | 20 + src/main/kotlin/util/ErrorBoundary.kt | 10 + src/main/kotlin/util/ErrorUtil.kt | 97 + src/main/kotlin/util/FirmFormatters.kt | 142 + src/main/kotlin/util/FragmentGuiScreen.kt | 93 + src/main/kotlin/util/HoveredItemStack.kt | 27 + src/main/kotlin/util/IdentifierSerializer.kt | 25 + .../kotlin/util/IdentityCharacteristics.kt | 15 + src/main/kotlin/util/IntUtil.kt | 12 + src/main/kotlin/util/JvmUtil.kt | 32 + src/main/kotlin/util/LegacyFormattingCode.kt | 37 + src/main/kotlin/util/LegacyTagParser.kt | 245 + src/main/kotlin/util/LegacyTagWriter.kt | 103 + src/main/kotlin/util/LoadResource.kt | 20 + src/main/kotlin/util/Locraw.kt | 12 + src/main/kotlin/util/LogIfNull.kt | 8 + src/main/kotlin/util/MC.kt | 152 + src/main/kotlin/util/MinecraftDispatcher.kt | 8 + src/main/kotlin/util/MoulConfigFragment.kt | 44 + src/main/kotlin/util/MoulConfigUtils.kt | 329 ++ src/main/kotlin/util/Optionalutil.kt | 5 + src/main/kotlin/util/SBData.kt | 89 + src/main/kotlin/util/ScoreboardUtil.kt | 55 + src/main/kotlin/util/ScreenUtil.kt | 38 + src/main/kotlin/util/SequenceUtil.kt | 11 + src/main/kotlin/util/SkyBlockIsland.kt | 52 + src/main/kotlin/util/SkyblockId.kt | 285 ++ src/main/kotlin/util/SortedMapSerializer.kt | 25 + src/main/kotlin/util/StringUtil.kt | 30 + src/main/kotlin/util/TemplateUtil.kt | 86 + src/main/kotlin/util/TestUtil.kt | 10 + src/main/kotlin/util/TimeMark.kt | 52 + src/main/kotlin/util/Timer.kt | 25 + src/main/kotlin/util/WarpUtil.kt | 96 + .../kotlin/util/accessors/GetRectangle.kt | 17 + src/main/kotlin/util/accessors/chathud.kt | 8 + src/main/kotlin/util/asm/AsmAnnotationUtil.kt | 89 + src/main/kotlin/util/assertions.kt | 35 + src/main/kotlin/util/async/input.kt | 89 + .../kotlin/util/collections/InstanceList.kt | 57 + .../util/collections/MutableMapWithMaxSize.kt | 40 + src/main/kotlin/util/collections/RangeUtil.kt | 40 + src/main/kotlin/util/collections/WeakCache.kt | 116 + src/main/kotlin/util/collections/listutil.kt | 9 + src/main/kotlin/util/colorconversion.kt | 13 + .../kotlin/util/compatloader/CompatLoader.kt | 50 + .../kotlin/util/compatloader/CompatMeta.kt | 48 + .../util/customgui/CoordRememberingSlot.kt | 14 + src/main/kotlin/util/customgui/CustomGui.kt | 91 + .../kotlin/util/customgui/HasCustomGui.kt | 17 + src/main/kotlin/util/data/DataHolder.kt | 62 + src/main/kotlin/util/data/IDataHolder.kt | 71 + .../kotlin/util/data/MultiFileDataHolder.kt | 63 + .../util/data/ProfileSpecificDataHolder.kt | 84 + .../kotlin/util/json/BlockPosSerializer.kt | 25 + .../util/json/DashlessUUIDSerializer.kt | 27 + src/main/kotlin/util/json/FirmCodecs.kt | 20 + .../util/json/InstantAsLongSerializer.kt | 22 + src/main/kotlin/util/json/KJsonOps.kt | 131 + src/main/kotlin/util/json/KJsonUtils.kt | 11 + .../util/json/SingletonSerializableList.kt | 31 + .../kotlin/util/math/GChainReconciliation.kt | 102 + src/main/kotlin/util/math/Projections.kt | 46 + src/main/kotlin/util/mc/ArmorUtil.kt | 8 + src/main/kotlin/util/mc/CommonTextures.kt | 7 + src/main/kotlin/util/mc/FakeInventory.kt | 41 + src/main/kotlin/util/mc/FakeSlot.kt | 15 + .../util/mc/FirmamentDataComponentTypes.kt | 60 + src/main/kotlin/util/mc/InitLevel.kt | 25 + .../util/mc/IntrospectableItemModelManager.kt | 7 + src/main/kotlin/util/mc/InventoryUtil.kt | 28 + src/main/kotlin/util/mc/ItemUtil.kt | 20 + src/main/kotlin/util/mc/MCTabListAPI.kt | 96 + src/main/kotlin/util/mc/NbtItemData.kt | 22 + src/main/kotlin/util/mc/NbtPrism.kt | 91 + src/main/kotlin/util/mc/NbtUtil.kt | 10 + src/main/kotlin/util/mc/PlayerUtil.kt | 7 + src/main/kotlin/util/mc/SNbtFormatter.kt | 142 + src/main/kotlin/util/mc/ScreenUtil.kt | 26 + src/main/kotlin/util/mc/SkullItemData.kt | 86 + src/main/kotlin/util/mc/SlotUtils.kt | 47 + .../kotlin/util/mc/TolerantRegistriesOps.kt | 29 + src/main/kotlin/util/mc/asFakeServer.kt | 37 + src/main/kotlin/util/propertyutil.kt | 9 + src/main/kotlin/util/regex.kt | 73 + .../kotlin/util/render/CustomRenderLayers.kt | 106 + src/main/kotlin/util/render/DrawContextExt.kt | 68 + .../util/render/FacingThePlayerContext.kt | 92 + .../kotlin/util/render/FirmamentShaders.kt | 20 + src/main/kotlin/util/render/LerpUtils.kt | 40 + .../util/render/RenderCircleProgress.kt | 101 + .../kotlin/util/render/RenderContextDSL.kt | 6 + .../util/render/RenderInWorldContext.kt | 316 ++ .../util/render/TintedOverlayTexture.kt | 35 + .../kotlin/util/render/TranslatedScissors.kt | 26 + src/main/kotlin/util/skyblock/AbilityUtils.kt | 139 + src/main/kotlin/util/skyblock/DungeonUtil.kt | 33 + src/main/kotlin/util/skyblock/ItemType.kt | 75 + src/main/kotlin/util/skyblock/Rarity.kt | 99 + src/main/kotlin/util/skyblock/SBItemUtil.kt | 21 + src/main/kotlin/util/skyblock/SackUtil.kt | 115 + .../kotlin/util/skyblock/SkyBlockItems.kt | 24 + src/main/kotlin/util/skyblock/TabListAPI.kt | 41 + src/main/kotlin/util/textutil.kt | 210 + src/main/kotlin/util/uuid.kt | 16 + .../firmament/filters/screen/always.json | 5 + .../filters/screen/always.json.license | 3 + .../assets/firmament/gui/anniversary_pig.xml | 27 + .../firmament/gui/button_editor_fragment.xml | 24 + .../gui/carnival/minesweeper_tutorial.xml | 49 + .../assets/firmament/gui/config/category.xml | 42 + .../firmament/gui/config/macros/combos.xml | 55 + .../gui/config/macros/editor_combo.xml | 42 + .../gui/config/macros/editor_wheel.xml | 43 + .../firmament/gui/config/macros/index.xml | 27 + .../firmament/gui/config/macros/wheel.xml | 54 + .../assets/firmament/gui/config/main.xml | 29 + .../firmament/gui/license_viewer/index.xml | 65 + .../firmament/gui/mining_block_info/index.xml | 38 + .../assets/firmament/gui/npc_waypoints.xml | 36 + .../assets/firmament/gui/pristine_profit.xml | 14 + .../assets/firmament/gui/repo_reload.xml | 7 + src/main/resources/assets/firmament/logo.png | Bin 0 -> 19770 bytes .../firmament/shaders/cape/parallax.fsh | 53 + .../shaders/circle_discard_color.fsh | 22 + .../shaders/core/rendertype_lines.fsh | 18 + .../shaders/core/rendertype_lines.json | 17 + .../shaders/core/rendertype_lines.vsh | 62 + .../assets/firmament/textures/cape/REUSE.toml | 19 + .../firmament/textures/cape/firm_static.png | Bin 0 -> 42249 bytes .../textures/cape/firmament_star.png | Bin 0 -> 1141 bytes .../firmament/textures/cape/fsr_static.png | Bin 0 -> 21747 bytes .../textures/cape/parallax_background.png | Bin 0 -> 2053 bytes .../textures/cape/parallax_template.png | Bin 0 -> 352 bytes .../assets/firmament/textures/gui/bar.png | Bin 0 -> 679 bytes .../assets/firmament/textures/gui/circle.png | Bin 0 -> 340 bytes .../firmament/textures/gui/circle.png.license | 4 + .../completed_commission_background.png | Bin 0 -> 558 bytes .../gui/sprites/generic_vanilla_widget.png | Bin 0 -> 4314 bytes .../sprites/generic_vanilla_widget.png.mcmeta | 10 + .../textures/gui/sprites/hotm_perk_preset.png | Bin 0 -> 558 bytes .../sprites/inventory_button_background.png | Bin 0 -> 635 bytes .../gui/sprites/item_rarity_background.png | Bin 0 -> 5061 bytes .../gui/sprites/selected_pet_background.png | Bin 0 -> 558 bytes .../textures/gui/sprites/slot_locked.png | Bin 0 -> 595 bytes .../storageoverlay/player_inventory.png | Bin 0 -> 1019 bytes .../storageoverlay/scroll_bar_background.png | Bin 0 -> 4348 bytes .../scroll_bar_background.png.mcmeta | 10 + .../storageoverlay/scroll_bar_knob.png | Bin 0 -> 4583 bytes .../storageoverlay/storage_controls.png | Bin 0 -> 745 bytes .../storage_controls.png.mcmeta | 10 + .../sprites/storageoverlay/storage_row.png | Bin 0 -> 649 bytes .../storageoverlay/storage_row.png.mcmeta | 9 + .../storageoverlay/upper_background.png | Bin 0 -> 1396 bytes .../upper_background.png.mcmeta | 10 + .../textures/gui/sprites/uuid_locked.png | Bin 0 -> 597 bytes .../gui/sprites/widget/button_active.png | Bin 0 -> 8353 bytes .../gui/sprites/widget/checkbox_checked.png | Bin 0 -> 683 bytes .../gui/sprites/widget/checkbox_unchecked.png | Bin 0 -> 614 bytes .../textures/gui/waypoint_selected.png | Bin 0 -> 225 bytes .../textures/gui/waypoint_unselected.png | Bin 0 -> 217 bytes .../firmament/textures/socials/discord.png | Bin 0 -> 14644 bytes .../assets/firmament/textures/socials/git.png | Bin 0 -> 79519 bytes .../firmament/textures/socials/modrinth.png | Bin 0 -> 4521 bytes src/main/resources/fabric.mod.json | 75 + src/main/resources/fabric.mod.json.license | 3 + src/main/resources/firmament.accesswidener | 36 + .../resources/firmament.accesswidener.license | 3 + src/main/resources/firmament.mixins.json | 10 + .../resources/firmament.mixins.json.license | 3 + src/main/resources/hotswap-agent.properties | 6 + src/main/resources/legacy_data/effects.json | 140 + .../resources/legacy_data/enchantments.json | 560 ++ src/main/resources/legacy_data/items.json | 3733 ++++++++++++++ .../sprites/inventory_button_background.png | Bin 0 -> 122 bytes .../storageoverlay/player_inventory.png | Bin 0 -> 639 bytes .../storageoverlay/scroll_bar_background.png | Bin 0 -> 147 bytes .../scroll_bar_background.png.mcmeta | 10 + .../storageoverlay/storage_controls.png | Bin 0 -> 768 bytes .../storage_controls.png.mcmeta | 10 + .../sprites/storageoverlay/storage_row.png | Bin 0 -> 203 bytes .../storageoverlay/storage_row.png.mcmeta | 9 + .../storageoverlay/upper_background.png | Bin 0 -> 795 bytes .../upper_background.png.mcmeta | 10 + .../transparent_overlay/pack.mcmeta | 10 + src/test/kotlin/MixinTest.kt | 34 + .../features/macros/KeyComboTrieCreation.kt | 103 + src/test/kotlin/root.kt | 30 + .../kotlin/testutil/AutoBootstrapExtension.kt | 14 + src/test/kotlin/testutil/ItemResources.kt | 94 + src/test/kotlin/util/ColorCodeTest.kt | 57 + src/test/kotlin/util/TextUtilText.kt | 18 + .../util/math/GChainReconciliationTest.kt | 75 + .../kotlin/util/math/ProjectionsBoxTest.kt | 28 + .../kotlin/util/skyblock/AbilityUtilsTest.kt | 87 + src/test/kotlin/util/skyblock/ItemTypeTest.kt | 28 + src/test/kotlin/util/skyblock/SackUtilTest.kt | 29 + .../kotlin/util/skyblock/TabListAPITest.kt | 48 + .../kotlin/util/skyblock/TimestampTest.kt | 28 + .../resources/testdata/chat/all-chat.snbt | 165 + .../chat/sacks/gain-and-lose-regular.snbt | 104 + .../chat/sacks/gain-rotten-flesh.snbt | 104 + .../testdata/items/aspect-of-the-void.snbt | 62 + .../testdata/items/backpack-in-menu.snbt | 122 + .../testdata/items/books/feather_falling.snbt | 39 + .../testdata/items/diamond-pickaxe.snbt | 51 + .../testdata/items/gemstone-gauntlet.snbt | 106 + .../resources/testdata/items/hyperion.snbt | 99 + .../testdata/items/implosion-belt.snbt | 108 + .../testdata/items/necron-boots.snbt | 71 + .../testdata/items/pets/lion-item.snbt | 65 + .../pets/mithril-golem-not-selected.snbt | 55 + .../testdata/items/pets/rabbit-selected.snbt | 63 + .../testdata/items/rune-in-sack.snbt | 34 + .../testdata/items/titanium-drill.snbt | 100 + .../testdata/tablist/dungeon_hub.snbt | 1170 +++++ src/texturePacks/README.md | 13 + .../firmament/features/texturepack/Compat.kt | 11 + .../texturepack/CustomBlockTextures.kt | 453 ++ .../texturepack/CustomGlobalArmorOverrides.kt | 180 + .../texturepack/CustomGlobalTextures.kt | 143 + .../texturepack/CustomModelOverrideParser.kt | 123 + .../texturepack/CustomScreenLayouts.kt | 224 + .../texturepack/CustomSkyBlockTextures.kt | 119 + .../features/texturepack/CustomTextColors.kt | 80 + .../texturepack/FirmamentModelPredicate.kt | 11 + .../FirmamentModelPredicateParser.kt | 8 + .../FirmamentRootPredicateSerializer.kt | 23 + .../features/texturepack/HeadModelChooser.kt | 90 + .../features/texturepack/PredicateModel.kt | 105 + .../features/texturepack/RarityMatcher.kt | 69 + .../features/texturepack/StringMatcher.kt | 160 + .../features/texturepack/TintOverrides.kt | 75 + .../texturepack/predicates/AlwaysPredicate.kt | 19 + .../texturepack/predicates/AndPredicate.kt | 29 + .../texturepack/predicates/CastPredicate.kt | 25 + .../predicates/DisplayNamePredicate.kt | 22 + .../predicates/ExtraAttributesPredicate.kt | 241 + .../predicates/GenericComponentPredicate.kt | 58 + .../texturepack/predicates/ItemPredicate.kt | 34 + .../texturepack/predicates/LorePredicate.kt | 22 + .../texturepack/predicates/NotPredicate.kt | 21 + .../texturepack/predicates/NumberMatcher.kt | 124 + .../texturepack/predicates/OrPredicate.kt | 29 + .../texturepack/predicates/PetPredicate.kt | 66 + .../predicates/PullingPredicate.kt | 26 + .../texturepack/predicates/SkullPredicate.kt | 63 + .../ApplyHeadModelInItemRenderer.java | 23 + .../BuildExtraBlockStateModels.java | 24 + .../custommodels/CustomSkullTexturePatch.java | 26 + .../InsertExtraBlockModelDependencies.java | 28 + .../ItemRenderStateExtraInfo.java | 28 + .../custommodels/LoadExtraBlockStates.java | 34 + .../custommodels/PatchArmorTexture.java | 30 + .../PatchLegacyArmorLayerSupport.java | 22 + ...atchLegacyTexturePathsIntoArmorLayers.java | 37 + .../ReplaceBlockBreakSoundPatch.java | 27 + .../ReplaceBlockHitSoundPatch.java | 31 + .../ReplaceBlockRenderManagerBlockModel.java | 37 + .../ReplaceFallbackBlockModel.java | 21 + .../mixins/custommodels/ReplaceHeadModel.java | 51 + .../custommodels/ReplaceItemModelPatch.java | 43 + .../custommodels/SupplyFakeModelPatch.java | 97 + .../screenlayouts/ExpandScreenBoundaries.java | 21 + .../screenlayouts/ReplaceAnvilScreen.java | 55 + .../screenlayouts/ReplaceForgingScreen.java | 9 + .../ReplaceFurnaceBackgrounds.java | 31 + .../ReplaceGenericBackgrounds.java | 28 + .../ReplacePlayerBackgrounds.java | 50 + .../ReplaceTextColorInHandledScreen.java | 65 + symbols/build.gradle.kts | 12 + symbols/src/main/kotlin/Subscribe.kt | 7 + .../kotlin/process/CompatMetaProcessor.kt | 63 + .../GameTestContainingClassProcessor.kt | 80 + .../process/SubscribeAnnotationProcessor.kt | 136 + testagent/build.gradle.kts | 15 + .../nea/firmament/testagent/AgentMain.java | 21 + .../ProtectedToPublicClassRewriter.java | 31 + .../ProtectedToPublicClassTransformer.java | 30 + translations/en_us.json | 552 ++ translations/extra.json | 6 + translations/extra_zh_cn.json | 6 + translations/zh_cn.json | 552 ++ web/.gitignore | 28 + web/.vscode/extensions.json | 4 + web/.vscode/launch.json | 11 + web/REUSE.toml | 20 + web/astro.config.mjs | 12 + web/package.json | 21 + web/pnpm-lock.yaml | 4487 +++++++++++++++++ web/src/components/Hero.astro | 19 + web/src/components/NavBar.astro | 26 + web/src/components/NavLink.astro | 11 + web/src/env.d.ts | 1 + web/src/layouts/Base.astro | 13 + web/src/layouts/Content.astro | 63 + web/src/layouts/Head.astro | 12 + web/src/pages/docs/_texture-pack-format.md | 832 +++ web/src/pages/docs/texture-pack-format.astro | 15 + web/src/pages/index.astro | 20 + web/src/pages/texture-packs.astro | 9 + web/src/panorama.png | Bin 0 -> 2282096 bytes web/tailwind.config.mjs | 8 + web/tsconfig.json | 3 + 709 files changed, 52244 insertions(+) create mode 100644 .editorconfig create mode 100644 .pre-commit-config.yaml create mode 100644 CONTRIBUTING.md create mode 100644 LICENSES/Apache-2.0.txt create mode 100644 LICENSES/CC-BY-4.0.txt create mode 100644 LICENSES/CC0-1.0.txt create mode 100644 LICENSES/GPL-3.0-or-later.txt create mode 100644 LICENSES/MIT.txt create mode 100644 REUSE.toml create mode 100644 build-logic/build.gradle.kts create mode 100644 build-logic/gradle/wrapper create mode 100644 build-logic/gradlew create mode 100644 build-logic/gradlew.bat create mode 100644 build-logic/settings.gradle.kts create mode 100644 build-logic/src/main/kotlin/EnvFile.kt create mode 100644 build-logic/src/main/kotlin/FabricModTransform.kt create mode 100644 build-logic/src/main/kotlin/InnerJarsUnpacker.kt create mode 100644 build-logic/src/main/kotlin/RepoDownload.kt create mode 100644 build-logic/src/main/kotlin/firmament.base.gradle.kts create mode 100644 build-logic/src/main/kotlin/firmament.common.gradle.kts create mode 100644 build-logic/src/main/kotlin/firmament.license-management.gradle.kts create mode 100644 build-logic/src/main/kotlin/firmament.repositories.gradle.kts create mode 100644 build-logic/src/main/kotlin/licenseinfo.kt create mode 100644 build-logic/src/main/kotlin/lookupversion.kt create mode 100644 build.gradle.kts create mode 100644 check-translation-ordering.sh create mode 100644 docs/How to release.md create mode 100644 docs/firmament_logo.webp create mode 100644 docs/firmament_logo.webp.license create mode 100644 docs/firmament_logo_256.webp create mode 100644 docs/firmament_logo_256.webp.license create mode 100644 docs/firmament_logo_256_nobg.webp create mode 100644 docs/firmament_logo_256_nobg.webp.license create mode 100644 docs/firmament_logo_256_trans.webp create mode 100644 docs/firmament_logo_256_trans.webp.license create mode 100644 docs/firmament_logo_nobg.webp create mode 100644 docs/firmament_logo_nobg.webp.license create mode 100644 docs/firmament_logo_trans.webp create mode 100644 docs/firmament_logo_trans.webp.license create mode 100644 docs/release_script.sh create mode 100644 gradle.properties create mode 100644 gradle/libs.versions.toml create mode 100644 gradle/wrapper/gradle-wrapper.jar.license create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 javaplugin/build.gradle.kts create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionPlugin.java create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionTask.java create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java create mode 100644 javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java create mode 100644 javaplugin/src/main/resources/META-INF/services/com.sun.source.util.Plugin create mode 100644 settings.gradle.kts create mode 100644 shell.nix create mode 100644 src/compat/citresewn/java/ConditionDirectAccessHelper.kt create mode 100644 src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java create mode 100644 src/compat/configured/java/BaseConfigNode.kt create mode 100644 src/compat/configured/java/ConfigCategory.kt create mode 100644 src/compat/configured/java/ConfigNode.kt create mode 100644 src/compat/configured/java/ConfigValue.kt create mode 100644 src/compat/configured/java/ConfigValueNode.kt create mode 100644 src/compat/configured/java/ConfiguredCompat.kt create mode 100644 src/compat/configured/java/ConfiguredConfigScreenProvider.kt create mode 100644 src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt create mode 100644 src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java create mode 100644 src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java create mode 100644 src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java create mode 100644 src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java create mode 100644 src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt create mode 100644 src/compat/moulconfig/java/MCConfigEditorIntegration.kt create mode 100644 src/compat/moulconfig/java/ProcessedCategoryFirm.kt create mode 100644 src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt create mode 100644 src/compat/moulconfig/java/ProcessedOptionFirm.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/math.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt create mode 100644 src/compat/rei/java/moe/nea/firmament/mixins/compat/HideREIRecipeWarning.java create mode 100644 src/compat/sodium/java/SodiumChunkReloader.kt create mode 100644 src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java create mode 100644 src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java create mode 100644 src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt create mode 100644 src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java create mode 100644 src/compat/yacl/java/KeybindingBuilder.kt create mode 100644 src/compat/yacl/java/KeybindingController.kt create mode 100644 src/compat/yacl/java/YaclIntegration.kt create mode 100644 src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java create mode 100644 src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java create mode 100644 src/main/java/moe/nea/firmament/init/EarlyRiser.java create mode 100644 src/main/java/moe/nea/firmament/init/HandledScreenRiser.java create mode 100644 src/main/java/moe/nea/firmament/init/Intermediary.java create mode 100644 src/main/java/moe/nea/firmament/init/IntermediaryName.java create mode 100644 src/main/java/moe/nea/firmament/init/MixinPlugin.java create mode 100644 src/main/java/moe/nea/firmament/init/RiserUtils.java create mode 100644 src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java create mode 100644 src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java create mode 100644 src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java create mode 100644 src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/CaseInsensitiveCommandMapPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java create mode 100644 src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java create mode 100644 src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java create mode 100644 src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java create mode 100644 src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java create mode 100644 src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java create mode 100644 src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java create mode 100644 src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatchForSession.java create mode 100644 src/main/java/moe/nea/firmament/mixins/RedirectWithoutSubCommands.java create mode 100644 src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java create mode 100644 src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java create mode 100644 src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/TextureUnpackBase64PadPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java create mode 100644 src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/YggdrasilSignatureIgnorePatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java create mode 100644 src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java create mode 100644 src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java create mode 100644 src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java create mode 100644 src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java create mode 100644 src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java create mode 100644 src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java create mode 100644 src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java create mode 100644 src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java create mode 100644 src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java create mode 100644 src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java create mode 100644 src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/SaveCapeToPlayerEntityRenderState.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java create mode 100644 src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java create mode 100644 src/main/kotlin/Compat.kt create mode 100644 src/main/kotlin/Firmament.kt create mode 100644 src/main/kotlin/apis/Profiles.kt create mode 100644 src/main/kotlin/apis/Routes.kt create mode 100644 src/main/kotlin/apis/UrsaManager.kt create mode 100644 src/main/kotlin/commands/CaseInsensitiveLiteralCommandNode.kt create mode 100644 src/main/kotlin/commands/Duration.kt create mode 100644 src/main/kotlin/commands/RestArgumentType.kt create mode 100644 src/main/kotlin/commands/dsl.kt create mode 100644 src/main/kotlin/commands/rome.kt create mode 100644 src/main/kotlin/events/AllowChatEvent.kt create mode 100644 src/main/kotlin/events/AttackBlockEvent.kt create mode 100644 src/main/kotlin/events/ChestInventoryUpdateEvent.kt create mode 100644 src/main/kotlin/events/ClientInitEvent.kt create mode 100644 src/main/kotlin/events/ClientStartedEvent.kt create mode 100644 src/main/kotlin/events/CommandEvent.kt create mode 100644 src/main/kotlin/events/CustomItemModelEvent.kt create mode 100644 src/main/kotlin/events/DebugInstantiateEvent.kt create mode 100644 src/main/kotlin/events/EarlyResourceReloadEvent.kt create mode 100644 src/main/kotlin/events/EntityDespawnEvent.kt create mode 100644 src/main/kotlin/events/EntityInteractionEvent.kt create mode 100644 src/main/kotlin/events/EntityRenderTintEvent.kt create mode 100644 src/main/kotlin/events/EntityUpdateEvent.kt create mode 100644 src/main/kotlin/events/FeaturesInitializedEvent.kt create mode 100644 src/main/kotlin/events/FinalizeResourceManagerEvent.kt create mode 100644 src/main/kotlin/events/FirmamentEvent.kt create mode 100644 src/main/kotlin/events/FirmamentEventBus.kt create mode 100644 src/main/kotlin/events/HandledScreenClickEvent.kt create mode 100644 src/main/kotlin/events/HandledScreenForegroundEvent.kt create mode 100644 src/main/kotlin/events/HandledScreenKeyPressedEvent.kt create mode 100644 src/main/kotlin/events/HandledScreenPushREIEvent.kt create mode 100644 src/main/kotlin/events/HotbarItemRenderEvent.kt create mode 100644 src/main/kotlin/events/HudRenderEvent.kt create mode 100644 src/main/kotlin/events/IsSlotProtectedEvent.kt create mode 100644 src/main/kotlin/events/ItemTooltipEvent.kt create mode 100644 src/main/kotlin/events/MaskCommands.kt create mode 100644 src/main/kotlin/events/ModifyChatEvent.kt create mode 100644 src/main/kotlin/events/OutgoingPacketEvent.kt create mode 100644 src/main/kotlin/events/ParticleSpawnEvent.kt create mode 100644 src/main/kotlin/events/PartyMessageReceivedEvent.kt create mode 100644 src/main/kotlin/events/PlayerInventoryUpdate.kt create mode 100644 src/main/kotlin/events/ProcessChatEvent.kt create mode 100644 src/main/kotlin/events/ProfileSwitchEvent.kt create mode 100644 src/main/kotlin/events/ReloadRegistrationEvent.kt create mode 100644 src/main/kotlin/events/ScreenChangeEvent.kt create mode 100644 src/main/kotlin/events/ScreenRenderPostEvent.kt create mode 100644 src/main/kotlin/events/ServerConnectedEvent.kt create mode 100644 src/main/kotlin/events/SkyblockServerUpdateEvent.kt create mode 100644 src/main/kotlin/events/SlotClickEvent.kt create mode 100644 src/main/kotlin/events/SlotRenderEvents.kt create mode 100644 src/main/kotlin/events/SoundReceiveEvent.kt create mode 100644 src/main/kotlin/events/TickEvent.kt create mode 100644 src/main/kotlin/events/UseBlockEvent.kt create mode 100644 src/main/kotlin/events/UseItemEvent.kt create mode 100644 src/main/kotlin/events/WorldKeyboardEvent.kt create mode 100644 src/main/kotlin/events/WorldMouseMoveEvent.kt create mode 100644 src/main/kotlin/events/WorldReadyEvent.kt create mode 100644 src/main/kotlin/events/WorldRenderLastEvent.kt create mode 100644 src/main/kotlin/events/registration/ChatEvents.kt create mode 100644 src/main/kotlin/events/subscription/Subscription.kt create mode 100644 src/main/kotlin/events/subscription/SubscriptionList.kt create mode 100644 src/main/kotlin/features/FeatureManager.kt create mode 100644 src/main/kotlin/features/FirmamentFeature.kt create mode 100644 src/main/kotlin/features/chat/AutoCompletions.kt create mode 100644 src/main/kotlin/features/chat/ChatLinks.kt create mode 100644 src/main/kotlin/features/chat/CopyChat.kt create mode 100644 src/main/kotlin/features/chat/PartyCommands.kt create mode 100644 src/main/kotlin/features/chat/QuickCommands.kt create mode 100644 src/main/kotlin/features/debug/AnimatedClothingScanner.kt create mode 100644 src/main/kotlin/features/debug/DebugLogger.kt create mode 100644 src/main/kotlin/features/debug/DebugView.kt create mode 100644 src/main/kotlin/features/debug/DeveloperFeatures.kt create mode 100644 src/main/kotlin/features/debug/ExportedTestConstantMeta.kt create mode 100644 src/main/kotlin/features/debug/MinorTrolling.kt create mode 100644 src/main/kotlin/features/debug/PowerUserTools.kt create mode 100644 src/main/kotlin/features/debug/SoundVisualizer.kt create mode 100644 src/main/kotlin/features/debug/itemeditor/ExportRecipe.kt create mode 100644 src/main/kotlin/features/debug/itemeditor/ItemExporter.kt create mode 100644 src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt create mode 100644 src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt create mode 100644 src/main/kotlin/features/debug/itemeditor/PromptScreen.kt create mode 100644 src/main/kotlin/features/diana/AncestralSpadeSolver.kt create mode 100644 src/main/kotlin/features/diana/DianaWaypoints.kt create mode 100644 src/main/kotlin/features/diana/NearbyBurrowsSolver.kt create mode 100644 src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt create mode 100644 src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt create mode 100644 src/main/kotlin/features/events/carnival/CarnivalFeatures.kt create mode 100644 src/main/kotlin/features/events/carnival/MinesweeperHelper.kt create mode 100644 src/main/kotlin/features/fixes/CompatibliltyFeatures.kt create mode 100644 src/main/kotlin/features/fixes/Fixes.kt create mode 100644 src/main/kotlin/features/garden/HideComposterNoises.kt create mode 100644 src/main/kotlin/features/inventory/CraftingOverlay.kt create mode 100644 src/main/kotlin/features/inventory/ItemHotkeys.kt create mode 100644 src/main/kotlin/features/inventory/ItemRarityCosmetics.kt create mode 100644 src/main/kotlin/features/inventory/JunkHighlighter.kt create mode 100644 src/main/kotlin/features/inventory/PetFeatures.kt create mode 100644 src/main/kotlin/features/inventory/PriceData.kt create mode 100644 src/main/kotlin/features/inventory/REIDependencyWarner.kt create mode 100644 src/main/kotlin/features/inventory/SaveCursorPosition.kt create mode 100644 src/main/kotlin/features/inventory/SlotLocking.kt create mode 100644 src/main/kotlin/features/inventory/TimerInLore.kt create mode 100644 src/main/kotlin/features/inventory/WardrobeKeybinds.kt create mode 100644 src/main/kotlin/features/inventory/buttons/InventoryButton.kt create mode 100644 src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt create mode 100644 src/main/kotlin/features/inventory/buttons/InventoryButtonTemplates.kt create mode 100644 src/main/kotlin/features/inventory/buttons/InventoryButtons.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageData.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StorageOverviewScreen.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/StoragePageSlot.kt create mode 100644 src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt create mode 100644 src/main/kotlin/features/items/BlockZapperOverlay.kt create mode 100644 src/main/kotlin/features/items/BonemerangOverlay.kt create mode 100644 src/main/kotlin/features/items/EtherwarpOverlay.kt create mode 100644 src/main/kotlin/features/macros/ComboProcessor.kt create mode 100644 src/main/kotlin/features/macros/HotkeyAction.kt create mode 100644 src/main/kotlin/features/macros/KeyComboTrie.kt create mode 100644 src/main/kotlin/features/macros/MacroData.kt create mode 100644 src/main/kotlin/features/macros/MacroUI.kt create mode 100644 src/main/kotlin/features/macros/RadialMenu.kt create mode 100644 src/main/kotlin/features/mining/CommissionFeatures.kt create mode 100644 src/main/kotlin/features/mining/Histogram.kt create mode 100644 src/main/kotlin/features/mining/HotmPresets.kt create mode 100644 src/main/kotlin/features/mining/MiningBlockInfoUi.kt create mode 100644 src/main/kotlin/features/mining/PickaxeAbility.kt create mode 100644 src/main/kotlin/features/mining/PristineProfitTracker.kt create mode 100644 src/main/kotlin/features/misc/CustomCapes.kt create mode 100644 src/main/kotlin/features/misc/Devs.kt create mode 100644 src/main/kotlin/features/misc/Hud.kt create mode 100644 src/main/kotlin/features/misc/LicenseViewer.kt create mode 100644 src/main/kotlin/features/misc/TimerFeature.kt create mode 100644 src/main/kotlin/features/notifications/Notifications.kt create mode 100644 src/main/kotlin/features/world/ColeWeightCompat.kt create mode 100644 src/main/kotlin/features/world/FairySouls.kt create mode 100644 src/main/kotlin/features/world/FirmWaypointManager.kt create mode 100644 src/main/kotlin/features/world/FirmWaypoints.kt create mode 100644 src/main/kotlin/features/world/NPCWaypoints.kt create mode 100644 src/main/kotlin/features/world/NavigableWaypoint.kt create mode 100644 src/main/kotlin/features/world/NavigationHelper.kt create mode 100644 src/main/kotlin/features/world/NpcWaypointGui.kt create mode 100644 src/main/kotlin/features/world/TemporaryWaypoints.kt create mode 100644 src/main/kotlin/features/world/Waypoints.kt create mode 100644 src/main/kotlin/gui/BarComponent.kt create mode 100644 src/main/kotlin/gui/CheckboxComponent.kt create mode 100644 src/main/kotlin/gui/EmptyComponent.kt create mode 100644 src/main/kotlin/gui/FirmButtonComponent.kt create mode 100644 src/main/kotlin/gui/FirmHoverComponent.kt create mode 100644 src/main/kotlin/gui/FixedComponent.kt create mode 100644 src/main/kotlin/gui/ImageComponent.kt create mode 100644 src/main/kotlin/gui/TickComponent.kt create mode 100644 src/main/kotlin/gui/config/AllConfigsGui.kt create mode 100644 src/main/kotlin/gui/config/BooleanHandler.kt create mode 100644 src/main/kotlin/gui/config/BuiltInConfigScreenProvider.kt create mode 100644 src/main/kotlin/gui/config/ChoiceHandler.kt create mode 100644 src/main/kotlin/gui/config/ClickHandler.kt create mode 100644 src/main/kotlin/gui/config/ColourHandler.kt create mode 100644 src/main/kotlin/gui/config/DurationHandler.kt create mode 100644 src/main/kotlin/gui/config/EnumRenderer.kt create mode 100644 src/main/kotlin/gui/config/FirmamentConfigScreenProvider.kt create mode 100644 src/main/kotlin/gui/config/GuiAppender.kt create mode 100644 src/main/kotlin/gui/config/HudMetaHandler.kt create mode 100644 src/main/kotlin/gui/config/IntegerHandler.kt create mode 100644 src/main/kotlin/gui/config/JAnyHud.kt create mode 100644 src/main/kotlin/gui/config/KeyBindingHandler.kt create mode 100644 src/main/kotlin/gui/config/KeyBindingStateManager.kt create mode 100644 src/main/kotlin/gui/config/ManagedConfig.kt create mode 100644 src/main/kotlin/gui/config/ManagedConfigElement.kt create mode 100644 src/main/kotlin/gui/config/ManagedOption.kt create mode 100644 src/main/kotlin/gui/config/StringHandler.kt create mode 100644 src/main/kotlin/gui/entity/EntityModifier.kt create mode 100644 src/main/kotlin/gui/entity/EntityRenderer.kt create mode 100644 src/main/kotlin/gui/entity/GuiPlayer.kt create mode 100644 src/main/kotlin/gui/entity/ModifyAge.kt create mode 100644 src/main/kotlin/gui/entity/ModifyCharged.kt create mode 100644 src/main/kotlin/gui/entity/ModifyEquipment.kt create mode 100644 src/main/kotlin/gui/entity/ModifyHorse.kt create mode 100644 src/main/kotlin/gui/entity/ModifyInvisible.kt create mode 100644 src/main/kotlin/gui/entity/ModifyName.kt create mode 100644 src/main/kotlin/gui/entity/ModifyPlayerSkin.kt create mode 100644 src/main/kotlin/gui/entity/ModifyRiding.kt create mode 100644 src/main/kotlin/gui/entity/ModifyWither.kt create mode 100644 src/main/kotlin/gui/hud/MoulConfigHud.kt create mode 100644 src/main/kotlin/jarvis/JarvisIntegration.kt create mode 100644 src/main/kotlin/keybindings/FirmamentKeyBindings.kt create mode 100644 src/main/kotlin/keybindings/IKeyBinding.kt create mode 100644 src/main/kotlin/keybindings/SavedKeyBinding.kt create mode 100644 src/main/kotlin/repo/BetterRepoRecipeCache.kt create mode 100644 src/main/kotlin/repo/EssenceRecipeProvider.kt create mode 100644 src/main/kotlin/repo/ExpLadder.kt create mode 100644 src/main/kotlin/repo/ExpensiveItemCacheApi.kt create mode 100644 src/main/kotlin/repo/ExtraRecipeProvider.kt create mode 100644 src/main/kotlin/repo/HypixelStaticData.kt create mode 100644 src/main/kotlin/repo/ItemCache.kt create mode 100644 src/main/kotlin/repo/ItemNameLookup.kt create mode 100644 src/main/kotlin/repo/MiningRepoData.kt create mode 100644 src/main/kotlin/repo/ModernOverlaysData.kt create mode 100644 src/main/kotlin/repo/PetData.kt create mode 100644 src/main/kotlin/repo/Reforge.kt create mode 100644 src/main/kotlin/repo/ReforgeStore.kt create mode 100644 src/main/kotlin/repo/RepoDownloadManager.kt create mode 100644 src/main/kotlin/repo/RepoItemTypeCache.kt create mode 100644 src/main/kotlin/repo/RepoManager.kt create mode 100644 src/main/kotlin/repo/RepoModResourcePack.kt create mode 100644 src/main/kotlin/repo/SBItemStack.kt create mode 100644 src/main/kotlin/repo/recipes/GenericRecipeRenderer.kt create mode 100644 src/main/kotlin/repo/recipes/RecipeLayouter.kt create mode 100644 src/main/kotlin/repo/recipes/SBCraftingRecipeRenderer.kt create mode 100644 src/main/kotlin/repo/recipes/SBEssenceUpgradeRecipeRenderer.kt create mode 100644 src/main/kotlin/repo/recipes/SBForgeRecipeRenderer.kt create mode 100644 src/main/kotlin/util/AprilFoolsUtil.kt create mode 100644 src/main/kotlin/util/Base64Util.kt create mode 100644 src/main/kotlin/util/BazaarPriceStrategy.kt create mode 100644 src/main/kotlin/util/ChromaColourUtil.kt create mode 100644 src/main/kotlin/util/ClipboardUtils.kt create mode 100644 src/main/kotlin/util/CommonSoundEffects.kt create mode 100644 src/main/kotlin/util/DurabilityBarEvent.kt create mode 100644 src/main/kotlin/util/ErrorBoundary.kt create mode 100644 src/main/kotlin/util/ErrorUtil.kt create mode 100644 src/main/kotlin/util/FirmFormatters.kt create mode 100644 src/main/kotlin/util/FragmentGuiScreen.kt create mode 100644 src/main/kotlin/util/HoveredItemStack.kt create mode 100644 src/main/kotlin/util/IdentifierSerializer.kt create mode 100644 src/main/kotlin/util/IdentityCharacteristics.kt create mode 100644 src/main/kotlin/util/IntUtil.kt create mode 100644 src/main/kotlin/util/JvmUtil.kt create mode 100644 src/main/kotlin/util/LegacyFormattingCode.kt create mode 100644 src/main/kotlin/util/LegacyTagParser.kt create mode 100644 src/main/kotlin/util/LegacyTagWriter.kt create mode 100644 src/main/kotlin/util/LoadResource.kt create mode 100644 src/main/kotlin/util/Locraw.kt create mode 100644 src/main/kotlin/util/LogIfNull.kt create mode 100644 src/main/kotlin/util/MC.kt create mode 100644 src/main/kotlin/util/MinecraftDispatcher.kt create mode 100644 src/main/kotlin/util/MoulConfigFragment.kt create mode 100644 src/main/kotlin/util/MoulConfigUtils.kt create mode 100644 src/main/kotlin/util/Optionalutil.kt create mode 100644 src/main/kotlin/util/SBData.kt create mode 100644 src/main/kotlin/util/ScoreboardUtil.kt create mode 100644 src/main/kotlin/util/ScreenUtil.kt create mode 100644 src/main/kotlin/util/SequenceUtil.kt create mode 100644 src/main/kotlin/util/SkyBlockIsland.kt create mode 100644 src/main/kotlin/util/SkyblockId.kt create mode 100644 src/main/kotlin/util/SortedMapSerializer.kt create mode 100644 src/main/kotlin/util/StringUtil.kt create mode 100644 src/main/kotlin/util/TemplateUtil.kt create mode 100644 src/main/kotlin/util/TestUtil.kt create mode 100644 src/main/kotlin/util/TimeMark.kt create mode 100644 src/main/kotlin/util/Timer.kt create mode 100644 src/main/kotlin/util/WarpUtil.kt create mode 100644 src/main/kotlin/util/accessors/GetRectangle.kt create mode 100644 src/main/kotlin/util/accessors/chathud.kt create mode 100644 src/main/kotlin/util/asm/AsmAnnotationUtil.kt create mode 100644 src/main/kotlin/util/assertions.kt create mode 100644 src/main/kotlin/util/async/input.kt create mode 100644 src/main/kotlin/util/collections/InstanceList.kt create mode 100644 src/main/kotlin/util/collections/MutableMapWithMaxSize.kt create mode 100644 src/main/kotlin/util/collections/RangeUtil.kt create mode 100644 src/main/kotlin/util/collections/WeakCache.kt create mode 100644 src/main/kotlin/util/collections/listutil.kt create mode 100644 src/main/kotlin/util/colorconversion.kt create mode 100644 src/main/kotlin/util/compatloader/CompatLoader.kt create mode 100644 src/main/kotlin/util/compatloader/CompatMeta.kt create mode 100644 src/main/kotlin/util/customgui/CoordRememberingSlot.kt create mode 100644 src/main/kotlin/util/customgui/CustomGui.kt create mode 100644 src/main/kotlin/util/customgui/HasCustomGui.kt create mode 100644 src/main/kotlin/util/data/DataHolder.kt create mode 100644 src/main/kotlin/util/data/IDataHolder.kt create mode 100644 src/main/kotlin/util/data/MultiFileDataHolder.kt create mode 100644 src/main/kotlin/util/data/ProfileSpecificDataHolder.kt create mode 100644 src/main/kotlin/util/json/BlockPosSerializer.kt create mode 100644 src/main/kotlin/util/json/DashlessUUIDSerializer.kt create mode 100644 src/main/kotlin/util/json/FirmCodecs.kt create mode 100644 src/main/kotlin/util/json/InstantAsLongSerializer.kt create mode 100644 src/main/kotlin/util/json/KJsonOps.kt create mode 100644 src/main/kotlin/util/json/KJsonUtils.kt create mode 100644 src/main/kotlin/util/json/SingletonSerializableList.kt create mode 100644 src/main/kotlin/util/math/GChainReconciliation.kt create mode 100644 src/main/kotlin/util/math/Projections.kt create mode 100644 src/main/kotlin/util/mc/ArmorUtil.kt create mode 100644 src/main/kotlin/util/mc/CommonTextures.kt create mode 100644 src/main/kotlin/util/mc/FakeInventory.kt create mode 100644 src/main/kotlin/util/mc/FakeSlot.kt create mode 100644 src/main/kotlin/util/mc/FirmamentDataComponentTypes.kt create mode 100644 src/main/kotlin/util/mc/InitLevel.kt create mode 100644 src/main/kotlin/util/mc/IntrospectableItemModelManager.kt create mode 100644 src/main/kotlin/util/mc/InventoryUtil.kt create mode 100644 src/main/kotlin/util/mc/ItemUtil.kt create mode 100644 src/main/kotlin/util/mc/MCTabListAPI.kt create mode 100644 src/main/kotlin/util/mc/NbtItemData.kt create mode 100644 src/main/kotlin/util/mc/NbtPrism.kt create mode 100644 src/main/kotlin/util/mc/NbtUtil.kt create mode 100644 src/main/kotlin/util/mc/PlayerUtil.kt create mode 100644 src/main/kotlin/util/mc/SNbtFormatter.kt create mode 100644 src/main/kotlin/util/mc/ScreenUtil.kt create mode 100644 src/main/kotlin/util/mc/SkullItemData.kt create mode 100644 src/main/kotlin/util/mc/SlotUtils.kt create mode 100644 src/main/kotlin/util/mc/TolerantRegistriesOps.kt create mode 100644 src/main/kotlin/util/mc/asFakeServer.kt create mode 100644 src/main/kotlin/util/propertyutil.kt create mode 100644 src/main/kotlin/util/regex.kt create mode 100644 src/main/kotlin/util/render/CustomRenderLayers.kt create mode 100644 src/main/kotlin/util/render/DrawContextExt.kt create mode 100644 src/main/kotlin/util/render/FacingThePlayerContext.kt create mode 100644 src/main/kotlin/util/render/FirmamentShaders.kt create mode 100644 src/main/kotlin/util/render/LerpUtils.kt create mode 100644 src/main/kotlin/util/render/RenderCircleProgress.kt create mode 100644 src/main/kotlin/util/render/RenderContextDSL.kt create mode 100644 src/main/kotlin/util/render/RenderInWorldContext.kt create mode 100644 src/main/kotlin/util/render/TintedOverlayTexture.kt create mode 100644 src/main/kotlin/util/render/TranslatedScissors.kt create mode 100644 src/main/kotlin/util/skyblock/AbilityUtils.kt create mode 100644 src/main/kotlin/util/skyblock/DungeonUtil.kt create mode 100644 src/main/kotlin/util/skyblock/ItemType.kt create mode 100644 src/main/kotlin/util/skyblock/Rarity.kt create mode 100644 src/main/kotlin/util/skyblock/SBItemUtil.kt create mode 100644 src/main/kotlin/util/skyblock/SackUtil.kt create mode 100644 src/main/kotlin/util/skyblock/SkyBlockItems.kt create mode 100644 src/main/kotlin/util/skyblock/TabListAPI.kt create mode 100644 src/main/kotlin/util/textutil.kt create mode 100644 src/main/kotlin/util/uuid.kt create mode 100644 src/main/resources/assets/firmament/filters/screen/always.json create mode 100644 src/main/resources/assets/firmament/filters/screen/always.json.license create mode 100644 src/main/resources/assets/firmament/gui/anniversary_pig.xml create mode 100644 src/main/resources/assets/firmament/gui/button_editor_fragment.xml create mode 100644 src/main/resources/assets/firmament/gui/carnival/minesweeper_tutorial.xml create mode 100644 src/main/resources/assets/firmament/gui/config/category.xml create mode 100644 src/main/resources/assets/firmament/gui/config/macros/combos.xml create mode 100644 src/main/resources/assets/firmament/gui/config/macros/editor_combo.xml create mode 100644 src/main/resources/assets/firmament/gui/config/macros/editor_wheel.xml create mode 100644 src/main/resources/assets/firmament/gui/config/macros/index.xml create mode 100644 src/main/resources/assets/firmament/gui/config/macros/wheel.xml create mode 100644 src/main/resources/assets/firmament/gui/config/main.xml create mode 100644 src/main/resources/assets/firmament/gui/license_viewer/index.xml create mode 100644 src/main/resources/assets/firmament/gui/mining_block_info/index.xml create mode 100644 src/main/resources/assets/firmament/gui/npc_waypoints.xml create mode 100644 src/main/resources/assets/firmament/gui/pristine_profit.xml create mode 100644 src/main/resources/assets/firmament/gui/repo_reload.xml create mode 100644 src/main/resources/assets/firmament/logo.png create mode 100644 src/main/resources/assets/firmament/shaders/cape/parallax.fsh create mode 100644 src/main/resources/assets/firmament/shaders/circle_discard_color.fsh create mode 100644 src/main/resources/assets/firmament/shaders/core/rendertype_lines.fsh create mode 100644 src/main/resources/assets/firmament/shaders/core/rendertype_lines.json create mode 100644 src/main/resources/assets/firmament/shaders/core/rendertype_lines.vsh create mode 100644 src/main/resources/assets/firmament/textures/cape/REUSE.toml create mode 100644 src/main/resources/assets/firmament/textures/cape/firm_static.png create mode 100644 src/main/resources/assets/firmament/textures/cape/firmament_star.png create mode 100644 src/main/resources/assets/firmament/textures/cape/fsr_static.png create mode 100644 src/main/resources/assets/firmament/textures/cape/parallax_background.png create mode 100644 src/main/resources/assets/firmament/textures/cape/parallax_template.png create mode 100644 src/main/resources/assets/firmament/textures/gui/bar.png create mode 100644 src/main/resources/assets/firmament/textures/gui/circle.png create mode 100644 src/main/resources/assets/firmament/textures/gui/circle.png.license create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/completed_commission_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/generic_vanilla_widget.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/generic_vanilla_widget.png.mcmeta create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/hotm_perk_preset.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/inventory_button_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/item_rarity_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/selected_pet_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/slot_locked.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/player_inventory.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png.mcmeta create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_knob.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png.mcmeta create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png.mcmeta create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png.mcmeta create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/uuid_locked.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/widget/button_active.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_checked.png create mode 100644 src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_unchecked.png create mode 100644 src/main/resources/assets/firmament/textures/gui/waypoint_selected.png create mode 100644 src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png create mode 100644 src/main/resources/assets/firmament/textures/socials/discord.png create mode 100644 src/main/resources/assets/firmament/textures/socials/git.png create mode 100644 src/main/resources/assets/firmament/textures/socials/modrinth.png create mode 100644 src/main/resources/fabric.mod.json create mode 100644 src/main/resources/fabric.mod.json.license create mode 100644 src/main/resources/firmament.accesswidener create mode 100644 src/main/resources/firmament.accesswidener.license create mode 100644 src/main/resources/firmament.mixins.json create mode 100644 src/main/resources/firmament.mixins.json.license create mode 100644 src/main/resources/hotswap-agent.properties create mode 100644 src/main/resources/legacy_data/effects.json create mode 100644 src/main/resources/legacy_data/enchantments.json create mode 100644 src/main/resources/legacy_data/items.json create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/inventory_button_background.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/player_inventory.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png.mcmeta create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png.mcmeta create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png.mcmeta create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png create mode 100644 src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png.mcmeta create mode 100644 src/main/resources/resourcepacks/transparent_overlay/pack.mcmeta create mode 100644 src/test/kotlin/MixinTest.kt create mode 100644 src/test/kotlin/features/macros/KeyComboTrieCreation.kt create mode 100644 src/test/kotlin/root.kt create mode 100644 src/test/kotlin/testutil/AutoBootstrapExtension.kt create mode 100644 src/test/kotlin/testutil/ItemResources.kt create mode 100644 src/test/kotlin/util/ColorCodeTest.kt create mode 100644 src/test/kotlin/util/TextUtilText.kt create mode 100644 src/test/kotlin/util/math/GChainReconciliationTest.kt create mode 100644 src/test/kotlin/util/math/ProjectionsBoxTest.kt create mode 100644 src/test/kotlin/util/skyblock/AbilityUtilsTest.kt create mode 100644 src/test/kotlin/util/skyblock/ItemTypeTest.kt create mode 100644 src/test/kotlin/util/skyblock/SackUtilTest.kt create mode 100644 src/test/kotlin/util/skyblock/TabListAPITest.kt create mode 100644 src/test/kotlin/util/skyblock/TimestampTest.kt create mode 100644 src/test/resources/testdata/chat/all-chat.snbt create mode 100644 src/test/resources/testdata/chat/sacks/gain-and-lose-regular.snbt create mode 100644 src/test/resources/testdata/chat/sacks/gain-rotten-flesh.snbt create mode 100644 src/test/resources/testdata/items/aspect-of-the-void.snbt create mode 100644 src/test/resources/testdata/items/backpack-in-menu.snbt create mode 100644 src/test/resources/testdata/items/books/feather_falling.snbt create mode 100644 src/test/resources/testdata/items/diamond-pickaxe.snbt create mode 100644 src/test/resources/testdata/items/gemstone-gauntlet.snbt create mode 100644 src/test/resources/testdata/items/hyperion.snbt create mode 100644 src/test/resources/testdata/items/implosion-belt.snbt create mode 100644 src/test/resources/testdata/items/necron-boots.snbt create mode 100644 src/test/resources/testdata/items/pets/lion-item.snbt create mode 100644 src/test/resources/testdata/items/pets/mithril-golem-not-selected.snbt create mode 100644 src/test/resources/testdata/items/pets/rabbit-selected.snbt create mode 100644 src/test/resources/testdata/items/rune-in-sack.snbt create mode 100644 src/test/resources/testdata/items/titanium-drill.snbt create mode 100644 src/test/resources/testdata/tablist/dungeon_hub.snbt create mode 100644 src/texturePacks/README.md create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/Compat.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomScreenLayouts.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/HeadModelChooser.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/CastPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/GenericComponentPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PullingPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/SkullPredicate.kt create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/BuildExtraBlockStateModels.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/InsertExtraBlockModelDependencies.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ItemRenderStateExtraInfo.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyTexturePathsIntoArmorLayers.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceHeadModel.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/SupplyFakeModelPatch.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ExpandScreenBoundaries.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceAnvilScreen.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceForgingScreen.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceFurnaceBackgrounds.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceGenericBackgrounds.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplacePlayerBackgrounds.java create mode 100644 src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceTextColorInHandledScreen.java create mode 100644 symbols/build.gradle.kts create mode 100644 symbols/src/main/kotlin/Subscribe.kt create mode 100644 symbols/src/main/kotlin/process/CompatMetaProcessor.kt create mode 100644 symbols/src/main/kotlin/process/GameTestContainingClassProcessor.kt create mode 100644 symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt create mode 100644 testagent/build.gradle.kts create mode 100644 testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java create mode 100644 testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java create mode 100644 testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java create mode 100644 translations/en_us.json create mode 100644 translations/extra.json create mode 100644 translations/extra_zh_cn.json create mode 100644 translations/zh_cn.json create mode 100644 web/.gitignore create mode 100644 web/.vscode/extensions.json create mode 100644 web/.vscode/launch.json create mode 100644 web/REUSE.toml create mode 100644 web/astro.config.mjs create mode 100644 web/package.json create mode 100644 web/pnpm-lock.yaml create mode 100644 web/src/components/Hero.astro create mode 100644 web/src/components/NavBar.astro create mode 100644 web/src/components/NavLink.astro create mode 100644 web/src/env.d.ts create mode 100644 web/src/layouts/Base.astro create mode 100644 web/src/layouts/Content.astro create mode 100644 web/src/layouts/Head.astro create mode 100644 web/src/pages/docs/_texture-pack-format.md create mode 100644 web/src/pages/docs/texture-pack-format.astro create mode 100644 web/src/pages/index.astro create mode 100644 web/src/pages/texture-packs.astro create mode 100644 web/src/panorama.png create mode 100644 web/tailwind.config.mjs create mode 100644 web/tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..1c59d9d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: CC0-1.0 + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 4 +indent_style = tab +insert_final_newline = true +max_line_length = 120 + + +[*.kt] +ij_kotlin_name_count_to_use_star_import = 99999 +ij_kotlin_name_count_to_use_star_import_for_members = 99999 +ij_kotlin_imports_layout = *, |, kotlinx.**, kotlin.**, net.minecraft.**, moe.nea.firmament.**, |, $* +ij_kotlin_packages_to_use_import_on_demand = false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..344d93e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: CC0-1.0 + +repos: + - repo: https://github.com/fsfe/reuse-tool + rev: v4.0.3 + hooks: + - id: reuse + - repo: local + hooks: + - id: ordered_translations + name: "Check translation ordering" + language: script + files: translations/.* + entry: ./check-translation-ordering.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f9815e5 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,52 @@ + +# Contributing to Firmament + +Contributions are tentatively welcomed. The structure of the mod is probably not really transparent to newcomers, but if +you are interested, feel free to tackle any [issues](https://github.com/nea89o/Firmament/issues/) or create your own +features. + +## Community + +If you need any help contributing feel free to join the [discord]. This is where you can raise more casual issues. Note +that using the discord is not mandatory for contributing. If you don't want to join the discord, feel free to ask +questions in issues or to otherwise contact me. + +## State of Firmament + +Many of the foundations of Firmament are not yet fix. If you find things confusing or think some of the fundamental +building blocks of Firmament should be changed, feel free to raise an issue. More than likely there is no deeper reason +for something confusing, aside from this being a bit of a sloppy project. + +## Development workflow + +Firmament is a fabric mod so the development workflow is quite similar to any other fabric mod. To build you will need a +Java capable IDE (strongly recommend IntelliJ here), as well as Java 21. To contribute back to Firmament you will need +to create a [fork](https://github.com/nea89o/Firmament/fork). This is your own copy of Firmament which you can change. +You can load that fork using IntelliJs "New" -> "Project from version control" import option. You might need to +authenticate your GitHub account to IntelliJ during this process or at a later point in time. + +### JBR + +By default, Firmament tries to launch with hotswapping enabled in the devenv. This will fail if your JVM does not +support hotswapping. In that case you can either remove the hotswapping arguments, or you can use [JBR](jbr). You can +manually select JBR in your run configuration, after it has been generated by gradle. + +``` +-XX:+AllowEnhancedClassRedefinition -XX:HotswapAgent=external -javaagent:SOMEPATH +``` + +### Features + +Typically, for each new set of features you will create a branch and then create a pull request back to the main +Firmament repo. Note that Firmament makes use of commit names to generate a changelog. As such the first line of each +commit should be something that can be interpreted by an end user. If you want to make an internal change you can use +the `[no changelog]` tag inside your commit message body to hide a commit from the changelog. Try to make one commit for +each feature. Don't worry if you have any problems with your git history, your pull request will history will be +rewritten to be fixed (but it would help me if you can keep your commit history clean). + +[discord]: https://discord.gg/64pFP94AWA +[jbr]: https://github.com/JetBrains/JetBrainsRuntime/releases/tag/jbr-release-21.0.5b631.16 diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt new file mode 100644 index 0000000..137069b --- /dev/null +++ b/LICENSES/Apache-2.0.txt @@ -0,0 +1,73 @@ +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + +To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/LICENSES/CC-BY-4.0.txt b/LICENSES/CC-BY-4.0.txt new file mode 100644 index 0000000..13ca539 --- /dev/null +++ b/LICENSES/CC-BY-4.0.txt @@ -0,0 +1,156 @@ +Creative Commons Attribution 4.0 International + + Creative Commons Corporation (“Creative Commonsâ€) is not a law firm and does not provide legal services or legal advice. Distribution of Creative Commons public licenses does not create a lawyer-client or other relationship. Creative Commons makes its licenses and related information available on an “as-is†basis. Creative Commons gives no warranties regarding its licenses, any material licensed under their terms and conditions, or any related information. Creative Commons disclaims all liability for damages resulting from their use to the fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and conditions that creators and other rights holders may use to share original works of authorship and other material subject to copyright and certain other rights specified in the public license below. The following considerations are for informational purposes only, are not exhaustive, and do not form part of our licenses. + +Considerations for licensors: Our public licenses are intended for use by those authorized to give the public permission to use material in ways otherwise restricted by copyright and certain other rights. Our licenses are irrevocable. Licensors should read and understand the terms and conditions of the license they choose before applying it. Licensors should also secure all rights necessary before applying our licenses so that the public can reuse the material as expected. Licensors should clearly mark any material not subject to the license. This includes other CC-licensed material, or material used under an exception or limitation to copyright. More considerations for licensors. + +Considerations for the public: By using one of our public licenses, a licensor grants the public permission to use the licensed material under specified terms and conditions. If the licensor’s permission is not necessary for any reason–for example, because of any applicable exception or limitation to copyright–then that use is not regulated by the license. Our licenses grant only permissions under copyright and certain other rights that a licensor has authority to grant. Use of the licensed material may still be restricted for other reasons, including because others have copyright or other rights in the material. A licensor may make special requests, such as asking that all changes be marked or described. Although not required by our licenses, you are encouraged to respect those requests where reasonable. More considerations for the public. + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions. + +Section 1 – Definitions. + + a. Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. + + d. Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License. + + g. Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights under this Public License. + + i. Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning. + +Section 2 – Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to: + + A. reproduce and Share the Licensed Material, in whole or in part; and + + B. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions. + + 3. Term. The term of this Public License is specified in Section 6(a). + + 4. Media and formats; technical modifications allowed. The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material. + + 5. Downstream recipients. + + A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License. + + B. No downstream restrictions. You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material. + + 6. No endorsement. Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i). + +b. Other rights. + + 1. Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this Public License. + + 3. To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties. + +Section 3 – License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified form), You must: + + A. retain the following if it is supplied by the Licensor with the Licensed Material: + + i. identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of warranties; + + v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; + + B. indicate if You modified the Licensed Material and retain an indication of any previous modifications; and + + C. indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information. + + 3. If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's License You apply must not prevent recipients of the Adapted Material from complying with this Public License. + +Section 4 – Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database; + + b. if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database. +For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights. + +Section 5 – Disclaimer of Warranties and Limitation of Liability. + + a. Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You. + + b. To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You. + + c. The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability. + +Section 6 – Term and Termination. + + a. This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or + + 2. upon express reinstatement by the Licensor. + + c. For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License. + + d. For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License. + + e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. + +Section 7 – Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License. + +Section 8 – Interpretation. + + a. For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions. + + c. No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor. + + d. Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority. + +Creative Commons is not a party to its public licenses. Notwithstanding, Creative Commons may elect to apply one of its public licenses to material it publishes and in those instances will be considered the “Licensor.†Except for the limited purpose of indicating that material is shared under a Creative Commons public license or as otherwise permitted by the Creative Commons policies published at creativecommons.org/policies, Creative Commons does not authorize the use of the trademark “Creative Commons†or any other trademark or logo of Creative Commons without its prior written consent including, without limitation, in connection with any unauthorized modifications to any of its public licenses or any other arrangements, understandings, or agreements concerning use of licensed material. For the avoidance of doubt, this paragraph does not form part of the public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/LICENSES/CC0-1.0.txt b/LICENSES/CC0-1.0.txt new file mode 100644 index 0000000..0e259d4 --- /dev/null +++ b/LICENSES/CC0-1.0.txt @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/GPL-3.0-or-later.txt new file mode 100644 index 0000000..f6cdd22 --- /dev/null +++ b/LICENSES/GPL-3.0-or-later.txt @@ -0,0 +1,232 @@ +GNU GENERAL PUBLIC LICENSE +Version 3, 29 June 2007 + +Copyright © 2007 Free Software Foundation, Inc. + +Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. + +Preamble + +The GNU General Public License is a free, copyleft license for software and other kinds of works. + +The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. + +When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. + +To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. + +For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. + +Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. + +For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. + +Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. + +Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. + +The precise terms and conditions for copying, distribution and modification follow. + +TERMS AND CONDITIONS + +0. Definitions. + +“This License†refers to version 3 of the GNU General Public License. + +“Copyright†also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. + +“The Program†refers to any copyrightable work licensed under this License. Each licensee is addressed as “youâ€. “Licensees†and “recipients†may be individuals or organizations. + +To “modify†a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a “modified version†of the earlier work or a work “based on†the earlier work. + +A “covered work†means either the unmodified Program or a work based on the Program. + +To “propagate†a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. + +To “convey†a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. + +An interactive user interface displays “Appropriate Legal Notices†to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. + +1. Source Code. +The “source code†for a work means the preferred form of the work for making modifications to it. “Object code†means any non-source form of a work. + +A “Standard Interface†means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. + +The “System Libraries†of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A “Major Componentâ€, in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. + +The “Corresponding Source†for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. + +The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. + +The Corresponding Source for a work in source code form is that same work. + +2. Basic Permissions. +All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. + +You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. + +Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. + +3. Protecting Users' Legal Rights From Anti-Circumvention Law. +No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. + +When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. + +4. Conveying Verbatim Copies. +You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. + +You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. + +5. Conveying Modified Source Versions. +You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to “keep intact all noticesâ€. + + c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. + +A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an “aggregate†if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. + +6. Conveying Non-Source Forms. +You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: + + a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. + + d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. + +A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. + +A “User Product†is either (1) a “consumer productâ€, which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, “normally used†refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. + +“Installation Information†for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. + +If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). + +The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. + +Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. + +7. Additional Terms. +“Additional permissions†are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. + +When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. + +Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or authors of the material; or + + e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. + +All other non-permissive additional terms are considered “further restrictions†within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. + +If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. + +Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. + +8. Termination. +You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). + +However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. + +Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. + +Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. + +9. Acceptance Not Required for Having Copies. +You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. + +10. Automatic Licensing of Downstream Recipients. +Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. + +An “entity transaction†is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. + +You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. + +11. Patents. +A “contributor†is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's “contributor versionâ€. + +A contributor's “essential patent claims†are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, “control†includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. + +Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. + +In the following three paragraphs, a “patent license†is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To “grant†such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. + +If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. “Knowingly relying†means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. + +If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. + +A patent license is “discriminatory†if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. + +Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. + +12. No Surrender of Others' Freedom. +If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. + +13. Use with the GNU Affero General Public License. +Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. + +14. Revised Versions of this License. +The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License “or any later version†applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. + +If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. + +Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. + +15. Disclaimer of Warranty. +THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS†WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +16. Limitation of Liability. +IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +17. Interpretation of Sections 15 and 16. +If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright†line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about boxâ€. + +You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer†for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . + +The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..2071b23 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,9 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/REUSE.toml b/REUSE.toml new file mode 100644 index 0000000..9a6cf0f --- /dev/null +++ b/REUSE.toml @@ -0,0 +1,53 @@ +#SPDX-FileCopyrightText: 2024 Linnea Gräf +# +#SPDX-License-Identifier: CC0-1.0 + +version = 1 +SPDX-PackageName = "Firmament" +SPDX-PackageSupplier = "Linnea Gräf " +SPDX-PackageDownloadLocation = "https://github.com/nea89o/Firmament" + +[[annotations]] +path = ["**/*.kt", "**/*.java"] +SPDX-License-Identifier = "GPL-3.0-or-later" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["src/main/resources/**/*.png", "src/main/resources/**/*.mcmeta"] +SPDX-License-Identifier = "CC-BY-4.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["src/main/resources/assets/firmament/shaders/**/*"] +SPDX-License-Identifier = "GPL-3.0-or-later" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = "translations/*.json" +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["src/main/resources/assets/firmament/gui/**/*.xml"] +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = "**/*.gradle.kts" +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["**/META-INF/services/*"] +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["src/test/resources/testdata/**/*.snbt"] +SPDX-License-Identifier = "CC-BY-4.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["src/main/resources/legacy_data/*.json"] +SPDX-License-Identifier = "MIT" +SPDX-FileCopyrightText = ["PrismarineJS Minecraft Data"] diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts new file mode 100644 index 0000000..431a04e --- /dev/null +++ b/build-logic/build.gradle.kts @@ -0,0 +1,22 @@ +// SPDX-FileCopyrightText: 2023 Linnea Gräf +// +// SPDX-License-Identifier: CC0-1.0 + +plugins { + `kotlin-dsl` + kotlin("jvm") version "2.0.21" +} +repositories { + mavenCentral() + gradlePluginPortal() + maven { + name = "jitpack" + url = uri("https://jitpack.io") + } +} +dependencies { + implementation("com.github.romangraef:neaslicenseextractificator:1.1.0") + api("com.gradleup.shadow:shadow-gradle-plugin:9.0.0-rc1") + implementation("net.fabricmc:access-widener:2.1.0") + implementation("com.google.code.gson:gson:2.10.1") +} diff --git a/build-logic/gradle/wrapper b/build-logic/gradle/wrapper new file mode 100644 index 0000000..3232fe4 --- /dev/null +++ b/build-logic/gradle/wrapper @@ -0,0 +1 @@ +../../gradle/wrapper \ No newline at end of file diff --git a/build-logic/gradlew b/build-logic/gradlew new file mode 100644 index 0000000..faf9300 --- /dev/null +++ b/build-logic/gradlew @@ -0,0 +1,251 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/build-logic/gradlew.bat b/build-logic/gradlew.bat new file mode 100644 index 0000000..9d21a21 --- /dev/null +++ b/build-logic/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 0000000..0108b7a --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,8 @@ +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} +rootProject.name = "firm-build-logic" diff --git a/build-logic/src/main/kotlin/EnvFile.kt b/build-logic/src/main/kotlin/EnvFile.kt new file mode 100644 index 0000000..ceec763 --- /dev/null +++ b/build-logic/src/main/kotlin/EnvFile.kt @@ -0,0 +1,13 @@ + +import java.io.File + +fun parseEnvFile(file: File): Map { + if (!file.exists()) return mapOf() + val map = mutableMapOf() + for (line in file.readText().lines()) { + if (line.isEmpty() || line.startsWith("#")) continue + val parts = line.split("=", limit = 2) + map[parts[0]] = parts.getOrNull(1) ?: "" + } + return map +} diff --git a/build-logic/src/main/kotlin/FabricModTransform.kt b/build-logic/src/main/kotlin/FabricModTransform.kt new file mode 100644 index 0000000..53affbe --- /dev/null +++ b/build-logic/src/main/kotlin/FabricModTransform.kt @@ -0,0 +1,80 @@ +import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer +import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext +import com.google.gson.Gson +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive +import java.io.Serializable +import net.fabricmc.accesswidener.AccessWidenerReader +import net.fabricmc.accesswidener.AccessWidenerWriter +import org.apache.tools.zip.ZipEntry +import org.apache.tools.zip.ZipOutputStream +import org.gradle.api.file.FileTreeElement +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.Internal + +open class FabricModTransform : ResourceTransformer { + + enum class AccessWidenerInclusion : Serializable { + ALL, + NONE, + } + + @get:Input + var mergeAccessWideners: AccessWidenerInclusion = AccessWidenerInclusion.ALL + + @get:Internal + internal var mergedFmj: JsonObject? = null + + @get:Internal + internal val foundAccessWideners = AccessWidenerWriter() + + @get:Internal + internal var foundAnyAccessWidener = false + + override fun canTransformResource(element: FileTreeElement): Boolean { + if (mergeAccessWideners == AccessWidenerInclusion.ALL && element.name.endsWith(".accesswidener")) + return true + return element.path == "fabric.mod.json" + } + + override fun transform(context: TransformerContext) { + if (context.path.endsWith(".accesswidener")) { + foundAnyAccessWidener = true + // TODO: allow filtering for only those mentioned in a fabric.mod.json, potentially + context.inputStream.use { stream -> + AccessWidenerReader(foundAccessWideners).read(stream.bufferedReader()) + } + return + } + // TODO: mixins.json relocations + val fmj = context.inputStream.use { stream -> + Gson().fromJson(stream.bufferedReader(), JsonObject::class.java) + } + val mergedFmj = this.mergedFmj + println("${fmj["id"]} is first? ${mergedFmj == null}") + if (mergedFmj == null) { + this.mergedFmj = fmj + } else { + // TODO: merge stuff + } + } + + override fun hasTransformedResource(): Boolean { + return mergedFmj != null + } + + override fun modifyOutputStream(os: ZipOutputStream, preserveFileTimestamps: Boolean) { + val mergedFmj = mergedFmj!! + if (foundAnyAccessWidener) { + val awFile = mergedFmj["accessWidener"] + require(awFile is JsonPrimitive && awFile.isString) + os.putNextEntry(ZipEntry(awFile.asString)) + os.write(foundAccessWideners.write()) + os.closeEntry() + } + os.putNextEntry(ZipEntry("fabric.mod.json")) + os.write(mergedFmj.toString().toByteArray()) + os.closeEntry() + } +} diff --git a/build-logic/src/main/kotlin/InnerJarsUnpacker.kt b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt new file mode 100644 index 0000000..de06467 --- /dev/null +++ b/build-logic/src/main/kotlin/InnerJarsUnpacker.kt @@ -0,0 +1,70 @@ +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive +import java.io.File +import java.util.zip.ZipInputStream +import org.gradle.api.DefaultTask +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.OutputFiles +import org.gradle.api.tasks.TaskAction +import kotlin.io.path.createDirectories +import kotlin.io.path.outputStream + +abstract class InnerJarsUnpacker : DefaultTask() { + @get:InputFiles + abstract val inputJars: ConfigurableFileCollection + + @get:OutputDirectory + abstract val outputDir: DirectoryProperty + + private fun getFabricModJson(inputFile: File): JsonObject { + inputFile.inputStream().use { + val zis = ZipInputStream(it) + while (true) { + val entry = zis.nextEntry ?: error("Failed to find fabric.mod.json") + if (entry.name == "fabric.mod.json") { + return Gson().fromJson(zis.reader(), JsonObject::class.java) + } + } + } + } + + @TaskAction + fun unpack() { + inputJars.forEach { inputFile -> + val fabricModObject = getFabricModJson(inputFile) + val jars = fabricModObject["jars"] as? JsonArray ?: error("No jars to unpack in $inputFile") + val jarPaths = jars.map { + ((it as? JsonObject)?.get("file") as? JsonPrimitive)?.asString + ?: error("Invalid Jar $it in $inputFile") + } + extractJars(inputFile, jarPaths) + } + } + + private fun extractJars(inputFile: File, jarPaths: List) { + val outputFile = outputDir.get().asFile.toPath() + val jarPathSet = jarPaths.toMutableSet() + inputFile.inputStream().use { + val zis = ZipInputStream(it) + while (true) { + val entry = zis.nextEntry ?: break + if (jarPathSet.remove(entry.name)) { + val resolvedPath = outputFile.resolve(entry.name) + resolvedPath.parent.createDirectories() + resolvedPath.outputStream().use { os -> + zis.copyTo(os) + } + } + } + } + if (jarPathSet.isNotEmpty()) { + error("Could not extract all jars: $jarPathSet") + } + } +} diff --git a/build-logic/src/main/kotlin/RepoDownload.kt b/build-logic/src/main/kotlin/RepoDownload.kt new file mode 100644 index 0000000..42a09b3 --- /dev/null +++ b/build-logic/src/main/kotlin/RepoDownload.kt @@ -0,0 +1,41 @@ +import java.net.URI +import java.util.zip.ZipInputStream +import org.gradle.api.DefaultTask +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.provider.Property +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction + +abstract class RepoDownload : DefaultTask() { + @get:Input + abstract val hash: Property + + @get:OutputDirectory + abstract val outputDirectory: DirectoryProperty + + init { + outputDirectory.convention(project.layout.buildDirectory.dir("extracted-test-repo")) + } + + @TaskAction + fun performDownload() { + val outputDir = outputDirectory.asFile.get().absoluteFile + outputDir.mkdirs() + URI("https://github.com/notEnoughUpdates/notEnoughUpdates-rEPO/archive/${hash.get()}.zip").toURL().openStream() + .let(::ZipInputStream) + .use { zipInput -> + while (true) { + val entry = zipInput.nextEntry ?: break + val destination = outputDir.resolve( + entry.name.substringAfter('/')).absoluteFile + require(outputDir in generateSequence(destination) { it.parentFile }) + if (entry.isDirectory) continue + destination.parentFile.mkdirs() + destination.outputStream().use { output -> + zipInput.copyTo(output) + } + } + } + } +} diff --git a/build-logic/src/main/kotlin/firmament.base.gradle.kts b/build-logic/src/main/kotlin/firmament.base.gradle.kts new file mode 100644 index 0000000..8c512a4 --- /dev/null +++ b/build-logic/src/main/kotlin/firmament.base.gradle.kts @@ -0,0 +1 @@ +group = "moe.nea.firmament" diff --git a/build-logic/src/main/kotlin/firmament.common.gradle.kts b/build-logic/src/main/kotlin/firmament.common.gradle.kts new file mode 100644 index 0000000..a359b3d --- /dev/null +++ b/build-logic/src/main/kotlin/firmament.common.gradle.kts @@ -0,0 +1,2 @@ +apply(plugin = "firmament.base") +apply(plugin = "firmament.repositories") diff --git a/build-logic/src/main/kotlin/firmament.license-management.gradle.kts b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts new file mode 100644 index 0000000..0a2626b --- /dev/null +++ b/build-logic/src/main/kotlin/firmament.license-management.gradle.kts @@ -0,0 +1,5 @@ +apply(plugin = "moe.nea.licenseextractificator") + +configure { + addExtraLicenseMatchers() +} diff --git a/build-logic/src/main/kotlin/firmament.repositories.gradle.kts b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts new file mode 100644 index 0000000..07a5709 --- /dev/null +++ b/build-logic/src/main/kotlin/firmament.repositories.gradle.kts @@ -0,0 +1,46 @@ +repositories { + mavenCentral() + maven("https://maven.terraformersmc.com/releases/") + maven("https://maven.shedaniel.me") + maven("https://maven.fabricmc.net") + maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") + maven("https://api.modrinth.com/maven") { + content { + includeGroup("maven.modrinth") + } + } + maven("https://repo.sleeping.town") { + content { + includeGroup("com.unascribed") + } + } + ivy("https://github.com/HotswapProjects/HotswapAgent/releases/download") { + patternLayout { + artifact("[revision]/[artifact]-[revision].[ext]") + } + content { + includeGroup("virtual.github.hotswapagent") + } + metadataSources { + artifact() + } + } + maven("https://server.bbkr.space/artifactory/libs-release") + maven("https://repo.nea.moe/releases") + maven("https://maven.notenoughupdates.org/releases") + maven("https://repo.nea.moe/mirror") + maven("https://jitpack.io/") { + content { + includeGroupByRegex("(com|io)\\.github\\..+") + excludeModule("io.github.cottonmc", "LibGui") + } + } + maven("https://repo.hypixel.net/repository/Hypixel/") + maven("https://maven.azureaaron.net/snapshots") + maven("https://maven.azureaaron.net/releases") + maven("https://www.cursemaven.com") + maven("https://maven.isxander.dev/releases") { + name = "Xander Maven" + } + mavenLocal() +} diff --git a/build-logic/src/main/kotlin/licenseinfo.kt b/build-logic/src/main/kotlin/licenseinfo.kt new file mode 100644 index 0000000..50e4593 --- /dev/null +++ b/build-logic/src/main/kotlin/licenseinfo.kt @@ -0,0 +1,144 @@ +// SPDX-FileCopyrightText: 2023 Linnea Gräf +// +// SPDX-License-Identifier: CC0-1.0 + +import moe.nea.licenseextractificator.LicenseExtension + +fun LicenseExtension.addExtraLicenseMatchers() { + solo { + name = "Firmament" + description = "A Hypixel SkyBlock mod" + developer("Linnea Gräf") { + webPresence = "https://nea.moe/" + } + spdxLicense.`GPL-3-0-or-later`() + webPresence = "https://git.nea.moe/nea/Firmament/" + } + match { + if (group == "net.minecraft") useLicense { + name = "Minecraft" + description = "Minecraft - The critically acclaimed video game" + license("All Rights Reserved", "https://www.minecraft.net/en-us/eula") + developer("Mojang") { + webPresence = "https://mojang.com" + } + webPresence = "https://www.minecraft.net/en-us" + } + if (module == "architectury") useLicense { + name = "Architectury API" + description = "An intermediary api aimed at easing development of multiplatform mods." + spdxLicense.`LGPL-3-0-or-later`() + developer("Architectury") { + webPresence = "https://docs.architectury.dev/" + } + webPresence = "https://github.com/architectury/architectury-api" + } + if (module.startsWith("RoughlyEnoughItems")) useLicense { + name = module + description = "Your recipe viewer mod for 1.13+." + spdxLicense.MIT() + developer("Shedaniel") { + webPresence = "https://shedaniel.me/" + } + webPresence = "https://github.com/shedaniel/RoughlyEnoughItems" + } + if (module == "cloth-config") useLicense { + name = "Cloth Config" + description = "Client sided configuration API" + spdxLicense.`LGPL-3-0-or-later`() + developer("Shedaniel") { + webPresence = "https://shedaniel.me/" + } + webPresence = "https://github.com/shedaniel/cloth-config" + } + if (module == "basic-math") useLicense { + name = "Cloth BasicMath" + description = "Basic Math Operations" + spdxLicense.Unlicense() + developer("Shedaniel") { + webPresence = "https://shedaniel.me/" + } + webPresence = "https://github.com/shedaniel/cloth-basic-math" + } + if (module == "fabric-language-kotlin") useLicense { + name = "Fabric Language Kotlin" + description = "Kotlin Language Support for Fabric mods" + webPresence = "https://github.com/FabricMC/fabric-language-kotlin" + spdxLicense.`Apache-2-0`() + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + } + if (group == "com.mojang") useLicense { + name = module + description = "Mojang library packaged by Minecraft" + } + } + module("net.fabricmc", "yarn") { + name = "Yarn" + description = "Libre Minecraft mappings, free to use for everyone. No exceptions." + spdxLicense.`CC0-1-0`() + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + webPresence = "https://github.com/FabricMC/yarn/" + } + module("com.mojang", "datafixerupper") { + name = "DataFixerUpper" + description = + "A set of utilities designed for incremental building, merging and optimization of data transformations." + spdxLicense.MIT() + developer("Mojang") { + webPresence = "https://mojang.com" + } + webPresence = "https://github.com/Mojang/DataFixerUpper" + } + module("com.mojang", "brigadier") { + name = "Brigadier" + description = "Brigadier is a command parser & dispatcher, designed and developed for Minecraft: Java Edition." + spdxLicense.MIT() + developer("Mojang") { + webPresence = "https://mojang.com" + } + webPresence = "https://github.com/Mojang/brigadier" + } + module("net.fabricmc", "tiny-remapper") { + name = "Tiny Remapper" + description = "Tiny JAR remapping tool" + spdxLicense.`LGPL-3-0-or-later`() + webPresence = "https://github.com/FabricMC/tiny-remapper" + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + } + module("net.fabricmc", "sponge-mixin") { + name = "Mixin" + description = "Mixin is a trait/mixin framework for Java using ASM" + spdxLicense.MIT() + webPresence = "https://github.com/FabricMC/mixin" + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + developer("SpongePowered") { + webPresence = "https://spongepowered.org/" + } + } + module("net.fabricmc", "tiny-mappings-parser") { + name = "Tiny Mappings Parser" + webPresence = "https://github.com/fabricMC/tiny-mappings-parser" + description = "Library for parsing .tiny mapping files" + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + spdxLicense.`Apache-2-0`() + } + module("net.fabricmc", "fabric-loader") { + name = "Fabric Loader" + description = " Fabric's mostly-version-independent mod loader." + spdxLicense.`Apache-2-0`() + developer("FabricMC") { + webPresence = "https://fabricmc.net/" + } + webPresence = "https://github.com/FabricMC/fabric-loader/" + } +} diff --git a/build-logic/src/main/kotlin/lookupversion.kt b/build-logic/src/main/kotlin/lookupversion.kt new file mode 100644 index 0000000..8a7c2de --- /dev/null +++ b/build-logic/src/main/kotlin/lookupversion.kt @@ -0,0 +1,25 @@ +fun execString(vararg args: String): String { + val pb = ProcessBuilder(*args) + .redirectOutput(ProcessBuilder.Redirect.PIPE) + .start() + pb.waitFor() + return pb.inputStream.readAllBytes().decodeToString().trim() +} + +private val tag = "([0-9.]+)(?:\\+[^-]*)?".toRegex() +private val tagOffset = "([0-9.]+)(?:\\+.*)?-([0-9]+)-(.+)".toRegex() + +inline fun Regex.useMatcher(string: String, block: (MatchResult) -> T): T? { + return matchEntire(string)?.let(block) +} + +fun getGitTagInfo(mcVersion: String): String { + val str = execString("git", "describe", "--tags", "HEAD") + tag.useMatcher(str) { + return it.groupValues[1] + "+mc$mcVersion" + } + tagOffset.useMatcher(str) { + return it.groupValues[1] + "-dev+mc$mcVersion+" + it.groupValues[3] + } + return "nogitversion+mc$mcVersion" +} diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..c8bdfdb --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,521 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf + * SPDX-FileCopyrightText: 2024 Linnea Gräf + * + * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar +import com.google.common.hash.Hashing +import com.google.devtools.ksp.gradle.KspAATask +import com.google.gson.Gson +import com.google.gson.JsonObject +import moe.nea.licenseextractificator.LicenseDiscoveryTask +import moe.nea.mcautotranslations.gradle.CollectTranslations +import net.fabricmc.loom.LoomGradleExtension +import org.apache.tools.ant.taskdefs.condition.Os +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import java.nio.charset.StandardCharsets +import java.util.* + +plugins { + java + `maven-publish` + alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.plugin.serialization) + alias(libs.plugins.kotlin.plugin.powerassert) + alias(libs.plugins.kotlin.plugin.ksp) + // alias(libs.plugins.loom) + alias(libs.plugins.shadow) apply false + // TODO: use arch loom once they update to 1.8 + id("fabric-loom") version "1.10.1" + id("firmament.common") + id("firmament.license-management") + alias(libs.plugins.mcAutoTranslations) +} + +version = getGitTagInfo(libs.versions.minecraft.get()) + +java { + withSourcesJar() + toolchain { + languageVersion.set(JavaLanguageVersion.of(21)) + } +} + +loom { + mixin.useLegacyMixinAp.set(false) +} + +tasks.withType(KotlinCompile::class) { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_21) + } +} + +kotlin { + sourceSets.all { + languageSettings { + enableLanguageFeature("BreakContinueInInlineLambdas") + } + } +} +fun String.capitalizeN() = replaceFirstChar { it.uppercaseChar() } +// Usually a normal sync takes care of this, but in CI everything needs to run in one shot, so we need to improvise. +val unpackAllJars by tasks.registering +fun innerJarsOf(name: String, dependency: Dependency): Provider { + val task = tasks.create("unpackInnerJarsFor${name.capitalizeN()}", InnerJarsUnpacker::class) { + this.inputJars.setFrom(files(configurations.detachedConfiguration(dependency))) + this.outputDir.set(layout.buildDirectory.dir("unpackedJars/$name").also { + it.get().asFile.mkdirs() + }) + } + unpackAllJars { dependsOn(task) } + return project.provider { + project.files(task).asFileTree + } +} + +val collectTranslations by tasks.registering(CollectTranslations::class) { + this.baseTranslations.from(file("translations/en_us.json")) + this.baseTranslations.from(file("translations/extra.json")) + this.classes.from(sourceSets.main.get().kotlin.classesDirectory) +} + +val shadowJar = tasks.register("shadowJar", ShadowJar::class) +val mergedSourceSetsJar = tasks.register("mergedSourceSetsJar", ShadowJar::class) + +val compatSourceSets: MutableSet = mutableSetOf() +fun createIsolatedSourceSet(name: String, path: String = "compat/$name", isEnabled: Boolean = true): SourceSet { + val ss = sourceSets.create(name) { + this.java.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) + this.kotlin.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) + } + val mainSS = sourceSets.main.get() + val upperName = ss.name.capitalizeN() + afterEvaluate { + tasks.named("ksp${upperName}Kotlin", KspAATask::class) { + this.commandLineArgumentProviders.add { // TODO: update https://github.com/google/ksp/issues/2075 + listOf("firmament.sourceset=${ss.name}") + } + } + tasks.named("compile${upperName}Kotlin", KotlinCompile::class) { + this.enabled = isEnabled + } + tasks.named("compile${upperName}Java", JavaCompile::class) { + this.enabled = isEnabled + } + } + compatSourceSets.add(ss) + loom.createRemapConfigurations(ss) + if (!isEnabled) { + ss.output.files.forEach { it.deleteRecursively() } + return ss + } + configurations { + (ss.implementationConfigurationName) { + extendsFrom(getByName(mainSS.compileClasspathConfigurationName)) + } + (ss.annotationProcessorConfigurationName) { + extendsFrom(getByName(mainSS.annotationProcessorConfigurationName)) + } + (mainSS.runtimeOnlyConfigurationName) { + if (isEnabled) + extendsFrom(getByName(ss.runtimeClasspathConfigurationName)) + } + ("ksp$upperName") { + extendsFrom(ksp.get()) + } + } + dependencies { + if (isEnabled) + runtimeOnly(ss.output) + (ss.implementationConfigurationName)(project.files(tasks.compileKotlin.map { it.destinationDirectory })) + (ss.implementationConfigurationName)(project.files(tasks.compileJava.map { it.destinationDirectory })) + } + mergedSourceSetsJar.configure { + from(ss.output) + } + // TODO: figure out why inheritances are not being respected by tiny kotlin names + tasks.remapJar { + classpath.from(configurations.getByName(ss.compileClasspathConfigurationName)) + } + collectTranslations { + this.classes.from(ss.kotlin.classesDirectory) + } + return ss +} + +val SourceSet.modImplementationConfigurationName + get() = + loom.remapConfigurations.find { + it.targetConfigurationName.get() == this.implementationConfigurationName + }!!.sourceConfiguration +val SourceSet.modRuntimeOnlyConfigurationName + get() = + loom.remapConfigurations.find { + it.targetConfigurationName.get() == this.runtimeOnlyConfigurationName + }!!.sourceConfiguration + +val shadowMe by configurations.creating { + exclude(group = "org.jetbrains.kotlin") + exclude(group = "org.jetbrains.kotlinx") + exclude(group = "org.jetbrains") + exclude(module = "gson") + exclude(group = "org.slf4j") +} +val transInclude by configurations.creating { + exclude(group = "com.mojang") + exclude(group = "org.jetbrains.kotlin") + exclude(group = "org.jetbrains.kotlinx") + isTransitive = true +} + +val hotswap by configurations.creating { + isVisible = false +} + +val nonModImplentation by configurations.creating { + configurations.implementation.get().extendsFrom(this) +} +val testAgent by configurations.creating { + isVisible = false +} + + +val configuredSourceSet = createIsolatedSourceSet( + "configured", + isEnabled = false +) // Wait for update (also low prio, because configured sucks) +val sodiumSourceSet = createIsolatedSourceSet("sodium", isEnabled = false) +val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false) // TODO: Wait for update +val yaclSourceSet = createIsolatedSourceSet("yacl") +val explosiveEnhancementSourceSet = + createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port +val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender") +val jadeSourceSet = createIsolatedSourceSet("jade") +val modmenuSourceSet = createIsolatedSourceSet("modmenu") +val reiSourceSet = createIsolatedSourceSet("rei") +val moulconfigSourceSet = createIsolatedSourceSet("moulconfig") +val customTexturesSourceSet = createIsolatedSourceSet("texturePacks", "texturePacks") + +dependencies { + // Minecraft dependencies + "minecraft"(libs.minecraft) + "mappings"("net.fabricmc:yarn:${libs.versions.yarn.get()}:v2") + + // Hotswap Dependency + hotswap(libs.hotswap) + + // Fabric dependencies + modImplementation(libs.fabric.loader) + modImplementation(libs.fabric.kotlin) + modImplementation(libs.moulconfig) + modImplementation(libs.manninghamMills) + modImplementation(libs.basicMath) + include(libs.basicMath) + (modmenuSourceSet.modImplementationConfigurationName)(libs.modmenu) + (explosiveEnhancementSourceSet.modImplementationConfigurationName)(libs.explosiveenhancement) + modImplementation(libs.hypixelmodapi) + include(libs.hypixelmodapi.fabric) + compileOnly(projects.javaplugin) + annotationProcessor(projects.javaplugin) + nonModImplentation("com.google.auto.service:auto-service-annotations:1.1.1") + ksp("dev.zacsweers.autoservice:auto-service-ksp:1.2.0") + include(libs.manninghamMills) + shadowMe(libs.moulconfig) + + annotationProcessor(libs.mixinextras) + nonModImplentation(libs.mixinextras) + include(libs.mixinextras) + + nonModImplentation(libs.nealisp) + shadowMe(libs.nealisp) + + modCompileOnly(libs.fabric.api) + modRuntimeOnly(libs.fabric.api.deprecated) + modCompileOnly(libs.jarvis.api) + include(libs.jarvis.fabric) + + (wildfireGenderSourceSet.modImplementationConfigurationName)(libs.femalegender) + (wildfireGenderSourceSet.implementationConfigurationName)(customTexturesSourceSet.output) + (configuredSourceSet.modImplementationConfigurationName)(libs.configured) + (sodiumSourceSet.modImplementationConfigurationName)(libs.sodium) + (jadeSourceSet.modImplementationConfigurationName)(libs.jade) + + (citResewnSourceSet.modImplementationConfigurationName)( + innerJarsOf("citresewn", dependencies.create(libs.citresewn.get())) + ) + (citResewnSourceSet.modImplementationConfigurationName)(libs.citresewn) + (yaclSourceSet.modImplementationConfigurationName)(libs.yacl) + + // Actual dependencies + (reiSourceSet.modImplementationConfigurationName)(libs.rei.api) + (reiSourceSet.modRuntimeOnlyConfigurationName)(libs.rei.fabric) + nonModImplentation(libs.repoparser) + shadowMe(libs.repoparser) + fun ktor(mod: String) = "io.ktor:ktor-$mod-jvm:${libs.versions.ktor.get()}" + // TODO: get rid of ktor. lowkey ballooning file size and like not neccessary at all for what i am doing.0 + transInclude(nonModImplentation(ktor("client-core"))!!) + transInclude(nonModImplentation(ktor("client-java"))!!) + transInclude(nonModImplentation(ktor("serialization-kotlinx-json"))!!) + transInclude(nonModImplentation(ktor("client-content-negotiation"))!!) + transInclude(nonModImplentation(ktor("client-encoding"))!!) + transInclude(nonModImplentation(ktor("client-logging"))!!) + + // Dev environment preinstalled mods + modLocalRuntime(libs.bundles.runtime.required) + modLocalRuntime(libs.bundles.runtime.optional) + modLocalRuntime(libs.jarvis.fabric) + modLocalRuntime(libs.modmenu) + + transInclude.resolvedConfiguration.resolvedArtifacts.forEach { + include(it.moduleVersion.id.toString()) + } + + + testImplementation("net.fabricmc:fabric-loader-junit:${libs.versions.fabric.loader.get()}") + testAgent(files(tasks.getByPath(":testagent:jar"))) + + implementation(projects.symbols) + ksp(projects.symbols) +} + +loom { + clientOnlyMinecraftJar() + accessWidenerPath.set(project.file("src/main/resources/firmament.accesswidener")) + runs { + removeIf { it.name != "client" } + configureEach { + property("fabric.log.level", "info") + property("firmament.debug", "true") + property( + "firmament.classroots", + compatSourceSets.joinToString(File.pathSeparator) { + File(it.output.classesDirs.asPath).absolutePath + }) + property("mixin.debug.export", "true") + property("mixin.debug", "true") + + parseEnvFile(file(".env")).forEach { (t, u) -> + environmentVariable(t, u) + } + parseEnvFile(file(".properties")).forEach { (t, u) -> + property(t, u) + } + } + named("client") { + property("devauth.enabled", "true") + vmArg("-ea") +// vmArg("-XX:+AllowEnhancedClassRedefinition") +// vmArg("-XX:HotswapAgent=external") +// vmArg("-javaagent:${hotswap.resolve().single().absolutePath}") + } + } +} + +mcAutoTranslations { + translationFunction.set("moe.nea.firmament.util.tr") + translationFunctionResolved.set("moe.nea.firmament.util.trResolved") +} + +val downloadTestRepo by tasks.registering(RepoDownload::class) { + this.hash.set(project.property("firmament.compiletimerepohash") as String) +} + +val updateTestRepo by tasks.registering { + outputs.upToDateWhen { false } + doLast { + val propertiesFile = rootProject.file("gradle.properties") + val json = + Gson().fromJson( + uri("https://api.github.com/repos/NotEnoughUpdates/NotEnoughUpdates-REPO/branches/master") + .toURL().readText(), JsonObject::class.java + ) + val latestSha = json["commit"].asJsonObject["sha"].asString + var text = propertiesFile.readText() + text = text.replace( + "firmament\\.compiletimerepohash=[^\n]*".toRegex(), + "firmament.compiletimerepohash=$latestSha" + ) + propertiesFile.writeText(text) + } +} + + +tasks.test { + val wd = file("build/testWorkDir") + workingDir(wd) + dependsOn(downloadTestRepo) + dependsOn(testAgent) + doFirst { + wd.mkdirs() + wd.resolve("config").deleteRecursively() + systemProperty( + "firmament.testrepo", + downloadTestRepo.flatMap { it.outputDirectory.asFile }.map { it.absolutePath }.get() + ) + jvmArgs("-javaagent:${testAgent.singleFile.absolutePath}") + } + systemProperty("jdk.attach.allowAttachSelf", "true") + jvmArgs("-XX:+EnableDynamicAgentLoading") + systemProperties( + "kotest.framework.classpath.scanning.config.disable" to true, + "kotest.framework.config.fqn" to "moe.nea.firmament.test.testutil.KotestPlugin", + ) + useJUnitPlatform() +} + + +tasks.withType { + this.sourceCompatibility = "21" + this.targetCompatibility = "21" + options.encoding = "UTF-8" + val module = "ALL-UNNAMED" + options.forkOptions.jvmArgs!!.addAll( + listOf( + "--add-exports=jdk.compiler/com.sun.tools.javac.util=$module", + "--add-exports=jdk.compiler/com.sun.tools.javac.comp=$module", + "--add-exports=jdk.compiler/com.sun.tools.javac.tree=$module", + "--add-exports=jdk.compiler/com.sun.tools.javac.api=$module", + "--add-exports=jdk.compiler/com.sun.tools.javac.code=$module", + ) + ) + options.isFork = true + afterEvaluate { + options.compilerArgs.add("-Xplugin:IntermediaryNameReplacement mappingFile=${LoomGradleExtension.get(project).mappingsFile.absolutePath} sourceNs=named") + } +} + +tasks.jar { + destinationDirectory.set(layout.buildDirectory.dir("badjars")) + archiveClassifier.set("slim") +} +mergedSourceSetsJar.configure { + from(zipTree(tasks.jar.flatMap { it.archiveFile })) + destinationDirectory.set(layout.buildDirectory.dir("badjars")) + archiveClassifier.set("merged-source-sets") + mergeServiceFiles() +} +shadowJar.configure { + from(zipTree(tasks.remapJar.flatMap { it.archiveFile })) + configurations = listOf(shadowMe) + archiveClassifier.set("") + relocate("io.github.moulberry.repo", "moe.nea.firmament.deps.repo") + relocate("io.github.notenoughupdates.moulconfig", "moe.nea.firmament.deps.moulconfig") + mergeServiceFiles() + transform() +} + +tasks.remapJar { +// injectAccessWidener.set(true) + inputFile.set(mergedSourceSetsJar.flatMap { it.archiveFile }) + dependsOn(mergedSourceSetsJar) + destinationDirectory.set(layout.buildDirectory.dir("badjars")) + archiveClassifier.set("remapped") +} + +tasks.assemble { dependsOn(shadowJar) } + + +tasks.processResources { + val replacements = listOf( + "version" to project.version.toString(), + "minecraft_version" to libs.versions.minecraft.get(), + "fabric_kotlin_version" to libs.versions.fabric.kotlin.get(), + "fabric_api_version" to libs.versions.fabric.api.get(), + "rei_version" to libs.versions.rei.get() + ) + replacements.forEach { (key, value) -> inputs.property(key, value) } + filesMatching("**/fabric.mod.json") { + expand(*replacements.toTypedArray()) + } + exclude("**/*.license") + from(tasks.scanLicenses) + from(collectTranslations) { + into("assets/firmament/lang") + } +} + +tasks.scanLicenses { + scanConfiguration(nonModImplentation) + scanConfiguration(configurations.modCompileClasspath.get()) + compatSourceSets.forEach { + scanConfiguration(it.modImplementationConfigurationName.get()) + } + outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.json")) + licenseFormatter.set(moe.nea.licenseextractificator.JsonLicenseFormatter()) +} +tasks.register("printAllLicenses", LicenseDiscoveryTask::class.java, licensing).configure { + outputFile.set(layout.buildDirectory.file("LICENSES-FIRMAMENT.txt")) + licenseFormatter.set(moe.nea.licenseextractificator.TextLicenseFormatter()) + compatSourceSets.forEach { + scanConfiguration(it.modImplementationConfigurationName.get()) + } + scanConfiguration(nonModImplentation) + scanConfiguration(configurations.modCompileClasspath.get()) + doLast { + println(outputFile.get().asFile.readText()) + } + outputs.upToDateWhen { false } +} +fun patchRenderDoc( + javaLauncher: JavaLauncher, +): JavaLauncher { + val wrappedJavaExecutable = javaLauncher.executablePath.asFile.absolutePath + require("\"" !in wrappedJavaExecutable) + val hashBytes = Hashing.sha256().hashString(wrappedJavaExecutable, StandardCharsets.UTF_8) + val hash = Base64.getUrlEncoder().encodeToString(hashBytes.asBytes()) + .replace("=", "") + val wrapperJavaRoot = rootProject.layout.buildDirectory + .dir("binaries/renderdoc-wrapped-java/$hash/") + .get() + val isWindows = Os.isFamily(Os.FAMILY_WINDOWS) + val wrapperJavaExe = + if (isWindows) wrapperJavaRoot.file("java.cmd") + else wrapperJavaRoot.file("java") + return object : JavaLauncher { + override fun getMetadata(): JavaInstallationMetadata { + return object : JavaInstallationMetadata by javaLauncher.metadata { + override fun isCurrentJvm(): Boolean { + return false + } + } + } + + override fun getExecutablePath(): RegularFile { + val fileF = wrapperJavaExe.asFile + if (!fileF.exists()) { + fileF.parentFile.mkdirs() + if (isWindows) { + fileF.writeText( + """ + setlocal enableextensions + start "" renderdoccmd.exe capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" %* + endlocal + """.trimIndent() + ) + } else { + fileF.writeText( + """ + #!/usr/bin/env bash + exec renderdoccmd capture --opt-hook-children --wait-for-exit --working-dir . "$wrappedJavaExecutable" "$@" + """.trimIndent() + ) + fileF.setExecutable(true) + } + } + return wrapperJavaExe + } + } +} +tasks.runClient { + javaLauncher.set(javaToolchains.launcherFor(java.toolchain).map { patchRenderDoc(it) }) +} + +tasks.withType().configureEach { + isPreserveFileTimestamps = false + isReproducibleFileOrder = true +} diff --git a/check-translation-ordering.sh b/check-translation-ordering.sh new file mode 100644 index 0000000..ebecb7c --- /dev/null +++ b/check-translation-ordering.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: GPL-3.0-or-later + +set -euo pipefail +jq -S --tab < translations/en_us.json | diff translations/en_us.json - diff --git a/docs/How to release.md b/docs/How to release.md new file mode 100644 index 0000000..d0d51d4 --- /dev/null +++ b/docs/How to release.md @@ -0,0 +1,19 @@ + + +# How to create a release + +There is a release script to automate some of these actions. + +- Bump the version on gradle.properties +- Create a tag with that same version (without `v` prefix, please) +- Create a changelog based on + `git log --pretty='- %s' --grep '[no changelog]' --invert-grep --fixed-strings oldversion..newversion | tac`, while + filtering out commits that should not be in the changelog. +- Upload to [GitHub](https://github.com/romangraef/Firmament/releases/new) +- Upload to [Modrinth](https://modrinth.com/mod/firmament/versions) +- Send a message in [Discord](https://discord.com/channels/1088154030628417616/1108565050693783683) +- Send a message in [the thread](https://hypixel.net/threads/firmament-a-skyblock-mod-for-1-20-1-fabric.5446366/) diff --git a/docs/firmament_logo.webp b/docs/firmament_logo.webp new file mode 100644 index 0000000000000000000000000000000000000000..d70327af8903154c3d862a2b1f2e2239ada39e39 GIT binary patch literal 474 zcmV<00VV!YNk&G}0RRA3MM6+kP&iD+0RR9mAHW9yzo0gft>oj-2dVX63n@cJ>7sd?X_^0Z2drcbEC*KmLF_|0zH{bh9?1xS_D4D1kqC z*D1%Ct?AKGjuQ~j67Ui+;*dNM!sRWdUoVeGJeUDuB*}3beFks`8UX+NQ^g%1g|HjZ ze+O>cIFh|W9B;ewi)H3K@$!qadMCo1e`^FC65jcT1SZp|-vUhMgiQY_FJLz18xnXO z6dk5~L1Krz)Q<_51Cbh>z48FB^GZEU5EWY?rzIv{nUUlX$Ywxnz$HzjON8;L9`v0g zkeK-dR?qrct8s{C0ERV$MMpr+Vyt9sYf{NIVDNVcH~qDY+rkoZ8oT5;(KtmzN66#)vNKthJZVrgX~ ztNfur@Bs=GiO2#=RtbPEI1mkDkwbu9`Ex+hk69gb|2t4-3DJ}21%K_B@WJjb3-@+Y z7dK{!oo&}}12CpiY>9ULeh&#)=+?AbOOiyGrQ}4xzU>3P*<2zQx{bG QeNA5r0Dxoj-2dVX63n@cJ>7sd?X_^0Z2drcbEC*KmLF_|0zH{bh9?1xS_D4D1kqC z*D1%Ct?AKGjuQ~j67Ui+;*dNM!sRWdUoVeGJQyfRk{m~pl08{qz>&ix*Z)7(!~>}1 z29b#VPr&WRZa?nr&ppp+sBas#hHW^{YN+9>P0_tye#7}wLk(Zk8^*9N9M5k!U(&EI ztmzG7*k<>u_8Y4`Piok&c5fKNHe2Zxi~YtYzLA9UBc<128^*BB7FJxbV(I=yA@O{v z4%;yBjd{(kxZ1)p{Cue))nS|c#uvVk8dhA>g=P4PdBXXSu;L57mLB#So4s~_Vo5*H zt0>#!`A|)7>B2~FxDG2U=?7kL$BMFR_jyo5VM~`CcC(lC6G>Ro4?OW7p132`^e2*V zKGZ+#CH=(1-ceZa=zc-EAmx)kUkW_!19!W1_cpxXfB3Ka1sA;FhQfJM;EB84x-aP` z5^s3og5CueJaI$WE6$e=+_0rD=_elcj>3w<4NqLsPux)U)s{UkT5-c>pZ0;ft#7*{ z_5UB~YOgpyTGJ1Ex7EF1MK5s2)85jFH}sS~KRR&39o2nFKQZvjrUN&u=^GwMN)MbD zRiq8o{j`tt9V>d9UF~c7W_w}JhpMgahrQc%SdXiH?Y^SyNS_DYke*o658QCan*KFx zpzu1Z(xdy$o(J{cu%>?v8z_6lezIfu`H(R0>)Qt^{c1muR+JrB@Pl{!U_s%0h<}bi zr3YT^2j204!h)Y+3kq-D=TEZl81@xcl>NZZ@CB7VKN5O@52QfZF|4rQXZV6j51c2l z_rN8%@(uKEQfBuuNANTg>o~HmujeN-f literal 0 HcmV?d00001 diff --git a/docs/firmament_logo_256.webp.license b/docs/firmament_logo_256.webp.license new file mode 100644 index 0000000..8b77b1b --- /dev/null +++ b/docs/firmament_logo_256.webp.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 ic22487 + +SPDX-License-Identifier: CC-BY-4.0 diff --git a/docs/firmament_logo_256_nobg.webp b/docs/firmament_logo_256_nobg.webp new file mode 100644 index 0000000000000000000000000000000000000000..c557fcaaad7f72666e6fcdd0c0e269926811519b GIT binary patch literal 9840 zcmbt)c|4X++x}eFz3<%i{kFU9`@Zi>cG;IKw|(Db&z@3A2!%o_3YC;XmKH^#LW!h8 zic0MQ(UOrN$^Ur& z-(}+^fc}}8kohOp|Lybtv=RasasB{6*gcOn|LEBGJ>0cdsY&tCdl-JQXJ_>f_6^v> zZ}+ft>>fb?5X67%e*ea_e{j&hvGPAS*2%$W&&M198Zqd9VZZ-{{exp8_RjCL=P&Ya z4tody-nhL>kYR*}Gi005!yr5)j6qY9m8b2GjE;(p-&?%z-%)51{}7Ga zW9t9kQT7P_6GS#DHc0Njw~CYVOOc85mD>v-7tRRs4fl@XuL6LZ1pshP`zORE{%aqw_mK9)3t)f*D1ZhSfZKaVguRzU29&)?X21ei z0UKZkoPY~(10KK&_<;bR0YM-PM1Uv|0}_A^B!SePmSln4-lJ6nNO2;K@^DD(`($GY7;>cNCqh&6{LZ5kO8tlHaG-wKpw~k1)vZV zfnsn390eudI5+`H!AWoml!FRT393Lfr~zj{EvN(a;2dZGji3o!0L|bMxC~lAE4T{U zKs)FF*TD_Y32uU0;5O(6cR&y51%2Qi=m&#f2;2t`z#}jW9)l-f6g≦2D?z&%p~Y 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 literal 0 HcmV?d00001 diff --git a/docs/firmament_logo_trans.webp.license b/docs/firmament_logo_trans.webp.license new file mode 100644 index 0000000..8b77b1b --- /dev/null +++ b/docs/firmament_logo_trans.webp.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2025 ic22487 + +SPDX-License-Identifier: CC-BY-4.0 diff --git a/docs/release_script.sh b/docs/release_script.sh new file mode 100644 index 0000000..8d87a09 --- /dev/null +++ b/docs/release_script.sh @@ -0,0 +1,225 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# ARG_OPTIONAL_BOOLEAN([no-check],[n],[Skip checking preconditions, such as a clean git working directory]) +# ARG_OPTIONAL_BOOLEAN([no-test],[t],[Skip running gradle tests.]) +# ARG_OPTIONAL_BOOLEAN([dry],[d],[Dry run]) +# ARG_HELP([Script to help creating releases]) +# ARGBASH_GO() +# needed because of Argbash --> m4_ignore([ +### START OF CODE GENERATED BY Argbash v2.10.0 one line above ### +# Argbash is a bash code generator used to get arguments parsing right. +# Argbash is FREE SOFTWARE, see https://argbash.io for more info + + +die() +{ + local _ret="${2:-1}" + test "${_PRINT_HELP:-no}" = yes && print_help >&2 + echo "$1" >&2 + exit "${_ret}" +} + + +begins_with_short_option() +{ + local first_option all_short_options='ntdh' + first_option="${1:0:1}" + test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 +} + +# THE DEFAULTS INITIALIZATION - OPTIONALS +_arg_no_check="off" +_arg_no_test="off" +_arg_dry="off" + + +print_help() +{ + printf '%s\n' "Script to help creating releases" + printf 'Usage: %s [-n|--(no-)no-check] [-t|--(no-)no-test] [-d|--(no-)dry] [-h|--help]\n' "$0" + printf '\t%s\n' "-n, --no-check, --no-no-check: Skip checking preconditions, such as a clean git working directory (off by default)" + printf '\t%s\n' "-t, --no-test, --no-no-test: Skip running gradle tests. (off by default)" + printf '\t%s\n' "-d, --dry, --no-dry: Dry run (off by default)" + printf '\t%s\n' "-h, --help: Prints help" +} + + +parse_commandline() +{ + while test $# -gt 0 + do + _key="$1" + case "$_key" in + -n|--no-no-check|--no-check) + _arg_no_check="on" + test "${1:0:5}" = "--no-" && _arg_no_check="off" + ;; + -n*) + _arg_no_check="on" + _next="${_key##-n}" + if test -n "$_next" -a "$_next" != "$_key" + then + { begins_with_short_option "$_next" && shift && set -- "-n" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option." + fi + ;; + -t|--no-no-test|--no-test) + _arg_no_test="on" + test "${1:0:5}" = "--no-" && _arg_no_test="off" + ;; + -t*) + _arg_no_test="on" + _next="${_key##-t}" + if test -n "$_next" -a "$_next" != "$_key" + then + { begins_with_short_option "$_next" && shift && set -- "-t" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option." + fi + ;; + -d|--no-dry|--dry) + _arg_dry="on" + test "${1:0:5}" = "--no-" && _arg_dry="off" + ;; + -d*) + _arg_dry="on" + _next="${_key##-d}" + if test -n "$_next" -a "$_next" != "$_key" + then + { begins_with_short_option "$_next" && shift && set -- "-d" "-${_next}" "$@"; } || die "The short option '$_key' can't be decomposed to ${_key:0:2} and -${_key:2}, because ${_key:0:2} doesn't accept value and '-${_key:2:1}' doesn't correspond to a short option." + fi + ;; + -h|--help) + print_help + exit 0 + ;; + -h*) + print_help + exit 0 + ;; + *) + _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 + ;; + esac + shift + done +} + +parse_commandline "$@" + +# OTHER STUFF GENERATED BY Argbash + +### END OF CODE GENERATED BY Argbash (sortof) ### ]) +# [ <-- needed because of Argbash +set -euo pipefail + +REMOTE=origin + +basedir="$(dirname "$(dirname "$(realpath "$0")")")" +echo "Found base directory at $basedir" + +if ! [ -d "$basedir/.git" ]; then + echo Could not find git directory. + exit 1 +fi + +if ! "${JAVA_HOME}"/bin/java -version 2>&1 | grep 'version "21.'>/dev/null && [ "$_arg_no_check" == off ]; then + echo Wrong java version + exit 1 +fi + +if [ -n "$(git status --porcelain)" ] && [ "$_arg_no_check" == off ]; then + echo Unclean git working environment + exit 1 +fi + +current_branch="$(git rev-parse --abbrev-ref HEAD)" + +if ! [[ "$current_branch" = "master" ]] && ! [[ "$current_branch" = mc-* ]]; then + echo "Not on branch master or a mc- branch." + exit 1 +fi + +git fetch --tags "$REMOTE" + +git tag --list --sort=v:refname + +oldversion="$(git describe --tags --abbrev=0|tr -d '\n')" + +echo "Choosing old version as $oldversion" + +# TODO: auto choose next version based on a command line flag: --minor --hotfix --major as well as minecraft info from libs.versions.toml +echo -n "Choosing next version as: " +read newversion + +if ! [[ "$newversion" = *+mc* ]] && [ "$_arg_no_check" == off ]; then + echo "Illegal next version $newversion. Please use a.b.c+mcx.y.z" + exit 1 +fi + +echo "Confirming new version as $newversion" + +if [ "$_arg_dry" == off ]; then + echo Committing release commit + git commit --allow-empty -m 'Prepare release '"$newversion"' + +[no changelog]' + echo Tagging release commit + git tag "$newversion" +fi +mkdir -p "$basedir/.gradle" +releasenotes="$basedir/.gradle/releasenotes.md" + +comparetag="$( +if [ "$_arg_dry" == off ]; then + echo "$newversion" +else + echo "HEAD" +fi)" + +echo Building release notes +echo "**Full Changelog**: " > "$releasenotes" +echo >> "$releasenotes" +git log --pretty='- %s' --grep '[no changelog]' --invert-grep --fixed-strings "$oldversion..$comparetag" | tac >> "$releasenotes" +echo >> "$releasenotes" + +echo Check Release notes: +echo ---------------------------------------------- +cat "$releasenotes" +echo ---------------------------------------------- +echo Press Enter to resume +read + +echo Building JAR +"$basedir"/gradlew --stop +if [ "$_arg_no_test" == off ]; then + echo Building and testing + "$basedir"/gradlew clean build +else + echo Building without testing + "$basedir"/gradlew clean assemble +fi + +echo Release notes: +echo ---------------------------------------------- +cat "$releasenotes" +echo ---------------------------------------------- + +if [ "$_arg_dry" == off ]; then + echo Pushing to github + git push "$REMOTE" "HEAD" "$newversion" + if command -v gh; then + echo Creating github release + (set -x; gh release create -t "Firmament $newversion" "$newversion" -F "$releasenotes" "$basedir/build/libs/Firmament-$newversion.jar") + else + echo Could not find github command utility. Opening github releases + xdg-open "https://github.com/nea89o/firmament/releases/new" + fi +fi + +echo Opening modrinth releases +xdg-open "https://modrinth.com/mod/firmament/versions" + +echo "Don't forget to upload a discord release as well:" + +# ] <-- needed because of Argbash diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..2385103 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: CC0-1.0 +# suppress inspection "UnusedProperty" for whole file +org.gradle.jvmargs=-Xmx4096M + +loom.platform=fabric + +archives_base_name=Firmament +maven_group=moe.nea.firmament + +firmament.compiletimerepohash=a6116d945491d7c57c93d43f51250f93d62d8434 + +# TODO: remove after https://github.com/google/ksp/issues/2072 +ksp.incremental=false diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..d4ff2c4 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,168 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: CC0-1.0 + +[versions] +minecraft = "1.21.5" + +# Update from https://kotlinlang.org/ +kotlin = "2.1.20" +# Update from https://github.com/google/ksp/releases +kotlin_ksp = "2.1.20-2.0.0" + +# Update from https://linkie.shedaniel.me/dependencies?loader=fabric +fabric_loader = "0.16.13" +fabric_api = "0.119.9+1.21.5" +yarn = "1.21.5+build.1" +modmenu = "14.0.0-rc.2" +architectury = "16.0.3" +# Update from https://maven.architectury.dev/me/shedaniel/RoughlyEnoughItems-fabric/ (but is typically late) +rei = "19.0.805" + +# Update from https://maven.fabricmc.net/net/fabricmc/fabric-language-kotlin/ +fabric_kotlin = "1.13.2+kotlin.2.1.20" + +# Update from https://maven.architectury.dev/dev/architectury/loom/dev.architectury.loom.gradle.plugin/ +loom = "1.7.414" # TODO: port back to architectury (and) 1.9.424 + +# Update from https://modrinth.com/mod/qolify/versions?l=fabric +qolify = "1.6.0-1.21.1" + +# Update from https://modrinth.com/mod/sodium/versions?l=fabric +sodium = "mc1.21.5-0.6.13-fabric" + +# Update from https://modrinth.com/mod/freecam/versions?l=fabric +freecammod = "1.3.3+mc1.21.5" + +# Update from https://modrinth.com/mod/no-chat-reports/versions?l=fabric +ncr = "Fabric-1.21.5-v2.12.0" + +# Update from https://modrinth.com/mod/female-gender/versions?l=fabric +femalegender = "4.3.4+1.21.5" + +shadow = "8.3.8" + +# Update from https://modrinth.com/mod/explosive-enhancement/versions?l=fabric +explosiveenhancement = "1.2.3-1.21.0" + +# Update from https://modrinth.com/mod/not-enough-animations/versions?l=fabric +notenoughanimations = "prj4BdjU" + +# Update from https://modrinth.com/mod/cit-resewn/versions?l=fabric +citresewn = "1.2.0+1.21" + +# Update from https://modrinth.com/mod/jade/versions?l=fabric +jade = "18.1.0+fabric" + +devauth = "1.2.1" + +# Update from https://ktor.io/docs/ +ktor = "3.1.2" + +# Update from https://repo.nea.moe/#/releases/moe/nea/neurepoparser +neurepoparser = "1.8.0" + +# Update from https://github.com/HotswapProjects/HotswapAgent/releases +# TODO: bump to 2.0.1 +hotswap_agent = "1.4.2-SNAPSHOT" + +# Update from https://github.com/LlamaLad7/MixinExtras/tags +mixinextras = "0.4.1" + +jarvis = "1.1.4" +nealisp = "1.1.0" + +# Update from https://github.com/NotEnoughUpdates/MoulConfig/tags +moulconfig = "4.0.1-beta" + +# Update from https://repo.nea.moe/#/releases/moe/nea/mc-auto-translations/moe.nea.mc-auto-translations.gradle.plugin +mcAutoTranslations = "0.3.0" + +# Update from https://www.curseforge.com/minecraft/mc-mods/configured/files/all?page=1&pageSize=20 +configured = "6023970" + +# Update from https://modrinth.com/mod/hypixel-mod-api/versions?l=fabric +hypixelmodapi = "1.0.1" +hypixelmodapi_fabric = "1.0.1+build.1+mc1.21" + +# Update from https://github.com/shedaniel/fabric-asm or https://maven.shedaniel.me/me/shedaniel/mm/ +manninghamMills = "2.4.1" + +# Update from https://docs.isxander.dev/yet-another-config-lib/installing-yacl +# Nvm, they just don't update docs: https://modrinth.com/mod/yacl/versions?l=fabric +yacl = "3.6.6+1.21.5-fabric" + +# Update from https://maven.shedaniel.me/me/shedaniel/cloth/basic-math/ +basicMath = "0.6.1" + +# Update from https://mvnrepository.com/artifact/net.lenni0451.classtransform/core +classtransform = "1.14.1" + +# Update from https://mvnrepository.com/artifact/org.ow2.asm/asm/ +asm = "9.8" + +[libraries] +minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } +fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" } +fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" } +fabric_api_deprecated = { module = "net.fabricmc.fabric-api:fabric-api-deprecated", version.ref = "fabric_api" } +fabric_kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric_kotlin" } +architectury = { module = "dev.architectury:architectury", version.ref = "architectury" } +rei_api = { module = "me.shedaniel:RoughlyEnoughItems-api", version.ref = "rei" } +moulconfig = { module = "org.notenoughupdates.moulconfig:modern-1.21.5", version.ref = "moulconfig" } +repoparser = { module = "moe.nea:neurepoparser", version.ref = "neurepoparser" } +mixinextras = { module = "io.github.llamalad7:mixinextras-fabric", version.ref = "mixinextras" } +jarvis_api = { module = "moe.nea.jarvis:jarvis-api", version.ref = "jarvis" } +jarvis_fabric = { module = "moe.nea.jarvis:jarvis-fabric", version.ref = "jarvis" } +nealisp = { module = "moe.nea:nealisp", version.ref = "nealisp" } +explosiveenhancement = { module = "maven.modrinth:explosive-enhancement", version.ref = "explosiveenhancement" } +manninghamMills = { module = "me.shedaniel:mm", version.ref = "manninghamMills" } +aaronhmapi = { module = "net.azureaaron:hm-api", version = "1.0.0+1.21" } +hypixelmodapi = { module = "net.hypixel:mod-api", version.ref = "hypixelmodapi" } +hypixelmodapi_fabric = { module = "maven.modrinth:hypixel-mod-api", version.ref = "hypixelmodapi_fabric" } +configured = { module = "curse.maven:configured-457570", version.ref = "configured" } +# Runtime: +notenoughanimations = { module = "maven.modrinth:not-enough-animations", version.ref = "notenoughanimations" } +hotswap = { module = "virtual.github.hotswapagent:hotswap-agent", version.ref = "hotswap_agent" } +architectury_fabric = { module = "dev.architectury:architectury-fabric", version.ref = "architectury" } +rei_fabric = { module = "me.shedaniel:RoughlyEnoughItems-fabric", version.ref = "rei" } +devauth = { module = "me.djtheredstoner:DevAuth-fabric", version.ref = "devauth" } +modmenu = { module = "maven.modrinth:modmenu", version.ref = "modmenu" } +qolify = { module = "maven.modrinth:qolify", version.ref = "qolify" } +ncr = { module = "maven.modrinth:no-chat-reports", version.ref = "ncr" } +sodium = { module = "maven.modrinth:sodium", version.ref = "sodium" } +freecammod = { module = "maven.modrinth:freecam", version.ref = "freecammod" } +citresewn = { module = "maven.modrinth:cit-resewn", version.ref = "citresewn" } +femalegender = { module = "maven.modrinth:female-gender", version.ref = "femalegender" } +jade = { module = "maven.modrinth:jade", version.ref = "jade" } +yacl = { module = "dev.isxander:yet-another-config-lib", version.ref = "yacl" } +basicMath = { module = "me.shedaniel.cloth:basic-math", version.ref = "basicMath" } +shadow = { module = "com.gradleup.shadow:shadow-gradle-plugin", version.ref = "shadow" } +classTransform-mixinsTranslator = { module = "net.lenni0451.classtransform:mixinstranslator", version.ref = "classtransform" } +classTransform-core = { module = "net.lenni0451.classtransform:core", version.ref = "classtransform" } + +asm = { module = "org.ow2.asm:asm", version.ref = "asm" } + +[bundles] +runtime_required = [ + # "rei_fabric", + # "notenoughanimations", + "hypixelmodapi_fabric", +] +runtime_optional = [ + "devauth", + # "freecammod", + # "sodium", + # "qolify", + # "ncr", + # "citresewn", +] + +[plugins] +kotlin_jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } +kotlin_plugin_serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } +kotlin_plugin_powerassert = { id = "org.jetbrains.kotlin.plugin.power-assert", version.ref = "kotlin" } +kotlin_plugin_ksp = { id = "com.google.devtools.ksp", version.ref = "kotlin_ksp" } +shadow = { id = "com.gradleup.shadow", version.ref = "shadow" } +loom = { id = "dev.architectury.loom", version.ref = "loom" } +mcAutoTranslations = { id = "moe.nea.mc-auto-translations", version.ref = "mcAutoTranslations" } diff --git a/gradle/wrapper/gradle-wrapper.jar.license b/gradle/wrapper/gradle-wrapper.jar.license new file mode 100644 index 0000000..9d85393 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.jar.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Gradle, Inc. + +SPDX-License-Identifier: Apache-2.0 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..4cdd0fb --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,9 @@ +# SPDX-FileCopyrightText: 2023 Gradle, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..bc899af --- /dev/null +++ b/gradlew @@ -0,0 +1,223 @@ +#!/bin/sh + +# Copyright © 2015-2021 the original authors. +# SPDX-FileCopyrightText: 2023 Gradle, Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..05b887c --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,93 @@ +REM SPDX-FileCopyrightText: 2023 Gradle, Inc. +REM +REM SPDX-License-Identifier: Apache-2.0 + +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/javaplugin/build.gradle.kts b/javaplugin/build.gradle.kts new file mode 100644 index 0000000..dc461bc --- /dev/null +++ b/javaplugin/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + java + idea + id("firmament.common") +} +dependencies { + implementation("net.fabricmc:stitch:0.6.2") +} +val compilerModules = listOf("util", "comp", "tree", "api", "code") + .map { "jdk.compiler/com.sun.tools.javac.$it" } + +tasks.withType(JavaCompile::class) { + val module = "ALL-UNNAMED" + options.compilerArgs.addAll( + compilerModules.map { "--add-exports=$it=$module" } + ) +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java new file mode 100644 index 0000000..7ba3b44 --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java @@ -0,0 +1,81 @@ +package moe.nea.firmament.javaplugin; + +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Names; + +public class InitReplacer extends TreeScanner { + private final MappingTree mappingTree; + private final TreeMaker treeMaker; + private final Names names; + private final IntermediaryNameResolutionTask plugin; + private Symbol.ClassSymbol classTree; + private CompilationUnitTree compilationUnitTree; + + public InitReplacer(MappingTree mappingTree, IntermediaryNameResolutionTask plugin) { + this.mappingTree = mappingTree; + this.treeMaker = plugin.treeMaker; + this.names = plugin.names; + this.plugin = plugin; + } + + @Override + public Void visitClass(ClassTree node, Void unused) { + this.classTree = plugin.utils.getSymbol(node); + return super.visitClass(node, unused); + } + + @Override + public Void visitCompilationUnit(CompilationUnitTree node, Void unused) { + this.compilationUnitTree = node; + return super.visitCompilationUnit(node, unused); + } + + @Override + public Void visitVariable(VariableTree node, Void unused) { + var annotation = node + .getModifiers().getAnnotations() + .stream() + .filter(it -> it.getAnnotationType().toString().equals("IntermediaryName")) // Crazy type-safety! + .findAny(); + if (annotation.isEmpty()) + return super.visitVariable(node, unused); + var jcAnnotation = (JCTree.JCAnnotation) annotation.get(); + var jcNode = (JCTree.JCVariableDecl) node; + if (node.getInitializer() != null) { + plugin.utils.reportError( + compilationUnitTree.getSourceFile(), + jcNode.getInitializer(), + "Providing an initializer for a variable is illegal for @IntermediaryName annotated fields" + ); + return super.visitVariable(node, unused); + } + var target = plugin.utils.getAnnotationValue(jcAnnotation, "value"); + var targetClass = plugin.utils.resolveClassLiteralExpression(target).tsym.flatName().toString(); + var intermediaryClass = mappingTree.resolveClassToIntermediary(targetClass); + if (intermediaryClass == null){ + plugin.utils.reportError( + compilationUnitTree.getSourceFile(), + jcNode.init, + "Unknown class name " + targetClass + ); + return super.visitVariable(node, unused); + } + var remapper = treeMaker.Select(treeMaker.This(classTree.type), names.fromString("remapper")); + var remappingCall = treeMaker.Apply( + List.nil(), + treeMaker.Select(remapper, names.fromString("mapClassName")), + List.of(treeMaker.Literal("intermediary"), + treeMaker.Literal(intermediaryClass))); + jcNode.init = remappingCall; + jcNode.mods.annotations = List.filter(jcNode.mods.annotations, jcAnnotation); + return super.visitVariable(node, unused); + } + +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java new file mode 100644 index 0000000..cb87b20 --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java @@ -0,0 +1,77 @@ +package moe.nea.firmament.javaplugin; + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.List; + +import javax.tools.JavaFileObject; + +public class IntermediaryMethodReplacer extends TreeScanner { + private final MappingTree mappings; + private final IntermediaryNameResolutionTask plugin; + private JavaFileObject sourceFile; + private CompilationUnitTree compilationUnit; + + public IntermediaryMethodReplacer(MappingTree mappings, IntermediaryNameResolutionTask plugin) { + this.mappings = mappings; + this.plugin = plugin; + } + + + @Override + public Void visitCompilationUnit(CompilationUnitTree node, Void unused) { + sourceFile = node.getSourceFile(); + compilationUnit = node; + return super.visitCompilationUnit(node, unused); + } + + public void replaceMethodName(JCTree.JCMethodInvocation node) { + var select = node.getMethodSelect(); + if (!(select instanceof JCTree.JCFieldAccess fieldAccess)) return; + if (!fieldAccess.name.contentEquals("methodName")) return; + if (!(node.args.head instanceof JCTree.JCMemberReference methodReference)) { + plugin.utils.reportError(sourceFile, node, "Please provide a Class::method reference directly (and nothing else)"); + return; + } + var clearName = methodReference.name.toString(); + var classRef = methodReference.expr; + var type = plugin.utils.resolveClassName(classRef, compilationUnit); + var intermediaryName = mappings.resolveMethodToIntermediary( + type.tsym.flatName().toString(), + clearName + ); + fieldAccess.name = plugin.names.fromString("id"); + node.args = List.of(plugin.treeMaker.Literal(intermediaryName)); + } + + public void replaceClassName(JCTree.JCMethodInvocation node) { + var select = node.getMethodSelect(); + if (!(select instanceof JCTree.JCFieldAccess fieldAccess)) return; + if (!fieldAccess.name.contentEquals("className")) return; + if (node.getTypeArguments().size() != 1) { + plugin.utils.reportError(sourceFile, node, "You need to explicitly provide the class you want the intermediary name for"); + return; + } + var head = node.typeargs.head; + var resolved = plugin.utils.resolveClassName(head, compilationUnit); + var sourceName = resolved.tsym.flatName().toString(); + var mappedName = mappings.resolveClassToIntermediary(sourceName); + if (mappedName == null) { + plugin.utils.reportError(sourceFile, node, "Unknown class name " + sourceName); + return; + } + fieldAccess.name = plugin.names.fromString("id"); + node.typeargs = List.nil(); + node.args = List.of(plugin.treeMaker.Literal(mappedName)); + } + + @Override + public Void visitMethodInvocation(MethodInvocationTree node, Void unused) { + replaceClassName((JCTree.JCMethodInvocation) node); + replaceMethodName((JCTree.JCMethodInvocation) node); + return super.visitMethodInvocation(node, unused); + } +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionPlugin.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionPlugin.java new file mode 100644 index 0000000..ba6a0c5 --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionPlugin.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.javaplugin; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.Plugin; + +import java.util.HashMap; +import java.util.Map; + +public class IntermediaryNameResolutionPlugin implements Plugin { + + @Override + public String getName() { + return "IntermediaryNameReplacement"; + } + + @Override + public void init(JavacTask task, String... args) { + Map argMap = new HashMap<>(); + for (String arg : args) { + String[] parts = arg.split("=", 2); + argMap.put(parts[0], parts.length == 2 ? parts[1] : "true"); + } + task.addTaskListener(new IntermediaryNameResolutionTask(this, task, argMap)); + } +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionTask.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionTask.java new file mode 100644 index 0000000..86a5598 --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryNameResolutionTask.java @@ -0,0 +1,44 @@ +package moe.nea.firmament.javaplugin; + +import com.sun.source.util.JavacTask; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.tools.javac.api.BasicJavacTask; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.Names; +import net.fabricmc.stitch.commands.tinyv2.TinyV2Reader; + +import java.io.File; +import java.io.IOException; +import java.util.Map; + +public class IntermediaryNameResolutionTask implements TaskListener { + TreeMaker treeMaker; + Names names; + MappingTree mappings; + Utils utils; + + public IntermediaryNameResolutionTask(IntermediaryNameResolutionPlugin intermediaryNameResolutionPlugin, JavacTask task, Map argMap) { + var context = ((BasicJavacTask) task).getContext(); + var mappingFile = new File(argMap.get("mappingFile")); + System.err.println("Loading mappings from " + mappingFile); + try { + var tinyV2File = TinyV2Reader.read(mappingFile.toPath()); + mappings = new MappingTree(tinyV2File, argMap.get("sourceNs"), argMap.getOrDefault("targetNs", "intermediary")); + } catch (IOException e) { + throw new RuntimeException(e); + } + treeMaker = TreeMaker.instance(context); + names = Names.instance(context); + utils = Utils.instance(context); + } + + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ENTER) return; + if (e.getCompilationUnit() == null || e.getSourceFile() == null) return; + e.getCompilationUnit().accept(new InitReplacer(mappings, this), null); + e.getCompilationUnit().accept(new IntermediaryMethodReplacer(mappings, this), null); + } + +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java new file mode 100644 index 0000000..eef5f9a --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java @@ -0,0 +1,51 @@ +package moe.nea.firmament.javaplugin; + +import net.fabricmc.stitch.commands.tinyv2.TinyClass; +import net.fabricmc.stitch.commands.tinyv2.TinyFile; +import net.fabricmc.stitch.commands.tinyv2.TinyMethod; + +import java.util.Map; +import java.util.stream.Collectors; + +public class MappingTree { + + private final Map classLookup; + private final int targetIndex; + private final int sourceIndex; + + public MappingTree(TinyFile tinyV2File, String sourceNamespace, String targetNamespace) { + sourceIndex = tinyV2File.getHeader().getNamespaces().indexOf(sourceNamespace); + if (sourceIndex < 0) + throw new RuntimeException("Could not find source namespace " + sourceNamespace + " in mappings file."); + this.classLookup = tinyV2File + .getClassEntries() + .stream() + .collect(Collectors.toMap(it -> it.getClassNames().get(sourceIndex), it -> it)); + targetIndex = tinyV2File.getHeader().getNamespaces().indexOf(targetNamespace); + if (targetIndex < 0) + throw new RuntimeException("Could not find target namespace " + targetNamespace + " in mappings file."); + } + + public String resolveMethodToIntermediary(String className, String methodName) { + var classData = classLookup.get(className.replace(".", "/")); + TinyMethod candidate = null; + for (TinyMethod method : classData.getMethods()) { + if (method.getMethodNames().get(sourceIndex).equals(methodName)) { + if (candidate != null) { + throw new RuntimeException("Found two candidates for method " + className + "." + methodName); + } + candidate = method; + } + } + return candidate.getMethodNames().get(targetIndex); + } + + public String resolveClassToIntermediary(String className) { + var cls = classLookup.get(className.replace(".", "/")); + if (cls == null) { + return null; + } + return cls.getClassNames().get(targetIndex) + .replace("/", "."); + } +} diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java new file mode 100644 index 0000000..4c8806d --- /dev/null +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java @@ -0,0 +1,121 @@ +package moe.nea.firmament.javaplugin; + +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.Tree; +import com.sun.tools.javac.comp.Attr; +import com.sun.tools.javac.code.Symbol; +import com.sun.tools.javac.code.Type; +import com.sun.tools.javac.code.Types; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Enter; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.JCDiagnostic; +import com.sun.tools.javac.util.JavacMessages; +import com.sun.tools.javac.util.Log; + +import javax.tools.JavaFileObject; +import java.util.ListResourceBundle; + +public class Utils { + private static final Context.Key KEY = new Context.Key<>(); + private final Log log; + private final JCDiagnostic.Factory diagnostics; + private final Types types; + private final Attr attr; + private final Enter enter; + + private Utils(Context context) { + context.put(KEY, this); + JavacMessages.instance(context).add(l -> new ListResourceBundle() { + + @Override + protected Object[][] getContents() { + return new Object[][]{ + new Object[]{"compiler.err.firmament.generic", "{0}"} + }; + } + }); + log = Log.instance(context); + diagnostics = JCDiagnostic.Factory.instance(context); + types = Types.instance(context); + attr = Attr.instance(context); + enter = Enter.instance(context); + } + + public static Utils instance(Context context) { + var utils = context.get(KEY); + if (utils == null) { + utils = new Utils(context); + } + return utils; + } + + public Type resolveClassName(ExpressionTree expression) { + var tree = (JCTree) expression; + return tree.type; + } + + public Type resolveClassName(ExpressionTree tree, CompilationUnitTree unit) { + return resolveClassName(tree, enter.getTopLevelEnv((JCTree.JCCompilationUnit) unit)); + } + + public Type resolveClassName(ExpressionTree tree, Env env) { + var t = resolveClassName(tree); + if (t != null) return t; + return attr.attribType((JCTree) tree, env); + } + + public Symbol getSymbol(IdentifierTree tree) { + return ((JCTree.JCIdent) tree).sym; + } + + public Symbol.ClassSymbol getSymbol(ClassTree tree) { + return ((JCTree.JCClassDecl) tree).sym; + } + + public ExpressionTree getAnnotationValue( + AnnotationTree tree, + String name) { + // TODO: strip parenthesis + for (var argument : tree.getArguments()) { + var assignment = (AssignmentTree) argument; + if (((IdentifierTree) assignment.getVariable()).getName().toString().equals(name)) + return assignment.getExpression(); + } + return null; + } + + public Type.ClassType resolveClassLiteralExpression(ExpressionTree tree) { + if (!(tree instanceof MemberSelectTree select)) + throw new RuntimeException("Cannot resolve non field access class literal: " + tree); + if (!select.getIdentifier().toString().equals("class")) + throw new RuntimeException("Class literal " + select + "accessed non .class attribute"); + + return (Type.ClassType) resolveClassName(select.getExpression()); + } + + public void reportError( + JavaFileObject file, + Tree node, + String message + ) { + var originalSource = log.useSource(file); + var error = diagnostics.error( + JCDiagnostic.DiagnosticFlag.API, + log.currentSource(), + node == null ? null : ((JCTree) node).pos(), + "firmament.generic", + message + ); + log.report(error); + log.useSource(originalSource); + } +} diff --git a/javaplugin/src/main/resources/META-INF/services/com.sun.source.util.Plugin b/javaplugin/src/main/resources/META-INF/services/com.sun.source.util.Plugin new file mode 100644 index 0000000..a9e5dbe --- /dev/null +++ b/javaplugin/src/main/resources/META-INF/services/com.sun.source.util.Plugin @@ -0,0 +1 @@ +moe.nea.firmament.javaplugin.IntermediaryNameResolutionPlugin diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..7b298b6 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2023 Linnea Gräf + * SPDX-FileCopyrightText: 2024 Linnea Gräf + * + * SPDX-License-Identifier: CC0-1.0 + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +pluginManagement { + repositories { + mavenLocal() + maven { + name = "fabricmc" + url = uri("https://maven.fabricmc.net/") + } + maven { + name = "architectury" + url = uri("https://maven.architectury.dev/") + } + maven { + name = "forgemc" + url = uri("https://maven.minecraftforge.net/") + } + maven { + name = "jitpack" + url = uri("https://jitpack.io") + } + maven { + url = uri("https://repo.nea.moe/releases") + } + mavenCentral() + gradlePluginPortal() + } +} + +rootProject.name = "Firmament" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +include("symbols") +include("javaplugin") +include("testagent") +includeBuild("build-logic") diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..ef882e8 --- /dev/null +++ b/shell.nix @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: GPL-3.0-or-later +{pkgs ? import {}}: +pkgs.mkShell { + buildInputs = with pkgs; [ + bash + gh + git + xdg-utils + reuse + pre-commit + glfw + jdk21 + libGL + wayland + flite + jack2 + openal + pulseaudio + pipewire + glibc + ]; + shellHook = '' + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.glfw}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.pipewire}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.pulseaudio}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.jack2}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.openal}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.libGL}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.wayland}/lib" + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.flite}/lib" + export JAVA_HOME=${pkgs.jdk21} + apply() { + echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" >.env + echo org.lwjgl.glfw.libname=${pkgs.glfw}/lib/libglfw.so >.properties + echo "jna.library.path=$LD_LIBRARY_PATH" >>.properties + echo "java.library.path=$LD_LIBRARY_PATH" >>.properties + } + + ''; +} diff --git a/src/compat/citresewn/java/ConditionDirectAccessHelper.kt b/src/compat/citresewn/java/ConditionDirectAccessHelper.kt new file mode 100644 index 0000000..af97a40 --- /dev/null +++ b/src/compat/citresewn/java/ConditionDirectAccessHelper.kt @@ -0,0 +1,59 @@ +package moe.nea.firmament.compat.citresewn + +import java.lang.invoke.MethodHandles +import java.util.function.BiPredicate +import java.util.function.Function +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT + +object ConditionNBTMixin { + class Helper { + // TODO: make lambdametafactory work by way of modifying the actual modifiers + + val stringMatcherType = ConditionNBT::class.java.getDeclaredField("matchString").type + + val accessMatcher = run { + val matchStringF = ConditionNBT::class.java.getDeclaredField("matchString"); + matchStringF.isAccessible = true + val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup()) +// val mt = MethodType.methodType(stringMatcherType, ConditionNBT::class.java) +// val callsite = LambdaMetafactory.metafactory( +// l, "apply", +// MethodType.methodType(Function::class.java), +// MethodType.methodType(java.lang.Object::class.java, java.lang.Object::class.java), +// l.unreflectGetter(matchStringF), +// mt +// ) + val getter = l.unreflectGetter(matchStringF) + Function { getter.invoke(it) as StringMatcher } + } + val directCaller = run { + val matchM = stringMatcherType.getDeclaredMethod("matches", String::class.java); + matchM.isAccessible = true + val l = MethodHandles.privateLookupIn(ConditionNBT::class.java, MethodHandles.lookup()) +// val mt = MethodType.methodType(java.lang.Boolean.TYPE, stringMatcherType, String::class.java) +// val callsite = LambdaMetafactory.metafactory( +// l, "test", +// MethodType.methodType(BiPredicate::class.java), +// mt, +// l.unreflect(matchM), +// mt +// ) + val func = l.unreflect(matchM) + BiPredicate { a, b -> func.invoke(a, b) as Boolean } + } + + fun test(condition: ConditionNBT, text: String): Boolean { + return directCaller.test(accessMatcher.apply(condition), text) as Boolean + } + } + + val helper = Helper() + + @JvmStatic + fun invokeDirectConditionNBTStringMatch( + nbt: ConditionNBT, + text: String, + ): Boolean { + return helper.test(nbt, text) + } +} diff --git a/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java b/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java new file mode 100644 index 0000000..0743d40 --- /dev/null +++ b/src/compat/citresewn/java/moe/nea/firmament/mixins/compat/citresewn/MixinConditionComponents.java @@ -0,0 +1,123 @@ +package moe.nea.firmament.mixins.compat.citresewn; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DataResult; +import com.mojang.serialization.DynamicOps; +import moe.nea.firmament.compat.citresewn.ConditionNBTMixin; +import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; +import net.minecraft.component.ComponentType; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.component.type.NbtComponent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import shcm.shsupercm.fabric.citresewn.CITResewn; +import shcm.shsupercm.fabric.citresewn.cit.CITContext; +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionComponents; +import shcm.shsupercm.fabric.citresewn.defaults.cit.conditions.ConditionNBT; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyGroup; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyKey; +import shcm.shsupercm.fabric.citresewn.pack.format.PropertyValue; + +// People are complaining but this really is not my place to fix things + +@Mixin(ConditionComponents.class) +@Pseudo +public class MixinConditionComponents { + @Shadow + private ComponentType componentType; + + @Shadow(remap = false) + private ConditionNBT fallbackNBTCheck; + @Unique + private String[] pathCheck; + @Unique + private int loreInt = -1; + + @Inject(method = "load", at = @At("HEAD"), remap = false) + public void addExtraAttributeSupport(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci, + @Local(argsOnly = true) LocalRef keyRef, + @Local(argsOnly = true) LocalRef valueRef) { + if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableLegacyCIT()) return; + if (!"nbt".equals(key.path())) return; + if (!value.keyMetadata().startsWith("ExtraAttributes.")) return; + keyRef.set(new PropertyKey(key.namespace(), "component")); + valueRef.set(new PropertyValue( + "minecraft:custom_data" + value.keyMetadata().substring("ExtraAttributes".length()), + value.value(), + value.separator(), + value.position(), + value.propertiesIdentifier(), + value.packName() + )); + CITResewn.logWarnLoading(properties.messageWithDescriptorOf("NBT condition is not supported since 1.21. THIS IS A FIRMAMENT SPECIAL FEATURE ALLOWING YOU TO CONTINUE TO USE nbt.ExtraAttributes.* PROPERTIES FOR A LIMITED TIME! UPDATE YOUR .PROPERTIES FILES OR SWITCH TO FIRMAMENT CIT (https://github.com/FirmamentMC/CitToFirm)", + value.position())); + } + + @Inject(method = "load", + at = @At(value = "INVOKE", remap = false, target = "Lshcm/shsupercm/fabric/citresewn/defaults/cit/conditions/ConditionNBT;loadNbtCondition(Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyValue;Lshcm/shsupercm/fabric/citresewn/pack/format/PropertyGroup;[Ljava/lang/String;Ljava/lang/String;)V"), + remap = false) + private void onLoadSavePath(PropertyKey key, PropertyValue value, PropertyGroup properties, CallbackInfo ci, + @Local String[] path) { + this.pathCheck = path; + this.loreInt = -1; + } + + @Unique + private boolean matchStringDirect(String directString, CITContext context) { + return ConditionNBTMixin.invokeDirectConditionNBTStringMatch(fallbackNBTCheck, directString); + } + + @WrapOperation(method = "test", at = @At(value = "INVOKE", target = "Lcom/mojang/serialization/Codec;encodeStart(Lcom/mojang/serialization/DynamicOps;Ljava/lang/Object;)Lcom/mojang/serialization/DataResult;"), remap = false) + DataResult fastPathUnsafeNbtComponent( + Codec instance, + DynamicOps dynamicOps, + Object o, + Operation original) { + if (o instanceof NbtComponent nbtComponent) { + return DataResult.success(nbtComponent.getNbt()); + } + return original.call(instance, dynamicOps, o); + } + + @Inject(method = "test", at = @At("HEAD"), cancellable = true, remap = false) + void fastPathDisplayName(CITContext context, CallbackInfoReturnable cir) { + if (this.componentType == DataComponentTypes.CUSTOM_NAME && pathCheck.length == 0) { + var displayName = context.stack.getComponents().get(DataComponentTypes.CUSTOM_NAME); + if (displayName != null) { + cir.setReturnValue(matchStringDirect((displayName.getString()), context)); + } + } + if (this.componentType == DataComponentTypes.LORE && pathCheck.length == 1) { + var lore = context.stack.getComponents().get(DataComponentTypes.LORE); + if (lore != null) { + var loreLines = lore.lines(); + if (pathCheck[0].equals("*")) { + for (var loreLine : loreLines) { + if (matchStringDirect((loreLine.getString()), context)) { + cir.setReturnValue(true); + return; + } + } + cir.setReturnValue(false); + } else { + if (loreInt < 0) + loreInt = Integer.parseInt(pathCheck[0]); + cir.setReturnValue(0 <= loreInt && loreInt < loreLines.size() && + matchStringDirect((loreLines.get(loreInt).getString()), context)); + } + } + } + } + + +} diff --git a/src/compat/configured/java/BaseConfigNode.kt b/src/compat/configured/java/BaseConfigNode.kt new file mode 100644 index 0000000..afe0375 --- /dev/null +++ b/src/compat/configured/java/BaseConfigNode.kt @@ -0,0 +1,40 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.IConfigEntry +import com.mrcrayfish.configured.api.IConfigValue +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.AllConfigsGui +import moe.nea.firmament.gui.config.ManagedConfig + +object BaseConfigNode : IConfigEntry { + override fun getChildren(): List { + return ManagedConfig.allManagedConfigs.getAll().map { + ConfigNode(it) // TODO: fix add categories here + } + } + + override fun isRoot(): Boolean { + return true + } + + override fun isLeaf(): Boolean { + return false + } + + override fun getValue(): IConfigValue<*>? { + return null + } + + override fun getEntryName(): String { + return "Firmament" + } + + override fun getTooltip(): Text? { + return null + } + + override fun getTranslationKey(): String? { + return null + } + +} diff --git a/src/compat/configured/java/ConfigCategory.kt b/src/compat/configured/java/ConfigCategory.kt new file mode 100644 index 0000000..4e33b8b --- /dev/null +++ b/src/compat/configured/java/ConfigCategory.kt @@ -0,0 +1,48 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.ConfigType +import com.mrcrayfish.configured.api.IConfigEntry +import com.mrcrayfish.configured.api.IModConfig +import com.mrcrayfish.configured.util.ConfigHelper +import java.nio.file.Path +import java.util.function.Consumer +import moe.nea.firmament.Firmament +import moe.nea.firmament.gui.config.ManagedConfig + +class ConfigCategory( + val category: ManagedConfig +) : BaseConfig() { + + override fun getRoot(): IConfigEntry { + return ConfigNode(category) + } + + override fun getTranslationKey(): String? { + return category.translationKey + } +} + +abstract class BaseConfig : IModConfig { + override fun update(p0: IConfigEntry) { + ConfigHelper.getChangedValues(p0).forEach { + it as ConfigValue + it.saveValue() + } + } + + override fun getType(): ConfigType { + return ConfigType.CLIENT + } + + override fun getFileName(): String { + return "" + } + + override fun getModId(): String { + return Firmament.MOD_ID + } + + override fun loadWorldConfig(p0: Path?, p1: Consumer?) { + } + +} diff --git a/src/compat/configured/java/ConfigNode.kt b/src/compat/configured/java/ConfigNode.kt new file mode 100644 index 0000000..16e54a6 --- /dev/null +++ b/src/compat/configured/java/ConfigNode.kt @@ -0,0 +1,39 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.IConfigEntry +import com.mrcrayfish.configured.api.IConfigValue +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.ManagedConfig + +class ConfigNode(val config: ManagedConfig) : IConfigEntry { + override fun getChildren(): List { + return config.allOptions.map { + ConfigValueNode(it.value) + } + } + + override fun isRoot(): Boolean { + return false + } + + override fun isLeaf(): Boolean { + return false + } + + override fun getValue(): IConfigValue<*>? { + return null + } + + override fun getEntryName(): String { + return config.translationKey + } + + override fun getTooltip(): Text? { + return null + } + + override fun getTranslationKey(): String { + return config.translationKey + } + +} diff --git a/src/compat/configured/java/ConfigValue.kt b/src/compat/configured/java/ConfigValue.kt new file mode 100644 index 0000000..e16c51c --- /dev/null +++ b/src/compat/configured/java/ConfigValue.kt @@ -0,0 +1,72 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.IConfigValue +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.ManagedOption + +class ConfigValue(val option: ManagedOption) : IConfigValue { + var value = option.get() + var initialValue = option.get() + + override fun get(): T { + return value + } + + override fun set(p0: T) { + this.value = p0 + } + + override fun getDefault(): T { + return option.default() + } + + override fun isDefault(): Boolean { + // TODO: should this be an option in handlers? + return option == option.default() + } + + override fun isChanged(): Boolean { + return value != initialValue + } + + override fun restore() { + this.value = option.default() + } + + override fun getComment(): Text? { + return null + } + + override fun getTranslationKey(): String? { + return option.rawLabelText + } + + override fun getValidationHint(): Text? { + return null + } + + override fun getName(): String { + return "" + } + + override fun cleanCache() { + + } + + override fun requiresWorldRestart(): Boolean { + return false + } + + override fun requiresGameRestart(): Boolean { + return false + } + + override fun isValid(p0: T): Boolean { + // TODO: should this be validated? + return true + } + + fun saveValue() { + option.set(value) + } +} diff --git a/src/compat/configured/java/ConfigValueNode.kt b/src/compat/configured/java/ConfigValueNode.kt new file mode 100644 index 0000000..df59739 --- /dev/null +++ b/src/compat/configured/java/ConfigValueNode.kt @@ -0,0 +1,37 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.IConfigEntry +import com.mrcrayfish.configured.api.IConfigValue +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.ManagedOption + +class ConfigValueNode(val option: ManagedOption<*>) : IConfigEntry { + override fun getChildren(): List { + return listOf() + } + + override fun isRoot(): Boolean { + return false + } + + override fun isLeaf(): Boolean { + return true + } + + val value = ConfigValue(option) + override fun getValue(): IConfigValue<*>? { + return value + } + + override fun getEntryName(): String { + return option.propertyName + } + + override fun getTooltip(): Text? { + return null + } + + override fun getTranslationKey(): String? { + return option.rawLabelText + } +} diff --git a/src/compat/configured/java/ConfiguredCompat.kt b/src/compat/configured/java/ConfiguredCompat.kt new file mode 100644 index 0000000..8e8b022 --- /dev/null +++ b/src/compat/configured/java/ConfiguredCompat.kt @@ -0,0 +1,30 @@ +package moe.nea.firmament.compat.configured + +import com.mrcrayfish.configured.api.IConfigEntry +import com.mrcrayfish.configured.api.IModConfig +import com.mrcrayfish.configured.api.IModConfigProvider +import com.mrcrayfish.configured.api.ModContext +import moe.nea.firmament.Firmament +import moe.nea.firmament.gui.config.AllConfigsGui +import moe.nea.firmament.gui.config.ManagedConfig + +/** + * Registered in `fabric.mod.json` at `custom.configured.providers` + */ +class ConfiguredCompat : IModConfigProvider { + override fun getConfigurationsForMod(modContext: ModContext): Set { + if (modContext.modId != Firmament.MOD_ID) return emptySet() + return buildSet { + add(object : BaseConfig() { + override fun getRoot(): IConfigEntry { + return BaseConfigNode + } + + override fun getTranslationKey(): String? { + return "firmament.config.all-configs" + } + }) + ManagedConfig.allManagedConfigs.getAll().mapTo(this) { ConfigCategory(it) } + } + } +} diff --git a/src/compat/configured/java/ConfiguredConfigScreenProvider.kt b/src/compat/configured/java/ConfiguredConfigScreenProvider.kt new file mode 100644 index 0000000..c0095bf --- /dev/null +++ b/src/compat/configured/java/ConfiguredConfigScreenProvider.kt @@ -0,0 +1,22 @@ +package moe.nea.firmament.compat.configured + +import com.google.auto.service.AutoService +import com.mrcrayfish.configured.integration.CatalogueConfigFactory +import net.fabricmc.loader.api.FabricLoader +import net.minecraft.client.gui.screen.Screen +import moe.nea.firmament.Firmament +import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider + +@AutoService(FirmamentConfigScreenProvider::class) +class ConfiguredConfigScreenProvider : FirmamentConfigScreenProvider { + override val key: String + get() = "configured" + override val isEnabled: Boolean + get() = FabricLoader.getInstance().isModLoaded("configured") + + override fun open(parent: Screen?): Screen { + return CatalogueConfigFactory.createConfigScreen( + parent, + FabricLoader.getInstance().getModContainer(Firmament.MOD_ID).get()) + } +} diff --git a/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt b/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt new file mode 100644 index 0000000..caf16a5 --- /dev/null +++ b/src/compat/explosiveEnhancement/java/ExplosiveEnhancementSpawner.kt @@ -0,0 +1,17 @@ +package moe.nea.firmament.compat.explosiveenhancement + +import com.google.auto.service.AutoService +import net.superkat.explosiveenhancement.api.ExplosiveApi +import net.minecraft.util.math.Vec3d +import moe.nea.firmament.features.fixes.CompatibliltyFeatures +import moe.nea.firmament.features.fixes.CompatibliltyFeatures.TConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.compatloader.CompatLoader + +@AutoService(CompatibliltyFeatures.ExplosiveApiWrapper::class) +@CompatLoader.RequireMod("explosiveenhancement") +class ExplosiveEnhancementSpawner : CompatibliltyFeatures.ExplosiveApiWrapper { + override fun spawnParticle(vec3d: Vec3d, power: Float) { + ExplosiveApi.spawnParticles(MC.world, vec3d.x, vec3d.y, vec3d.z, TConfig.explosionSize / 10F) + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt new file mode 100644 index 0000000..d1cfef4 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/Compat.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.compat.jade + +import net.fabricmc.loader.api.FabricLoader +import moe.nea.firmament.util.compatloader.CompatMeta +import moe.nea.firmament.util.compatloader.ICompatMeta + +@CompatMeta +object Compat : ICompatMeta { + override fun shouldLoad(): Boolean { + return FabricLoader.getInstance().isModLoaded("jade") + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt new file mode 100644 index 0000000..53e3255 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomFakeBlockProvider.kt @@ -0,0 +1,41 @@ +package moe.nea.firmament.compat.jade + +import snownee.jade.api.Accessor +import snownee.jade.api.BlockAccessor +import snownee.jade.api.IWailaClientRegistration +import snownee.jade.api.callback.JadeRayTraceCallback +import net.minecraft.util.hit.HitResult +import moe.nea.firmament.repo.MiningRepoData +import moe.nea.firmament.util.mc.FirmamentDataComponentTypes + +class CustomFakeBlockProvider(val registration: IWailaClientRegistration) : JadeRayTraceCallback { + + override fun onRayTrace( + hitResult: HitResult, + accessor: Accessor<*>?, + originalAccessor: Accessor<*>? + ): Accessor<*>? { + if (!JadeIntegration.TConfig.blockDetection) return accessor + if (accessor !is BlockAccessor) return accessor + val customBlock = JadeIntegration.customBlocks[accessor.block] + if (customBlock == null) return accessor + return registration.blockAccessor() + .from(accessor) + .fakeBlock(customBlock.getDisplayItem(accessor.block)) + .build() + } + + companion object { + @JvmStatic + fun hasCustomBlock(accessor: BlockAccessor): Boolean { + return getCustomBlock(accessor) != null + } + + @JvmStatic + fun getCustomBlock(accessor: BlockAccessor): MiningRepoData.CustomMiningBlock? { + if (!accessor.isFakeBlock) return null + val item = accessor.fakeBlock + return item.get(FirmamentDataComponentTypes.CUSTOM_MINING_BLOCK_DATA) + } + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt new file mode 100644 index 0000000..29fecd2 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/CustomMiningHardnessProvider.kt @@ -0,0 +1,97 @@ +package moe.nea.firmament.compat.jade + +import snownee.jade.api.BlockAccessor +import snownee.jade.api.IBlockComponentProvider +import snownee.jade.api.ITooltip +import snownee.jade.api.config.IPluginConfig +import kotlin.time.DurationUnit +import net.minecraft.block.BlockState +import net.minecraft.util.Identifier +import net.minecraft.util.math.BlockPos +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.tr + +object CustomMiningHardnessProvider : IBlockComponentProvider { + + override fun appendTooltip( + tooltip: ITooltip, + block: BlockAccessor, + config: IPluginConfig? + ) { + val customBlock = CustomFakeBlockProvider.getCustomBlock(block) ?: return + if (customBlock.breakingPower > 0) + tooltip.add(tr("firmament.jade.breaking_power", "Required Breaking Power: ${customBlock.breakingPower}")) + } + + override fun getUid(): Identifier = + Firmament.identifier("custom_mining_hardness") + + data class BreakingInfo( + val blockPos: BlockPos, val stage: Int, + val state: BlockState?, + val ts: TimeMark = TimeMark.now() + ) + + var previousBreakingInfo: BreakingInfo? = null + var currentBreakingInfo: BreakingInfo? = null + + @Subscribe + fun clearInfoOnStopBreaking(event: TickEvent) { + val isBreakingBlock = MC.interactionManager?.isBreakingBlock ?: false + if (!isBreakingBlock) { + previousBreakingInfo = null + currentBreakingInfo = null + } + } + + @JvmStatic + fun setBreakingInfo(blockPos: BlockPos, stage: Int) { + previousBreakingInfo = currentBreakingInfo + val state = MC.world?.getBlockState(blockPos) + if (previousBreakingInfo?.let { it.state != state || it.blockPos != blockPos } ?: false) + previousBreakingInfo == null + currentBreakingInfo = BreakingInfo(blockPos.toImmutable(), stage, state) + // For some reason hypixel initially sends a stage 10 packet, and then fixes it up with a stage 0 packet. + // Ignore the stage 10 packet if we dont have any previous packets for this block. + // This could in theory still have issues if someone perfectly stops breaking a block the tick it finishes and then does not break another block until it respawns, but i deem that to be too much of an edge case. + if (stage == 10 && previousBreakingInfo == null) { + previousBreakingInfo = null + currentBreakingInfo = null + } + } + + @JvmStatic + fun replaceBreakProgress(original: Float): Float { + if (!JadeIntegration.TConfig.miningProgress) return original + if (!isOnMiningIsland()) return original + val pos = MC.interactionManager?.currentBreakingPos ?: return original + val info = currentBreakingInfo + if (info?.blockPos != pos || info.state != MC.world?.getBlockState(pos)) { + currentBreakingInfo = null + previousBreakingInfo = null + return original + } + // TODO: improve this interpolation to work across all stages, to alleviate some of the jittery bar. + // Maybe introduce a proper mining API that tracks the actual progress with some sort of FSM + val interpolatedStage = previousBreakingInfo?.let { prev -> + val timeBetweenTicks = (info.ts - prev.ts).toDouble(DurationUnit.SECONDS) + val stagesPerUpdate = (info.stage - prev.stage).toDouble() + if (stagesPerUpdate < 1) return@let null + val stagesPerSecond = stagesPerUpdate / timeBetweenTicks + info.stage + (info.ts.passedTime().toDouble(DurationUnit.SECONDS) * stagesPerSecond) + .coerceAtMost(stagesPerUpdate) + }?.toFloat() + val stage = interpolatedStage ?: info.stage.toFloat() + return stage / 10F + } + + @JvmStatic + fun replaceBlockBreakSpeed(original: Float): Float { + if (isOnMiningIsland()) return 0F + return original + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt new file mode 100644 index 0000000..10bff1b --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/DrillToolProvider.kt @@ -0,0 +1,77 @@ +package moe.nea.firmament.compat.jade + +import java.util.Optional +import java.util.function.UnaryOperator +import snownee.jade.api.BlockAccessor +import snownee.jade.api.IBlockComponentProvider +import snownee.jade.api.ITooltip +import snownee.jade.api.JadeIds +import snownee.jade.api.config.IPluginConfig +import snownee.jade.api.theme.IThemeHelper +import snownee.jade.api.ui.IElement +import snownee.jade.api.ui.IElementHelper +import snownee.jade.impl.ui.ItemStackElement +import snownee.jade.impl.ui.TextElement +import kotlin.jvm.optionals.getOrDefault +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import net.minecraft.util.math.Vec2f +import moe.nea.firmament.Firmament +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.MC + +class DrillToolProvider : IBlockComponentProvider { + @OptIn(ExpensiveItemCacheApi::class) + override fun appendTooltip( + tooltip: ITooltip, + accessor: BlockAccessor, + p2: IPluginConfig? + ) { + val customBlock = CustomFakeBlockProvider.getCustomBlock(accessor) ?: return + val tool = RepoManager.miningData.getToolsThatCanBreak(customBlock.breakingPower).firstOrNull() + ?.asImmutableItemStack() ?: return + tooltip.replace(JadeIds.MC_HARVEST_TOOL, UnaryOperator { elements -> + elements.map { inner -> + val lastItemIndex = inner.indexOfLast { it is ItemStackElement } + if (lastItemIndex < 0) return@map inner + val innerMut = inner.toMutableList() + val harvestIndicator = innerMut.indexOfLast { + it is TextElement && it.cachedSize == Vec2f.ZERO && it.text.visit { + if (it.isEmpty()) Optional.empty() else Optional.of(true) + }.getOrDefault(false) + } + val canHarvest = SBItemStack(MC.stackInHand).breakingPower >= customBlock.breakingPower + val lastItem = innerMut[lastItemIndex] as ItemStackElement + if (harvestIndicator < 0) { + innerMut.add(lastItemIndex + 1, canHarvestIndicator(canHarvest, lastItem.alignment)) + } else { + innerMut.set(harvestIndicator, canHarvestIndicator(canHarvest, lastItem.alignment)) + } + innerMut.set(lastItemIndex, IElementHelper.get() + .item(tool, 0.75f) + .translate(lastItem.translation) + .size(lastItem.size) + .message(null) + .align(lastItem.alignment)) + innerMut.subList(0, lastItemIndex - 1).removeIf { it is ItemStackElement } + innerMut + } + }) + } + + fun canHarvestIndicator(canHarvest: Boolean, align: IElement.Align): IElement { + val t = IThemeHelper.get() + val text = if (canHarvest) t.success(CHECK) else t.danger(X) + return IElementHelper.get().text(text) + .scale(0.75F).zOffset(800).size(Vec2f.ZERO).translate(Vec2f(-3F, 3.25F)).align(align) + } + + private val CHECK: Text = Text.literal("✔") + private val X: Text = Text.literal("✕") + + override fun getUid(): Identifier { + return Firmament.identifier("toolprovider") + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt new file mode 100644 index 0000000..51e2453 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/FirmamentJadePlugin.kt @@ -0,0 +1,21 @@ +package moe.nea.firmament.compat.jade + +import snownee.jade.api.IWailaClientRegistration +import snownee.jade.api.IWailaCommonRegistration +import snownee.jade.api.IWailaPlugin +import snownee.jade.api.WailaPlugin +import net.minecraft.block.Block +import moe.nea.firmament.Firmament + +@WailaPlugin +class FirmamentJadePlugin : IWailaPlugin { + override fun register(registration: IWailaCommonRegistration) { + Firmament.logger.debug("Registering Jade integration...") + } + + override fun registerClient(registration: IWailaClientRegistration) { + registration.registerBlockComponent(CustomMiningHardnessProvider, Block::class.java) + registration.registerBlockComponent(DrillToolProvider(), Block::class.java) + registration.addRayTraceCallback(CustomFakeBlockProvider(registration)) + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt new file mode 100644 index 0000000..d411c26 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/JadeIntegration.kt @@ -0,0 +1,50 @@ +package moe.nea.firmament.compat.jade + +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.SkyblockServerUpdateEvent +import moe.nea.firmament.repo.MiningRepoData +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.ErrorUtil +import net.minecraft.block.Block +import moe.nea.firmament.events.ReloadRegistrationEvent +import moe.nea.firmament.gui.config.ManagedConfig + +object JadeIntegration { + object TConfig : ManagedConfig("jade-integration", Category.INTEGRATIONS) { + val miningProgress by toggle("progress") { true } + val blockDetection by toggle("blocks") { true } + } + + var customBlocks: Map = mapOf() + + fun refreshBlockInfo() { + if (!isOnMiningIsland()) { + customBlocks = mapOf() + return + } + val blocks = RepoManager.miningData.customMiningBlocks + .flatMap { customBlock -> + // TODO: add a lifted helper method for this + customBlock.blocks189.filter { it.isCurrentlyActive } + .mapNotNull { it.block } + .map { customBlock to it } + } + .groupBy { it.second } + customBlocks = blocks.mapNotNull { (block, customBlocks) -> + val singleMatch = + ErrorUtil.notNullOr(customBlocks.singleOrNull()?.first, + "Two custom blocks both want to supply custom mining behaviour for $block.") { return@mapNotNull null } + block to singleMatch + }.toMap() + } + + @Subscribe + fun onRepoReload(event: ReloadRegistrationEvent) { + event.repo.registerReloadListener { refreshBlockInfo() } + } + + @Subscribe + fun onWorldSwap(event: SkyblockServerUpdateEvent) { + refreshBlockInfo() + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt b/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt new file mode 100644 index 0000000..364dc02 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/compat/jade/utils.kt @@ -0,0 +1,6 @@ +package moe.nea.firmament.compat.jade + +import moe.nea.firmament.util.SBData + +fun isOnMiningIsland(): Boolean = + SBData.skyblockLocation?.hasCustomMining ?: false diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java new file mode 100644 index 0000000..1b58e3c --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/ElementAccessor.java @@ -0,0 +1,12 @@ +package moe.nea.firmament.mixins.compat.jade; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import snownee.jade.api.ui.Element; +import snownee.jade.api.ui.IElement; + +@Mixin(Element.class) +public interface ElementAccessor { + @Accessor("align") + IElement.Align getAlign_firmament(); +} diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java new file mode 100644 index 0000000..3677d01 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/EnforceToolDisplayForCustomBlocksInHarvestToolProvider.java @@ -0,0 +1,33 @@ +package moe.nea.firmament.mixins.compat.jade; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.compat.jade.CustomFakeBlockProvider; +import net.minecraft.block.Blocks; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import snownee.jade.addon.harvest.HarvestToolProvider; +import snownee.jade.api.BlockAccessor; + +import java.util.List; + +@Mixin(HarvestToolProvider.class) +public class EnforceToolDisplayForCustomBlocksInHarvestToolProvider { + @ModifyExpressionValue(method = "getText", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;isToolRequired()Z")) + private boolean overwriteRequiresTool(boolean original, @Local(argsOnly = true) BlockAccessor accessor) { + if (CustomFakeBlockProvider.hasCustomBlock(accessor)) + return true; + return original; + } + + private static final List REPLACEABLE_TOOL = List.of(new ItemStack(Blocks.ENCHANTING_TABLE)); + + @ModifyExpressionValue(method = "getText", at = @At(value = "INVOKE", target = "Lcom/google/common/cache/Cache;get(Ljava/lang/Object;Ljava/util/concurrent/Callable;)Ljava/lang/Object;")) + private Object overwriteAvailableTools(Object original, @Local(argsOnly = true) BlockAccessor accessor) { + var orig = (List) original; + if (orig.isEmpty() && CustomFakeBlockProvider.hasCustomBlock(accessor)) + return REPLACEABLE_TOOL; + return orig; + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java new file mode 100644 index 0000000..7d71ae8 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/OnUpdateBreakProgress.java @@ -0,0 +1,22 @@ +package moe.nea.firmament.mixins.compat.jade; + +import moe.nea.firmament.compat.jade.CustomMiningHardnessProvider; +import moe.nea.firmament.util.MC; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; + +@Mixin(WorldRenderer.class) +public class OnUpdateBreakProgress { + @Inject(method = "setBlockBreakingInfo", at = @At("HEAD")) + private void replaceBreakProgress(int entityId, BlockPos pos, int stage, CallbackInfo ci) { + if (entityId == 0 && null != MC.INSTANCE.getInteractionManager() && Objects.equals(MC.INSTANCE.getInteractionManager().currentBreakingPos, pos)) { + CustomMiningHardnessProvider.setBreakingInfo(pos, stage); + } + } +} diff --git a/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java new file mode 100644 index 0000000..203f7e4 --- /dev/null +++ b/src/compat/jade/java/moe/nea/firmament/mixins/compat/jade/PatchBreakingBarSpeedJade.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.mixins.compat.jade; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.compat.jade.CustomMiningHardnessProvider; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import snownee.jade.JadeClient; + +@Mixin(JadeClient.class) +public class PatchBreakingBarSpeedJade { + @ModifyExpressionValue( + method = "drawBreakingProgress", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/network/ClientPlayerInteractionManager;currentBreakingProgress:F", opcode = Opcodes.GETFIELD) + ) + private static float replaceBlockBreakingProgress(float original) { + return CustomMiningHardnessProvider.replaceBreakProgress(original); + } + + @ModifyExpressionValue(method = "drawBreakingProgress", + at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;calcBlockBreakingDelta(Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)F")) + private static float replacePlayerSpecificBreakingProgress(float original) { + return CustomMiningHardnessProvider.replaceBlockBreakSpeed(original); + } +} diff --git a/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt b/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt new file mode 100644 index 0000000..ff58c20 --- /dev/null +++ b/src/compat/modmenu/java/moe/nea/firmament/compat/modmenu/FirmamentModMenuPlugin.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.compat.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(parent = it) } + } +} diff --git a/src/compat/moulconfig/java/MCConfigEditorIntegration.kt b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt new file mode 100644 index 0000000..874e58d --- /dev/null +++ b/src/compat/moulconfig/java/MCConfigEditorIntegration.kt @@ -0,0 +1,438 @@ +package moe.nea.firmament.compat.moulconfig + +import com.google.auto.service.AutoService +import io.github.notenoughupdates.moulconfig.ChromaColour +import io.github.notenoughupdates.moulconfig.Config +import io.github.notenoughupdates.moulconfig.DescriptionRendereringBehaviour +import io.github.notenoughupdates.moulconfig.Social +import io.github.notenoughupdates.moulconfig.common.IMinecraft +import io.github.notenoughupdates.moulconfig.common.MyResourceLocation +import io.github.notenoughupdates.moulconfig.gui.GuiComponent +import io.github.notenoughupdates.moulconfig.gui.GuiElementWrapper +import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor +import io.github.notenoughupdates.moulconfig.gui.HorizontalAlign +import io.github.notenoughupdates.moulconfig.gui.MoulConfigEditor +import io.github.notenoughupdates.moulconfig.gui.VerticalAlign +import io.github.notenoughupdates.moulconfig.gui.component.AlignComponent +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.gui.editors.ComponentEditor +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorAccordion +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorBoolean +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorButton +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorColour +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorDropdown +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorText +import io.github.notenoughupdates.moulconfig.observer.GetSetter +import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory +import io.github.notenoughupdates.moulconfig.processor.ProcessedOption +import java.lang.reflect.Type +import java.net.URI +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.DurationUnit +import net.minecraft.client.gui.screen.Screen +import net.minecraft.util.Identifier +import net.minecraft.util.StringIdentifiable +import net.minecraft.util.Util +import moe.nea.firmament.Firmament +import moe.nea.firmament.gui.config.AllConfigsGui +import moe.nea.firmament.gui.config.BooleanHandler +import moe.nea.firmament.gui.config.ChoiceHandler +import moe.nea.firmament.gui.config.ClickHandler +import moe.nea.firmament.gui.config.ColourHandler +import moe.nea.firmament.gui.config.DurationHandler +import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider +import moe.nea.firmament.gui.config.HudMeta +import moe.nea.firmament.gui.config.HudMetaHandler +import moe.nea.firmament.gui.config.IntegerHandler +import moe.nea.firmament.gui.config.KeyBindingHandler +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.gui.config.StringHandler +import moe.nea.firmament.gui.toMoulConfig +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MoulConfigUtils.xmap + +@AutoService(FirmamentConfigScreenProvider::class) +class MCConfigEditorIntegration : FirmamentConfigScreenProvider { + override val key: String + get() = "moulconfig" + + val handlers: MutableMap>, ((ManagedConfig.OptionHandler<*>, ManagedOption<*>, accordionId: Int, configObject: Config) -> ProcessedEditableOptionFirm<*>)> = + mutableMapOf() + + fun > register( + handlerClass: Class, + transform: (H, ManagedOption, accordionId: Int, configObject: Config) -> ProcessedEditableOptionFirm + ) { + handlers[handlerClass] = + transform as ((ManagedConfig.OptionHandler<*>, ManagedOption<*>, accordionId: Int, configObject: Config) -> ProcessedEditableOptionFirm<*>) + } + + fun getHandler( + option: ManagedOption, + accordionId: Int, + configObject: Config + ): ProcessedEditableOptionFirm<*> { + val transform = handlers[option.handler.javaClass] + ?: error("Could not transform ${option.handler}") // TODO: replace with soft error and an error config element + return transform.invoke(option.handler, option, accordionId, configObject) as ProcessedEditableOptionFirm + } + + class CustomSliderEditor( + option: ProcessedOption, + setter: GetSetter, + fromT: (T) -> Float, + toT: (Float) -> T, + minValue: T, maxValue: T, + minStep: Float, + formatter: (T) -> String, + ) : ComponentEditor(option) { + override fun getDelegate(): GuiComponent { + return delegateI + } + + val mappedSetter = setter.xmap(fromT, toT) + + private val delegateI by lazy { + wrapComponent( + RowComponent( + AlignComponent( + TextComponent( + IMinecraft.instance.defaultFontRenderer, + { formatter(setter.get()) }, + 25, + TextComponent.TextAlignment.CENTER, false, false + ), + GetSetter.constant(HorizontalAlign.CENTER), + GetSetter.constant(VerticalAlign.CENTER) + ), + SliderComponent( + mappedSetter, + fromT(minValue), + fromT(maxValue), + minStep, + 40 + ) + ) + ) + } + } + + fun helpRegisterChoice() where T : Enum, T : StringIdentifiable { + register(ChoiceHandler::class.java as Class>) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorDropdown( + this, + handler.universe.map { handler.renderer.getName(option, it).string }.toTypedArray() + ) + } + + override fun toT(any: Any?): T? { + return handler.universe[any as Int] + } + + override fun getType(): Type { + return Int::class.java + } + + override fun fromT(t: T): Any { + return t.ordinal + } + } + } + } + + init { + helpRegisterChoice() + register(BooleanHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorBoolean(this, -1, configObject) + } + + override fun toT(any: Any?): Boolean? { + return any as Boolean + } + + override fun getType(): Type { + return Boolean::class.java + } + + override fun fromT(t: Boolean): Any { + return t + } + } + } + register(StringHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorText(this) + } + + override fun getType(): Type { + return String::class.java + } + + override fun fromT(t: String): Any { + return t + } + + override fun toT(any: Any?): String? { + return any as String + } + } + } + register(ColourHandler::class.java) { handler, option, accordionId, configObject -> + object : ProcessedEditableOptionFirm(option, accordionId, configObject) { + override fun fromT(t: ChromaColour): Any { + return t + } + + override fun toT(any: Any?): ChromaColour? { + return any as ChromaColour? + } + + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorColour(this) + } + + override fun getType(): Type? { + return ChromaColour::class.java + } + } + + } + register(ClickHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorButton(this, -1, "Click", configObject) + } + + override fun toT(any: Any?): Unit? { + return null + } + + override fun fromT(t: Unit): Any { + return Runnable { handler.runnable() } + } + + override fun getType(): Type { + return Runnable::class.java + } + } + } + register(HudMetaHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorButton(this, -1, "Edit HUD", configObject) + } + + override fun fromT(t: HudMeta): Any { + return Runnable { + handler.openEditor(option, MC.screen!!) + } + } + + + override fun getType(): Type { + return Runnable::class.java + } + + override fun toT(any: Any?): HudMeta? = null + } + } + register(DurationHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return CustomSliderEditor( + this, + option, + { it.toDouble(DurationUnit.SECONDS).toFloat() }, + { it.toDouble().seconds }, + handler.min, + handler.max, + 0.1F, + FirmFormatters::formatTimespan + ) + } + + override fun toT(any: Any?): Duration? = null + override fun fromT(t: Duration): Any { + ErrorUtil.softError("Getting on a slider component") + return Unit + } + + override fun getType(): Type { + return Nothing::class.java + } + + } + } + register(IntegerHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return CustomSliderEditor( + this, + option, + { it.toFloat() }, + { it.toInt() }, + handler.min, + handler.max, + 1F, + Integer::toString + ) + } + + override fun toT(any: Any?): Int? = null + override fun fromT(t: Int): Any { + ErrorUtil.softError("Getting on a slider component") + return Unit + } + + override fun getType(): Type { + return Nothing::class.java + } + } + } + register(KeyBindingHandler::class.java) { handler, option, categoryAccordionId, configObject -> + object : ProcessedEditableOptionFirm(option, categoryAccordionId, configObject) { + override fun createEditor(): GuiOptionEditor { + return object : ComponentEditor(this) { + val button = wrapComponent(handler.createButtonComponent(option)) + override fun getDelegate(): GuiComponent { + return button + } + } + } + + override fun toT(any: Any?): SavedKeyBinding? { + return null + } + + override fun getType(): Type { + return Nothing::class.java + } + + override fun fromT(t: SavedKeyBinding): Any { + ErrorUtil.softError("Cannot get a keybinding editor") + return Unit + } + } + } + } + + val configObject = object : Config() { + override fun saveNow() { + ManagedConfig.allManagedConfigs.getAll().forEach { it.save() } + } + + override fun shouldAutoFocusSearchbar(): Boolean { + return true + } + + override fun getTitle(): String { + return "Firmament ${Firmament.version.friendlyString}" + } + + @Deprecated("Deprecated in java") + override fun executeRunnable(runnableId: Int) { + if (runnableId >= 0) + ErrorUtil.softError("Executed runnable $runnableId") + } + + override fun getDescriptionBehaviour(option: ProcessedOption?): DescriptionRendereringBehaviour { + return DescriptionRendereringBehaviour.EXPAND_PANEL + } + + fun mkSocial(name: String, identifier: Identifier, link: String) = object : Social() { + override fun onClick() { + Util.getOperatingSystem().open(URI(link)) + } + + override fun getTooltip(): List { + return listOf(name) + } + + override fun getIcon(): MyResourceLocation { + return identifier.toMoulConfig() + } + } + + private val socials = listOf( + mkSocial( + "Discord", Firmament.identifier("textures/socials/discord.png"), + Firmament.modContainer.metadata.contact.get("discord").get() + ), + mkSocial( + "Source Code", Firmament.identifier("textures/socials/git.png"), + Firmament.modContainer.metadata.contact.get("sources").get() + ), + mkSocial( + "Modrinth", Firmament.identifier("textures/socials/modrinth.png"), + Firmament.modContainer.metadata.contact.get("modrinth").get() + ), + ) + + override fun getSocials(): List { + return socials + } + } + val categories = ManagedConfig.Category.entries.map { + val options = mutableListOf() + var nextAccordionId = 720 + it.configs.forEach { config -> + val categoryAccordionId = nextAccordionId++ + options.add(object : ProcessedOptionFirm(-1, configObject) { + override fun getDebugDeclarationLocation(): String { + return "FirmamentConfig:${config.name}" + } + + override fun getName(): String { + return config.labelText.string + } + + override fun getDescription(): String { + return "Missing description" + } + + override fun get(): Any { + return Unit + } + + override fun getType(): Type { + return Unit.javaClass + } + + override fun set(value: Any?): Boolean { + return false + } + + override fun createEditor(): GuiOptionEditor { + return GuiOptionEditorAccordion(this, categoryAccordionId) + } + }) + config.allOptions.forEach { (key, option) -> + val processedOption = getHandler(option, categoryAccordionId, configObject) + options.add(processedOption) + } + } + + return@map ProcessedCategoryFirm(it, options) + } + + override fun open(search: String?, parent: Screen?): Screen { + val editor = MoulConfigEditor(ProcessedCategory.collect(categories), configObject) + if (search != null) + editor.search(search) + editor.setWide(AllConfigsGui.ConfigConfig.enableWideMC) + return GuiElementWrapper(editor) // TODO : add parent support + } + +} diff --git a/src/compat/moulconfig/java/ProcessedCategoryFirm.kt b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt new file mode 100644 index 0000000..5313441 --- /dev/null +++ b/src/compat/moulconfig/java/ProcessedCategoryFirm.kt @@ -0,0 +1,47 @@ +package moe.nea.firmament.compat.moulconfig + +import io.github.notenoughupdates.moulconfig.gui.editors.GuiOptionEditorAccordion +import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory +import io.github.notenoughupdates.moulconfig.processor.ProcessedOption +import moe.nea.firmament.gui.config.ManagedConfig + +class ProcessedCategoryFirm( + val category: ManagedConfig.Category, + private val options: List +) : ProcessedCategory { + val accordions = options.filter { it.editor is GuiOptionEditorAccordion } + .associateBy { (it.editor as GuiOptionEditorAccordion).accordionId } + init { + for (option in options) { + option.category = this + } + } + + override fun getDebugDeclarationLocation(): String? { + return "FirmamentCategory.${category.name}" + } + + override fun getDisplayName(): String { + return category.labelText.string + } + + override fun getDescription(): String { + return category.description.string + } + + override fun getIdentifier(): String { + return category.name + } + + override fun getParentCategoryId(): String? { + return null + } + + override fun getOptions(): List { + return options + } + + override fun getAccordionAnchors(): Map { + return accordions + } +} diff --git a/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt new file mode 100644 index 0000000..f0e9aa4 --- /dev/null +++ b/src/compat/moulconfig/java/ProcessedEditableOptionFirm.kt @@ -0,0 +1,44 @@ +package moe.nea.firmament.compat.moulconfig + +import io.github.notenoughupdates.moulconfig.Config +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.util.ErrorUtil + +abstract class ProcessedEditableOptionFirm( + val managedOption: ManagedOption, + categoryAccordionId: Int, + configObject: Config, +) : ProcessedOptionFirm(categoryAccordionId, configObject) { + val managedConfig = managedOption.element + override fun getDebugDeclarationLocation(): String { + return "FirmamentOption:${managedConfig.name}:${managedOption.propertyName}" + } + + override fun getName(): String { + return managedOption.labelText.string + } + + override fun getDescription(): String { + return managedOption.labelDescription.string + } + + abstract fun fromT(t: T): Any + abstract fun toT(any: Any?): T? + + final override fun get(): Any { + return fromT(managedOption.value) + } + + final override fun set(p0: Any?): Boolean { + managedOption.value = toT(p0) ?: run { + ErrorUtil.softError("Failed to set value p0 in $this") + return false + } + managedConfig.save() + return true + } + + override fun explicitNotifyChange() { + managedConfig.save() + } +} diff --git a/src/compat/moulconfig/java/ProcessedOptionFirm.kt b/src/compat/moulconfig/java/ProcessedOptionFirm.kt new file mode 100644 index 0000000..6936048 --- /dev/null +++ b/src/compat/moulconfig/java/ProcessedOptionFirm.kt @@ -0,0 +1,42 @@ +package moe.nea.firmament.compat.moulconfig + +import io.github.notenoughupdates.moulconfig.Config +import io.github.notenoughupdates.moulconfig.annotations.SearchTag +import io.github.notenoughupdates.moulconfig.gui.GuiOptionEditor +import io.github.notenoughupdates.moulconfig.processor.ProcessedCategory +import io.github.notenoughupdates.moulconfig.processor.ProcessedOption + +abstract class ProcessedOptionFirm( + private val accordionId: Int, + private val config: Config +) : ProcessedOption { + override fun getPath(): String? { + return "nonsense" + } + lateinit var category: ProcessedCategoryFirm + override fun getAccordionId(): Int { + return accordionId + } + + protected abstract fun createEditor(): GuiOptionEditor + val editorInstance by lazy { createEditor() } + + override fun getSearchTags(): Array { + return emptyArray() + } + + override fun getEditor(): GuiOptionEditor { + return editorInstance + } + + override fun getCategory(): ProcessedCategory { + return category + } + + override fun getConfig(): Config { + return config + } + + override fun explicitNotifyChange() { + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt new file mode 100644 index 0000000..9ab4d22 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/Compat.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.compat.rei + +import net.fabricmc.loader.api.FabricLoader +import moe.nea.firmament.util.compatloader.CompatMeta +import moe.nea.firmament.util.compatloader.ICompatMeta + +@CompatMeta +object Compat : ICompatMeta { + override fun shouldLoad(): Boolean { + return FabricLoader.getInstance().isModLoaded("roughlyenoughitems") + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt new file mode 100644 index 0000000..1097654 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt @@ -0,0 +1,54 @@ +package moe.nea.firmament.compat.rei + +import me.shedaniel.math.Dimension +import me.shedaniel.math.FloatingDimension +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 +import moe.nea.firmament.gui.entity.EntityRenderer +import moe.nea.firmament.util.ErrorUtil + + +class EntityWidget( + val entity: LivingEntity?, + val point: Point, + val size: FloatingDimension = FloatingDimension(defaultSize) +) : WidgetWithBounds() { + override fun children(): List { + 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, + size.width, size.height, + mouseX.toDouble(), + mouseY.toDouble()) + } + } catch (ex: Exception) { + ErrorUtil.softError("Failed to render constructed entity: $entity", ex) + hasErrored = true + } finally { + } + if (hasErrored) { + context.fill(point.x, point.y, point.x + size.width.toInt(), point.y + size.height.toInt(), 0xFFAA2222.toInt()) + } + } + + companion object { + val defaultSize = Dimension(50, 80) + } + + override fun getBounds(): Rectangle { + return Rectangle(point, size) + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt new file mode 100644 index 0000000..71e867a --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiCommonPlugin.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.compat.rei + +import me.shedaniel.rei.api.common.entry.type.EntryTypeRegistry +import me.shedaniel.rei.api.common.plugins.REICommonPlugin +import moe.nea.firmament.repo.RepoManager + +class FirmamentReiCommonPlugin : REICommonPlugin { + override fun registerEntryTypes(registry: EntryTypeRegistry) { + if (!RepoManager.shouldLoadREI()) return + registry.register(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID, SBItemEntryDefinition) + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt new file mode 100644 index 0000000..3a494b9 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/FirmamentReiPlugin.kt @@ -0,0 +1,172 @@ +package moe.nea.firmament.compat.rei + +import io.github.moulberry.repo.data.NEUCraftingRecipe +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.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.compat.rei.recipes.GenericREIRecipeCategory +import moe.nea.firmament.compat.rei.recipes.SBKatRecipe +import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe +import moe.nea.firmament.compat.rei.recipes.SBRecipe +import moe.nea.firmament.compat.rei.recipes.SBReforgeRecipe +import moe.nea.firmament.compat.rei.recipes.SBShopRecipe +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.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.repo.recipes.SBCraftingRecipeRenderer +import moe.nea.firmament.repo.recipes.SBEssenceUpgradeRecipeRenderer +import moe.nea.firmament.repo.recipes.SBForgeRecipeRenderer +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.guessRecipeId +import moe.nea.firmament.util.skyblockId +import moe.nea.firmament.util.unformattedString + + +class FirmamentReiPlugin : REIClientPlugin { + + companion object { + @ExpensiveItemCacheApi + fun EntryStack.asItemEntry(): EntryStack { + return EntryStack.of(VanillaEntryTypes.ITEM, value.asImmutableItemStack()) + } + + val SKYBLOCK_ITEM_TYPE_ID = Identifier.of("firmament", "skyblockitems") + } + + @OptIn(ExpensiveItemCacheApi::class) + override fun registerTransferHandlers(registry: TransferHandlerRegistry) { + if (!RepoManager.shouldLoadREI()) return + registry.register(TransferHandler { context -> + val screen = context.containerScreen + val display = context.display + if (display !is SBRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable() + val recipe = display.neuRecipe + if (recipe !is NEUCraftingRecipe) return@TransferHandler TransferHandler.Result.createNotApplicable() + val neuItem = RepoManager.getNEUItem(SkyblockId(recipe.output.itemId)) + ?: error("Could not find neu item ${recipe.output.itemId} which is used in a recipe output") + val useSuperCraft = context.isStackedCrafting || RepoManager.Config.alwaysSuperCraft + if (neuItem.isVanilla && useSuperCraft) return@TransferHandler TransferHandler.Result.createFailed( + Text.translatable( + "firmament.recipe.novanilla" + ) + ) + var shouldReturn = true + if (context.isActuallyCrafting && !useSuperCraft) { + val craftingScreen = (screen as? GenericContainerScreen) + ?.takeIf { it.title?.unformattedString == CraftingOverlay.CRAFTING_SCREEN_NAME } + if (craftingScreen == null) { + MC.sendCommand("craft") + shouldReturn = false + } + CraftingOverlay.setOverlay(craftingScreen, recipe) + } + if (context.isActuallyCrafting && useSuperCraft) { + shouldReturn = false + MC.sendCommand("viewrecipe ${neuItem.guessRecipeId()}") + } + return@TransferHandler TransferHandler.Result.createSuccessful().blocksFurtherHandling(shouldReturn) + }) + } + + + val generics = listOf>( + // Order matters: The order in here is the order in which they show up in REI + GenericREIRecipeCategory(SBCraftingRecipeRenderer), + GenericREIRecipeCategory(SBForgeRecipeRenderer), + GenericREIRecipeCategory(SBEssenceUpgradeRecipeRenderer), + ) + + override fun registerCategories(registry: CategoryRegistry) { + if (!RepoManager.shouldLoadREI()) return + + registry.add(generics) + registry.add(SBMobDropRecipe.Category) + registry.add(SBKatRecipe.Category) + registry.add(SBReforgeRecipe.Category) + registry.add(SBShopRecipe.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) { + if (!RepoManager.shouldLoadREI()) return + + generics.forEach { + it.registerDynamicGenerator(registry) + } + registry.registerDisplayGenerator( + SBReforgeRecipe.catIdentifier, + SBReforgeRecipe.DynamicGenerator + ) + registry.registerDisplayGenerator( + SBMobDropRecipe.Category.categoryIdentifier, + SkyblockMobDropRecipeDynamicGenerator + ) + registry.registerDisplayGenerator( + SBShopRecipe.Category.categoryIdentifier, + SkyblockShopRecipeDynamicGenerator + ) + registry.registerDisplayGenerator( + SBKatRecipe.Category.categoryIdentifier, + SkyblockKatRecipeDynamicGenerator + ) + } + + override fun registerCollapsibleEntries(registry: CollapsibleEntryRegistry) { + if (!RepoManager.shouldLoadREI()) return + + 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 isHandingScreen(screen: Class?): Boolean { + return screen == StorageOverlayScreen::class.java + } + + override fun shouldScreenBeOverlaid(screen: R): ActionResult { + return ActionResult.SUCCESS + } + }) + registry.registerFocusedStack(SkyblockItemIdFocusedStackProvider) + } + + override fun registerEntries(registry: EntryRegistry) { + if (!RepoManager.shouldLoadREI()) return + + registry.removeEntryIf { true } + RepoManager.neuRepo.items?.items?.values?.forEach { neuItem -> + registry.addEntry(SBItemEntryDefinition.getEntry(neuItem.skyblockId)) + } + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt new file mode 100644 index 0000000..b917c3e --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/HoveredItemStackProvider.kt @@ -0,0 +1,38 @@ +package moe.nea.firmament.compat.rei + +import com.google.auto.service.AutoService +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.util.HoveredItemStackProvider +import moe.nea.firmament.util.compatloader.CompatLoader + +@AutoService(HoveredItemStackProvider::class) +@CompatLoader.RequireMod("roughlyenoughitems") +class ScreenRegistryHoveredItemStackProvider : HoveredItemStackProvider { + override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? { + val entryStack = ScreenRegistry.getInstance().getFocusedStack(screen, PointHelper.ofMouse()) + ?: return null + return entryStack.value as? ItemStack ?: entryStack.cheatsAs().value + } +} + +@AutoService(HoveredItemStackProvider::class) +@CompatLoader.RequireMod("roughlyenoughitems") +class OverlayHoveredItemStackProvider : HoveredItemStackProvider { + override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? { + 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/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt new file mode 100644 index 0000000..5e4eee3 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntryRenderer.kt @@ -0,0 +1,123 @@ +/* + * SPDX-FileCopyrightText: 2018-2023 shedaniel + * SPDX-FileCopyrightText: 2023 Linnea Gräf + * SPDX-FileCopyrightText: 2024 Linnea Gräf + * + * SPDX-License-Identifier: GPL-3.0-or-later + * SPDX-License-Identifier: MIT + */ + +package moe.nea.firmament.compat.rei + +import me.shedaniel.math.Rectangle +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.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.DrawContext +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.item.tooltip.TooltipType +import net.minecraft.text.Text +import moe.nea.firmament.events.ItemTooltipEvent +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.ItemCache +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.darkGrey +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt + +// TODO: make this re implement BatchedEntryRenderer, if possible (likely not, due to no-alloc rendering) +// Also it is probably not even that much faster now, with render layers. +object NEUItemEntryRenderer : EntryRenderer { + @OptIn(ExpensiveItemCacheApi::class) + override fun render( + entry: EntryStack, + context: DrawContext, + bounds: Rectangle, + mouseX: Int, + mouseY: Int, + delta: Float + ) { + val neuItem = entry.value.neuItem + val itemToRender = if(!RepoManager.Config.perfectRenders.rendersPerfectVisuals() && !entry.value.isWarm() && neuItem != null) { + ItemCache.recacheSoon(neuItem) + ItemStack(Items.PAINTING) + } else { + entry.value.asImmutableItemStack() + } + + context.matrices.push() + context.matrices.translate(bounds.centerX.toFloat(), bounds.centerY.toFloat(), 0F) + context.matrices.scale(bounds.width.toFloat() / 16F, bounds.height.toFloat() / 16F, 1f) + context.drawItemWithoutEntity(itemToRender, -8, -8) + context.drawStackOverlay( + minecraft.textRenderer, itemToRender, -8, -8, + if (entry.value.getStackSize() > 1000) FirmFormatters.shortFormat( + entry.value.getStackSize() + .toDouble() + ) + else null + ) + context.matrices.pop() + } + + val minecraft = MinecraftClient.getInstance() + var canUseVanillaTooltipEvents = true + + @OptIn(ExpensiveItemCacheApi::class) + override fun getTooltip(entry: EntryStack, tooltipContext: TooltipContext): Tooltip? { + if (!entry.value.isWarm() && !RepoManager.Config.perfectRenders.rendersPerfectText()) { + val neuItem = entry.value.neuItem + if (neuItem != null) { + val lore = mutableListOf() + lore.add(Text.literal(neuItem.displayName)) + neuItem.lore.mapTo(mutableListOf()) { Text.literal(it) } + return Tooltip.create(lore) + } + } + + val stack = entry.value.asImmutableItemStack() + + val lore = mutableListOf(stack.displayNameAccordingToNbt) + lore.addAll(stack.loreAccordingToNbt) + if (canUseVanillaTooltipEvents) { + try { + ItemTooltipCallback.EVENT.invoker().getTooltip( + stack, tooltipContext.vanillaContext(), TooltipType.BASIC, lore + ) + } catch (ex: Exception) { + canUseVanillaTooltipEvents = false + ErrorUtil.softError("Failed to use vanilla tooltips", ex) + } + } else { + ItemTooltipEvent.publish( + ItemTooltipEvent( + stack, + tooltipContext.vanillaContext(), + TooltipType.BASIC, + lore + ) + ) + } + if (entry.value.getStackSize() > 1000 && lore.isNotEmpty()) + lore.add(1, Text.literal("${entry.value.getStackSize()}x").darkGrey()) + // TODO: tags aren't sent as early now so some tooltip components that use tags will crash the game +// stack.getTooltip( +// Item.TooltipContext.create( +// tooltipContext.vanillaContext().registryLookup +// ?: MC.defaultRegistries +// ), +// MC.player, +// TooltipType.BASIC +// ) + return Tooltip.create(lore) + } + + +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt new file mode 100644 index 0000000..724d193 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/NEUItemEntrySerializer.kt @@ -0,0 +1,17 @@ +package moe.nea.firmament.compat.rei + +import com.mojang.serialization.Codec +import me.shedaniel.rei.api.common.entry.EntrySerializer +import net.minecraft.network.RegistryByteBuf +import net.minecraft.network.codec.PacketCodec +import moe.nea.firmament.repo.SBItemStack + +object NEUItemEntrySerializer : EntrySerializer { + override fun codec(): Codec { + return SBItemStack.CODEC + } + + override fun streamCodec(): PacketCodec { + return SBItemStack.PACKET_CODEC.cast() + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt new file mode 100644 index 0000000..8e39f28 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/REIRecipeLayouter.kt @@ -0,0 +1,62 @@ +package moe.nea.firmament.compat.rei + +import io.github.notenoughupdates.moulconfig.gui.GuiComponent +import me.shedaniel.math.Dimension +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import me.shedaniel.rei.api.client.gui.widgets.Widget +import me.shedaniel.rei.api.client.gui.widgets.Widgets +import net.minecraft.text.Text +import moe.nea.firmament.compat.rei.recipes.wrapWidget +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.repo.recipes.RecipeLayouter + +class REIRecipeLayouter : RecipeLayouter { + val container: MutableList = mutableListOf() + fun add(t: T): T = t.also(container::add) + + override fun createItemSlot( + x: Int, + y: Int, + content: SBItemStack?, + slotKind: RecipeLayouter.SlotKind + ) { + val slot = Widgets.createSlot(Point(x, y)) + if (content != null) + slot.entry(SBItemEntryDefinition.getEntry(content)) + when (slotKind) { + RecipeLayouter.SlotKind.SMALL_INPUT -> slot.markInput() + RecipeLayouter.SlotKind.SMALL_OUTPUT -> slot.markOutput() + RecipeLayouter.SlotKind.BIG_OUTPUT -> { + slot.markOutput().disableBackground() + add(Widgets.createResultSlotBackground(Point(x, y))) + } + } + add(slot) + } + + override fun createTooltip(rectangle: Rectangle, label: Text) { + add(Widgets.createTooltip(rectangle, label)) + } + + override fun createLabel(x: Int, y: Int, text: Text) { + add(Widgets.createLabel(Point(x, y), text)) + } + + override fun createArrow(x: Int, y: Int) = + add(Widgets.createArrow(Point(x, y))).bounds + + override fun createMoulConfig( + x: Int, + y: Int, + w: Int, + h: Int, + component: GuiComponent + ) { + add(wrapWidget(Rectangle(Point(x, y), Dimension(w, h)), component)) + } + + override fun createFire(ingredientsCenter: Point, animationTicks: Int) { + add(Widgets.createBurningFire(ingredientsCenter).animationDurationTicks(animationTicks.toDouble())) + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt new file mode 100644 index 0000000..740eeeb --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SBItemEntryDefinition.kt @@ -0,0 +1,97 @@ +package moe.nea.firmament.compat.rei + +import io.github.moulberry.repo.data.NEUIngredient +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.ItemConvertible +import net.minecraft.item.ItemStack +import net.minecraft.registry.tag.TagKey +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.compat.rei.FirmamentReiPlugin.Companion.asItemEntry +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.SkyblockId + +object SBItemEntryDefinition : EntryDefinition { + override fun equals(o1: SBItemStack, o2: SBItemStack, context: ComparisonContext): Boolean { + return o1.skyblockId == o2.skyblockId && o1.getStackSize() == o2.getStackSize() + } + + @OptIn(ExpensiveItemCacheApi::class) + override fun cheatsAs(entry: EntryStack?, value: SBItemStack): ItemStack { + return value.asCopiedItemStack() + } + + override fun getValueType(): Class = SBItemStack::class.java + override fun getType(): EntryType = EntryType.deferred(FirmamentReiPlugin.SKYBLOCK_ITEM_TYPE_ID) + + override fun getRenderer(): EntryRenderer = NEUItemEntryRenderer + + override fun getSerializer(): EntrySerializer { + return NEUItemEntrySerializer + } + + override fun getTagsFor(entry: EntryStack?, value: SBItemStack?): Stream>? { + return Stream.empty() + } + + @OptIn(ExpensiveItemCacheApi::class) + override fun asFormattedText(entry: EntryStack, value: SBItemStack): Text { + val neuItem = entry.value.neuItem + return if (!RepoManager.Config.perfectRenders.rendersPerfectText() || entry.value.isWarm() || neuItem == null) { + VanillaEntryTypes.ITEM.definition.asFormattedText(entry.asItemEntry(), value.asImmutableItemStack()) + } else { + Text.literal(neuItem.displayName) + } + } + + override fun hash(entry: EntryStack, 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?, value: SBItemStack): SBItemStack { + return value.copy( + stackSize = 1, petData = RepoManager.getPotentialStubPetData(value.skyblockId), + stars = 0, extraLore = listOf(), reforge = null + ) + } + + override fun normalize(entry: EntryStack?, value: SBItemStack): SBItemStack { + return wildcard(entry, value) + } + + override fun copy(entry: EntryStack?, value: SBItemStack): SBItemStack { + return value + } + + override fun isEmpty(entry: EntryStack?, value: SBItemStack): Boolean { + return value.getStackSize() == 0 + } + + override fun getIdentifier(entry: EntryStack?, value: SBItemStack): Identifier { + return value.skyblockId.identifier + } + + fun getEntry(sbItemStack: SBItemStack): EntryStack = + EntryStack.of(this, sbItemStack) + + fun getEntry(skyblockId: SkyblockId, count: Int = 1): EntryStack = + getEntry(SBItemStack(skyblockId, count)) + + fun getEntry(ingredient: NEUIngredient): EntryStack = + getEntry(SkyblockId(ingredient.itemId), count = ingredient.amount.toInt()) + + fun getPassthrough(item: ItemConvertible) = getEntry(SBItemStack.passthrough(ItemStack(item.asItem()))) + + fun getEntry(stack: ItemStack): EntryStack = + getEntry(SBItemStack(stack)) +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt new file mode 100644 index 0000000..900ebab --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockCraftingRecipeDynamicGenerator.kt @@ -0,0 +1,56 @@ +package moe.nea.firmament.compat.rei + +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.NEUNpcShopRecipe +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.compat.rei.recipes.SBKatRecipe +import moe.nea.firmament.compat.rei.recipes.SBMobDropRecipe +import moe.nea.firmament.compat.rei.recipes.SBShopRecipe +import moe.nea.firmament.repo.EssenceRecipeProvider +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack + + +val SkyblockMobDropRecipeDynamicGenerator = + neuDisplayGenerator { SBMobDropRecipe(it) } +val SkyblockShopRecipeDynamicGenerator = + neuDisplayGenerator { SBShopRecipe(it) } +val SkyblockKatRecipeDynamicGenerator = + neuDisplayGenerator { SBKatRecipe(it) } + +inline fun neuDisplayGenerator(crossinline mapper: (T) -> D) = + neuDisplayGeneratorWithItem { _, it -> mapper(it) } + +inline fun neuDisplayGeneratorWithItem(crossinline mapper: (SBItemStack, T) -> D) = + neuDisplayGeneratorWithItem(T::class.java, mapper) +inline fun neuDisplayGeneratorWithItem( + filter: Class, + crossinline mapper: (SBItemStack, T) -> D) = + object : DynamicDisplayGenerator { + override fun getRecipeFor(entry: EntryStack<*>): Optional> { + if (entry.type != SBItemEntryDefinition.type) return Optional.empty() + val item = entry.castValue() + val recipes = RepoManager.getRecipesFor(item.skyblockId) + val craftingRecipes = recipes.filterIsInstance(filter) + return Optional.of(craftingRecipes.map { mapper(item, it) }) + } + + override fun generate(builder: ViewSearchBuilder): Optional> { + return Optional.empty() // TODO: allows searching without blocking getRecipeFor + } + + override fun getUsageFor(entry: EntryStack<*>): Optional> { + if (entry.type != SBItemEntryDefinition.type) return Optional.empty() + val item = entry.castValue() + val recipes = RepoManager.getUsagesFor(item.skyblockId) + val craftingRecipes = recipes.filterIsInstance(filter) + return Optional.of(craftingRecipes.map { mapper(item, it) }) + } + } diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt new file mode 100644 index 0000000..9ccfab4 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/SkyblockItemIdFocusedStackProvider.kt @@ -0,0 +1,23 @@ + + +package moe.nea.firmament.compat.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 + +object SkyblockItemIdFocusedStackProvider : FocusedStackProvider { + override fun provide(screen: Screen?, mouse: Point?): CompoundEventResult> { + 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() + return CompoundEventResult.interruptTrue(SBItemEntryDefinition.getEntry(item)) + } + + override fun getPriority(): Double = 1_000_000.0 +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/math.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/math.kt new file mode 100644 index 0000000..f4808c7 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/math.kt @@ -0,0 +1,8 @@ +package moe.nea.firmament.compat.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/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt new file mode 100644 index 0000000..15cb818 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/GenericREIRecipeCategory.kt @@ -0,0 +1,67 @@ +package moe.nea.firmament.compat.rei.recipes + +import io.github.moulberry.repo.data.NEURecipe +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.client.registry.display.DisplayRegistry +import me.shedaniel.rei.api.common.category.CategoryIdentifier +import me.shedaniel.rei.api.common.util.EntryStacks +import net.minecraft.text.Text +import moe.nea.firmament.compat.rei.REIRecipeLayouter +import moe.nea.firmament.compat.rei.neuDisplayGeneratorWithItem +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.repo.recipes.GenericRecipeRenderer + +class GenericREIRecipeCategory( + val renderer: GenericRecipeRenderer, +) : DisplayCategory> { + private val dynamicGenerator = + neuDisplayGeneratorWithItem, T>(renderer.typ) { item, recipe -> + GenericRecipe( + recipe, + item, + categoryIdentifier + ) + } + + private val categoryIdentifier = CategoryIdentifier.of>(renderer.identifier) + override fun getCategoryIdentifier(): CategoryIdentifier> { + return categoryIdentifier + } + + override fun getDisplayHeight(): Int { + return renderer.displayHeight + } + + override fun getTitle(): Text? { + return renderer.title + } + + override fun getIcon(): Renderer? { + return EntryStacks.of(renderer.icon) + } + + override fun setupDisplay(display: GenericRecipe, bounds: Rectangle): List { + val layouter = REIRecipeLayouter() + layouter.container.add(Widgets.createRecipeBase(bounds)) + renderer.render(display.neuRecipe, bounds, layouter, display.sourceItem) + return layouter.container + } + + fun registerDynamicGenerator(registry: DisplayRegistry) { + registry.registerDisplayGenerator(categoryIdentifier, dynamicGenerator) + } +} + +class GenericRecipe( + override val neuRecipe: T, + val sourceItem: SBItemStack?, + val id: CategoryIdentifier> +) : SBRecipe() { + override fun getCategoryIdentifier(): CategoryIdentifier<*>? { + return id + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt new file mode 100644 index 0000000..cce1465 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBKatRecipe.kt @@ -0,0 +1,222 @@ +package moe.nea.firmament.compat.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.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.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.repo.PetData +import moe.nea.firmament.repo.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 { + override fun getCategoryIdentifier(): CategoryIdentifier = + 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 = SBItemEntryDefinition.getPassthrough(Items.BONE) + override fun setupDisplay(display: SBKatRecipe, bounds: Rectangle): List { + 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 { + 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/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt new file mode 100644 index 0000000..b595c23 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBMobDropRecipe.kt @@ -0,0 +1,105 @@ +package moe.nea.firmament.compat.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.compat.rei.EntityWidget +import moe.nea.firmament.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.gui.entity.EntityRenderer + +class SBMobDropRecipe(override val neuRecipe: NEUMobDropRecipe) : SBRecipe() { + override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.categoryIdentifier + + object Category : DisplayCategory { + override fun getCategoryIdentifier(): CategoryIdentifier = + 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 = SBItemEntryDefinition.getPassthrough(Items.DIAMOND_SWORD) + override fun setupDisplay(display: SBMobDropRecipe, bounds: Rectangle): List { + 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()) + } + 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() + 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/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt new file mode 100644 index 0000000..de7779f --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBRecipe.kt @@ -0,0 +1,42 @@ +package moe.nea.firmament.compat.rei.recipes + +import io.github.moulberry.repo.data.NEUIngredient +import io.github.moulberry.repo.data.NEURecipe +import java.util.Optional +import me.shedaniel.rei.api.common.display.Display +import me.shedaniel.rei.api.common.display.DisplaySerializer +import me.shedaniel.rei.api.common.entry.EntryIngredient +import net.minecraft.util.Identifier +import moe.nea.firmament.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.util.SkyblockId + +abstract class SBRecipe : Display { + override fun getDisplayLocation(): Optional { + // In theory, we could return a location for the neuRecipe here. (Something along the lines of neurepo:items/item_id.json/0 for the 0th recipe in the items/item_id.json recipes array). + return Optional.empty() + } + + override fun getSerializer(): DisplaySerializer? { + // While returning null here is discouraged, we are fine to do so, since this recipe will never travel through the network + return null + } + + abstract val neuRecipe: NEURecipe + override fun getInputEntries(): List { + 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 { + 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/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt new file mode 100644 index 0000000..fca3edf --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt @@ -0,0 +1,217 @@ +@file:OptIn(ExpensiveItemCacheApi::class) + +package moe.nea.firmament.compat.rei.recipes + +import java.util.Optional +import me.shedaniel.math.Dimension +import me.shedaniel.math.FloatingDimension +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.Label +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.client.registry.display.DynamicDisplayGenerator +import me.shedaniel.rei.api.client.view.ViewSearchBuilder +import me.shedaniel.rei.api.common.category.CategoryIdentifier +import me.shedaniel.rei.api.common.display.Display +import me.shedaniel.rei.api.common.display.DisplaySerializer +import me.shedaniel.rei.api.common.entry.EntryIngredient +import me.shedaniel.rei.api.common.entry.EntryStack +import net.minecraft.entity.EntityType +import net.minecraft.entity.SpawnReason +import net.minecraft.registry.entry.RegistryEntry +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import net.minecraft.village.VillagerProfession +import moe.nea.firmament.Firmament +import moe.nea.firmament.compat.rei.EntityWidget +import moe.nea.firmament.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.gui.entity.EntityRenderer +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.Reforge +import moe.nea.firmament.repo.ReforgeStore +import moe.nea.firmament.repo.RepoItemTypeCache +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.AprilFoolsUtil +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.gold +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.skyblock.ItemType +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.skyblock.SkyBlockItems +import moe.nea.firmament.util.skyblockId +import moe.nea.firmament.util.tr + +class SBReforgeRecipe( + val reforge: Reforge, + val limitToItem: SBItemStack?, +) : Display { + companion object { + val catIdentifier = CategoryIdentifier.of(Firmament.MOD_ID, "reforge_recipe") + } + + object Category : DisplayCategory { + override fun getCategoryIdentifier(): CategoryIdentifier { + return catIdentifier + } + + override fun getTitle(): Text { + return tr("firmament.recipecategory.reforge", "Reforge") + } + + override fun getIcon(): Renderer { + return SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL) + } + + override fun setupDisplay(display: SBReforgeRecipe, bounds: Rectangle): MutableList { + val list = mutableListOf() + list.add(Widgets.createRecipeBase(bounds)) + val inputSlot = Widgets.createSlot(Point(bounds.minX + 10, bounds.centerY - 9)) + .markInput().entries(display.inputItems) + list.add(inputSlot) + if (display.reforgeStone != null) { + list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24, bounds.centerY - 9 - 10)) + .markInput().entry(display.reforgeStone)) + list.add(Widgets.withTooltip( + Widgets.withTranslate(Widgets.wrapRenderer( + Rectangle(Point(bounds.minX + 10 + 24, bounds.centerY - 9 + 10), Dimension(16, 16)), + SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL)), 0.0, 0.0, 150.0), + Rarity.entries.mapNotNull { rarity -> + display.reforge.reforgeCosts?.get(rarity)?.let { rarity to it } + }.map { (rarity, cost) -> + Text.literal("") + .append(rarity.text) + .append(": ") + .append(Text.literal("${FirmFormatters.formatCommas(cost, 0)} Coins").gold()) + } + )) + } else { + val size = if (AprilFoolsUtil.isAprilFoolsDay) 1.2 else 0.6 + val dimension = + FloatingDimension(EntityWidget.defaultSize.width * size, EntityWidget.defaultSize.height * size) + list.add(Widgets.withTooltip( + EntityWidget( + EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND) + ?.also { it.villagerData = it.villagerData.withProfession(MC.currentOrDefaultRegistries.getEntryOrThrow(VillagerProfession.WEAPONSMITH)) }, + Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2), + dimension + ), + tr("firmament.recipecategory.reforge.basic", + "This is a basic reforge, available at the Blacksmith.").grey() + )) + } + list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24 + 24, bounds.centerY - 9)) + .markInput().entries(display.outputItems)) + val statToLineMappings = mutableListOf>() + for ((i, statId) in display.reforge.statUniverse.withIndex()) { + val label = Widgets.createLabel( + Point(bounds.minX + 10 + 24 + 24 + 20, bounds.minY + 8 + i * 11), + SBItemStack.Companion.StatLine(SBItemStack.statIdToName(statId), null).reconstitute(7)) + .horizontalAlignment(Label.LEFT_ALIGNED) + statToLineMappings.add(statId to label) + list.add(label) + } + fun updateStatLines() { + val entry = inputSlot.currentEntry?.castValue() ?: return + val stats = display.reforge.reforgeStats?.get(entry.rarity) ?: mapOf() + for ((stat, label) in statToLineMappings) { + label.message = + SBItemStack.Companion.StatLine( + SBItemStack.statIdToName(stat), null, + valueNum = stats[stat] + ).reconstitute(7) + } + } + updateStatLines() + inputSlot.withEntriesListener { updateStatLines() } + return list + } + } + + object DynamicGenerator : DynamicDisplayGenerator { + fun getRecipesForSBItemStack(item: SBItemStack): Optional> { + val reforgeRecipes = mutableListOf() + for (reforge in ReforgeStore.findEligibleForInternalName(item.skyblockId)) { + reforgeRecipes.add(SBReforgeRecipe(reforge, item)) + } + for (reforge in ReforgeStore.findEligibleForItem(item.itemType ?: ItemType.NIL)) { + reforgeRecipes.add(SBReforgeRecipe(reforge, item)) + } + if (reforgeRecipes.isEmpty()) return Optional.empty() + return Optional.of(reforgeRecipes) + } + + override fun getRecipeFor(entry: EntryStack<*>): Optional> { + if (entry.type != SBItemEntryDefinition.type) return Optional.empty() + val item = entry.castValue() + return getRecipesForSBItemStack(item) + } + + override fun getUsageFor(entry: EntryStack<*>): Optional> { + if (entry.type != SBItemEntryDefinition.type) return Optional.empty() + val item = entry.castValue() + ReforgeStore.byReforgeStone[item.skyblockId]?.let { stoneReforge -> + return Optional.of(listOf(SBReforgeRecipe(stoneReforge, null))) + } + return getRecipesForSBItemStack(item) + } + + override fun generate(builder: ViewSearchBuilder): Optional> { + // TODO: check builder.recipesFor and such and optionally return all reforge recipes + return Optional.empty() + } + } + + private val inputItems = run { + if (limitToItem != null) return@run listOf(SBItemEntryDefinition.getEntry(limitToItem)) + val eligibleItems = reforge.eligibleItems.flatMap { + when (it) { + is Reforge.ReforgeEligibilityFilter.AllowsInternalName -> + listOfNotNull(RepoManager.getNEUItem(it.internalName)) + + is Reforge.ReforgeEligibilityFilter.AllowsItemType -> + ReforgeStore.resolveItemType(it.itemType) + .flatMapTo(mutableSetOf()) { + (RepoItemTypeCache.byItemType[it] ?: listOf()) + + (RepoItemTypeCache.byItemType[it.dungeonVariant] ?: listOf()) + }.toList() + + is Reforge.ReforgeEligibilityFilter.AllowsVanillaItemType -> { + listOf() // TODO: add filter support for this and potentially rework this to search for the declared item type in repo, instead of remapped item type + } + } + } + eligibleItems.map { SBItemEntryDefinition.getEntry(it.skyblockId) } + } + private val outputItems = + inputItems.map { SBItemEntryDefinition.getEntry(it.value.copy(reforge = reforge.reforgeId)) } + private val reforgeStone = reforge.reforgeStone?.let(SBItemEntryDefinition::getEntry) + private val inputEntries = + listOf(EntryIngredient.of(inputItems)) + listOfNotNull(reforgeStone?.let(EntryIngredient::of)) + private val outputEntries = listOf(EntryIngredient.of(outputItems)) + + override fun getInputEntries(): List { + return inputEntries + } + + override fun getOutputEntries(): List { + return outputEntries + } + + override fun getCategoryIdentifier(): CategoryIdentifier<*> { + return catIdentifier + } + + override fun getDisplayLocation(): Optional { + return Optional.empty() + } + + override fun getSerializer(): DisplaySerializer? { + return null + } +} diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt new file mode 100644 index 0000000..a252802 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBShopRecipe.kt @@ -0,0 +1,61 @@ +package moe.nea.firmament.compat.rei.recipes + +import io.github.moulberry.repo.data.NEUNpcShopRecipe +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.entry.EntryIngredient +import net.minecraft.item.Items +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.util.skyblockId + +class SBShopRecipe(override val neuRecipe: NEUNpcShopRecipe) : SBRecipe() { + override fun getCategoryIdentifier(): CategoryIdentifier<*> = Category.catIdentifier + val merchant = SBItemEntryDefinition.getEntry(neuRecipe.isSoldBy.skyblockId) + override fun getInputEntries(): List { + return listOf(EntryIngredient.of(merchant)) + super.getInputEntries() + } + + object Category : DisplayCategory { + val catIdentifier = CategoryIdentifier.of(Firmament.MOD_ID, "npc_shopping") + override fun getCategoryIdentifier(): CategoryIdentifier = catIdentifier + + override fun getTitle(): Text = Text.literal("SkyBlock NPC Shopping") + + override fun getIcon(): Renderer = SBItemEntryDefinition.getPassthrough(Items.EMERALD) + override fun setupDisplay(display: SBShopRecipe, bounds: Rectangle): List { + val point = Point(bounds.centerX, bounds.centerY) + return buildList { + add(Widgets.createRecipeBase(bounds)) + add(Widgets.createSlot(Point(point.x - 2 - 18 / 2, point.y - 18 - 6)) + .unmarkInputOrOutput() + .entry(display.merchant) + .disableBackground()) + add(Widgets.createArrow(Point(point.x - 2 - 24 / 2, point.y - 6))) + val cost = display.neuRecipe.cost + for ((i, item) in cost.withIndex()) { + add(Widgets.createSlot(Point( + point.x - 14 - 18, + point.y + i * 18 - 18 * cost.size / 2)) + .entry(SBItemEntryDefinition.getEntry(item)) + .markInput()) + // TODO: fix frame clipping + } + add(Widgets.createResultSlotBackground(Point(point.x + 18, point.y - 18 / 2))) + add( + Widgets.createSlot(Point(point.x + 18, point.y - 18 / 2)) + .entry(SBItemEntryDefinition.getEntry(display.neuRecipe.result)) + .disableBackground().markOutput() + ) + } + } + + } + +} diff --git a/src/compat/rei/java/moe/nea/firmament/mixins/compat/HideREIRecipeWarning.java b/src/compat/rei/java/moe/nea/firmament/mixins/compat/HideREIRecipeWarning.java new file mode 100644 index 0000000..14eeaf2 --- /dev/null +++ b/src/compat/rei/java/moe/nea/firmament/mixins/compat/HideREIRecipeWarning.java @@ -0,0 +1,20 @@ +package moe.nea.firmament.mixins.compat; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(targets = "me.shedaniel.rei.impl.client.gui.hints.ImportantWarningsWidget") +@Pseudo +public class HideREIRecipeWarning { + @Shadow + private boolean visible; + + @Inject(method = "", at = @At("TAIL")) + private void onCreateImportantWidget(CallbackInfo ci) { + visible = false; + } +} diff --git a/src/compat/sodium/java/SodiumChunkReloader.kt b/src/compat/sodium/java/SodiumChunkReloader.kt new file mode 100644 index 0000000..0256b88 --- /dev/null +++ b/src/compat/sodium/java/SodiumChunkReloader.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.compat.sodium + +import net.caffeinemc.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 + ?.markGraphDirty() + } +} diff --git a/src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java b/src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java new file mode 100644 index 0000000..f75874d --- /dev/null +++ b/src/compat/sodium/java/moe/nea/firmament/mixins/accessor/sodium/AccessorSodiumWorldRenderer.java @@ -0,0 +1,14 @@ +package moe.nea.firmament.mixins.accessor.sodium; + +import net.caffeinemc.mods.sodium.client.render.SodiumWorldRenderer; +import net.caffeinemc.mods.sodium.client.render.chunk.RenderSectionManager; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(SodiumWorldRenderer.class) +@Pseudo +public interface AccessorSodiumWorldRenderer { + @Accessor(value = "renderSectionManager", remap = false) + RenderSectionManager getRenderSectionManager_firmament(); +} diff --git a/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java b/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java new file mode 100644 index 0000000..fe87310 --- /dev/null +++ b/src/compat/sodium/java/moe/nea/firmament/mixins/custommodels/PatchBlockModelInSodiumChunkGenerator.java @@ -0,0 +1,29 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.caffeinemc.mods.sodium.client.render.chunk.compile.tasks.ChunkBuilderMeshingTask; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.block.BlockModels; +import net.minecraft.client.render.model.BakedModel; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ChunkBuilderMeshingTask.class) +public class PatchBlockModelInSodiumChunkGenerator { + @WrapOperation( + method = "execute(Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildContext;Lnet/caffeinemc/mods/sodium/client/util/task/CancellationToken;)Lnet/caffeinemc/mods/sodium/client/render/chunk/compile/ChunkBuildOutput;", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;")) + private BakedModel replaceBlockModel(BlockModels instance, BlockState state, Operation original, + @Local(name = "blockPos") BlockPos.Mutable pos) { + var replacement = CustomBlockTextures.getReplacementModel(state, pos); + if (replacement != null) return replacement; + CustomBlockTextures.enterFallbackCall(); + var fallback = original.call(instance, state); + CustomBlockTextures.exitFallbackCall(); + return fallback; + } +} diff --git a/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt b/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt new file mode 100644 index 0000000..347dd5d --- /dev/null +++ b/src/compat/wildfireGender/java/moe/nea/firmament/compat/gender/Compat.kt @@ -0,0 +1,13 @@ +package moe.nea.firmament.compat.gender + +import net.fabricmc.loader.api.FabricLoader +import moe.nea.firmament.util.compatloader.CompatMeta +import moe.nea.firmament.util.compatloader.ICompatMeta + +@CompatMeta +object Compat : ICompatMeta { + override fun shouldLoad(): Boolean { + return FabricLoader.getInstance().isModLoaded("wildfire_gender") + } + +} diff --git a/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java b/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java new file mode 100644 index 0000000..c3e8950 --- /dev/null +++ b/src/compat/wildfireGender/java/moe/nea/firmament/mixins/compat/wildfiregender/PatchArmorTexturesInGenderMod.java @@ -0,0 +1,23 @@ +package moe.nea.firmament.mixins.compat.wildfiregender; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.wildfire.render.GenderArmorLayer; +import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; +import net.minecraft.component.type.EquippableComponent; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Pseudo; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GenderArmorLayer.class) +@Pseudo +public class PatchArmorTexturesInGenderMod { + @ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/BipedEntityRenderState;FF)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;")) + private Object replaceArmorMaterial(Object original, @Local ItemStack chestplate) { + var overrides = CustomGlobalArmorOverrides.overrideArmor(chestplate, EquipmentSlot.CHEST); + return overrides.orElse((EquippableComponent) original); + } +} diff --git a/src/compat/yacl/java/KeybindingBuilder.kt b/src/compat/yacl/java/KeybindingBuilder.kt new file mode 100644 index 0000000..322ddff --- /dev/null +++ b/src/compat/yacl/java/KeybindingBuilder.kt @@ -0,0 +1,16 @@ +package moe.nea.firmament.compat.yacl + +import dev.isxander.yacl3.api.Controller +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.controller.ControllerBuilder +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.keybindings.SavedKeyBinding + +class KeybindingBuilder( + val option: Option, + val managedOption: ManagedOption +) : ControllerBuilder { + override fun build(): Controller { + return KeybindingController(option, managedOption) + } +} diff --git a/src/compat/yacl/java/KeybindingController.kt b/src/compat/yacl/java/KeybindingController.kt new file mode 100644 index 0000000..204d521 --- /dev/null +++ b/src/compat/yacl/java/KeybindingController.kt @@ -0,0 +1,83 @@ +package moe.nea.firmament.compat.yacl + +import dev.isxander.yacl3.api.Controller +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.utils.Dimension +import dev.isxander.yacl3.gui.AbstractWidget +import dev.isxander.yacl3.gui.YACLScreen +import dev.isxander.yacl3.gui.controllers.ControllerWidget +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.KeyBindingHandler +import moe.nea.firmament.gui.config.KeyBindingStateManager +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.keybindings.SavedKeyBinding + +class KeybindingController( + val option: Option, + val managedOption: ManagedOption, +) : Controller { + val handler = managedOption.handler as KeyBindingHandler + override fun option(): Option { + return option + } + + override fun formatValue(): Text { + return option.pendingValue().format() + } + + override fun provideWidget(screen: YACLScreen, widgetDimension: Dimension): AbstractWidget { + lateinit var button: ControllerWidget + val sm = KeyBindingStateManager( + { option.pendingValue() }, + { option.requestSet(it) }, + { screen.focused = null }, + { screen.focused = button }, + ) + button = KeybindingWidget(sm, this, screen, widgetDimension) + option.addListener { t, u -> + sm.updateLabel() + } + sm.updateLabel() + return button + } +} + +class KeybindingWidget( + val sm: KeyBindingStateManager, + controller: KeybindingController, + screen: YACLScreen, + dimension: Dimension +) : ControllerWidget(controller, screen, dimension) { + override fun getHoveredControlWidth(): Int { + return 130 + } + + override fun getValueText(): Text { + return sm.label + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return sm.keyboardEvent(keyCode, true) + } + + override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return sm.keyboardEvent(keyCode, false) + } + + override fun unfocus() { + sm.onLostFocus() + } + + override fun setFocused(focused: Boolean) { + super.setFocused(focused) + if (!focused) sm.onLostFocus() + } + + override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { + if (button == 0 && isHovered) { + sm.onClick() + return true + } + return super.mouseClicked(mouseX, mouseY, button) + } +} diff --git a/src/compat/yacl/java/YaclIntegration.kt b/src/compat/yacl/java/YaclIntegration.kt new file mode 100644 index 0000000..285d60c --- /dev/null +++ b/src/compat/yacl/java/YaclIntegration.kt @@ -0,0 +1,227 @@ +package moe.nea.firmament.compat.yacl + +import com.google.auto.service.AutoService +import dev.isxander.yacl3.api.Binding +import dev.isxander.yacl3.api.ButtonOption +import dev.isxander.yacl3.api.ConfigCategory +import dev.isxander.yacl3.api.LabelOption +import dev.isxander.yacl3.api.Option +import dev.isxander.yacl3.api.OptionDescription +import dev.isxander.yacl3.api.OptionGroup +import dev.isxander.yacl3.api.YetAnotherConfigLib +import dev.isxander.yacl3.api.controller.ColorControllerBuilder +import dev.isxander.yacl3.api.controller.ControllerBuilder +import dev.isxander.yacl3.api.controller.DoubleSliderControllerBuilder +import dev.isxander.yacl3.api.controller.EnumControllerBuilder +import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder +import dev.isxander.yacl3.api.controller.StringControllerBuilder +import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder +import dev.isxander.yacl3.api.controller.ValueFormatter +import dev.isxander.yacl3.gui.YACLScreen +import dev.isxander.yacl3.gui.tab.ListHolderWidget +import io.github.notenoughupdates.moulconfig.ChromaColour +import java.awt.Color +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.DurationUnit +import net.minecraft.client.gui.Element +import net.minecraft.client.gui.screen.Screen +import net.minecraft.text.Text +import moe.nea.firmament.gui.config.BooleanHandler +import moe.nea.firmament.gui.config.ChoiceHandler +import moe.nea.firmament.gui.config.ClickHandler +import moe.nea.firmament.gui.config.ColourHandler +import moe.nea.firmament.gui.config.DurationHandler +import moe.nea.firmament.gui.config.EnumRenderer +import moe.nea.firmament.gui.config.FirmamentConfigScreenProvider +import moe.nea.firmament.gui.config.HudMeta +import moe.nea.firmament.gui.config.HudMetaHandler +import moe.nea.firmament.gui.config.IntegerHandler +import moe.nea.firmament.gui.config.KeyBindingHandler +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.gui.config.StringHandler +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.getRGBAWithoutAnimation +import moe.nea.firmament.util.toChromaWithoutAnimation + + +@AutoService(FirmamentConfigScreenProvider::class) +class YaclIntegration : FirmamentConfigScreenProvider { + fun buildCategories() = + ManagedConfig.Category.entries + .map(::buildCategory) + + private fun buildCategory(category: ManagedConfig.Category): ConfigCategory { + return ConfigCategory.createBuilder() + .name(category.labelText) + .also { categoryB -> + category.configs.forEach { + categoryB.group( + OptionGroup.createBuilder() + .name(it.labelText) + .options(buildOptions(it.sortedOptions)) + .build() + ) + } + } + .build() + } + + fun buildOptions(options: List>): Collection> = + options.flatMap { buildOption(it) } + + private fun buildOption(managedOption: ManagedOption): Collection> { + val handler = managedOption.handler + val binding = Binding.generic( + managedOption.default(), + managedOption::value, + { managedOption.value = it; managedOption.element.save() }) + + fun createDefaultBinding(function: (Option) -> ControllerBuilder): Option.Builder { + return Option.createBuilder() + .name(managedOption.labelText) + .description(OptionDescription.of(managedOption.labelDescription)) + .binding(binding as Binding) + .controller { function(it) } + } + + fun Option.single() = listOf(this) + fun ButtonOption.Builder.single() = build().single() + fun Option.Builder.single() = build().single() + when (handler) { + is ClickHandler -> return ButtonOption.createBuilder() + .name(managedOption.labelText) + .action { t, u -> + handler.runnable() + } + .single() + + is HudMetaHandler -> return ButtonOption.createBuilder() + .name(managedOption.labelText) + .action { t, u -> + handler.openEditor(managedOption as ManagedOption, t) + } + .single() + + is ChoiceHandler<*> -> return createDefaultBinding { + createChoiceBinding(handler as ChoiceHandler<*>, managedOption as ManagedOption<*>, it as Option<*>) + }.single() + + is ColourHandler -> { + managedOption as ManagedOption + val colorBinding = + Binding.generic( + managedOption.default().getRGBAWithoutAnimation(), + { managedOption.value.getRGBAWithoutAnimation() }, + { + managedOption.value = + it.toChromaWithoutAnimation(managedOption.value.timeForFullRotationInMillis) + managedOption.element.save() + }) + val speedBinding = + Binding.generic( + managedOption.default().timeForFullRotationInMillis, + { managedOption.value.timeForFullRotationInMillis }, + { + managedOption.value = managedOption.value.copy(timeForFullRotationInMillis = it) + managedOption.element.save() + } + ) + + return listOf( + Option.createBuilder() + .name(managedOption.labelText) + .binding(colorBinding) + .controller { + ColorControllerBuilder.create(it) + .allowAlpha(true) + } + .build(), + Option.createBuilder() + .name(managedOption.labelText) + .binding(speedBinding) + .controller { IntegerSliderControllerBuilder.create(it).range(0, 60_000).step(10) } + .build(), + ) + } + + is BooleanHandler -> return createDefaultBinding(TickBoxControllerBuilder::create).single() + is StringHandler -> return createDefaultBinding(StringControllerBuilder::create).single() + is IntegerHandler -> return createDefaultBinding { + IntegerSliderControllerBuilder.create(it).range(handler.min, handler.max).step(1) + }.single() + + is DurationHandler -> return Option.createBuilder() + .name(managedOption.labelText) + .binding((binding as Binding).xmap({ it.toDouble(DurationUnit.SECONDS) }, { it.seconds })) + .controller { + DoubleSliderControllerBuilder.create(it) + .formatValue { Text.literal(FirmFormatters.formatTimespan(it.seconds)) } + .step(0.1) + .range(handler.min.toDouble(DurationUnit.SECONDS), handler.max.toDouble(DurationUnit.SECONDS)) + } + .single() + + is KeyBindingHandler -> return createDefaultBinding { + KeybindingBuilder(it, managedOption as ManagedOption) + }.single() + + else -> return listOf(LabelOption.create(Text.literal("This option is currently unhandled for this config menu. Please report this as a bug."))) + } + } + + private enum class Sacrifice {} + + private fun createChoiceBinding( + handler: ChoiceHandler<*>, + managedOption: ManagedOption<*>, + option: Option<*> + ): ControllerBuilder { + val b = EnumControllerBuilder.create(option as Option) + b.enumClass(handler.enumClass as Class) + /** + * This is a function with E to avoid realizing the Sacrifice outside of a `X` wrapper. + */ + fun > makeValueFormatter(): ValueFormatter { + return ValueFormatter { + (handler.renderer as EnumRenderer).getName(managedOption as ManagedOption, it) + } + } + b.formatValue(makeValueFormatter()) + return b as ControllerBuilder + } + + + fun buildConfig(): YetAnotherConfigLib { + return YetAnotherConfigLib.createBuilder() + .title(Text.literal("Firmament")) + .categories(buildCategories()) + .build() + } + + override val key: String + get() = "yacl" + + override fun open(search: String?, parent: Screen?): Screen { + return object : YACLScreen(buildConfig(), parent) { + override fun setFocused(focused: Element?) { + if (this.focused is KeybindingWidget && + focused is ListHolderWidget<*> + ) { + return + } + super.setFocused(focused) + } + + override fun shouldCloseOnEsc(): Boolean { + if (focused is KeybindingWidget) { + return false + } + return super.shouldCloseOnEsc() + } + } + } + +} diff --git a/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java new file mode 100644 index 0000000..a9db7f9 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/AutoDiscoveryPlugin.java @@ -0,0 +1,187 @@ +package moe.nea.firmament.init; + + +import moe.nea.firmament.util.ErrorUtil; +import moe.nea.firmament.util.compatloader.ICompatMeta; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class AutoDiscoveryPlugin { + public static List getDefaultAllMixinClassesFQNs() { + var defaultName = "moe.nea.firmament.mixins"; + var plugin = new AutoDiscoveryPlugin(); + plugin.setMixinPackage(defaultName); + var mixins = plugin.getMixins(); + return mixins.stream().map(it -> defaultName + "." + it).toList(); + } + + private static final List mixinPlugins = new ArrayList<>(); + + public static List getMixinPlugins() { + return mixinPlugins; + } + + private String mixinPackage; + + public void setMixinPackage(String mixinPackage) { + this.mixinPackage = mixinPackage; + mixinPlugins.add(this); + } + + /** + * Resolves the base class root for a given class URL. This resolves either the JAR root, or the class file root. + * In either case the return value of this + the class name will resolve back to the original class url, or to other + * class urls for other classes. + */ + public URL getBaseUrlForClassUrl(URL classUrl) { + String string = classUrl.toString(); + if (classUrl.getProtocol().equals("jar")) { + try { + return new URL(string.substring(4).split("!")[0]); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + if (string.endsWith(".class")) { + try { + return new URL(string.replace("\\", "/") + .replace(getClass().getCanonicalName() + .replace(".", "/") + ".class", "")); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + return classUrl; + } + + /** + * Get the package that contains all the mixins. This value is set using {@link #setMixinPackage}. + */ + public String getMixinPackage() { + return mixinPackage; + } + + /** + * Get the path inside the class root to the mixin package + */ + public String getMixinBaseDir() { + return mixinPackage.replace(".", "/"); + } + + /** + * A list of all discovered mixins. + */ + private List mixins = null; + + /** + * Try to add mixin class ot the mixins based on the filepath inside of the class root. + * Removes the {@code .class} file suffix, as well as the base mixin package. + *

This method cannot be called after mixin initialization.

+ * + * @param className the name or path of a class to be registered as a mixin. + */ + public void tryAddMixinClass(String className) { + if (!className.endsWith(".class")) return; + String norm = (className.substring(0, className.length() - ".class".length())) + .replace("\\", "/") + .replace("/", "."); + if (norm.startsWith(getMixinPackage() + ".") && !norm.endsWith(".") && ICompatMeta.Companion.shouldLoad(norm)) { + mixins.add(norm.substring(getMixinPackage().length() + 1)); + } + } + + private void tryDiscoverFromContentFile(URL url) { + Path file; + try { + file = Paths.get(getBaseUrlForClassUrl(url).toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + System.out.println("Base directory found at " + file); + if (!Files.exists(file)) { + System.out.println("Skipping non-existing mixin root: " + file); + return; + } + if (Files.isDirectory(file)) { + walkDir(file); + } else { + walkJar(file); + } + System.out.println("Found mixins: " + mixins); + + } + + /** + * Search through the JAR or class directory to find mixins contained in {@link #getMixinPackage()} + */ + public List getMixins() { + if (mixins != null) return mixins; + try { + System.out.println("Trying to discover mixins"); + mixins = new ArrayList<>(); + URL classUrl = getClass().getProtectionDomain().getCodeSource().getLocation(); + System.out.println("Found classes at " + classUrl); + tryDiscoverFromContentFile(classUrl); + var classRoots = System.getProperty("firmament.classroots"); + if (classRoots != null && !classRoots.isBlank()) { + System.out.println("Found firmament class roots: " + classRoots); + for (String s : classRoots.split(File.pathSeparator)) { + if (s.isBlank()) { + continue; + } + tryDiscoverFromContentFile(new File(s).toURI().toURL()); + } + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + return mixins; + } + + /** + * Search through directory for mixin classes based on {@link #getMixinBaseDir}. + * + * @param classRoot The root directory in which classes are stored for the default package. + */ + private void walkDir(Path classRoot) { + System.out.println("Trying to find mixins from directory"); + var path = classRoot.resolve(getMixinBaseDir()); + if (!Files.exists(path)) return; + try (Stream classes = Files.walk(path)) { + classes.map(it -> classRoot.relativize(it).toString()) + .forEach(this::tryAddMixinClass); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Read through a JAR file, trying to find all mixins inside. + */ + private void walkJar(Path file) { + System.out.println("Trying to find mixins from jar file"); + try (ZipInputStream zis = new ZipInputStream(Files.newInputStream(file))) { + ZipEntry next; + while ((next = zis.getNextEntry()) != null) { + tryAddMixinClass(next.getName()); + zis.closeEntry(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java b/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java new file mode 100644 index 0000000..d60e3e7 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/ClientPlayerRiser.java @@ -0,0 +1,75 @@ +package moe.nea.firmament.init; + +import me.shedaniel.mm.api.ClassTinkerers; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +import java.lang.reflect.Modifier; +import java.util.Objects; + +public class ClientPlayerRiser extends RiserUtils { + @IntermediaryName(net.minecraft.entity.player.PlayerEntity.class) + String PlayerEntity; + @IntermediaryName(net.minecraft.world.World.class) + String World; + String GameProfile = "com.mojang.authlib.GameProfile"; + @IntermediaryName(net.minecraft.util.math.BlockPos.class) + String BlockPos; + @IntermediaryName(net.minecraft.client.network.AbstractClientPlayerEntity.class) + String AbstractClientPlayerEntity; + String GuiPlayer = "moe.nea.firmament.gui.entity.GuiPlayer"; + // World world, BlockPos pos, float yaw, GameProfile gameProfile + Type constructorDescriptor = Type.getMethodType(Type.VOID_TYPE, getTypeForClassName(World), getTypeForClassName(BlockPos), Type.FLOAT_TYPE, getTypeForClassName(GameProfile)); + + + private void mapClassNode(ClassNode classNode, Type superClass) { + for (MethodNode method : classNode.methods) { + if (Objects.equals(method.name, "") && Type.getMethodType(method.desc).equals(constructorDescriptor)) { + modifyConstructor(method, superClass); + return; + } + } + var node = new MethodNode(Opcodes.ASM9, "", constructorDescriptor.getDescriptor(), null, null); + classNode.methods.add(node); + modifyConstructor(node, superClass); + } + + + private void modifyConstructor(MethodNode method, Type superClass) { + method.access = (method.access | Modifier.PUBLIC) & ~Modifier.PRIVATE & ~Modifier.PROTECTED; + if (method.instructions.size() != 0) return; // Some other mod has already made a constructor here + + // World world, BlockPos pos, float yaw, GameProfile gameProfile + // ALOAD this + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 0)); + + // ALOAD World + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 1)); + + // ALOAD BlockPos + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 2)); + + // ALOAD yaw + method.instructions.add(new VarInsnNode(Opcodes.FLOAD, 3)); + + // ALOAD gameProfile + method.instructions.add(new VarInsnNode(Opcodes.ALOAD, 4)); + + // Call super + method.instructions.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, superClass.getInternalName(), "", constructorDescriptor.getDescriptor(), false)); + + // Return + method.instructions.add(new InsnNode(Opcodes.RETURN)); + } + + @Override + public void addTinkerers() { + ClassTinkerers.addTransformation(AbstractClientPlayerEntity, it -> mapClassNode(it, getTypeForClassName(PlayerEntity)), true); + ClassTinkerers.addTransformation(GuiPlayer, it -> mapClassNode(it, getTypeForClassName(AbstractClientPlayerEntity)), true); + } +} diff --git a/src/main/java/moe/nea/firmament/init/EarlyRiser.java b/src/main/java/moe/nea/firmament/init/EarlyRiser.java new file mode 100644 index 0000000..5441255 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/EarlyRiser.java @@ -0,0 +1,12 @@ + +package moe.nea.firmament.init; + +public class EarlyRiser implements Runnable { + @Override + public void run() { + new ClientPlayerRiser().addTinkerers(); + new HandledScreenRiser().addTinkerers(); + new SectionBuilderRiser().addTinkerers(); +// TODO: new ItemColorsSodiumRiser().addTinkerers(); + } +} diff --git a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java new file mode 100644 index 0000000..f7db18c --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java @@ -0,0 +1,151 @@ + +package moe.nea.firmament.init; + +import me.shedaniel.mm.api.ClassTinkerers; +import net.minecraft.client.gui.Element; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.InsnNode; +import org.objectweb.asm.tree.JumpInsnNode; +import org.objectweb.asm.tree.LabelNode; +import org.objectweb.asm.tree.LdcInsnNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +import java.lang.reflect.Modifier; +import java.util.function.Consumer; + +public class HandledScreenRiser extends RiserUtils { + @IntermediaryName(net.minecraft.client.gui.screen.Screen.class) + String Screen; + @IntermediaryName(net.minecraft.client.gui.screen.ingame.HandledScreen.class) + String HandledScreen; + Type mouseScrolledDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE, Type.DOUBLE_TYPE); + String mouseScrolled = remapper.mapMethodName("intermediary", "net.minecraft.class_364", "method_25401", + mouseScrolledDesc.getDescriptor()); + // boolean keyReleased(int keyCode, int scanCode, int modifiers) + Type keyReleasedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.INT_TYPE, Type.INT_TYPE, Type.INT_TYPE); + String keyReleased = remapper.mapMethodName("intermediary", Intermediary.className(), + Intermediary.methodName(Element::keyReleased), + keyReleasedDesc.getDescriptor()); + // public boolean charTyped(char chr, int modifiers) + Type charTypedDesc = Type.getMethodType(Type.BOOLEAN_TYPE, Type.CHAR_TYPE, Type.INT_TYPE); + String charTyped = remapper.mapMethodName("intermediary", Intermediary.className(), + Intermediary.methodName(Element::charTyped), + charTypedDesc.getDescriptor()); + + + @Override + public void addTinkerers() { + ClassTinkerers.addTransformation(HandledScreen, this::addMouseScroll, true); + ClassTinkerers.addTransformation(HandledScreen, this::addKeyReleased, true); + ClassTinkerers.addTransformation(HandledScreen, this::addCharTyped, true); + } + + /** + * Insert a handler that roughly inserts the following code at the beginning of the instruction list: + *
+	 * if (insertInvoke(insertLoads)) return true
+	 * 
+ * + * @param node The method node to prepend the instructions to + * @param insertLoads insert all the loads, including the {@code this} parameter + * @param insertInvoke insert the invokevirtual/invokestatic call + */ + void insertTrueHandler(MethodNode node, + Consumer insertLoads, + Consumer insertInvoke) { + + var insns = new InsnList(); + insertLoads.accept(insns); + insertInvoke.accept(insns); + // Create jump target (but not insert it yet) + var jumpIfFalse = new LabelNode(); + // IFEQ (if returned boolean == 0), jump to jumpIfFalse + insns.add(new JumpInsnNode(Opcodes.IFEQ, jumpIfFalse)); + // LDC 1 (as int, which is what booleans are at runtime) + insns.add(new LdcInsnNode(1)); + // IRETURN return int on stack (booleans are int at runtime) + insns.add(new InsnNode(Opcodes.IRETURN)); + insns.add(jumpIfFalse); + node.instructions.insert(insns); + } + + void addKeyReleased(ClassNode classNode) { + addSuperInjector( + classNode, keyReleased, keyReleasedDesc, "keyReleased_firmament", + insns -> { + // ALOAD 0, load this + insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); + // ILOAD 1-3, load args + insns.add(new VarInsnNode(Opcodes.ILOAD, 1)); + insns.add(new VarInsnNode(Opcodes.ILOAD, 2)); + insns.add(new VarInsnNode(Opcodes.ILOAD, 3)); + }); + } + + void addCharTyped(ClassNode classNode) { + addSuperInjector( + classNode, charTyped, charTypedDesc, "charTyped_firmament", + insns -> { + // ALOAD 0, load this + insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); + // ILOAD 1-2, load args. chars = ints + insns.add(new VarInsnNode(Opcodes.ILOAD, 1)); + insns.add(new VarInsnNode(Opcodes.ILOAD, 2)); + }); + } + + void addSuperInjector( + ClassNode classNode, + String name, + Type desc, + String firmamentName, + Consumer loadArgs + ) { + var keyReleasedNode = findMethod(classNode, name, desc); + if (keyReleasedNode == null) { + keyReleasedNode = new MethodNode( + Modifier.PUBLIC, + name, + desc.getDescriptor(), + null, + new String[0] + ); + var insns = keyReleasedNode.instructions; + loadArgs.accept(insns); + // INVOKESPECIAL call super method + insns.add(new MethodInsnNode(Opcodes.INVOKESPECIAL, getTypeForClassName(Screen).getInternalName(), + name, desc.getDescriptor())); + // IRETURN return int on stack (booleans are int at runtime) + insns.add(new InsnNode(Opcodes.IRETURN)); + classNode.methods.add(keyReleasedNode); + } + insertTrueHandler(keyReleasedNode, loadArgs, insns -> { + // INVOKEVIRTUAL call custom handler + insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, + getTypeForClassName(HandledScreen).getInternalName(), + firmamentName, + desc.getDescriptor())); + }); + + } + + void addMouseScroll(ClassNode classNode) { + addSuperInjector( + classNode, mouseScrolled, mouseScrolledDesc, "mouseScrolled_firmament", + insns -> { + // ALOAD 0, load this + insns.add(new VarInsnNode(Opcodes.ALOAD, 0)); + // DLOAD 1-4, load the 4 argument doubles. Note that since doubles are two entries wide we skip 2 each time. + insns.add(new VarInsnNode(Opcodes.DLOAD, 1)); + insns.add(new VarInsnNode(Opcodes.DLOAD, 3)); + insns.add(new VarInsnNode(Opcodes.DLOAD, 5)); + insns.add(new VarInsnNode(Opcodes.DLOAD, 7)); + }); + } + +} diff --git a/src/main/java/moe/nea/firmament/init/Intermediary.java b/src/main/java/moe/nea/firmament/init/Intermediary.java new file mode 100644 index 0000000..61494d7 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/Intermediary.java @@ -0,0 +1,63 @@ +package moe.nea.firmament.init; + +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.MappingResolver; +import org.objectweb.asm.Type; + +import java.util.List; + +public class Intermediary { + private static final MappingResolver RESOLVER = FabricLoader.getInstance().getMappingResolver(); + + static String methodName(Object object) { + throw new AssertionError("Cannot be called at runtime"); + } + + static String className() { + throw new AssertionError("Cannot be called at runtime"); + } + + static String id(String source) { + return source; + } + +// public record Class( +// Type intermediaryClass +// ) { +// public Class(String intermediaryClass) { +// this(Type.getObjectType(intermediaryClass.replace('.', '/'))); +// } +// +// public String getMappedName() { +// return RESOLVER.mapClassName("intermediary", intermediaryClass.getInternalName() +// .replace('/', '.')); +// } +// } +// +// public record Method( +// Type intermediaryClassName, +// String intermediaryMethodName, +// Type intermediaryReturnType, +// List intermediaryArgumentTypes +// ) { +// public Method( +// String intermediaryClassName, +// String intermediaryMethodName, +// String intermediaryReturnType, +// String... intermediaryArgumentTypes +// ) { +// this(intermediaryClassName, intermediaryMethodName, intermediaryReturnType, List.of(intermediaryArgumentTypes)); +// } +// +// public String getMappedMethodName() { +// return RESOLVER.mapMethodName("intermediary", +// intermediaryClassName.getInternalName().replace('/', '.')); +// } +// +// public Type getIntermediaryDescriptor() { +// return Type.getMethodType(intermediaryReturnType, intermediaryArgumentTypes.toArray(Type[]::new)); +// } +// +// +// } +} diff --git a/src/main/java/moe/nea/firmament/init/IntermediaryName.java b/src/main/java/moe/nea/firmament/init/IntermediaryName.java new file mode 100644 index 0000000..a22ad0f --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/IntermediaryName.java @@ -0,0 +1,21 @@ +package moe.nea.firmament.init; + +import net.fabricmc.loader.api.MappingResolver; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Injects the intermediary name of the given field into this field by replacing its initializer with a call to + * {@link MappingResolver#mapClassName(String, String)} + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.FIELD) +public @interface IntermediaryName { + // String method() default ""; +// +// String field() default ""; + Class value(); +} diff --git a/src/main/java/moe/nea/firmament/init/MixinPlugin.java b/src/main/java/moe/nea/firmament/init/MixinPlugin.java new file mode 100644 index 0000000..d48139b --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/MixinPlugin.java @@ -0,0 +1,76 @@ + + +package moe.nea.firmament.init; + +import com.llamalad7.mixinextras.MixinExtrasBootstrap; +import org.objectweb.asm.tree.ClassNode; +import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; +import org.spongepowered.asm.mixin.extensibility.IMixinInfo; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class MixinPlugin implements IMixinConfigPlugin { + + AutoDiscoveryPlugin autoDiscoveryPlugin = new AutoDiscoveryPlugin(); + public static List instances = new ArrayList<>(); + public String mixinPackage; + + @Override + public void onLoad(String mixinPackage) { + MixinExtrasBootstrap.init(); + instances.add(this); + this.mixinPackage = mixinPackage; + autoDiscoveryPlugin.setMixinPackage(mixinPackage); + } + + @Override + public String getRefMapperConfig() { + return null; + } + + @Override + public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { + if (!Boolean.getBoolean("firmament.debug") && mixinClassName.contains("devenv.")) { + return false; + } + return true; + } + + @Override + public void acceptTargets(Set myTargets, Set otherTargets) { + + } + + @Override + public List getMixins() { + return autoDiscoveryPlugin.getMixins().stream().filter(it -> this.shouldApplyMixin(null, it)) + .toList(); + } + + @Override + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + + } + + public Set getAppliedFullPathMixins() { + return new HashSet<>(appliedMixins); + } + + public Set getExpectedFullPathMixins() { + return getMixins() + .stream() + .map(it -> mixinPackage + "." + it) + .collect(Collectors.toSet()); + } + + public List appliedMixins = new ArrayList<>(); + + @Override + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { + appliedMixins.add(mixinClassName); + } +} diff --git a/src/main/java/moe/nea/firmament/init/RiserUtils.java b/src/main/java/moe/nea/firmament/init/RiserUtils.java new file mode 100644 index 0000000..c1c8fd1 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/RiserUtils.java @@ -0,0 +1,27 @@ + +package moe.nea.firmament.init; + +import net.fabricmc.loader.api.FabricLoader; +import net.fabricmc.loader.api.MappingResolver; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; + +public abstract class RiserUtils { + protected Type getTypeForClassName(String className) { + return Type.getObjectType(className.replace('.', '/')); + } + + protected MappingResolver remapper = FabricLoader.getInstance().getMappingResolver(); + + public abstract void addTinkerers(); + + protected MethodNode findMethod(ClassNode classNode, String name, Type desc) { + for (MethodNode method : classNode.methods) { + if (method.name.equals(name) && desc.getDescriptor().equals(method.desc)) + return method; + } + return null; + } + +} diff --git a/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java new file mode 100644 index 0000000..8b65946 --- /dev/null +++ b/src/main/java/moe/nea/firmament/init/SectionBuilderRiser.java @@ -0,0 +1,118 @@ +package moe.nea.firmament.init; + +import me.shedaniel.mm.api.ClassTinkerers; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.block.BlockRenderManager; +import net.minecraft.client.render.chunk.SectionBuilder; +import net.minecraft.client.render.model.BlockStateModel; +import net.minecraft.util.math.BlockPos; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.InsnList; +import org.objectweb.asm.tree.LocalVariableNode; +import org.objectweb.asm.tree.MethodInsnNode; +import org.objectweb.asm.tree.MethodNode; +import org.objectweb.asm.tree.VarInsnNode; + +public class SectionBuilderRiser extends RiserUtils { + + @IntermediaryName(SectionBuilder.class) + String SectionBuilder; + @IntermediaryName(BlockPos.class) + String BlockPos; + @IntermediaryName(BlockRenderManager.class) + String BlockRenderManager; + @IntermediaryName(BlockState.class) + String BlockState; + @IntermediaryName(BlockStateModel.class) + String BlockStateModel; + String CustomBlockTextures = "moe.nea.firmament.features.texturepack.CustomBlockTextures"; + + Type getModelDesc = Type.getMethodType( + getTypeForClassName(BlockRenderManager), + getTypeForClassName(BlockState) + ); + String getModel = remapper.mapMethodName( + "intermediary", + Intermediary.className(), + Intermediary.methodName(net.minecraft.client.render.block.BlockRenderManager::getModel), + Type.getMethodDescriptor( + getTypeForClassName(Intermediary.className()), + getTypeForClassName(Intermediary.className()) + ) + ); + + @Override + public void addTinkerers() { + if (FabricLoader.getInstance().isModLoaded("fabric-renderer-indigo")) + ClassTinkerers.addTransformation(SectionBuilder, this::handle, true); + } + + private void handle(ClassNode classNode) { + System.out.println("AVAST! "+ getModel); + for (MethodNode method : classNode.methods) { + if ((method.name.endsWith("$fabric-renderer-indigo$hookBuildRenderBlock") + || method.name.endsWith("$fabric-renderer-indigo$hookChunkBuildTessellate")) && + method.name.startsWith("redirect$")) { + handleIndigo(method); + return; + } + } + System.err.println("Could not inject indigo rendering hook. Is a custom renderer installed (e.g. sodium)?"); + } + + private void handleIndigo(MethodNode method) { + LocalVariableNode blockPosVar = null, blockStateVar = null; + for (LocalVariableNode localVariable : method.localVariables) { + if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockPos))) { + blockPosVar = localVariable; + } + if (Type.getType(localVariable.desc).equals(getTypeForClassName(BlockState))) { + blockStateVar = localVariable; + } + } + if (blockPosVar == null || blockStateVar == null) { + System.err.println("Firmament could inject into indigo: missing either block pos or blockstate"); + return; + } + for (AbstractInsnNode instruction : method.instructions) { + if (instruction.getOpcode() != Opcodes.INVOKEVIRTUAL) continue; + var methodInsn = (MethodInsnNode) instruction; + if (!(methodInsn.name.equals(getModel) && Type.getObjectType(methodInsn.owner).equals(getTypeForClassName(BlockRenderManager)))) + continue; + method.instructions.insertBefore( + methodInsn, + new MethodInsnNode( + Opcodes.INVOKESTATIC, + getTypeForClassName(CustomBlockTextures).getInternalName(), + "enterFallbackCall", + Type.getMethodDescriptor(Type.VOID_TYPE) + )); + + var insnList = new InsnList(); + insnList.add(new MethodInsnNode( + Opcodes.INVOKESTATIC, + getTypeForClassName(CustomBlockTextures).getInternalName(), + "exitFallbackCall", + Type.getMethodDescriptor(Type.VOID_TYPE) + )); + insnList.add(new VarInsnNode(Opcodes.ALOAD, blockPosVar.index)); + insnList.add(new VarInsnNode(Opcodes.ALOAD, blockStateVar.index)); + insnList.add(new MethodInsnNode( + Opcodes.INVOKESTATIC, + getTypeForClassName(CustomBlockTextures).getInternalName(), + "patchIndigo", + Type.getMethodDescriptor( + getTypeForClassName(BlockStateModel), + getTypeForClassName(BlockStateModel), + getTypeForClassName(BlockPos), + getTypeForClassName(BlockState)), + false + )); + method.instructions.insert(methodInsn, insnList); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java b/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java new file mode 100644 index 0000000..59769c6 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/AlwaysDisplayFirmamentClientCommandErrors.java @@ -0,0 +1,18 @@ +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import net.fabricmc.fabric.impl.command.client.ClientCommandInternals; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ClientCommandInternals.class) +public class AlwaysDisplayFirmamentClientCommandErrors { + @ModifyExpressionValue(method = "executeCommand", at = @At(value = "INVOKE", target = "Lnet/fabricmc/fabric/impl/command/client/ClientCommandInternals;isIgnoredException(Lcom/mojang/brigadier/exceptions/CommandExceptionType;)Z")) + private static boolean markFirmamentExceptionsAsNotIgnores(boolean original, @Local(argsOnly = true) String command) { + if (command.startsWith("firm ") || command.equals("firm") || command.startsWith("firmament ") || command.equals("firmament")) { + return false; + } + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java b/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java new file mode 100644 index 0000000..d8e35d7 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/AppendRepoAsResourcePack.java @@ -0,0 +1,34 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.repo.RepoModResourcePack; +import net.fabricmc.fabric.api.resource.ModResourcePack; +import net.fabricmc.fabric.impl.resource.loader.ModResourcePackSorter; +import net.fabricmc.fabric.impl.resource.loader.ModResourcePackUtil; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.resource.ResourceType; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; + +@Mixin(ModResourcePackUtil.class) +public class AppendRepoAsResourcePack { + @Inject( + method = "getModResourcePacks", + at = @At(value = "INVOKE", target = "Lnet/fabricmc/fabric/impl/resource/loader/ModResourcePackSorter;getPacks()Ljava/util/List;"), + require = 0 + ) + private static void onAppendModResourcePack( + FabricLoader fabricLoader, ResourceType type, @Nullable String subPath, CallbackInfoReturnable> cir, + @Local ModResourcePackSorter sorter + ) { + RepoModResourcePack.Companion.append(sorter); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java b/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java new file mode 100644 index 0000000..d898c44 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/BandAidResourcePackPatch.java @@ -0,0 +1,25 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.repo.RepoModResourcePack; +import net.minecraft.resource.ReloadableResourceManagerImpl; +import net.minecraft.resource.Resource; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Optional; + +@Mixin(ReloadableResourceManagerImpl.class) +public class BandAidResourcePackPatch { + + @ModifyReturnValue( + method = "getResource", + at = @At("RETURN") + ) + private Optional injectOurCustomResourcesInCaseExistingMethodsFailed(Optional original, @Local Identifier identifier) { + return original.or(() -> RepoModResourcePack.Companion.createResourceDirectly(identifier)); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/CaseInsensitiveCommandMapPatch.java b/src/main/java/moe/nea/firmament/mixins/CaseInsensitiveCommandMapPatch.java new file mode 100644 index 0000000..3bbf2ff --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/CaseInsensitiveCommandMapPatch.java @@ -0,0 +1,25 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.mojang.brigadier.tree.CommandNode; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Locale; +import java.util.Map; + +@Mixin(value = CommandNode.class, remap = false) +public class CaseInsensitiveCommandMapPatch { + @WrapOperation(method = "getRelevantNodes", at = @At(value = "INVOKE", target = "Ljava/util/Map;get(Ljava/lang/Object;)Ljava/lang/Object;"), remap = false) + public Object modify(Map map, Object text, Operation op) { + var original = op.call(map, text); + if (original == null) { + return map.get(((String) text).toLowerCase(Locale.ROOT)); + } + return original; + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java b/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java new file mode 100644 index 0000000..9f6fb4d --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/ChatPeekingPatch.java @@ -0,0 +1,25 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.gui.hud.ChatHud; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +@Mixin(ChatHud.class) +public class ChatPeekingPatch { + + @ModifyVariable(method = "render", at = @At(value = "HEAD"), index = 5, argsOnly = true) + public boolean onGetChatHud(boolean old) { + return old || Fixes.INSTANCE.shouldPeekChat(); + } + + @ModifyExpressionValue(method = "getHeight()I", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;isChatFocused()Z")) + public boolean onGetChatHudHeight(boolean old) { + return old || Fixes.INSTANCE.shouldPeekChat(); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java b/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java new file mode 100644 index 0000000..6996818 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/CopyChatPatch.java @@ -0,0 +1,44 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.features.chat.CopyChat; +import moe.nea.firmament.mixins.accessor.AccessorChatHud; +import moe.nea.firmament.util.ClipboardUtils; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import net.minecraft.client.gui.screen.ChatScreen; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import net.minecraft.util.math.MathHelper; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.List; + +@Mixin(ChatScreen.class) +public class CopyChatPatch { + @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true) + private void onRightClick(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) throws NoSuchFieldException, IllegalAccessException { + if (button != 1 || !CopyChat.TConfig.INSTANCE.getCopyChat()) return; + MinecraftClient client = MinecraftClient.getInstance(); + ChatHud chatHud = client.inGameHud.getChatHud(); + int lineIndex = getChatLineIndex(chatHud, mouseY); + if (lineIndex < 0) return; + List visible = ((AccessorChatHud) chatHud).getVisibleMessages_firmament(); + if (lineIndex >= visible.size()) return; + ChatHudLine.Visible line = visible.get(lineIndex); + String text = CopyChat.INSTANCE.orderedTextToString(line.content()); + ClipboardUtils.INSTANCE.setTextContent(text); + chatHud.addMessage(Text.literal("Copied: ").append(text).formatted(Formatting.GRAY)); + cir.setReturnValue(true); + cir.cancel(); + } + + @Unique + private int getChatLineIndex(ChatHud chatHud, double mouseY) { + double chatLineY = ((AccessorChatHud) chatHud).toChatLineY_firmament(mouseY); + return MathHelper.floor(chatLineY + ((AccessorChatHud) chatHud).getScrolledLines_firmament()); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java b/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java new file mode 100644 index 0000000..fde3580 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/CustomDurabilityBarPatch.java @@ -0,0 +1,53 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import moe.nea.firmament.util.DurabilityBarEvent; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(DrawContext.class) +public class CustomDurabilityBarPatch { + @WrapOperation( + method = "drawItemBar", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isItemBarVisible()Z") + ) + private boolean onIsItemBarVisible( + ItemStack instance, Operation original, + @Share("barOverride") LocalRef barOverride + ) { + if (original.call(instance)) + return true; + DurabilityBarEvent event = new DurabilityBarEvent(instance); + DurabilityBarEvent.Companion.publish(event); + barOverride.set(event.getBarOverride()); + return barOverride.get() != null; + } + + @WrapOperation(method = "drawItemBar", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemBarStep()I")) + private int overrideItemStep( + ItemStack instance, Operation original, + @Share("barOverride") LocalRef barOverride + ) { + if (barOverride.get() != null) + return Math.round(barOverride.get().getPercentage() * 13); + return original.call(instance); + } + + @WrapOperation(method = "drawItemBar", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;getItemBarColor()I")) + private int overrideItemColor( + ItemStack instance, Operation original, + @Share("barOverride") LocalRef barOverride + ) { + if (barOverride.get() != null) + return barOverride.get().getColor().getColor(); + return original.call(instance); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java b/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java new file mode 100644 index 0000000..717d404 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/DFUEntityIdFixPatch.java @@ -0,0 +1,35 @@ + + +package moe.nea.firmament.mixins; + +import com.mojang.datafixers.DataFix; +import com.mojang.datafixers.TypeRewriteRule; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.datafixers.util.Pair; +import net.minecraft.datafixer.TypeReferences; +import net.minecraft.datafixer.fix.EntityIdFix; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Map; + +// TODO: rework this +@Mixin(EntityIdFix.class) +public abstract class DFUEntityIdFixPatch extends DataFix { + @Shadow + @Final + private static Map RENAMED_ENTITIES; + + public DFUEntityIdFixPatch(Schema outputSchema, boolean changesType) { + super(outputSchema, changesType); + } + + @Inject(method = "makeRule", at = @At("RETURN"), cancellable = true) + public void onMakeRule(CallbackInfoReturnable cir) { + cir.setReturnValue(TypeRewriteRule.seq(fixTypeEverywhere("EntityIdFix", getInputSchema().findChoiceType(TypeReferences.ENTITY), getOutputSchema().findChoiceType(TypeReferences.ENTITY), dynamicOps -> pair -> ((Pair) pair).mapFirst(string -> RENAMED_ENTITIES.getOrDefault(string, (String) string))), convertUnchecked("Fix Type", getInputSchema().getType(TypeReferences.ITEM_STACK), getOutputSchema().getType(TypeReferences.ITEM_STACK)))); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java b/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java new file mode 100644 index 0000000..ed7a2d4 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/DisableHurtCam.java @@ -0,0 +1,18 @@ +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.render.GameRenderer; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(GameRenderer.class) +public class DisableHurtCam { + @ModifyExpressionValue(method = "tiltViewWhenHurt", at = @At(value = "FIELD", target = "Lnet/minecraft/entity/LivingEntity;hurtTime:I", opcode = Opcodes.GETFIELD)) + private int replaceHurtTime(int original) { + if (Fixes.TConfig.INSTANCE.getNoHurtCam()) + return 0; + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java b/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java new file mode 100644 index 0000000..f1b07bb --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/DispatchMouseInputEventsPatch.java @@ -0,0 +1,17 @@ +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import moe.nea.firmament.events.WorldMouseMoveEvent; +import net.minecraft.client.Mouse; +import net.minecraft.client.network.ClientPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Mouse.class) +public class DispatchMouseInputEventsPatch { + @WrapWithCondition(method = "updateMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;changeLookDirection(DD)V")) + public boolean onRotatePlayer(ClientPlayerEntity instance, double deltaX, double deltaY) { + var event = WorldMouseMoveEvent.Companion.publish(new WorldMouseMoveEvent(deltaX, deltaY)); + return !event.getCancelled(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java b/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java new file mode 100644 index 0000000..e98faf6 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/EarlyResourceReloadPatch.java @@ -0,0 +1,25 @@ + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.EarlyResourceReloadEvent; +import net.minecraft.resource.ReloadableResourceManagerImpl; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; +import net.minecraft.resource.ResourceReload; +import net.minecraft.util.Unit; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@Mixin(ReloadableResourceManagerImpl.class) +public abstract class EarlyResourceReloadPatch implements ResourceManager { + @Inject(method = "reload", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/SimpleResourceReload;start(Lnet/minecraft/resource/ResourceManager;Ljava/util/List;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;Ljava/util/concurrent/CompletableFuture;Z)Lnet/minecraft/resource/ResourceReload;", shift = At.Shift.BEFORE)) + public void onResourceReload(Executor prepareExecutor, Executor applyExecutor, CompletableFuture initialStage, List packs, CallbackInfoReturnable cir) { + EarlyResourceReloadEvent.Companion.publish(new EarlyResourceReloadEvent(this, prepareExecutor)); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java b/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java new file mode 100644 index 0000000..22bebec --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/EntityDespawnPatch.java @@ -0,0 +1,20 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.EntityDespawnEvent; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientWorld.class) +public class EntityDespawnPatch { + @Inject(method = "removeEntity", at = @At(value = "TAIL")) + private void onRemoved(int entityId, Entity.RemovalReason removalReason, CallbackInfo ci, @Local @Nullable Entity entity) { + EntityDespawnEvent.Companion.publish(new EntityDespawnEvent(entity, entityId, removalReason)); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java b/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java new file mode 100644 index 0000000..8ade59b --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/EntityInteractEventPatch.java @@ -0,0 +1,34 @@ + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.EntityInteractionEvent; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.EntityHitResult; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerInteractionManager.class) +public class EntityInteractEventPatch { + @Inject(method = "attackEntity", at = @At("HEAD")) + private void onAttack(PlayerEntity player, Entity target, CallbackInfo ci) { + EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.ATTACK, target, Hand.MAIN_HAND)); + } + + @Inject(method = "interactEntity", at = @At("HEAD")) + private void onInteract(PlayerEntity player, Entity entity, Hand hand, CallbackInfoReturnable cir) { + EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.INTERACT, entity, hand)); + } + + @Inject(method = "interactEntityAtLocation", at = @At("HEAD")) + private void onInteractAtLocation(PlayerEntity player, Entity entity, EntityHitResult hitResult, Hand hand, CallbackInfoReturnable cir) { + EntityInteractionEvent.Companion.publish(new EntityInteractionEvent(EntityInteractionEvent.InteractionKind.INTERACT_AT_LOCATION, entity, hand)); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java new file mode 100644 index 0000000..d956da9 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/EntityUpdateEventListener.java @@ -0,0 +1,48 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.EntityUpdateEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.client.network.ClientConnectionState; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.entity.LivingEntity; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket; +import net.minecraft.network.packet.s2c.play.EntityEquipmentUpdateS2CPacket; +import net.minecraft.network.packet.s2c.play.EntityTrackerUpdateS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class EntityUpdateEventListener extends ClientCommonNetworkHandler { + + @Shadow + private ClientWorld world; + + protected EntityUpdateEventListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) { + super(client, connection, connectionState); + } + + @Inject(method = "onEntityEquipmentUpdate", at = @At(value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", shift = At.Shift.AFTER)) + private void onEquipmentUpdate(EntityEquipmentUpdateS2CPacket packet, CallbackInfo ci, @Local LivingEntity entity) { + EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.EquipmentUpdate(entity, packet.getEquipmentList())); + } + + @Inject(method = "onEntityAttributes", at = @At("TAIL")) + private void onAttributeUpdate(EntityAttributesS2CPacket packet, CallbackInfo ci) { + EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.AttributeUpdate( + (LivingEntity) world.getEntityById(packet.getEntityId()), packet.getEntries())); + } + + @Inject(method = "onEntityTrackerUpdate", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/data/DataTracker;writeUpdatedEntries(Ljava/util/List;)V", shift = At.Shift.AFTER)) + private void onEntityTracker(EntityTrackerUpdateS2CPacket packet, CallbackInfo ci, @Local Entity entity) { + EntityUpdateEvent.Companion.publish(new EntityUpdateEvent.TrackedDataUpdate(entity, packet.trackedValues())); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java new file mode 100644 index 0000000..699d5b7 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/FirmKeybindsInVanillaControlsPatch.java @@ -0,0 +1,58 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.gui.config.KeyBindingHandler; +import moe.nea.firmament.gui.config.ManagedConfig; +import moe.nea.firmament.keybindings.FirmamentKeyBindings; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.option.ControlsListWidget; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ControlsListWidget.KeyBindingEntry.class) +public class FirmKeybindsInVanillaControlsPatch { + + @Mutable + @Shadow + @Final + private ButtonWidget editButton; + + @Shadow + @Final + private KeyBinding binding; + + @Shadow + @Final + private ButtonWidget resetButton; + + @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/ButtonWidget;builder(Lnet/minecraft/text/Text;Lnet/minecraft/client/gui/widget/ButtonWidget$PressAction;)Lnet/minecraft/client/gui/widget/ButtonWidget$Builder;")) + public ButtonWidget.PressAction onInit(ButtonWidget.PressAction action) { + var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(binding); + if (config == null) return action; + return button -> { + ((KeyBindingHandler) config.getHandler()) + .getManagedConfig() + .showConfigEditor(MinecraftClient.getInstance().currentScreen); + }; + } + + @Inject(method = "update", at = @At("HEAD"), cancellable = true) + public void onUpdate(CallbackInfo ci) { + var config = FirmamentKeyBindings.INSTANCE.getKeyBindings().get(binding); + if (config == null) return; + resetButton.active = false; + editButton.setMessage(Text.translatable("firmament.keybinding.external", config.getValue().format())); + ci.cancel(); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java new file mode 100644 index 0000000..c5af8b6 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/HideStatusEffectsPatch.java @@ -0,0 +1,29 @@ +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.screen.ingame.StatusEffectsDisplay; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(InventoryScreen.class) +public abstract class HideStatusEffectsPatch { + @Shadow + public abstract boolean shouldHideStatusEffectHud(); + + @Inject(method = "shouldHideStatusEffectHud", at = @At("HEAD"), cancellable = true) + private void hideStatusEffects(CallbackInfoReturnable cir) { + cir.setReturnValue(!Fixes.TConfig.INSTANCE.getHidePotionEffects()); + } + + @WrapWithCondition(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/StatusEffectsDisplay;drawStatusEffects(Lnet/minecraft/client/gui/DrawContext;IIF)V")) + private boolean conditionalRenderStatuses(StatusEffectsDisplay instance, DrawContext context, int mouseX, int mouseY, float tickDelta) { + return shouldHideStatusEffectHud() || !Fixes.TConfig.INSTANCE.getHidePotionEffects(); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java b/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java new file mode 100644 index 0000000..49e86fb --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/HudRenderEventsPatch.java @@ -0,0 +1,36 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.HotbarItemRenderEvent; +import moe.nea.firmament.events.HudRenderEvent; +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.render.RenderTickCounter; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(InGameHud.class) +public class HudRenderEventsPatch { + @Inject(method = "renderSleepOverlay", at = @At(value = "HEAD")) + public void renderCallBack(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { + HudRenderEvent.Companion.publish(new HudRenderEvent(context, tickCounter)); + } + + @Inject(method = "renderHotbarItem", at = @At("HEAD")) + public void onRenderHotbarItem(DrawContext context, int x, int y, RenderTickCounter tickCounter, PlayerEntity player, ItemStack stack, int seed, CallbackInfo ci) { + if (stack != null && !stack.isEmpty()) + HotbarItemRenderEvent.Companion.publish(new HotbarItemRenderEvent(stack, context, x, y, tickCounter)); + } + + @Inject(method = "renderStatusEffectOverlay", at = @At("HEAD"), cancellable = true) + public void hideStatusEffects(CallbackInfo ci) { + if (Fixes.TConfig.INSTANCE.getHidePotionEffectsHud()) ci.cancel(); + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java new file mode 100644 index 0000000..a7c3875 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java @@ -0,0 +1,41 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.mojang.brigadier.CommandDispatcher; +import moe.nea.firmament.events.MaskCommands; +import moe.nea.firmament.events.ParticleSpawnEvent; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.ParticleS2CPacket; +import net.minecraft.util.math.Vec3d; +import org.joml.Vector3f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class IncomingPacketListenerPatches { + + @ModifyExpressionValue(method = "onCommandTree", at = @At(value = "NEW", target = "(Lcom/mojang/brigadier/tree/RootCommandNode;)Lcom/mojang/brigadier/CommandDispatcher;", remap = false)) + public CommandDispatcher onOnCommandTree(CommandDispatcher dispatcher) { + MaskCommands.Companion.publish(new MaskCommands(dispatcher)); + return dispatcher; + } + + @Inject(method = "onParticle", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER), cancellable = true) + public void onParticleSpawn(ParticleS2CPacket packet, CallbackInfo ci) { + var event = new ParticleSpawnEvent( + packet.getParameters(), + new Vec3d(packet.getX(), packet.getY(), packet.getZ()), + new Vector3f(packet.getOffsetX(), packet.getOffsetY(), packet.getOffsetZ()), + packet.isImportant(), + packet.getCount(), + packet.getSpeed() + ); + ParticleSpawnEvent.Companion.publish(event); + if (event.getCancelled()) + ci.cancel(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java b/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java new file mode 100644 index 0000000..d2b3f91 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/KeyPressInWorldEventPatch.java @@ -0,0 +1,20 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import moe.nea.firmament.events.WorldKeyboardEvent; +import net.minecraft.client.Keyboard; +import net.minecraft.client.util.InputUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(Keyboard.class) +public class KeyPressInWorldEventPatch { + + @WrapWithCondition(method = "onKey", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V")) + public boolean onKeyBoardInWorld(InputUtil.Key key, long window, int _key, int scancode, int action, int modifiers) { + var event = WorldKeyboardEvent.Companion.publish(new WorldKeyboardEvent(_key, scancode, modifiers)); + return !event.getCancelled(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java b/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java new file mode 100644 index 0000000..0a90b35 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/MainWindowFirstLoadPatch.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.Firmament; +import moe.nea.firmament.events.DebugInstantiateEvent; +import net.minecraft.client.gui.LogoDrawer; +import net.minecraft.client.gui.screen.TitleScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TitleScreen.class) +public class MainWindowFirstLoadPatch { + @Unique + private static boolean hasInited = false; + + @Inject(method = "(ZLnet/minecraft/client/gui/LogoDrawer;)V", at = @At("RETURN")) + private void onCreate(boolean doBackgroundFade, LogoDrawer logoDrawer, CallbackInfo ci) { + if (!hasInited) { + try { + DebugInstantiateEvent.Companion.publish(new DebugInstantiateEvent()); + } catch (Throwable t) { + Firmament.INSTANCE.getLogger().error("Failed to instantiate debug instances", t); + System.exit(1); + throw t; + } + } + hasInited = true; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java b/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java new file mode 100644 index 0000000..1673987 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/MinecraftInitLevelListener.java @@ -0,0 +1,26 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.util.mc.InitLevel; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class MinecraftInitLevelListener { + @Inject(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initBackendSystem()Lnet/minecraft/util/TimeSupplier$Nanoseconds;")) + private void onInitRenderBackend(CallbackInfo ci) { + InitLevel.bump(InitLevel.RENDER_INIT); + } + + @Inject(method = "", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/systems/RenderSystem;initRenderer(JIZLjava/util/function/BiFunction;Z)V")) + private void onInitRender(CallbackInfo ci) { + InitLevel.bump(InitLevel.RENDER); + } + + @Inject(method = "", at = @At(value = "TAIL")) + private void onFinishedLoading(CallbackInfo ci) { + InitLevel.bump(InitLevel.MAIN_MENU); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java new file mode 100644 index 0000000..43aec40 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/MixinHandledScreen.java @@ -0,0 +1,102 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.events.HandledScreenClickEvent; +import moe.nea.firmament.events.HandledScreenForegroundEvent; +import moe.nea.firmament.events.HandledScreenKeyPressedEvent; +import moe.nea.firmament.events.IsSlotProtectedEvent; +import moe.nea.firmament.events.SlotRenderEvents; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = HandledScreen.class, priority = 990) +public abstract class MixinHandledScreen { + + @Shadow + @Final + protected T handler; + + @Shadow + public abstract T getScreenHandler(); + + @Shadow + protected int y; + @Shadow + protected int x; + @Unique + PlayerInventory playerInventory; + + @Inject(method = "", at = @At("TAIL")) + public void savePlayerInventory(ScreenHandler handler, PlayerInventory inventory, Text title, CallbackInfo ci) { + this.playerInventory = inventory; + } + + @Inject(method = "keyPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;handleHotbarKeyPressed(II)Z", shift = At.Shift.BEFORE), cancellable = true) + public void onKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { + if (HandledScreenKeyPressedEvent.Companion.publish(new HandledScreenKeyPressedEvent((HandledScreen) (Object) this, keyCode, scanCode, modifiers)).getCancelled()) { + cir.setReturnValue(true); + } + } + + @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true) + public void onMouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { + if (HandledScreenClickEvent.Companion.publish(new HandledScreenClickEvent((HandledScreen) (Object) this, mouseX, mouseY, button)).getCancelled()) { + cir.setReturnValue(true); + } + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawForeground(Lnet/minecraft/client/gui/DrawContext;II)V", shift = At.Shift.AFTER)) + public void onAfterRenderForeground(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + context.getMatrices().push(); + context.getMatrices().translate(-x, -y, 0); + HandledScreenForegroundEvent.Companion.publish(new HandledScreenForegroundEvent((HandledScreen) (Object) this, context, mouseX, mouseY, delta)); + context.getMatrices().pop(); + } + + @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) + public void onMouseClickedSlot(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { + if (slotId == -999 && getScreenHandler() != null && actionType == SlotActionType.PICKUP) { // -999 is code for "clicked outside the main window" + ItemStack cursorStack = getScreenHandler().getCursorStack(); + if (cursorStack != null && IsSlotProtectedEvent.shouldBlockInteraction(slot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE, cursorStack)) { + ci.cancel(); + return; + } + } + if (IsSlotProtectedEvent.shouldBlockInteraction(slot, actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) { + ci.cancel(); + return; + } + if (actionType == SlotActionType.SWAP && 0 <= button && button < 9) { + if (IsSlotProtectedEvent.shouldBlockInteraction(new Slot(playerInventory, button, 0, 0), actionType, IsSlotProtectedEvent.MoveOrigin.INVENTORY_MOVE)) { + ci.cancel(); + } + } + } + + + @WrapOperation(method = "drawSlots", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawSlot(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/screen/slot/Slot;)V")) + public void onDrawSlots(HandledScreen instance, DrawContext context, Slot slot, Operation original) { + var before = new SlotRenderEvents.Before(context, slot); + SlotRenderEvents.Before.Companion.publish(before); + original.call(instance, context, slot); + var after = new SlotRenderEvents.After(context, slot); + SlotRenderEvents.After.Companion.publish(after); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java b/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java new file mode 100644 index 0000000..12455f4 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/MixinPlayerScreenHandler.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.PlayerScreenHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(PlayerScreenHandler.class) +public class MixinPlayerScreenHandler { + + @Unique + private static final int OFF_HAND_SLOT = 40; + + @Inject(method = "", at = @At("TAIL")) + private void moveOffHandSlot(PlayerInventory inventory, boolean onServer, PlayerEntity owner, CallbackInfo ci) { + if (Fixes.TConfig.INSTANCE.getHideOffHand()) { + PlayerScreenHandler self = (PlayerScreenHandler) (Object) this; + self.slots.stream() + .filter(slot -> slot.getIndex() == OFF_HAND_SLOT) + .forEach(slot -> { + slot.x = -1000; + slot.y = -1000; + }); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java b/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java new file mode 100644 index 0000000..2dbe738 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/MixinRecipeBookScreen.java @@ -0,0 +1,16 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.gui.screen.ingame.RecipeBookScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = RecipeBookScreen.class, priority = 999) +public class MixinRecipeBookScreen { + @Inject(method = "addRecipeBook", at = @At("HEAD"), cancellable = true) + public void addRecipeBook(CallbackInfo ci) { + if (Fixes.TConfig.INSTANCE.getHideRecipeBook()) ci.cancel(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java b/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java new file mode 100644 index 0000000..25505b7 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/OutgoingPacketEventPatch.java @@ -0,0 +1,21 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.OutgoingPacketEvent; +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.network.packet.Packet; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientCommonNetworkHandler.class) +public class OutgoingPacketEventPatch { + @Inject(method = "sendPacket(Lnet/minecraft/network/packet/Packet;)V", at = @At("HEAD"), cancellable = true) + public void onSendPacket(Packet packet, CallbackInfo ci) { + if (OutgoingPacketEvent.Companion.publish(new OutgoingPacketEvent(packet)).getCancelled()) { + ci.cancel(); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java new file mode 100644 index 0000000..f07604e --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/PlayerDropEventPatch.java @@ -0,0 +1,28 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.IsSlotProtectedEvent; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.screen.slot.Slot; +import net.minecraft.screen.slot.SlotActionType; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(ClientPlayerEntity.class) +public abstract class PlayerDropEventPatch extends PlayerEntity { + public PlayerDropEventPatch() { + super(null, null, 0, null); + } + + @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) + public void onDropSelectedItem(boolean entireStack, CallbackInfoReturnable cir) { + Slot fakeSlot = new Slot(getInventory(), getInventory().getSelectedSlot(), 0, 0); + if (IsSlotProtectedEvent.shouldBlockInteraction(fakeSlot, SlotActionType.THROW, IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR)) { + cir.setReturnValue(false); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatchForSession.java b/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatchForSession.java new file mode 100644 index 0000000..46995ec --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/PropertySignatureIgnorePatchForSession.java @@ -0,0 +1,24 @@ + +package moe.nea.firmament.mixins; + +import com.mojang.authlib.SignatureState; +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; +import moe.nea.firmament.features.fixes.Fixes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = YggdrasilMinecraftSessionService.class, remap = false) +public class PropertySignatureIgnorePatchForSession { + @Inject(method = "getPropertySignatureState", at = @At("HEAD"), cancellable = true, remap = false) + public void markEverythingAsSigned(Property property, CallbackInfoReturnable cir) { + // Due to https://github.com/inglettronald/DulkirMod-Fabric/blob/22a3fc514a080fbe31f76f9ba7e85c36d8d0f67f/src/main/java/com/dulkirfabric/mixin/YggdrasilMinecraftSessionServiceMixin.java + // we sadly need to inject here too. Dulkirmod is very eager to early on mark a signature as unsigned + // and we want the opposite + if (Fixes.TConfig.INSTANCE.getFixUnsignedPlayerSkins()) { + cir.setReturnValue(SignatureState.SIGNED); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/RedirectWithoutSubCommands.java b/src/main/java/moe/nea/firmament/mixins/RedirectWithoutSubCommands.java new file mode 100644 index 0000000..2186aee --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/RedirectWithoutSubCommands.java @@ -0,0 +1,42 @@ +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.ParseResults; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.context.CommandContextBuilder; +import com.mojang.brigadier.tree.CommandNode; +import moe.nea.firmament.util.ErrorUtil; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.HashSet; + +@Mixin(CommandDispatcher.class) +public class RedirectWithoutSubCommands { + @Inject( + method = "parseNodes", + at = @At( + value = "INVOKE", + target = "Lcom/mojang/brigadier/context/CommandContextBuilder;withCommand(Lcom/mojang/brigadier/Command;)Lcom/mojang/brigadier/context/CommandContextBuilder;", + shift = At.Shift.AFTER + ) + ) + private void injectCommandForRedirects( + CommandNode node, StringReader originalReader, CommandContextBuilder contextSoFar, CallbackInfoReturnable> cir, + @Local(index = 10) CommandContextBuilder context, + @Local(index = 9) CommandNode child + ) { + var p = child; + var set = new HashSet<>(); + if (context.getCommand() == null && p.getRedirect() != null) { + p = p.getRedirect(); + context.withCommand(p.getCommand()); + if (!set.add(p)) { + ErrorUtil.INSTANCE.softError("Redirect circle detected in " + p); + } + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java b/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java new file mode 100644 index 0000000..28fe3d9 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/ResourceReloaderRegistrationPatch.java @@ -0,0 +1,26 @@ + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.FinalizeResourceManagerEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.RunArgs; +import net.minecraft.resource.ReloadableResourceManagerImpl; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class ResourceReloaderRegistrationPatch { + @Shadow + @Final + private ReloadableResourceManagerImpl resourceManager; + + @Inject(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/resource/ResourcePackManager;createResourcePacks()Ljava/util/List;", shift = At.Shift.BEFORE)) + private void onBeforeResourcePackCreation(RunArgs args, CallbackInfo ci) { + FinalizeResourceManagerEvent.Companion.publish(new FinalizeResourceManagerEvent(this.resourceManager)); + } +} + diff --git a/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java b/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java new file mode 100644 index 0000000..fd3adca --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SaveCursorPositionPatch.java @@ -0,0 +1,40 @@ + + +package moe.nea.firmament.mixins; + +import kotlin.Pair; +import moe.nea.firmament.features.inventory.SaveCursorPosition; +import net.minecraft.client.Mouse; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Mouse.class) +public class SaveCursorPositionPatch { + @Shadow + private double x; + + @Shadow + private double y; + + @Inject(method = "lockCursor", at = @At(value = "FIELD", opcode = Opcodes.PUTFIELD, target = "Lnet/minecraft/client/Mouse;cursorLocked:Z")) + public void onLockCursor(CallbackInfo ci) { + SaveCursorPosition.saveCursorOriginal(x, y); + } + + @Inject(method = "lockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;getHandle()J")) + public void onLockCursorAfter(CallbackInfo ci) { + SaveCursorPosition.saveCursorMiddle(x, y); + } + + @Inject(method = "unlockCursor", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/Window;getHandle()J")) + public void onUnlockCursor(CallbackInfo ci) { + Pair cursorPosition = SaveCursorPosition.loadCursor(this.x, this.y); + if (cursorPosition == null) return; + this.x = cursorPosition.getFirst(); + this.y = cursorPosition.getSecond(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java b/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java new file mode 100644 index 0000000..2f2f188 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SaveOriginalCommandTreePacket.java @@ -0,0 +1,17 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.features.chat.QuickCommands; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public class SaveOriginalCommandTreePacket { + @Inject(method = "onCommandTree", at = @At(value = "RETURN")) + private void saveUnmodifiedCommandTree(CommandTreeS2CPacket packet, CallbackInfo ci) { + QuickCommands.INSTANCE.setLastReceivedTreePacket(packet); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java b/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java new file mode 100644 index 0000000..6d19405 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/ScreenChangeEventPatch.java @@ -0,0 +1,32 @@ + + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import moe.nea.firmament.events.ScreenChangeEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public abstract class ScreenChangeEventPatch { + @Shadow + @Nullable + public Screen currentScreen; + + @Inject(method = "setScreen", at = @At("HEAD"), cancellable = true) + public void onScreenChange(Screen screen, CallbackInfo ci, @Local(argsOnly = true) LocalRef screenLocalRef) { + var event = new ScreenChangeEvent(currentScreen, screen); + if (ScreenChangeEvent.Companion.publish(event).getCancelled()) { + ci.cancel(); + } else if (event.getOverrideScreen() != null) { + screenLocalRef.set(event.getOverrideScreen()); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java b/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java new file mode 100644 index 0000000..21e7899 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SlotClickEventPatch.java @@ -0,0 +1,41 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import moe.nea.firmament.events.SlotClickEvent; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.SlotActionType; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayerInteractionManager.class) +public class SlotClickEventPatch { + + @Inject(method = "clickSlot", at = @At(value = "FIELD", target = "Lnet/minecraft/screen/ScreenHandler;slots:Lnet/minecraft/util/collection/DefaultedList;", opcode = Opcodes.GETFIELD)) + private void onSlotClickSaveSlot(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef slotContent) { + if (0 <= slotId && slotId < handler.slots.size()) { + slotContent.set(handler.getSlot(slotId).getStack().copy()); + } + } + + @Inject(method = "clickSlot", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayNetworkHandler;sendPacket(Lnet/minecraft/network/packet/Packet;)V")) + private void onSlotClick(int syncId, int slotId, int button, SlotActionType actionType, PlayerEntity player, CallbackInfo ci, @Local ScreenHandler handler, @Share("slotContent") LocalRef slotContent) { + if (0 <= slotId && slotId < handler.slots.size()) { + SlotClickEvent.Companion.publish(new SlotClickEvent( + handler.getSlot(slotId), + slotContent.get(), + button, + actionType + )); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java new file mode 100644 index 0000000..a4ae931 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SlotUpdateListener.java @@ -0,0 +1,54 @@ + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.ChestInventoryUpdateEvent; +import moe.nea.firmament.events.PlayerInventoryUpdate; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientCommonNetworkHandler; +import net.minecraft.client.network.ClientConnectionState; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.packet.s2c.play.InventoryS2CPacket; +import net.minecraft.network.packet.s2c.play.ScreenHandlerSlotUpdateS2CPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ClientPlayNetworkHandler.class) +public abstract class SlotUpdateListener extends ClientCommonNetworkHandler { + protected SlotUpdateListener(MinecraftClient client, ClientConnection connection, ClientConnectionState connectionState) { + super(client, connection, connectionState); + } + + @Inject( + method = "onScreenHandlerSlotUpdate", + at = @At(value = "TAIL")) + private void onSingleSlotUpdate( + ScreenHandlerSlotUpdateS2CPacket packet, + CallbackInfo ci) { + var player = this.client.player; + assert player != null; + if (packet.getSyncId() == 0) { + PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Single(packet.getSlot(), packet.getStack())); + } else if (packet.getSyncId() == player.currentScreenHandler.syncId) { + ChestInventoryUpdateEvent.Companion.publish( + new ChestInventoryUpdateEvent.Single(packet.getSlot(), packet.getStack()) + ); + } + } + + @Inject(method = "onInventory", + at = @At("TAIL")) + private void onMultiSlotUpdate(InventoryS2CPacket packet, CallbackInfo ci) { + var player = this.client.player; + assert player != null; + if (packet.syncId() == 0) { + PlayerInventoryUpdate.Companion.publish(new PlayerInventoryUpdate.Multi(packet.contents())); + } else if (packet.syncId() == player.currentScreenHandler.syncId) { + ChestInventoryUpdateEvent.Companion.publish( + new ChestInventoryUpdateEvent.Multi(packet.contents()) + ); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java b/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java new file mode 100644 index 0000000..b8cba80 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/SoundReceiveEventPatch.java @@ -0,0 +1,32 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import moe.nea.firmament.events.SoundReceiveEvent; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.entity.Entity; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.Vec3d; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ClientPlayNetworkHandler.class) +public class SoundReceiveEventPatch { + @WrapWithCondition(method = "onPlaySound", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/world/ClientWorld;playSound(Lnet/minecraft/entity/Entity;DDDLnet/minecraft/registry/entry/RegistryEntry;Lnet/minecraft/sound/SoundCategory;FFJ)V")) + private boolean postEventWhenSoundIsPlayed(ClientWorld instance, @Nullable Entity source, double x, double y, double z, RegistryEntry sound, SoundCategory category, float volume, float pitch, long seed) { + var event = new SoundReceiveEvent( + sound, + category, + new Vec3d(x,y,z), + pitch, + volume, + seed + ); + SoundReceiveEvent.Companion.publish(event); + return !event.getCancelled(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/TextureUnpackBase64PadPatch.java b/src/main/java/moe/nea/firmament/mixins/TextureUnpackBase64PadPatch.java new file mode 100644 index 0000000..43ce950 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/TextureUnpackBase64PadPatch.java @@ -0,0 +1,19 @@ + +package moe.nea.firmament.mixins; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.mojang.authlib.yggdrasil.YggdrasilMinecraftSessionService; +import moe.nea.firmament.util.Base64Util; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(value = YggdrasilMinecraftSessionService.class, remap = false) +public class TextureUnpackBase64PadPatch { + @ModifyExpressionValue(method = "unpackTextures", + remap = false, + at = @At(value = "INVOKE", target = "Lcom/mojang/authlib/properties/Property;value()Ljava/lang/String;")) + private String base64PadTexture(String original) { + if (original.length() % 4 == 0) return original; + return Base64Util.INSTANCE.padToValidBase64(original); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java b/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java new file mode 100644 index 0000000..1acbf20 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/ToggleSprintPatch.java @@ -0,0 +1,18 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.client.option.KeyBinding; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(KeyBinding.class) +public class ToggleSprintPatch { + @Inject(method = "isPressed", at = @At("HEAD"), cancellable = true) + public void onIsPressed(CallbackInfoReturnable cir) { + Fixes.INSTANCE.handleIsPressed((KeyBinding) (Object) this, cir); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java b/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java new file mode 100644 index 0000000..ac6f614 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/TolerateFirmamentTolerateRegistryOwners.java @@ -0,0 +1,18 @@ +package moe.nea.firmament.mixins; + +import moe.nea.firmament.util.mc.TolerantRegistriesOps; +import net.minecraft.registry.entry.RegistryEntryOwner; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(RegistryEntryOwner.class) +public interface TolerateFirmamentTolerateRegistryOwners { + @Inject(method = "ownerEquals", at = @At("HEAD"), cancellable = true) + private void equalTolerantRegistryOwners(RegistryEntryOwner other, CallbackInfoReturnable cir) { + if (other instanceof TolerantRegistriesOps.TolerantOwner) { + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java b/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java new file mode 100644 index 0000000..d4b8c9e --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/WorldReadyEventPatch.java @@ -0,0 +1,19 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.WorldReadyEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.DownloadingTerrainScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class WorldReadyEventPatch { + @Inject(method = "joinWorld", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;setWorld(Lnet/minecraft/client/world/ClientWorld;)V", shift = At.Shift.AFTER)) + public void onClose(CallbackInfo ci) { + WorldReadyEvent.Companion.publish(new WorldReadyEvent()); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java b/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java new file mode 100644 index 0000000..3ed8c1b --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/WorldRenderLastEventPatch.java @@ -0,0 +1,45 @@ + + +package moe.nea.firmament.mixins; + +import moe.nea.firmament.events.WorldRenderLastEvent; +import net.minecraft.client.render.*; +import net.minecraft.client.util.Handle; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.profiler.Profiler; +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(WorldRenderer.class) +public abstract class WorldRenderLastEventPatch { + @Shadow + @Final + private BufferBuilderStorage bufferBuilders; + + @Shadow + @Final + private DefaultFramebufferSet framebufferSet; + + @Shadow + protected abstract void checkEmpty(MatrixStack matrices); + + @Inject(method = "method_62214", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;pop()V", shift = At.Shift.AFTER)) + public void onWorldRenderLast(Fog fog, RenderTickCounter renderTickCounter, Camera camera, Profiler profiler, Matrix4f matrix4f, Matrix4f matrix4f2, Handle handle, Handle handle2, boolean bl, Frustum frustum, Handle handle3, Handle handle4, CallbackInfo ci) { + var imm = this.bufferBuilders.getEntityVertexConsumers(); + var stack = new MatrixStack(); + // TODO: pre-cancel this event if F1 is active + var event = new WorldRenderLastEvent( + stack, renderTickCounter, + camera, + imm + ); + WorldRenderLastEvent.Companion.publish(event); + imm.draw(); + checkEmpty(stack); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/YggdrasilSignatureIgnorePatch.java b/src/main/java/moe/nea/firmament/mixins/YggdrasilSignatureIgnorePatch.java new file mode 100644 index 0000000..2f1499c --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/YggdrasilSignatureIgnorePatch.java @@ -0,0 +1,21 @@ + + +package moe.nea.firmament.mixins; + +import com.mojang.authlib.properties.Property; +import com.mojang.authlib.yggdrasil.YggdrasilServicesKeyInfo; +import moe.nea.firmament.features.fixes.Fixes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(value = YggdrasilServicesKeyInfo.class, remap = false) +public class YggdrasilSignatureIgnorePatch { + @Inject(method = "validateProperty", at = @At("HEAD"), cancellable = true, remap = false) + public void validate(Property property, CallbackInfoReturnable cir) { + if (Fixes.TConfig.INSTANCE.getFixUnsignedPlayerSkins()) { + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java new file mode 100644 index 0000000..0a10046 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorAbstractClientPlayerEntity.java @@ -0,0 +1,13 @@ + +package moe.nea.firmament.mixins.accessor; + +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.network.PlayerListEntry; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(AbstractClientPlayerEntity.class) +public interface AccessorAbstractClientPlayerEntity { + @Accessor("playerListEntry") + void setPlayerListEntry_firmament(PlayerListEntry playerListEntry); +} diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java new file mode 100644 index 0000000..d164aac --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorChatHud.java @@ -0,0 +1,24 @@ +package moe.nea.firmament.mixins.accessor; + +import net.minecraft.client.gui.hud.ChatHud; +import net.minecraft.client.gui.hud.ChatHudLine; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.List; + +@Mixin(ChatHud.class) +public interface AccessorChatHud { + @Accessor("messages") + List getMessages_firmament(); + + @Accessor("visibleMessages") + List getVisibleMessages_firmament(); + + @Accessor("scrolledLines") + int getScrolledLines_firmament(); + + @Invoker("toChatLineY") + double toChatLineY_firmament(double y); +} diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java new file mode 100644 index 0000000..f55ef4f --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorHandledScreen.java @@ -0,0 +1,39 @@ +package moe.nea.firmament.mixins.accessor; + +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.screen.slot.Slot; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(HandledScreen.class) +public interface AccessorHandledScreen { + @Accessor("focusedSlot") + @Nullable + Slot getFocusedSlot_Firmament(); + + @Accessor("backgroundWidth") + int getBackgroundWidth_Firmament(); + + @Accessor("backgroundWidth") + void setBackgroundWidth_Firmament(int newBackgroundWidth); + + @Accessor("backgroundHeight") + int getBackgroundHeight_Firmament(); + + @Accessor("backgroundHeight") + void setBackgroundHeight_Firmament(int newBackgroundHeight); + + @Accessor("x") + int getX_Firmament(); + + @Accessor("x") + void setX_Firmament(int newX); + + @Accessor("y") + int getY_Firmament(); + + @Accessor("y") + void setY_Firmament(int newY); + +} diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java new file mode 100644 index 0000000..81ea0fd --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorPlayerListHud.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.mixins.accessor; + +import net.minecraft.client.gui.hud.PlayerListHud; +import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +import java.util.Comparator; +import java.util.List; + +@Mixin(PlayerListHud.class) +public interface AccessorPlayerListHud { + + @Accessor("ENTRY_ORDERING") + static Comparator getEntryOrdering() { + throw new AssertionError(); + } + + @Invoker("collectPlayerEntries") + List collectPlayerEntries_firmament(); + + @Accessor("footer") + @Nullable Text getFooter_firmament(); + + @Accessor("header") + @Nullable Text getHeader_firmament(); + +} diff --git a/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java new file mode 100644 index 0000000..8b25562 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/accessor/AccessorWorldRenderer.java @@ -0,0 +1,17 @@ +package moe.nea.firmament.mixins.accessor; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.entity.player.BlockBreakingInfo; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +import java.util.SortedSet; + +@Mixin(WorldRenderer.class) +public interface AccessorWorldRenderer { + @Accessor("blockBreakingProgressions") + @NotNull + Long2ObjectMap> getBlockBreakingProgressions_firmament(); +} diff --git a/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java b/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java new file mode 100644 index 0000000..c705625 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/customgui/OriginalSlotCoords.java @@ -0,0 +1,43 @@ + +package moe.nea.firmament.mixins.customgui; + +import moe.nea.firmament.util.customgui.CoordRememberingSlot; +import net.minecraft.screen.slot.Slot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(Slot.class) +public class OriginalSlotCoords implements CoordRememberingSlot { + + @Shadow + public int x; + @Shadow + public int y; + @Unique + public int originalX; + @Unique + public int originalY; + + @Override + public void rememberCoords_firmament() { + this.originalX = this.x; + this.originalY = this.y; + } + + @Override + public void restoreCoords_firmament() { + this.x = this.originalX; + this.y = this.originalY; + } + + @Override + public int getOriginalX_firmament() { + return originalX; + } + + @Override + public int getOriginalY_firmament() { + return originalY; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java new file mode 100644 index 0000000..6e1090a --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/customgui/PatchHandledScreen.java @@ -0,0 +1,212 @@ + +package moe.nea.firmament.mixins.customgui; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.HandledScreenKeyReleasedEvent; +import moe.nea.firmament.util.customgui.CoordRememberingSlot; +import moe.nea.firmament.util.customgui.CustomGui; +import moe.nea.firmament.util.customgui.HasCustomGui; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(HandledScreen.class) +public class PatchHandledScreen extends Screen implements HasCustomGui { + @Shadow + @Final + protected T handler; + @Shadow + protected int x; + @Shadow + protected int y; + @Shadow + protected int backgroundHeight; + @Shadow + protected int backgroundWidth; + @Unique + public CustomGui override; + @Unique + public boolean hasRememberedSlots = false; + @Unique + private int originalBackgroundWidth; + @Unique + private int originalBackgroundHeight; + + protected PatchHandledScreen(Text title) { + super(title); + } + + @Nullable + @Override + public CustomGui getCustomGui_Firmament() { + return override; + } + + @Override + public void setCustomGui_Firmament(@Nullable CustomGui gui) { + if (this.override != null) { + backgroundHeight = originalBackgroundHeight; + backgroundWidth = originalBackgroundWidth; + } + if (gui != null) { + originalBackgroundHeight = backgroundHeight; + originalBackgroundWidth = backgroundWidth; + } + this.override = gui; + } + + public boolean mouseScrolled_firmament(double mouseX, double mouseY, double horizontalAmount, double verticalAmount) { + return override != null && override.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount); + } + + public boolean keyReleased_firmament(int keyCode, int scanCode, int modifiers) { + if (HandledScreenKeyReleasedEvent.Companion.publish(new HandledScreenKeyReleasedEvent((HandledScreen) (Object) this, keyCode, scanCode, modifiers)).getCancelled()) + return true; + return override != null && override.keyReleased(keyCode, scanCode, modifiers); + } + + public boolean charTyped_firmament(char chr, int modifiers) { + return override != null && override.charTyped(chr, modifiers); + } + + @Inject(method = "init", at = @At("TAIL")) + private void onInit(CallbackInfo ci) { + if (override != null) { + override.onInit(); + } + } + + @Inject(method = "drawForeground", at = @At("HEAD"), cancellable = true) + private void onDrawForeground(DrawContext context, int mouseX, int mouseY, CallbackInfo ci) { + if (override != null && !override.shouldDrawForeground()) + ci.cancel(); + } + + + @WrapOperation( + method = "drawSlots", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawSlot(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/screen/slot/Slot;)V")) + private void beforeSlotRender(HandledScreen instance, DrawContext context, Slot slot, Operation original) { + if (override != null) { + override.beforeSlotRender(context, slot); + } + original.call(instance, context, slot); + if (override != null) { + override.afterSlotRender(context, slot); + } + } + + @Inject(method = "isClickOutsideBounds", at = @At("HEAD"), cancellable = true) + public void onIsClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable cir) { + if (override != null) { + cir.setReturnValue(override.isClickOutsideBounds(mouseX, mouseY)); + } + } + + @Inject(method = "isPointWithinBounds", at = @At("HEAD"), cancellable = true) + public void onIsPointWithinBounds(int x, int y, int width, int height, double pointX, double pointY, CallbackInfoReturnable cir) { + if (override != null) { + cir.setReturnValue(override.isPointWithinBounds(x + this.x, y + this.y, width, height, pointX, pointY)); + } + } + + @Inject(method = "isPointOverSlot", at = @At("HEAD"), cancellable = true) + public void onIsPointOverSlot(Slot slot, double pointX, double pointY, CallbackInfoReturnable cir) { + if (override != null) { + cir.setReturnValue(override.isPointOverSlot(slot, this.x, this.y, pointX, pointY)); + } + } + + @Inject(method = "render", at = @At("HEAD")) + public void moveSlots(DrawContext context, int mouseX, int mouseY, float delta, CallbackInfo ci) { + if (override != null) { + for (Slot slot : handler.slots) { + if (!hasRememberedSlots) { + ((CoordRememberingSlot) slot).rememberCoords_firmament(); + } + override.moveSlot(slot); + } + hasRememberedSlots = true; + } else { + if (hasRememberedSlots) { + for (Slot slot : handler.slots) { + ((CoordRememberingSlot) slot).restoreCoords_firmament(); + } + hasRememberedSlots = false; + } + } + } + + @Inject(at = @At("HEAD"), method = "close", cancellable = true) + private void onVoluntaryExit(CallbackInfo ci) { + if (override != null) { + if (!override.onVoluntaryExit()) + ci.cancel(); + } + } + + @WrapWithCondition(method = "renderBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;drawBackground(Lnet/minecraft/client/gui/DrawContext;FII)V")) + public boolean preventDrawingBackground(HandledScreen instance, DrawContext drawContext, float delta, int mouseX, int mouseY) { + if (override != null) { + override.render(drawContext, delta, mouseX, mouseY); + } + return override == null; + } + + @WrapOperation( + method = "mouseClicked", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/Screen;mouseClicked(DDI)Z")) + public boolean overrideMouseClicks(HandledScreen instance, double mouseX, double mouseY, int button, + Operation original) { + if (override != null) { + if (override.mouseClick(mouseX, mouseY, button)) + return true; + } + return original.call(instance, mouseX, mouseY, button); + } + + @Inject(method = "mouseDragged", at = @At("HEAD"), cancellable = true) + public void overrideMouseDrags(double mouseX, double mouseY, int button, double deltaX, double deltaY, CallbackInfoReturnable cir) { + if (override != null) { + if (override.mouseDragged(mouseX, mouseY, button, deltaX, deltaY)) + cir.setReturnValue(true); + } + } + + @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) + private void overrideKeyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable cir) { + if (override != null) { + if (override.keyPressed(keyCode, scanCode, modifiers)) { + cir.setReturnValue(true); + } + } + } + + + @Inject( + method = "mouseReleased", + at = @At("HEAD"), cancellable = true) + public void overrideMouseReleases(double mouseX, double mouseY, int button, CallbackInfoReturnable cir) { + if (override != null) { + if (override.mouseReleased(mouseX, mouseY, button)) + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java b/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java new file mode 100644 index 0000000..a15d825 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/DisableCommonPacketWarnings.java @@ -0,0 +1,42 @@ + + +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.CustomPayload; +import net.minecraft.util.Identifier; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Objects; + +@Mixin(ClientPlayNetworkHandler.class) +public class DisableCommonPacketWarnings { + + @Inject(method = "warnOnUnknownPayload", at = @At("HEAD"), cancellable = true) + public void onCustomPacketError(CustomPayload customPayload, CallbackInfo ci) { + if (Objects.equals(customPayload.getId(), Identifier.of("badlion", "mods"))) { + ci.cancel(); + } + } + + @Redirect(method = "onEntityPassengersSet", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;)V", remap = false)) + public void onUnknownPassenger(Logger instance, String s) { + // Ignore passenger data for unknown entities, since HyPixel just sends a lot of those. + } + + @Redirect(method = "onTeam", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;[Ljava/lang/Object;)V", remap = false)) + public void onOnTeam(Logger instance, String s, Object[] objects) { + // Ignore data for unknown teams, since HyPixel just sends a lot of invalid team data. + } + + @Redirect(method = "onPlayerList", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false)) + public void onOnPlayerList(Logger instance, String s, Object o, Object o2) { + // Ignore invalid player info, since HyPixel just sends a lot of invalid player info + } + +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java b/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java new file mode 100644 index 0000000..689a757 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/DisableInvalidFishingHook.java @@ -0,0 +1,17 @@ + + +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.entity.projectile.FishingBobberEntity; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(FishingBobberEntity.class) +public class DisableInvalidFishingHook { + @Redirect(method = "onSpawnPacket", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)V", remap = false)) + public void onOnSpawnPacket(Logger instance, String s, Object o, Object o1) { + // Don't warn for broken fishing hooks, since HyPixel sends a bunch of those + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java new file mode 100644 index 0000000..ef8c9eb --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/EarlyInstantiateTranslations.java @@ -0,0 +1,19 @@ +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.text.TranslatableTextContent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(TranslatableTextContent.class) +public abstract class EarlyInstantiateTranslations { + @Shadow + protected abstract void updateTranslations(); + + @Inject(method = "", at = @At("TAIL")) + private void onInit(String key, String fallback, Object[] args, CallbackInfo ci) { + updateTranslations(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java new file mode 100644 index 0000000..6620b47 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyCloser.java @@ -0,0 +1,16 @@ + +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.client.util.Window; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Window.class) +public class IdentifyCloser { + @Inject(method = "close", at = @At("HEAD")) + public void onClose(CallbackInfo ci) { + Thread.dumpStack(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java new file mode 100644 index 0000000..fac0688 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/IdentifyStopperPatch.java @@ -0,0 +1,16 @@ + +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MinecraftClient.class) +public class IdentifyStopperPatch { + @Inject(method = "scheduleStop", at = @At("HEAD")) + private void onStop(CallbackInfo ci) { + Thread.dumpStack(); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java b/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java new file mode 100644 index 0000000..d7b6cc3 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/MixinKeyboard.java @@ -0,0 +1,20 @@ + + +package moe.nea.firmament.mixins.devenv; + +import moe.nea.firmament.features.debug.DeveloperFeatures; +import net.minecraft.client.Keyboard; +import net.minecraft.client.MinecraftClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +import java.util.concurrent.CompletableFuture; + +@Mixin(Keyboard.class) +public class MixinKeyboard { + @Redirect(method = "processF3", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;reloadResources()Ljava/util/concurrent/CompletableFuture;")) + public CompletableFuture redirectReloadResources(MinecraftClient instance) { + return DeveloperFeatures.hookOnBeforeResourceReload(instance); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java b/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java new file mode 100644 index 0000000..34a733c --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/MixinScoreboard.java @@ -0,0 +1,17 @@ + + +package moe.nea.firmament.mixins.devenv; + +import net.minecraft.scoreboard.Scoreboard; +import org.slf4j.Logger; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(Scoreboard.class) +public class MixinScoreboard { + @Redirect(method = "addTeam", at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;warn(Ljava/lang/String;Ljava/lang/Object;)V", remap = false)) + public void onExistingteam(Logger instance, String s, Object o) { + // Ignore creations of existing teams + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java b/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java new file mode 100644 index 0000000..6d44e29 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/WarnForUnknownCustomPayloadSends.java @@ -0,0 +1,18 @@ + +package moe.nea.firmament.mixins.devenv; + +import moe.nea.firmament.Firmament; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.network.packet.UnknownCustomPayload; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(UnknownCustomPayload.class) +public class WarnForUnknownCustomPayloadSends { + @Inject(method = "method_56493", at = @At("HEAD")) + private static void warn(UnknownCustomPayload value, PacketByteBuf buf, CallbackInfo ci) { + Firmament.INSTANCE.getLogger().warn("Unknown custom payload is being sent: {}", value); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java new file mode 100644 index 0000000..33840c1 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/devenv/WarnOnMissingTranslations.java @@ -0,0 +1,38 @@ +package moe.nea.firmament.mixins.devenv; + +import moe.nea.firmament.features.debug.DeveloperFeatures; +import moe.nea.firmament.util.MC; +import net.minecraft.client.resource.language.TranslationStorage; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Set; +import java.util.TreeSet; + +@Mixin(TranslationStorage.class) +public abstract class WarnOnMissingTranslations { + @Shadow + public abstract boolean hasTranslation(String key); + + @Unique + private final Set missingTranslations = new TreeSet<>(); + + @Inject(method = "get", at = @At("HEAD")) + private void onGetTranslationKey(String key, String fallback, CallbackInfoReturnable cir) { + warnForMissingTranslation(key); + } + + @Unique + private void warnForMissingTranslation(String key) { + if (!key.contains("firmament")) return; + if (hasTranslation(key)) return; + if (!missingTranslations.add(key)) return; + MC.INSTANCE.sendChat(Text.literal("Missing firmament translation: " + key)); + DeveloperFeatures.hookMissingTranslations(missingTranslations); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java b/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java new file mode 100644 index 0000000..0abed22 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/feature/DisableSlotHighlights.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.mixins.feature; + +import moe.nea.firmament.features.fixes.Fixes; +import net.minecraft.component.DataComponentTypes; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.slot.Slot; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(Slot.class) +public abstract class DisableSlotHighlights { + @Shadow + public abstract ItemStack getStack(); + + @Inject(method = "canBeHighlighted", at = @At("HEAD"), cancellable = true) + private void dontHighlight(CallbackInfoReturnable cir) { + if (!Fixes.TConfig.INSTANCE.getHideSlotHighlights()) return; + var display = getStack().get(DataComponentTypes.TOOLTIP_DISPLAY); + if (display != null && display.hideTooltip()) + cir.setReturnValue(false); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java new file mode 100644 index 0000000..5a92f89 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeFeatureRenderer.java @@ -0,0 +1,43 @@ +package moe.nea.firmament.mixins.feature.devcosmetics; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import kotlin.Unit; +import moe.nea.firmament.features.misc.CustomCapes; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.feature.CapeFeatureRenderer; +import net.minecraft.client.render.entity.feature.FeatureRenderer; +import net.minecraft.client.render.entity.feature.FeatureRendererContext; +import net.minecraft.client.render.entity.model.BipedEntityModel; +import net.minecraft.client.render.entity.model.PlayerEntityModel; +import net.minecraft.client.render.entity.state.PlayerEntityRenderState; +import net.minecraft.client.util.SkinTextures; +import net.minecraft.client.util.math.MatrixStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(CapeFeatureRenderer.class) +public abstract class CustomCapeFeatureRenderer extends FeatureRenderer { + public CustomCapeFeatureRenderer(FeatureRendererContext context) { + super(context); + } + + @WrapOperation( + method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/PlayerEntityRenderState;FF)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/model/BipedEntityModel;render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumer;II)V") + ) + private void onRender(BipedEntityModel instance, MatrixStack matrixStack, VertexConsumer vertexConsumer, int light, int overlay, Operation original, @Local PlayerEntityRenderState playerEntityRenderState, @Local SkinTextures skinTextures, @Local VertexConsumerProvider vertexConsumerProvider) { + CustomCapes.render( + playerEntityRenderState, + vertexConsumer, + RenderLayer.getEntitySolid(skinTextures.capeTexture()), + vertexConsumerProvider, + updatedConsumer -> { + original.call(instance, matrixStack, updatedConsumer, light, overlay); + return Unit.INSTANCE; + }); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java new file mode 100644 index 0000000..428d7ec --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/CustomCapeStorage.java @@ -0,0 +1,23 @@ +package moe.nea.firmament.mixins.feature.devcosmetics; + +import moe.nea.firmament.features.misc.CustomCapes; +import net.minecraft.client.render.entity.state.PlayerEntityRenderState; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(PlayerEntityRenderState.class) +public class CustomCapeStorage implements CustomCapes.CapeStorage { + @Unique + CustomCapes.CustomCape customCape; + + @Override + public CustomCapes.@Nullable CustomCape getCape_firmament() { + return customCape; + } + + @Override + public void setCape_firmament(CustomCapes.@Nullable CustomCape customCape) { + this.customCape = customCape; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/SaveCapeToPlayerEntityRenderState.java b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/SaveCapeToPlayerEntityRenderState.java new file mode 100644 index 0000000..ae9c743 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/feature/devcosmetics/SaveCapeToPlayerEntityRenderState.java @@ -0,0 +1,19 @@ +package moe.nea.firmament.mixins.feature.devcosmetics; + +import moe.nea.firmament.features.misc.CustomCapes; +import net.minecraft.client.network.AbstractClientPlayerEntity; +import net.minecraft.client.render.entity.PlayerEntityRenderer; +import net.minecraft.client.render.entity.state.PlayerEntityRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(PlayerEntityRenderer.class) +public class SaveCapeToPlayerEntityRenderState { + @Inject(method = "updateRenderState(Lnet/minecraft/client/network/AbstractClientPlayerEntity;Lnet/minecraft/client/render/entity/state/PlayerEntityRenderState;F)V", + at = @At("TAIL")) + private void addCustomCape(AbstractClientPlayerEntity abstractClientPlayerEntity, PlayerEntityRenderState playerEntityRenderState, float f, CallbackInfo ci) { + CustomCapes.addCapeData(abstractClientPlayerEntity, playerEntityRenderState); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java new file mode 100644 index 0000000..2b96e5c --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ChangeColorOfLivingEntities.java @@ -0,0 +1,62 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.client.render.entity.state.LivingEntityRenderState; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.LivingEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyArg; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Applies various rendering modifications from {@link EntityRenderTintEvent} + */ +@Mixin(LivingEntityRenderer.class) +public class ChangeColorOfLivingEntities> { + @ModifyReturnValue(method = "getMixColor", at = @At("RETURN")) + private int changeColor(int original, @Local(argsOnly = true) S state) { + var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state); + if (tintState.getHasTintOverride_firmament()) + return tintState.getTint_firmament(); + return original; + } + + @ModifyArg( + method = "getOverlay", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/OverlayTexture;getU(F)I"), + allow = 1 + ) + private static float modifyLightOverlay(float originalWhiteOffset, @Local(argsOnly = true) LivingEntityRenderState state) { + var tintState = EntityRenderTintEvent.HasTintRenderState.cast(state); + if (tintState.getHasTintOverride_firmament() || tintState.getOverlayTexture_firmament() != null) { + return 1F; // TODO: add interpolation percentage to render state extension + } + return originalWhiteOffset; + } + + @Inject(method = "render(Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;pop()V")) + private void afterRender(S livingEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) { + var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState); + var overlayTexture = tintState.getOverlayTexture_firmament(); + if (overlayTexture != null && vertexConsumerProvider instanceof VertexConsumerProvider.Immediate imm) { + imm.drawCurrentLayer(); + } + EntityRenderTintEvent.overlayOverride = null; + } + + @Inject(method = "render(Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/util/math/MatrixStack;push()V")) + private void beforeRender(S livingEntityRenderState, MatrixStack matrixStack, VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo ci) { + var tintState = EntityRenderTintEvent.HasTintRenderState.cast(livingEntityRenderState); + var overlayTexture = tintState.getOverlayTexture_firmament(); + if (overlayTexture != null) { + EntityRenderTintEvent.overlayOverride = overlayTexture; + } + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java new file mode 100644 index 0000000..1019027 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/EntityRenderStateTint.java @@ -0,0 +1,55 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import moe.nea.firmament.events.EntityRenderTintEvent; +import moe.nea.firmament.util.render.TintedOverlayTexture; +import net.minecraft.client.render.entity.state.EntityRenderState; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(EntityRenderState.class) +public class EntityRenderStateTint implements EntityRenderTintEvent.HasTintRenderState { + @Unique + int tint = -1; + @Unique + TintedOverlayTexture overlayTexture; + @Unique + boolean hasTintOverride = false; + + @Override + public int getTint_firmament() { + return tint; + } + + @Override + public void setTint_firmament(int i) { + tint = i; + hasTintOverride = true; + } + + @Override + public boolean getHasTintOverride_firmament() { + return hasTintOverride; + } + + @Override + public void setHasTintOverride_firmament(boolean b) { + hasTintOverride = b; + } + + @Override + public void reset_firmament() { + hasTintOverride = false; + overlayTexture = null; + } + + @Override + public @Nullable TintedOverlayTexture getOverlayTexture_firmament() { + return overlayTexture; + } + + @Override + public void setOverlayTexture_firmament(@Nullable TintedOverlayTexture tintedOverlayTexture) { + this.overlayTexture = tintedOverlayTexture; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java new file mode 100644 index 0000000..7938340 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/InjectIntoRenderState.java @@ -0,0 +1,30 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.entity.EntityRenderer; +import net.minecraft.client.render.entity.state.EntityRenderState; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * Dispatches {@link EntityRenderTintEvent} to collect additional render state used by {@link ChangeColorOfLivingEntities} + */ +@Mixin(EntityRenderer.class) +public class InjectIntoRenderState { + + @Inject( + method = "updateRenderState", + at = @At("RETURN")) + private void onUpdateRenderState(T entity, S state, float tickDelta, CallbackInfo ci) { + var renderState = EntityRenderTintEvent.HasTintRenderState.cast(state); + renderState.reset_firmament(); + var tintEvent = new EntityRenderTintEvent( + entity, + renderState + ); + EntityRenderTintEvent.Companion.publish(tintEvent); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java new file mode 100644 index 0000000..61e5c65 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/ReplaceOverlayTexture.java @@ -0,0 +1,24 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +/** + * Replaces the overlay texture used by rendering with the override specified in {@link EntityRenderTintEvent#overlayOverride} + */ +@Mixin(RenderLayer.Overlay.class) +public class ReplaceOverlayTexture { + @ModifyExpressionValue( + method = {"method_23555", "method_23556"}, + expect = 2, + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;getOverlayTexture()Lnet/minecraft/client/render/OverlayTexture;")) + private static OverlayTexture replaceOverlayTexture(OverlayTexture original) { + if (EntityRenderTintEvent.overlayOverride != null) + return EntityRenderTintEvent.overlayOverride; + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java new file mode 100644 index 0000000..d9c174c --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableEquipmentRenderer.java @@ -0,0 +1,34 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.entity.equipment.EquipmentRenderer; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +/** + * Patch to make {@link EquipmentRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified. + */ +@Mixin(EquipmentRenderer.class) +public class UseOverlayableEquipmentRenderer { + @WrapOperation(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderLayer;getArmorCutoutNoCull(Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;")) + private RenderLayer replace(Identifier texture, Operation original) { + if (EntityRenderTintEvent.overlayOverride != null) + return RenderLayer.getEntityTranslucent(texture); + return original.call(texture); + } + + @ModifyExpressionValue(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I")) + private int replaceUvIndex(int original) { + if (EntityRenderTintEvent.overlayOverride != null) + return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java new file mode 100644 index 0000000..07bc5cf --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableHeadFeatureRenderer.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.entity.feature.HeadFeatureRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +/** + * Patch to make {@link HeadFeatureRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified. + * @see UseOverlayableItemRenderer + */ +@Mixin(HeadFeatureRenderer.class) +public class UseOverlayableHeadFeatureRenderer { + + @ModifyExpressionValue(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/LivingEntityRenderState;FF)V", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I")) + private int replaceUvIndex(int original) { + if (EntityRenderTintEvent.overlayOverride != null) + return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java new file mode 100644 index 0000000..620ab2c --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableItemRenderer.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderPhase; +import net.minecraft.client.render.item.ItemRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +/** + * Patch to make {@link ItemRenderState} use a {@link RenderLayer} that allows uses Minecraft's overlay texture. + * + * @see UseOverlayableHeadFeatureRenderer + */ +@Mixin(ItemRenderState.LayerRenderState.class) +public class UseOverlayableItemRenderer { + @ModifyExpressionValue(method = "render", at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/item/ItemRenderState$LayerRenderState;renderLayer:Lnet/minecraft/client/render/RenderLayer;")) + private RenderLayer replace(RenderLayer original) { + if (EntityRenderTintEvent.overlayOverride != null && original instanceof RenderLayer.MultiPhase multiPhase && multiPhase.phases.texture instanceof RenderPhase.Texture texture && texture.getId().isPresent()) + return RenderLayer.getEntityTranslucent(texture.getId().get()); + return original; + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java new file mode 100644 index 0000000..9905af1 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/render/entitytints/UseOverlayableSkullBlockEntityRenderer.java @@ -0,0 +1,25 @@ +package moe.nea.firmament.mixins.render.entitytints; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import moe.nea.firmament.events.EntityRenderTintEvent; +import net.minecraft.client.render.OverlayTexture; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +/** + * Patch to make {@link SkullBlockEntityRenderer} use a {@link RenderLayer} that allows uses Minecraft's overlay texture, if a {@link EntityRenderTintEvent#overlayOverride} is specified. + */ + +@Mixin(SkullBlockEntityRenderer.class) +public class UseOverlayableSkullBlockEntityRenderer { + @ModifyExpressionValue(method = "renderSkull", + at = @At(value = "FIELD", target = "Lnet/minecraft/client/render/OverlayTexture;DEFAULT_UV:I")) + private static int replaceUvIndex(int original) { + if (EntityRenderTintEvent.overlayOverride != null) + return OverlayTexture.packUv(15, 10); // TODO: store this info in a global alongside overlayOverride + return original; + } + +} diff --git a/src/main/kotlin/Compat.kt b/src/main/kotlin/Compat.kt new file mode 100644 index 0000000..ba3c88d --- /dev/null +++ b/src/main/kotlin/Compat.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament + +import moe.nea.firmament.util.compatloader.CompatMeta +import moe.nea.firmament.util.compatloader.ICompatMeta + +@CompatMeta +object Compat : ICompatMeta { + override fun shouldLoad(): Boolean { + return true + } +} diff --git a/src/main/kotlin/Firmament.kt b/src/main/kotlin/Firmament.kt new file mode 100644 index 0000000..b00546a --- /dev/null +++ b/src/main/kotlin/Firmament.kt @@ -0,0 +1,182 @@ +package moe.nea.firmament + +import com.google.gson.Gson +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.fabric.api.resource.ResourceManagerHelper +import net.fabricmc.fabric.api.resource.ResourcePackActivationType +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.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import kotlin.coroutines.EmptyCoroutineContext +import net.minecraft.command.CommandRegistryAccess +import net.minecraft.util.Identifier +import moe.nea.firmament.commands.registerFirmamentCommand +import moe.nea.firmament.events.ClientInitEvent +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 +import moe.nea.firmament.util.mc.InitLevel +import moe.nea.firmament.util.tr + +object Firmament { + val modContainer by lazy { FabricLoader.getInstance().getModContainer(MOD_ID).get() } + 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 } + + private val DEFAULT_JSON_INDENT = " " + + @OptIn(ExperimentalSerializationApi::class) + val json = Json { + prettyPrint = DEBUG + isLenient = true + allowTrailingComma = true + ignoreUnknownKeys = true + encodeDefaults = true + prettyPrintIndent = if (prettyPrint) "\t" else DEFAULT_JSON_INDENT + } + + /** + * FUCK two space indentation + */ + val twoSpaceJson = Json(from = json) { + prettyPrint = true + prettyPrintIndent = " " + } + val gson = Gson() + val tightJson = Json(from = json) { + prettyPrint = false + // Reset pretty print indent back to default to prevent getting yelled at by json + prettyPrintIndent = DEFAULT_JSON_INDENT + encodeDefaults = false + explicitNulls = false + } + + + 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, + @Suppress("UNUSED_PARAMETER") + ctx: CommandRegistryAccess + ) { + registerFirmamentCommand(dispatcher) + CommandEvent.publish(CommandEvent(dispatcher, ctx, MC.networkHandler?.commandDispatcher)) + } + + @JvmStatic + fun onInitialize() { + } + + @JvmStatic + fun onClientInitialize() { + InitLevel.bump(InitLevel.MC_INIT) + FeatureManager.subscribeEvents() + ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { instance -> + TickEvent.publish(TickEvent(MC.currentTick++)) + }) + 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)) + }) + }) + ClientInitEvent.publish(ClientInitEvent()) + ResourceManagerHelper.registerBuiltinResourcePack( + identifier("transparent_overlay"), + modContainer, + tr("firmament.resourcepack.transparentoverlay", "Transparent Firmament Overlay"), + ResourcePackActivationType.NORMAL + ) + } + + + fun identifier(path: String) = Identifier.of(MOD_ID, path) + inline fun tryDecodeJsonFromStream(inputStream: InputStream): Result { + return runCatching { + json.decodeFromStream(inputStream) + } + } +} diff --git a/src/main/kotlin/apis/Profiles.kt b/src/main/kotlin/apis/Profiles.kt new file mode 100644 index 0000000..a6c334b --- /dev/null +++ b/src/main/kotlin/apis/Profiles.kt @@ -0,0 +1,194 @@ + + +@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 java.time.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 +) + +@Serializable +data class CollectionResponse( + val success: Boolean, + val collections: Map +) + +@Serializable +data class CollectionInfo( + val name: String, + val maxTiers: Int, + val tiers: List +) + +@Serializable +data class CollectionTier( + val tier: Int, + val amountRequired: Long, + val unlocks: List, +) + + +@Serializable +data class Profiles( + val success: Boolean, + val profiles: List? +) + +@Serializable +data class Profile( + @SerialName("profile_id") + val profileId: UUID, + @SerialName("cute_name") + val cuteName: String, + val selected: Boolean = false, + val members: Map, +) + +enum class Skill(val accessor: KProperty1, 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 { + 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 = 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 = 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 = 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 MowojangNameLookup( + val name: String, + val id: UUID, +) diff --git a/src/main/kotlin/apis/Routes.kt b/src/main/kotlin/apis/Routes.kt new file mode 100644 index 0000000..5e29402 --- /dev/null +++ b/src/main/kotlin/apis/Routes.kt @@ -0,0 +1,95 @@ + + +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> = CaseInsensitiveMap() + private val profiles: MutableMap> = mutableMapOf() + private val accounts: MutableMap> = mutableMapOf() + private val UUIDToName: MutableMap> = mutableMapOf() + + suspend fun getPlayerNameForUUID(uuid: UUID): String? { + return withContext(MinecraftDispatcher) { + UUIDToName.computeIfAbsent(uuid) { + async(Firmament.coroutineScope.coroutineContext) { + val response = Firmament.httpClient.get("https://mowojang.matdoes.dev/$uuid") + if (!response.status.isSuccess()) return@async null + val data = response.body() + launch(MinecraftDispatcher) { + nameToUUID[data.name] = async { data.id } + } + data.name + } + } + }.await() + } + + suspend fun getUUIDForPlayerName(name: String): UUID? { + return withContext(MinecraftDispatcher) { + nameToUUID.computeIfAbsent(name) { + async(Firmament.coroutineScope.coroutineContext) { + val response = Firmament.httpClient.get("https://mowojang.matdoes.dev/$name") + if (!response.status.isSuccess()) return@async null + val data = response.body() + launch(MinecraftDispatcher) { + UUIDToName[data.id] = async { data.name } + } + data.id + } + } + }.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().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() + } + } + }.await() + } + +} diff --git a/src/main/kotlin/apis/UrsaManager.kt b/src/main/kotlin/apis/UrsaManager.kt new file mode 100644 index 0000000..13f7aef --- /dev/null +++ b/src/main/kotlin/apis/UrsaManager.kt @@ -0,0 +1,72 @@ + + +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): 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/commands/CaseInsensitiveLiteralCommandNode.kt b/src/main/kotlin/commands/CaseInsensitiveLiteralCommandNode.kt new file mode 100644 index 0000000..10772b0 --- /dev/null +++ b/src/main/kotlin/commands/CaseInsensitiveLiteralCommandNode.kt @@ -0,0 +1,75 @@ + + +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( + literal: String, command: Command?, requirement: Predicate?, + redirect: CommandNode?, modifier: RedirectModifier?, forks: Boolean +) : LiteralCommandNode( + literal.lowercase(), command, requirement, redirect, modifier, forks +) { + class Builder(literal: String) : LiteralArgumentBuilder(literal) { + override fun build(): LiteralCommandNode { + val result = CaseInsensitiveLiteralCommandNode( + literal, + command, requirement, redirect, redirectModifier, isFork + ) + for (argument in arguments) { + result.addChild(argument) + } + return result + } + } + + override fun createBuilder(): LiteralArgumentBuilder { + return Builder(literal).also { + it.requires(requirement) + it.forward(redirect, redirectModifier, isFork) + if (command != null) + it.executes(command) + } + } + + override fun parse(reader: StringReader, contextBuilder: CommandContextBuilder) { + 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 "" + } + + 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/commands/Duration.kt b/src/main/kotlin/commands/Duration.kt new file mode 100644 index 0000000..42f143d --- /dev/null +++ b/src/main/kotlin/commands/Duration.kt @@ -0,0 +1,75 @@ +package moe.nea.firmament.commands + +import com.mojang.brigadier.StringReader +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.context.CommandContext +import com.mojang.brigadier.exceptions.DynamicCommandExceptionType +import com.mojang.brigadier.suggestion.Suggestions +import com.mojang.brigadier.suggestion.SuggestionsBuilder +import java.util.concurrent.CompletableFuture +import java.util.function.Function +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import kotlin.time.DurationUnit +import kotlin.time.toDuration +import moe.nea.firmament.util.tr + +object DurationArgumentType : ArgumentType { + val unknownTimeCode = DynamicCommandExceptionType { timeCode -> + tr("firmament.command-argument.duration.error", + "Unknown time code '$timeCode'") + } + + override fun parse(reader: StringReader): Duration { + val start = reader.cursor + val string = reader.readUnquotedString() + val matcher = regex.matcher(string) + var s = 0 + var time = 0.seconds + fun createError(till: Int) { + throw unknownTimeCode.createWithContext( + reader.also { it.cursor = start + s }, + string.substring(s, till)) + } + + while (matcher.find()) { + if (matcher.start() != s) { + createError(matcher.start()) + } + s = matcher.end() + val amount = matcher.group("count").toDouble() + val what = timeSuffixes[matcher.group("what").single()]!! + time += amount.toDuration(what) + } + if (string.length != s) { + createError(string.length) + } + return time + } + + + override fun listSuggestions( + context: CommandContext, + builder: SuggestionsBuilder + ): CompletableFuture { + val remaining = builder.remainingLowerCase.substringBefore(' ') + if (remaining.isEmpty()) return super.listSuggestions(context, builder) + if (remaining.last().isDigit()) { + for (timeSuffix in timeSuffixes.keys) { + builder.suggest(remaining + timeSuffix) + } + } + return builder.buildFuture() + } + + val timeSuffixes = mapOf( + 'm' to DurationUnit.MINUTES, + 's' to DurationUnit.SECONDS, + 'h' to DurationUnit.HOURS, + ) + val regex = "(?[0-9]+)(?[${timeSuffixes.keys.joinToString("")}])".toPattern() + + override fun getExamples(): Collection { + return listOf("3m", "20s", "1h45m") + } +} diff --git a/src/main/kotlin/commands/RestArgumentType.kt b/src/main/kotlin/commands/RestArgumentType.kt new file mode 100644 index 0000000..361907f --- /dev/null +++ b/src/main/kotlin/commands/RestArgumentType.kt @@ -0,0 +1,15 @@ + + +package moe.nea.firmament.commands + +import com.mojang.brigadier.StringReader +import com.mojang.brigadier.arguments.ArgumentType + +object RestArgumentType : ArgumentType { + override fun parse(reader: StringReader): String { + val remaining = reader.remaining + reader.cursor += remaining.length + return remaining + } + +} diff --git a/src/main/kotlin/commands/dsl.kt b/src/main/kotlin/commands/dsl.kt new file mode 100644 index 0000000..d1f0d8c --- /dev/null +++ b/src/main/kotlin/commands/dsl.kt @@ -0,0 +1,118 @@ + + +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.context get() = this +operator fun > C.get(arg: TypeSafeArg): T { + return arg.get(this) +} + +fun literal( + name: String, + block: CaseInsensitiveLiteralCommandNode.Builder.() -> Unit +): CaseInsensitiveLiteralCommandNode.Builder = + CaseInsensitiveLiteralCommandNode.Builder(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(val name: String, val argument: ArgumentType) { + val argClass by lazy { + argument.javaClass + .iterate>> { + it.superclass + } + .flatMap { + it.genericInterfaces.toList() + } + .filterIsInstance() + .find { it.rawType == ArgumentType::class.java }!! + .let { normalizeGeneric(it.actualTypeArguments[0]) } + } + + @JvmName("getWithThis") + fun CommandContext.get(): T = + get(this) + + + fun get(ctx: CommandContext): T { + try { + return ctx.getArgument(name, argClass) as T + } catch (e: Exception) { + if (ctx.child != null) { + return get(ctx.child) + } + throw e + } + } +} + + +fun argument( + name: String, + argument: ArgumentType, + block: RequiredArgumentBuilder.(TypeSafeArg) -> Unit +): RequiredArgumentBuilder = + RequiredArgumentBuilder.argument(name, argument).also { block(it, TypeSafeArg(name, argument)) } + +fun , AT : Any> T.thenArgument( + name: String, + argument: ArgumentType, + block: RequiredArgumentBuilder.(TypeSafeArg) -> Unit +): T = then(argument(name, argument, block)) + +fun > T.suggestsList(provider: CommandContext.() -> Iterable) { + suggests(SuggestionProvider { context, builder -> + provider(context) + .asSequence() + .filter { it.startsWith(builder.remaining, ignoreCase = true) } + .forEach { + builder.suggest(it) + } + builder.buildFuture() + }) +} + +fun > T.thenLiteral( + name: String, + block: CaseInsensitiveLiteralCommandNode.Builder.() -> Unit +): T = + then(literal(name, block)) + +fun > T.then(node: ArgumentBuilder, block: T.() -> Unit): T = + then(node).also(block) + +fun > T.thenExecute(block: suspend CommandContext.() -> Unit): T = + executes { + Firmament.coroutineScope.launch(MinecraftDispatcher) { + block(it) + } + 1 + } + + diff --git a/src/main/kotlin/commands/rome.kt b/src/main/kotlin/commands/rome.kt new file mode 100644 index 0000000..f808231 --- /dev/null +++ b/src/main/kotlin/commands/rome.kt @@ -0,0 +1,376 @@ +package moe.nea.firmament.commands + +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.arguments.IntegerArgumentType +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.nbt.NbtOps +import net.minecraft.text.Text +import net.minecraft.text.TextCodecs +import moe.nea.firmament.apis.UrsaManager +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.FirmamentEventBus +import moe.nea.firmament.features.debug.DebugLogger +import moe.nea.firmament.features.debug.DeveloperFeatures +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.features.mining.MiningBlockInfoUi +import moe.nea.firmament.gui.config.AllConfigsGui +import moe.nea.firmament.gui.config.BooleanHandler +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.init.MixinPlugin +import moe.nea.firmament.repo.HypixelStaticData +import moe.nea.firmament.repo.ItemCache +import moe.nea.firmament.repo.RepoDownloadManager +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.FirmFormatters.debugPath +import moe.nea.firmament.util.FirmFormatters.formatBool +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.ScreenUtil +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.accessors.messages +import moe.nea.firmament.util.asBazaarStock +import moe.nea.firmament.util.collections.InstanceList +import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.mc.SNbtFormatter +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.unformattedString + + +fun firmamentCommand() = literal("firmament") { + thenLiteral("config") { + thenExecute { + AllConfigsGui.showAllGuis() + } + thenLiteral("toggle") { + thenArgument("config", string()) { config -> + suggestsList { + ManagedConfig.allManagedConfigs.getAll().asSequence().map { it.name }.asIterable() + } + thenArgument("property", string()) { property -> + suggestsList { + (ManagedConfig.allManagedConfigs.getAll().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 = ManagedConfig.allManagedConfigs.getAll().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 + 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("checkpr") { + thenArgument("prnum", IntegerArgumentType.integer(1)) { prnum -> + thenExecute { + val prnum = this[prnum] + source.sendFeedback(tr("firmament.repo.reload.pr", "Temporarily reloading repo from PR #${prnum}.")) + RepoManager.downloadOverridenBranch("refs/pull/$prnum/head") + } + } + } + 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.asBazaarStock] + 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(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { + thenLiteral("simulate") { + thenArgument("message", RestArgumentType) { message -> + thenExecute { + MC.instance.messageHandler.onGameMessage(Text.literal(get(message)), false) + } + } + } + thenLiteral("debuglog") { + thenLiteral("toggle") { + thenArgument("tag", string()) { tag -> + suggestsList { DebugLogger.allInstances.getAll().map { it.tag } + DebugLogger.EnabledLogs.data } + thenExecute { + val tagText = this[tag] + val enabled = DebugLogger.EnabledLogs.data + if (tagText in enabled) { + enabled.remove(tagText) + source.sendFeedback(Text.literal("Disabled $tagText debug logging")) + } else { + enabled.add(tagText) + source.sendFeedback(Text.literal("Enabled $tagText debug logging")) + } + } + } + } + } + thenLiteral("screens") { + thenExecute { + MC.sendChat(Text.literal(""" + |Screen: ${MC.screen} (${MC.screen?.title}) + |Screen Handler: ${MC.handledScreen?.screenHandler} ${MC.handledScreen?.screenHandler?.syncId} + |Player Screen Handler: ${MC.player?.currentScreenHandler} ${MC.player?.currentScreenHandler?.syncId} + """.trimMargin())) + } + } + thenLiteral("blocks") { + thenExecute { + ScreenUtil.setScreenLater(MiningBlockInfoUi.makeScreen()) + } + } + thenLiteral("dumpchat") { + thenExecute { + MC.inGameHud.chatHud.messages.forEach { + val nbt = TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it.content).orThrow + println(nbt) + } + } + thenArgument("search", string()) { search -> + thenExecute { + MC.inGameHud.chatHud.messages + .filter { this[search] in it.content.unformattedString } + .forEach { + val nbt = TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it.content).orThrow + println(SNbtFormatter.prettify(nbt)) + } + } + } + } + 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)) + source.sendFeedback(tr("firmament.sbinfo.custommining", + "Custom Mining: ${formatBool(locrawInfo.skyblockLocation?.hasCustomMining ?: false)}")) + } + } + } + thenLiteral("copyEntities") { + thenExecute { + val player = MC.player ?: return@thenExecute + player.world.getOtherEntities(player, player.boundingBox.expand(12.0)) + .forEach(PowerUserTools::showEntity) + PowerUserTools.showEntity(player) + } + } + 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)) + } + } + } + thenLiteral("events") { + thenExecute { + source.sendFeedback(tr("firmament.event.start", "Event Bus Readout:")) + FirmamentEventBus.allEventBuses.forEach { eventBus -> + val prefixName = eventBus.eventType.typeName.removePrefix("moe.nea.firmament") + source.sendFeedback(tr( + "firmament.event.bustype", + "- $prefixName:")) + eventBus.handlers.forEach { handler -> + source.sendFeedback(tr( + "firmament.event.handler", + " * ${handler.label}")) + } + } + } + } + thenLiteral("caches") { + thenExecute { + source.sendFeedback(Text.literal("Caches:")) + WeakCache.allInstances.getAll().forEach { + source.sendFeedback(Text.literal(" - ${it.name}: ${it.size}")) + } + source.sendFeedback(Text.translatable("Instance lists:")) + InstanceList.allInstances.getAll().forEach { + source.sendFeedback(Text.literal(" - ${it.name}: ${it.size}")) + } + } + } + thenLiteral("mixins") { + thenExecute { + MixinPlugin.instances.forEach { plugin -> + source.sendFeedback(tr("firmament.mixins.start.package", "Mixins (base ${plugin.mixinPackage}):")) + plugin.appliedMixins + .map { it.removePrefix(plugin.mixinPackage) } + .forEach { + source.sendFeedback(Text.literal(" - ").withColor(0xD020F0) + .append(Text.literal(it).withColor(0xF6BA20))) + } + } + } + } + thenLiteral("repo") { + thenExecute { + source.sendFeedback(tr("firmament.repo.info.ref", "Repo Upstream: ${RepoManager.getRepoRef()}")) + source.sendFeedback(tr("firmament.repo.info.downloadedref", + "Downloaded ref: ${RepoDownloadManager.latestSavedVersionHash}")) + source.sendFeedback(tr("firmament.repo.info.location", + "Saved location: ${debugPath(RepoDownloadManager.repoSavedLocation)}")) + source.sendFeedback(tr("firmament.repo.info.reloadstatus", + "Incomplete: ${ + formatBool(RepoManager.neuRepo.isIncomplete, + trueIsGood = false) + }, Unstable ${formatBool(RepoManager.neuRepo.isUnstable, trueIsGood = false)}")) + source.sendFeedback(tr("firmament.repo.info.items", + "Loaded items: ${RepoManager.neuRepo.items?.items?.size}")) + source.sendFeedback(tr("firmament.repo.info.itemcache", + "ItemCache flawless: ${formatBool(ItemCache.isFlawless)}")) + source.sendFeedback(tr("firmament.repo.info.itemdir", + "Items on disk: ${debugPath(RepoDownloadManager.repoSavedLocation.resolve("items"))}")) + } + } + } + thenExecute { + AllConfigsGui.showAllGuis() + } + CommandEvent.SubCommand.publish(CommandEvent.SubCommand(this@literal)) +} + + +fun registerFirmamentCommand(dispatcher: CommandDispatcher) { + val firmament = dispatcher.register(firmamentCommand()) + dispatcher.register(literal("firm") { + redirect(firmament) + }) +} + + + + diff --git a/src/main/kotlin/events/AllowChatEvent.kt b/src/main/kotlin/events/AllowChatEvent.kt new file mode 100644 index 0000000..3069843 --- /dev/null +++ b/src/main/kotlin/events/AllowChatEvent.kt @@ -0,0 +1,16 @@ + + +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() +} diff --git a/src/main/kotlin/events/AttackBlockEvent.kt b/src/main/kotlin/events/AttackBlockEvent.kt new file mode 100644 index 0000000..bbaa81d --- /dev/null +++ b/src/main/kotlin/events/AttackBlockEvent.kt @@ -0,0 +1,18 @@ + +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() +} diff --git a/src/main/kotlin/events/ChestInventoryUpdateEvent.kt b/src/main/kotlin/events/ChestInventoryUpdateEvent.kt new file mode 100644 index 0000000..ddf54fc --- /dev/null +++ b/src/main/kotlin/events/ChestInventoryUpdateEvent.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.events + +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.MC + +sealed class ChestInventoryUpdateEvent : FirmamentEvent() { + companion object : FirmamentEventBus() + data class Single(val slot: Int, val stack: ItemStack) : ChestInventoryUpdateEvent() + data class Multi(val contents: List) : ChestInventoryUpdateEvent() + val inventory = MC.screen +} diff --git a/src/main/kotlin/events/ClientInitEvent.kt b/src/main/kotlin/events/ClientInitEvent.kt new file mode 100644 index 0000000..7d13d65 --- /dev/null +++ b/src/main/kotlin/events/ClientInitEvent.kt @@ -0,0 +1,5 @@ +package moe.nea.firmament.events + +class ClientInitEvent : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/ClientStartedEvent.kt b/src/main/kotlin/events/ClientStartedEvent.kt new file mode 100644 index 0000000..637916d --- /dev/null +++ b/src/main/kotlin/events/ClientStartedEvent.kt @@ -0,0 +1,6 @@ + +package moe.nea.firmament.events + +class ClientStartedEvent : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/CommandEvent.kt b/src/main/kotlin/events/CommandEvent.kt new file mode 100644 index 0000000..cc9cf45 --- /dev/null +++ b/src/main/kotlin/events/CommandEvent.kt @@ -0,0 +1,45 @@ + + +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, + val ctx: CommandRegistryAccess, + val serverCommands: CommandDispatcher<*>?, +) : FirmamentEvent() { + companion object : FirmamentEventBus() + + /** + * 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, + ) : FirmamentEvent() { + companion object : FirmamentEventBus() + + fun subcommand(name: String, block: CaseInsensitiveLiteralCommandNode.Builder.() -> 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.() -> Unit + ): LiteralCommandNode { + return dispatcher.register(literal(name, block)) + } +} diff --git a/src/main/kotlin/events/CustomItemModelEvent.kt b/src/main/kotlin/events/CustomItemModelEvent.kt new file mode 100644 index 0000000..7b86980 --- /dev/null +++ b/src/main/kotlin/events/CustomItemModelEvent.kt @@ -0,0 +1,75 @@ +package moe.nea.firmament.events + +import java.util.Objects +import java.util.Optional +import kotlin.jvm.optionals.getOrNull +import net.minecraft.component.DataComponentTypes +import net.minecraft.item.ItemStack +import net.minecraft.util.Identifier +import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.collections.WeakCache.CacheFunction +import moe.nea.firmament.util.mc.IntrospectableItemModelManager + +// TODO: assert an order on these events +data class CustomItemModelEvent( + val itemStack: ItemStack, + val itemModelManager: IntrospectableItemModelManager, + var overrideModel: Identifier? = null, +) : FirmamentEvent() { + companion object : FirmamentEventBus() { + val weakCache = + object : WeakCache>("ItemModelIdentifier") { + override fun mkRef( + key: ItemStack, + extraData: IntrospectableItemModelManager + ): WeakCache>.Ref { + return IRef(key, extraData) + } + + inner class IRef(weakInstance: ItemStack, data: IntrospectableItemModelManager) : + Ref(weakInstance, data) { + override fun shouldBeEvicted(): Boolean = false + val isSimpleStack = weakInstance.componentChanges.isEmpty || (weakInstance.componentChanges.size() == 1 && weakInstance.get( + DataComponentTypes.CUSTOM_DATA)?.isEmpty == true) + val item = weakInstance.item + override fun hashCode(): Int { + if (isSimpleStack) + return Objects.hash(item, extraData) + return super.hashCode() + } + + override fun equals(other: Any?): Boolean { + if (other is IRef && isSimpleStack) { + return other.isSimpleStack && item == other.item + } + return super.equals(other) + } + } + } + val cache = CacheFunction.WithExtraData(weakCache, ::getModelIdentifier0) + + @JvmStatic + fun getModelIdentifier(itemStack: ItemStack?, itemModelManager: IntrospectableItemModelManager): Identifier? { + if (itemStack == null) return null + return cache.invoke(itemStack, itemModelManager).getOrNull() + } + + fun getModelIdentifier0( + itemStack: ItemStack, + itemModelManager: IntrospectableItemModelManager + ): Optional { + // TODO: add an error / warning if the model does not exist + return Optional.ofNullable(publish(CustomItemModelEvent(itemStack, itemModelManager)).overrideModel) + } + } + + fun overrideIfExists(overrideModel: Identifier) { + if (itemModelManager.hasModel_firmament(overrideModel)) + this.overrideModel = overrideModel + } + + fun overrideIfEmpty(identifier: Identifier) { + if (overrideModel == null) + overrideModel = identifier + } +} diff --git a/src/main/kotlin/events/DebugInstantiateEvent.kt b/src/main/kotlin/events/DebugInstantiateEvent.kt new file mode 100644 index 0000000..3470a8c --- /dev/null +++ b/src/main/kotlin/events/DebugInstantiateEvent.kt @@ -0,0 +1,9 @@ +package moe.nea.firmament.events + +/** + * Called in a devenv after minecraft has been initialized. This event should be used to force instantiation of lazy + * variables (and similar late init) to cause any possible issues to materialize. + */ +class DebugInstantiateEvent : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/EarlyResourceReloadEvent.kt b/src/main/kotlin/events/EarlyResourceReloadEvent.kt new file mode 100644 index 0000000..ec8377a --- /dev/null +++ b/src/main/kotlin/events/EarlyResourceReloadEvent.kt @@ -0,0 +1,10 @@ + +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() +} diff --git a/src/main/kotlin/events/EntityDespawnEvent.kt b/src/main/kotlin/events/EntityDespawnEvent.kt new file mode 100644 index 0000000..93dc477 --- /dev/null +++ b/src/main/kotlin/events/EntityDespawnEvent.kt @@ -0,0 +1,11 @@ + +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() +} diff --git a/src/main/kotlin/events/EntityInteractionEvent.kt b/src/main/kotlin/events/EntityInteractionEvent.kt new file mode 100644 index 0000000..123ea39 --- /dev/null +++ b/src/main/kotlin/events/EntityInteractionEvent.kt @@ -0,0 +1,29 @@ + +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() + 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/events/EntityRenderTintEvent.kt b/src/main/kotlin/events/EntityRenderTintEvent.kt new file mode 100644 index 0000000..29b888b --- /dev/null +++ b/src/main/kotlin/events/EntityRenderTintEvent.kt @@ -0,0 +1,66 @@ +package moe.nea.firmament.events + +import net.minecraft.client.render.GameRenderer +import net.minecraft.client.render.OverlayTexture +import net.minecraft.client.render.entity.state.EntityRenderState +import net.minecraft.entity.Entity +import net.minecraft.entity.LivingEntity +import moe.nea.firmament.util.render.TintedOverlayTexture + +/** + * Change the tint color of a [LivingEntity] + */ +class EntityRenderTintEvent( + val entity: Entity, + val renderState: HasTintRenderState +) : FirmamentEvent.Cancellable() { + init { + if (entity !is LivingEntity) { + cancel() + } + } + + companion object : FirmamentEventBus() { + /** + * Static variable containing an override for [GameRenderer.getOverlayTexture]. Should be only set briefly. + * + * This variable only affects render layers that naturally make use of the overlay texture, have proper overlay UVs set (`overlay u != 0`), and have a shader that makes use of the overlay (does not have the `NO_OVERLAY` flag set in its json definition). + * + * Currently supported layers: [net.minecraft.client.render.entity.equipment.EquipmentRenderer], [net.minecraft.client.render.entity.model.PlayerEntityModel], as well as some others naturally. + * + * @see moe.nea.firmament.mixins.render.entitytints.ReplaceOverlayTexture + * @see TintedOverlayTexture + */ + @JvmField + var overlayOverride: OverlayTexture? = null + } + + @Suppress("PropertyName", "FunctionName") + interface HasTintRenderState { + /** + * Multiplicative tint applied before the overlay. + */ + var tint_firmament: Int + + /** + * Must be set for [tint_firmament] to have any effect. + */ + var hasTintOverride_firmament: Boolean + + // TODO: allow for more specific selection of which layers get tinted + /** + * Specify a [TintedOverlayTexture] to be used. This does not apply to render layers not using the overlay texture. + * @see overlayOverride + */ + var overlayTexture_firmament: TintedOverlayTexture? + fun reset_firmament() + + companion object { + @JvmStatic + fun cast(state: EntityRenderState): HasTintRenderState { + return state as HasTintRenderState + } + } + } + +} diff --git a/src/main/kotlin/events/EntityUpdateEvent.kt b/src/main/kotlin/events/EntityUpdateEvent.kt new file mode 100644 index 0000000..fec2fa5 --- /dev/null +++ b/src/main/kotlin/events/EntityUpdateEvent.kt @@ -0,0 +1,60 @@ +package moe.nea.firmament.events + +import com.mojang.datafixers.util.Pair +import net.minecraft.entity.Entity +import net.minecraft.entity.EquipmentSlot +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.data.DataTracker +import net.minecraft.item.ItemStack +import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.util.MC + +/** + * 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() { + @Subscribe + fun onPlayerInventoryUpdate(event: PlayerInventoryUpdate) { + val p = MC.player ?: return + val updatedSlots = listOf( + EquipmentSlot.HEAD to 39, + EquipmentSlot.CHEST to 38, + EquipmentSlot.LEGS to 37, + EquipmentSlot.FEET to 36, + EquipmentSlot.OFFHAND to 40, + EquipmentSlot.MAINHAND to p.inventory.selectedSlot, // TODO: also equipment update when you swap your selected slot perhaps + ).mapNotNull { (slot, stackIndex) -> + val slotIndex = p.playerScreenHandler.getSlotIndex(p.inventory, stackIndex).asInt + event.getOrNull(slotIndex)?.let { + Pair.of(slot, it) + } + } + if (updatedSlots.isNotEmpty()) + publish(EquipmentUpdate(p, updatedSlots)) + } + } + + abstract val entity: Entity + + data class AttributeUpdate( + override val entity: LivingEntity, + val attributes: List, + ) : EntityUpdateEvent() + + data class TrackedDataUpdate( + override val entity: Entity, + val trackedValues: List>, + ) : EntityUpdateEvent() + + data class EquipmentUpdate( + override val entity: Entity, + val newEquipment: List>, + ) : EntityUpdateEvent() + +// TODO: onEntityPassengersSet, onEntityAttach?, onEntityStatusEffect +} diff --git a/src/main/kotlin/events/FeaturesInitializedEvent.kt b/src/main/kotlin/events/FeaturesInitializedEvent.kt new file mode 100644 index 0000000..ad2ad8a --- /dev/null +++ b/src/main/kotlin/events/FeaturesInitializedEvent.kt @@ -0,0 +1,8 @@ + +package moe.nea.firmament.events + +import moe.nea.firmament.features.FirmamentFeature + +data class FeaturesInitializedEvent(val features: List) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/FinalizeResourceManagerEvent.kt b/src/main/kotlin/events/FinalizeResourceManagerEvent.kt new file mode 100644 index 0000000..12167f8 --- /dev/null +++ b/src/main/kotlin/events/FinalizeResourceManagerEvent.kt @@ -0,0 +1,32 @@ +package moe.nea.firmament.events + +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import net.minecraft.resource.ReloadableResourceManagerImpl +import net.minecraft.resource.ResourceManager +import net.minecraft.resource.ResourceReloader + +data class FinalizeResourceManagerEvent( + val resourceManager: ReloadableResourceManagerImpl, +) : FirmamentEvent() { + companion object : FirmamentEventBus() + + inline fun registerOnApply(name: String, crossinline function: () -> Unit) { + resourceManager.registerReloader(object : ResourceReloader { + override fun reload( + synchronizer: ResourceReloader.Synchronizer, + manager: ResourceManager, + prepareExecutor: Executor, + applyExecutor: Executor + ): CompletableFuture { + return CompletableFuture.completedFuture(Unit) + .thenCompose(synchronizer::whenPrepared) + .thenAcceptAsync({ function() }, applyExecutor) + } + + override fun getName(): String { + return name + } + }) + } +} diff --git a/src/main/kotlin/events/FirmamentEvent.kt b/src/main/kotlin/events/FirmamentEvent.kt new file mode 100644 index 0000000..1a93ef5 --- /dev/null +++ b/src/main/kotlin/events/FirmamentEvent.kt @@ -0,0 +1,38 @@ + + +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() + * } + * ``` + */ +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/events/FirmamentEventBus.kt b/src/main/kotlin/events/FirmamentEventBus.kt new file mode 100644 index 0000000..af4e16a --- /dev/null +++ b/src/main/kotlin/events/FirmamentEventBus.kt @@ -0,0 +1,65 @@ +package moe.nea.firmament.events + +import java.util.concurrent.CopyOnWriteArrayList +import org.apache.commons.lang3.reflect.TypeUtils +import moe.nea.firmament.Firmament +import moe.nea.firmament.util.ErrorUtil +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 { + companion object { + val allEventBuses = mutableListOf>() + } + + val eventType = TypeUtils.getTypeArguments(javaClass, FirmamentEventBus::class.java)!!.values.single() + + init { + allEventBuses.add(this) + } + + data class Handler( + val invocation: (T) -> Unit, val receivesCancelled: Boolean, + var knownErrors: MutableSet> = mutableSetOf(), + val label: String, + ) + + private val toHandle: MutableList> = CopyOnWriteArrayList() + val handlers: List> get() = toHandle + + fun subscribe(label: String, handle: (T) -> Unit) { + subscribe(false, label, handle) + } + + fun subscribe(receivesCancelled: Boolean, label: String, handle: (T) -> Unit) { + toHandle.add(Handler(handle, receivesCancelled, label = label)) + } + + 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) + ErrorUtil.softError("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/events/HandledScreenClickEvent.kt b/src/main/kotlin/events/HandledScreenClickEvent.kt new file mode 100644 index 0000000..4c3003c --- /dev/null +++ b/src/main/kotlin/events/HandledScreenClickEvent.kt @@ -0,0 +1,10 @@ + + +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() +} diff --git a/src/main/kotlin/events/HandledScreenForegroundEvent.kt b/src/main/kotlin/events/HandledScreenForegroundEvent.kt new file mode 100644 index 0000000..f16d30e --- /dev/null +++ b/src/main/kotlin/events/HandledScreenForegroundEvent.kt @@ -0,0 +1,16 @@ + + +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() +} diff --git a/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt b/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt new file mode 100644 index 0000000..183ec71 --- /dev/null +++ b/src/main/kotlin/events/HandledScreenKeyPressedEvent.kt @@ -0,0 +1,38 @@ +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 + +sealed interface HandledScreenKeyEvent { + val screen: HandledScreen<*> + val keyCode: Int + val scanCode: Int + val modifiers: Int + + fun matches(keyBinding: KeyBinding): Boolean { + return matches(IKeyBinding.minecraft(keyBinding)) + } + + fun matches(keyBinding: IKeyBinding): Boolean { + return keyBinding.matches(keyCode, scanCode, modifiers) + } +} + +data class HandledScreenKeyPressedEvent( + override val screen: HandledScreen<*>, + override val keyCode: Int, + override val scanCode: Int, + override val modifiers: Int +) : FirmamentEvent.Cancellable(), HandledScreenKeyEvent { + companion object : FirmamentEventBus() +} + +data class HandledScreenKeyReleasedEvent( + override val screen: HandledScreen<*>, + override val keyCode: Int, + override val scanCode: Int, + override val modifiers: Int +) : FirmamentEvent.Cancellable(), HandledScreenKeyEvent { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/HandledScreenPushREIEvent.kt b/src/main/kotlin/events/HandledScreenPushREIEvent.kt new file mode 100644 index 0000000..1bb495a --- /dev/null +++ b/src/main/kotlin/events/HandledScreenPushREIEvent.kt @@ -0,0 +1,18 @@ + + +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 = mutableListOf() +) : FirmamentEvent() { + + fun block(rectangle: Rectangle) { + rectangles.add(rectangle) + } + + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/HotbarItemRenderEvent.kt b/src/main/kotlin/events/HotbarItemRenderEvent.kt new file mode 100644 index 0000000..a1940e6 --- /dev/null +++ b/src/main/kotlin/events/HotbarItemRenderEvent.kt @@ -0,0 +1,17 @@ + + +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() +} diff --git a/src/main/kotlin/events/HudRenderEvent.kt b/src/main/kotlin/events/HudRenderEvent.kt new file mode 100644 index 0000000..a773a93 --- /dev/null +++ b/src/main/kotlin/events/HudRenderEvent.kt @@ -0,0 +1,17 @@ + + +package moe.nea.firmament.events + +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.render.RenderTickCounter +import net.minecraft.world.GameMode +import moe.nea.firmament.util.MC + +/** + * Called when hud elements should be rendered, before the screen, but after the world. + */ +data class HudRenderEvent(val context: DrawContext, val tickDelta: RenderTickCounter) : FirmamentEvent() { + val isRenderingHud = !MC.options.hudHidden + val isRenderingCursor = MC.interactionManager?.currentGameMode != GameMode.SPECTATOR && isRenderingHud + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/IsSlotProtectedEvent.kt b/src/main/kotlin/events/IsSlotProtectedEvent.kt new file mode 100644 index 0000000..8fe0a96 --- /dev/null +++ b/src/main/kotlin/events/IsSlotProtectedEvent.kt @@ -0,0 +1,65 @@ +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 +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.hover +import moe.nea.firmament.util.red +import moe.nea.firmament.util.tr + +data class IsSlotProtectedEvent( + val slot: Slot?, + val actionType: SlotActionType, + var isProtected: Boolean, + val itemStackOverride: ItemStack?, + val origin: MoveOrigin, + var silent: Boolean = false, +) : FirmamentEvent() { + val itemStack get() = itemStackOverride ?: slot!!.stack + + fun protect() { + isProtected = true + silent = false + } + + fun protectSilent() { + if (!isProtected) { + silent = true + } + isProtected = true + } + + enum class MoveOrigin { + DROP_FROM_HOTBAR, + SALVAGE, + INVENTORY_MOVE + ; + } + + companion object : FirmamentEventBus() { + @JvmStatic + @JvmOverloads + fun shouldBlockInteraction( + slot: Slot?, action: SlotActionType, + origin: MoveOrigin, + itemStackOverride: ItemStack? = null, + ): Boolean { + if (slot == null && itemStackOverride == null) return false + val event = IsSlotProtectedEvent(slot, action, false, itemStackOverride, origin) + publish(event) + if (event.isProtected && !event.silent) { + MC.sendChat(tr("firmament.protectitem", "Firmament protected your item: ${event.itemStack.name}.\n") + .red() + .append(tr("firmament.protectitem.hoverhint", "Hover for more info.").grey()) + .hover(tr("firmament.protectitem.hint", + "To unlock this item use the Lock Slot or Lock Item keybind from Firmament while hovering over this item."))) + CommonSoundEffects.playFailure() + } + return event.isProtected + } + } +} diff --git a/src/main/kotlin/events/ItemTooltipEvent.kt b/src/main/kotlin/events/ItemTooltipEvent.kt new file mode 100644 index 0000000..d86e06f --- /dev/null +++ b/src/main/kotlin/events/ItemTooltipEvent.kt @@ -0,0 +1,14 @@ + + +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 +) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/MaskCommands.kt b/src/main/kotlin/events/MaskCommands.kt new file mode 100644 index 0000000..35aade0 --- /dev/null +++ b/src/main/kotlin/events/MaskCommands.kt @@ -0,0 +1,13 @@ + + +package moe.nea.firmament.events + +import com.mojang.brigadier.CommandDispatcher + +data class MaskCommands(val dispatcher: CommandDispatcher<*>) : FirmamentEvent() { + companion object : FirmamentEventBus() + + fun mask(name: String) { + dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = true) } + } +} diff --git a/src/main/kotlin/events/ModifyChatEvent.kt b/src/main/kotlin/events/ModifyChatEvent.kt new file mode 100644 index 0000000..a5868e8 --- /dev/null +++ b/src/main/kotlin/events/ModifyChatEvent.kt @@ -0,0 +1,21 @@ + + +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() +} diff --git a/src/main/kotlin/events/OutgoingPacketEvent.kt b/src/main/kotlin/events/OutgoingPacketEvent.kt new file mode 100644 index 0000000..93890ea --- /dev/null +++ b/src/main/kotlin/events/OutgoingPacketEvent.kt @@ -0,0 +1,9 @@ + + +package moe.nea.firmament.events + +import net.minecraft.network.packet.Packet + +data class OutgoingPacketEvent(val packet: Packet<*>) : FirmamentEvent.Cancellable() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/ParticleSpawnEvent.kt b/src/main/kotlin/events/ParticleSpawnEvent.kt new file mode 100644 index 0000000..9359e4b --- /dev/null +++ b/src/main/kotlin/events/ParticleSpawnEvent.kt @@ -0,0 +1,18 @@ + + +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() +} diff --git a/src/main/kotlin/events/PartyMessageReceivedEvent.kt b/src/main/kotlin/events/PartyMessageReceivedEvent.kt new file mode 100644 index 0000000..4688dfe --- /dev/null +++ b/src/main/kotlin/events/PartyMessageReceivedEvent.kt @@ -0,0 +1,9 @@ +package moe.nea.firmament.events + +data class PartyMessageReceivedEvent( + val from: ProcessChatEvent, + val message: String, + val name: String, +) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/PlayerInventoryUpdate.kt b/src/main/kotlin/events/PlayerInventoryUpdate.kt new file mode 100644 index 0000000..88439a9 --- /dev/null +++ b/src/main/kotlin/events/PlayerInventoryUpdate.kt @@ -0,0 +1,22 @@ +package moe.nea.firmament.events + +import net.minecraft.item.ItemStack + +sealed class PlayerInventoryUpdate : FirmamentEvent() { + companion object : FirmamentEventBus() + data class Single(val slot: Int, val stack: ItemStack) : PlayerInventoryUpdate() { + override fun getOrNull(slot: Int): ItemStack? { + if (slot == this.slot) return stack + return null + } + + } + + data class Multi(val contents: List) : PlayerInventoryUpdate() { + override fun getOrNull(slot: Int): ItemStack? { + return contents.getOrNull(slot) + } + } + + abstract fun getOrNull(slot: Int): ItemStack? +} diff --git a/src/main/kotlin/events/ProcessChatEvent.kt b/src/main/kotlin/events/ProcessChatEvent.kt new file mode 100644 index 0000000..76c0b27 --- /dev/null +++ b/src/main/kotlin/events/ProcessChatEvent.kt @@ -0,0 +1,28 @@ + + +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() +} diff --git a/src/main/kotlin/events/ProfileSwitchEvent.kt b/src/main/kotlin/events/ProfileSwitchEvent.kt new file mode 100644 index 0000000..683b7dd --- /dev/null +++ b/src/main/kotlin/events/ProfileSwitchEvent.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.events + +import java.util.UUID + +data class ProfileSwitchEvent(val oldProfile: UUID?, val newProfile: UUID?) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/ReloadRegistrationEvent.kt b/src/main/kotlin/events/ReloadRegistrationEvent.kt new file mode 100644 index 0000000..4c3083e --- /dev/null +++ b/src/main/kotlin/events/ReloadRegistrationEvent.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.events + +import io.github.moulberry.repo.NEURepository + +data class ReloadRegistrationEvent(val repo: NEURepository) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/ScreenChangeEvent.kt b/src/main/kotlin/events/ScreenChangeEvent.kt new file mode 100644 index 0000000..489e487 --- /dev/null +++ b/src/main/kotlin/events/ScreenChangeEvent.kt @@ -0,0 +1,10 @@ + + +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() +} diff --git a/src/main/kotlin/events/ScreenRenderPostEvent.kt b/src/main/kotlin/events/ScreenRenderPostEvent.kt new file mode 100644 index 0000000..79f4913 --- /dev/null +++ b/src/main/kotlin/events/ScreenRenderPostEvent.kt @@ -0,0 +1,16 @@ + + +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() +} diff --git a/src/main/kotlin/events/ServerConnectedEvent.kt b/src/main/kotlin/events/ServerConnectedEvent.kt new file mode 100644 index 0000000..26897f2 --- /dev/null +++ b/src/main/kotlin/events/ServerConnectedEvent.kt @@ -0,0 +1,18 @@ +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() { + init { + ClientPlayConnectionEvents.INIT.register(ClientPlayConnectionEvents.Init { clientPlayNetworkHandler: ClientPlayNetworkHandler, minecraftClient: MinecraftClient -> + publishSync(ServerConnectedEvent(clientPlayNetworkHandler.connection)) + }) + } + } +} diff --git a/src/main/kotlin/events/SkyblockServerUpdateEvent.kt b/src/main/kotlin/events/SkyblockServerUpdateEvent.kt new file mode 100644 index 0000000..0bc5143 --- /dev/null +++ b/src/main/kotlin/events/SkyblockServerUpdateEvent.kt @@ -0,0 +1,15 @@ + + +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() +} diff --git a/src/main/kotlin/events/SlotClickEvent.kt b/src/main/kotlin/events/SlotClickEvent.kt new file mode 100644 index 0000000..d4abfb0 --- /dev/null +++ b/src/main/kotlin/events/SlotClickEvent.kt @@ -0,0 +1,15 @@ + +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() +} diff --git a/src/main/kotlin/events/SlotRenderEvents.kt b/src/main/kotlin/events/SlotRenderEvents.kt new file mode 100644 index 0000000..5234176 --- /dev/null +++ b/src/main/kotlin/events/SlotRenderEvents.kt @@ -0,0 +1,37 @@ + + +package moe.nea.firmament.events + +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.texture.Sprite +import net.minecraft.screen.slot.Slot +import net.minecraft.util.Identifier +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.render.drawGuiTexture + +interface SlotRenderEvents { + val context: DrawContext + val slot: Slot + + fun highlight(sprite: Identifier) { + context.drawGuiTexture( + slot.x, slot.y, 0, 16, 16, + sprite + ) + } + + data class Before( + override val context: DrawContext, override val slot: Slot, + ) : FirmamentEvent(), + SlotRenderEvents { + companion object : FirmamentEventBus() + } + + data class After( + override val context: DrawContext, override val slot: Slot, + ) : FirmamentEvent(), + SlotRenderEvents { + companion object : FirmamentEventBus() + } +} diff --git a/src/main/kotlin/events/SoundReceiveEvent.kt b/src/main/kotlin/events/SoundReceiveEvent.kt new file mode 100644 index 0000000..d1b85b6 --- /dev/null +++ b/src/main/kotlin/events/SoundReceiveEvent.kt @@ -0,0 +1,18 @@ + +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, + val category: SoundCategory, + val position: Vec3d, + val pitch: Float, + val volume: Float, + val seed: Long +) : FirmamentEvent.Cancellable() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/TickEvent.kt b/src/main/kotlin/events/TickEvent.kt new file mode 100644 index 0000000..18007f8 --- /dev/null +++ b/src/main/kotlin/events/TickEvent.kt @@ -0,0 +1,7 @@ + + +package moe.nea.firmament.events + +data class TickEvent(val tickCount: Int) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/UseBlockEvent.kt b/src/main/kotlin/events/UseBlockEvent.kt new file mode 100644 index 0000000..8bbe0de --- /dev/null +++ b/src/main/kotlin/events/UseBlockEvent.kt @@ -0,0 +1,11 @@ + +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() +} diff --git a/src/main/kotlin/events/UseItemEvent.kt b/src/main/kotlin/events/UseItemEvent.kt new file mode 100644 index 0000000..e294bb1 --- /dev/null +++ b/src/main/kotlin/events/UseItemEvent.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.events + +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.item.ItemStack +import net.minecraft.util.Hand +import net.minecraft.world.World + +data class UseItemEvent(val playerEntity: PlayerEntity, val world: World, val hand: Hand) : FirmamentEvent.Cancellable() { + companion object : FirmamentEventBus() + val item: ItemStack = playerEntity.getStackInHand(hand) +} diff --git a/src/main/kotlin/events/WorldKeyboardEvent.kt b/src/main/kotlin/events/WorldKeyboardEvent.kt new file mode 100644 index 0000000..1d6a758 --- /dev/null +++ b/src/main/kotlin/events/WorldKeyboardEvent.kt @@ -0,0 +1,17 @@ +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() + + fun matches(keyBinding: KeyBinding): Boolean { + return matches(IKeyBinding.minecraft(keyBinding)) + } + + fun matches(keyBinding: IKeyBinding, atLeast: Boolean = false): Boolean { + return if (atLeast) keyBinding.matchesAtLeast(keyCode, scanCode, modifiers) else + keyBinding.matches(keyCode, scanCode, modifiers) + } +} diff --git a/src/main/kotlin/events/WorldMouseMoveEvent.kt b/src/main/kotlin/events/WorldMouseMoveEvent.kt new file mode 100644 index 0000000..7a17ba4 --- /dev/null +++ b/src/main/kotlin/events/WorldMouseMoveEvent.kt @@ -0,0 +1,5 @@ +package moe.nea.firmament.events + +data class WorldMouseMoveEvent(val deltaX: Double, val deltaY: Double) : FirmamentEvent.Cancellable() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/WorldReadyEvent.kt b/src/main/kotlin/events/WorldReadyEvent.kt new file mode 100644 index 0000000..c79b100 --- /dev/null +++ b/src/main/kotlin/events/WorldReadyEvent.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.events + +class WorldReadyEvent : FirmamentEvent() { + companion object : FirmamentEventBus() +// class FullyLoaded : FirmamentEvent() { +// companion object : FirmamentEventBus() { +// TODO: check WorldLoadingState +// } +// } +} diff --git a/src/main/kotlin/events/WorldRenderLastEvent.kt b/src/main/kotlin/events/WorldRenderLastEvent.kt new file mode 100644 index 0000000..3c2103d --- /dev/null +++ b/src/main/kotlin/events/WorldRenderLastEvent.kt @@ -0,0 +1,24 @@ + + +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 camera: Camera, + val vertexConsumers: VertexConsumerProvider.Immediate, +) : FirmamentEvent() { + companion object : FirmamentEventBus() +} diff --git a/src/main/kotlin/events/registration/ChatEvents.kt b/src/main/kotlin/events/registration/ChatEvents.kt new file mode 100644 index 0000000..1dcc91a --- /dev/null +++ b/src/main/kotlin/events/registration/ChatEvents.kt @@ -0,0 +1,63 @@ +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.fabricmc.fabric.api.event.player.UseItemCallback +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 +import moe.nea.firmament.events.UseItemEvent + +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 + }) + UseBlockCallback.EVENT.register(UseBlockCallback { player, world, hand, hitResult -> + if (UseItemEvent.publish(UseItemEvent(player, world, hand)).cancelled) + ActionResult.CONSUME + else ActionResult.PASS + }) + UseItemCallback.EVENT.register(UseItemCallback { playerEntity, world, hand -> + if (UseItemEvent.publish(UseItemEvent(playerEntity, world, hand)).cancelled) ActionResult.CONSUME + else ActionResult.PASS + }) +} diff --git a/src/main/kotlin/events/subscription/Subscription.kt b/src/main/kotlin/events/subscription/Subscription.kt new file mode 100644 index 0000000..1c1d3bd --- /dev/null +++ b/src/main/kotlin/events/subscription/Subscription.kt @@ -0,0 +1,17 @@ + +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( + val owner: Any, + val invoke: (T) -> Unit, + val eventBus: FirmamentEventBus, + val methodName: String, +) diff --git a/src/main/kotlin/events/subscription/SubscriptionList.kt b/src/main/kotlin/events/subscription/SubscriptionList.kt new file mode 100644 index 0000000..817efc3 --- /dev/null +++ b/src/main/kotlin/events/subscription/SubscriptionList.kt @@ -0,0 +1,28 @@ +package moe.nea.firmament.events.subscription + +import java.util.ServiceLoader +import kotlin.streams.asSequence +import moe.nea.firmament.Firmament + +interface SubscriptionList { + fun provideSubscriptions(addSubscription: (Subscription<*>) -> Unit) + + companion object { + val allLists by lazy { + ServiceLoader.load(SubscriptionList::class.java) + .stream() + .asSequence() + .mapNotNull { + kotlin.runCatching { it.get() } + .getOrElse { ex -> + Firmament.logger.error("Could not load subscriptions from ${it.type()}", ex) + null + } + } + .toList() + } + init { + require(allLists.isNotEmpty()) + } + } +} diff --git a/src/main/kotlin/features/FeatureManager.kt b/src/main/kotlin/features/FeatureManager.kt new file mode 100644 index 0000000..e0799c4 --- /dev/null +++ b/src/main/kotlin/features/FeatureManager.kt @@ -0,0 +1,133 @@ +package moe.nea.firmament.features + +import kotlinx.serialization.Serializable +import kotlinx.serialization.serializer +import moe.nea.firmament.Firmament +import moe.nea.firmament.events.FeaturesInitializedEvent +import moe.nea.firmament.events.FirmamentEvent +import moe.nea.firmament.events.subscription.Subscription +import moe.nea.firmament.events.subscription.SubscriptionList +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.PetFeatures +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.WardrobeKeybinds +import moe.nea.firmament.features.inventory.buttons.InventoryButtons +import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay +import moe.nea.firmament.features.items.EtherwarpOverlay +import moe.nea.firmament.features.mining.PickaxeAbility +import moe.nea.firmament.features.mining.PristineProfitTracker +import moe.nea.firmament.features.misc.CustomCapes +import moe.nea.firmament.features.misc.Hud +import moe.nea.firmament.features.world.FairySouls +import moe.nea.firmament.features.world.Waypoints +import moe.nea.firmament.util.compatloader.ICompatMeta +import moe.nea.firmament.util.data.DataHolder + +object FeatureManager : DataHolder(serializer(), "features", ::Config) { + @Serializable + data class Config( + val enabledFeatures: MutableMap = mutableMapOf() + ) + + private val features = mutableMapOf() + + val allFeatures: Collection get() = features.values + + private var hasAutoloaded = false + + 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(CompatibliltyFeatures) + loadFeature(AnniversaryFeatures) + loadFeature(QuickCommands) + loadFeature(PetFeatures) + loadFeature(SaveCursorPosition) + loadFeature(PriceData) + loadFeature(Fixes) + loadFeature(CustomCapes) + loadFeature(Hud) + loadFeature(EtherwarpOverlay) + loadFeature(WardrobeKeybinds) + 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() { + SubscriptionList.allLists.forEach { list -> + if (ICompatMeta.shouldLoad(list.javaClass.name)) + runCatching { + list.provideSubscriptions { + it.owner.javaClass.classes.forEach { + runCatching { it.getDeclaredField("INSTANCE").get(null) } + } + subscribeSingleEvent(it) + } + }.getOrElse { + // TODO: allow annotating source sets to specifically opt out of loading for mods, maybe automatically + Firmament.logger.info("Ignoring events from $list, likely due to a missing compat mod.", it) + } + } + } + + private fun subscribeSingleEvent(it: Subscription) { + it.eventBus.subscribe(false, "${it.owner.javaClass.simpleName}:${it.methodName}", 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/features/FirmamentFeature.kt b/src/main/kotlin/features/FirmamentFeature.kt new file mode 100644 index 0000000..2cfc4fd --- /dev/null +++ b/src/main/kotlin/features/FirmamentFeature.kt @@ -0,0 +1,23 @@ + + +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/features/chat/AutoCompletions.kt b/src/main/kotlin/features/chat/AutoCompletions.kt new file mode 100644 index 0000000..9e0de40 --- /dev/null +++ b/src/main/kotlin/features/chat/AutoCompletions.kt @@ -0,0 +1,55 @@ +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, Category.CHAT) { + 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/features/chat/ChatLinks.kt b/src/main/kotlin/features/chat/ChatLinks.kt new file mode 100644 index 0000000..1fb12e1 --- /dev/null +++ b/src/main/kotlin/features/chat/ChatLinks.kt @@ -0,0 +1,165 @@ +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.URI +import java.net.URL +import java.util.Collections +import java.util.concurrent.atomic.AtomicInteger +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.render.drawTexture +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, Category.CHAT) { + 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://[^. ]+\\.[^ ]+(\\.?(\\s|$))".toRegex() + val nextTexId = AtomicInteger(0) + + data class Image( + val texture: Identifier, + val width: Int, + val height: Int, + ) + + val imageCache: MutableMap> = + Collections.synchronizedMap(mutableMapOf>()) + + 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 texId = Firmament.identifier("dynamic_image_preview${nextTexId.getAndIncrement()}") + MC.textureManager.registerTexture( + texId, + NativeImageBackedTexture({ texId.path }, image) + ) + Image(texId, 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 as? HoverEvent.ShowText ?: return + val value = hoverEvent.value + 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) + val url = nextMatch?.groupValues[0] + val uri = runCatching { url?.let(::URI) }.getOrNull() + if (nextMatch == null || url == null || uri == null) { + s.append(Text.literal(text.substring(index, text.length))) + break + } + val range = nextMatch.groups[0]!!.range + s.append(Text.literal(text.substring(index, range.first))) + s.append( + Text.literal(url).setStyle( + Style.EMPTY.withUnderline(true).withColor( + Formatting.AQUA + ).withHoverEvent(HoverEvent.ShowText(Text.literal(url))) + .withClickEvent(ClickEvent.OpenUrl(uri)) + ) + ) + if (isImageUrl(url)) + tryCacheUrl(url) + index = range.last + 1 + } + s + } + } +} diff --git a/src/main/kotlin/features/chat/CopyChat.kt b/src/main/kotlin/features/chat/CopyChat.kt new file mode 100644 index 0000000..64f8734 --- /dev/null +++ b/src/main/kotlin/features/chat/CopyChat.kt @@ -0,0 +1,31 @@ +package moe.nea.firmament.features.chat + +import net.minecraft.text.OrderedText +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ClientStartedEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.reconstitute + + +object CopyChat : FirmamentFeature { + override val identifier: String + get() = "copy-chat" + + object TConfig : ManagedConfig(identifier, Category.CHAT) { + val copyChat by toggle("copy-chat") { false } + } + + @Subscribe + fun onInit(event: ClientStartedEvent) { + } + + override val config: ManagedConfig? + get() = TConfig + + fun orderedTextToString(orderedText: OrderedText): String { + return orderedText.reconstitute().string + } + + +} diff --git a/src/main/kotlin/features/chat/PartyCommands.kt b/src/main/kotlin/features/chat/PartyCommands.kt new file mode 100644 index 0000000..de3a0d9 --- /dev/null +++ b/src/main/kotlin/features/chat/PartyCommands.kt @@ -0,0 +1,134 @@ +package moe.nea.firmament.features.chat + +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.StringReader +import com.mojang.brigadier.exceptions.CommandSyntaxException +import com.mojang.brigadier.tree.LiteralCommandNode +import kotlin.time.Duration.Companion.seconds +import net.minecraft.util.math.BlockPos +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.CaseInsensitiveLiteralCommandNode +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.PartyMessageReceivedEvent +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.useMatch + +object PartyCommands { + + val messageInChannel = "(?Party|Guild) >([^:]+?)? (?[^: ]+): (?.+)".toPattern() + + @Subscribe + fun onChat(event: ProcessChatEvent) { + messageInChannel.useMatch(event.unformattedString) { + val channel = group("channel") + val message = group("message") + val name = group("name") + if (channel == "Party") { + PartyMessageReceivedEvent.publish(PartyMessageReceivedEvent( + event, message, name + )) + } + } + } + + val commandPrefixes = "!-?$.&#+~€\"@°_;:³²`'´ß\\,|".toSet() + + data class PartyCommandContext( + val name: String + ) + + val dispatch = CommandDispatcher().also { dispatch -> + fun register( + name: String, + vararg alias: String, + block: CaseInsensitiveLiteralCommandNode.Builder.() -> Unit = {}, + ): LiteralCommandNode { + val node = + dispatch.register(CaseInsensitiveLiteralCommandNode.Builder(name).also(block)) + alias.forEach { register(it) { redirect(node) } } + return node + } + + register("warp", "pw", "pwarp", "partywarp") { + executes { + // TODO: add check if you are the party leader + MC.sendCommand("p warp") + 0 + } + } + + register("transfer", "pt", "ptme") { + executes { + MC.sendCommand("p transfer ${it.source.name}") + 0 + } + } + + register("allinvite", "allinv") { + executes { + MC.sendCommand("p settings allinvite") + 0 + } + } + + register("coords") { + executes { + val p = MC.player?.blockPos ?: BlockPos.ORIGIN + MC.sendCommand("pc x: ${p.x}, y: ${p.y}, z: ${p.z}") + 0 + } + } + // TODO: downtime tracker (display message again at end of dungeon) + // instance ends: kuudra, dungeons, bacte + // TODO: at TPS command + } + + object TConfig : ManagedConfig("party-commands", Category.CHAT) { + val enable by toggle("enable") { false } + val cooldown by duration("cooldown", 0.seconds, 20.seconds) { 2.seconds } + val ignoreOwnCommands by toggle("ignore-own") { false } + } + + var lastCommand = TimeMark.farPast() + + @Subscribe + fun listPartyCommands(event: CommandEvent.SubCommand) { + event.subcommand("partycommands") { + thenExecute { + // TODO: Better help, including descriptions and redirect detection + MC.sendChat(tr("firmament.partycommands.help", "Available party commands: ${dispatch.root.children.map { it.name }}. Available prefixes: $commandPrefixes")) + } + } + } + + @Subscribe + fun onPartyMessage(event: PartyMessageReceivedEvent) { + if (!TConfig.enable) return + if (event.message.firstOrNull() !in commandPrefixes) return + if (event.name == MC.playerName && TConfig.ignoreOwnCommands) return + if (lastCommand.passedTime() < TConfig.cooldown) { + MC.sendChat(tr("firmament.partycommands.cooldown", "Skipping party command. Cooldown not passed.")) + return + } + // TODO: add trust levels + val commandLine = event.message.substring(1) + try { + dispatch.execute(StringReader(commandLine), PartyCommandContext(event.name)) + } catch (ex: Exception) { + if (ex is CommandSyntaxException) { + MC.sendChat(tr("firmament.partycommands.unknowncommand", "Unknown party command.")) + return + } else { + MC.sendChat(tr("firmament.partycommands.unknownerror", "Unknown error during command execution.")) + ErrorUtil.softError("Unknown error during command execution.", ex) + } + } + lastCommand = TimeMark.now() + } +} diff --git a/src/main/kotlin/features/chat/QuickCommands.kt b/src/main/kotlin/features/chat/QuickCommands.kt new file mode 100644 index 0000000..7963171 --- /dev/null +++ b/src/main/kotlin/features/chat/QuickCommands.kt @@ -0,0 +1,154 @@ +package moe.nea.firmament.features.chat + +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.context.CommandContext +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource +import net.fabricmc.fabric.impl.command.client.ClientCommandInternals +import net.minecraft.command.CommandRegistryAccess +import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket +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.gui.config.ManagedConfig +import moe.nea.firmament.gui.config.ManagedOption +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.tr + +object QuickCommands : FirmamentFeature { + override val identifier: String + get() = "quick-commands" + + object TConfig : ManagedConfig("quick-commands", Category.CHAT) { + val enableJoin by toggle("join") { true } + val enableDh by toggle("dh") { true } + override fun onChange(option: ManagedOption<*>) { + reloadCommands() + } + } + + fun reloadCommands() { + val lastPacket = lastReceivedTreePacket ?: return + val network = MC.networkHandler ?: return + val fallback = ClientCommandInternals.getActiveDispatcher() + try { + val dispatcher = CommandDispatcher() + ClientCommandInternals.setActiveDispatcher(dispatcher) + ClientCommandRegistrationCallback.EVENT.invoker() + .register(dispatcher, CommandRegistryAccess.of(network.combinedDynamicRegistries, + network.enabledFeatures)) + ClientCommandInternals.finalizeInit() + network.onCommandTree(lastPacket) + } catch (ex: Exception) { + ClientCommandInternals.setActiveDispatcher(fallback) + throw ex + } + } + + + 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 + } + + var lastReceivedTreePacket: CommandTreeS2CPacket? = null + + val kuudraLevelNames = listOf("NORMAL", "HOT", "BURNING", "FIERY", "INFERNAL") + val dungeonLevelNames = listOf("ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN") + + @Subscribe + fun registerDh(event: CommandEvent) { + if (!TConfig.enableDh) return + event.register("dh") { + thenExecute { + MC.sendCommand("warp dhub") + } + } + event.register("dn") { + thenExecute { + MC.sendChat(tr("firmament.quickwarp.deez-nutz", "Warping to... Deez Nuts!").grey()) + MC.sendCommand("warp dhub") + } + } + } + + @Subscribe + fun registerJoin(it: CommandEvent) { + if (!TConfig.enableJoin) return + 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.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/features/debug/AnimatedClothingScanner.kt b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt new file mode 100644 index 0000000..4edccfb --- /dev/null +++ b/src/main/kotlin/features/debug/AnimatedClothingScanner.kt @@ -0,0 +1,193 @@ +package moe.nea.firmament.features.debug + +import net.minecraft.command.argument.RegistryKeyArgumentType +import net.minecraft.component.ComponentType +import net.minecraft.entity.Entity +import net.minecraft.entity.decoration.ArmorStandEntity +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtOps +import net.minecraft.registry.RegistryKeys +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.EntityUpdateEvent +import moe.nea.firmament.events.WorldReadyEvent +import moe.nea.firmament.util.ClipboardUtils +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.math.GChainReconciliation +import moe.nea.firmament.util.math.GChainReconciliation.shortenCycle +import moe.nea.firmament.util.mc.NbtPrism +import moe.nea.firmament.util.tr + +object AnimatedClothingScanner { + + data class LensOfFashionTheft( + val prism: NbtPrism, + val component: ComponentType, + ) { + fun observe(itemStack: ItemStack): Collection { + val x = itemStack.get(component) ?: return listOf() + val nbt = component.codecOrThrow.encodeStart(NbtOps.INSTANCE, x).orThrow + return prism.access(nbt) + } + } + + var lens: LensOfFashionTheft<*>? = null + var subject: Entity? = null + var history: MutableList = mutableListOf() + val metaHistory: MutableList> = mutableListOf() + + @OptIn(ExperimentalStdlibApi::class) + @Subscribe + fun onUpdate(event: EntityUpdateEvent) { + val s = subject ?: return + if (event.entity != s) return + val l = lens ?: return + if (event is EntityUpdateEvent.EquipmentUpdate) { + event.newEquipment.forEach { + val formatted = (l.observe(it.second)).joinToString() + history.add(formatted) + // TODO: add a slot filter + } + } + } + + fun reduceHistory(reducer: (List, List) -> List): List { + return metaHistory.fold(history, reducer).shortenCycle() + } + + @Subscribe + fun onSubCommand(event: CommandEvent.SubCommand) { + event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { + thenLiteral("stealthisfit") { + thenLiteral("clear") { + thenExecute { + subject = null + metaHistory.clear() + history.clear() + MC.sendChat(tr("firmament.fitstealer.clear", "Cleared fit stealing history")) + } + } + thenLiteral("copy") { + thenExecute { + val history = reduceHistory { a, b -> a + b } + copyHistory(history) + MC.sendChat(tr("firmament.fitstealer.copied", "Copied the history")) + } + thenLiteral("deduplicated") { + thenExecute { + val history = reduceHistory { a, b -> + (a.toMutableSet() + b).toList() + } + copyHistory(history) + MC.sendChat( + tr( + "firmament.fitstealer.copied.deduplicated", + "Copied the deduplicated history" + ) + ) + } + } + thenLiteral("merged") { + thenExecute { + val history = reduceHistory(GChainReconciliation::reconcileCycles) + copyHistory(history) + MC.sendChat(tr("firmament.fitstealer.copied.merged", "Copied the merged history")) + } + } + } + thenLiteral("target") { + thenLiteral("self") { + thenExecute { + toggleObserve(MC.player!!) + } + } + thenLiteral("pet") { + thenExecute { + source.sendFeedback( + tr( + "firmament.fitstealer.stealingpet", + "Observing nearest marker armourstand" + ) + ) + val p = MC.player!! + val nearestPet = p.world.getEntitiesByClass( + ArmorStandEntity::class.java, + p.boundingBox.expand(10.0), + { it.isMarker }) + .minBy { it.squaredDistanceTo(p) } + toggleObserve(nearestPet) + } + } + thenExecute { + val ent = MC.instance.targetedEntity + if (ent == null) { + source.sendFeedback( + tr( + "firmament.fitstealer.notargetundercursor", + "No entity under cursor" + ) + ) + } else { + toggleObserve(ent) + } + } + } + thenLiteral("path") { + thenArgument( + "component", + RegistryKeyArgumentType.registryKey(RegistryKeys.DATA_COMPONENT_TYPE) + ) { component -> + thenArgument("path", NbtPrism.Argument) { path -> + thenExecute { + lens = LensOfFashionTheft( + get(path), + MC.unsafeGetRegistryEntry(get(component))!!, + ) + source.sendFeedback( + tr( + "firmament.fitstealer.lensset", + "Analyzing path ${get(path)} for component ${get(component).value}" + ) + ) + } + } + } + } + } + } + } + + private fun copyHistory(toCopy: List) { + ClipboardUtils.setTextContent(toCopy.joinToString("\n")) + } + + @Subscribe + fun onWorldSwap(event: WorldReadyEvent) { + subject = null + if (history.isNotEmpty()) { + metaHistory.add(history) + history = mutableListOf() + } + } + + private fun toggleObserve(entity: Entity?) { + subject = if (subject == null) entity else null + if (subject == null) { + metaHistory.add(history) + history = mutableListOf() + } + MC.sendChat( + subject?.let { + tr( + "firmament.fitstealer.targeted", + "Observing the equipment of ${it.name}." + ) + } ?: tr("firmament.fitstealer.targetlost", "No longer logging equipment."), + ) + } +} diff --git a/src/main/kotlin/features/debug/DebugLogger.kt b/src/main/kotlin/features/debug/DebugLogger.kt new file mode 100644 index 0000000..9115956 --- /dev/null +++ b/src/main/kotlin/features/debug/DebugLogger.kt @@ -0,0 +1,26 @@ +package moe.nea.firmament.features.debug + +import kotlinx.serialization.serializer +import net.minecraft.text.Text +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.collections.InstanceList +import moe.nea.firmament.util.data.DataHolder + +class DebugLogger(val tag: String) { + companion object { + val allInstances = InstanceList("DebugLogger") + } + + object EnabledLogs : DataHolder>(serializer(), "DebugLogs", ::mutableSetOf) + + init { + allInstances.add(this) + } + + fun isEnabled() = DeveloperFeatures.isEnabled && EnabledLogs.data.contains(tag) + fun log(text: String) = log { text } + fun log(text: () -> String) { + if (!isEnabled()) return + MC.sendChat(Text.literal(text())) + } +} diff --git a/src/main/kotlin/features/debug/DebugView.kt b/src/main/kotlin/features/debug/DebugView.kt new file mode 100644 index 0000000..ee54260 --- /dev/null +++ b/src/main/kotlin/features/debug/DebugView.kt @@ -0,0 +1,29 @@ + + +package moe.nea.firmament.features.debug + +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +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( + val obj: T, + val timer: TimeMark, + ) + + private val storedVariables: MutableMap> = sortedMapOf() + override val identifier: String + get() = "debug-view" + override val defaultEnabled: Boolean + get() = Firmament.DEBUG + + fun showVariable(label: String, obj: T) { + synchronized(this) { + storedVariables[label] = StoredVariable(obj, TimeMark.now()) + } + } + +} diff --git a/src/main/kotlin/features/debug/DeveloperFeatures.kt b/src/main/kotlin/features/debug/DeveloperFeatures.kt new file mode 100644 index 0000000..fd236f9 --- /dev/null +++ b/src/main/kotlin/features/debug/DeveloperFeatures.kt @@ -0,0 +1,121 @@ +package moe.nea.firmament.features.debug + +import java.io.File +import java.nio.file.Path +import java.util.concurrent.CompletableFuture +import org.objectweb.asm.ClassReader +import org.objectweb.asm.Type +import org.objectweb.asm.tree.ClassNode +import org.spongepowered.asm.mixin.Mixin +import kotlinx.serialization.json.encodeToStream +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.annotations.Subscribe +import moe.nea.firmament.events.DebugInstantiateEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.init.MixinPlugin +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.asm.AsmAnnotationUtil +import moe.nea.firmament.util.iterate + +object DeveloperFeatures : FirmamentFeature { + val DEVELOPER_SUBCOMMAND: String = "dev" + 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", Category.DEV) { + val autoRebuildResources by toggle("auto-rebuild") { false } + } + + var missingTranslations: Set? = null + + @JvmStatic + fun hookMissingTranslations(missingTranslations: Set) { + this.missingTranslations = missingTranslations + } + + @Subscribe + fun loadAllMixinClasses(event: DebugInstantiateEvent) { + val allMixinClasses = mutableSetOf() + MixinPlugin.instances.forEach { plugin -> + val prefix = plugin.mixinPackage + "." + val classes = plugin.mixins.map { prefix + it } + allMixinClasses.addAll(classes) + for (cls in classes) { + val targets = javaClass.classLoader.getResourceAsStream("${cls.replace(".", "/")}.class").use { + val node = ClassNode() + ClassReader(it).accept(node, 0) + val mixins = mutableListOf() + (node.visibleAnnotations.orEmpty() + node.invisibleAnnotations.orEmpty()).forEach { + val annotationType = Type.getType(it.desc) + val mixinType = Type.getType(Mixin::class.java) + if (mixinType == annotationType) { + mixins.add(AsmAnnotationUtil.createProxy(Mixin::class.java, it)) + } + } + mixins.flatMap { it.targets.toList() } + mixins.flatMap { it.value.map { it.java.name } } + } + for (target in targets) + try { + Firmament.logger.debug("Loading ${target} to force instantiate ${cls}") + Class.forName(target, true, javaClass.classLoader) + } catch (ex: Throwable) { + Firmament.logger.error("Could not load class ${target} that has been mixind by $cls", ex) + } + } + } + Firmament.logger.info("Forceloaded all Firmament mixins:") + val applied = MixinPlugin.instances.flatMap { it.appliedMixins }.toSet() + applied.forEach { Firmament.logger.info(" - ${it}") } + require(allMixinClasses == applied) + } + + @Subscribe + fun dumpMissingTranslations(tickEvent: TickEvent) { + val toDump = missingTranslations ?: return + missingTranslations = null + File("missing_translations.json").outputStream().use { + Firmament.json.encodeToStream(toDump.associateWith { "Mis" + "sing translation" }, it) + } + } + + @JvmStatic + fun hookOnBeforeResourceReload(client: MinecraftClient): CompletableFuture { + val reloadFuture = if (TConfig.autoRebuildResources && isEnabled && gradleDir != null) { + val builder = ProcessBuilder("./gradlew", ":processResources") + builder.directory(gradleDir.toFile()) + builder.inheritIO() + val process = builder.start() + MC.sendChat(Text.translatable("firmament.dev.resourcerebuild.start")) + val startTime = TimeMark.now() + process.toHandle().onExit().thenApply { + MC.sendChat( + Text.stringifiedTranslatable( + "firmament.dev.resourcerebuild.done", + startTime.passedTime() + ) + ) + Unit + } + } else { + CompletableFuture.completedFuture(Unit) + } + return reloadFuture.thenCompose { client.reloadResources() } + } +} + diff --git a/src/main/kotlin/features/debug/ExportedTestConstantMeta.kt b/src/main/kotlin/features/debug/ExportedTestConstantMeta.kt new file mode 100644 index 0000000..f0250dc --- /dev/null +++ b/src/main/kotlin/features/debug/ExportedTestConstantMeta.kt @@ -0,0 +1,27 @@ +package moe.nea.firmament.features.debug + +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import java.util.Optional +import net.minecraft.SharedConstants +import moe.nea.firmament.Firmament + +data class ExportedTestConstantMeta( + val dataVersion: Int, + val modVersion: Optional, +) { + companion object { + val current = ExportedTestConstantMeta( + SharedConstants.getGameVersion().saveVersion.id, + Optional.of("Firmament ${Firmament.version.friendlyString}") + ) + + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + Codec.INT.fieldOf("dataVersion").forGetter(ExportedTestConstantMeta::dataVersion), + Codec.STRING.optionalFieldOf("modVersion").forGetter(ExportedTestConstantMeta::modVersion), + ).apply(it, ::ExportedTestConstantMeta) + } + val SOURCE_CODEC = CODEC.fieldOf("source").codec() + } +} diff --git a/src/main/kotlin/features/debug/MinorTrolling.kt b/src/main/kotlin/features/debug/MinorTrolling.kt new file mode 100644 index 0000000..32035a6 --- /dev/null +++ b/src/main/kotlin/features/debug/MinorTrolling.kt @@ -0,0 +1,27 @@ + + +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/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt new file mode 100644 index 0000000..0800a4f --- /dev/null +++ b/src/main/kotlin/features/debug/PowerUserTools.kt @@ -0,0 +1,245 @@ +package moe.nea.firmament.features.debug + +import com.mojang.serialization.JsonOps +import kotlin.jvm.optionals.getOrNull +import net.minecraft.block.SkullBlock +import net.minecraft.block.entity.SkullBlockEntity +import net.minecraft.component.DataComponentTypes +import net.minecraft.component.type.ProfileComponent +import net.minecraft.entity.Entity +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.nbt.NbtList +import net.minecraft.nbt.NbtOps +import net.minecraft.predicate.NbtPredicate +import net.minecraft.text.Text +import net.minecraft.text.TextCodecs +import net.minecraft.util.Identifier +import net.minecraft.util.Nameable +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.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.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.mc.IntrospectableItemModelManager +import moe.nea.firmament.util.mc.SNbtFormatter +import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.iterableArmorItems +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.grey + +object PowerUserTools : FirmamentFeature { + override val identifier: String + get() = "power-user" + + object TConfig : ManagedConfig(identifier, Category.DEV) { + 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 copyLoreData by keyBindingWithDefaultUnbound("copy-lore") + val copySkullTexture by keyBindingWithDefaultUnbound("copy-skull-texture") + val copyEntityData by keyBindingWithDefaultUnbound("entity-data") + val copyItemStack by keyBindingWithDefaultUnbound("copy-item-stack") + val copyTitle by keyBindingWithDefaultUnbound("copy-title") + val exportItemStackToRepo by keyBindingWithDefaultUnbound("export-item-stack") + val exportUIRecipes by keyBindingWithDefaultUnbound("export-recipe") + val exportNpcLocation by keyBindingWithDefaultUnbound("export-npc-location") + val highlightNonOverlayItems by toggle("highlight-non-overlay") { false } + val dontHighlightSemicolonItems by toggle("dont-highlight-semicolon-items") { false } + } + + override val config + get() = TConfig + + var lastCopiedStack: Pair? = null + set(value) { + field = value + if (value != null) lastCopiedStackViewTime = 2 + } + var lastCopiedStackViewTime = 0 + + @Subscribe + fun resetLastCopiedStack(event: TickEvent) { + if (lastCopiedStackViewTime-- < 0) lastCopiedStack = null + } + + @Subscribe + fun resetLastCopiedStackOnScreenChange(event: ScreenChangeEvent) { + 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) { + val nbt = NbtPredicate.entityToNbt(target) + nbt.remove("Inventory") + nbt.put("StyledName", TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, target.styledDisplayName).orThrow) + println(SNbtFormatter.prettify(nbt)) + ClipboardUtils.setTextContent(SNbtFormatter.prettify(nbt)) + 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 ((slot, armorItem) in target.iterableArmorItems) { + 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) + } + } + + // TODO: leak this through some other way, maybe. + lateinit var getSkullId: (profile: ProfileComponent) -> Identifier? + + @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.getModelIdentifier0(item, object : IntrospectableItemModelManager { + override fun hasModel_firmament(identifier: Identifier): Boolean { + return true + } + }).getOrNull() // TODO: remove global texture overrides, maybe + 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?.toPrettyString() ?: "" + ClipboardUtils.setTextContent(nbt) + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.nbt")) + } else if (it.matches(TConfig.copyLoreData)) { + val list = mutableListOf(item.displayNameAccordingToNbt) + list.addAll(item.loreAccordingToNbt) + ClipboardUtils.setTextContent(list.joinToString("\n") { + TextCodecs.CODEC.encodeStart(JsonOps.INSTANCE, it).result().getOrNull().toString() + }) + lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.lore")) + } 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 = getSkullId(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") + } else if (it.matches(TConfig.copyItemStack)) { + val nbt = ItemStack.CODEC + .encodeStart(MC.currentOrDefaultRegistries.getOps(NbtOps.INSTANCE), item) + .orThrow + ClipboardUtils.setTextContent(nbt.toPrettyString()) + lastCopiedStack = Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.stack")) + } else if (it.matches(TConfig.copyTitle)) { + val allTitles = NbtList() + val inventoryNames = + it.screen.screenHandler.slots + .mapNotNullTo(mutableSetOf()) { it.inventory } + .filterIsInstance() + .map { it.name } + for (it in listOf(it.screen.title) + inventoryNames) { + allTitles.add(TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it).result().getOrNull()!!) + } + ClipboardUtils.setTextContent(allTitles.toPrettyString()) + MC.sendChat(tr("firmament.power-user.title.copied", "Copied screen and inventory titles")) + } + } + + @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 = getSkullId(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).grey()) + } + val (item, text) = lastCopiedStack ?: return + if (!ItemStack.areEqual(item, it.stack)) { + lastCopiedStack = null + return + } + lastCopiedStackViewTime = 0 + it.lines.add(text) + } + + +} diff --git a/src/main/kotlin/features/debug/SoundVisualizer.kt b/src/main/kotlin/features/debug/SoundVisualizer.kt new file mode 100644 index 0000000..f805e6b --- /dev/null +++ b/src/main/kotlin/features/debug/SoundVisualizer.kt @@ -0,0 +1,65 @@ +package moe.nea.firmament.features.debug + +import net.minecraft.text.Text +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.commands.thenLiteral +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.SoundReceiveEvent +import moe.nea.firmament.events.WorldReadyEvent +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.util.red +import moe.nea.firmament.util.render.RenderInWorldContext + +object SoundVisualizer { + + var showSounds = false + + var sounds = mutableListOf() + + + @Subscribe + fun onSubCommand(event: CommandEvent.SubCommand) { + event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { + thenLiteral("sounds") { + thenExecute { + showSounds = !showSounds + if (!showSounds) { + sounds.clear() + } + } + } + } + } + + @Subscribe + fun onWorldSwap(event: WorldReadyEvent) { + sounds.clear() + } + + @Subscribe + fun onRender(event: WorldRenderLastEvent) { + RenderInWorldContext.renderInWorld(event) { + sounds.forEach { event -> + withFacingThePlayer(event.position) { + text( + Text.literal(event.sound.value().id.toString()).also { + if (event.cancelled) + it.red() + }, + verticalAlign = RenderInWorldContext.VerticalAlign.CENTER, + ) + } + } + } + } + + @Subscribe + fun onSoundReceive(event: SoundReceiveEvent) { + if (!showSounds) return + if (sounds.size > 1000) { + sounds.subList(0, 200).clear() + } + sounds.add(event) + } +} diff --git a/src/main/kotlin/features/debug/itemeditor/ExportRecipe.kt b/src/main/kotlin/features/debug/itemeditor/ExportRecipe.kt new file mode 100644 index 0000000..9356dd3 --- /dev/null +++ b/src/main/kotlin/features/debug/itemeditor/ExportRecipe.kt @@ -0,0 +1,255 @@ +package moe.nea.firmament.features.debug.itemeditor + +import kotlinx.coroutines.launch +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import net.minecraft.client.network.AbstractClientPlayerEntity +import net.minecraft.entity.decoration.ArmorStandEntity +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.events.WorldKeyboardEvent +import moe.nea.firmament.features.debug.PowerUserTools +import moe.nea.firmament.repo.ItemNameLookup +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.SHORT_NUMBER_FORMAT +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.async.waitForTextInput +import moe.nea.firmament.util.ifDropLast +import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.mc.setSkullOwner +import moe.nea.firmament.util.parseShortNumber +import moe.nea.firmament.util.red +import moe.nea.firmament.util.removeColorCodes +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.unformattedString +import moe.nea.firmament.util.useMatch + +object ExportRecipe { + + + val xNames = "123" + val yNames = "ABC" + + val slotIndices = (0..<9).map { + val x = it % 3 + val y = it / 3 + + (yNames[y].toString() + xNames[x].toString()) to x + y * 9 + 10 + } + val resultSlot = 25 + val craftingTableSlut = resultSlot - 2 + + @Subscribe + fun exportNpcLocation(event: WorldKeyboardEvent) { + if (!event.matches(PowerUserTools.TConfig.exportNpcLocation)) { + return + } + val entity = MC.instance.targetedEntity + if (entity == null) { + MC.sendChat(tr("firmament.repo.export.npc.noentity", "Could not find entity to export")) + return + } + Firmament.coroutineScope.launch { + val guessName = entity.world.getEntitiesByClass( + ArmorStandEntity::class.java, + entity.boundingBox.expand(0.1), + { !it.name.string.contains("CLICK") }) + .firstOrNull()?.customName?.string + ?: "" + val reply = waitForTextInput("$guessName (NPC)", "Export stub") + val id = generateName(reply) + ItemExporter.exportStub(id, "§9$reply") { + val playerEntity = entity as? AbstractClientPlayerEntity + val textureUrl = playerEntity?.skinTextures?.textureUrl + if (textureUrl != null) + it.setSkullOwner(playerEntity.uuid, textureUrl) + } + ItemExporter.modifyJson(id) { + val mutJson = it.toMutableMap() + mutJson["island"] = JsonPrimitive(SBData.skyblockLocation?.locrawMode ?: "unknown") + mutJson["x"] = JsonPrimitive(entity.blockX) + mutJson["y"] = JsonPrimitive(entity.blockY) + mutJson["z"] = JsonPrimitive(entity.blockZ) + JsonObject(mutJson) + } + } + } + + @Subscribe + fun onRecipeKeyBind(event: HandledScreenKeyPressedEvent) { + if (!event.matches(PowerUserTools.TConfig.exportUIRecipes)) { + return + } + val title = event.screen.title.string + val sellSlot = event.screen.getSlotByIndex(49, false)?.stack + val craftingTableSlot = event.screen.getSlotByIndex(craftingTableSlut, false) + if (craftingTableSlot?.stack?.displayNameAccordingToNbt?.unformattedString == "Crafting Table") { + slotIndices.forEach { (_, index) -> + event.screen.getSlotByIndex(index, false)?.stack?.let(ItemExporter::ensureExported) + } + val inputs = slotIndices.associate { (name, index) -> + val id = event.screen.getSlotByIndex(index, false)?.stack?.takeIf { !it.isEmpty() }?.let { + "${it.skyBlockId?.neuItem}:${it.count}" + } ?: "" + name to JsonPrimitive(id) + } + val output = event.screen.getSlotByIndex(resultSlot, false)?.stack!! + val overrideOutputId = output.skyBlockId!!.neuItem + val count = output.count + val recipe = JsonObject( + inputs + mapOf( + "type" to JsonPrimitive("crafting"), + "count" to JsonPrimitive(count), + "overrideOutputId" to JsonPrimitive(overrideOutputId) + ) + ) + ItemExporter.appendRecipe(output.skyBlockId!!, recipe) + MC.sendChat(tr("firmament.repo.export.recipe", "Recipe for ${output.skyBlockId} exported.")) + return + } else if (sellSlot?.displayNameAccordingToNbt?.string == "Sell Item" || (sellSlot?.loreAccordingToNbt + ?: listOf()).any { it.string == "Click to buyback!" } + ) { + val shopId = SkyblockId(title.uppercase().replace(" ", "_") + "_NPC") + if (!ItemExporter.isExported(shopId)) { + // TODO: export location + skin of last clicked npc + ItemExporter.exportStub(shopId, "§9$title (NPC)") + } + for (index in (9..9 * 5)) { + val item = event.screen.getSlotByIndex(index, false)?.stack ?: continue + val skyblockId = item.skyBlockId ?: continue + val costLines = item.loreAccordingToNbt + .map { it.string.trim() } + .dropWhile { !it.startsWith("Cost") } + .dropWhile { it == "Cost" } + .takeWhile { it != "Click to trade!" } + .takeWhile { it != "Stock" } + .filter { !it.isBlank() } + .map { it.removePrefix("Cost: ") } + + + val costs = costLines.mapNotNull { lineText -> + val line = findStackableItemByName(lineText) + if (line == null) { + MC.sendChat( + tr( + "firmament.repo.itemshop.fail", + "Could not parse cost item ${lineText} for ${item.displayNameAccordingToNbt}" + ).red() + ) + } + line + } + + + ItemExporter.appendRecipe( + shopId, JsonObject( + mapOf( + "type" to JsonPrimitive("npc_shop"), + "cost" to JsonArray(costs.map { JsonPrimitive("${it.first.neuItem}:${it.second}") }), + "result" to JsonPrimitive("${skyblockId.neuItem}:${item.count}"), + ) + ) + ) + } + MC.sendChat(tr("firmament.repo.export.itemshop", "Item Shop export for ${title} complete.")) + } else { + MC.sendChat(tr("firmament.repo.export.recipe.fail", "No Recipe found")) + } + } + + private val coinRegex = "(?$SHORT_NUMBER_FORMAT) Coins?".toPattern() + private val stackedItemRegex = "(?.*) x(?$SHORT_NUMBER_FORMAT)".toPattern() + private val reverseStackedItemRegex = "(?$SHORT_NUMBER_FORMAT)x (?.*)".toPattern() + private val essenceRegex = "(?.*) Essence x(?$SHORT_NUMBER_FORMAT)".toPattern() + private val numberedItemRegex = "(?$SHORT_NUMBER_FORMAT) (?.*)".toPattern() + + private val etherialRewardPattern = "\\+(?${SHORT_NUMBER_FORMAT})x? (?.*)".toPattern() + + fun findForName(name: String, fallbackToGenerated: Boolean = true): SkyblockId? { + var id = ItemNameLookup.guessItemByName(name, true) + if (id == null && fallbackToGenerated) { + id = generateName(name) + } + return id + } + + fun skill(name: String): SkyblockId { + return SkyblockId("SKYBLOCK_SKILL_${name}") + } + + fun generateName(name: String): SkyblockId { + return SkyblockId(name.uppercase().replace(" ", "_").replace(Regex("[^A-Z_]+"), "")) + } + + fun findStackableItemByName(name: String, fallbackToGenerated: Boolean = false): Pair? { + val properName = name.removeColorCodes().trim() + if (properName == "FREE" || properName == "This Chest is Free!") { + return Pair(SkyBlockItems.COINS, 0.0) + } + coinRegex.useMatch(properName) { + return Pair(SkyBlockItems.COINS, parseShortNumber(group("amount"))) + } + etherialRewardPattern.useMatch(properName) { + val id = when (val id = group("what")) { + "Copper" -> SkyblockId("SKYBLOCK_COPPER") + "Bits" -> SkyblockId("SKYBLOCK_BIT") + "Garden Experience" -> SkyblockId("SKYBLOCK_SKILL_GARDEN") + "Farming XP" -> SkyblockId("SKYBLOCK_SKILL_FARMING") + "Gold Essence" -> SkyblockId("ESSENCE_GOLD") + "Gemstone Powder" -> SkyblockId("SKYBLOCK_POWDER_GEMSTONE") + "Mithril Powder" -> SkyblockId("SKYBLOCK_POWDER_MITHRIL") + "Pelts" -> SkyblockId("SKYBLOCK_PELT") + "Fine Flour" -> SkyblockId("FINE_FLOUR") + else -> { + id.ifDropLast(" Experience") { + skill(generateName(it).neuItem) + } ?: id.ifDropLast(" XP") { + skill(generateName(it).neuItem) + } ?: id.ifDropLast(" Powder") { + SkyblockId("SKYBLOCK_POWDER_${generateName(it).neuItem}") + } ?: id.ifDropLast(" Essence") { + SkyblockId("ESSENCE_${generateName(it).neuItem}") + } ?: generateName(id) + } + } + return Pair(id, parseShortNumber(group("amount"))) + } + essenceRegex.useMatch(properName) { + return Pair( + SkyblockId("ESSENCE_${group("essence").uppercase()}"), + parseShortNumber(group("count")) + ) + } + stackedItemRegex.useMatch(properName) { + val item = findForName(group("name"), fallbackToGenerated) + if (item != null) { + val count = parseShortNumber(group("count")) + return Pair(item, count) + } + } + reverseStackedItemRegex.useMatch(properName) { + val item = findForName(group("name"), fallbackToGenerated) + if (item != null) { + val count = parseShortNumber(group("count")) + return Pair(item, count) + } + } + numberedItemRegex.useMatch(properName) { + val item = findForName(group("what"), fallbackToGenerated) + if (item != null) { + val count = parseShortNumber(group("count")) + return Pair(item, count) + } + } + + return findForName(properName, fallbackToGenerated)?.let { Pair(it, 1.0) } + } + +} diff --git a/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt new file mode 100644 index 0000000..2a56204 --- /dev/null +++ b/src/main/kotlin/features/debug/itemeditor/ItemExporter.kt @@ -0,0 +1,242 @@ +package moe.nea.firmament.features.debug.itemeditor + +import kotlinx.coroutines.launch +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import kotlin.io.path.createParentDirectories +import kotlin.io.path.exists +import kotlin.io.path.notExists +import kotlin.io.path.readText +import kotlin.io.path.relativeTo +import kotlin.io.path.writeText +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.nbt.NbtString +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +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.commands.thenLiteral +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.events.SlotRenderEvents +import moe.nea.firmament.features.debug.DeveloperFeatures +import moe.nea.firmament.features.debug.ExportedTestConstantMeta +import moe.nea.firmament.features.debug.PowerUserTools +import moe.nea.firmament.repo.RepoDownloadManager +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.LegacyTagParser +import moe.nea.firmament.util.LegacyTagWriter.Companion.toLegacyString +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.focusedItemStack +import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.mc.toNbtList +import moe.nea.firmament.util.render.drawGuiTexture +import moe.nea.firmament.util.setSkyBlockId +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.tr + +object ItemExporter { + + fun exportItem(itemStack: ItemStack): Text { + nonOverlayCache.clear() + val exporter = LegacyItemExporter.createExporter(itemStack) + var json = exporter.exportJson() + val fileName = json.jsonObject["internalname"]!!.jsonPrimitive.content + val itemFile = RepoDownloadManager.repoSavedLocation.resolve("items").resolve("${fileName}.json") + itemFile.createParentDirectories() + if (itemFile.exists()) { + val existing = try { + Firmament.json.decodeFromString(itemFile.readText()) + } catch (ex: Exception) { + ex.printStackTrace() + JsonObject(mapOf()) + } + val mut = json.jsonObject.toMutableMap() + for (prop in existing) { + if (prop.key !in mut || mut[prop.key]!!.let { + (it is JsonPrimitive && (it.content.isEmpty() || it.content == "0")) || (it is JsonArray && it.isEmpty()) || (it is JsonObject && it.isEmpty()) + }) + mut[prop.key] = prop.value + } + json = JsonObject(mut) + } + val jsonFormatted = Firmament.twoSpaceJson.encodeToString(json) + itemFile.writeText(jsonFormatted) + val overlayFile = RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay") + .resolve(ExportedTestConstantMeta.current.dataVersion.toString()) + .resolve("${fileName}.snbt") + overlayFile.createParentDirectories() + overlayFile.writeText(exporter.exportModernSnbt().toPrettyString()) + return tr( + "firmament.repoexport.success", + "Exported item to ${itemFile.relativeTo(RepoDownloadManager.repoSavedLocation)}${ + exporter.warnings.joinToString( + "" + ) { "\nWarning: $it" } + }" + ) + } + + fun pathFor(skyBlockId: SkyblockId) = + RepoManager.neuRepo.baseFolder.resolve("items/${skyBlockId.neuItem}.json") + + fun isExported(skyblockId: SkyblockId) = + pathFor(skyblockId).exists() + + fun ensureExported(itemStack: ItemStack) { + if (!isExported(itemStack.skyBlockId ?: return)) + MC.sendChat(exportItem(itemStack)) + } + + fun modifyJson(skyblockId: SkyblockId, modify: (JsonObject) -> JsonObject) { + val oldJson = Firmament.json.decodeFromString(pathFor(skyblockId).readText()) + val newJson = modify(oldJson) + pathFor(skyblockId).writeText(Firmament.twoSpaceJson.encodeToString(JsonObject(newJson))) + } + + fun appendRecipe(skyblockId: SkyblockId, recipe: JsonObject) { + modifyJson(skyblockId) { oldJson -> + val mutableJson = oldJson.toMutableMap() + val recipes = ((mutableJson["recipes"] as JsonArray?) ?: listOf()).toMutableList() + recipes.add(recipe) + mutableJson["recipes"] = JsonArray(recipes) + JsonObject(mutableJson) + } + } + + @Subscribe + fun onCommand(event: CommandEvent.SubCommand) { + event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { + thenLiteral("reexportlore") { + thenArgument("itemid", RestArgumentType) { itemid -> + suggests { ctx, builder -> + val spaceIndex = builder.remaining.lastIndexOf(" ") + val (before, after) = + if (spaceIndex < 0) Pair("", builder.remaining) + else Pair( + builder.remaining.substring(0, spaceIndex + 1), + builder.remaining.substring(spaceIndex + 1) + ) + RepoManager.neuRepo.items.items.keys + .asSequence() + .filter { it.startsWith(after, ignoreCase = true) } + .forEach { + builder.suggest(before + it) + } + + builder.buildFuture() + } + thenExecute { + for (itemid in get(itemid).split(" ").map { SkyblockId(it) }) { + if (pathFor(itemid).notExists()) { + MC.sendChat( + tr( + "firmament.repo.export.relore.fail", + "Could not find json file to relore for ${itemid}" + ) + ) + } + fixLoreNbtFor(itemid) + MC.sendChat( + tr( + "firmament.repo.export.relore", + "Updated lore / display name for $itemid" + ) + ) + } + } + } + thenLiteral("all") { + thenExecute { + var i = 0 + val chunkSize = 100 + val items = RepoManager.neuRepo.items.items.keys + Firmament.coroutineScope.launch { + items.chunked(chunkSize).forEach { key -> + MC.sendChat( + tr( + "firmament.repo.export.relore.progress", + "Updated lore / display for ${i * chunkSize} / ${items.size}." + ) + ) + i++ + key.forEach { + fixLoreNbtFor(SkyblockId(it)) + } + } + MC.sendChat(tr("firmament.repo.export.relore.alldone", "All lores updated.")) + } + } + } + } + } + } + + fun fixLoreNbtFor(itemid: SkyblockId) { + modifyJson(itemid) { + val mutJson = it.toMutableMap() + val legacyTag = LegacyTagParser.parse(mutJson["nbttag"]!!.jsonPrimitive.content) + val display = legacyTag.getCompoundOrEmpty("display") + legacyTag.put("display", display) + display.putString("Name", mutJson["displayname"]!!.jsonPrimitive.content) + display.put( + "Lore", + (mutJson["lore"] as JsonArray).map { NbtString.of(it.jsonPrimitive.content) } + .toNbtList() + ) + mutJson["nbttag"] = JsonPrimitive(legacyTag.toLegacyString()) + JsonObject(mutJson) + } + } + + @Subscribe + fun onKeyBind(event: HandledScreenKeyPressedEvent) { + if (event.matches(PowerUserTools.TConfig.exportItemStackToRepo)) { + val itemStack = event.screen.focusedItemStack ?: return + PowerUserTools.lastCopiedStack = (itemStack to exportItem(itemStack)) + } + } + + val nonOverlayCache = mutableMapOf() + + @Subscribe + fun onRender(event: SlotRenderEvents.Before) { + if (!PowerUserTools.TConfig.highlightNonOverlayItems) { + return + } + val stack = event.slot.stack ?: return + val id = event.slot.stack.skyBlockId?.neuItem + if (PowerUserTools.TConfig.dontHighlightSemicolonItems && id != null && id.contains(";")) return + val isExported = nonOverlayCache.getOrPut(stack.skyBlockId ?: return) { + RepoDownloadManager.repoSavedLocation.resolve("itemsOverlay") + .resolve(ExportedTestConstantMeta.current.dataVersion.toString()) + .resolve("${stack.skyBlockId}.snbt") + .exists() + } + if (!isExported) + event.context.drawGuiTexture( + Firmament.identifier("selected_pet_background"), + event.slot.x, event.slot.y, 16, 16, + ) + } + + fun exportStub(skyblockId: SkyblockId, title: String, extra: (ItemStack) -> Unit = {}) { + exportItem(ItemStack(Items.PLAYER_HEAD).also { + it.displayNameAccordingToNbt = Text.literal(title) + it.loreAccordingToNbt = listOf(Text.literal("")) + it.setSkyBlockId(skyblockId) + extra(it) // LOL + }) + MC.sendChat(tr("firmament.repo.export.stub", "Exported a stub item for $skyblockId")) + } +} diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt new file mode 100644 index 0000000..bc8c618 --- /dev/null +++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt @@ -0,0 +1,89 @@ +package moe.nea.firmament.features.debug.itemeditor + +import kotlinx.serialization.Serializable +import kotlin.jvm.optionals.getOrNull +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtCompound +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.ItemCache +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.StringUtil.camelWords + +/** + * Load data based on [prismarine.js' 1.8 item data](https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/items.json) + */ +object LegacyItemData { + @Serializable + data class ItemData( + val id: Int, + val name: String, + val displayName: String, + val stackSize: Int, + val variations: List = listOf() + ) { + val properId = if (name.contains(":")) name else "minecraft:$name" + + fun allVariants() = + variations.map { LegacyItemType(properId, it.metadata.toShort()) } + LegacyItemType(properId, 0) + } + + @Serializable + data class Variation( + val metadata: Int, val displayName: String + ) + + data class LegacyItemType( + val name: String, + val metadata: Short + ) { + override fun toString(): String { + return "$name:$metadata" + } + } + + @Serializable + data class EnchantmentData( + val id: Int, + val name: String, + val displayName: String, + ) + + inline fun getLegacyData(name: String) = + Firmament.tryDecodeJsonFromStream( + LegacyItemData::class.java.getResourceAsStream("/legacy_data/$name.json")!! + ).getOrThrow() + + val enchantmentData = getLegacyData>("enchantments") + val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) } + + val itemDat = getLegacyData>("items") + + @OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread. + val itemLut = itemDat.flatMap { item -> + item.allVariants().map { legacyItemType -> + val nbt = ItemCache.convert189ToModern(NbtCompound().apply { + putString("id", legacyItemType.name) + putByte("Count", 1) + putShort("Damage", legacyItemType.metadata) + })!! + val stack = ItemStack.fromNbt(MC.defaultRegistries, nbt).getOrNull() + ?: error("Could not transform ${legacyItemType}") + stack.item to legacyItemType + } + }.toMap() + + @Serializable + data class LegacyEffect( + val id: Int, + val name: String, + val displayName: String, + val type: String + ) + + val effectList = getLegacyData>("effects") + .associateBy { + it.name.camelWords().map { it.trim().lowercase() }.joinToString("_") + } +} diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt new file mode 100644 index 0000000..ecf3d2c --- /dev/null +++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt @@ -0,0 +1,311 @@ +package moe.nea.firmament.features.debug.itemeditor + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.buildJsonObject +import kotlinx.serialization.json.put +import kotlin.concurrent.thread +import kotlin.jvm.optionals.getOrNull +import net.minecraft.component.DataComponentTypes +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtByte +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtList +import net.minecraft.nbt.NbtOps +import net.minecraft.nbt.NbtString +import net.minecraft.registry.tag.ItemTags +import net.minecraft.text.Text +import net.minecraft.util.Unit +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ClientStartedEvent +import moe.nea.firmament.features.debug.ExportedTestConstantMeta +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.HypixelPetInfo +import moe.nea.firmament.util.LegacyTagWriter.Companion.toLegacyString +import moe.nea.firmament.util.StringUtil.words +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.extraAttributes +import moe.nea.firmament.util.getLegacyFormatString +import moe.nea.firmament.util.json.toJsonArray +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.mc.toNbtList +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.transformEachRecursively +import moe.nea.firmament.util.unformattedString + +class LegacyItemExporter private constructor(var itemStack: ItemStack) { + init { + require(!itemStack.isEmpty) + itemStack.count = 1 + } + + var lore = itemStack.loreAccordingToNbt + var name = itemStack.displayNameAccordingToNbt + val extraAttribs = itemStack.extraAttributes.copy() + val legacyNbt = NbtCompound() + val warnings = mutableListOf() + + // TODO: check if lore contains non 1.8.9 able hex codes and emit lore in overlay files if so + + fun preprocess() { + // TODO: split up preprocess steps into preprocess actions that can be toggled in a ui + extraAttribs.remove("timestamp") + extraAttribs.remove("uuid") + extraAttribs.remove("modifier") + extraAttribs.getString("petInfo").ifPresent { petInfoJson -> + var petInfo = Firmament.json.decodeFromString(petInfoJson) + petInfo = petInfo.copy(candyUsed = 0, heldItem = null, exp = 0.0, active = null, uuid = null) + extraAttribs.putString("petInfo", Firmament.tightJson.encodeToString(petInfo)) + } + itemStack.skyBlockId?.let { + extraAttribs.putString("id", it.neuItem) + } + trimLore() + itemStack.loreAccordingToNbt = itemStack.item.defaultStack.loreAccordingToNbt + itemStack.remove(DataComponentTypes.CUSTOM_NAME) + } + + fun trimLore() { + val rarityIdx = lore.indexOfLast { + val firstWordInLine = it.unformattedString.words().filter { it.length > 2 }.firstOrNull() + firstWordInLine?.let(Rarity::fromString) != null + } + if (rarityIdx >= 0) { + lore = lore.subList(0, rarityIdx + 1) + } + + trimStats() + + deleteLineUntilNextSpace { it.startsWith("Held Item: ") } + deleteLineUntilNextSpace { it.startsWith("Progress to Level ") } + deleteLineUntilNextSpace { it.startsWith("MAX LEVEL") } + deleteLineUntilNextSpace { it.startsWith("Click to view recipe!") } + collapseWhitespaces() + + name = name.transformEachRecursively { + var string = it.directLiteralStringContent ?: return@transformEachRecursively it + string = string.replace("Lvl \\d+".toRegex(), "Lvl {LVL}") + Text.literal(string).setStyle(it.style) + } + + if (lore.isEmpty()) + lore = listOf(Text.empty()) + } + + private fun trimStats() { + val lore = this.lore.toMutableList() + for (index in lore.indices) { + val value = lore[index] + val statLine = SBItemStack.parseStatLine(value) + if (statLine == null) break + val v = value.copy() + require(value.directLiteralStringContent == "") + v.siblings.removeIf { it.directLiteralStringContent!!.contains("(") } + val last = v.siblings.last() + v.siblings[v.siblings.lastIndex] = + Text.literal(last.directLiteralStringContent!!.trimEnd()) + .setStyle(last.style) + lore[index] = v + } + this.lore = lore + } + + fun collapseWhitespaces() { + lore = (listOf(null as Text?) + lore).zipWithNext() + .filter { !it.first?.unformattedString.isNullOrBlank() || !it.second?.unformattedString.isNullOrBlank() } + .map { it.second!! } + } + + fun deleteLineUntilNextSpace(search: (String) -> Boolean) { + val idx = lore.indexOfFirst { search(it.unformattedString) } + if (idx < 0) return + val l = lore.toMutableList() + val p = l.subList(idx, l.size) + val nextBlank = p.indexOfFirst { it.unformattedString.isEmpty() } + if (nextBlank < 0) + p.clear() + else + p.subList(0, nextBlank).clear() + lore = l + } + + fun processNbt() { + // TODO: calculate hideflags + legacyNbt.put("HideFlags", NbtInt.of(254)) + copyUnbreakable() + copyItemModel() + copyPotion() + copyExtraAttributes() + copyLegacySkullNbt() + copyDisplay() + copyColour() + copyEnchantments() + copyEnchantGlint() + // TODO: copyDisplay + } + + private fun copyPotion() { + val effects = itemStack.get(DataComponentTypes.POTION_CONTENTS) ?: return + legacyNbt.put("CustomPotionEffects", NbtList().also { + effects.effects.forEach { effect -> + val effectId = effect.effectType.key.get().value.path + val duration = effect.duration + val legacyId = LegacyItemData.effectList[effectId]!! + + it.add(NbtCompound().apply { + put("Ambient", NbtByte.of(false)) + put("Duration", NbtInt.of(duration)) + put("Id", NbtByte.of(legacyId.id.toByte())) + put("Amplifier", NbtByte.of(effect.amplifier.toByte())) + }) + } + }) + } + + fun NbtCompound.getOrPutCompound(name: String): NbtCompound { + val compound = getCompoundOrEmpty(name) + put(name, compound) + return compound + } + + private fun copyColour() { + if (!itemStack.isIn(ItemTags.DYEABLE)) { + itemStack.remove(DataComponentTypes.DYED_COLOR) + return + } + val leatherTint = itemStack.componentChanges.get(DataComponentTypes.DYED_COLOR)?.getOrNull() ?: return + legacyNbt.getOrPutCompound("display").put("color", NbtInt.of(leatherTint.rgb)) + } + + private fun copyItemModel() { + val itemModel = itemStack.get(DataComponentTypes.ITEM_MODEL) ?: return + legacyNbt.put("ItemModel", NbtString.of(itemModel.toString())) + } + + private fun copyDisplay() { + legacyNbt.getOrPutCompound("display").apply { + put("Lore", lore.map { NbtString.of(it.getLegacyFormatString(trimmed = true)) }.toNbtList()) + putString("Name", name.getLegacyFormatString(trimmed = true)) + } + } + + fun exportModernSnbt(): NbtElement { + val overlay = ItemStack.CODEC.encodeStart(NbtOps.INSTANCE, itemStack) + .orThrow + val overlayWithVersion = + ExportedTestConstantMeta.SOURCE_CODEC.encode(ExportedTestConstantMeta.current, NbtOps.INSTANCE, overlay) + .orThrow + return overlayWithVersion + } + + fun prepare() { + preprocess() + processNbt() + itemStack.extraAttributes = extraAttribs + } + + fun exportJson(): JsonElement { + return buildJsonObject { + val (itemId, damage) = legacyifyItemStack() + put("itemid", itemId) + put("displayname", name.getLegacyFormatString(trimmed = true)) + put("nbttag", legacyNbt.toLegacyString()) + put("damage", damage) + put("lore", lore.map { it.getLegacyFormatString(trimmed = true) }.toJsonArray()) + val sbId = itemStack.skyBlockId + if (sbId == null) + warnings.add("Could not find skyblock id") + put("internalname", sbId?.neuItem) + put("clickcommand", "") + put("crafttext", "") + put("modver", "Firmament ${Firmament.version.friendlyString}") + put("infoType", "") + put("info", JsonArray(listOf())) + } + + } + + companion object { + fun createExporter(itemStack: ItemStack): LegacyItemExporter { + return LegacyItemExporter(itemStack.copy()).also { it.prepare() } + } + + @Subscribe + fun load(event: ClientStartedEvent) { + thread(start = true, name = "ItemExporter Meta Load Thread") { + LegacyItemData.itemLut + } + } + } + + fun copyEnchantGlint() { + if (itemStack.get(DataComponentTypes.ENCHANTMENT_GLINT_OVERRIDE) == true) { + val ench = legacyNbt.getListOrEmpty("ench") + legacyNbt.put("ench", ench) + } + } + + private fun copyUnbreakable() { + if (itemStack.get(DataComponentTypes.UNBREAKABLE) == Unit.INSTANCE) { + legacyNbt.putBoolean("Unbreakable", true) + } + } + + fun copyEnchantments() { + val enchantments = itemStack.get(DataComponentTypes.ENCHANTMENTS)?.takeIf { !it.isEmpty } ?: return + val enchTag = legacyNbt.getListOrEmpty("ench") + legacyNbt.put("ench", enchTag) + enchantments.enchantmentEntries.forEach { entry -> + val id = entry.key.key.get().value + val legacyId = LegacyItemData.enchantmentLut[id] + if (legacyId == null) { + warnings.add("Could not find legacy enchantment id for ${id}") + return@forEach + } + enchTag.add(NbtCompound().apply { + putShort("lvl", entry.intValue.toShort()) + putShort( + "id", + legacyId.id.toShort() + ) + }) + } + } + + fun copyExtraAttributes() { + legacyNbt.put("ExtraAttributes", extraAttribs) + } + + fun copyLegacySkullNbt() { + val profile = itemStack.get(DataComponentTypes.PROFILE) ?: return + legacyNbt.put("SkullOwner", NbtCompound().apply { + profile.id.ifPresent { + putString("Id", it.toString()) + } + putBoolean("hypixelPopulated", true) + put("Properties", NbtCompound().apply { + profile.properties().forEach { prop, value -> + val list = getListOrEmpty(prop) + put(prop, list) + list.add(NbtCompound().apply { + value.signature?.let { + putString("Signature", it) + } + putString("Value", value.value) + putString("Name", value.name) + }) + } + }) + }) + } + + fun legacyifyItemStack(): LegacyItemData.LegacyItemType { + // TODO: add a default here + return LegacyItemData.itemLut[itemStack.item]!! + } +} diff --git a/src/main/kotlin/features/debug/itemeditor/PromptScreen.kt b/src/main/kotlin/features/debug/itemeditor/PromptScreen.kt new file mode 100644 index 0000000..187b70b --- /dev/null +++ b/src/main/kotlin/features/debug/itemeditor/PromptScreen.kt @@ -0,0 +1,15 @@ +package moe.nea.firmament.features.debug.itemeditor + +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.TextComponent +import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent +import io.github.notenoughupdates.moulconfig.observer.GetSetter +import kotlin.reflect.KMutableProperty0 +import moe.nea.firmament.gui.FirmButtonComponent +import moe.nea.firmament.util.MoulConfigUtils + diff --git a/src/main/kotlin/features/diana/AncestralSpadeSolver.kt b/src/main/kotlin/features/diana/AncestralSpadeSolver.kt new file mode 100644 index 0000000..ff85c00 --- /dev/null +++ b/src/main/kotlin/features/diana/AncestralSpadeSolver.kt @@ -0,0 +1,131 @@ +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 +import moe.nea.firmament.util.skyblock.SkyBlockItems + +object AncestralSpadeSolver : SubscriptionOwner { + var lastDing = TimeMark.farPast() + private set + private val pitches = mutableListOf() + val particlePositions = mutableListOf() + var nextGuess: Vec3d? = null + private set + + private var lastTeleportAttempt = TimeMark.farPast() + + fun isEnabled() = + DianaWaypoints.TConfig.ancestralSpadeSolver + && SBData.skyblockLocation == SkyBlockIsland.HUB + && MC.player?.inventory?.containsAny { it.skyBlockId == SkyBlockItems.ANCESTRAL_SPADE } == 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 { + tinyBlock(it, 1f, 0x80FFFFFF.toInt()) + // TODO: replace this + color(1f, 1f, 0f, 1f) + tracer(it, lineWidth = 3f) + } + if (particlePositions.size > 2 && lastDing.passedTime() < 10.seconds && nextGuess != null) { + // TODO: replace this // TODO: add toggle + 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/features/diana/DianaWaypoints.kt b/src/main/kotlin/features/diana/DianaWaypoints.kt new file mode 100644 index 0000000..6d87262 --- /dev/null +++ b/src/main/kotlin/features/diana/DianaWaypoints.kt @@ -0,0 +1,31 @@ +package moe.nea.firmament.features.diana + +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.AttackBlockEvent +import moe.nea.firmament.events.UseBlockEvent +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, Category.EVENTS) { + val ancestralSpadeSolver by toggle("ancestral-spade") { true } + val ancestralSpadeTeleport by keyBindingWithDefaultUnbound("ancestral-teleport") + val nearbyWaypoints by toggle("nearby-waypoints") { true } + } + + + @Subscribe + fun onBlockUse(event: UseBlockEvent) { + NearbyBurrowsSolver.onBlockClick(event.hitResult.blockPos) + } + + @Subscribe + fun onBlockAttack(event: AttackBlockEvent) { + NearbyBurrowsSolver.onBlockClick(event.blockPos) + } +} + + diff --git a/src/main/kotlin/features/diana/NearbyBurrowsSolver.kt b/src/main/kotlin/features/diana/NearbyBurrowsSolver.kt new file mode 100644 index 0000000..2fb4002 --- /dev/null +++ b/src/main/kotlin/features/diana/NearbyBurrowsSolver.kt @@ -0,0 +1,144 @@ +package moe.nea.firmament.features.diana + +import me.shedaniel.math.Color +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.collections.mutableMapWithMaxSize +import moe.nea.firmament.util.render.RenderInWorldContext.Companion.renderInWorld + +object NearbyBurrowsSolver : SubscriptionOwner { + + + private val recentlyDugBurrows: MutableMap = mutableMapWithMaxSize(20) + private val recentEnchantParticles: MutableMap = mutableMapWithMaxSize(500) + private var lastBlockClick: BlockPos? = null + + enum class BurrowType { + START, MOB, TREASURE + } + + val burrows = mutableMapOf() + + @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) { + val color = when (burrow) { + BurrowType.START -> Color.ofRGBA(.2f, .8f, .2f, 0.4f) + BurrowType.MOB -> Color.ofRGBA(0.3f, 0.4f, 0.9f, 0.4f) + BurrowType.TREASURE -> Color.ofRGBA(1f, 0.7f, 0.2f, 0.4f) + } + block(location, color.color) + } + } + } + + @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/features/events/anniversity/AnniversaryFeatures.kt b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt new file mode 100644 index 0000000..0cfaeba --- /dev/null +++ b/src/main/kotlin/features/events/anniversity/AnniversaryFeatures.kt @@ -0,0 +1,226 @@ + +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.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.ItemNameLookup +import moe.nea.firmament.repo.SBItemStack +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, Category.EVENTS) { + 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(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 (?.*) 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() + + fun ObservableList.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 = "\\+(?$SHORT_NUMBER_FORMAT) (?[^ ]+) XP".toPattern() + val coinReward = "\\+(?$SHORT_NUMBER_FORMAT) coins".toPattern() + val itemReward = "(?:(?[0-9]+)x )?(?.*)".toPattern() + fun parseReward(string: String): Reward { + expReward.useMatch(string) { + val exp = parseShortNumber(group("exp")) + val kind = group("kind") + return Reward.EXP(exp, kind) + } + coinReward.useMatch(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) { + SBItemStack(backedBy.item, backedBy.amount) + } else { + SBItemStack(SkyblockId.NULL) + } + + @OptIn(ExpensiveItemCacheApi::class) + @Bind + fun name(): String { + return when (backedBy) { + is Reward.Coins -> "Coins" + is Reward.EXP -> backedBy.skill + is Reward.Items -> itemStack.asImmutableItemStack().name.string + is Reward.Unknown -> backedBy.text + } + } + + @Bind + fun isKnown() = backedBy !is Reward.Unknown + } + + @get:Bind("rewards") + val rewards = ObservableList(mutableListOf()) + + } + +} diff --git a/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt b/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt new file mode 100644 index 0000000..9935051 --- /dev/null +++ b/src/main/kotlin/features/events/anniversity/CenturyRaffleFeatures.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.features.events.anniversity + +import java.util.Optional +import me.shedaniel.math.Color +import kotlin.jvm.optionals.getOrNull +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.text.Style +import net.minecraft.util.Formatting +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.EntityRenderTintEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.render.TintedOverlayTexture +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems + +object CenturyRaffleFeatures { + object TConfig : ManagedConfig("centuryraffle", Category.EVENTS) { + val highlightPlayersForSlice by toggle("highlight-cake-players") { true } +// val highlightAllPlayers by toggle("highlight-all-cake-players") { true } + } + + val cakeIcon = "⛃" + + val cakeColors = listOf( + CakeTeam(SkyBlockItems.SLICE_OF_BLUEBERRY_CAKE, Formatting.BLUE), + CakeTeam(SkyBlockItems.SLICE_OF_CHEESECAKE, Formatting.YELLOW), + CakeTeam(SkyBlockItems.SLICE_OF_GREEN_VELVET_CAKE, Formatting.GREEN), + CakeTeam(SkyBlockItems.SLICE_OF_RED_VELVET_CAKE, Formatting.RED), + CakeTeam(SkyBlockItems.SLICE_OF_STRAWBERRY_SHORTCAKE, Formatting.LIGHT_PURPLE), + ) + + data class CakeTeam( + val id: SkyblockId, + val formatting: Formatting, + ) { + val searchedTextRgb = formatting.colorValue!! + val brightenedRgb = Color.ofOpaque(searchedTextRgb)//.brighter(2.0) + val tintOverlay by lazy { + TintedOverlayTexture().setColor(brightenedRgb) + } + } + + val sliceToColor = cakeColors.associateBy { it.id } + + @Subscribe + fun onEntityRender(event: EntityRenderTintEvent) { + if (!TConfig.highlightPlayersForSlice) return + val requestedCakeTeam = sliceToColor[MC.stackInHand?.skyBlockId] ?: return + // TODO: cache the requested color + val player = event.entity as? PlayerEntity ?: return + val cakeColor: Style = player.styledDisplayName.visit( + { style, text -> + if (text == cakeIcon) Optional.of(style) + else Optional.empty() + }, Style.EMPTY).getOrNull() ?: return + if (cakeColor.color?.rgb == requestedCakeTeam.searchedTextRgb) { + event.renderState.overlayTexture_firmament = requestedCakeTeam.tintOverlay + } + } + +} diff --git a/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt b/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt new file mode 100644 index 0000000..840fb8c --- /dev/null +++ b/src/main/kotlin/features/events/carnival/CarnivalFeatures.kt @@ -0,0 +1,17 @@ + +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, Category.EVENTS) { + 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/features/events/carnival/MinesweeperHelper.kt b/src/main/kotlin/features/events/carnival/MinesweeperHelper.kt new file mode 100644 index 0000000..cfc05cc --- /dev/null +++ b/src/main/kotlin/features/events/carnival/MinesweeperHelper.kt @@ -0,0 +1,276 @@ + +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.mc.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) (?[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 = mutableMapOf(), + val knownBombPositions: MutableSet = 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.RunCommand("/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.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/features/fixes/CompatibliltyFeatures.kt b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt new file mode 100644 index 0000000..76f6ed4 --- /dev/null +++ b/src/main/kotlin/features/fixes/CompatibliltyFeatures.kt @@ -0,0 +1,41 @@ +package moe.nea.firmament.features.fixes + +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.compatloader.CompatLoader + +object CompatibliltyFeatures : FirmamentFeature { + override val identifier: String + get() = "compatibility" + + object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) { + 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) + + companion object : CompatLoader(ExplosiveApiWrapper::class.java) + } + + private val explosiveApiWrapper = ExplosiveApiWrapper.singleInstance + + @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/features/fixes/Fixes.kt b/src/main/kotlin/features/fixes/Fixes.kt new file mode 100644 index 0000000..0105624 --- /dev/null +++ b/src/main/kotlin/features/fixes/Fixes.kt @@ -0,0 +1,82 @@ +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.text.Text +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.tr + +object Fixes : FirmamentFeature { + override val identifier: String + get() = "fixes" + + object TConfig : ManagedConfig(identifier, Category.MISC) { // TODO: split this config + val fixUnsignedPlayerSkins by toggle("player-skins") { true } + var autoSprint by toggle("auto-sprint") { false } + val autoSprintKeyBinding by keyBindingWithDefaultUnbound("auto-sprint-keybinding") + val autoSprintUnderWater by toggle("auto-sprint-underwater") { true } + val autoSprintHud by position("auto-sprint-hud", 80, 10) { Point(0.0, 1.0) } + val peekChat by keyBindingWithDefaultUnbound("peek-chat") + val hidePotionEffects by toggle("hide-mob-effects") { false } + val hidePotionEffectsHud by toggle("hide-potion-effects-hud") { false } + val noHurtCam by toggle("disable-hurt-cam") { false } + val hideSlotHighlights by toggle("hide-slot-highlights") { false } + val hideRecipeBook by toggle("hide-recipe-book") { false } + val hideOffHand by toggle("hide-off-hand") { false } + } + + override val config: ManagedConfig + get() = TConfig + + fun handleIsPressed( + keyBinding: KeyBinding, + cir: CallbackInfoReturnable + ) { + if (keyBinding !== MinecraftClient.getInstance().options.sprintKey) return + if (!TConfig.autoSprint) return + val player = MC.player ?: return + if (player.isSprinting) return + if (!TConfig.autoSprintUnderWater && player.isTouchingWater) return + 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, ( + if (MC.player?.isSprinting == true) { + Text.translatable("firmament.fixes.auto-sprint.sprinting") + } else if (TConfig.autoSprint) { + if (!TConfig.autoSprintUnderWater && MC.player?.isTouchingWater == true) + tr("firmament.fixes.auto-sprint.under-water", "In Water") + else + Text.translatable("firmament.fixes.auto-sprint.on") + } else { + Text.translatable("firmament.fixes.auto-sprint.not-sprinting") + } + ), 0, 0, -1, true + ) + 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/features/garden/HideComposterNoises.kt b/src/main/kotlin/features/garden/HideComposterNoises.kt new file mode 100644 index 0000000..69207a9 --- /dev/null +++ b/src/main/kotlin/features/garden/HideComposterNoises.kt @@ -0,0 +1,32 @@ +package moe.nea.firmament.features.garden + +import net.minecraft.entity.passive.WolfSoundVariants +import net.minecraft.sound.SoundEvent +import net.minecraft.sound.SoundEvents +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.SoundReceiveEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.SkyBlockIsland + +object HideComposterNoises { + object TConfig : ManagedConfig("composter", Category.GARDEN) { + val hideComposterNoises by toggle("no-more-noises") { false } + } + + val composterSoundEvents: List = listOf( + SoundEvents.BLOCK_PISTON_EXTEND, + SoundEvents.BLOCK_WATER_AMBIENT, + SoundEvents.ENTITY_CHICKEN_EGG, + SoundEvents.WOLF_SOUNDS[WolfSoundVariants.Type.CLASSIC]!!.growlSound().value(), + ) + + @Subscribe + fun onNoise(event: SoundReceiveEvent) { + if (!TConfig.hideComposterNoises) return + if (SBData.skyblockLocation == SkyBlockIsland.GARDEN) { + if (event.sound.value() in composterSoundEvents) + event.cancel() + } + } +} diff --git a/src/main/kotlin/features/inventory/CraftingOverlay.kt b/src/main/kotlin/features/inventory/CraftingOverlay.kt new file mode 100644 index 0000000..f823086 --- /dev/null +++ b/src/main/kotlin/features/inventory/CraftingOverlay.kt @@ -0,0 +1,83 @@ +package moe.nea.firmament.features.inventory + +import io.github.moulberry.repo.data.NEUCraftingRecipe +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.ScreenChangeEvent +import moe.nea.firmament.events.SlotRenderEvents +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.skyblockId + +object CraftingOverlay : FirmamentFeature { + + private var screen: GenericContainerScreen? = null + private var recipe: NEUCraftingRecipe? = null + private var useNextScreen = false + private val craftingOverlayIndices = listOf( + 10, 11, 12, + 19, 20, 21, + 28, 29, 30, + ) + val CRAFTING_SCREEN_NAME = "Craft Item" + + fun setOverlay(screen: GenericContainerScreen?, recipe: NEUCraftingRecipe) { + this.screen = screen + if (screen == null) { + useNextScreen = true + } + this.recipe = recipe + } + + @Subscribe + fun onScreenChange(event: ScreenChangeEvent) { + if (useNextScreen && event.new is GenericContainerScreen + && event.new.title?.string == "Craft Item" + ) { + useNextScreen = false + screen = event.new + } + } + + override val identifier: String + get() = "crafting-overlay" + + @OptIn(ExpensiveItemCacheApi::class) + @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.inputs[recipeIndex] + val actualStack = slot.stack ?: ItemStack.EMPTY!! + val actualEntry = SBItemStack(actualStack) + if ((actualEntry.skyblockId != expectedItem.skyblockId || 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 = SBItemStack(expectedItem)?.asImmutableItemStack() ?: return + event.context.drawItem(itemStack, event.slot.x, event.slot.y) + event.context.drawStackOverlay( + MC.font, + itemStack, + event.slot.x, + event.slot.y, + "${Formatting.RED}${expectedItem.amount.toInt()}" + ) + } + } +} diff --git a/src/main/kotlin/features/inventory/ItemHotkeys.kt b/src/main/kotlin/features/inventory/ItemHotkeys.kt new file mode 100644 index 0000000..e826b31 --- /dev/null +++ b/src/main/kotlin/features/inventory/ItemHotkeys.kt @@ -0,0 +1,42 @@ +package moe.nea.firmament.features.inventory + +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.HypixelStaticData +import moe.nea.firmament.repo.ItemCache +import moe.nea.firmament.repo.ItemCache.asItemStack +import moe.nea.firmament.repo.ItemCache.isBroken +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.asBazaarStock +import moe.nea.firmament.util.focusedItemStack +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SBItemUtil.getSearchName + +object ItemHotkeys { + object TConfig : ManagedConfig("item-hotkeys", Category.INVENTORY) { + val openGlobalTradeInterface by keyBindingWithDefaultUnbound("global-trade-interface") + } + + @OptIn(ExpensiveItemCacheApi::class) + @Subscribe + fun onHandledInventoryPress(event: HandledScreenKeyPressedEvent) { + if (!event.matches(TConfig.openGlobalTradeInterface)) { + return + } + var item = event.screen.focusedItemStack ?: return + val skyblockId = item.skyBlockId ?: return + item = RepoManager.getNEUItem(skyblockId)?.asItemStack()?.takeIf { !it.isBroken } ?: item + if (HypixelStaticData.hasBazaarStock(skyblockId.asBazaarStock)) { + MC.sendCommand("bz ${item.getSearchName()}") + } else if (HypixelStaticData.hasAuctionHouseOffers(skyblockId)) { + MC.sendCommand("ahs ${item.getSearchName()}") + } else { + return + } + event.cancel() + } + +} diff --git a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt new file mode 100644 index 0000000..fdc378a --- /dev/null +++ b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.features.inventory + +import java.awt.Color +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.render.RenderLayer +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.collections.lastNotNullOfOrNull +import moe.nea.firmament.util.collections.memoizeIdentity +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.unformattedString + +object ItemRarityCosmetics : FirmamentFeature { + override val identifier: String + get() = "item-rarity-cosmetics" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val showItemRarityBackground by toggle("background") { false } + val showItemRarityInHotbar by toggle("background-hotbar") { false } + } + + override val config: ManagedConfig + get() = TConfig + + private val rarityToColor = Rarity.colourMap.mapValues { + val c = Color(it.value.colorValue!!) + c.rgb + } + + fun drawItemStackRarity(drawContext: DrawContext, x: Int, y: Int, item: ItemStack) { + val rarity = Rarity.fromItem(item) ?: return + val rgb = rarityToColor[rarity] ?: 0xFF00FF80.toInt() + drawContext.drawGuiTexture( + RenderLayer::getGuiTextured, + Identifier.of("firmament:item_rarity_background"), + x, y, + 16, 16, + rgb + ) + } + + + @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/features/inventory/JunkHighlighter.kt b/src/main/kotlin/features/inventory/JunkHighlighter.kt new file mode 100644 index 0000000..80fd99d --- /dev/null +++ b/src/main/kotlin/features/inventory/JunkHighlighter.kt @@ -0,0 +1,29 @@ +package moe.nea.firmament.features.inventory + +import org.lwjgl.glfw.GLFW +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.SlotRenderEvents +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.skyblock.SBItemUtil.getSearchName +import moe.nea.firmament.util.useMatch + +object JunkHighlighter : FirmamentFeature { + override val identifier: String + get() = "junk-highlighter" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val junkRegex by string("regex") { "" } + val highlightBind by keyBinding("highlight") { GLFW.GLFW_KEY_LEFT_CONTROL } + } + + @Subscribe + fun onDrawSlot(event: SlotRenderEvents.After) { + if(!TConfig.highlightBind.isPressed() || TConfig.junkRegex.isEmpty()) return + val junkRegex = TConfig.junkRegex.toPattern() + val slot = event.slot + junkRegex.useMatch(slot.stack.getSearchName()) { + event.context.fill(slot.x, slot.y, slot.x + 16, slot.y + 16, 0xffff0000.toInt()) + } + } +} diff --git a/src/main/kotlin/features/inventory/PetFeatures.kt b/src/main/kotlin/features/inventory/PetFeatures.kt new file mode 100644 index 0000000..9393b03 --- /dev/null +++ b/src/main/kotlin/features/inventory/PetFeatures.kt @@ -0,0 +1,86 @@ +package moe.nea.firmament.features.inventory + +import moe.nea.jarvis.api.Point +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Formatting +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.events.SlotRenderEvents +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.FirmFormatters.formatPercent +import moe.nea.firmament.util.FirmFormatters.shortFormat +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.petData +import moe.nea.firmament.util.render.drawGuiTexture +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.titleCase +import moe.nea.firmament.util.useMatch +import moe.nea.firmament.util.withColor + +object PetFeatures : FirmamentFeature { + override val identifier: String + get() = "pets" + + override val config: ManagedConfig? + get() = TConfig + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val highlightEquippedPet by toggle("highlight-pet") { true } + var petOverlay by toggle("pet-overlay") { false } + val petOverlayHud by position("pet-overlay-hud", 80, 10) { Point(0.5, 1.0) } + } + + val petMenuTitle = "Pets(?: \\([0-9]+/[0-9]+\\))?".toPattern() + var petItemStack: ItemStack? = null + + @Subscribe + fun onSlotRender(event: SlotRenderEvents.Before) { + if (!TConfig.highlightEquippedPet) return + val stack = event.slot.stack + if (stack.petData?.active == true) + petMenuTitle.useMatch(MC.screenName ?: return) { + petItemStack = stack + event.context.drawGuiTexture( + Firmament.identifier("selected_pet_background"), + event.slot.x, event.slot.y, 16, 16, + ) + } + } + + @Subscribe + fun onRenderHud(it: HudRenderEvent) { + if (!TConfig.petOverlay || !SBData.isOnSkyblock) return + val itemStack = petItemStack ?: return + val petData = petItemStack?.petData ?: return + val rarity = Rarity.fromNeuRepo(petData.tier) + val rarityCode = Rarity.colourMap[rarity] ?: Formatting.WHITE + val xp = petData.level + val petType = titleCase(petData.type) + val heldItem = petData.heldItem?.let { item -> "Held Item: ${titleCase(item)}" } + + it.context.matrices.push() + TConfig.petOverlayHud.applyTransformations(it.context.matrices) + + val lines = mutableListOf() + it.context.matrices.push() + it.context.matrices.translate(-0.5, -0.5, 0.0) + it.context.matrices.scale(2f, 2f, 1f) + it.context.drawItem(itemStack, 0, 0) + it.context.matrices.pop() + + lines.add(Text.literal("[Lvl ${xp.currentLevel}] ").append(Text.literal(petType).withColor(rarityCode))) + if (heldItem != null) lines.add(Text.literal(heldItem)) + if (xp.currentLevel != xp.maxLevel) lines.add(Text.literal("Required L${xp.currentLevel + 1}: ${shortFormat(xp.expInCurrentLevel.toDouble())}/${shortFormat(xp.expRequiredForNextLevel.toDouble())} (${formatPercent(xp.percentageToNextLevel.toDouble())})")) + lines.add(Text.literal("Required L100: ${shortFormat(xp.expTotal.toDouble())}/${shortFormat(xp.expRequiredForMaxLevel.toDouble())} (${formatPercent(xp.percentageToMaxLevel.toDouble())})")) + + for ((index, line) in lines.withIndex()) { + it.context.drawText(MC.font, line.copy().withColor(Formatting.GRAY), 36, MC.font.fontHeight * index, -1, true) + } + + it.context.matrices.pop() + } +} diff --git a/src/main/kotlin/features/inventory/PriceData.kt b/src/main/kotlin/features/inventory/PriceData.kt new file mode 100644 index 0000000..241fb43 --- /dev/null +++ b/src/main/kotlin/features/inventory/PriceData.kt @@ -0,0 +1,120 @@ +package moe.nea.firmament.features.inventory + +import org.lwjgl.glfw.GLFW +import net.minecraft.text.Text +import net.minecraft.util.StringIdentifiable +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.formatCommas +import moe.nea.firmament.util.asBazaarStock +import moe.nea.firmament.util.bold +import moe.nea.firmament.util.darkGrey +import moe.nea.firmament.util.gold +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.yellow + +object PriceData : FirmamentFeature { + override val identifier: String + get() = "price-data" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val tooltipEnabled by toggle("enable-always") { true } + val enableKeybinding by keyBindingWithDefaultUnbound("enable-keybind") + val stackSizeKey by keyBinding("stack-size-keybind") { GLFW.GLFW_KEY_LEFT_SHIFT } + val avgLowestBin by choice( + "avg-lowest-bin-days", + ) { + AvgLowestBin.THREEDAYAVGLOWESTBIN + } + } + + enum class AvgLowestBin : StringIdentifiable { + OFF, + ONEDAYAVGLOWESTBIN, + THREEDAYAVGLOWESTBIN, + SEVENDAYAVGLOWESTBIN; + + override fun asString(): String { + return name + } + } + + override val config get() = TConfig + + fun formatPrice(label: Text, price: Double): Text { + return Text.literal("") + .yellow() + .bold() + .append(label) + .append(": ") + .append( + Text.literal(formatCommas(price, fractionalDigits = 1)) + .append(if (price != 1.0) " coins" else " coin") + .gold() + .bold() + ) + } + + @Subscribe + fun onItemTooltip(it: ItemTooltipEvent) { + if (!TConfig.tooltipEnabled) return + if (TConfig.enableKeybinding.isBound && !TConfig.enableKeybinding.isPressed()) return + val sbId = it.stack.skyBlockId + val stackSize = it.stack.count + val isShowingStack = TConfig.stackSizeKey.isPressed() + val multiplier = if (isShowingStack) stackSize else 1 + val multiplierText = + if (isShowingStack) + tr("firmament.tooltip.multiply", "Showing prices for x${stackSize}").darkGrey() + else + tr( + "firmament.tooltip.multiply.hint", + "[${TConfig.stackSizeKey.format()}] to show x${stackSize}" + ).darkGrey() + val bazaarData = HypixelStaticData.bazaarData[sbId?.asBazaarStock] + val lowestBin = HypixelStaticData.lowestBin[sbId] + val avgBinValue: Double? = when (TConfig.avgLowestBin) { + AvgLowestBin.ONEDAYAVGLOWESTBIN -> HypixelStaticData.avg1dlowestBin[sbId] + AvgLowestBin.THREEDAYAVGLOWESTBIN -> HypixelStaticData.avg3dlowestBin[sbId] + AvgLowestBin.SEVENDAYAVGLOWESTBIN -> HypixelStaticData.avg7dlowestBin[sbId] + AvgLowestBin.OFF -> null + } + if (bazaarData != null) { + it.lines.add(Text.literal("")) + it.lines.add(multiplierText) + it.lines.add( + formatPrice( + tr("firmament.tooltip.bazaar.buy-order", "Bazaar Buy Order"), + bazaarData.quickStatus.sellPrice * multiplier + ) + ) + it.lines.add( + formatPrice( + tr("firmament.tooltip.bazaar.sell-order", "Bazaar Sell Order"), + bazaarData.quickStatus.buyPrice * multiplier + ) + ) + } else if (lowestBin != null) { + it.lines.add(Text.literal("")) + it.lines.add(multiplierText) + it.lines.add( + formatPrice( + tr("firmament.tooltip.ah.lowestbin", "Lowest BIN"), + lowestBin * multiplier + ) + ) + if (avgBinValue != null) { + it.lines.add( + formatPrice( + tr("firmament.tooltip.ah.avg-lowestbin", "AVG Lowest BIN"), + avgBinValue * multiplier + ) + ) + } + } + } +} diff --git a/src/main/kotlin/features/inventory/REIDependencyWarner.kt b/src/main/kotlin/features/inventory/REIDependencyWarner.kt new file mode 100644 index 0000000..476759a --- /dev/null +++ b/src/main/kotlin/features/inventory/REIDependencyWarner.kt @@ -0,0 +1,85 @@ +package moe.nea.firmament.features.inventory + +import java.net.URI +import net.fabricmc.loader.api.FabricLoader +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlin.time.Duration.Companion.seconds +import net.minecraft.SharedConstants +import net.minecraft.text.ClickEvent +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.SkyblockServerUpdateEvent +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.aqua +import moe.nea.firmament.util.bold +import moe.nea.firmament.util.clickCommand +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.lime +import moe.nea.firmament.util.red +import moe.nea.firmament.util.white +import moe.nea.firmament.util.yellow + +object REIDependencyWarner { + val reiModId = "roughlyenoughitems" + val hasREI = FabricLoader.getInstance().isModLoaded(reiModId) + var sentWarning = false + + fun modrinthLink(slug: String) = + "https://modrinth.com/mod/$slug/versions?g=${SharedConstants.getGameVersion().name}&l=fabric" + + fun downloadButton(modName: String, modId: String, slug: String): Text { + val alreadyDownloaded = FabricLoader.getInstance().isModLoaded(modId) + return Text.literal(" - ") + .white() + .append(Text.literal("[").aqua()) + .append(Text.translatable("firmament.download", modName) + .styled { it.withClickEvent(ClickEvent.OpenUrl(URI (modrinthLink(slug)))) } + .yellow() + .also { + if (alreadyDownloaded) + it.append(Text.translatable("firmament.download.already", modName) + .lime()) + }) + .append(Text.literal("]").aqua()) + } + + @Subscribe + fun checkREIDependency(event: SkyblockServerUpdateEvent) { + if (!SBData.isOnSkyblock) return + if (!RepoManager.Config.warnForMissingItemListMod) return + if (hasREI) return + if (sentWarning) return + sentWarning = true + Firmament.coroutineScope.launch { + delay(2.seconds) + // TODO: should we offer an automatic install that actually downloads the JARs and places them into the mod folder? + MC.sendChat( + Text.translatable("firmament.reiwarning").red().bold().append("\n") + .append(downloadButton("RoughlyEnoughItems", reiModId, "rei")).append("\n") + .append(downloadButton("Architectury API", "architectury", "architectury-api")).append("\n") + .append(downloadButton("Cloth Config API", "cloth-config", "cloth-config")).append("\n") + .append(Text.translatable("firmament.reiwarning.disable") + .clickCommand("/firm disablereiwarning") + .grey()) + ) + } + } + + @Subscribe + fun onSubcommand(event: CommandEvent.SubCommand) { + if (hasREI) return + event.subcommand("disablereiwarning") { + thenExecute { + RepoManager.Config.warnForMissingItemListMod = false + RepoManager.Config.save() + MC.sendChat(Text.translatable("firmament.reiwarning.disabled").yellow()) + } + } + } +} diff --git a/src/main/kotlin/features/inventory/SaveCursorPosition.kt b/src/main/kotlin/features/inventory/SaveCursorPosition.kt new file mode 100644 index 0000000..c47867b --- /dev/null +++ b/src/main/kotlin/features/inventory/SaveCursorPosition.kt @@ -0,0 +1,66 @@ + + +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, Category.INVENTORY) { + 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? = null + var savedPosition: SavedPosition? = null + + data class SavedPosition( + val middle: Pair, + val cursor: Pair, + val savedAt: TimeMark = TimeMark.now() + ) + + @JvmStatic + fun saveCursorOriginal(positionedX: Double, positionedY: Double) { + savedPositionedP1 = Pair(positionedX, positionedY) + } + + @JvmStatic + fun loadCursor(middleX: Double, middleY: Double): Pair? { + 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/features/inventory/SlotLocking.kt b/src/main/kotlin/features/inventory/SlotLocking.kt new file mode 100644 index 0000000..0a3f01b --- /dev/null +++ b/src/main/kotlin/features/inventory/SlotLocking.kt @@ -0,0 +1,504 @@ +@file:UseSerializers(DashlessUUIDSerializer::class) + +package moe.nea.firmament.features.inventory + +import java.util.UUID +import org.lwjgl.glfw.GLFW +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +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.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.int +import kotlinx.serialization.serializer +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.render.RenderLayer +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.item.ItemStack +import net.minecraft.screen.GenericContainerScreenHandler +import net.minecraft.screen.slot.Slot +import net.minecraft.screen.slot.SlotActionType +import net.minecraft.util.Identifier +import net.minecraft.util.StringIdentifiable +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.FeaturesInitializedEvent +import moe.nea.firmament.events.HandledScreenForegroundEvent +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.events.HandledScreenKeyReleasedEvent +import moe.nea.firmament.events.IsSlotProtectedEvent +import moe.nea.firmament.events.ScreenChangeEvent +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.extraAttributes +import moe.nea.firmament.util.json.DashlessUUIDSerializer +import moe.nea.firmament.util.lime +import moe.nea.firmament.util.mc.ScreenUtil.getSlotByIndex +import moe.nea.firmament.util.mc.SlotUtils.swapWithHotBar +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.red +import moe.nea.firmament.util.render.drawLine +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.DungeonUtil +import moe.nea.firmament.util.skyblock.SkyBlockItems +import moe.nea.firmament.util.skyblockUUID +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.unformattedString + +object SlotLocking : FirmamentFeature { + override val identifier: String + get() = "slot-locking" + + @Serializable + data class Data( + val lockedSlots: MutableSet = mutableSetOf(), + val lockedSlotsRift: MutableSet = mutableSetOf(), + val lockedUUIDs: MutableSet = mutableSetOf(), + val boundSlots: BoundSlots = BoundSlots() + ) + + @Serializable + data class BoundSlot( + val hotbar: Int, + val inventory: Int, + ) + + @Serializable(with = BoundSlots.Serializer::class) + data class BoundSlots( + val pairs: MutableSet = mutableSetOf() + ) { + fun findMatchingSlots(index: Int): List { + return pairs.filter { it.hotbar == index || it.inventory == index } + } + + fun removeDuplicateForInventory(index: Int) { + pairs.removeIf { it.inventory == index } + } + + fun removeAllInvolving(index: Int): Boolean { + return pairs.removeIf { it.inventory == index || it.hotbar == index } + } + + fun insert(hotbar: Int, inventory: Int) { + if (!TConfig.allowMultiBinding) { + removeAllInvolving(hotbar) + removeAllInvolving(inventory) + } + pairs.add(BoundSlot(hotbar, inventory)) + } + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = serializer().descriptor + + override fun serialize( + encoder: Encoder, + value: BoundSlots + ) { + serializer>() + .serialize(encoder, value.pairs) + } + + override fun deserialize(decoder: Decoder): BoundSlots { + decoder as JsonDecoder + val json = decoder.decodeJsonElement() + if (json is JsonObject) { + return BoundSlots(json.entries.map { + BoundSlot(it.key.toInt(), (it.value as JsonPrimitive).int) + }.toMutableSet()) + } + return BoundSlots(decoder.json.decodeFromJsonElement(serializer>(), json)) + + } + } + } + + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val lockSlot by keyBinding("lock") { GLFW.GLFW_KEY_L } + val lockUUID by keyBindingWithOutDefaultModifiers("lock-uuid") { + SavedKeyBinding(GLFW.GLFW_KEY_L, shift = true) + } + val slotBind by keyBinding("bind") { GLFW.GLFW_KEY_L } + val slotBindRequireShift by toggle("require-quick-move") { true } + val slotRenderLines by choice("bind-render") { SlotRenderLinesMode.ONLY_BOXES } + val allowMultiBinding by toggle("multi-bind") { true } // TODO: filter based on this option + val protectAllHuntingBoxes by toggle("hunting-box") { false } + val allowDroppingInDungeons by toggle("drop-in-dungeons") { true } + } + + enum class SlotRenderLinesMode : StringIdentifiable { + EVERYTHING, + ONLY_BOXES, + NOTHING; + + override fun asString(): String { + return name + } + } + + override val config: TConfig + get() = TConfig + + object DConfig : ProfileSpecificDataHolder(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, + IsSlotProtectedEvent.MoveOrigin.SALVAGE, + 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 + if (TConfig.protectAllHuntingBoxes && (stack.isHuntingBox())) { + event.protect() + return + } + val uuid = stack.skyblockUUID ?: return + if (uuid in (lockedUUIDs ?: return)) { + event.protect() + } + } + + fun ItemStack.isHuntingBox(): Boolean { + return skyBlockId == SkyBlockItems.HUNTING_TOOLKIT || extraAttributes.get("tool_kit") != null + } + + @Subscribe + fun onProtectSlot(it: IsSlotProtectedEvent) { + if (it.slot != null && it.slot.inventory is PlayerInventory && it.slot.index in (lockedSlots ?: setOf())) { + it.protect() + } + } + + @Subscribe + fun onEvent(event: FeaturesInitializedEvent) { + IsSlotProtectedEvent.subscribe(receivesCancelled = true, "SlotLocking:unlockInDungeons") { + if (it.isProtected + && it.origin == IsSlotProtectedEvent.MoveOrigin.DROP_FROM_HOTBAR + && DungeonUtil.isInActiveDungeon + && TConfig.allowDroppingInDungeons + ) { + it.isProtected = false + } + } + } + + @Subscribe + fun onQuickMoveBoundSlot(it: IsSlotProtectedEvent) { + val boundSlots = DConfig.data?.boundSlots ?: BoundSlots() + val isValidAction = + it.actionType == SlotActionType.QUICK_MOVE || (it.actionType == SlotActionType.PICKUP && !TConfig.slotBindRequireShift) + if (!isValidAction) return + val handler = MC.handledScreen?.screenHandler ?: return + val slot = it.slot + if (slot != null && it.slot.inventory is PlayerInventory) { + val matchingSlots = boundSlots.findMatchingSlots(slot.index) + if (matchingSlots.isEmpty()) return + it.protectSilent() + val boundSlot = matchingSlots.singleOrNull() ?: return + val inventorySlot = MC.handledScreen?.getSlotByIndex(boundSlot.inventory, true) + inventorySlot?.swapWithHotBar(handler, boundSlot.hotbar) + } + } + + @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 + if (stack.isHuntingBox()) { + MC.sendChat( + tr( + "firmament.slot-locking.hunting-box-unbindable-hint", + "The hunting box cannot be UUID bound reliably. It changes its own UUID frequently when switching tools. " + ).red().append( + tr( + "firmament.slot-locking.hunting-box-unbindable-hint.solution", + "Use the Firmament config option for locking all hunting boxes instead." + ).lime() + ) + ) + CommonSoundEffects.playFailure() + 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 onLockSlotKeyRelease(it: HandledScreenKeyReleasedEvent) { + val inventory = MC.handledScreen ?: return + inventory as AccessorHandledScreen + val slot = inventory.focusedSlot_Firmament + val storedSlot = storedLockingSlot ?: return + + if (it.matches(TConfig.slotBind) && slot != storedSlot && slot != null && slot.isHotbar() != storedSlot.isHotbar()) { + storedLockingSlot = null + val hotBarSlot = if (slot.isHotbar()) slot else storedSlot + val invSlot = if (slot.isHotbar()) storedSlot else slot + val boundSlots = DConfig.data?.boundSlots ?: return + lockedSlots?.remove(hotBarSlot.index) + lockedSlots?.remove(invSlot.index) + boundSlots.removeDuplicateForInventory(invSlot.index) + boundSlots.insert(hotBarSlot.index, invSlot.index) + DConfig.markDirty() + CommonSoundEffects.playSuccess() + return + } + if (it.matches(TConfig.lockSlot) && slot == storedSlot) { + storedLockingSlot = null + toggleSlotLock(slot) + return + } + if (it.matches(TConfig.slotBind)) { + storedLockingSlot = null + val boundSlots = DConfig.data?.boundSlots ?: return + if (slot != null) + boundSlots.removeAllInvolving(slot.index) + } + } + + @Subscribe + fun onRenderAllBoundSlots(event: HandledScreenForegroundEvent) { + val boundSlots = DConfig.data?.boundSlots ?: return + fun findByIndex(index: Int) = event.screen.getSlotByIndex(index, true) + val accScreen = event.screen as AccessorHandledScreen + val sx = accScreen.x_Firmament + val sy = accScreen.y_Firmament + val highlitSlots = mutableSetOf() + for (it in boundSlots.pairs) { + val hotbarSlot = findByIndex(it.hotbar) ?: continue + val inventorySlot = findByIndex(it.inventory) ?: continue + + val (hotX, hotY) = hotbarSlot.lineCenter() + val (invX, invY) = inventorySlot.lineCenter() + val anyHovered = accScreen.focusedSlot_Firmament === hotbarSlot + || accScreen.focusedSlot_Firmament === inventorySlot + if (!anyHovered && TConfig.slotRenderLines == SlotRenderLinesMode.NOTHING) + continue + if (anyHovered) { + highlitSlots.add(hotbarSlot) + highlitSlots.add(inventorySlot) + } + fun color(highlit: Boolean) = + if (highlit) + me.shedaniel.math.Color.ofOpaque(0x00FF00) + else + me.shedaniel.math.Color.ofTransparent(0xc0a0f000.toInt()) + if (TConfig.slotRenderLines == SlotRenderLinesMode.EVERYTHING || anyHovered) + event.context.drawLine( + invX + sx, invY + sy, + hotX + sx, hotY + sy, + color(anyHovered) + ) + event.context.drawBorder( + hotbarSlot.x + sx, + hotbarSlot.y + sy, + 16, 16, color(hotbarSlot in highlitSlots).color + ) + event.context.drawBorder( + inventorySlot.x + sx, + inventorySlot.y + sy, + 16, 16, color(inventorySlot in highlitSlots).color + ) + } + } + + @Subscribe + fun onRenderCurrentDraggingSlot(event: HandledScreenForegroundEvent) { + val draggingSlot = storedLockingSlot ?: return + val accScreen = event.screen as AccessorHandledScreen + val hoveredSlot = accScreen.focusedSlot_Firmament + ?.takeIf { it.inventory is PlayerInventory } + ?.takeIf { it == draggingSlot || it.isHotbar() != draggingSlot.isHotbar() } + val sx = accScreen.x_Firmament + val sy = accScreen.y_Firmament + val (borderX, borderY) = draggingSlot.lineCenter() + event.context.drawBorder(draggingSlot.x + sx, draggingSlot.y + sy, 16, 16, 0xFF00FF00u.toInt()) + if (hoveredSlot == null) { + event.context.drawLine( + borderX + sx, borderY + sy, + event.mouseX, event.mouseY, + me.shedaniel.math.Color.ofOpaque(0x00FF00) + ) + } else if (hoveredSlot != draggingSlot) { + val (hovX, hovY) = hoveredSlot.lineCenter() + event.context.drawLine( + borderX + sx, borderY + sy, + hovX + sx, hovY + sy, + me.shedaniel.math.Color.ofOpaque(0x00FF00) + ) + event.context.drawBorder( + hoveredSlot.x + sx, + hoveredSlot.y + sy, + 16, 16, 0xFF00FF00u.toInt() + ) + } + } + + fun Slot.lineCenter(): Pair { + return if (isHotbar()) { + x + 9 to y + } else { + x + 9 to y + 17 + } + } + + + fun Slot.isHotbar(): Boolean { + return index < 9 + } + + @Subscribe + fun onScreenChange(event: ScreenChangeEvent) { + storedLockingSlot = null + } + + var storedLockingSlot: Slot? = null + + fun toggleSlotLock(slot: Slot) { + val lockedSlots = lockedSlots ?: return + val boundSlots = DConfig.data?.boundSlots ?: BoundSlots() + if (slot.inventory is PlayerInventory) { + if (boundSlots.removeAllInvolving(slot.index)) { + // intentionally do nothing + } else if (slot.index in lockedSlots) { + lockedSlots.remove(slot.index) + } else { + lockedSlots.add(slot.index) + } + DConfig.markDirty() + CommonSoundEffects.playSuccess() + } + } + + @Subscribe + fun onLockSlot(it: HandledScreenKeyPressedEvent) { + val inventory = MC.handledScreen ?: return + inventory as AccessorHandledScreen + + val slot = inventory.focusedSlot_Firmament ?: return + if (slot.inventory !is PlayerInventory) return + if (it.matches(TConfig.slotBind)) { + storedLockingSlot = storedLockingSlot ?: slot + return + } + if (!it.matches(TConfig.lockSlot)) { + return + } + toggleSlotLock(slot) + } + + @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) { + it.context.drawGuiTexture( + RenderLayer::getGuiTexturedOverlay, + when { + isSlotLocked -> + (Identifier.of("firmament:slot_locked")) + + isUUIDLocked -> + (Identifier.of("firmament:uuid_locked")) + + else -> + error("unreachable") + }, + it.slot.x, it.slot.y, + 16, 16, + -1 + ) + } + } +} diff --git a/src/main/kotlin/features/inventory/TimerInLore.kt b/src/main/kotlin/features/inventory/TimerInLore.kt new file mode 100644 index 0000000..e939404 --- /dev/null +++ b/src/main/kotlin/features/inventory/TimerInLore.kt @@ -0,0 +1,150 @@ +package moe.nea.firmament.features.inventory + +import java.time.ZoneId +import java.time.ZonedDateTime +import java.time.format.DateTimeFormatter +import java.time.format.DateTimeFormatterBuilder +import java.time.format.FormatStyle +import java.time.format.TextStyle +import java.time.temporal.ChronoField +import net.minecraft.text.Text +import net.minecraft.util.StringIdentifiable +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ItemTooltipEvent +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.aqua +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.timestamp +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.unformattedString + +object TimerInLore { + object TConfig : ManagedConfig("lore-timers", Category.INVENTORY) { + val showTimers by toggle("show") { true } + val showCreationTimestamp by toggle("show-creation") { true } + val timerFormat by choice("format") { TimerFormat.SOCIALIST } + } + + enum class TimerFormat(val formatter: DateTimeFormatter) : StringIdentifiable { + RFC(DateTimeFormatter.RFC_1123_DATE_TIME), + LOCAL(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)), + SOCIALIST( + { + appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT) + appendLiteral(" ") + appendValue(ChronoField.DAY_OF_MONTH, 2) + appendLiteral(".") + appendValue(ChronoField.MONTH_OF_YEAR, 2) + appendLiteral(".") + appendValue(ChronoField.YEAR, 4) + appendLiteral(" ") + appendValue(ChronoField.HOUR_OF_DAY, 2) + appendLiteral(":") + appendValue(ChronoField.MINUTE_OF_HOUR, 2) + appendLiteral(":") + appendValue(ChronoField.SECOND_OF_MINUTE, 2) + }), + AMERICAN("EEEE, MMM d h:mm a yyyy"), + RFCPrecise(DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss.SSS Z")), + ; + + constructor(block: DateTimeFormatterBuilder.() -> Unit) + : this(DateTimeFormatterBuilder().also(block).toFormatter()) + + constructor(format: String) : this(DateTimeFormatter.ofPattern(format)) + + override fun asString(): String { + return name + } + } + + enum class CountdownTypes( + val match: String, + val label: String, // TODO: convert to a string + val isRelative: Boolean = false, + ) { + STARTING("Starting in:", "Starts at"), + STARTS("Starts in:", "Starts at"), + INTEREST("Interest in:", "Interest at"), + UNTILINTEREST("Until interest:", "Interest at"), + ENDS("Ends in:", "Ends at"), + REMAINING("Remaining:", "Ends at"), + DURATION("Duration:", "Finishes at"), + TIMELEFT("Time left:", "Ends at"), + EVENTTIMELEFT("Event lasts for", "Ends at", isRelative = true), + SHENSUCKS("Auction ends in:", "Auction ends at"), + ENDS_PET_LEVELING( + "Ends:", + "Finishes at" + ), + CALENDARDETAILS(" (§e", "Starts at"), + COMMUNITYPROJECTS("Contribute again", "Come back at"), + CHOCOLATEFACTORY("Next Charge", "Available at"), + STONKSAUCTION("Auction ends in", "Ends at"), + LIZSTONKREDEMPTION("Resets in:", "Resets at"), + TIMEREMAININGS("Time Remaining:", "Ends at"), + COOLDOWN("Cooldown:", "Come back at"), + ONCOOLDOWN("On cooldown:", "Available at"), + EVENTENDING("Event ends in:", "Ends at"); + } + + val regex = + "(?i)(?:(?[0-9]+) ?(y|years?) )?(?:(?[0-9]+) ?(d|days?))? ?(?:(?[0-9]+) ?(h|hours?))? ?(?:(?[0-9]+) ?(m|minutes?))? ?(?:(?[0-9]+) ?(s|seconds?))?\\b".toRegex() + + @Subscribe + fun creationInLore(event: ItemTooltipEvent) { + if (!TConfig.showCreationTimestamp) return + val timestamp = event.stack.timestamp ?: return + val formattedTimestamp = TConfig.timerFormat.formatter.format(ZonedDateTime.ofInstant(timestamp, ZoneId.systemDefault())) + event.lines.add(tr("firmament.lore.creationtimestamp", "Created at: $formattedTimestamp").grey()) + } + + @Subscribe + fun modifyLore(event: ItemTooltipEvent) { + if (!TConfig.showTimers) return + var lastTimer: ZonedDateTime? = null + for (i in event.lines.indices) { + val line = event.lines[i].unformattedString + val countdownType = CountdownTypes.entries.find { it.match in line } ?: continue + if (countdownType == CountdownTypes.CALENDARDETAILS + && !event.stack.displayNameAccordingToNbt.unformattedString.startsWith("Day ") + ) continue + + val countdownMatch = regex.findAll(line).filter { it.value.isNotBlank() }.lastOrNull() ?: continue + val (years, days, hours, minutes, seconds) = + listOf("years", "days", "hours", "minutes", "seconds") + .map { + countdownMatch.groups[it]?.value?.toLong() ?: 0L + } + if (years + days + hours + minutes + seconds == 0L) continue + var baseLine = ZonedDateTime.now(SBData.hypixelTimeZone) + if (countdownType.isRelative) { + if (lastTimer == null) { + event.lines.add( + i + 1, + tr( + "firmament.loretimer.missingrelative", + "Found a relative countdown with no baseline (Firmament)" + ).grey() + ) + continue + } + baseLine = lastTimer + } + val timer = + baseLine.plusYears(years).plusDays(days).plusHours(hours).plusMinutes(minutes).plusSeconds(seconds) + lastTimer = timer + val localTimer = timer.withZoneSameInstant(ZoneId.systemDefault()) + // TODO: install approximate time stabilization algorithm + event.lines.add( + i + 1, + Text.literal("${countdownType.label}: ") + .grey() + .append(Text.literal(TConfig.timerFormat.formatter.format(localTimer)).aqua()) + ) + } + } + +} diff --git a/src/main/kotlin/features/inventory/WardrobeKeybinds.kt b/src/main/kotlin/features/inventory/WardrobeKeybinds.kt new file mode 100644 index 0000000..6e2b4a9 --- /dev/null +++ b/src/main/kotlin/features/inventory/WardrobeKeybinds.kt @@ -0,0 +1,80 @@ +package moe.nea.firmament.features.inventory + +import org.lwjgl.glfw.GLFW +import net.minecraft.item.Items +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.mc.SlotUtils.clickLeftMouseButton + +object WardrobeKeybinds : FirmamentFeature { + override val identifier: String + get() = "wardrobe-keybinds" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val wardrobeKeybinds by toggle("wardrobe-keybinds") { false } + val changePageKeybind by keyBinding("change-page") { GLFW.GLFW_KEY_ENTER } + val nextPage by keyBinding("next-page") { GLFW.GLFW_KEY_D } + val previousPage by keyBinding("previous-page") { GLFW.GLFW_KEY_A } + val slotKeybinds = (1..9).map { + keyBinding("slot-$it") { GLFW.GLFW_KEY_0 + it } + } + } + + override val config: ManagedConfig? + get() = TConfig + + val slotKeybindsWithSlot = TConfig.slotKeybinds.withIndex().map { (index, keybinding) -> + index + 36 to keybinding + } + + @Subscribe + fun switchSlot(event: HandledScreenKeyPressedEvent) { + if (MC.player == null || MC.world == null || MC.interactionManager == null) return + + val regex = Regex("Wardrobe \\([12]/2\\)") + if (!regex.matches(event.screen.title.string)) return + if (!TConfig.wardrobeKeybinds) return + + if ( + event.matches(TConfig.changePageKeybind) || + event.matches(TConfig.previousPage) || + event.matches(TConfig.nextPage) + ) { + event.cancel() + + val handler = event.screen.screenHandler + val previousSlot = handler.getSlot(45) + val nextSlot = handler.getSlot(53) + + val backPressed = event.matches(TConfig.changePageKeybind) || event.matches(TConfig.previousPage) + val nextPressed = event.matches(TConfig.changePageKeybind) || event.matches(TConfig.nextPage) + + if (backPressed && previousSlot.stack.item == Items.ARROW) { + previousSlot.clickLeftMouseButton(handler) + } else if (nextPressed && nextSlot.stack.item == Items.ARROW) { + nextSlot.clickLeftMouseButton(handler) + } + } + + + + val slot = + slotKeybindsWithSlot + .find { event.matches(it.second.get()) } + ?.first ?: return + + event.cancel() + + val handler = event.screen.screenHandler + val invSlot = handler.getSlot(slot) + + val itemStack = invSlot.stack + if (itemStack.item != Items.PINK_DYE && itemStack.item != Items.LIME_DYE) return + + invSlot.clickLeftMouseButton(handler) + } + +} diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButton.kt b/src/main/kotlin/features/inventory/buttons/InventoryButton.kt new file mode 100644 index 0000000..955ae88 --- /dev/null +++ b/src/main/kotlin/features/inventory/buttons/InventoryButton.kt @@ -0,0 +1,103 @@ +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.ExpensiveItemCacheApi +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.collections.memoize +import moe.nea.firmament.util.mc.arbitraryUUID +import moe.nea.firmament.util.mc.createSkullItem +import moe.nea.firmament.util.render.drawGuiTexture + +@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) + @OptIn(ExpensiveItemCacheApi::class) + fun getItemForName0(icon: String): ItemStack { + val repoItem = RepoManager.getNEUItem(SkyblockId(icon)) + var itemStack = repoItem.asItemStack(idHint = SkyblockId(icon)) + if (repoItem == null) { + when { + icon.startsWith("skull:") -> { + itemStack = createSkullItem( + arbitraryUUID, + "https://textures.minecraft.net/texture/${icon.substring("skull:".length)}" + ) + } + + else -> { + 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.drawGuiTexture( + 0, + 0, + 0, + dimensions.width, + dimensions.height, + 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/features/inventory/buttons/InventoryButtonEditor.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt new file mode 100644 index 0000000..eecbd17 --- /dev/null +++ b/src/main/kotlin/features/inventory/buttons/InventoryButtonEditor.kt @@ -0,0 +1,300 @@ +package moe.nea.firmament.features.inventory.buttons + +import io.github.notenoughupdates.moulconfig.common.IItemStack +import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent +import io.github.notenoughupdates.moulconfig.platform.ModernItemStack +import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext +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.MinecraftClient +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.gui.widget.ButtonWidget +import net.minecraft.client.gui.widget.TextWidget +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 +import moe.nea.firmament.util.tr + +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 = + InventoryButtons.DConfig.data.buttons.map { it.copy() }.toMutableList() + + override fun close() { + InventoryButtons.DConfig.data.buttons = buttons + InventoryButtons.DConfig.markDirty() + super.close() + } + + override fun resize(client: MinecraftClient, width: Int, height: Int) { + lastGuiRect.move( + MC.window.scaledWidth / 2 - lastGuiRect.width / 2, + MC.window.scaledHeight / 2 - lastGuiRect.height / 2 + ) + super.resize(client, width, height) + } + + override fun init() { + super.init() + addDrawableChild( + TextWidget( + lastGuiRect.minX, + 25, + lastGuiRect.width, + 9, + Text.translatable("firmament.inventory-buttons.delete"), + MC.font + ).alignCenter() + ) + addDrawableChild( + TextWidget( + lastGuiRect.minX, + 40, + lastGuiRect.width, + 9, + Text.translatable("firmament.inventory-buttons.info"), + MC.font + ).alignCenter() + ) + addDrawableChild( + ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.reset")) { + val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bXQ==") + if (newButtons != null) + buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) }) + } + .position(lastGuiRect.minX + 10, lastGuiRect.minY + 10) + .width(lastGuiRect.width - 20) + .build() + ) + addDrawableChild( + ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.load-preset")) { + val t = ClipboardUtils.getTextContents() + val newButtons = InventoryButtonTemplates.loadTemplate(t) + if (newButtons != null) + buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) }) + } + .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() + ) + addDrawableChild( + ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.simple-preset")) { + // Preset from NEU + // Credit: https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/9b1fcfebc646e9fb69f99006327faa3e734e5f51/src/main/resources/assets/notenoughupdates/invbuttons/presets.json#L900-L1348 + val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bIntcblx0XCJ4XCI6IDE2MCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcImJvbmVcIixcblx0XCJjb21tYW5kXCI6IFwicGV0c1wiXG59Iiwie1xuXHRcInhcIjogMTQwLFxuXHRcInlcIjogLTIwLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwiYXJtb3Jfc3RhbmRcIixcblx0XCJjb21tYW5kXCI6IFwid2FyZHJvYmVcIlxufSIsIntcblx0XCJ4XCI6IDEyMCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcImVuZGVyX2NoZXN0XCIsXG5cdFwiY29tbWFuZFwiOiBcInN0b3JhZ2VcIlxufSIsIntcblx0XCJ4XCI6IDEwMCxcblx0XCJ5XCI6IC0yMCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcInNrdWxsOmQ3Y2M2Njg3NDIzZDA1NzBkNTU2YWM1M2UwNjc2Y2I1NjNiYmRkOTcxN2NkODI2OWJkZWJlZDZmNmQ0ZTdiZjhcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBpc2xhbmRcIlxufSIsIntcblx0XCJ4XCI6IDgwLFxuXHRcInlcIjogLTIwLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwic2t1bGw6MzVmNGI0MGNlZjllMDE3Y2Q0MTEyZDI2YjYyNTU3ZjhjMWQ1YjE4OWRhMmU5OTUzNDIyMmJjOGNlYzdkOTE5NlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGh1YlwiXG59Il0=") + if (newButtons != null) + buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) }) + } + .position(lastGuiRect.minX + 10, lastGuiRect.minY + 85) + .width(lastGuiRect.width - 20) + .build() + ) + addDrawableChild( + ButtonWidget.builder(Text.translatable("firmament.inventory-buttons.all-warps-preset")) { + // Preset from NEU + // Credit: https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/9b1fcfebc646e9fb69f99006327faa3e734e5f51/src/main/resources/assets/notenoughupdates/invbuttons/presets.json#L1817-L2276 + val newButtons = InventoryButtonTemplates.loadTemplate("TkVVQlVUVE9OUy9bIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtODQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6YzljODg4MWU0MjkxNWE5ZDI5YmI2MWExNmZiMjZkMDU5OTEzMjA0ZDI2NWRmNWI0MzliM2Q3OTJhY2Q1NlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGhvbWVcIlxufSIsIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtNjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6ZDdjYzY2ODc0MjNkMDU3MGQ1NTZhYzUzZTA2NzZjYjU2M2JiZGQ5NzE3Y2Q4MjY5YmRlYmVkNmY2ZDRlN2JmOFwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGh1YlwiXG59Iiwie1xuXHRcInhcIjogMixcblx0XCJ5XCI6IC00NCxcblx0XCJhbmNob3JSaWdodFwiOiB0cnVlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo5YjU2ODk1Yjk2NTk4OTZhZDY0N2Y1ODU5OTIzOGFmNTMyZDQ2ZGI5YzFiMDM4OWI4YmJlYjcwOTk5ZGFiMzNkXCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZHVuZ2Vvbl9odWJcIlxufSIsIntcblx0XCJ4XCI6IDIsXG5cdFwieVwiOiAtMjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogdHJ1ZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6Nzg0MGI4N2Q1MjI3MWQyYTc1NWRlZGM4Mjg3N2UwZWQzZGY2N2RjYzQyZWE0NzllYzE0NjE3NmIwMjc3OWE1XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZW5kXCJcbn0iLCJ7XG5cdFwieFwiOiAxMDksXG5cdFwieVwiOiAtMTksXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IGZhbHNlLFxuXHRcImljb25cIjogXCJza3VsbDo4NmYwNmVhYTMwMDRhZWVkMDliM2Q1YjQ1ZDk3NmRlNTg0ZTY5MWMwZTljYWRlMTMzNjM1ZGU5M2QyM2I5ZWRiXCIsXG5cdFwiY29tbWFuZFwiOiBcImhvdG1cIlxufSIsIntcblx0XCJ4XCI6IDEzMCxcblx0XCJ5XCI6IC0xOSxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkVOREVSX0NIRVNUXCIsXG5cdFwiY29tbWFuZFwiOiBcInN0b3JhZ2VcIlxufSIsIntcblx0XCJ4XCI6IDE1MSxcblx0XCJ5XCI6IC0xOSxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkJPTkVcIixcblx0XCJjb21tYW5kXCI6IFwicGV0c1wiXG59Iiwie1xuXHRcInhcIjogLTE5LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogZmFsc2UsXG5cdFwiaWNvblwiOiBcIkdPTERfQkxPQ0tcIixcblx0XCJjb21tYW5kXCI6IFwiYWhcIlxufSIsIntcblx0XCJ4XCI6IC0xOSxcblx0XCJ5XCI6IDIyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiBmYWxzZSxcblx0XCJpY29uXCI6IFwiR09MRF9CQVJESU5HXCIsXG5cdFwiY29tbWFuZFwiOiBcImJ6XCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtODQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjQzOGNmM2Y4ZTU0YWZjM2IzZjkxZDIwYTQ5ZjMyNGRjYTE0ODYwMDdmZTU0NTM5OTA1NTUyNGMxNzk0MWY0ZGNcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBtdXNldW1cIlxufSIsIntcblx0XCJ4XCI6IC0xOSxcblx0XCJ5XCI6IC02NCxcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6ZjQ4ODBkMmMxZTdiODZlODc1MjJlMjA4ODI2NTZmNDViYWZkNDJmOTQ5MzJiMmM1ZTBkNmVjYWE0OTBjYjRjXCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZ2FyZGVuXCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtNDQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjRkM2E2YmQ5OGFjMTgzM2M2NjRjNDkwOWZmOGQyZGM2MmNlODg3YmRjZjNjYzViMzg0ODY1MWFlNWFmNmJcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBiYXJuXCJcbn0iLCJ7XG5cdFwieFwiOiAtMTksXG5cdFwieVwiOiAtMjQsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjUxNTM5ZGRkZjllZDI1NWVjZTYzNDgxOTNjZDc1MDEyYzgyYzkzYWVjMzgxZjA1NTcyY2VjZjczNzk3MTFiM2JcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBkZXNlcnRcIlxufSIsIntcblx0XCJ4XCI6IDQsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo3M2JjOTY1ZDU3OWMzYzYwMzlmMGExN2ViN2MyZTZmYWY1MzhjN2E1ZGU4ZTYwZWM3YTcxOTM2MGQwYTg1N2E5XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgZ29sZFwiXG59Iiwie1xuXHRcInhcIjogMjUsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo1NjlhMWYxMTQxNTFiNDUyMTM3M2YzNGJjMTRjMjk2M2E1MDExY2RjMjVhNjU1NGM0OGM3MDhjZDk2ZWJmY1wiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGRlZXBcIlxufSIsIntcblx0XCJ4XCI6IDQ2LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6MjFkYmUzMGIwMjdhY2JjZWI2MTI1NjNiZDg3N2NkN2ViYjcxOWVhNmVkMTM5OTAyN2RjZWU1OGJiOTA0OWQ0YVwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGNyeXN0YWxzXCJcbn0iLCJ7XG5cdFwieFwiOiA2Nyxcblx0XCJ5XCI6IDIsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjVjYmQ5ZjVlYzFlZDAwNzI1OTk5NjQ5MWU2OWZmNjQ5YTMxMDZjZjkyMDIyN2IxYmIzYTcxZWU3YTg5ODYzZlwiLFxuXHRcImNvbW1hbmRcIjogXCJ3YXJwIGZvcmdlXCJcbn0iLCJ7XG5cdFwieFwiOiA4OCxcblx0XCJ5XCI6IDIsXG5cdFwiYW5jaG9yUmlnaHRcIjogZmFsc2UsXG5cdFwiYW5jaG9yQm90dG9tXCI6IHRydWUsXG5cdFwiaWNvblwiOiBcInNrdWxsOjZiMjBiMjNjMWFhMmJlMDI3MGYwMTZiNGM5MGQ2ZWU2YjgzMzBhMTdjZmVmODc4NjlkNmFkNjBiMmZmYmYzYjVcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBtaW5lc1wiXG59Iiwie1xuXHRcInhcIjogMTA5LFxuXHRcInlcIjogMixcblx0XCJhbmNob3JSaWdodFwiOiBmYWxzZSxcblx0XCJhbmNob3JCb3R0b21cIjogdHJ1ZSxcblx0XCJpY29uXCI6IFwic2t1bGw6YTIyMWY4MTNkYWNlZTBmZWY4YzU5Zjc2ODk0ZGJiMjY0MTU0NzhkOWRkZmM0NGMyZTcwOGE2ZDNiNzU0OWJcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBwYXJrXCJcbn0iLCJ7XG5cdFwieFwiOiAxMzAsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDo5ZDdlM2IxOWFjNGYzZGVlOWM1Njc3YzEzNTMzM2I5ZDM1YTdmNTY4YjYzZDFlZjRhZGE0YjA2OGI1YTI1XCIsXG5cdFwiY29tbWFuZFwiOiBcIndhcnAgc3BpZGVyXCJcbn0iLCJ7XG5cdFwieFwiOiAxNTEsXG5cdFwieVwiOiAyLFxuXHRcImFuY2hvclJpZ2h0XCI6IGZhbHNlLFxuXHRcImFuY2hvckJvdHRvbVwiOiB0cnVlLFxuXHRcImljb25cIjogXCJza3VsbDpjMzY4N2UyNWM2MzJiY2U4YWE2MWUwZDY0YzI0ZTY5NGMzZWVhNjI5ZWE5NDRmNGNmMzBkY2ZiNGZiY2UwNzFcIixcblx0XCJjb21tYW5kXCI6IFwid2FycCBuZXRoZXJcIlxufSJd") + if (newButtons != null) + buttons = moveButtons(newButtons.map { it.copy(command = it.command?.removePrefix("/")) }) + } + .position(lastGuiRect.minX + 10, lastGuiRect.minY + 110) + .width(lastGuiRect.width - 20) + .build() + ) + } + + private fun moveButtons(buttons: List): MutableList { + val newButtons: MutableList = ArrayList(buttons.size) + val movedButtons = mutableListOf() + for (button in buttons) { + if ((!button.anchorBottom && !button.anchorRight && button.x > 0 && button.y > 0)) { + MC.sendChat( + tr( + "firmament.inventory-buttons.button-moved", + "One of your imported buttons intersects with the inventory and has been moved to the top left." + ) + ) + movedButtons.add( + button.copy( + x = 0, + y = -InventoryButton.dimensions.width, + anchorRight = false, + anchorBottom = false + ) + ) + } else { + newButtons.add(button) + } + } + var i = 0 + val zeroRect = Rectangle(0, 0, 1, 1) + for (movedButton in movedButtons) { + fun getPosition(button: InventoryButton, index: Int) = + button.copy( + x = (index % 10) * InventoryButton.dimensions.width, + y = (index / 10) * -InventoryButton.dimensions.height, + anchorRight = false, anchorBottom = false + ) + while (true) { + val newPos = getPosition(movedButton, i++) + val newBounds = newPos.getBounds(zeroRect) + if (newButtons.none { it.getBounds(zeroRect).intersects(newBounds) }) { + newButtons.add(newPos) + break + } + } + } + return newButtons + } + + override fun renderBackground(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { + context.matrices.push() + context.matrices.translate(0F, 0F, -15F) + super.renderBackground(context, mouseX, mouseY, delta) + context.matrices.pop() + } + + 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) + PanelComponent.DefaultBackgroundRenderer.VANILLA + .render( + ModernRenderContext(context), + lastGuiRect.minX, lastGuiRect.minY, + lastGuiRect.width, lastGuiRect.height, + ) + 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) { + if (InputUtil.isKeyPressed(MC.window.handle, InputUtil.GLFW_KEY_LEFT_CONTROL)) Editor(clickedButton).delete() + else 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? { + 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 + } + val rect = InventoryButton(offsetX, offsetY, anchorRight, anchorBottom).getBounds(lastGuiRect) + if (rect.intersects(lastGuiRect)) return null + val anchoredCoords = AnchoredCoords(anchorRight, anchorBottom, offsetX, offsetY) + return anchoredCoords + } + + 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/features/inventory/buttons/InventoryButtonTemplates.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtonTemplates.kt new file mode 100644 index 0000000..d282157 --- /dev/null +++ b/src/main/kotlin/features/inventory/buttons/InventoryButtonTemplates.kt @@ -0,0 +1,33 @@ +package moe.nea.firmament.features.inventory.buttons + +import kotlinx.serialization.encodeToString +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.util.ErrorUtil +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? { + val buttons = TemplateUtil.maybeDecodeTemplate>(legacyPrefix, t) ?: return null + return buttons.mapNotNull { + ErrorUtil.catch("Could not import button") { + Firmament.json.decodeFromString(it).also { + if (it.icon?.startsWith("extra:") == true) { + MC.sendChat(Text.translatable("firmament.inventory-buttons.import-failed")) + } + } + }.or { + null + } + } + } + + fun saveTemplate(buttons: List): String { + return TemplateUtil.encodeTemplate(legacyPrefix, buttons.map { Firmament.json.encodeToString(it) }) + } +} diff --git a/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt new file mode 100644 index 0000000..ab80d97 --- /dev/null +++ b/src/main/kotlin/features/inventory/buttons/InventoryButtons.kt @@ -0,0 +1,114 @@ + + +package moe.nea.firmament.features.inventory.buttons + +import me.shedaniel.math.Rectangle +import kotlinx.serialization.Serializable +import kotlinx.serialization.serializer +import kotlin.time.Duration.Companion.seconds +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.gui.screen.ingame.InventoryScreen +import net.minecraft.text.Text +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.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.ScreenUtil +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.data.DataHolder +import moe.nea.firmament.util.accessors.getRectangle +import moe.nea.firmament.util.gold + +object InventoryButtons { + + object TConfig : ManagedConfig("inventory-buttons-config", Category.INVENTORY) { + val _openEditor by button("open-editor") { + openEditor() + } + val hoverText by toggle("hover-text") { true } + val onlyInv by toggle("only-inv") { false } + } + + object DConfig : DataHolder(serializer(), "inventory-buttons", ::Data) + + @Serializable + data class Data( + var buttons: MutableList = mutableListOf() + ) + + fun getValidButtons(screen: HandledScreen<*>): Sequence { + return DConfig.data.buttons.asSequence().filter { button -> + button.isValid() && (!TConfig.onlyInv || screen is InventoryScreen) + } + } + + + @Subscribe + fun onRectangles(it: HandledScreenPushREIEvent) { + val bounds = it.screen.getRectangle() + for (button in getValidButtons(it.screen)) { + val buttonBounds = button.getBounds(bounds) + it.block(buttonBounds) + } + } + + @Subscribe + fun onClickScreen(it: HandledScreenClickEvent) { + val bounds = it.screen.getRectangle() + for (button in getValidButtons(it.screen)) { + val buttonBounds = button.getBounds(bounds) + if (buttonBounds.contains(it.mouseX, it.mouseY)) { + MC.sendCommand(button.command!! /* non null invariant covered by getValidButtons */) + break + } + } + } + + var lastHoveredComponent: InventoryButton? = null + var lastMouseMove = TimeMark.farPast() + + @Subscribe + fun onRenderForeground(it: HandledScreenForegroundEvent) { + val bounds = it.screen.getRectangle() + + var hoveredComponent: InventoryButton? = null + for (button in getValidButtons(it.screen)) { + 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() + + if (buttonBounds.contains(it.mouseX, it.mouseY) && TConfig.hoverText && hoveredComponent == null) { + hoveredComponent = button + if (lastMouseMove.passedTime() > 0.6.seconds && lastHoveredComponent === button) { + it.context.drawTooltip( + MC.font, + listOf(Text.literal(button.command).gold()), + buttonBounds.minX - 15, + buttonBounds.maxY + 20, + ) + } + } + } + if (hoveredComponent !== lastHoveredComponent) + lastMouseMove = TimeMark.now() + lastHoveredComponent = hoveredComponent + lastRectangle = bounds + } + + var lastRectangle: Rectangle? = null + fun openEditor() { + ScreenUtil.setScreenLater( + InventoryButtonEditor( + lastRectangle ?: Rectangle( + MC.window.scaledWidth / 2 - 88, + MC.window.scaledHeight / 2 - 83, + 176, 166, + ) + ) + ) + } +} diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt new file mode 100644 index 0000000..d7346c2 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageBackingHandle.kt @@ -0,0 +1,59 @@ +@file:OptIn(ExperimentalContracts::class) + +package moe.nea.firmament.features.inventory.storageoverlay + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract +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 ` 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. + */ + @OptIn(ExperimentalContracts::class) + fun fromScreen(screen: Screen?): StorageBackingHandle? { + contract { + returnsNotNull() implies (screen != null) + } + 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/features/inventory/storageoverlay/StorageData.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageData.kt new file mode 100644 index 0000000..7555c56 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageData.kt @@ -0,0 +1,21 @@ + + +@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 = sortedMapOf() +) { + @Serializable + data class StorageInventory( + var title: String, + val slot: StoragePageSlot, + var inventory: VirtualInventory?, + ) +} diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt new file mode 100644 index 0000000..f59b293 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlay.kt @@ -0,0 +1,200 @@ +package moe.nea.firmament.features.inventory.storageoverlay + +import io.github.notenoughupdates.moulconfig.ChromaColour +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.SlotRenderEvents +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(serializer(), "storage-data", ::StorageData) + + override val identifier: String + get() = "storage-overlay" + + object TConfig : ManagedConfig(identifier, Category.INVENTORY) { + val alwaysReplace by toggle("always-replace") { true } + val outlineActiveStoragePage by toggle("outline-active-page") { false } + val outlineActiveStoragePageColour by colour("outline-active-page-colour") { + ChromaColour.fromRGB( + 255, + 255, + 0, + 0, + 255 + ) + } + val columns by integer("rows", 1, 10) { 3 } + val height by integer("height", 80, 3000) { 3 * 18 * 6 } + val retainScroll by toggle("retain-scroll") { true } + 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 } + val itemsBlockScrolling by toggle("block-item-scrolling") { true } + val highlightSearchResults by toggle("highlight-search-results") { true } + val highlightSearchResultsColour by colour("highlight-search-results-colour") { + ChromaColour.fromRGB( + 0, + 176, + 0, + 0, + 255 + ) + } + } + + @Subscribe + fun highlightSlots(event: SlotRenderEvents.Before) { + if (!TConfig.highlightSearchResults) return + val storageOverlayScreen = + (MC.screen as? StorageOverlayScreen) + ?: (MC.handledScreen?.customGui as? StorageOverlayCustom)?.overview + ?: return + val stack = event.slot.stack ?: return + val search = storageOverlayScreen.searchText.get().takeIf { it.isNotBlank() } ?: return + if (storageOverlayScreen.matchesSearch(stack, search)) { + event.context.fill( + event.slot.x, + event.slot.y, + event.slot.x + 16, + event.slot.y + 16, + TConfig.highlightSearchResultsColour.getEffectiveColourRGB() + ) + } + } + + + 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 + if (storageOverlayScreen?.isExiting == true) 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 + ) { + 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 + ) { + // 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/features/inventory/storageoverlay/StorageOverlayCustom.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt new file mode 100644 index 0000000..e4d4e42 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayCustom.kt @@ -0,0 +1,122 @@ +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 +import moe.nea.firmament.util.focusedItemStack + +class StorageOverlayCustom( + val handler: StorageBackingHandle, + val screen: GenericContainerScreen, + val overview: StorageOverlayScreen, +) : CustomGui() { + override fun onVoluntaryExit(): Boolean { + overview.isExiting = true + StorageOverlayScreen.resetScroll() + return super.onVoluntaryExit() + } + + override fun getBounds(): List { + 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 mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + return overview.mouseReleased(mouseX, mouseY, button) + } + + override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + return overview.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) + } + + override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return overview.keyReleased(keyCode, scanCode, modifiers) + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return overview.keyPressed(keyCode, scanCode, modifiers) + } + + override fun charTyped(chr: Char, modifiers: Int): Boolean { + return overview.charTyped(chr, modifiers) + } + + 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) + overview.drawControls(drawContext, mouseX, mouseY) + } + + 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 { + if (screen.focusedItemStack != null && StorageOverlay.TConfig.itemsBlockScrolling) + return false + return overview.mouseScrolled(mouseX, mouseY, horizontalAmount, verticalAmount) + } +} diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt new file mode 100644 index 0000000..267799d --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverlayScreen.kt @@ -0,0 +1,562 @@ +package moe.nea.firmament.features.inventory.storageoverlay + +import io.github.notenoughupdates.moulconfig.common.IMinecraft +import io.github.notenoughupdates.moulconfig.gui.GuiContext +import io.github.notenoughupdates.moulconfig.gui.KeyboardEvent +import io.github.notenoughupdates.moulconfig.gui.MouseEvent +import io.github.notenoughupdates.moulconfig.gui.component.ColumnComponent +import io.github.notenoughupdates.moulconfig.gui.component.PanelComponent +import io.github.notenoughupdates.moulconfig.gui.component.TextComponent +import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent +import io.github.notenoughupdates.moulconfig.observer.GetSetter +import io.github.notenoughupdates.moulconfig.observer.Property +import java.util.TreeSet +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.client.gui.screen.ingame.HandledScreen +import net.minecraft.item.ItemStack +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.SlotRenderEvents +import moe.nea.firmament.gui.EmptyComponent +import moe.nea.firmament.gui.FirmButtonComponent +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MoulConfigUtils.adopt +import moe.nea.firmament.util.MoulConfigUtils.clickMCComponentInPlace +import moe.nea.firmament.util.MoulConfigUtils.drawMCComponentInPlace +import moe.nea.firmament.util.MoulConfigUtils.typeMCComponentInPlace +import moe.nea.firmament.util.StringUtil.words +import moe.nea.firmament.util.assertTrueOr +import moe.nea.firmament.util.customgui.customGui +import moe.nea.firmament.util.mc.FakeSlot +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.render.drawGuiTexture +import moe.nea.firmament.util.render.enableScissorWithoutTranslation +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.unformattedString + +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_SLOTS_WIDTH = SLOT_SIZE * 9 + val PAGE_WIDTH = PAGE_SLOTS_WIDTH + 4 + val HOTBAR_X = 12 + val HOTBAR_Y = 67 + val MAIN_INVENTORY_Y = 9 + val SCROLL_BAR_WIDTH = 8 + val SCROLL_BAR_HEIGHT = 16 + val CONTROL_X_INSET = 3 + val CONTROL_Y_INSET = 5 + val CONTROL_WIDTH = 70 + val CONTROL_BACKGROUND_WIDTH = CONTROL_WIDTH + CONTROL_X_INSET + 1 + val CONTROL_HEIGHT = 50 + + var scroll: Float = 0F + var lastRenderedInnerHeight = 0 + + fun resetScroll() { + if (!StorageOverlay.TConfig.retainScroll) scroll = 0F + } + } + + var isExiting: Boolean = false + 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( + height - PLAYER_HEIGHT - minOf(80, height / 10), + StorageOverlay.TConfig.height + ) + 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 controlX = playerX - CONTROL_WIDTH + CONTROL_X_INSET + val controlY = playerY - CONTROL_Y_INSET + val totalWidth = overviewWidth + val totalHeight = overviewHeight - PLAYER_Y_INSET + PLAYER_HEIGHT + } + + var measurements = Measurements() + + public override fun init() { + super.init() + pageWidthCount = StorageOverlay.TConfig.columns + .coerceAtMost((width - PADDING) / (PAGE_WIDTH + PADDING)) + .coerceAtLeast(1) + measurements = Measurements() + scroll = scroll.coerceAtMost(getMaxScroll()).coerceAtLeast(0F) + } + + override fun mouseScrolled( + mouseX: Double, + mouseY: Double, + horizontalAmount: Double, + verticalAmount: Double + ): Boolean { + coerceScroll(StorageOverlay.adjustScrollSpeed(verticalAmount).toFloat()) + return true + } + + fun coerceScroll(offset: Float) { + scroll = (scroll + offset) + .coerceAtMost(getMaxScroll()) + .coerceAtLeast(0F) + } + + 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") + val controllerBackground = Identifier.of("firmament:storageoverlay/storage_controls") + + override fun close() { + isExiting = true + resetScroll() + 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) + drawControls(context, mouseX, mouseY) + } + + 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 editPages() { + isExiting = true + MC.instance.send { + val hs = MC.screen as? HandledScreen<*> + if (StorageBackingHandle.fromScreen(hs) is StorageBackingHandle.Overview) { + hs.customGui = null + hs.init(MC.instance, width, height) + } else { + MC.sendCommand("storage") + } + } + } + + val guiContext = GuiContext(EmptyComponent()) + private val knobStub = EmptyComponent() + val editButton = FirmButtonComponent( + TextComponent(tr("firmament.storage-overlay.edit-pages", "Edit Pages").string), + action = ::editPages + ) + val searchText = Property.of("") // TODO: sync with REI + val searchField = TextFieldComponent( + searchText, 100, GetSetter.constant(true), + tr("firmament.storage-overlay.search.suggestion", "Search...").string, + IMinecraft.instance.defaultFontRenderer + ) + val controlComponent = PanelComponent( + ColumnComponent( + searchField, + editButton, + ), + 8, PanelComponent.DefaultBackgroundRenderer.TRANSPARENT + ) + + init { + searchText.addObserver { _, _ -> + layoutedForEach(StorageOverlay.Data.data ?: StorageData(), { _, _, _ -> }) + coerceScroll(0F) + } + guiContext.adopt(knobStub) + guiContext.adopt(controlComponent) + } + + fun drawControls(context: DrawContext, mouseX: Int, mouseY: Int) { + context.drawGuiTexture( + controllerBackground, + measurements.controlX, + measurements.controlY, + CONTROL_BACKGROUND_WIDTH, CONTROL_HEIGHT + ) + context.drawMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + mouseX, mouseY + ) + } + + fun drawBackgrounds(context: DrawContext) { + context.drawGuiTexture( + upperBackgroundSprite, + measurements.x, + measurements.y, + measurements.overviewWidth, + measurements.overviewHeight + ) + context.drawGuiTexture( + playerInventorySprite, + measurements.playerX, + measurements.playerY, + PLAYER_WIDTH, + PLAYER_HEIGHT + ) + } + + fun getPlayerInventorySlotPosition(int: Int): Pair { + 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?.mainStacks ?: return + items.withIndex().forEach { (index, item) -> + val (x, y) = getPlayerInventorySlotPosition(index) + context.drawItem(item, x, y, 0) + context.drawStackOverlay(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.enableScissorWithoutTranslation( + rect.minX.toFloat(), rect.minY.toFloat(), + rect.maxX.toFloat(), rect.maxY.toFloat(), + ) + } + + fun drawPages( + context: DrawContext, mouseX: Int, mouseY: Int, delta: Float, + excluding: StoragePageSlot?, + slots: List?, + 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() + } + + + var knobGrabbed: Boolean + get() = guiContext.focusedElement == knobStub + set(value) = knobStub.setFocus(value) + + override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean { + return mouseClicked(mouseX, mouseY, button, null) + } + + override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + if (knobGrabbed) { + knobGrabbed = false + return true + } + if (clickMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + mouseX.toInt(), mouseY.toInt(), + MouseEvent.Click(button, false) + ) + ) return true + return super.mouseReleased(mouseX, mouseY, button) + } + + override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + if (knobGrabbed) { + val sbRect = getScrollBarRect() + val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight() + scroll = (getMaxScroll() * percentage).toFloat() + mouseScrolled(0.0, 0.0, 0.0, 0.0) + return true + } + return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY) + } + + fun mouseClicked(mouseX: Double, mouseY: Double, button: Int, activePage: StoragePageSlot?): Boolean { + guiContext.setFocusedElement(null) // Blur all elements. They will be refocused by clickMCComponentInPlace if in doubt, and we don't have any double click components. + 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)) { + val percentage = (mouseY - sbRect.getY()) / sbRect.getHeight() + scroll = (getMaxScroll() * percentage).toFloat() + mouseScrolled(0.0, 0.0, 0.0, 0.0) + knobGrabbed = true + return true + } + if (clickMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + mouseX.toInt(), mouseY.toInt(), + MouseEvent.Click(button, true) + ) + ) return true + return false + } + + override fun charTyped(chr: Char, modifiers: Int): Boolean { + if (typeMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + KeyboardEvent.CharTyped(chr) + ) + ) { + return true + } + return super.charTyped(chr, modifiers) + } + + override fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + if (typeMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + KeyboardEvent.KeyPressed(keyCode, false) + ) + ) { + return true + } + return super.keyReleased(keyCode, scanCode, modifiers) + } + + override fun shouldCloseOnEsc(): Boolean { + return this === MC.screen // Fixes this UI closing the handled screen on Escape press. + } + + override fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + if (typeMCComponentInPlace( + controlComponent, + measurements.controlX, measurements.controlY, + CONTROL_WIDTH, CONTROL_HEIGHT, + KeyboardEvent.KeyPressed(keyCode, true) + ) + ) { + return true + } + return super.keyPressed(keyCode, scanCode, modifiers) + } + + + var searchCache: String? = null + var filteredPagesCache = setOf() + + fun getFilteredPages(): Set { + val searchValue = searchText.get() + val data = StorageOverlay.Data.data ?: return filteredPagesCache // Do not update cache if data is missing + if (searchCache == searchValue) return filteredPagesCache + val result = + data.storageInventories + .entries.asSequence() + .filter { it.value.inventory?.stacks?.any { matchesSearch(it, searchValue) } ?: true } + .map { it.key } + .toSet() + searchCache = searchValue + filteredPagesCache = result + return result + } + + + fun matchesSearch(itemStack: ItemStack, search: String): Boolean { + val searchWords = search.words().toCollection(TreeSet()) + fun removePrefixes(value: String) { + searchWords.removeIf { value.contains(it, ignoreCase = true) } + } + itemStack.displayNameAccordingToNbt.unformattedString.words().forEach(::removePrefixes) + if (searchWords.isEmpty()) return true + itemStack.loreAccordingToNbt.forEach { + it.unformattedString.words().forEach(::removePrefixes) + } + return searchWords.isEmpty() + } + + 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 + val filter = getFilteredPages() + for ((page, inventory) in data.storageInventories.entries) { + if (page !in filter) continue + val currentHeight = inventory.inventory?.let { it.rows * SLOT_SIZE + 6 + 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?, + 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() + val pageHeight = inv.rows * SLOT_SIZE + 8 + textRenderer.fontHeight + if (slots != null && StorageOverlay.TConfig.outlineActiveStoragePage) + context.drawBorder( + x, + y + 3 + textRenderer.fontHeight, + PAGE_WIDTH, + inv.rows * SLOT_SIZE + 4, + StorageOverlay.TConfig.outlineActiveStoragePageColour.getEffectiveColourRGB() + ) + context.drawText( + textRenderer, Text.literal(name), x + 6, y + 3, + if (slots == null) 0xFFFFFFFF.toInt() else 0xFFFFFF00.toInt(), true + ) + context.drawGuiTexture( + slotRowSprite, + x + 2, + y + 5 + textRenderer.fontHeight, + PAGE_SLOTS_WIDTH, + inv.rows * SLOT_SIZE + ) + inv.stacks.forEachIndexed { index, stack -> + val slotX = (index % 9) * SLOT_SIZE + x + 3 + val slotY = (index / 9) * SLOT_SIZE + y + 5 + textRenderer.fontHeight + 1 + val fakeSlot = FakeSlot(stack, slotX, slotY) + if (slots == null) { + SlotRenderEvents.Before.publish(SlotRenderEvents.Before(context, fakeSlot)) + context.drawItem(stack, slotX, slotY) + context.drawStackOverlay(textRenderer, stack, slotX, slotY) + SlotRenderEvents.After.publish(SlotRenderEvents.After(context, fakeSlot)) + } else { + val slot = slots[index] + slot.x = slotX - slotOffset.x + slot.y = slotY - slotOffset.y + } + } + return pageHeight + 6 + } + + fun getBounds(): List { + return listOf( + Rectangle( + measurements.x, + measurements.y, + measurements.overviewWidth, + measurements.overviewHeight + ), + Rectangle( + measurements.playerX, + measurements.playerY, + PLAYER_WIDTH, + PLAYER_HEIGHT + ), + Rectangle( + measurements.controlX, + measurements.controlY, + CONTROL_WIDTH, + CONTROL_HEIGHT + ) + ) + } +} diff --git a/src/main/kotlin/features/inventory/storageoverlay/StorageOverviewScreen.kt b/src/main/kotlin/features/inventory/storageoverlay/StorageOverviewScreen.kt new file mode 100644 index 0000000..3462d3d --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StorageOverviewScreen.kt @@ -0,0 +1,135 @@ + + +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( + Blocks.RED_STAINED_GLASS_PANE.asItem(), + Blocks.BROWN_STAINED_GLASS_PANE.asItem(), + Items.GRAY_DYE + ) + val pageWidth get() = 19 * 9 + + var scroll = 0 + var lastRenderedHeight = 0 + } + + val content = StorageOverlay.Data.data ?: StorageData() + var isClosing = false + + override fun init() { + super.init() + scroll = scroll.coerceAtMost(getMaxScroll()).coerceAtLeast(0) + } + + override fun close() { + if (!StorageOverlay.TConfig.retainScroll) scroll = 0 + super.close() + } + + 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, 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(getMaxScroll()).coerceAtLeast(0) + return true + } + + private fun getMaxScroll() = lastRenderedHeight - height + 2 * StorageOverlay.config.margin + + 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.drawStackOverlay(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/features/inventory/storageoverlay/StoragePageSlot.kt b/src/main/kotlin/features/inventory/storageoverlay/StoragePageSlot.kt new file mode 100644 index 0000000..9259415 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/StoragePageSlot.kt @@ -0,0 +1,66 @@ + + +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 { + object Serializer : KSerializer { + 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/features/inventory/storageoverlay/VirtualInventory.kt b/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt new file mode 100644 index 0000000..d99acd7 --- /dev/null +++ b/src/main/kotlin/features/inventory/storageoverlay/VirtualInventory.kt @@ -0,0 +1,76 @@ +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 kotlin.jvm.optionals.getOrNull +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 +import net.minecraft.registry.RegistryOps +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.mc.TolerantRegistriesOps + +@Serializable(with = VirtualInventory.Serializer::class) +data class VirtualInventory( + val stacks: List +) { + val rows = stacks.size / 9 + + init { + assert(stacks.size % 9 == 0) + assert(stacks.size / 9 in 1..5) + } + + + object Serializer : KSerializer { + 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).getOrNull() + val ops = getOps() + return VirtualInventory(items?.map { + it as NbtCompound + if (it.isEmpty) ItemStack.EMPTY + else ErrorUtil.catch("Could not deserialize item") { + ItemStack.CODEC.parse(ops, it).orThrow + }.or { ItemStack.EMPTY } + } ?: listOf()) + } + + fun getOps() = TolerantRegistriesOps(NbtOps.INSTANCE, MC.currentOrDefaultRegistries) + + override fun serialize(encoder: Encoder, value: VirtualInventory) { + val list = NbtList() + val ops = getOps() + value.stacks.forEach { + if (it.isEmpty) list.add(NbtCompound()) + else list.add(ErrorUtil.catch("Could not serialize item") { + ItemStack.CODEC.encode(it, + ops, + NbtCompound()).orThrow + } + .or { NbtCompound() }) + } + val baos = ByteArrayOutputStream() + NbtIo.writeCompressed(NbtCompound().also { it.put(INVENTORY, list) }, baos) + encoder.encodeString(baos.toByteArray().encodeBase64()) + } + } +} diff --git a/src/main/kotlin/features/items/BlockZapperOverlay.kt b/src/main/kotlin/features/items/BlockZapperOverlay.kt new file mode 100644 index 0000000..c207d67 --- /dev/null +++ b/src/main/kotlin/features/items/BlockZapperOverlay.kt @@ -0,0 +1,146 @@ +package moe.nea.firmament.features.items + +import io.github.notenoughupdates.moulconfig.ChromaColour +import java.util.LinkedList +import net.minecraft.block.Block +import net.minecraft.block.BlockState +import net.minecraft.block.Blocks +import net.minecraft.util.hit.BlockHitResult +import net.minecraft.util.hit.HitResult +import net.minecraft.util.math.BlockPos +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ClientStartedEvent +import moe.nea.firmament.events.WorldKeyboardEvent +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.render.RenderInWorldContext +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems + +object BlockZapperOverlay : FirmamentFeature { + override val identifier: String + get() = "block-zapper-overlay" + + object TConfig : ManagedConfig(identifier, Category.ITEMS) { + var blockZapperOverlay by toggle("block-zapper-overlay") { false } + val color by colour("color") { ChromaColour.fromStaticRGB(160, 0, 0, 60) } + var undoKey by keyBindingWithDefaultUnbound("undo-key") + } + + @Subscribe + fun onInit(event: ClientStartedEvent) { + } + + override val config: ManagedConfig + get() = TConfig + + val bannedZapper: List = listOf( + Blocks.WHEAT, + Blocks.CARROTS, + Blocks.POTATOES, + Blocks.PUMPKIN, + Blocks.PUMPKIN_STEM, + Blocks.MELON, + Blocks.MELON_STEM, + Blocks.CACTUS, + Blocks.SUGAR_CANE, + Blocks.NETHER_WART, + Blocks.TALL_GRASS, + Blocks.SUNFLOWER, + Blocks.FARMLAND, + Blocks.BREWING_STAND, + Blocks.SNOW, + Blocks.RED_MUSHROOM, + Blocks.BROWN_MUSHROOM, + ) + + private val zapperOffsets: List = listOf( + BlockPos(0, 0, -1), + BlockPos(0, 0, 1), + BlockPos(-1, 0, 0), + BlockPos(1, 0, 0), + BlockPos(0, 1, 0), + BlockPos(0, -1, 0) + ) + + // Skidded from NEU + // Credit: https://github.com/NotEnoughUpdates/NotEnoughUpdates/blob/9b1fcfebc646e9fb69f99006327faa3e734e5f51/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java#L1281-L1355 (Modified) + @Subscribe + fun renderBlockZapperOverlay(event: WorldRenderLastEvent) { + if (!TConfig.blockZapperOverlay) return + val player = MC.player ?: return + val world = player.world ?: return + val heldItem = MC.stackInHand + if (heldItem.skyBlockId != SkyBlockItems.BLOCK_ZAPPER) return + val hitResult = MC.instance.crosshairTarget ?: return + + val zapperBlocks: HashSet = HashSet() + val returnablePositions = LinkedList() + + if (hitResult is BlockHitResult && hitResult.type == HitResult.Type.BLOCK) { + var pos: BlockPos = hitResult.blockPos + val firstBlockState: BlockState = world.getBlockState(pos) + val block = firstBlockState.block + + val initialAboveBlock = world.getBlockState(pos.up()).block + if (!bannedZapper.contains(initialAboveBlock) && !bannedZapper.contains(block)) { + var i = 0 + while (i < 164) { + zapperBlocks.add(pos) + returnablePositions.remove(pos) + + val availableNeighbors: MutableList = ArrayList() + + for (offset in zapperOffsets) { + val newPos = pos.add(offset) + + if (zapperBlocks.contains(newPos)) continue + + val state: BlockState? = world.getBlockState(newPos) + if (state != null && state.block === block) { + val above = newPos.up() + val aboveBlock = world.getBlockState(above).block + if (!bannedZapper.contains(aboveBlock)) { + availableNeighbors.add(newPos) + } + } + } + + if (availableNeighbors.size >= 2) { + returnablePositions.add(pos) + pos = availableNeighbors[0] + } else if (availableNeighbors.size == 1) { + pos = availableNeighbors[0] + } else if (returnablePositions.isEmpty()) { + break + } else { + i-- + pos = returnablePositions.last() + } + + i++ + } + } + + RenderInWorldContext.renderInWorld(event) { + if (MC.player?.isSneaking ?: false) { + zapperBlocks.forEach { + block(it, TConfig.color.getEffectiveColourRGB()) + } + } else { + sharedVoxelSurface(zapperBlocks, TConfig.color.getEffectiveColourRGB()) + } + } + } + } + + @Subscribe + fun onWorldKeyboard(it: WorldKeyboardEvent) { + if (!TConfig.undoKey.isBound) return + if (!it.matches(TConfig.undoKey)) return + if (MC.stackInHand.skyBlockId != SkyBlockItems.BLOCK_ZAPPER) return + MC.sendCommand("undozap") + } +} diff --git a/src/main/kotlin/features/items/BonemerangOverlay.kt b/src/main/kotlin/features/items/BonemerangOverlay.kt new file mode 100644 index 0000000..ffdffe3 --- /dev/null +++ b/src/main/kotlin/features/items/BonemerangOverlay.kt @@ -0,0 +1,101 @@ +package moe.nea.firmament.features.items + +import me.shedaniel.math.Color +import moe.nea.jarvis.api.Point +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.decoration.ArmorStandEntity +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.util.Formatting +import net.minecraft.util.math.Box +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ClientStartedEvent +import moe.nea.firmament.events.EntityRenderTintEvent +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.render.TintedOverlayTexture +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems +import moe.nea.firmament.util.tr + +object BonemerangOverlay : FirmamentFeature { + override val identifier: String + get() = "bonemerang-overlay" + + object TConfig : ManagedConfig(identifier, Category.ITEMS) { + var bonemerangOverlay by toggle("bonemerang-overlay") { false } + val bonemerangOverlayHud by position("bonemerang-overlay-hud", 80, 10) { Point(0.1, 1.0) } + var highlightHitEntities by toggle("highlight-hit-entities") { false } + } + + @Subscribe + fun onInit(event: ClientStartedEvent) { + } + + override val config: ManagedConfig + get() = TConfig + + fun getEntities(): MutableSet { + val entities = mutableSetOf() + val camera = MC.camera as? PlayerEntity ?: return entities + val player = MC.player ?: return entities + val world = player.world ?: return entities + + val cameraPos = camera.eyePos + val rayDirection = camera.rotationVector.normalize() + val endPos = cameraPos.add(rayDirection.multiply(15.0)) + val foundEntities = world.getOtherEntities(camera, Box(cameraPos, endPos).expand(1.0)) + + for (entity in foundEntities) { + if (entity !is LivingEntity || entity is ArmorStandEntity || entity.isInvisible) continue + val hitResult = entity.boundingBox.expand(0.35).raycast(cameraPos, endPos).orElse(null) + if (hitResult != null) entities.add(entity) + } + + return entities + } + + + val throwableWeapons = listOf( + SkyBlockItems.BONE_BOOMERANG, SkyBlockItems.STARRED_BONE_BOOMERANG, + SkyBlockItems.TRIBAL_SPEAR, + ) + + + @Subscribe + fun onEntityRender(event: EntityRenderTintEvent) { + if (!TConfig.highlightHitEntities) return + if (MC.stackInHand.skyBlockId !in throwableWeapons) return + + val entities = getEntities() + if (entities.isEmpty()) return + if (event.entity !in entities) return + + val tintOverlay by lazy { + TintedOverlayTexture().setColor(Color.ofOpaque(Formatting.BLUE.colorValue!!)) + } + + event.renderState.overlayTexture_firmament = tintOverlay + } + + + @Subscribe + fun onRenderHud(it: HudRenderEvent) { + if (!TConfig.bonemerangOverlay) return + if (MC.stackInHand.skyBlockId !in throwableWeapons) return + + val entities = getEntities() + + it.context.matrices.push() + TConfig.bonemerangOverlayHud.applyTransformations(it.context.matrices) + it.context.drawText( + MC.font, String.format( + tr( + "firmament.bonemerang-overlay.bonemerang-overlay.display", "Bonemerang Targets: %s" + ).string, entities.size + ), 0, 0, -1, true + ) + it.context.matrices.pop() + } +} diff --git a/src/main/kotlin/features/items/EtherwarpOverlay.kt b/src/main/kotlin/features/items/EtherwarpOverlay.kt new file mode 100644 index 0000000..f6ab1a2 --- /dev/null +++ b/src/main/kotlin/features/items/EtherwarpOverlay.kt @@ -0,0 +1,54 @@ +package moe.nea.firmament.features.items + +import io.github.notenoughupdates.moulconfig.ChromaColour +import me.shedaniel.math.Color +import net.minecraft.util.hit.BlockHitResult +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.extraAttributes +import moe.nea.firmament.util.render.RenderInWorldContext +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.SkyBlockItems + +object EtherwarpOverlay : FirmamentFeature { + override val identifier: String + get() = "etherwarp-overlay" + + object TConfig : ManagedConfig(identifier, Category.ITEMS) { + var etherwarpOverlay by toggle("etherwarp-overlay") { false } + var onlyShowWhileSneaking by toggle("only-show-while-sneaking") { true } + var cube by toggle("cube") { true } + val cubeColour by colour("cube-colour") { ChromaColour.fromStaticRGB(172, 0, 255, 60) } + var wireframe by toggle("wireframe") { false } + } + + override val config: ManagedConfig + get() = TConfig + + + @Subscribe + fun renderEtherwarpOverlay(event: WorldRenderLastEvent) { + if (!TConfig.etherwarpOverlay) return + val player = MC.player ?: return + if (TConfig.onlyShowWhileSneaking && !player.isSneaking) return + val world = player.world + val camera = MC.camera ?: return + val heldItem = MC.stackInHand + if (heldItem.skyBlockId !in listOf(SkyBlockItems.ASPECT_OF_THE_VOID, SkyBlockItems.ASPECT_OF_THE_END)) return + if (!heldItem.extraAttributes.contains("ethermerge")) return + + val hitResult = camera.raycast(61.0, 0.0f, false) + if (hitResult !is BlockHitResult) return + val blockPos = hitResult.blockPos + if (camera.squaredDistanceTo(blockPos.toCenterPos()) > 61 * 61) return + if (!world.getBlockState(blockPos.up()).isAir) return + if (!world.getBlockState(blockPos.up(2)).isAir) return + RenderInWorldContext.renderInWorld(event) { + if (TConfig.cube) block(blockPos, TConfig.cubeColour.getEffectiveColourRGB()) + if (TConfig.wireframe) wireframeCube(blockPos, 10f) + } + } +} diff --git a/src/main/kotlin/features/macros/ComboProcessor.kt b/src/main/kotlin/features/macros/ComboProcessor.kt new file mode 100644 index 0000000..5c5ac0e --- /dev/null +++ b/src/main/kotlin/features/macros/ComboProcessor.kt @@ -0,0 +1,114 @@ +package moe.nea.firmament.features.macros + +import kotlin.time.Duration.Companion.seconds +import net.minecraft.client.util.InputUtil +import net.minecraft.text.Text +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.events.WorldKeyboardEvent +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.tr + +object ComboProcessor { + + var rootTrie: Branch = Branch(mapOf()) + private set + + var activeTrie: Branch = rootTrie + private set + + var isInputting = false + var lastInput = TimeMark.farPast() + val breadCrumbs = mutableListOf() + + init { + val f = SavedKeyBinding(InputUtil.GLFW_KEY_F) + val one = SavedKeyBinding(InputUtil.GLFW_KEY_1) + val two = SavedKeyBinding(InputUtil.GLFW_KEY_2) + setActions( + MacroData.DConfig.data.comboActions + ) + } + + fun setActions(actions: List) { + rootTrie = KeyComboTrie.fromComboList(actions) + reset() + } + + fun reset() { + activeTrie = rootTrie + lastInput = TimeMark.now() + isInputting = false + breadCrumbs.clear() + } + + @Subscribe + fun onTick(event: TickEvent) { + if (isInputting && lastInput.passedTime() > 3.seconds) + reset() + } + + + @Subscribe + fun onRender(event: HudRenderEvent) { + if (!isInputting) return + if (!event.isRenderingHud) return + event.context.matrices.push() + val width = 120 + event.context.matrices.translate( + (MC.window.scaledWidth - width) / 2F, + (MC.window.scaledHeight) / 2F + 8, + 0F + ) + val breadCrumbText = breadCrumbs.joinToString(" > ") + event.context.drawText( + MC.font, + tr("firmament.combo.active", "Current Combo: ").append(breadCrumbText), + 0, + 0, + -1, + true + ) + event.context.matrices.translate(0F, MC.font.fontHeight + 2F, 0F) + for ((key, value) in activeTrie.nodes) { + event.context.drawText( + MC.font, + Text.literal("$breadCrumbText > $key: ").append(value.label), + 0, + 0, + -1, + true + ) + event.context.matrices.translate(0F, MC.font.fontHeight + 1F, 0F) + } + event.context.matrices.pop() + } + + @Subscribe + fun onKeyBinding(event: WorldKeyboardEvent) { + val nextEntry = activeTrie.nodes.entries + .find { event.matches(it.key) } + if (nextEntry == null) { + reset() + return + } + event.cancel() + breadCrumbs.add(nextEntry.key) + lastInput = TimeMark.now() + isInputting = true + val value = nextEntry.value + when (value) { + is Branch -> { + activeTrie = value + } + + is Leaf -> { + value.execute() + reset() + } + }.let { } + } +} diff --git a/src/main/kotlin/features/macros/HotkeyAction.kt b/src/main/kotlin/features/macros/HotkeyAction.kt new file mode 100644 index 0000000..011f797 --- /dev/null +++ b/src/main/kotlin/features/macros/HotkeyAction.kt @@ -0,0 +1,40 @@ +package moe.nea.firmament.features.macros + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.minecraft.text.Text +import moe.nea.firmament.util.MC + +@Serializable +sealed interface HotkeyAction { + // TODO: execute + val label: Text + fun execute() +} + +@Serializable +@SerialName("command") +data class CommandAction(val command: String) : HotkeyAction { + override val label: Text + get() = Text.literal("/$command") + + override fun execute() { + MC.sendCommand(command) + } +} + +// Mit onscreen anzeige: +// F -> 1 /equipment +// F -> 2 /wardrobe +// Bei Combos: Keys buffern! (für wardrobe hotkeys beispielsweiße) + +// Radial menu +// Hold F +// Weight (mach eins doppelt so groß) +// /equipment +// /wardrobe + +// Bei allen: Filter! +// - Nur in Dungeons / andere Insel +// - Nur wenn ich Item X im inventar habe (fishing rod) + diff --git a/src/main/kotlin/features/macros/KeyComboTrie.kt b/src/main/kotlin/features/macros/KeyComboTrie.kt new file mode 100644 index 0000000..452bc56 --- /dev/null +++ b/src/main/kotlin/features/macros/KeyComboTrie.kt @@ -0,0 +1,73 @@ +package moe.nea.firmament.features.macros + +import kotlinx.serialization.Serializable +import net.minecraft.text.Text +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.ErrorUtil + +sealed interface KeyComboTrie { + val label: Text + + companion object { + fun fromComboList( + combos: List, + ): Branch { + val root = Branch(mutableMapOf()) + for (combo in combos) { + var p = root + if (combo.keys.isEmpty()) { + ErrorUtil.softUserError("Key Combo for ${combo.action.label.string} is empty") + continue + } + for ((index, key) in combo.keys.withIndex()) { + val m = (p.nodes as MutableMap) + if (index == combo.keys.lastIndex) { + if (key in m) { + ErrorUtil.softUserError("Overlapping actions found for ${combo.keys.joinToString(" > ")} (another action ${m[key]} already exists).") + break + } + + m[key] = Leaf(combo.action) + } else { + val c = m.getOrPut(key) { Branch(mutableMapOf()) } + if (c !is Branch) { + ErrorUtil.softUserError("Overlapping actions found for ${combo.keys} (final node exists at index $index) through another action already") + break + } else { + p = c + } + } + } + } + return root + } + } +} + +@Serializable +data class MacroWheel( + val key: SavedKeyBinding, + val options: List +) + +@Serializable +data class ComboKeyAction( + val action: HotkeyAction, + val keys: List, +) + +data class Leaf(val action: HotkeyAction) : KeyComboTrie { + override val label: Text + get() = action.label + + fun execute() { + action.execute() + } +} + +data class Branch( + val nodes: Map +) : KeyComboTrie { + override val label: Text + get() = Text.literal("...") // TODO: better labels +} diff --git a/src/main/kotlin/features/macros/MacroData.kt b/src/main/kotlin/features/macros/MacroData.kt new file mode 100644 index 0000000..91de423 --- /dev/null +++ b/src/main/kotlin/features/macros/MacroData.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.features.macros + +import kotlinx.serialization.Serializable +import moe.nea.firmament.util.data.DataHolder + +@Serializable +data class MacroData( + var comboActions: List = listOf(), + var wheels: List = listOf(), +) { + object DConfig : DataHolder(kotlinx.serialization.serializer(), "macros", ::MacroData) +} diff --git a/src/main/kotlin/features/macros/MacroUI.kt b/src/main/kotlin/features/macros/MacroUI.kt new file mode 100644 index 0000000..8c22c5c --- /dev/null +++ b/src/main/kotlin/features/macros/MacroUI.kt @@ -0,0 +1,285 @@ +package moe.nea.firmament.features.macros + +import io.github.notenoughupdates.moulconfig.gui.CloseEventListener +import io.github.notenoughupdates.moulconfig.observer.ObservableList +import io.github.notenoughupdates.moulconfig.xml.Bind +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.gui.config.AllConfigsGui.toObservableList +import moe.nea.firmament.gui.config.KeyBindingStateManager +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MoulConfigUtils +import moe.nea.firmament.util.ScreenUtil + +class MacroUI { + + + companion object { + @Subscribe + fun onCommands(event: CommandEvent.SubCommand) { + // TODO: add button in config + event.subcommand("macros") { + thenExecute { + ScreenUtil.setScreenLater(MoulConfigUtils.loadScreen("config/macros/index", MacroUI(), null)) + } + } + } + + } + + @field:Bind("combos") + val combos = Combos() + + @field:Bind("wheels") + val wheels = Wheels() + var dontSave = false + + @Bind + fun beforeClose(): CloseEventListener.CloseAction { + if (!dontSave) + save() + return CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE + } + + fun save() { + MacroData.DConfig.data.comboActions = combos.actions.map { it.asSaveable() } + MacroData.DConfig.data.wheels = wheels.wheels.map { it.asSaveable() } + MacroData.DConfig.markDirty() + RadialMacros.setWheels(MacroData.DConfig.data.wheels) + ComboProcessor.setActions(MacroData.DConfig.data.comboActions) + } + + fun discard() { + dontSave = true + MC.screen?.close() + } + + class Command( + @field:Bind("text") + var text: String, + val parent: Wheel, + ) { + @Bind + fun delete() { + parent.editableCommands.removeIf { it === this } + parent.editableCommands.update() + parent.commands.update() + } + + fun asCommandAction() = CommandAction(text) + } + + inner class Wheel( + val parent: Wheels, + var binding: SavedKeyBinding, + commands: List, + ) { + + fun asSaveable(): MacroWheel { + return MacroWheel(binding, commands.map { it.asCommandAction() }) + } + + @Bind("keyCombo") + fun text() = binding.format().string + + @field:Bind("commands") + val commands = commands.mapTo(ObservableList(mutableListOf())) { Command(it.command, this) } + + @field:Bind("editableCommands") + val editableCommands = this.commands.toObservableList() + + @Bind + fun addOption() { + editableCommands.add(Command("", this)) + } + + @Bind + fun back() { + MC.screen?.close() + } + + @Bind + fun edit() { + MC.screen = MoulConfigUtils.loadScreen("config/macros/editor_wheel", this, MC.screen) + } + + @Bind + fun delete() { + parent.wheels.removeIf { it === this } + parent.wheels.update() + } + + val sm = KeyBindingStateManager( + { binding }, + { binding = it }, + ::blur, + ::requestFocus + ) + + @field:Bind + val button = sm.createButton() + + init { + sm.updateLabel() + } + + fun blur() { + button.blur() + } + + + fun requestFocus() { + button.requestFocus() + } + } + + inner class Wheels { + @field:Bind("wheels") + val wheels: ObservableList = MacroData.DConfig.data.wheels.mapTo(ObservableList(mutableListOf())) { + Wheel(this, it.key, it.options.map { CommandAction((it as CommandAction).command) }) + } + + @Bind + fun discard() { + this@MacroUI.discard() + } + + @Bind + fun saveAndClose() { + this@MacroUI.saveAndClose() + } + + @Bind + fun save() { + this@MacroUI.save() + } + + @Bind + fun addWheel() { + wheels.add(Wheel(this, SavedKeyBinding.unbound(), listOf())) + } + } + + fun saveAndClose() { + save() + MC.screen?.close() + } + + inner class Combos { + @field:Bind("actions") + val actions: ObservableList = ObservableList( + MacroData.DConfig.data.comboActions.mapTo(mutableListOf()) { + ActionEditor(it, this) + } + ) + + @Bind + fun addCommand() { + actions.add( + ActionEditor( + ComboKeyAction( + CommandAction("ac Hello from a Firmament Hotkey"), + listOf() + ), + this + ) + ) + } + + @Bind + fun discard() { + this@MacroUI.discard() + } + + @Bind + fun saveAndClose() { + this@MacroUI.saveAndClose() + } + + @Bind + fun save() { + this@MacroUI.save() + } + } + + class KeyBindingEditor(var binding: SavedKeyBinding, val parent: ActionEditor) { + val sm = KeyBindingStateManager( + { binding }, + { binding = it }, + ::blur, + ::requestFocus + ) + + @field:Bind + val button = sm.createButton() + + init { + sm.updateLabel() + } + + fun blur() { + button.blur() + } + + + fun requestFocus() { + button.requestFocus() + } + + @Bind + fun delete() { + parent.combo.removeIf { it === this } + parent.combo.update() + } + } + + class ActionEditor(val action: ComboKeyAction, val parent: Combos) { + fun asSaveable(): ComboKeyAction { + return ComboKeyAction( + CommandAction(command), + combo.map { it.binding } + ) + } + + @field:Bind("command") + var command: String = (action.action as CommandAction).command + + @field:Bind("combo") + val combo = action.keys.map { KeyBindingEditor(it, this) }.toObservableList() + + @Bind + fun formattedCombo() = + combo.joinToString(" > ") { it.binding.toString() } + + @Bind + fun addStep() { + combo.add(KeyBindingEditor(SavedKeyBinding.unbound(), this)) + } + + @Bind + fun back() { + MC.screen?.close() + } + + @Bind + fun delete() { + parent.actions.removeIf { it === this } + parent.actions.update() + } + + @Bind + fun edit() { + MC.screen = MoulConfigUtils.loadScreen("config/macros/editor_combo", this, MC.screen) + } + } +} + +private fun ObservableList.setAll(ts: Collection) { + val observer = this.observer + this.clear() + this.addAll(ts) + this.observer = observer + this.update() +} diff --git a/src/main/kotlin/features/macros/RadialMenu.kt b/src/main/kotlin/features/macros/RadialMenu.kt new file mode 100644 index 0000000..9e5222f --- /dev/null +++ b/src/main/kotlin/features/macros/RadialMenu.kt @@ -0,0 +1,153 @@ +package moe.nea.firmament.features.macros + +import org.joml.Vector2f +import util.render.CustomRenderLayers +import kotlin.math.atan2 +import kotlin.math.cos +import kotlin.math.sin +import kotlin.math.sqrt +import net.minecraft.client.gui.DrawContext +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.events.WorldKeyboardEvent +import moe.nea.firmament.events.WorldMouseMoveEvent +import moe.nea.firmament.features.macros.RadialMenuViewer.RadialMenu +import moe.nea.firmament.features.macros.RadialMenuViewer.RadialMenuOption +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.render.RenderCircleProgress +import moe.nea.firmament.util.render.drawLine +import moe.nea.firmament.util.render.lerpAngle +import moe.nea.firmament.util.render.wrapAngle +import moe.nea.firmament.util.render.Ï„ + +object RadialMenuViewer { + interface RadialMenu { + val key: SavedKeyBinding + val options: List + } + + interface RadialMenuOption { + val isEnabled: Boolean + fun resolve() + fun renderSlice(drawContext: DrawContext) + } + + var activeMenu: RadialMenu? = null + set(value) { + if (value?.options.isNullOrEmpty()) { + field = null + } else { + field = value + } + delta = Vector2f(0F, 0F) + } + var delta = Vector2f(0F, 0F) + val maxSelectionSize = 100F + + @Subscribe + fun onMouseMotion(event: WorldMouseMoveEvent) { + val menu = activeMenu ?: return + event.cancel() + delta.add(event.deltaX.toFloat(), event.deltaY.toFloat()) + val m = delta.lengthSquared() + if (m > maxSelectionSize * maxSelectionSize) { + delta.mul(maxSelectionSize / sqrt(m)) + } + } + + val INNER_CIRCLE_RADIUS = 16 + + @Subscribe + fun onRender(event: HudRenderEvent) { + val menu = activeMenu ?: return + val mat = event.context.matrices + mat.push() + mat.translate( + (MC.window.scaledWidth) / 2F, + (MC.window.scaledHeight) / 2F, + 0F + ) + val sliceWidth = (Ï„ / menu.options.size).toFloat() + var selectedAngle = wrapAngle(atan2(delta.y, delta.x)) + if (delta.lengthSquared() < INNER_CIRCLE_RADIUS * INNER_CIRCLE_RADIUS) + selectedAngle = Float.NaN + for ((idx, option) in menu.options.withIndex()) { + val range = (sliceWidth * idx)..(sliceWidth * (idx + 1)) + mat.push() + mat.scale(64F, 64F, 1F) + val cutout = INNER_CIRCLE_RADIUS / 64F / 2 + RenderCircleProgress.renderCircularSlice( + event.context, + CustomRenderLayers.TRANSLUCENT_CIRCLE_GUI, + 0F, 1F, 0F, 1F, + range, + color = if (selectedAngle in range) 0x70A0A0A0 else 0x70FFFFFF, + innerCutoutRadius = cutout + ) + mat.pop() + mat.push() + val centreAngle = lerpAngle(range.start, range.endInclusive, 0.5F) + val vec = Vector2f(cos(centreAngle), sin(centreAngle)).mul(40F) + mat.translate(vec.x, vec.y, 0F) + option.renderSlice(event.context) + mat.pop() + } + event.context.drawLine(1, 1, delta.x.toInt(), delta.y.toInt(), me.shedaniel.math.Color.ofOpaque(0x00FF00)) + mat.pop() + } + + @Subscribe + fun onTick(event: TickEvent) { + val menu = activeMenu ?: return + if (!menu.key.isPressed(true)) { + val angle = atan2(delta.y, delta.x) + + val choiceIndex = (wrapAngle(angle) * menu.options.size / Ï„).toInt() + val choice = menu.options[choiceIndex] + val selectedAny = delta.lengthSquared() > INNER_CIRCLE_RADIUS * INNER_CIRCLE_RADIUS + activeMenu = null + if (selectedAny) + choice.resolve() + } + } + +} + +object RadialMacros { + var wheels = MacroData.DConfig.data.wheels + private set + + fun setWheels(wheels: List) { + this.wheels = wheels + RadialMenuViewer.activeMenu = null + } + + @Subscribe + fun onOpen(event: WorldKeyboardEvent) { + if (RadialMenuViewer.activeMenu != null) return + wheels.forEach { wheel -> + if (event.matches(wheel.key, atLeast = true)) { + class R(val action: HotkeyAction) : RadialMenuOption { + override val isEnabled: Boolean + get() = true + + override fun resolve() { + action.execute() + } + + override fun renderSlice(drawContext: DrawContext) { + drawContext.drawCenteredTextWithShadow(MC.font, action.label, 0, 0, -1) + } + } + RadialMenuViewer.activeMenu = object : RadialMenu { + override val key: SavedKeyBinding + get() = wheel.key + override val options: List = + wheel.options.map { R(it) } + } + } + } + } +} diff --git a/src/main/kotlin/features/mining/CommissionFeatures.kt b/src/main/kotlin/features/mining/CommissionFeatures.kt new file mode 100644 index 0000000..faba253 --- /dev/null +++ b/src/main/kotlin/features/mining/CommissionFeatures.kt @@ -0,0 +1,26 @@ +package moe.nea.firmament.features.mining + +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.SlotRenderEvents +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.unformattedString + +object CommissionFeatures { + object Config : ManagedConfig("commissions", Category.MINING) { + val highlightCompletedCommissions by toggle("highlight-completed") { true } + } + + + @Subscribe + fun onSlotRender(event: SlotRenderEvents.Before) { + if (!Config.highlightCompletedCommissions) return + if (MC.screenName != "Commissions") return + val stack = event.slot.stack + if (stack.loreAccordingToNbt.any { it.unformattedString == "COMPLETED" }) { + event.highlight(Firmament.identifier("completed_commission_background")) + } + } +} diff --git a/src/main/kotlin/features/mining/Histogram.kt b/src/main/kotlin/features/mining/Histogram.kt new file mode 100644 index 0000000..ed48437 --- /dev/null +++ b/src/main/kotlin/features/mining/Histogram.kt @@ -0,0 +1,81 @@ + +package moe.nea.firmament.features.mining + +import java.util.* +import kotlin.time.Duration +import moe.nea.firmament.util.TimeMark + +class Histogram( + val maxSize: Int, + val maxDuration: Duration, +) { + + data class OrderedTimestamp(val timestamp: TimeMark, val order: Int) : Comparable { + 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 = 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 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/features/mining/HotmPresets.kt b/src/main/kotlin/features/mining/HotmPresets.kt new file mode 100644 index 0000000..2241fee --- /dev/null +++ b/src/main/kotlin/features/mining/HotmPresets.kt @@ -0,0 +1,218 @@ +package moe.nea.firmament.features.mining + +import me.shedaniel.math.Rectangle +import kotlinx.serialization.Serializable +import kotlin.time.Duration.Companion.seconds +import net.minecraft.block.Blocks +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.item.Items +import net.minecraft.screen.GenericContainerScreenHandler +import net.minecraft.screen.slot.Slot +import net.minecraft.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.ChestInventoryUpdateEvent +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.ScreenChangeEvent +import moe.nea.firmament.events.SlotRenderEvents +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.TemplateUtil +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.customgui.CustomGui +import moe.nea.firmament.util.customgui.customGui +import moe.nea.firmament.util.mc.CommonTextures +import moe.nea.firmament.util.mc.SlotUtils.clickRightMouseButton +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.render.drawGuiTexture +import moe.nea.firmament.util.unformattedString +import moe.nea.firmament.util.useMatch + +object HotmPresets { + val SHARE_PREFIX = "FIRMHOTM/" + + @Serializable + data class HotmPreset( + val perks: List, + ) + + @Serializable + data class PerkPreset(val perkName: String) + + var hotmCommandSent = TimeMark.farPast() + val hotmInventoryName = "Heart of the Mountain" + + @Subscribe + fun onScreenOpen(event: ScreenChangeEvent) { + val title = event.new?.title?.unformattedString + if (title != hotmInventoryName) return + val screen = event.new as? HandledScreen<*> ?: return + val oldHandler = (event.old as? HandledScreen<*>)?.customGui + if (oldHandler is HotmScrollPrompt) { + event.new.customGui = oldHandler + oldHandler.setNewScreen(screen) + return + } + if (hotmCommandSent.passedTime() > 5.seconds) return + hotmCommandSent = TimeMark.farPast() + screen.customGui = HotmScrollPrompt(screen) + } + + class HotmScrollPrompt(var screen: HandledScreen<*>) : CustomGui() { + var bounds = Rectangle( + 0, 0, 0, 0 + ) + + fun setNewScreen(screen: HandledScreen<*>) { + this.screen = screen + onInit() + hasScrolled = false + } + + override fun render(drawContext: DrawContext, delta: Float, mouseX: Int, mouseY: Int) { + drawContext.drawGuiTexture( + CommonTextures.genericWidget(), + bounds.x, bounds.y, + bounds.width, + bounds.height, + ) + drawContext.drawCenteredTextWithShadow( + MC.font, + if (hasAll) { + Text.translatable("firmament.hotmpreset.copied") + } else if (!hasScrolled) { + Text.translatable("firmament.hotmpreset.scrollprompt") + } else { + Text.translatable("firmament.hotmpreset.scrolled") + }, + bounds.centerX, + bounds.centerY - 5, + -1 + ) + } + + + var hasScrolled = false + var hasAll = false + + override fun mouseClick(mouseX: Double, mouseY: Double, button: Int): Boolean { + if (!hasScrolled) { + val slot = screen.screenHandler.getSlot(8) + println("Clicking ${slot.stack}") + slot.clickRightMouseButton(screen.screenHandler) + } + hasScrolled = true + return super.mouseClick(mouseX, mouseY, button) + } + + override fun shouldDrawForeground(): Boolean { + return false + } + + override fun getBounds(): List { + return listOf(bounds) + } + + override fun onInit() { + bounds = Rectangle( + screen.width / 2 - 150, + screen.height / 2 - 100, + 300, 200 + ) + val screen = screen as AccessorHandledScreen + screen.x_Firmament = bounds.x + screen.y_Firmament = bounds.y + screen.backgroundWidth_Firmament = bounds.width + screen.backgroundHeight_Firmament = bounds.height + } + + override fun moveSlot(slot: Slot) { + slot.x = -10000 + } + + val coveredRows = mutableSetOf() + val unlockedPerks = mutableSetOf() + val allRows = (1..10).toSet() + + fun onNewItems(event: ChestInventoryUpdateEvent) { + val handler = screen.screenHandler as? GenericContainerScreenHandler ?: return + for (it in handler.slots) { + if (it.inventory is PlayerInventory) continue + val stack = it.stack + val name = stack.displayNameAccordingToNbt.unformattedString + tierRegex.useMatch(name) { + coveredRows.add(group("tier").toInt()) + } + if (stack.item == Items.DIAMOND + || stack.item == Items.EMERALD + || stack.item == Blocks.EMERALD_BLOCK.asItem() + ) { + unlockedPerks.add(name) + } + } + if (allRows == coveredRows) { + ClipboardUtils.setTextContent(TemplateUtil.encodeTemplate(SHARE_PREFIX, HotmPreset( + unlockedPerks.map { PerkPreset(it) } + ))) + hasAll = true + } + } + } + + val tierRegex = "Tier (?[0-9]+)".toPattern() + var highlightedPerks: Set = emptySet() + + @Subscribe + fun onSlotUpdates(event: ChestInventoryUpdateEvent) { + val customGui = (event.inventory as? HandledScreen<*>)?.customGui + if (customGui is HotmScrollPrompt) { + customGui.onNewItems(event) + } + } + + @Subscribe + fun resetOnScreen(event: ScreenChangeEvent) { + if (event.new != null && event.new.title.unformattedString != hotmInventoryName) { + highlightedPerks = emptySet() + } + } + + @Subscribe + fun onSlotRender(event: SlotRenderEvents.Before) { + if (hotmInventoryName == MC.screenName + && event.slot.stack.displayNameAccordingToNbt.unformattedString in highlightedPerks + ) { + event.highlight((Firmament.identifier("hotm_perk_preset"))) + } + } + + @Subscribe + fun onCommand(event: CommandEvent.SubCommand) { + event.subcommand("exporthotm") { + thenExecute { + hotmCommandSent = TimeMark.now() + MC.sendCommand("hotm") + source.sendFeedback(Text.translatable("firmament.hotmpreset.openinghotm")) + } + } + event.subcommand("importhotm") { + thenExecute { + val template = + TemplateUtil.maybeDecodeTemplate(SHARE_PREFIX, ClipboardUtils.getTextContents()) + if (template == null) { + source.sendFeedback(Text.translatable("firmament.hotmpreset.failedimport")) + } else { + highlightedPerks = template.perks.mapTo(mutableSetOf()) { it.perkName } + source.sendFeedback(Text.translatable("firmament.hotmpreset.okayimport")) + MC.sendCommand("hotm") + } + } + } + } + +} diff --git a/src/main/kotlin/features/mining/MiningBlockInfoUi.kt b/src/main/kotlin/features/mining/MiningBlockInfoUi.kt new file mode 100644 index 0000000..e8ea4f4 --- /dev/null +++ b/src/main/kotlin/features/mining/MiningBlockInfoUi.kt @@ -0,0 +1,54 @@ +package moe.nea.firmament.features.mining + +import io.github.notenoughupdates.moulconfig.observer.ObservableList +import io.github.notenoughupdates.moulconfig.observer.Property +import io.github.notenoughupdates.moulconfig.platform.ModernItemStack +import io.github.notenoughupdates.moulconfig.xml.Bind +import net.minecraft.client.gui.screen.Screen +import net.minecraft.item.ItemStack +import moe.nea.firmament.repo.MiningRepoData +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.MoulConfigUtils +import moe.nea.firmament.util.SkyBlockIsland + +object MiningBlockInfoUi { + class MiningInfo(miningData: MiningRepoData) { + @field:Bind("search") + @JvmField + var search = "" + + @get:Bind("ores") + val blocks = miningData.customMiningBlocks.mapTo(ObservableList(mutableListOf())) { OreInfo(it, this) } + } + + class OreInfo(block: MiningRepoData.CustomMiningBlock, info: MiningInfo) { + @get:Bind("oreName") + val oreName = block.name ?: "No Name" + + @get:Bind("blocks") + val res = ObservableList(block.blocks189.map { BlockInfo(it, info) }) + } + + class BlockInfo(val block: MiningRepoData.Block189, val info: MiningInfo) { + @get:Bind("item") + val item = ModernItemStack.of(block.block?.let { ItemStack(it) } ?: ItemStack.EMPTY) + + @get:Bind("isSelected") + val isSelected get() = info.search.let { block.isActiveIn(SkyBlockIsland.forMode(it)) } + + @get:Bind("itemName") + val itemName get() = item.getDisplayName() + + @get:Bind("restrictions") + val res = ObservableList( + if (block.onlyIn != null) + block.onlyIn.map { " §r- §a${it.userFriendlyName}" } + else + listOf("Everywhere") + ) + } + + fun makeScreen(): Screen { + return MoulConfigUtils.loadScreen("mining_block_info/index", MiningInfo(RepoManager.miningData), null) + } +} diff --git a/src/main/kotlin/features/mining/PickaxeAbility.kt b/src/main/kotlin/features/mining/PickaxeAbility.kt new file mode 100644 index 0000000..a049001 --- /dev/null +++ b/src/main/kotlin/features/mining/PickaxeAbility.kt @@ -0,0 +1,244 @@ +package moe.nea.firmament.features.mining + +import java.util.regex.Pattern +import kotlin.jvm.optionals.getOrNull +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import net.minecraft.client.MinecraftClient +import net.minecraft.client.toast.SystemToast +import net.minecraft.item.ItemStack +import net.minecraft.util.DyeColor +import net.minecraft.util.Hand +import net.minecraft.util.Identifier +import net.minecraft.util.StringIdentifiable +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.events.ProfileSwitchEvent +import moe.nea.firmament.events.SlotClickEvent +import moe.nea.firmament.events.UseItemEvent +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.SBData +import moe.nea.firmament.util.SHORT_NUMBER_FORMAT +import moe.nea.firmament.util.SkyBlockIsland +import moe.nea.firmament.util.TIME_PATTERN +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.extraAttributes +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.parseShortNumber +import moe.nea.firmament.util.parseTimePattern +import moe.nea.firmament.util.red +import moe.nea.firmament.util.render.RenderCircleProgress +import moe.nea.firmament.util.render.lerp +import moe.nea.firmament.util.skyblock.AbilityUtils +import moe.nea.firmament.util.skyblock.DungeonUtil +import moe.nea.firmament.util.skyblock.ItemType +import moe.nea.firmament.util.toShedaniel +import moe.nea.firmament.util.tr +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, Category.MINING) { + val cooldownEnabled by toggle("ability-cooldown") { false } + val disableInDungeons by toggle("disable-in-dungeons") { true } + val cooldownScale by integer("ability-scale", 16, 64) { 16 } + val cooldownReadyToast by toggle("ability-cooldown-toast") { false } + val drillFuelBar by toggle("fuel-bar") { true } + val blockOnPrivateIsland by choice( + "block-on-dynamic", + ) { + BlockPickaxeAbility.ONLY_DESTRUCTIVE + } + } + + enum class BlockPickaxeAbility : StringIdentifiable { + NEVER, + ALWAYS, + ONLY_DESTRUCTIVE; + + override fun asString(): String { + return name + } + } + + var lobbyJoinTime = TimeMark.farPast() + var lastUsage = mutableMapOf() + var abilityOverride: String? = null + var defaultAbilityDurations = mutableMapOf( + "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 + ) + val destructiveAbilities = setOf("Pickobulus") + val pickaxeTypes = setOf(ItemType.PICKAXE, ItemType.DRILL, ItemType.GAUNTLET) + + override val config: ManagedConfig + get() = TConfig + + fun getCooldownPercentage(name: String, cooldown: Duration): Double { + val sinceLastUsage = lastUsage[name]?.passedTime() ?: Duration.INFINITE + val sinceLobbyJoin = lobbyJoinTime.passedTime() + if (SBData.skyblockLocation == SkyBlockIsland.MINESHAFT) { + if (sinceLobbyJoin < sinceLastUsage) { + return 1.0 + } + } + if (sinceLastUsage < cooldown) + return sinceLastUsage / cooldown + return 1.0 + } + + @Subscribe + fun onPickaxeRightClick(event: UseItemEvent) { + if (TConfig.blockOnPrivateIsland == BlockPickaxeAbility.NEVER) return + if (SBData.skyblockLocation != SkyBlockIsland.PRIVATE_ISLAND && SBData.skyblockLocation != SkyBlockIsland.GARDEN) return + val itemType = ItemType.fromItemStack(event.item) + if (itemType !in pickaxeTypes) return + val ability = AbilityUtils.getAbilities(event.item) + val shouldBlock = when (TConfig.blockOnPrivateIsland) { + BlockPickaxeAbility.NEVER -> false + BlockPickaxeAbility.ALWAYS -> ability.any() + BlockPickaxeAbility.ONLY_DESTRUCTIVE -> ability.any { it.name in destructiveAbilities } + } + if (shouldBlock) { + MC.sendChat(tr("firmament.pickaxe.blocked", + "Firmament blocked a pickaxe ability from being used on a private island.") + .red() // TODO: .clickCommand("firm confignavigate ${TConfig.identifier} block-on-dynamic") + ) + event.cancel() + } + } + + @Subscribe + fun onSlotClick(it: SlotClickEvent) { + if (MC.screen?.title?.unformattedString == "Heart of the Mountain") { + val name = it.stack.displayNameAccordingToNbt.unformattedString + 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 + val fuel = extra.getInt("drill_fuel").getOrNull() ?: return + var percentage = fuel / maxFuel.toFloat() + if (percentage > 1f) percentage = 1f + 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() + abilityOverride = group("name") + } + abilitySwitchPattern.useMatch(it.unformattedString) { + abilityOverride = group("ability") + } + pickaxeAbilityCooldownPattern.useMatch(it.unformattedString) { + val ability = abilityOverride ?: return@useMatch + val remainingCooldown = parseTimePattern(group("remainingCooldown")) + val length = defaultAbilityDurations[ability] ?: return@useMatch + lastUsage[ability] = TimeMark.ago(length - remainingCooldown) + } + nowAvailable.useMatch(it.unformattedString) { + val ability = group("name") + lastUsage[ability] = TimeMark.farPast() + if (!TConfig.cooldownReadyToast) return + val mc: MinecraftClient = MinecraftClient.getInstance() + mc.toastManager.add( + SystemToast.create(mc, SystemToast.Type.NARRATOR_TOGGLE, tr("firmament.pickaxe.ability-ready","Pickaxe Cooldown"), tr("firmament.pickaxe.ability-ready.desc", "Pickaxe ability is ready!")) + ) + } + } + + @Subscribe + fun onWorldReady(event: WorldReadyEvent) { + lobbyJoinTime = TimeMark.now() + abilityOverride = null + } + + @Subscribe + fun onProfileSwitch(event: ProfileSwitchEvent) { + lastUsage.entries.removeIf { + it.value < lobbyJoinTime + } + } + + val abilityUsePattern = Pattern.compile("You used your (?.*) Pickaxe Ability!") + val fuelPattern = Pattern.compile("Fuel: .*/(?$SHORT_NUMBER_FORMAT)") + val pickaxeAbilityCooldownPattern = + Pattern.compile("Your pickaxe ability is on cooldown for (?$TIME_PATTERN)\\.") + val nowAvailable = Pattern.compile("(?[a-zA-Z0-9 ]+) is now available!") + + 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") }) + return null + val ability = AbilityUtils.getAbilities(itemStack).firstOrNull() ?: return null + return PickaxeAbilityData(ability.name, ability.cooldown ?: return null) + } + + val cooldownPattern = Pattern.compile("Cooldown: (?$TIME_PATTERN)") + val abilitySwitchPattern = + Pattern.compile("You selected (?.*) as your Pickaxe Ability\\. This ability will apply to all of your pickaxes!") + + @Subscribe + fun renderHud(event: HudRenderEvent) { + if (!TConfig.cooldownEnabled) return + if (TConfig.disableInDungeons && DungeonUtil.isInDungeonIsland) return + if (!event.isRenderingCursor) 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/features/mining/PristineProfitTracker.kt b/src/main/kotlin/features/mining/PristineProfitTracker.kt new file mode 100644 index 0000000..377a470 --- /dev/null +++ b/src/main/kotlin/features/mining/PristineProfitTracker.kt @@ -0,0 +1,148 @@ +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.StringUtil.parseIntWithComma +import moe.nea.firmament.util.data.ProfileSpecificDataHolder +import moe.nea.firmament.util.formattedString +import moe.nea.firmament.util.useMatch + +object PristineProfitTracker : FirmamentFeature { + override val identifier: String + get() = "pristine-profit" + + enum class GemstoneKind( + val label: String, + ) { + SAPPHIRE("Sapphire"), + RUBY("Ruby"), + AMETHYST("Amethyst"), + AMBER("Amber"), + TOPAZ("Topaz"), + JADE("Jade"), + JASPER("Jasper"), + OPAL("Opal"), + PERIDOT("Peridot"), + ONXY("Onyx"), + AQUAMARINE("Aquamarine"), + CITRINE("Citrine"), + ; + + val flawedId: SkyblockId = SkyblockId("FLAWED_${name}_GEM") + val fineId: SkyblockId = SkyblockId("FINE_${name}_GEM") + } + + @Serializable + data class Data( + var maxMoneyPerSecond: Double = 1.0, + var maxCollectionPerSecond: Double = 1.0, + ) + + object DConfig : ProfileSpecificDataHolder(serializer(), identifier, ::Data) + + override val config: ManagedConfig? + get() = TConfig + + object TConfig : ManagedConfig(identifier, Category.MINING) { + val timeout by duration("timeout", 0.seconds, 120.seconds) { 30.seconds } + val gui by position("position", 100, 30) { Point(0.05, 0.2) } + val useFineGemstones by toggle("fine-gemstones") { false } + } + + val sellingStrategy = BazaarPriceStrategy.SELL_ORDER + + val pristineRegex = + "PRISTINE! You found . Flawed (?${ + GemstoneKind.entries.joinToString("|") { it.label } + }) Gemstone x(?[0-9,]+)!".toPattern() + + val collectionHistogram = Histogram(10000, 180.seconds) + + /** + * Separate histogram for money, since money changes based on gemstone, therefore we cannot calculate money from collection. + */ + val moneyHistogram = Histogram(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 + val FLAWED_PER_FINE = 80 + val ROUGHS_PER_FINE = ROUGHS_PER_FLAWED * FLAWED_PER_FINE + + 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 = + if (TConfig.useFineGemstones) sellingStrategy.getSellPrice(gemstoneKind.fineId) * flawedCount / FLAWED_PER_FINE + else 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/features/misc/CustomCapes.kt b/src/main/kotlin/features/misc/CustomCapes.kt new file mode 100644 index 0000000..dc5187a --- /dev/null +++ b/src/main/kotlin/features/misc/CustomCapes.kt @@ -0,0 +1,192 @@ +package moe.nea.firmament.features.misc + +import com.mojang.blaze3d.systems.RenderSystem +import java.util.OptionalDouble +import java.util.OptionalInt +import util.render.CustomRenderPipelines +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import net.minecraft.client.network.AbstractClientPlayerEntity +import net.minecraft.client.render.BufferBuilder +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.VertexConsumer +import net.minecraft.client.render.VertexConsumerProvider +import net.minecraft.client.render.entity.state.PlayerEntityRenderState +import net.minecraft.client.util.BufferAllocator +import net.minecraft.client.util.SkinTextures +import net.minecraft.util.Identifier +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 + +object CustomCapes : FirmamentFeature { + override val identifier: String + get() = "developer-capes" + + object TConfig : ManagedConfig(identifier, Category.DEV) { + val showCapes by toggle("show-cape") { true } + } + + override val config: ManagedConfig + get() = TConfig + + interface CustomCapeRenderer { + fun replaceRender( + renderLayer: RenderLayer, + vertexConsumerProvider: VertexConsumerProvider, + model: (VertexConsumer) -> Unit + ) + } + + data class TexturedCapeRenderer( + val location: Identifier + ) : CustomCapeRenderer { + override fun replaceRender( + renderLayer: RenderLayer, + vertexConsumerProvider: VertexConsumerProvider, + model: (VertexConsumer) -> Unit + ) { + model(vertexConsumerProvider.getBuffer(RenderLayer.getEntitySolid(location))) + } + } + + data class ParallaxedHighlightCapeRenderer( + val template: Identifier, + val background: Identifier, + val overlay: Identifier, + val animationSpeed: Duration, + ) : CustomCapeRenderer { + override fun replaceRender( + renderLayer: RenderLayer, + vertexConsumerProvider: VertexConsumerProvider, + model: (VertexConsumer) -> Unit + ) { + BufferAllocator(2048).use { allocator -> + val bufferBuilder = BufferBuilder(allocator, renderLayer.drawMode, renderLayer.vertexFormat) + model(bufferBuilder) + bufferBuilder.end().use { buffer -> + val commandEncoder = RenderSystem.getDevice().createCommandEncoder() + val vertexBuffer = renderLayer.vertexFormat.uploadImmediateVertexBuffer(buffer.buffer) + val indexBufferConstructor = RenderSystem.getSequentialBuffer(renderLayer.drawMode) + val indexBuffer = indexBufferConstructor.getIndexBuffer(buffer.drawParameters.indexCount) + val templateTexture = MC.textureManager.getTexture(template) + val backgroundTexture = MC.textureManager.getTexture(background) + val foregroundTexture = MC.textureManager.getTexture(overlay) + commandEncoder.createRenderPass( + MC.instance.framebuffer.colorAttachment, + OptionalInt.empty(), + MC.instance.framebuffer.depthAttachment, + OptionalDouble.empty(), + ).use { renderPass -> + // TODO: account for lighting + renderPass.setPipeline(CustomRenderPipelines.PARALLAX_CAPE_SHADER) + renderPass.bindSampler("Sampler0", templateTexture.glTexture) + renderPass.bindSampler("Sampler1", backgroundTexture.glTexture) + renderPass.bindSampler("Sampler3", foregroundTexture.glTexture) + val animationValue = (startTime.passedTime() / animationSpeed).mod(1F) + renderPass.setUniform("Animation", animationValue.toFloat()) + renderPass.setIndexBuffer(indexBuffer, indexBufferConstructor.indexType) + renderPass.setVertexBuffer(0, vertexBuffer) + renderPass.drawIndexed(0, buffer.drawParameters.indexCount) + } + } + } + } + } + + interface CapeStorage { + companion object { + @JvmStatic + fun cast(playerEntityRenderState: PlayerEntityRenderState) = + playerEntityRenderState as CapeStorage + + } + + var cape_firmament: CustomCape? + } + + data class CustomCape( + val id: String, + val label: String, + val render: CustomCapeRenderer, + ) + + enum class AllCapes(val label: String, val render: CustomCapeRenderer) { + FIRMAMENT_ANIMATED( + "Animated Firmament", ParallaxedHighlightCapeRenderer( + Firmament.identifier("textures/cape/parallax_template.png"), + Firmament.identifier("textures/cape/parallax_background.png"), + Firmament.identifier("textures/cape/firmament_star.png"), + 110.seconds + ) + ), + + FURFSKY_STATIC( + "FurfSky", + TexturedCapeRenderer(Firmament.identifier("textures/cape/fsr_static.png")) + ), + + FIRMAMENT_STATIC( + "Firmament", + TexturedCapeRenderer(Firmament.identifier("textures/cape/firm_static.png")) + ) + ; + + val cape = CustomCape(name, label, render) + } + + val byId = AllCapes.entries.associateBy { it.cape.id } + val byUuid = + listOf( + listOf( + Devs.nea to AllCapes.FIRMAMENT_ANIMATED, + Devs.kath to AllCapes.FIRMAMENT_STATIC, + Devs.jani to AllCapes.FIRMAMENT_ANIMATED, + ), + Devs.FurfSky.all.map { it to AllCapes.FURFSKY_STATIC }, + ).flatten().flatMap { (dev, cape) -> dev.uuids.map { it to cape.cape } }.toMap() + + @JvmStatic + fun render( + playerEntityRenderState: PlayerEntityRenderState, + vertexConsumer: VertexConsumer, + renderLayer: RenderLayer, + vertexConsumerProvider: VertexConsumerProvider, + model: (VertexConsumer) -> Unit + ) { + val capeStorage = CapeStorage.cast(playerEntityRenderState) + val firmCape = capeStorage.cape_firmament + if (firmCape != null) { + firmCape.render.replaceRender(renderLayer, vertexConsumerProvider, model) + } else { + model(vertexConsumer) + } + } + + @JvmStatic + fun addCapeData( + player: AbstractClientPlayerEntity, + playerEntityRenderState: PlayerEntityRenderState + ) { + val cape = if (TConfig.showCapes) byUuid[player.uuid] else null + val capeStorage = CapeStorage.cast(playerEntityRenderState) + if (cape == null) { + capeStorage.cape_firmament = null + } else { + capeStorage.cape_firmament = cape + playerEntityRenderState.skinTextures = SkinTextures( + playerEntityRenderState.skinTextures.texture, + playerEntityRenderState.skinTextures.textureUrl, + Firmament.identifier("placeholder/fake_cape"), + playerEntityRenderState.skinTextures.elytraTexture, + playerEntityRenderState.skinTextures.model, + playerEntityRenderState.skinTextures.secure, + ) + playerEntityRenderState.capeVisible = true + } + } + + val startTime = TimeMark.now() +} diff --git a/src/main/kotlin/features/misc/Devs.kt b/src/main/kotlin/features/misc/Devs.kt new file mode 100644 index 0000000..1f16400 --- /dev/null +++ b/src/main/kotlin/features/misc/Devs.kt @@ -0,0 +1,38 @@ +package moe.nea.firmament.features.misc + +import java.util.UUID + +object Devs { + data class Dev( + val uuids: List, + ) { + constructor(vararg uuid: UUID) : this(uuid.toList()) + constructor(vararg uuid: String) : this(uuid.map { UUID.fromString(it) }) + } + + val nea = Dev("d3cb85e2-3075-48a1-b213-a9bfb62360c1", "842204e6-6880-487b-ae5a-0595394f9948") + val kath = Dev("add71246-c46e-455c-8345-c129ea6f146c", "b491990d-53fd-4c5f-a61e-19d58cc7eddf") + val jani = Dev("8a9f1841-48e9-48ed-b14f-76a124e6c9df") + + object FurfSky { + val smolegit = Dev("02b38b96-eb19-405a-b319-d6bc00b26ab3") + val itsCen = Dev("ada70b5a-ac37-49d2-b18c-1351672f8051") + val webster = Dev("02166f1b-9e8d-4e48-9e18-ea7a4499492d") + val vrachel = Dev("22e98637-ba97-4b6b-a84f-fb57a461ce43") + val cunuduh = Dev("2a15e3b3-c46e-4718-b907-166e1ab2efdc") + val eiiies = Dev("2ae162f2-81a7-4f91-a4b2-104e78a0a7e1") + val june = Dev("2584a4e3-f917-4493-8ced-618391f3b44f") + val denasu = Dev("313cbd25-8ade-4e41-845c-5cab555a30c9") + val libyKiwii = Dev("4265c52e-bd6f-4d3c-9cf6-bdfc8fb58023") + val madeleaan = Dev("bcb119a3-6000-4324-bda1-744f00c44b31") + val turtleSP = Dev("f1ca1934-a582-4723-8283-89921d008657") + val papayamm = Dev("ae0eea30-f6a2-40fe-ac17-9c80b3423409") + val persuasiveViksy = Dev("ba7ac144-28e0-4f55-a108-1a72fe744c9e") + val all = listOf( + smolegit, itsCen, webster, vrachel, cunuduh, eiiies, + june, denasu, libyKiwii, madeleaan, turtleSP, papayamm, + persuasiveViksy + ) + } + +} diff --git a/src/main/kotlin/features/misc/Hud.kt b/src/main/kotlin/features/misc/Hud.kt new file mode 100644 index 0000000..9661fc5 --- /dev/null +++ b/src/main/kotlin/features/misc/Hud.kt @@ -0,0 +1,77 @@ +package moe.nea.firmament.features.misc + +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.HudRenderEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.tr +import moe.nea.jarvis.api.Point +import net.minecraft.client.network.PlayerListEntry +import net.minecraft.text.Text + +object Hud : FirmamentFeature { + override val identifier: String + get() = "hud" + + object TConfig : ManagedConfig(identifier, Category.MISC) { + var dayCount by toggle("day-count") { false } + val dayCountHud by position("day-count-hud", 80, 10) { Point(0.5, 0.8) } + var fpsCount by toggle("fps-count") { false } + val fpsCountHud by position("fps-count-hud", 80, 10) { Point(0.5, 0.9) } + var pingCount by toggle("ping-count") { false } + val pingCountHud by position("ping-count-hud", 80, 10) { Point(0.5, 1.0) } + } + + override val config: ManagedConfig + get() = TConfig + + @Subscribe + fun onRenderHud(it: HudRenderEvent) { + if (TConfig.dayCount) { + it.context.matrices.push() + TConfig.dayCountHud.applyTransformations(it.context.matrices) + val day = (MC.world?.timeOfDay ?: 0L) / 24000 + it.context.drawText( + MC.font, + Text.literal(String.format(tr("firmament.config.hud.day-count-hud.display", "Day: %s").string, day)), + 36, + MC.font.fontHeight, + -1, + true + ) + it.context.matrices.pop() + } + + if (TConfig.fpsCount) { + it.context.matrices.push() + TConfig.fpsCountHud.applyTransformations(it.context.matrices) + it.context.drawText( + MC.font, Text.literal( + String.format( + tr("firmament.config.hud.fps-count-hud.display", "FPS: %s").string, MC.instance.currentFps + ) + ), 36, MC.font.fontHeight, -1, true + ) + it.context.matrices.pop() + } + + if (TConfig.pingCount) { + it.context.matrices.push() + TConfig.pingCountHud.applyTransformations(it.context.matrices) + val ping = MC.player?.let { + val entry: PlayerListEntry? = MC.networkHandler?.getPlayerListEntry(it.uuid) + entry?.latency ?: -1 + } ?: -1 + it.context.drawText( + MC.font, Text.literal( + String.format( + tr("firmament.config.hud.ping-count-hud.display", "Ping: %s ms").string, ping + ) + ), 36, MC.font.fontHeight, -1, true + ) + + it.context.matrices.pop() + } + } +} diff --git a/src/main/kotlin/features/misc/LicenseViewer.kt b/src/main/kotlin/features/misc/LicenseViewer.kt new file mode 100644 index 0000000..4219177 --- /dev/null +++ b/src/main/kotlin/features/misc/LicenseViewer.kt @@ -0,0 +1,128 @@ +package moe.nea.firmament.features.misc + +import io.github.notenoughupdates.moulconfig.observer.ObservableList +import io.github.notenoughupdates.moulconfig.xml.Bind +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlinx.serialization.json.decodeFromStream +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MoulConfigUtils +import moe.nea.firmament.util.ScreenUtil +import moe.nea.firmament.util.tr + +object LicenseViewer { + @Serializable + data class Software( + val licenses: List = listOf(), + val webPresence: String? = null, + val projectName: String, + val projectDescription: String? = null, + val developers: List = listOf(), + ) { + + @Bind + fun hasWebPresence() = webPresence != null + + @Bind + fun webPresence() = webPresence ?: "" + @Bind + fun open() { + MC.openUrl(webPresence ?: return) + } + + @Bind + fun projectName() = projectName + + @Bind + fun projectDescription() = projectDescription ?: "" + + @get:Bind("developers") + @Transient + val developersO = ObservableList(developers) + + @get:Bind("licenses") + @Transient + val licenses0 = ObservableList(licenses) + } + + @Serializable + data class Developer( + @get:Bind("name") val name: String, + val webPresence: String? = null + ) { + + @Bind + fun open() { + MC.openUrl(webPresence ?: return) + } + + @Bind + fun hasWebPresence() = webPresence != null + + @Bind + fun webPresence() = webPresence ?: "" + } + + @Serializable + data class License( + @get:Bind("name") val licenseName: String, + val licenseUrl: String? = null + ) { + @Bind + fun open() { + MC.openUrl(licenseUrl ?: return) + } + + @Bind + fun hasUrl() = licenseUrl != null + + @Bind + fun url() = licenseUrl ?: "" + } + + data class LicenseList( + val softwares: List + ) { + @get:Bind("softwares") + val obs = ObservableList(softwares) + } + + @OptIn(ExperimentalSerializationApi::class) + val licenses: LicenseList? = ErrorUtil.catch("Could not load licenses") { + Firmament.json.decodeFromStream?>( + javaClass.getResourceAsStream("/LICENSES-FIRMAMENT.json") ?: error("Could not find LICENSES-FIRMAMENT.json") + )?.let { LicenseList(it) } + }.orNull() + + fun showLicenses() { + ErrorUtil.catch("Could not display licenses") { + ScreenUtil.setScreenLater( + MoulConfigUtils.loadScreen( + "license_viewer/index", licenses!!, null + ) + ) + }.or { + MC.sendChat( + tr( + "firmament.licenses.notfound", + "Could not load licenses. Please check the Firmament source code for information directly." + ) + ) + } + } + + @Subscribe + fun onSubcommand(event: CommandEvent.SubCommand) { + event.subcommand("licenses") { + thenExecute { + showLicenses() + } + } + } +} diff --git a/src/main/kotlin/features/misc/TimerFeature.kt b/src/main/kotlin/features/misc/TimerFeature.kt new file mode 100644 index 0000000..7c4833d --- /dev/null +++ b/src/main/kotlin/features/misc/TimerFeature.kt @@ -0,0 +1,124 @@ +package moe.nea.firmament.features.misc + +import com.mojang.brigadier.arguments.IntegerArgumentType +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.DurationArgumentType +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.events.TickEvent +import moe.nea.firmament.util.CommonSoundEffects +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MinecraftDispatcher +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.clickCommand +import moe.nea.firmament.util.lime +import moe.nea.firmament.util.red +import moe.nea.firmament.util.tr +import moe.nea.firmament.util.yellow + +object TimerFeature { + data class Timer( + val start: TimeMark, + val duration: Duration, + val message: String, + val timerId: Int, + ) { + fun timeLeft() = (duration - start.passedTime()).coerceAtLeast(0.seconds) + fun isDone() = start.passedTime() >= duration + } + + // Theoretically for optimal performance this could be a treeset keyed to the end time + val timers = mutableListOf() + + @Subscribe + fun tick(event: TickEvent) { + timers.removeAll { + if (it.isDone()) { + MC.sendChat(tr("firmament.timer.finished", + "The timer you set ${FirmFormatters.formatTimespan(it.duration)} ago just went off: ${it.message}") + .yellow()) + Firmament.coroutineScope.launch { + withContext(MinecraftDispatcher) { + repeat(5) { + CommonSoundEffects.playSuccess() + delay(0.2.seconds) + } + } + } + true + } else { + false + } + } + } + + fun startTimer(duration: Duration, message: String) { + val timerId = createTimerId++ + timers.add(Timer(TimeMark.now(), duration, message, timerId)) + MC.sendChat( + tr("firmament.timer.start", + "Timer started for $message in ${FirmFormatters.formatTimespan(duration)}.").lime() + .append(" ") + .append( + tr("firmament.timer.cancelbutton", + "Click here to cancel the timer." + ).clickCommand("/firm timer clear $timerId").red() + ) + ) + } + + fun clearTimer(timerId: Int) { + val timer = timers.indexOfFirst { it.timerId == timerId } + if (timer < 0) { + MC.sendChat(tr("firmament.timer.cancel.fail", + "Could not cancel that timer. Maybe it was already cancelled?").red()) + } else { + val timerData = timers[timer] + timers.removeAt(timer) + MC.sendChat(tr("firmament.timer.cancel.done", + "Cancelled timer ${timerData.message}. It would have been done in ${ + FirmFormatters.formatTimespan(timerData.timeLeft()) + }.").lime()) + } + } + + var createTimerId = 0 + + @Subscribe + fun onCommands(event: CommandEvent.SubCommand) { + event.subcommand("cleartimer") { + thenArgument("timerId", IntegerArgumentType.integer(0)) { timerId -> + thenExecute { + clearTimer(this[timerId]) + } + } + thenExecute { + timers.map { it.timerId }.forEach { + clearTimer(it) + } + } + } + event.subcommand("timer") { + thenArgument("time", DurationArgumentType) { duration -> + thenExecute { + startTimer(this[duration], "no message") + } + thenArgument("message", RestArgumentType) { message -> + thenExecute { + startTimer(this[duration], this[message]) + } + } + } + } + } +} diff --git a/src/main/kotlin/features/notifications/Notifications.kt b/src/main/kotlin/features/notifications/Notifications.kt new file mode 100644 index 0000000..8d912d1 --- /dev/null +++ b/src/main/kotlin/features/notifications/Notifications.kt @@ -0,0 +1,7 @@ + +package moe.nea.firmament.features.notifications + +import moe.nea.firmament.features.FirmamentFeature + +object Notifications { +} diff --git a/src/main/kotlin/features/world/ColeWeightCompat.kt b/src/main/kotlin/features/world/ColeWeightCompat.kt new file mode 100644 index 0000000..f7f1317 --- /dev/null +++ b/src/main/kotlin/features/world/ColeWeightCompat.kt @@ -0,0 +1,125 @@ +package moe.nea.firmament.features.world + +import kotlinx.serialization.Serializable +import net.minecraft.text.Text +import net.minecraft.util.math.BlockPos +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.DefaultSource +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.commands.thenLiteral +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.util.ClipboardUtils +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.tr + +object ColeWeightCompat { + @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, + ) + + fun fromFirm(waypoints: FirmWaypoints, relativeTo: BlockPos): List { + return waypoints.waypoints.map { + ColeWeightWaypoint(it.x - relativeTo.x, it.y - relativeTo.y, it.z - relativeTo.z) + } + } + + fun intoFirm(waypoints: List, relativeTo: BlockPos): FirmWaypoints { + val w = waypoints + .filter { it.x != null && it.y != null && it.z != null } + .map { FirmWaypoints.Waypoint(it.x!! + relativeTo.x, it.y!! + relativeTo.y, it.z!! + relativeTo.z) } + return FirmWaypoints( + "Imported Waypoints", + "imported", + null, + w.toMutableList(), + false + ) + } + + fun copyAndInform( + source: DefaultSource, + origin: BlockPos, + positiveFeedback: (Int) -> Text, + ) { + val waypoints = Waypoints.useNonEmptyWaypoints() + ?.let { fromFirm(it, origin) } + if (waypoints == null) { + source.sendError(Waypoints.textNothingToExport()) + return + } + val data = + Firmament.tightJson.encodeToString>(waypoints) + ClipboardUtils.setTextContent(data) + source.sendFeedback(positiveFeedback(waypoints.size)) + } + + fun importAndInform( + source: DefaultSource, + pos: BlockPos?, + positiveFeedback: (Int) -> Text + ) { + val text = ClipboardUtils.getTextContents() + val wr = tryParse(text).map { intoFirm(it, pos ?: BlockPos.ORIGIN) } + val waypoints = wr.getOrElse { + source.sendError( + tr("firmament.command.waypoint.import.cw.error", + "Could not import ColeWeight waypoints.")) + Firmament.logger.error(it) + return + } + waypoints.lastRelativeImport = pos + Waypoints.waypoints = waypoints + source.sendFeedback(positiveFeedback(waypoints.size)) + } + + @Subscribe + fun onEvent(event: CommandEvent.SubCommand) { + event.subcommand(Waypoints.WAYPOINTS_SUBCOMMAND) { + thenLiteral("exportcw") { + thenExecute { + copyAndInform(source, BlockPos.ORIGIN) { + tr("firmament.command.waypoint.export.cw", + "Copied $it waypoints to clipboard in ColeWeight format.") + } + } + } + thenLiteral("exportrelativecw") { + thenExecute { + copyAndInform(source, MC.player?.blockPos ?: BlockPos.ORIGIN) { + tr("firmament.command.waypoint.export.cw.relative", + "Copied $it relative waypoints to clipboard in ColeWeight format. Make sure to stand in the same position when importing.") + } + } + } + thenLiteral("importcw") { + thenExecute { + importAndInform(source, null) { + tr("firmament.command.waypoint.import.cw.success", + "Imported $it waypoints from ColeWeight.") + } + } + } + thenLiteral("importrelativecw") { + thenExecute { + importAndInform(source, MC.player!!.blockPos) { + tr("firmament.command.waypoint.import.cw.relative", + "Imported $it relative waypoints from clipboard. Make sure you stand in the same position as when you exported these waypoints for them to line up correctly.") + } + } + } + } + } + + fun tryParse(string: String): Result> { + return runCatching { + Firmament.tightJson.decodeFromString>(string) + } + } +} diff --git a/src/main/kotlin/features/world/FairySouls.kt b/src/main/kotlin/features/world/FairySouls.kt new file mode 100644 index 0000000..d4bf560 --- /dev/null +++ b/src/main/kotlin/features/world/FairySouls.kt @@ -0,0 +1,132 @@ + + +package moe.nea.firmament.features.world + +import io.github.moulberry.repo.data.Coordinate +import me.shedaniel.math.Color +import kotlinx.serialization.Serializable +import kotlinx.serialization.serializer +import net.minecraft.text.Text +import net.minecraft.util.math.BlockPos +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> = mutableMapOf() + ) + + override val config: ManagedConfig + get() = TConfig + + object DConfig : ProfileSpecificDataHolder(serializer(), "found-fairysouls", ::Data) + + + object TConfig : ManagedConfig("fairy-souls", Category.MISC) { + 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 = emptyList() + var currentMissingSouls: List = 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 = + 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) { + currentMissingSouls.forEach { + block(it.blockPos, Color.ofRGBA(176, 0, 255, 128).color) + } + 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/features/world/FirmWaypointManager.kt b/src/main/kotlin/features/world/FirmWaypointManager.kt new file mode 100644 index 0000000..d18483c --- /dev/null +++ b/src/main/kotlin/features/world/FirmWaypointManager.kt @@ -0,0 +1,168 @@ +package moe.nea.firmament.features.world + +import com.mojang.brigadier.arguments.StringArgumentType +import kotlinx.serialization.serializer +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.suggestsList +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.util.ClipboardUtils +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TemplateUtil +import moe.nea.firmament.util.data.MultiFileDataHolder +import moe.nea.firmament.util.tr + +object FirmWaypointManager { + object DataHolder : MultiFileDataHolder(serializer(), "waypoints") + + val SHARE_PREFIX = "FIRM_WAYPOINTS/" + val ENCODED_SHARE_PREFIX = TemplateUtil.getPrefixComparisonSafeBase64Encoding(SHARE_PREFIX) + + fun createExportableCopy( + waypoints: FirmWaypoints, + ): FirmWaypoints { + val copy = waypoints.copy(waypoints = waypoints.waypoints.toMutableList()) + if (waypoints.isRelativeTo != null) { + val origin = waypoints.lastRelativeImport + if (origin != null) { + copy.waypoints.replaceAll { + it.copy( + x = it.x - origin.x, + y = it.y - origin.y, + z = it.z - origin.z, + ) + } + } else { + TODO("Add warning!") + } + } + return copy + } + + fun loadWaypoints(waypoints: FirmWaypoints, sendFeedback: (Text) -> Unit) { + val copy = waypoints.deepCopy() + if (copy.isRelativeTo != null) { + val origin = MC.player!!.blockPos + copy.waypoints.replaceAll { + it.copy( + x = it.x + origin.x, + y = it.y + origin.y, + z = it.z + origin.z, + ) + } + copy.lastRelativeImport = origin.toImmutable() + sendFeedback(tr("firmament.command.waypoint.import.ordered.success", + "Imported ${copy.size} relative waypoints. Make sure you stand in the correct spot while loading the waypoints: ${copy.isRelativeTo}.")) + } else { + sendFeedback(tr("firmament.command.waypoint.import.success", + "Imported ${copy.size} waypoints.")) + } + Waypoints.waypoints = copy + } + + fun setOrigin(source: DefaultSource, text: String?) { + val waypoints = Waypoints.useEditableWaypoints() + waypoints.isRelativeTo = text ?: waypoints.isRelativeTo ?: "" + val pos = MC.player!!.blockPos + waypoints.lastRelativeImport = pos + source.sendFeedback(tr("firmament.command.waypoint.originset", + "Set the origin of waypoints to ${FirmFormatters.formatPosition(pos)}. Run /firm waypoints export to save the waypoints relative to this position.")) + } + + @Subscribe + fun onCommands(event: CommandEvent.SubCommand) { + event.subcommand(Waypoints.WAYPOINTS_SUBCOMMAND) { + thenLiteral("setorigin") { + thenExecute { + setOrigin(source, null) + } + thenArgument("hint", RestArgumentType) { text -> + thenExecute { + setOrigin(source, this[text]) + } + } + } + thenLiteral("clearorigin") { + thenExecute { + val waypoints = Waypoints.useEditableWaypoints() + waypoints.lastRelativeImport = null + waypoints.isRelativeTo = null + source.sendFeedback(tr("firmament.command.waypoint.originunset", + "Unset the origin of the waypoints. Run /firm waypoints export to save the waypoints with absolute coordinates.")) + } + } + thenLiteral("save") { + thenArgument("name", StringArgumentType.string()) { name -> + suggestsList { DataHolder.list().keys } + thenExecute { + val waypoints = Waypoints.useNonEmptyWaypoints() + if (waypoints == null) { + source.sendError(Waypoints.textNothingToExport()) + return@thenExecute + } + waypoints.id = get(name) + val exportableWaypoints = createExportableCopy(waypoints) + DataHolder.insert(get(name), exportableWaypoints) + DataHolder.save() + source.sendFeedback(tr("firmament.command.waypoint.saved", + "Saved waypoints locally as ${get(name)}. Use /firm waypoints load to load them again.")) + } + } + } + thenLiteral("load") { + thenArgument("name", StringArgumentType.string()) { name -> + suggestsList { DataHolder.list().keys } + thenExecute { + val name = get(name) + val waypoints = DataHolder.list()[name] + if (waypoints == null) { + source.sendError( + tr("firmament.command.waypoint.nosaved", + "No saved waypoint for ${name}. Use tab completion to see available names.")) + return@thenExecute + } + loadWaypoints(waypoints, source::sendFeedback) + } + } + } + thenLiteral("export") { + thenExecute { + val waypoints = Waypoints.useNonEmptyWaypoints() + if (waypoints == null) { + source.sendError(Waypoints.textNothingToExport()) + return@thenExecute + } + val exportableWaypoints = createExportableCopy(waypoints) + val data = TemplateUtil.encodeTemplate(SHARE_PREFIX, exportableWaypoints) + ClipboardUtils.setTextContent(data) + source.sendFeedback(tr("firmament.command.waypoint.export", + "Copied ${exportableWaypoints.size} waypoints to clipboard in Firmament format.")) + } + } + thenLiteral("import") { + thenExecute { + val text = ClipboardUtils.getTextContents() + if (text.startsWith("[")) { + source.sendError(tr("firmament.command.waypoint.import.lookslikecw", + "The waypoints in your clipboard look like they might be ColeWeight waypoints. If so, use /firm waypoints importcw or /firm waypoints importrelativecw.")) + return@thenExecute + } + val waypoints = TemplateUtil.maybeDecodeTemplate(SHARE_PREFIX, text) + if (waypoints == null) { + source.sendError(tr("firmament.command.waypoint.import.error", + "Could not import Firmament waypoints from your clipboard. Make sure they are Firmament compatible waypoints.")) + return@thenExecute + } + loadWaypoints(waypoints, source::sendFeedback) + } + } + } + } +} diff --git a/src/main/kotlin/features/world/FirmWaypoints.kt b/src/main/kotlin/features/world/FirmWaypoints.kt new file mode 100644 index 0000000..d0cd55a --- /dev/null +++ b/src/main/kotlin/features/world/FirmWaypoints.kt @@ -0,0 +1,37 @@ +package moe.nea.firmament.features.world + +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import net.minecraft.util.math.BlockPos + +@Serializable +data class FirmWaypoints( + var label: String, + var id: String, + /** + * A hint to indicate where to stand while loading the waypoints. + */ + var isRelativeTo: String?, + var waypoints: MutableList, + var isOrdered: Boolean, + // TODO: val resetOnSwap: Boolean, +) { + + fun deepCopy() = copy(waypoints = waypoints.toMutableList()) + @Transient + var lastRelativeImport: BlockPos? = null + + val size get() = waypoints.size + @Serializable + data class Waypoint( + val x: Int, + val y: Int, + val z: Int, + ) { + val blockPos get() = BlockPos(x, y, z) + + companion object { + fun from(blockPos: BlockPos) = Waypoint(blockPos.x, blockPos.y, blockPos.z) + } + } +} diff --git a/src/main/kotlin/features/world/NPCWaypoints.kt b/src/main/kotlin/features/world/NPCWaypoints.kt new file mode 100644 index 0000000..592b8fa --- /dev/null +++ b/src/main/kotlin/features/world/NPCWaypoints.kt @@ -0,0 +1,40 @@ +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() + + @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/features/world/NavigableWaypoint.kt b/src/main/kotlin/features/world/NavigableWaypoint.kt new file mode 100644 index 0000000..28a517f --- /dev/null +++ b/src/main/kotlin/features/world/NavigableWaypoint.kt @@ -0,0 +1,22 @@ +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/features/world/NavigationHelper.kt b/src/main/kotlin/features/world/NavigationHelper.kt new file mode 100644 index 0000000..acdfb86 --- /dev/null +++ b/src/main/kotlin/features/world/NavigationHelper.kt @@ -0,0 +1,121 @@ +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 + ): MutableList? { + var shortestChain: MutableList? = 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/features/world/NpcWaypointGui.kt b/src/main/kotlin/features/world/NpcWaypointGui.kt new file mode 100644 index 0000000..6146e50 --- /dev/null +++ b/src/main/kotlin/features/world/NpcWaypointGui.kt @@ -0,0 +1,68 @@ +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, +) { + + 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 { + return results + } + + @Bind + fun tick() { + if (search != lastSearch) { + updateSearch() + lastSearch = search + } + } + + val results: ObservableList = 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/features/world/TemporaryWaypoints.kt b/src/main/kotlin/features/world/TemporaryWaypoints.kt new file mode 100644 index 0000000..3c8e895 --- /dev/null +++ b/src/main/kotlin/features/world/TemporaryWaypoints.kt @@ -0,0 +1,74 @@ +package moe.nea.firmament.features.world + +import me.shedaniel.math.Color +import kotlin.compareTo +import kotlin.text.clear +import kotlin.time.Duration.Companion.seconds +import net.minecraft.text.Text +import net.minecraft.util.math.BlockPos +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.events.WorldReadyEvent +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.features.world.Waypoints.TConfig +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.TimeMark +import moe.nea.firmament.util.render.RenderInWorldContext + +object TemporaryWaypoints { + data class TemporaryWaypoint( + val pos: BlockPos, + val postedAt: TimeMark, + ) + val temporaryPlayerWaypointList = mutableMapOf() + val temporaryPlayerWaypointMatcher = "(?i)x: (-?[0-9]+),? y: (-?[0-9]+),? z: (-?[0-9]+)".toPattern() + @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 onRenderTemporaryWaypoints(event: WorldRenderLastEvent) { + temporaryPlayerWaypointList.entries.removeIf { it.value.postedAt.passedTime() > TConfig.tempWaypointDuration } + if (temporaryPlayerWaypointList.isEmpty()) return + RenderInWorldContext.renderInWorld(event) { + temporaryPlayerWaypointList.forEach { (_, waypoint) -> + block(waypoint.pos, Color.ofRGBA(255, 255, 0, 128).color) + } + 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() + } + +} diff --git a/src/main/kotlin/features/world/Waypoints.kt b/src/main/kotlin/features/world/Waypoints.kt new file mode 100644 index 0000000..b4f91b0 --- /dev/null +++ b/src/main/kotlin/features/world/Waypoints.kt @@ -0,0 +1,234 @@ +package moe.nea.firmament.features.world + +import com.mojang.brigadier.arguments.IntegerArgumentType +import me.shedaniel.math.Color +import kotlin.time.Duration.Companion.hours +import kotlin.time.Duration.Companion.seconds +import net.minecraft.command.argument.BlockPosArgumentType +import net.minecraft.text.Text +import net.minecraft.util.math.Vec3d +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.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.MC +import moe.nea.firmament.util.mc.asFakeServer +import moe.nea.firmament.util.render.RenderInWorldContext +import moe.nea.firmament.util.tr + +object Waypoints : FirmamentFeature { + override val identifier: String + get() = "waypoints" + + object TConfig : ManagedConfig(identifier, Category.MINING) { // TODO: add to misc + 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 } + val resetWaypointOrderOnWorldSwap by toggle("reset-order-on-swap") { true } + // TODO: look ahead size + } + + override val config get() = TConfig + var waypoints: FirmWaypoints? = null + var orderedIndex = 0 + + @Subscribe + fun onRenderOrderedWaypoints(event: WorldRenderLastEvent) { + val w = useNonEmptyWaypoints() ?: return + RenderInWorldContext.renderInWorld(event) { + if (!w.isOrdered) { + w.waypoints.withIndex().forEach { + block(it.value.blockPos, Color.ofRGBA(0, 80, 160, 128).color) + if (TConfig.showIndex) withFacingThePlayer(it.value.blockPos.toCenterPos()) { + text(Text.literal(it.index.toString())) + } + } + } else { + orderedIndex %= w.waypoints.size + val firstColor = Color.ofRGBA(0, 200, 40, 180) + color(firstColor) + tracer(w.waypoints[orderedIndex].blockPos.toCenterPos(), lineWidth = 3f) + w.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 + block(pos.blockPos, col.color) + if (TConfig.showIndex) withFacingThePlayer(pos.blockPos.toCenterPos()) { + text(Text.literal(index.toString())) + } + } + } + } + } + + @Subscribe + fun onTick(event: TickEvent) { + val w = useNonEmptyWaypoints() ?: return + if (!w.isOrdered) return + orderedIndex %= w.waypoints.size + val p = MC.player?.pos ?: return + if (TConfig.skipToNearest) { + orderedIndex = + (w.waypoints.withIndex().minBy { it.value.blockPos.getSquaredDistance(p) }.index + 1) % w.waypoints.size + + } else { + if (w.waypoints[orderedIndex].blockPos.isWithinDistance(p, 3.0)) { + orderedIndex = (orderedIndex + 1) % w.waypoints.size + } + } + } + + + fun useEditableWaypoints(): FirmWaypoints { + var w = waypoints + if (w == null) { + w = FirmWaypoints("Unlabeled", "unknown", null, mutableListOf(), false) + waypoints = w + } + return w + } + + fun useNonEmptyWaypoints(): FirmWaypoints? { + val w = waypoints + if (w == null) return null + if (w.waypoints.isEmpty()) return null + return w + } + + val WAYPOINTS_SUBCOMMAND = "waypoints" + + @Subscribe + fun onWorldSwap(event: WorldReadyEvent) { + if (TConfig.resetWaypointOrderOnWorldSwap) { + orderedIndex = 0 + } + } + + @Subscribe + fun onCommand(event: CommandEvent.SubCommand) { + event.subcommand("waypoint") { + thenArgument("pos", BlockPosArgumentType.blockPos()) { pos -> + thenExecute { + source + val position = pos.get(this).toAbsoluteBlockPos(source.asFakeServer()) + val w = useEditableWaypoints() + w.waypoints.add(FirmWaypoints.Waypoint.from(position)) + source.sendFeedback(Text.stringifiedTranslatable("firmament.command.waypoint.added", + position.x, + position.y, + position.z)) + } + } + } + event.subcommand(WAYPOINTS_SUBCOMMAND) { + thenLiteral("reset") { + thenExecute { + orderedIndex = 0 + source.sendFeedback(tr( + "firmament.command.waypoint.reset", + "Reset your ordered waypoint index back to 0. If you want to delete all waypoints use /firm waypoints clear instead.")) + } + } + thenLiteral("changeindex") { + thenArgument("from", IntegerArgumentType.integer(0)) { fromIndex -> + thenArgument("to", IntegerArgumentType.integer(0)) { toIndex -> + thenExecute { + val w = useEditableWaypoints() + val toIndex = toIndex.get(this) + val fromIndex = fromIndex.get(this) + if (fromIndex !in w.waypoints.indices) { + source.sendError(textInvalidIndex(fromIndex)) + return@thenExecute + } + if (toIndex !in w.waypoints.indices) { + source.sendError(textInvalidIndex(toIndex)) + return@thenExecute + } + val waypoint = w.waypoints.removeAt(fromIndex) + w.waypoints.add( + if (toIndex > fromIndex) toIndex - 1 + else toIndex, + waypoint) + source.sendFeedback( + tr("firmament.command.waypoint.indexchange", + "Moved waypoint from index $fromIndex to $toIndex. Note that this only matters for ordered waypoints.") + ) + } + } + } + } + thenLiteral("clear") { + thenExecute { + waypoints = null + source.sendFeedback(Text.translatable("firmament.command.waypoint.clear")) + } + } + thenLiteral("toggleordered") { + thenExecute { + val w = useEditableWaypoints() + w.isOrdered = !w.isOrdered + if (w.isOrdered) { + val p = MC.player?.pos ?: Vec3d.ZERO + orderedIndex = // TODO: this should be extracted to a utility method + w.waypoints.withIndex().minByOrNull { it.value.blockPos.getSquaredDistance(p) }?.index ?: 0 + } + source.sendFeedback(Text.translatable("firmament.command.waypoint.ordered.toggle.${w.isOrdered}")) + } + } + thenLiteral("skip") { + thenExecute { + val w = useNonEmptyWaypoints() + if (w != null && w.isOrdered) { + orderedIndex = (orderedIndex + 1) % w.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) + val w = useNonEmptyWaypoints() + if (w != null && index in w.waypoints.indices) { + w.waypoints.removeAt(index) + source.sendFeedback(Text.stringifiedTranslatable("firmament.command.waypoint.remove", + index)) + } else { + source.sendError(Text.stringifiedTranslatable("firmament.command.waypoint.remove.error")) + } + } + } + } + } + } + + fun textInvalidIndex(index: Int) = + tr("firmament.command.waypoint.invalid-index", + "Invalid index $index provided.") + + fun textNothingToExport(): Text = + tr("firmament.command.waypoint.export.nowaypoints", + "No waypoints to export found. Add some with /firm waypoint ~ ~ ~.") +} + +fun List.wrappingWindow(startIndex: Int, windowSize: Int): List { + val result = ArrayList(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 +} diff --git a/src/main/kotlin/gui/BarComponent.kt b/src/main/kotlin/gui/BarComponent.kt new file mode 100644 index 0000000..da781da --- /dev/null +++ b/src/main/kotlin/gui/BarComponent.kt @@ -0,0 +1,115 @@ +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.client.render.RenderLayer +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament + +class BarComponent( + val progress: GetSetter, val total: GetSetter, + 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( + RenderLayer::getGuiTextured, + identifier, + x, y, x + width, x + height, + u1, u2, v1, v2, + color.color + ) + } + } + + 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) +} diff --git a/src/main/kotlin/gui/CheckboxComponent.kt b/src/main/kotlin/gui/CheckboxComponent.kt new file mode 100644 index 0000000..fc48661 --- /dev/null +++ b/src/main/kotlin/gui/CheckboxComponent.kt @@ -0,0 +1,57 @@ +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.MouseEvent +import io.github.notenoughupdates.moulconfig.observer.GetSetter +import io.github.notenoughupdates.moulconfig.platform.ModernRenderContext +import net.minecraft.client.render.RenderLayer +import moe.nea.firmament.Firmament + +class CheckboxComponent( + val state: GetSetter, + val value: T, +) : GuiComponent() { + override fun getWidth(): Int { + return 16 + } + + override fun getHeight(): Int { + return 16 + } + + fun isEnabled(): Boolean { + return state.get() == value + } + + override fun render(context: GuiImmediateContext) { + val ctx = (context.renderContext as ModernRenderContext).drawContext + ctx.drawGuiTexture( + RenderLayer::getGuiTextured, + if (isEnabled()) Firmament.identifier("widget/checkbox_checked") + else Firmament.identifier("widget/checkbox_unchecked"), + 0, 0, + 16, 16 + ) + } + + var isClicking = false + + override fun mouseEvent(mouseEvent: MouseEvent, context: GuiImmediateContext): Boolean { + if (mouseEvent is MouseEvent.Click) { + if (isClicking && !mouseEvent.mouseState && mouseEvent.mouseButton == 0) { + isClicking = false + if (context.isHovered) + state.set(value) + blur() + return true + } + if (mouseEvent.mouseState && mouseEvent.mouseButton == 0 && context.isHovered) { + requestFocus() + isClicking = true + return true + } + } + return false + } +} diff --git a/src/main/kotlin/gui/EmptyComponent.kt b/src/main/kotlin/gui/EmptyComponent.kt new file mode 100644 index 0000000..13efa89 --- /dev/null +++ b/src/main/kotlin/gui/EmptyComponent.kt @@ -0,0 +1,17 @@ +package moe.nea.firmament.gui + +import io.github.notenoughupdates.moulconfig.gui.GuiComponent +import io.github.notenoughupdates.moulconfig.gui.GuiImmediateContext + +class EmptyComponent : GuiComponent() { + override fun getWidth(): Int { + return 0 + } + + override fun getHeight(): Int { + return 0 + } + + override fun render(context: GuiImmediateContext) { + } +} diff --git a/src/main/kotlin/gui/FirmButtonComponent.kt b/src/main/kotlin/gui/FirmButtonComponent.kt new file mode 100644 index 0000000..fe9b476 --- /dev/null +++ b/src/main/kotlin/gui/FirmButtonComponent.kt @@ -0,0 +1,81 @@ + +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 = 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 = + 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()) + element.render(getChildContext(context)) + context.renderContext.popMatrix() + } +} diff --git a/src/main/kotlin/gui/FirmHoverComponent.kt b/src/main/kotlin/gui/FirmHoverComponent.kt new file mode 100644 index 0000000..e38582a --- /dev/null +++ b/src/main/kotlin/gui/FirmHoverComponent.kt @@ -0,0 +1,59 @@ +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>, + val hoverDelay: Duration, +) : GuiComponent() { + override fun getWidth(): Int { + return child.width + } + + override fun getHeight(): Int { + return child.height + } + + override fun foldChildren( + initial: T, + visitor: BiFunction + ): T { + return visitor.apply(child, initial) + } + + override fun render(context: GuiImmediateContext) { + if (context.isHovered && (permaHover || lastMouseMove.passedTime() > hoverDelay)) { + context.renderContext.scheduleDrawTooltip(context.mouseX, context.mouseY, 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/gui/FixedComponent.kt b/src/main/kotlin/gui/FixedComponent.kt new file mode 100644 index 0000000..ae1da2d --- /dev/null +++ b/src/main/kotlin/gui/FixedComponent.kt @@ -0,0 +1,38 @@ + +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?, + val fixedHeight: GetSetter?, + val component: GuiComponent, +) : GuiComponent() { + override fun getWidth(): Int = fixedWidth?.get() ?: component.width + + override fun getHeight(): Int = fixedHeight?.get() ?: component.height + + override fun foldChildren(initial: T, visitor: BiFunction): 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/gui/ImageComponent.kt b/src/main/kotlin/gui/ImageComponent.kt new file mode 100644 index 0000000..695c0ed --- /dev/null +++ b/src/main/kotlin/gui/ImageComponent.kt @@ -0,0 +1,35 @@ +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, + 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.drawComplexTexture( + resourceLocation.get(), + 0f, 0f, + context.width.toFloat(), context.height.toFloat(), + { + it.uv(u1, v1, u2, v2) + } + ) + } +} diff --git a/src/main/kotlin/gui/TickComponent.kt b/src/main/kotlin/gui/TickComponent.kt new file mode 100644 index 0000000..d1879b1 --- /dev/null +++ b/src/main/kotlin/gui/TickComponent.kt @@ -0,0 +1,18 @@ +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/gui/config/AllConfigsGui.kt b/src/main/kotlin/gui/config/AllConfigsGui.kt new file mode 100644 index 0000000..f9ffd2d --- /dev/null +++ b/src/main/kotlin/gui/config/AllConfigsGui.kt @@ -0,0 +1,103 @@ +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.annotations.Subscribe +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.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 } + + object ConfigConfig : ManagedConfig("configconfig", Category.META) { + val enableYacl by toggle("enable-yacl") { false } + val enableMoulConfig by toggle("enable-moulconfig") { true } + val enableWideMC by toggle("wide-moulconfig") { false } + } + + fun List.toObservableList(): ObservableList = ObservableList(this) + + class CategoryMapping(val category: ManagedConfig.Category) { + @get:Bind("configs") + val configs = category.configs.map { EntryMapping(it) }.toObservableList() + + @Bind + fun name() = category.labelText.string + + @Bind + fun close() { + MC.screen?.close() + } + + class EntryMapping(val config: ManagedConfig) { + @Bind + fun name() = Text.translatable("firmament.config.${config.name}").string + + @Bind + fun openEditor() { + config.showConfigEditor(MC.screen) + } + } + } + + class CategoryView { + @get:Bind("categories") + val categories = ManagedConfig.Category.entries + .map { CategoryEntry(it) } + .toObservableList() + + class CategoryEntry(val category: ManagedConfig.Category) { + @Bind + fun name() = category.labelText.string + + @Bind + fun open() { + MC.screen = MoulConfigUtils.loadScreen("config/category", CategoryMapping(category), MC.screen) + } + } + } + + fun makeBuiltInScreen(parent: Screen? = null): Screen { + return MoulConfigUtils.loadScreen("config/main", CategoryView(), parent) + } + + fun makeScreen(search: String? = null, parent: Screen? = null): Screen { + val wantedKey = when { + ConfigConfig.enableMoulConfig -> "moulconfig" + ConfigConfig.enableYacl -> "yacl" + else -> "builtin" + } + val provider = FirmamentConfigScreenProvider.providers.find { it.key == wantedKey } + ?: FirmamentConfigScreenProvider.providers.first() + return provider.open(search, parent) + } + + fun showAllGuis() { + setScreenLater(makeScreen()) + } + + @Subscribe + fun registerCommands(event: CommandEvent.SubCommand) { + event.subcommand("search") { + thenArgument("search", RestArgumentType) { search -> + thenExecute { + val search = this[search] + setScreenLater(makeScreen(search = search)) + } + } + } + } + +} diff --git a/src/main/kotlin/gui/config/BooleanHandler.kt b/src/main/kotlin/gui/config/BooleanHandler.kt new file mode 100644 index 0000000..8592777 --- /dev/null +++ b/src/main/kotlin/gui/config/BooleanHandler.kt @@ -0,0 +1,37 @@ + + +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 { + override fun toJson(element: Boolean): JsonElement? { + return JsonPrimitive(element) + } + + override fun fromJson(element: JsonElement): Boolean { + return element.jsonPrimitive.boolean + } + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow( + opt.labelText, + CenterComponent(SwitchComponent(object : GetSetter { + override fun get(): Boolean { + return opt.get() + } + + override fun set(newValue: Boolean) { + opt.set(newValue) + config.save() + } + }, 200) + )) + } +} diff --git a/src/main/kotlin/gui/config/BuiltInConfigScreenProvider.kt b/src/main/kotlin/gui/config/BuiltInConfigScreenProvider.kt new file mode 100644 index 0000000..8ecdfa2 --- /dev/null +++ b/src/main/kotlin/gui/config/BuiltInConfigScreenProvider.kt @@ -0,0 +1,14 @@ +package moe.nea.firmament.gui.config + +import com.google.auto.service.AutoService +import net.minecraft.client.gui.screen.Screen + +@AutoService(FirmamentConfigScreenProvider::class) +class BuiltInConfigScreenProvider : FirmamentConfigScreenProvider { + override val key: String + get() = "builtin" + + override fun open(search: String?, parent: Screen?): Screen { + return AllConfigsGui.makeBuiltInScreen(parent) + } +} diff --git a/src/main/kotlin/gui/config/ChoiceHandler.kt b/src/main/kotlin/gui/config/ChoiceHandler.kt new file mode 100644 index 0000000..2ea3efc --- /dev/null +++ b/src/main/kotlin/gui/config/ChoiceHandler.kt @@ -0,0 +1,48 @@ +package moe.nea.firmament.gui.config + +import io.github.notenoughupdates.moulconfig.gui.HorizontalAlign +import io.github.notenoughupdates.moulconfig.gui.VerticalAlign +import io.github.notenoughupdates.moulconfig.gui.component.AlignComponent +import io.github.notenoughupdates.moulconfig.gui.component.RowComponent +import io.github.notenoughupdates.moulconfig.gui.component.TextComponent +import kotlinx.serialization.json.JsonElement +import kotlin.jvm.optionals.getOrNull +import net.minecraft.util.StringIdentifiable +import moe.nea.firmament.gui.CheckboxComponent +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.json.KJsonOps + +class ChoiceHandler( + val enumClass: Class, + val universe: List, +) : ManagedConfig.OptionHandler where E : Enum, E : StringIdentifiable { + val codec = StringIdentifiable.createCodec { + @Suppress("UNCHECKED_CAST", "PLATFORM_CLASS_MAPPED_TO_KOTLIN") + (universe as java.util.List<*>).toArray(arrayOfNulls>(0)) as Array + } + val renderer = EnumRenderer.default() + + override fun toJson(element: E): JsonElement? { + return codec.encodeStart(KJsonOps.INSTANCE, element) + .promotePartial { ErrorUtil.softError("Failed to encode json element '$element': $it") }.result() + .getOrNull() + } + + override fun fromJson(element: JsonElement): E { + return codec.decode(KJsonOps.INSTANCE, element) + .promotePartial { ErrorUtil.softError("Failed to decode json element '$element': $it") } + .result() + .get() + .first + } + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendFullRow(TextComponent(opt.labelText.string)) + for (e in universe) { + guiAppender.appendFullRow(RowComponent( + AlignComponent(CheckboxComponent(opt, e), { HorizontalAlign.LEFT }, { VerticalAlign.CENTER }), + TextComponent(renderer.getName(opt, e).string) + )) + } + } +} diff --git a/src/main/kotlin/gui/config/ClickHandler.kt b/src/main/kotlin/gui/config/ClickHandler.kt new file mode 100644 index 0000000..fa1c621 --- /dev/null +++ b/src/main/kotlin/gui/config/ClickHandler.kt @@ -0,0 +1,24 @@ + + +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 { + override fun toJson(element: Unit): JsonElement? { + return null + } + + override fun fromJson(element: JsonElement) {} + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow( + opt.labelText, + FirmButtonComponent( + TextComponent(opt.labelText.string), + action = runnable), + ) + } +} diff --git a/src/main/kotlin/gui/config/ColourHandler.kt b/src/main/kotlin/gui/config/ColourHandler.kt new file mode 100644 index 0000000..83ce8ac --- /dev/null +++ b/src/main/kotlin/gui/config/ColourHandler.kt @@ -0,0 +1,82 @@ +package moe.nea.firmament.gui.config + +import io.github.notenoughupdates.moulconfig.ChromaColour +import io.github.notenoughupdates.moulconfig.gui.component.ColorSelectComponent +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement + +class ColourHandler(val config: ManagedConfig) : + ManagedConfig.OptionHandler { + @Serializable + data class ChromaDelegate( + @SerialName("h") + val hue: Float, + @SerialName("s") + val saturation: Float, + @SerialName("b") + val brightness: Float, + @SerialName("a") + val alpha: Int, + @SerialName("c") + val timeForFullRotationInMillis: Int, + ) { + constructor(delegate: ChromaColour) : this( + delegate.hue, + delegate.saturation, + delegate.brightness, + delegate.alpha, + delegate.timeForFullRotationInMillis + ) + + fun into(): ChromaColour = ChromaColour(hue, saturation, brightness, timeForFullRotationInMillis, alpha) + } + + object ChromaSerializer : KSerializer { + override val descriptor: SerialDescriptor + get() = SerialDescriptor("FirmChromaColour", ChromaDelegate.serializer().descriptor) + + override fun serialize( + encoder: Encoder, + value: ChromaColour + ) { + encoder.encodeSerializableValue(ChromaDelegate.serializer(), ChromaDelegate(value)) + } + + override fun deserialize(decoder: Decoder): ChromaColour { + return decoder.decodeSerializableValue(ChromaDelegate.serializer()).into() + } + } + + override fun toJson(element: ChromaColour): JsonElement? { + return Json.encodeToJsonElement(ChromaSerializer, element) + } + + override fun fromJson(element: JsonElement): ChromaColour { + return Json.decodeFromJsonElement(ChromaSerializer, element) + } + + override fun emitGuiElements( + opt: ManagedOption, + guiAppender: GuiAppender + ) { + guiAppender.appendLabeledRow( + opt.labelText, + ColorSelectComponent( + 0, + 0, + opt.value.toLegacyString(), + { + opt.value = ChromaColour.forLegacyString(it) + config.save() + }, + { } + ) + ) + } +} diff --git a/src/main/kotlin/gui/config/DurationHandler.kt b/src/main/kotlin/gui/config/DurationHandler.kt new file mode 100644 index 0000000..8d485b1 --- /dev/null +++ b/src/main/kotlin/gui/config/DurationHandler.kt @@ -0,0 +1,58 @@ + + +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 { + 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, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow( + opt.labelText, + RowComponent( + TextComponent(IMinecraft.instance.defaultFontRenderer, + { FirmFormatters.formatTimespan(opt.value) }, + 40, + TextComponent.TextAlignment.CENTER, + true, + false), + SliderComponent( + object : GetSetter { + 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/gui/config/EnumRenderer.kt b/src/main/kotlin/gui/config/EnumRenderer.kt new file mode 100644 index 0000000..3b80b7e --- /dev/null +++ b/src/main/kotlin/gui/config/EnumRenderer.kt @@ -0,0 +1,15 @@ +package moe.nea.firmament.gui.config + +import net.minecraft.text.Text + +interface EnumRenderer { + fun getName(option: ManagedOption, value: E): Text + + companion object { + fun > default() = object : EnumRenderer { + override fun getName(option: ManagedOption, value: E): Text { + return Text.translatable(option.rawLabelText + ".choice." + value.name.lowercase()) + } + } + } +} diff --git a/src/main/kotlin/gui/config/FirmamentConfigScreenProvider.kt b/src/main/kotlin/gui/config/FirmamentConfigScreenProvider.kt new file mode 100644 index 0000000..8700ffa --- /dev/null +++ b/src/main/kotlin/gui/config/FirmamentConfigScreenProvider.kt @@ -0,0 +1,24 @@ +package moe.nea.firmament.gui.config + +import net.minecraft.client.gui.screen.Screen +import moe.nea.firmament.util.compatloader.CompatLoader + +interface FirmamentConfigScreenProvider { + val key: String + val isEnabled: Boolean get() = true + + fun open(search: String?, parent: Screen?): Screen + + companion object : CompatLoader(FirmamentConfigScreenProvider::class) { + val providers by lazy { + allValidInstances + .filter { it.isEnabled } + .sortedWith( + Comparator + .comparing({ it.key == "builtin" }) + .reversed() + .then(Comparator.comparing({ it.key })) + ).toList() + } + } +} diff --git a/src/main/kotlin/gui/config/GuiAppender.kt b/src/main/kotlin/gui/config/GuiAppender.kt new file mode 100644 index 0000000..329319d --- /dev/null +++ b/src/main/kotlin/gui/config/GuiAppender.kt @@ -0,0 +1,40 @@ + + +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() + 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/gui/config/HudMetaHandler.kt b/src/main/kotlin/gui/config/HudMetaHandler.kt new file mode 100644 index 0000000..a9659ee --- /dev/null +++ b/src/main/kotlin/gui/config/HudMetaHandler.kt @@ -0,0 +1,42 @@ +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.client.gui.screen.Screen +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 { + 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) + } + + fun openEditor(option: ManagedOption, oldScreen: Screen) { + MC.screen = JarvisIntegration.jarvis.getHudEditor( + oldScreen, + listOf(option.value) + ) + } + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow( + opt.labelText, + FirmButtonComponent( + TextComponent( + Text.stringifiedTranslatable("firmament.hud.edit", label).string), + ) { + openEditor(opt, guiAppender.screenAccessor()) + }) + } +} diff --git a/src/main/kotlin/gui/config/IntegerHandler.kt b/src/main/kotlin/gui/config/IntegerHandler.kt new file mode 100644 index 0000000..31ce90f --- /dev/null +++ b/src/main/kotlin/gui/config/IntegerHandler.kt @@ -0,0 +1,54 @@ + + +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 { + override fun toJson(element: Int): JsonElement? { + return JsonPrimitive(element) + } + + override fun fromJson(element: JsonElement): Int { + return element.jsonPrimitive.int + } + + override fun emitGuiElements(opt: ManagedOption, 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 { + 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/gui/config/JAnyHud.kt b/src/main/kotlin/gui/config/JAnyHud.kt new file mode 100644 index 0000000..35c4eb2 --- /dev/null +++ b/src/main/kotlin/gui/config/JAnyHud.kt @@ -0,0 +1,48 @@ + + +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/gui/config/KeyBindingHandler.kt b/src/main/kotlin/gui/config/KeyBindingHandler.kt new file mode 100644 index 0000000..14a4b32 --- /dev/null +++ b/src/main/kotlin/gui/config/KeyBindingHandler.kt @@ -0,0 +1,52 @@ +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 kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.encodeToJsonElement +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 { + + override fun initOption(opt: ManagedOption) { + FirmamentKeyBindings.registerKeyBinding(name, opt) + } + + override fun toJson(element: SavedKeyBinding): JsonElement? { + return Json.encodeToJsonElement(element) + } + + override fun fromJson(element: JsonElement): SavedKeyBinding { + return Json.decodeFromJsonElement(element) + } + + fun createButtonComponent(opt: ManagedOption): FirmButtonComponent { + lateinit var button: FirmButtonComponent + val sm = KeyBindingStateManager( + { opt.value }, + { + opt.value = it + opt.element.save() + }, + { button.blur() }, + { button.requestFocus() } + ) + button = sm.createButton() + sm.updateLabel() + return button + } + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow(opt.labelText, createButtonComponent(opt)) + } + +} diff --git a/src/main/kotlin/gui/config/KeyBindingStateManager.kt b/src/main/kotlin/gui/config/KeyBindingStateManager.kt new file mode 100644 index 0000000..1528ac4 --- /dev/null +++ b/src/main/kotlin/gui/config/KeyBindingStateManager.kt @@ -0,0 +1,146 @@ +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 net.minecraft.text.Text +import net.minecraft.util.Formatting +import moe.nea.firmament.gui.FirmButtonComponent +import moe.nea.firmament.keybindings.SavedKeyBinding + +class KeyBindingStateManager( + val value: () -> SavedKeyBinding, + val setValue: (key: SavedKeyBinding) -> Unit, + val blur: () -> Unit, + val requestFocus: () -> Unit, +) { + var editing = false + var lastPressed = 0 + var lastPressedNonModifier = 0 + var label: Text = Text.literal("") + + fun onClick() { + if (editing) { + editing = false + blur() + } else { + editing = true + requestFocus() + } + updateLabel() + } + + fun keyboardEvent(keyCode: Int, pressed: Boolean): Boolean { + return if (pressed) onKeyPressed(keyCode, SavedKeyBinding.getModInt()) + else onKeyReleased(keyCode, SavedKeyBinding.getModInt()) + } + + fun onKeyPressed(ch: Int, modifiers: Int): Boolean { + if (!editing) { + return false + } + if (ch == GLFW.GLFW_KEY_ESCAPE) { + lastPressedNonModifier = 0 + editing = false + lastPressed = 0 + setValue(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 { + setValue( + SavedKeyBinding( + ch, modifiers + ) + ) + editing = false + blur() + lastPressed = 0 + lastPressedNonModifier = 0 + } + updateLabel() + return true + } + + 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)) { + setValue(SavedKeyBinding(ch, modifiers)) + editing = false + blur() + lastPressed = 0 + lastPressedNonModifier = 0 + } + updateLabel() + return true + } + + fun updateLabel() { + var stroke = value().format() + if (editing) { + stroke = Text.literal("") + val (shift, ctrl, alt) = 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 + } + + fun createButton(): FirmButtonComponent { + return object : FirmButtonComponent( + TextComponent( + IMinecraft.instance.defaultFontRenderer, + { this@KeyBindingStateManager.label.string }, + 130, + TextComponent.TextAlignment.LEFT, + false, + false + ), action = { + this@KeyBindingStateManager.onClick() + }) { + override fun keyboardEvent(event: KeyboardEvent, context: GuiImmediateContext): Boolean { + if (event is KeyboardEvent.KeyPressed) { + return this@KeyBindingStateManager.keyboardEvent(event.keycode, event.pressed) + } + return super.keyboardEvent(event, context) + } + + override fun getBackground(context: GuiImmediateContext): NinePatch { + if (this@KeyBindingStateManager.editing) return activeBg + return super.getBackground(context) + } + + + override fun onLostFocus() { + this@KeyBindingStateManager.onLostFocus() + } + } + } +} diff --git a/src/main/kotlin/gui/config/ManagedConfig.kt b/src/main/kotlin/gui/config/ManagedConfig.kt new file mode 100644 index 0000000..12b82d6 --- /dev/null +++ b/src/main/kotlin/gui/config/ManagedConfig.kt @@ -0,0 +1,260 @@ +package moe.nea.firmament.gui.config + +import com.mojang.serialization.Codec +import io.github.notenoughupdates.moulconfig.ChromaColour +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 net.minecraft.util.StringIdentifiable +import moe.nea.firmament.Firmament +import moe.nea.firmament.gui.FirmButtonComponent +import moe.nea.firmament.keybindings.SavedKeyBinding +import moe.nea.firmament.util.ScreenUtil.setScreenLater +import moe.nea.firmament.util.collections.InstanceList + +abstract class ManagedConfig( + override val name: String, + val category: Category, + // TODO: allow vararg secondaryCategories: Category, +) : ManagedConfigElement() { + enum class Category { + // Böse Kategorie, nicht benutzten lol + MISC, + CHAT, + INVENTORY, + ITEMS, + MINING, + GARDEN, + EVENTS, + INTEGRATIONS, + META, + DEV, + ; + + val labelText: Text = Text.translatable("firmament.config.category.${name.lowercase()}") + val description: Text = Text.translatable("firmament.config.category.${name.lowercase()}.description") + val configs: MutableList = mutableListOf() + } + + companion object { + val allManagedConfigs = InstanceList("ManagedConfig") + } + + interface OptionHandler { + fun initOption(opt: ManagedOption) {} + fun toJson(element: T): JsonElement? + fun fromJson(element: JsonElement): T + fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) + } + + init { + allManagedConfigs.getAll().forEach { + require(it.name != name) { "Duplicate name '$name' used for config" } + } + allManagedConfigs.add(this) + category.configs.add(this) + } + + // TODO: warn if two files use the same config file name :( + 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>() + val sortedOptions = mutableListOf>() + + private var latestGuiAppender: GuiAppender? = null + + protected fun option( + propertyName: String, + default: () -> T, + handler: OptionHandler + ): ManagedOption { + 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 { + return option(propertyName, default, BooleanHandler(this)) + } + + protected fun colour(propertyName: String, default: ()-> ChromaColour) : ManagedOption { + return option(propertyName, default, ColourHandler(this)) + } + + protected fun choice( + propertyName: String, + enumClass: Class, + default: () -> E + ): ManagedOption where E : Enum, E : StringIdentifiable { + return option(propertyName, default, ChoiceHandler(enumClass, enumClass.enumConstants.toList())) + } + + protected inline fun choice( + propertyName: String, + noinline default: () -> E + ): ManagedOption where E : Enum, E : StringIdentifiable { + return choice(propertyName, E::class.java, default) + } + + private fun createStringIdentifiable(x: () -> Array): Codec where E : Enum, E : StringIdentifiable { + return StringIdentifiable.createCodec { x() } + } + + // TODO: wait on https://youtrack.jetbrains.com/issue/KT-73434 +// protected inline fun choice( +// propertyName: String, +// noinline default: () -> E +// ): ManagedOption where E : Enum, E : StringIdentifiable { +// return choice( +// propertyName, +// enumEntries().toList(), +// StringIdentifiable.createCodec { enumValues() }, +// EnumRenderer.default(), +// default +// ) +// } + open fun onChange(option: ManagedOption<*>) { + } + + protected fun duration( + propertyName: String, + min: Duration, + max: Duration, + default: () -> Duration, + ): ManagedOption { + return option(propertyName, default, DurationHandler(this, min, max)) + } + + + protected fun position( + propertyName: String, + width: Int, + height: Int, + default: () -> Point, + ): ManagedOption { + 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 = keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(default()) } + + protected fun keyBindingWithOutDefaultModifiers( + propertyName: String, + default: () -> SavedKeyBinding, + ): ManagedOption { + return option(propertyName, default, KeyBindingHandler("firmament.config.${name}.${propertyName}", this)) + } + + protected fun keyBindingWithDefaultUnbound( + propertyName: String, + ): ManagedOption { + return keyBindingWithOutDefaultModifiers(propertyName) { SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) } + } + + protected fun integer( + propertyName: String, + min: Int, + max: Int, + default: () -> Int, + ): ManagedOption { + return option(propertyName, default, IntegerHandler(this, min, max)) + } + + protected fun button(propertyName: String, runnable: () -> Unit): ManagedOption { + return option(propertyName, { }, ClickHandler(this, runnable)) + } + + protected fun string(propertyName: String, default: () -> String): ManagedOption { + return option(propertyName, default, StringHandler(this)) + } + + + fun reloadGui() { + latestGuiAppender?.reloadables?.forEach { it() } + } + + val translationKey get() = "firmament.config.${name}" + val labelText: Text = Text.translatable(translationKey) + + 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/gui/config/ManagedConfigElement.kt b/src/main/kotlin/gui/config/ManagedConfigElement.kt new file mode 100644 index 0000000..28cd6b8 --- /dev/null +++ b/src/main/kotlin/gui/config/ManagedConfigElement.kt @@ -0,0 +1,8 @@ + + +package moe.nea.firmament.gui.config + +abstract class ManagedConfigElement { + abstract val name: String + +} diff --git a/src/main/kotlin/gui/config/ManagedOption.kt b/src/main/kotlin/gui/config/ManagedOption.kt new file mode 100644 index 0000000..830086c --- /dev/null +++ b/src/main/kotlin/gui/config/ManagedOption.kt @@ -0,0 +1,68 @@ +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.util.ErrorUtil + +class ManagedOption( + val element: ManagedConfig, + val propertyName: String, + val default: () -> T, + val handler: ManagedConfig.OptionHandler +) : ReadWriteProperty, GetSetter { + 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 = Text.translatable(rawLabelText) + val descriptionTranslationKey = "firmament.config.${element.name}.${propertyName}.description" + val labelDescription: Text = Text.translatable(descriptionTranslationKey) + + private var actualValue: T? = null + var value: T + get() = actualValue ?: error("Lateinit variable not initialized") + set(value) { + actualValue = value + element.onChange(this) + } + + 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) { + ErrorUtil.logError( + "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/gui/config/StringHandler.kt b/src/main/kotlin/gui/config/StringHandler.kt new file mode 100644 index 0000000..a326abb --- /dev/null +++ b/src/main/kotlin/gui/config/StringHandler.kt @@ -0,0 +1,36 @@ + + +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 { + override fun toJson(element: String): JsonElement? { + return JsonPrimitive(element) + } + + override fun fromJson(element: JsonElement): String { + return element.jsonPrimitive.content + } + + override fun emitGuiElements(opt: ManagedOption, guiAppender: GuiAppender) { + guiAppender.appendLabeledRow( + opt.labelText, + TextFieldComponent( + object : GetSetter 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/gui/entity/EntityModifier.kt b/src/main/kotlin/gui/entity/EntityModifier.kt new file mode 100644 index 0000000..9623070 --- /dev/null +++ b/src/main/kotlin/gui/entity/EntityModifier.kt @@ -0,0 +1,9 @@ + +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/gui/entity/EntityRenderer.kt b/src/main/kotlin/gui/entity/EntityRenderer.kt new file mode 100644 index 0000000..a1b2577 --- /dev/null +++ b/src/main/kotlin/gui/entity/EntityRenderer.kt @@ -0,0 +1,237 @@ +package moe.nea.firmament.gui.entity + +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonObject +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.entity.SpawnReason +import net.minecraft.util.Identifier +import net.minecraft.world.World +import moe.nea.firmament.util.ErrorUtil +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.iterate +import moe.nea.firmament.util.openFirmamentResource +import moe.nea.firmament.util.render.enableScissorWithTranslation + +object EntityRenderer { + val fakeWorld: World get() = MC.lastWorld!! + private fun t(entityType: EntityType): () -> T { + return { entityType.create(fakeWorld, SpawnReason.LOAD)!! } + } + + val entityIds: Map LivingEntity> = mapOf( + "Armadillo" to t(EntityType.ARMADILLO), + "ArmorStand" to t(EntityType.ARMOR_STAND), + "Axolotl" to t(EntityType.AXOLOTL), + "BREEZE" to t(EntityType.BREEZE), + "Bat" to t(EntityType.BAT), + "Bee" to t(EntityType.BEE), + "Blaze" to t(EntityType.BLAZE), + "CaveSpider" to t(EntityType.CAVE_SPIDER), + "Chicken" to t(EntityType.CHICKEN), + "Cod" to t(EntityType.COD), + "Cow" to t(EntityType.COW), + "Creaking" to t(EntityType.CREAKING), + "Creeper" to t(EntityType.CREEPER), + "Dolphin" to t(EntityType.DOLPHIN), + "Donkey" to t(EntityType.DONKEY), + "Dragon" to t(EntityType.ENDER_DRAGON), + "Drowned" to t(EntityType.DROWNED), + "Eisengolem" to t(EntityType.IRON_GOLEM), + "Enderman" to t(EntityType.ENDERMAN), + "Endermite" to t(EntityType.ENDERMITE), + "Evoker" to t(EntityType.EVOKER), + "Fox" to t(EntityType.FOX), + "Frog" to t(EntityType.FROG), + "Ghast" to t(EntityType.GHAST), + "Giant" to t(EntityType.GIANT), + "GlowSquid" to t(EntityType.GLOW_SQUID), + "Goat" to t(EntityType.GOAT), + "Guardian" to t(EntityType.GUARDIAN), + "Horse" to t(EntityType.HORSE), + "Husk" to t(EntityType.HUSK), + "Illusioner" to t(EntityType.ILLUSIONER), + "LLama" to t(EntityType.LLAMA), + "MagmaCube" to t(EntityType.MAGMA_CUBE), + "Mooshroom" to t(EntityType.MOOSHROOM), + "Mule" to t(EntityType.MULE), + "Ocelot" to t(EntityType.OCELOT), + "Panda" to t(EntityType.PANDA), + "Phantom" to t(EntityType.PHANTOM), + "Pig" to t(EntityType.PIG), + "Piglin" to t(EntityType.PIGLIN), + "PiglinBrute" to t(EntityType.PIGLIN_BRUTE), + "Pigman" to t(EntityType.ZOMBIFIED_PIGLIN), + "Pillager" to t(EntityType.PILLAGER), + "Player" to { makeGuiPlayer(fakeWorld) }, + "PolarBear" to t(EntityType.POLAR_BEAR), + "Pufferfish" to t(EntityType.PUFFERFISH), + "Rabbit" to t(EntityType.RABBIT), + "Salmom" to t(EntityType.SALMON), + "Sheep" to t(EntityType.SHEEP), + "Shulker" to t(EntityType.SHULKER), + "Silverfish" to t(EntityType.SILVERFISH), + "Skeleton" to t(EntityType.SKELETON), + "Slime" to t(EntityType.SLIME), + "Sniffer" to t(EntityType.SNIFFER), + "Snowman" to t(EntityType.SNOW_GOLEM), + "Spider" to t(EntityType.SPIDER), + "Squid" to t(EntityType.SQUID), + "Stray" to t(EntityType.STRAY), + "Strider" to t(EntityType.STRIDER), + "Tadpole" to t(EntityType.TADPOLE), + "TropicalFish" to t(EntityType.TROPICAL_FISH), + "Turtle" to t(EntityType.TURTLE), + "Vex" to t(EntityType.VEX), + "Villager" to t(EntityType.VILLAGER), + "Vindicator" to t(EntityType.VINDICATOR), + "Warden" to t(EntityType.WARDEN), + "Witch" to t(EntityType.WITCH), + "Wither" to t(EntityType.WITHER), + "WitherSkeleton" to t(EntityType.WITHER_SKELETON), + "Wolf" to t(EntityType.WOLF), + "Zoglin" to t(EntityType.ZOGLIN), + "Zombie" to t(EntityType.ZOMBIE), + "ZombieVillager" to t(EntityType.ZOMBIE_VILLAGER) + ) + val entityModifiers: Map = 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, + ) + + fun applyModifiers(entityId: String, modifiers: List): LivingEntity? { + val entityType = ErrorUtil.notNullOr(entityIds[entityId], "Could not create entity with id $entityId") { + return null + } + var entity = ErrorUtil.catch("") { entityType() }.or { return null } + for (modifierJson in modifiers) { + val modifier = ErrorUtil.notNullOr( + modifierJson["type"]?.asString?.let(entityModifiers::get), + "Could not create entity with id $entityId. Failed to apply 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 = ErrorUtil.notNullOr(info["entity"]?.asString, "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, + // TODO: Add width, height properties here + width: Double, + height: Double, + mouseX: Double, + mouseY: Double, + entityScale: Double = (height - 10.0) / 2.0 + ) { + var bottomOffset = 0.0 + 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 + width).toInt(), + (posY + height).toInt(), + minOf(2F / maxSize, 1F) * entityScale, + -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: Double, + bottomOffset: Double, + mouseX: Double, + mouseY: Double, + entity: LivingEntity + ) { + context.enableScissorWithTranslation(x1.toFloat(), y1.toFloat(), x2.toFloat(), y2.toFloat()) + val centerX = (x1 + x2) / 2f + val centerY = (y1 + y2) / 2f + val hw = (x2 - x1) / 2 + val hh = (y2 - y1) / 2 + val targetYaw = atan(((centerX - mouseX) / hw)).toFloat() + val targetPitch = atan(((centerY - mouseY) / hh)).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.lastHeadYaw + 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.lastHeadYaw = entity.yaw + val vector3f = Vector3f(0.0f, (entity.height / 2.0f + bottomOffset).toFloat(), 0.0f) + InventoryScreen.drawEntity( + context, + centerX, + centerY, + size.toFloat(), + vector3f, + rotateToFaceTheFront, + rotateToFaceTheCamera, + entity + ) + entity.bodyYaw = oldBodyYaw + entity.yaw = oldYaw + entity.pitch = oldPitch + entity.lastHeadYaw = oldPrevHeadYaw + entity.headYaw = oldHeadYaw + context.disableScissor() + } + + +} diff --git a/src/main/kotlin/gui/entity/GuiPlayer.kt b/src/main/kotlin/gui/entity/GuiPlayer.kt new file mode 100644 index 0000000..f728dbf --- /dev/null +++ b/src/main/kotlin/gui/entity/GuiPlayer.kt @@ -0,0 +1,62 @@ +package moe.nea.firmament.gui.entity + +import com.mojang.authlib.GameProfile +import java.util.UUID +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.util.math.Vec3d +import net.minecraft.world.World + +/** + * @see moe.nea.firmament.init.EarlyRiser + */ +fun makeGuiPlayer(world: World): GuiPlayer { + val constructor = GuiPlayer::class.java.getDeclaredConstructor( + World::class.java, + BlockPos::class.java, + Float::class.javaPrimitiveType, + GameProfile::class.java + ) + val player = constructor.newInstance(world, BlockPos.ORIGIN, 0F, GameProfile(UUID.randomUUID(), "Linnea")) + player.postInit() + return player +} + +class GuiPlayer(world: ClientWorld?, profile: GameProfile?) : AbstractClientPlayerEntity(world, profile) { + override fun isSpectator(): Boolean { + return false + } + + fun postInit() { + skinTexture = DefaultSkinHelper.getSkinTextures(this.getUuid()).texture + lastVelocity = Vec3d.ZERO + model = Model.WIDE + } + + override fun isCreative(): Boolean { + return false + } + + override fun shouldRenderName(): Boolean { + return false + } + + lateinit var skinTexture: Identifier + 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/gui/entity/ModifyAge.kt b/src/main/kotlin/gui/entity/ModifyAge.kt new file mode 100644 index 0000000..a65c368 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyAge.kt @@ -0,0 +1,25 @@ + +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/gui/entity/ModifyCharged.kt b/src/main/kotlin/gui/entity/ModifyCharged.kt new file mode 100644 index 0000000..d22f6e3 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyCharged.kt @@ -0,0 +1,14 @@ + +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/gui/entity/ModifyEquipment.kt b/src/main/kotlin/gui/entity/ModifyEquipment.kt new file mode 100644 index 0000000..2ef5007 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyEquipment.kt @@ -0,0 +1,55 @@ +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.Item +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.mc.setEncodedSkullOwner +import moe.nea.firmament.util.mc.arbitraryUUID + +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 + } + + @OptIn(ExpensiveItemCacheApi::class) + 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(arbitraryUUID, 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))) + return stack + } +} diff --git a/src/main/kotlin/gui/entity/ModifyHorse.kt b/src/main/kotlin/gui/entity/ModifyHorse.kt new file mode 100644 index 0000000..7c8baa7 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyHorse.kt @@ -0,0 +1,59 @@ +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.EquipmentSlot +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.SpawnReason +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, SpawnReason.LOAD)!! + "zombie" -> EntityType.ZOMBIE_HORSE.create(fakeWorld, SpawnReason.LOAD)!! + "mule" -> EntityType.MULE.create(fakeWorld, SpawnReason.LOAD)!! + "donkey" -> EntityType.DONKEY.create(fakeWorld, SpawnReason.LOAD)!! + "horse" -> EntityType.HORSE.create(fakeWorld, SpawnReason.LOAD)!! + 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) { + this.equipStack(EquipmentSlot.SADDLE, + if (shouldBeSaddled) ItemStack(Items.SADDLE) + else ItemStack.EMPTY) +} + +fun AbstractHorseEntity.setHorseArmor(itemStack: ItemStack) { + this.equipBodyArmor(itemStack) +} diff --git a/src/main/kotlin/gui/entity/ModifyInvisible.kt b/src/main/kotlin/gui/entity/ModifyInvisible.kt new file mode 100644 index 0000000..8d36991 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyInvisible.kt @@ -0,0 +1,13 @@ + +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/gui/entity/ModifyName.kt b/src/main/kotlin/gui/entity/ModifyName.kt new file mode 100644 index 0000000..a03da96 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyName.kt @@ -0,0 +1,14 @@ + +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/gui/entity/ModifyPlayerSkin.kt b/src/main/kotlin/gui/entity/ModifyPlayerSkin.kt new file mode 100644 index 0000000..28f0070 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyPlayerSkin.kt @@ -0,0 +1,47 @@ + +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/gui/entity/ModifyRiding.kt b/src/main/kotlin/gui/entity/ModifyRiding.kt new file mode 100644 index 0000000..5c4c78d --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyRiding.kt @@ -0,0 +1,15 @@ + +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/gui/entity/ModifyWither.kt b/src/main/kotlin/gui/entity/ModifyWither.kt new file mode 100644 index 0000000..6083d88 --- /dev/null +++ b/src/main/kotlin/gui/entity/ModifyWither.kt @@ -0,0 +1,20 @@ + +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/gui/hud/MoulConfigHud.kt b/src/main/kotlin/gui/hud/MoulConfigHud.kt new file mode 100644 index 0000000..e99b069 --- /dev/null +++ b/src/main/kotlin/gui/hud/MoulConfigHud.kt @@ -0,0 +1,66 @@ + +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("MoulConfigHud:render") { + 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("MoulConfigHud:finalizeResourceManager") { + 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/jarvis/JarvisIntegration.kt b/src/main/kotlin/jarvis/JarvisIntegration.kt new file mode 100644 index 0000000..96f47f7 --- /dev/null +++ b/src/main/kotlin/jarvis/JarvisIntegration.kt @@ -0,0 +1,64 @@ + + +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 { + 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 { + return configs.flatMap { config -> + config.sortedOptions.map { + object : JarvisConfigOption { + override fun title(): Text { + return it.labelText + } + + override fun description(): List { + return emptyList() + } + + override fun jumpTo(parentScreen: Screen?): Screen { + return config.getConfigEditor(parentScreen) + } + } + } + } + } +} diff --git a/src/main/kotlin/keybindings/FirmamentKeyBindings.kt b/src/main/kotlin/keybindings/FirmamentKeyBindings.kt new file mode 100644 index 0000000..59b131a --- /dev/null +++ b/src/main/kotlin/keybindings/FirmamentKeyBindings.kt @@ -0,0 +1,25 @@ +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.ManagedOption +import moe.nea.firmament.util.TestUtil + +object FirmamentKeyBindings { + fun registerKeyBinding(name: String, config: ManagedOption) { + val vanillaKeyBinding = KeyBinding( + name, + InputUtil.Type.KEYSYM, + -1, + "firmament.key.category" + ) + if (!TestUtil.isInTest) { + KeyBindingHelper.registerKeyBinding(vanillaKeyBinding) + } + keyBindings[vanillaKeyBinding] = config + } + + val keyBindings = mutableMapOf>() + +} diff --git a/src/main/kotlin/keybindings/IKeyBinding.kt b/src/main/kotlin/keybindings/IKeyBinding.kt new file mode 100644 index 0000000..9d9b106 --- /dev/null +++ b/src/main/kotlin/keybindings/IKeyBinding.kt @@ -0,0 +1,50 @@ + + +package moe.nea.firmament.keybindings + +import net.minecraft.client.option.KeyBinding + +interface IKeyBinding { + fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean + fun matchesAtLeast(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.matchesAtLeast(keyCode, scanCode, modifiers) && (modifiers and wantedModifiers) == wantedModifiers + } + + override fun matchesAtLeast( + keyCode: Int, + scanCode: Int, + modifiers: Int + ): Boolean { + return old.matchesAtLeast(keyCode, scanCode, modifiers) && (modifiers.inv() and wantedModifiers) == 0 + } + } + } + + companion object { + fun minecraft(keyBinding: KeyBinding) = object : IKeyBinding { + override fun matches(keyCode: Int, scanCode: Int, modifiers: Int) = + keyBinding.matchesKey(keyCode, scanCode) + + override fun matchesAtLeast( + keyCode: Int, + scanCode: Int, + modifiers: Int + ): Boolean = + keyBinding.matchesKey(keyCode, scanCode) + } + + fun ofKeyCode(wantedKeyCode: Int) = object : IKeyBinding { + override fun matches(keyCode: Int, scanCode: Int, modifiers: Int): Boolean = keyCode == wantedKeyCode && modifiers == 0 + override fun matchesAtLeast( + keyCode: Int, + scanCode: Int, + modifiers: Int + ): Boolean = keyCode == wantedKeyCode + } + } +} diff --git a/src/main/kotlin/keybindings/SavedKeyBinding.kt b/src/main/kotlin/keybindings/SavedKeyBinding.kt new file mode 100644 index 0000000..01baa8f --- /dev/null +++ b/src/main/kotlin/keybindings/SavedKeyBinding.kt @@ -0,0 +1,125 @@ +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 +import moe.nea.firmament.util.mc.InitLevel + +// TODO: add support for mouse keybindings +@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) : 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 { + 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() = shiftKeys.any { InputUtil.isKeyPressed(h, it) } + + fun unbound(): SavedKeyBinding = + SavedKeyBinding(GLFW.GLFW_KEY_UNKNOWN) + + val controlKeys = if (MinecraftClient.IS_SYSTEM_MAC) { + listOf(GLFW.GLFW_KEY_LEFT_SUPER, GLFW.GLFW_KEY_RIGHT_SUPER) + } else { + listOf(GLFW.GLFW_KEY_LEFT_CONTROL, GLFW.GLFW_KEY_RIGHT_CONTROL) + } + val shiftKeys = listOf(GLFW.GLFW_KEY_LEFT_SHIFT, GLFW.GLFW_KEY_RIGHT_SHIFT) + + val altKeys = listOf(GLFW.GLFW_KEY_LEFT_ALT, GLFW.GLFW_KEY_RIGHT_ALT) + } + + fun isPressed(atLeast: Boolean = false): Boolean { + if (!isBound) return false + val h = MC.window.handle + if (!InputUtil.isKeyPressed(h, keyCode)) return false + + // These are modifiers, so if the searched keyCode is a modifier key, then that key does not count as the modifier + val ctrl = keyCode !in controlKeys && controlKeys.any { InputUtil.isKeyPressed(h, it) } + val shift = keyCode !in shiftKeys && isShiftDown() + val alt = keyCode !in altKeys && altKeys.any { InputUtil.isKeyPressed(h, it) } + if (atLeast) + return (ctrl >= this.ctrl) && + (alt >= this.alt) && + (shift >= this.shift) + + return (ctrl == this.ctrl) && + (alt == this.alt) && + (shift == this.shift) + } + + override fun matchesAtLeast(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + if (this.keyCode == GLFW.GLFW_KEY_UNKNOWN) return false + val (shift, ctrl, alt) = getMods(modifiers) + return keyCode == this.keyCode && this.shift <= shift && this.ctrl <= ctrl && this.alt <= alt + } + + 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) + } + + override fun toString(): String { + return format().string + } + + fun format(): Text { + val stroke = Text.literal("") + if (ctrl) { + stroke.append("CTRL + ") + } + if (alt) { + stroke.append("ALT + ") + } + if (shift) { + stroke.append("SHIFT + ") // TODO: translations? + } + if (InitLevel.isAtLeast(InitLevel.RENDER_INIT)) { + stroke.append(InputUtil.Type.KEYSYM.createFromCode(keyCode).localizedText) + } else { + stroke.append(keyCode.toString()) + } + return stroke + } + +} diff --git a/src/main/kotlin/repo/BetterRepoRecipeCache.kt b/src/main/kotlin/repo/BetterRepoRecipeCache.kt new file mode 100644 index 0000000..6d18223 --- /dev/null +++ b/src/main/kotlin/repo/BetterRepoRecipeCache.kt @@ -0,0 +1,31 @@ +package moe.nea.firmament.repo + +import io.github.moulberry.repo.IReloadable +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEUNpcShopRecipe +import io.github.moulberry.repo.data.NEURecipe +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.skyblockId + +class BetterRepoRecipeCache(vararg val extraProviders: ExtraRecipeProvider) : IReloadable { + var usages: Map> = mapOf() + var recipes: Map> = mapOf() + + override fun reload(repository: NEURepository) { + val usages = mutableMapOf>() + val recipes = mutableMapOf>() + val baseRecipes = repository.items.items.values + .asSequence() + .flatMap { it.recipes } + (baseRecipes + extraProviders.flatMap { it.provideExtraRecipes() }) + .forEach { recipe -> + if (recipe is NEUNpcShopRecipe) { + usages.getOrPut(recipe.isSoldBy.skyblockId, ::mutableSetOf).add(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/repo/EssenceRecipeProvider.kt b/src/main/kotlin/repo/EssenceRecipeProvider.kt new file mode 100644 index 0000000..38559d5 --- /dev/null +++ b/src/main/kotlin/repo/EssenceRecipeProvider.kt @@ -0,0 +1,51 @@ +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, ExtraRecipeProvider { + data class EssenceUpgradeRecipe( + val itemId: SkyblockId, + val starCountAfter: Int, + val essenceCost: Int, + val essenceType: String, // TODO: replace with proper type + val extraItems: List, + ) : NEURecipe { + val essenceIngredient = NEUIngredient.fromString("${essenceType}:$essenceCost") + val allUpgradeComponents = listOf(essenceIngredient) + extraItems + + override fun getAllInputs(): Collection { + return listOf(NEUIngredient.fromString(itemId.neuItem + ":1")) + allUpgradeComponents + } + + override fun getAllOutputs(): Collection { + return listOf(NEUIngredient.fromString(itemId.neuItem + ":1")) + } + } + + var recipes = listOf() + private set + + override fun provideExtraRecipes(): Iterable = recipes + + override fun reload(repository: NEURepository) { + val recipes = mutableListOf() + 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/repo/ExpLadder.kt b/src/main/kotlin/repo/ExpLadder.kt new file mode 100644 index 0000000..25a74de --- /dev/null +++ b/src/main/kotlin/repo/ExpLadder.kt @@ -0,0 +1,95 @@ + + +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 + val percentageToMaxLevel: Float = expTotal / expRequiredForMaxLevel + } + + data class ExpLadder( + val individualLevelCost: List, + ) { + 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() { + 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/repo/ExpensiveItemCacheApi.kt b/src/main/kotlin/repo/ExpensiveItemCacheApi.kt new file mode 100644 index 0000000..eef95a6 --- /dev/null +++ b/src/main/kotlin/repo/ExpensiveItemCacheApi.kt @@ -0,0 +1,8 @@ +package moe.nea.firmament.repo + +/** + * Marker for functions that could potentially invoke DFU. Please do not call on a lot of objects at once, or try to make sure the item is cached and fall back to a more gentle function call using [SBItemStack.isWarm] and similar functions. + */ +@RequiresOptIn +@Retention(AnnotationRetention.BINARY) +annotation class ExpensiveItemCacheApi diff --git a/src/main/kotlin/repo/ExtraRecipeProvider.kt b/src/main/kotlin/repo/ExtraRecipeProvider.kt new file mode 100644 index 0000000..9d3b5a0 --- /dev/null +++ b/src/main/kotlin/repo/ExtraRecipeProvider.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.repo + +import io.github.moulberry.repo.data.NEURecipe + +interface ExtraRecipeProvider { + fun provideExtraRecipes(): Iterable +} diff --git a/src/main/kotlin/repo/HypixelStaticData.kt b/src/main/kotlin/repo/HypixelStaticData.kt new file mode 100644 index 0000000..b0ada77 --- /dev/null +++ b/src/main/kotlin/repo/HypixelStaticData.kt @@ -0,0 +1,122 @@ +package moe.nea.firmament.repo + +import io.ktor.client.call.body +import io.ktor.client.request.get +import org.apache.logging.log4j.LogManager +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +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.util.SkyblockId + +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 = mapOf() + private set + var avg1dlowestBin: Map = mapOf() + private set + var avg3dlowestBin: Map = mapOf() + private set + var avg7dlowestBin: Map = mapOf() + private set + var bazaarData: Map = mapOf() + private set + var collectionData: Map = 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 = mapOf(), + ) + + + fun getPriceOfItem(item: SkyblockId): Double? = bazaarData[SkyblockId.BazaarStock.fromSkyBlockId(item)]?.quickStatus?.buyPrice ?: lowestBin[item] + + fun hasBazaarStock(item: SkyblockId.BazaarStock): Boolean { + return item in bazaarData + } + + fun hasAuctionHouseOffers(item: SkyblockId): Boolean { + return (item in lowestBin) // TODO: || (item in biddableAuctionPrices) + } + + fun spawnDataCollectionLoop() { + Firmament.coroutineScope.launch { + logger.info("Updating collection data") + updateCollectionData() + } + Firmament.coroutineScope.launch { + while (true) { + logger.info("Updating NEU prices") + updatePrices() + delay(10.minutes) + } + } + } + + 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>() + avg1dlowestBin = Firmament.httpClient.get("$moulberryBaseUrl/auction_averages_lbin/1day.json") + .body>() + avg3dlowestBin = Firmament.httpClient.get("$moulberryBaseUrl/auction_averages_lbin/3day.json") + .body>() + avg7dlowestBin = Firmament.httpClient.get("$moulberryBaseUrl/auction_averages_lbin/7day.json") + .body>() + } + + private suspend fun fetchBazaarPrices() { + val response = Firmament.httpClient.get("$hypixelApiBaseUrl/skyblock/bazaar").body() + if (!response.success) { + logger.warn("Retrieved unsuccessful bazaar data") + } + bazaarData = response.products + } + + private suspend fun updateCollectionData() { + val response = + Firmament.httpClient.get("$hypixelApiBaseUrl/resources/skyblock/collections").body() + 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/repo/ItemCache.kt b/src/main/kotlin/repo/ItemCache.kt new file mode 100644 index 0000000..14decd8 --- /dev/null +++ b/src/main/kotlin/repo/ItemCache.kt @@ -0,0 +1,312 @@ +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 java.text.NumberFormat +import java.util.UUID +import java.util.concurrent.ConcurrentHashMap +import org.apache.logging.log4j.LogManager +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import kotlin.io.path.readText +import kotlin.jvm.optionals.getOrNull +import net.minecraft.SharedConstants +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.nbt.NbtString +import net.minecraft.nbt.StringNbtReader +import net.minecraft.text.MutableText +import net.minecraft.text.Style +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.features.debug.ExportedTestConstantMeta +import moe.nea.firmament.repo.RepoManager.initialize +import moe.nea.firmament.util.LegacyFormattingCode +import moe.nea.firmament.util.LegacyTagParser +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MinecraftDispatcher +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.TestUtil +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.mc.FirmamentDataComponentTypes +import moe.nea.firmament.util.mc.appendLore +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.mc.modifyLore +import moe.nea.firmament.util.mc.setCustomName +import moe.nea.firmament.util.mc.setSkullOwner +import moe.nea.firmament.util.skyblockId +import moe.nea.firmament.util.transformEachRecursively + +object ItemCache : IReloadable { + private val cache: MutableMap = 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()) + } + + @ExpensiveItemCacheApi + private fun NbtCompound.transformFrom10809ToModern() = convert189ToModern(this@transformFrom10809ToModern) + val currentSaveVersion = SharedConstants.getGameVersion().saveVersion.id + + @ExpensiveItemCacheApi + fun convert189ToModern(nbtComponent: NbtCompound): NbtCompound? = + try { + df.update( + TypeReferences.ITEM_STACK, + Dynamic(NbtOps.INSTANCE, nbtComponent), + -1, + currentSaveVersion + ).value as NbtCompound + } catch (e: Exception) { + isFlawless = false + logger.error("Could not data fix up $this", e) + null + } + + val ItemStack.isBroken + get() = get(FirmamentDataComponentTypes.IS_BROKEN) ?: false + + fun ItemStack.withFallback(fallback: ItemStack?): ItemStack { + if (isBroken && fallback != null) return fallback + return this + } + + 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) + ) + ) + ) + set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(NbtCompound().apply { + put("ID", NbtString.of(neuItem?.skyblockItemId ?: idHint?.neuItem ?: "null")) + })) + set(FirmamentDataComponentTypes.IS_BROKEN, true) + } + } + + fun un189Lore(lore: String): MutableText { + val base = Text.literal("") + base.setStyle(Style.EMPTY.withItalic(false)) + var lastColorCode = Style.EMPTY + var readOffset = 0 + while (readOffset < lore.length) { + var nextCode = lore.indexOf('§', readOffset) + if (nextCode < 0) { + nextCode = lore.length + } + val text = lore.substring(readOffset, nextCode) + if (text.isNotEmpty()) { + base.append(Text.literal(text).setStyle(lastColorCode)) + } + readOffset = nextCode + 2 + if (nextCode + 1 < lore.length) { + val colorCode = lore[nextCode + 1] + val formatting = LegacyFormattingCode.byCode[colorCode.lowercaseChar()] ?: LegacyFormattingCode.RESET + val modernFormatting = formatting.modern + if (modernFormatting.isColor) { + lastColorCode = Style.EMPTY.withColor(modernFormatting) + } else { + lastColorCode = lastColorCode.withFormatting(modernFormatting) + } + } + } + return base + } + + fun tryFindFromModernFormat(skyblockId: SkyblockId): NbtCompound? { + val overlayFile = + RepoManager.overlayData.getMostModernReadableOverlay(skyblockId, currentSaveVersion) ?: return null + val overlay = StringNbtReader.readCompound(overlayFile.path.readText()) + val result = ExportedTestConstantMeta.SOURCE_CODEC.decode( + NbtOps.INSTANCE, overlay + ).result().getOrNull() ?: return null + val meta = result.first + return df.update( + TypeReferences.ITEM_STACK, + Dynamic(NbtOps.INSTANCE, result.second), + meta.dataVersion, + currentSaveVersion + ).value as NbtCompound + } + + @ExpensiveItemCacheApi + private fun NEUItem.asItemStackNow(): ItemStack { + + try { + var modernItemTag = tryFindFromModernFormat(this.skyblockId) + val oldItemTag = get10809CompoundTag() + var usedOldNbt = false + if (modernItemTag == null) { + usedOldNbt = true + modernItemTag = oldItemTag.transformFrom10809ToModern() + ?: return brokenItemStack(this) + } + val itemInstance = + ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this) + if (usedOldNbt) { + val tag = oldItemTag.getCompound("tag") + val extraAttributes = tag.flatMap { it.getCompound("ExtraAttributes") } + .getOrNull() + if (extraAttributes != null) + itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes)) + val itemModel = tag.flatMap { it.getString("ItemModel") }.getOrNull() + if (itemModel != null) + itemInstance.set(DataComponentTypes.ITEM_MODEL, Identifier.of(itemModel)) + } + itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) } + itemInstance.displayNameAccordingToNbt = un189Lore(displayName) + return itemInstance + } catch (e: Exception) { + e.printStackTrace() + return brokenItemStack(this) + } + } + + fun hasCacheFor(skyblockId: SkyblockId): Boolean { + return skyblockId.neuItem in cache + } + + @ExpensiveItemCacheApi + fun NEUItem?.asItemStack(idHint: SkyblockId? = null, loreReplacements: Map? = 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) { + modifyLore { lore -> + lore.map { + it.applyLoreReplacements(loreReplacements) + } + } + } + + fun Text.applyLoreReplacements(loreReplacements: Map): Text { + return this.transformEachRecursively { + var string = it.directLiteralStringContent ?: return@transformEachRecursively it + loreReplacements.forEach { (find, replace) -> + string = string.replace("{$find}", replace) + } + Text.literal(string).setStyle(it.style) + } + } + + var itemRecacheScope: CoroutineScope? = null + + private var recacheSoonSubmitted = mutableSetOf() + + @OptIn(ExpensiveItemCacheApi::class) + fun recacheSoon(neuItem: NEUItem) { + itemRecacheScope?.launch { + if (!withContext(MinecraftDispatcher) { + recacheSoonSubmitted.add(neuItem.skyblockId) + }) { + return@launch + } + neuItem.asItemStack() + } + } + + @OptIn(ExpensiveItemCacheApi::class) + override fun reload(repository: NEURepository) { + val j = itemRecacheScope + j?.cancel("New reload invoked") + cache.clear() + isFlawless = true + if (TestUtil.isInTest) return + val newScope = + CoroutineScope( + Firmament.coroutineScope.coroutineContext + + SupervisorJob(Firmament.globalJob) + + Dispatchers.Default.limitedParallelism( + (Runtime.getRuntime().availableProcessors() / 4).coerceAtLeast(1) + ) + ) + val items = repository.items?.items + newScope.launch { + val items = items ?: return@launch + items.values.chunked(500).map { chunk -> + async { + chunk.forEach { + it.asItemStack() // Rebuild cache + } + } + }.awaitAll() + } + itemRecacheScope = newScope + } + + 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 + } + + init { + if (TestUtil.isInTest) { + initialize() + } + } + +} + + +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/repo/ItemNameLookup.kt b/src/main/kotlin/repo/ItemNameLookup.kt new file mode 100644 index 0000000..1250730 --- /dev/null +++ b/src/main/kotlin/repo/ItemNameLookup.kt @@ -0,0 +1,101 @@ +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 { + return name.removeColorCodes().split(" ").filterTo(mutableSetOf()) { it.isNotBlank() } + } + + var nameMap: NavigableMap> = TreeMap() + + override fun reload(repository: NEURepository) { + val nameMap = TreeMap>() + 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 { + val names = mutableSetOf() + 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 { + val candidates = mutableSetOf() + 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, + 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 + } + + init { + RepoManager.initialize() + } + +} diff --git a/src/main/kotlin/repo/MiningRepoData.kt b/src/main/kotlin/repo/MiningRepoData.kt new file mode 100644 index 0000000..e96a241 --- /dev/null +++ b/src/main/kotlin/repo/MiningRepoData.kt @@ -0,0 +1,133 @@ +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.Collections +import java.util.NavigableMap +import java.util.TreeMap +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlinx.serialization.serializer +import kotlin.jvm.optionals.getOrNull +import kotlin.streams.asSequence +import net.minecraft.block.Block +import net.minecraft.item.BlockItem +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtCompound +import net.minecraft.text.Text +import moe.nea.firmament.repo.ReforgeStore.kJson +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.mc.FirmamentDataComponentTypes +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.skyblockId + +class MiningRepoData : IReloadable { + var customMiningAreas: Map = mapOf() + private set + var customMiningBlocks: List = listOf() + private set + var toolsByBreakingPower: NavigableMap = Collections.emptyNavigableMap() + private set + + + data class BreakingPowerKey( + val breakingPower: Int, + val itemId: SkyblockId? = null + ) { + companion object { + val COMPARATOR: Comparator = + Comparator + .comparingInt { it.breakingPower } + .thenComparing(Comparator.comparing( + { it.itemId }, + nullsFirst(Comparator.comparing { "PICK" in it.neuItem || "BING" in it.neuItem }.thenComparing(Comparator.naturalOrder())))) + } + } + + override fun reload(repo: NEURepository) { + customMiningAreas = repo.file("mining/custom_mining_areas.json") + ?.kJson(serializer()) ?: mapOf() + customMiningBlocks = repo.tree("mining/blocks") + .asSequence() + .filter { it.path.endsWith(".json") } + .map { it.kJson(serializer()) } + .toList() + toolsByBreakingPower = Collections.unmodifiableNavigableMap( + repo.items.items + .values + .asSequence() + .map { SBItemStack(it.skyblockId) } + .filter { it.breakingPower > 0 } + .associateTo(TreeMap(BreakingPowerKey.COMPARATOR)) { + BreakingPowerKey(it.breakingPower, it.skyblockId) to it + }) + } + + fun getToolsThatCanBreak(breakingPower: Int): Collection { + return toolsByBreakingPower.tailMap(BreakingPowerKey(breakingPower, null), true).values + } + + @Serializable + data class CustomMiningBlock( + val breakingPower: Int = 0, + val blockStrength: Int = 0, + val name: String? = null, + val baseDrop: SkyblockId? = null, + val blocks189: List = emptyList() + ) { + @Transient + val dropItem = baseDrop?.let(::SBItemStack) + @OptIn(ExpensiveItemCacheApi::class) + private val labeledStack by lazy { + dropItem?.asCopiedItemStack()?.also(::markItemStack) + } + + private fun markItemStack(itemStack: ItemStack) { + itemStack.set(FirmamentDataComponentTypes.CUSTOM_MINING_BLOCK_DATA, this) + if (name != null) + itemStack.displayNameAccordingToNbt = Text.literal(name) + } + + fun getDisplayItem(block: Block): ItemStack { + return labeledStack ?: ItemStack(block).also(::markItemStack) + } + } + + @Serializable + data class Block189( + val itemId: String, + val damage: Short = 0, + val onlyIn: List? = null, + ) { + @Transient + val block = convertToModernBlock() + + val isCurrentlyActive: Boolean + get() = isActiveIn(SBData.skyblockLocation ?: SkyBlockIsland.NIL) + + fun isActiveIn(location: SkyBlockIsland) = onlyIn == null || location in onlyIn + + @OptIn(ExpensiveItemCacheApi::class) + private fun convertToModernBlock(): Block? { + // TODO: this should be in a shared util, really + val newCompound = ItemCache.convert189ToModern(NbtCompound().apply { + putString("id", itemId) + putShort("Damage", damage) + }) ?: return null + val itemStack = ItemStack.fromNbt(MC.defaultRegistries, newCompound).getOrNull() ?: return null + val blockItem = itemStack.item as? BlockItem ?: return null + return blockItem.block + } + } + + @Serializable + data class CustomMiningArea( + val isSpecialMining: Boolean = true + ) + + +} diff --git a/src/main/kotlin/repo/ModernOverlaysData.kt b/src/main/kotlin/repo/ModernOverlaysData.kt new file mode 100644 index 0000000..543b800 --- /dev/null +++ b/src/main/kotlin/repo/ModernOverlaysData.kt @@ -0,0 +1,41 @@ +package moe.nea.firmament.repo + +import io.github.moulberry.repo.IReloadable +import io.github.moulberry.repo.NEURepository +import java.nio.file.Path +import kotlin.io.path.extension +import kotlin.io.path.isDirectory +import kotlin.io.path.listDirectoryEntries +import kotlin.io.path.nameWithoutExtension +import moe.nea.firmament.util.SkyblockId + +// TODO: move this over to the repo parser +class ModernOverlaysData : IReloadable { + data class OverlayFile( + val version: Int, + val path: Path, + ) + + var overlays: Map> = mapOf() + override fun reload(repo: NEURepository) { + val items = mutableMapOf>() + repo.baseFolder.resolve("itemsOverlay") + .takeIf { it.isDirectory() } + ?.listDirectoryEntries() + ?.forEach { versionFolder -> + val version = versionFolder.fileName.toString().toIntOrNull() ?: return@forEach + versionFolder.listDirectoryEntries() + .forEach { item -> + if (item.extension != "snbt") return@forEach + val itemId = item.nameWithoutExtension + items.getOrPut(SkyblockId(itemId)) { mutableListOf() }.add(OverlayFile(version, item)) + } + } + this.overlays = items + } + + fun getOverlayFiles(skyblockId: SkyblockId) = overlays[skyblockId] ?: listOf() + fun getMostModernReadableOverlay(skyblockId: SkyblockId, version: Int) = getOverlayFiles(skyblockId) + .filter { it.version <= version } + .maxByOrNull { it.version } +} diff --git a/src/main/kotlin/repo/PetData.kt b/src/main/kotlin/repo/PetData.kt new file mode 100644 index 0000000..2ce3402 --- /dev/null +++ b/src/main/kotlin/repo/PetData.kt @@ -0,0 +1,24 @@ +package moe.nea.firmament.repo + +import io.github.moulberry.repo.data.Rarity +import moe.nea.firmament.util.HypixelPetInfo + +// 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) } +} diff --git a/src/main/kotlin/repo/Reforge.kt b/src/main/kotlin/repo/Reforge.kt new file mode 100644 index 0000000..dc0d93d --- /dev/null +++ b/src/main/kotlin/repo/Reforge.kt @@ -0,0 +1,160 @@ +package moe.nea.firmament.repo + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.MapSerializer +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 +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.serializer +import net.minecraft.item.Item +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryKeys +import net.minecraft.util.Identifier +import moe.nea.firmament.util.ReforgeId +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.skyblock.ItemType +import moe.nea.firmament.util.skyblock.Rarity + +@Serializable +data class Reforge( + val reforgeName: String, + @SerialName("internalName") val reforgeStone: SkyblockId? = null, + val nbtModifier: ReforgeId? = null, + val requiredRarities: List? = null, + val itemTypes: @Serializable(with = ReforgeEligibilityFilter.ItemTypesSerializer::class) List? = null, + val allowOn: List? = null, + val reforgeCosts: RarityMapped? = null, + val reforgeAbility: RarityMapped? = null, + val reforgeStats: RarityMapped>? = null, +) { + val eligibleItems get() = allowOn ?: itemTypes ?: listOf() + + val statUniverse: Set = Rarity.entries.flatMapTo(mutableSetOf()) { + reforgeStats?.get(it)?.keys ?: emptySet() + } + + @Serializable(with = ReforgeEligibilityFilter.Serializer::class) + sealed interface ReforgeEligibilityFilter { + object ItemTypesSerializer : KSerializer> { + override val descriptor: SerialDescriptor + get() = JsonElement.serializer().descriptor + + override fun deserialize(decoder: Decoder): List { + decoder as JsonDecoder + val jsonElement = decoder.decodeJsonElement() + if (jsonElement is JsonPrimitive && jsonElement.isString) { + return jsonElement.content.split("/").map { AllowsItemType(ItemType.ofName(it)) } + } + if (jsonElement is JsonArray) { + return decoder.json.decodeFromJsonElement(serializer>(), jsonElement) + } + jsonElement as JsonObject + val filters = mutableListOf() + jsonElement["internalName"]?.let { + decoder.json.decodeFromJsonElement(serializer>(), it).forEach { + filters.add(AllowsInternalName(it)) + } + } + jsonElement["itemId"]?.let { + decoder.json.decodeFromJsonElement(serializer>(), it).forEach { + val ident = Identifier.tryParse(it) + if (ident != null) + filters.add(AllowsVanillaItemType(RegistryKey.of(RegistryKeys.ITEM, ident))) + } + } + return filters + } + + override fun serialize(encoder: Encoder, value: List) { + TODO("Not yet implemented") + } + } + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = serializer().descriptor + + override fun deserialize(decoder: Decoder): ReforgeEligibilityFilter { + val jsonObject = serializer().deserialize(decoder) + jsonObject["internalName"]?.let { + return AllowsInternalName(SkyblockId((it as JsonPrimitive).content)) + } + jsonObject["itemType"]?.let { + return AllowsItemType(ItemType.ofName((it as JsonPrimitive).content)) + } + jsonObject["minecraftId"]?.let { + return AllowsVanillaItemType(RegistryKey.of(RegistryKeys.ITEM, + Identifier.of((it as JsonPrimitive).content))) + } + error("Unknown item type") + } + + override fun serialize(encoder: Encoder, value: ReforgeEligibilityFilter) { + TODO("Not yet implemented") + } + + } + + data class AllowsItemType(val itemType: ItemType) : ReforgeEligibilityFilter + data class AllowsInternalName(val internalName: SkyblockId) : ReforgeEligibilityFilter + data class AllowsVanillaItemType(val minecraftId: RegistryKey) : ReforgeEligibilityFilter + } + + + val reforgeId get() = nbtModifier ?: ReforgeId(reforgeName.lowercase()) + + @Serializable(with = RarityMapped.Serializer::class) + sealed interface RarityMapped { + fun get(rarity: Rarity?): T? + + class Serializer( + val values: KSerializer + ) : KSerializer> { + override val descriptor: SerialDescriptor + get() = JsonElement.serializer().descriptor + + val indirect = MapSerializer(Rarity.serializer(), values) + override fun deserialize(decoder: Decoder): RarityMapped { + decoder as JsonDecoder + val element = decoder.decodeJsonElement() + if (element is JsonObject) { + return PerRarity(decoder.json.decodeFromJsonElement(indirect, element)) + } else { + return Direct(decoder.json.decodeFromJsonElement(values, element)) + } + } + + override fun serialize(encoder: Encoder, value: RarityMapped) { + when (value) { + is Direct -> + values.serialize(encoder, value.value) + + is PerRarity -> + indirect.serialize(encoder, value.values) + } + } + } + + @Serializable + data class Direct(val value: T) : RarityMapped { + override fun get(rarity: Rarity?): T { + return value + } + } + + @Serializable + data class PerRarity(val values: Map) : RarityMapped { + override fun get(rarity: Rarity?): T? { + return values[rarity] + } + } + } + +} diff --git a/src/main/kotlin/repo/ReforgeStore.kt b/src/main/kotlin/repo/ReforgeStore.kt new file mode 100644 index 0000000..4c01974 --- /dev/null +++ b/src/main/kotlin/repo/ReforgeStore.kt @@ -0,0 +1,125 @@ +package moe.nea.firmament.repo + +import com.google.gson.JsonElement +import com.mojang.serialization.JsonOps +import io.github.moulberry.repo.IReloadable +import io.github.moulberry.repo.NEURepoFile +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.NEURepositoryException +import io.github.moulberry.repo.data.NEURecipe +import kotlinx.serialization.KSerializer +import kotlinx.serialization.serializer +import net.minecraft.item.Item +import net.minecraft.registry.RegistryKey +import moe.nea.firmament.Firmament +import moe.nea.firmament.util.ReforgeId +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.json.KJsonOps +import moe.nea.firmament.util.skyblock.ItemType + +object ReforgeStore : ExtraRecipeProvider, IReloadable { + override fun provideExtraRecipes(): Iterable { + return emptyList() + } + + var byType: Map> = mapOf() + var byVanilla: Map, List> = mapOf() + var byInternalName: Map> = mapOf() + var modifierLut = mapOf() + var byReforgeStone = mapOf() + var allReforges = listOf() + + fun findEligibleForItem(itemType: ItemType): List { + return byType[itemType] ?: listOf() + } + + fun findEligibleForInternalName(internalName: SkyblockId): List { + return byInternalName[internalName] ?: listOf() + } + + //TODO: return byVanillla + override fun reload(repo: NEURepository) { + val basicReforges = + repo.file("constants/reforges.json") + ?.kJson(serializer>()) + ?.values ?: emptyList() + val advancedReforges = + repo.file("constants/reforgestones.json") + ?.kJson(serializer>()) + ?.values ?: emptyList() + val allReforges = (basicReforges + advancedReforges) + modifierLut = allReforges.associateBy { it.reforgeId } + byReforgeStone = allReforges.filter { it.reforgeStone != null } + .associateBy { it.reforgeStone!! } + val byType = mutableMapOf>() + val byVanilla = mutableMapOf, MutableList>() + val byInternalName = mutableMapOf>() + this.byType = byType + this.byVanilla = byVanilla + this.byInternalName = byInternalName + for (reforge in allReforges) { + for (eligibleItem in reforge.eligibleItems) { + when (eligibleItem) { + is Reforge.ReforgeEligibilityFilter.AllowsInternalName -> { + byInternalName.getOrPut(eligibleItem.internalName, ::mutableListOf).add(reforge) + } + + is Reforge.ReforgeEligibilityFilter.AllowsItemType -> { + val actualItemTypes = resolveItemType(eligibleItem.itemType) + for (itemType in actualItemTypes) { + byType.getOrPut(itemType, ::mutableListOf).add(reforge) + byType.getOrPut(itemType.dungeonVariant, ::mutableListOf).add(reforge) + } + } + + is Reforge.ReforgeEligibilityFilter.AllowsVanillaItemType -> { + byVanilla.getOrPut(eligibleItem.minecraftId, ::mutableListOf).add(reforge) + } + } + } + } + this.allReforges = allReforges + } + + fun resolveItemType(itemType: ItemType): List { + if (ItemType.SWORD == itemType) { + return listOf( + ItemType.SWORD, + ItemType.GAUNTLET, + ItemType.LONGSWORD,// TODO: check name + ItemType.FISHING_WEAPON,// TODO: check name + ) + } + if (itemType == ItemType.ofName("ARMOR")) { + return listOf( + ItemType.CHESTPLATE, + ItemType.LEGGINGS, + ItemType.HELMET, + ItemType.BOOTS, + ) + } + if (itemType == ItemType.EQUIPMENT) { + return listOf( + ItemType.CLOAK, + ItemType.BRACELET, + ItemType.NECKLACE, + ItemType.BELT, + ItemType.GLOVES, + ) + } + if (itemType == ItemType.ROD) { + return listOf(ItemType.FISHING_ROD, ItemType.FISHING_WEAPON) + } + return listOf(itemType) + } + + fun NEURepoFile.kJson(serializer: KSerializer): T { + val rawJson = json(JsonElement::class.java) + try { + val kJsonElement = JsonOps.INSTANCE.convertTo(KJsonOps.INSTANCE, rawJson) + return Firmament.json.decodeFromJsonElement(serializer, kJsonElement) + } catch (ex: Exception) { + throw NEURepositoryException(path, "Could not decode kotlin JSON element", ex) + } + } +} diff --git a/src/main/kotlin/repo/RepoDownloadManager.kt b/src/main/kotlin/repo/RepoDownloadManager.kt new file mode 100644 index 0000000..888248d --- /dev/null +++ b/src/main/kotlin/repo/RepoDownloadManager.kt @@ -0,0 +1,127 @@ +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.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(branchOverride: String?): 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/${branchOverride ?: RepoManager.Config.branch}") + if (response.status.value != 200) { + return null + } + return response.body().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, branch: String? = null): Boolean = + withContext(CoroutineName("Repo Update Check")) { + val latestSha = requestLatestGithubSha(branch) + 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/repo/RepoItemTypeCache.kt b/src/main/kotlin/repo/RepoItemTypeCache.kt new file mode 100644 index 0000000..414ec09 --- /dev/null +++ b/src/main/kotlin/repo/RepoItemTypeCache.kt @@ -0,0 +1,15 @@ +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 moe.nea.firmament.util.skyblock.ItemType + +object RepoItemTypeCache : IReloadable { + + var byItemType: Map> = mapOf() + + override fun reload(repository: NEURepository) { + byItemType = repository.items.items.values.groupBy { ItemType.fromEscapeCodeLore(it.lore.lastOrNull() ?: "") } + } +} diff --git a/src/main/kotlin/repo/RepoManager.kt b/src/main/kotlin/repo/RepoManager.kt new file mode 100644 index 0000000..c3d1c52 --- /dev/null +++ b/src/main/kotlin/repo/RepoManager.kt @@ -0,0 +1,211 @@ +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 java.nio.file.Path +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import net.minecraft.client.MinecraftClient +import net.minecraft.network.packet.s2c.play.SynchronizeRecipesS2CPacket +import net.minecraft.recipe.display.CuttingRecipeDisplay +import net.minecraft.util.StringIdentifiable +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.util.ErrorUtil +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MinecraftDispatcher +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.TestUtil +import moe.nea.firmament.util.tr + +object RepoManager { + object Config : ManagedConfig("repo", Category.META) { + 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 enableREI by toggle("enable-rei") { true } + val disableItemGroups by toggle("disable-item-groups") { true } + val reload by button("reload") { + save() + Firmament.coroutineScope.launch { + RepoManager.reload() + } + } + val redownload by button("redownload") { + save() + RepoManager.launchAsyncUpdate(true) + } + val alwaysSuperCraft by toggle("enable-super-craft") { true } + var warnForMissingItemListMod by toggle("warn-for-missing-item-list-mod") { true } + val perfectRenders by choice("perfect-renders") { PerfectRender.RENDER } + } + + enum class PerfectRender(val label: String) : StringIdentifiable { + NOTHING("nothing"), + RENDER("render"), + RENDER_AND_TEXT("text"), + ; + + fun rendersPerfectText() = this == RENDER_AND_TEXT + fun rendersPerfectVisuals() = this == RENDER || this == RENDER_AND_TEXT + + override fun asString(): String? = label + } + + val currentDownloadedSha by RepoDownloadManager::latestSavedVersionHash + + var recentlyFailedToUpdateItemList = false + + val essenceRecipeProvider = EssenceRecipeProvider() + val recipeCache = BetterRepoRecipeCache(essenceRecipeProvider, ReforgeStore) + val miningData = MiningRepoData() + val overlayData = ModernOverlaysData() + + fun makeNEURepository(path: Path): NEURepository { + return NEURepository.of(path).apply { + registerReloadListener(overlayData) + registerReloadListener(ItemCache) + registerReloadListener(RepoItemTypeCache) + registerReloadListener(ExpLadders) + registerReloadListener(ItemNameLookup) + registerReloadListener(ReforgeStore) + registerReloadListener(essenceRecipeProvider) + registerReloadListener(recipeCache) + registerReloadListener(miningData) + ReloadRegistrationEvent.publish(ReloadRegistrationEvent(this)) + registerReloadListener { + if (TestUtil.isInTest) return@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 + } + } + } + } + } + + lateinit var neuRepo: NEURepository + private set + + fun getAllRecipes() = neuRepo.items.items.values.asSequence().flatMap { it.recipes } + + fun getRecipesFor(skyblockId: SkyblockId): Set = recipeCache.recipes[skyblockId] ?: setOf() + fun getUsagesFor(skyblockId: SkyblockId): Set = recipeCache.usages[skyblockId] ?: setOf() + + private fun trySendClientboundUpdateRecipesPacket(): Boolean { + return MinecraftClient.getInstance().world != null && MinecraftClient.getInstance().networkHandler?.onSynchronizeRecipes( + SynchronizeRecipesS2CPacket(mutableMapOf(), CuttingRecipeDisplay.Grouping.empty()) + ) != 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 downloadOverridenBranch(branch: String) { + Firmament.coroutineScope.launch { + RepoDownloadManager.downloadUpdate(true, branch) + reload() + } + } + + fun launchAsyncUpdate(force: Boolean = false) { + Firmament.coroutineScope.launch { + RepoDownloadManager.downloadUpdate(force) + reload() + } + } + + fun reloadForTest(from: Path) { + neuRepo = makeNEURepository(from) + reloadSync() + } + + + suspend fun reload() { + withContext(Dispatchers.IO) { + reloadSync() + } + } + + fun reloadSync() { + try { + logger.info("Repo reload started.") + neuRepo.reload() + logger.info("Repo reload completed.") + } catch (exc: NEURepositoryException) { + ErrorUtil.softError("Failed to reload repository", exc) + MC.sendChat( + tr( + "firmament.repo.reloadfail", + "Failed to reload repository. This will result in some mod features not working." + ) + ) + } + } + + private var wasInitialized = false + fun initialize() { + if (wasInitialized) return + wasInitialized = true + System.getProperty("firmament.testrepo")?.let { compTimeRepo -> + reloadForTest(Path.of(compTimeRepo)) + return + } + neuRepo = makeNEURepository(RepoDownloadManager.repoSavedLocation) + if (Config.autoUpdate) { + launchAsyncUpdate() + } else { + Firmament.coroutineScope.launch { + reload() + } + } + } + + init { + if (TestUtil.isInTest) { + initialize() + } + } + + 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.entries.indices) return null + if (petId !in neuRepo.constants.petNumbers) return null + return PetData(Rarity.entries[intIndex], petId, 0.0, true) + } + + fun getRepoRef(): String { + return "${Config.username}/${Config.reponame}#${Config.branch}" + } + + fun shouldLoadREI(): Boolean = Config.enableREI +} diff --git a/src/main/kotlin/repo/RepoModResourcePack.kt b/src/main/kotlin/repo/RepoModResourcePack.kt new file mode 100644 index 0000000..4fec14a --- /dev/null +++ b/src/main/kotlin/repo/RepoModResourcePack.kt @@ -0,0 +1,127 @@ +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.fabric.impl.resource.loader.ModResourcePackSorter +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.ResourceMetadataSerializer +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import net.minecraft.util.path.PathUtil +import moe.nea.firmament.Firmament + +class RepoModResourcePack(val basePath: Path) : ModResourcePack { + companion object { + fun append(packs: ModResourcePackSorter) { + Firmament.logger.info("Registering mod resource pack") + packs.addPack(RepoModResourcePack(RepoDownloadManager.repoSavedLocation)) + } + + fun createResourceDirectly(identifier: Identifier): Optional { + 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? { + return getFile(segments)?.let { InputSupplier.create(it) } + } + + fun getFile(segments: Array): 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? { + 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 { + if (type != ResourceType.CLIENT_RESOURCES) return emptySet() + return setOf("neurepo") + } + + override fun parseMetadata(metadataSerializer: ResourceMetadataSerializer?): T? { + return AbstractFileResourcePack.parseMetadata( + metadataSerializer, """ +{ + "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/repo/SBItemStack.kt b/src/main/kotlin/repo/SBItemStack.kt new file mode 100644 index 0000000..01d1c4d --- /dev/null +++ b/src/main/kotlin/repo/SBItemStack.kt @@ -0,0 +1,458 @@ +package moe.nea.firmament.repo + +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import io.github.moulberry.repo.constants.PetNumbers +import io.github.moulberry.repo.data.NEUIngredient +import io.github.moulberry.repo.data.NEUItem +import net.minecraft.item.ItemStack +import net.minecraft.network.RegistryByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.codec.PacketCodecs +import net.minecraft.text.Style +import net.minecraft.text.Text +import net.minecraft.text.TextColor +import net.minecraft.util.Formatting +import moe.nea.firmament.repo.ItemCache.asItemStack +import moe.nea.firmament.repo.ItemCache.withFallback +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.LegacyFormattingCode +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.ReforgeId +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.blue +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.extraAttributes +import moe.nea.firmament.util.getReforgeId +import moe.nea.firmament.util.getUpgradeStars +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.mc.appendLore +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.mc.modifyLore +import moe.nea.firmament.util.modifyExtraAttributes +import moe.nea.firmament.util.petData +import moe.nea.firmament.util.prepend +import moe.nea.firmament.util.reconstitute +import moe.nea.firmament.util.removeColorCodes +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.skyblock.ItemType +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.skyblockId +import moe.nea.firmament.util.unformattedString +import moe.nea.firmament.util.useMatch +import moe.nea.firmament.util.withColor + +data class SBItemStack constructor( + val skyblockId: SkyblockId, + val neuItem: NEUItem?, + private var stackSize: Int, + private var petData: PetData?, + val extraLore: List = emptyList(), + val stars: Int = 0, + val fallback: ItemStack? = null, + val reforge: ReforgeId? = null, +) { + + 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 + } + + companion object { + val PACKET_CODEC: PacketCodec = PacketCodec.tuple( + SkyblockId.PACKET_CODEC, { it.skyblockId }, + PacketCodecs.VAR_INT, { it.stackSize }, + { id, count -> SBItemStack(id, count) } + ) + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + SkyblockId.CODEC.fieldOf("skyblockId").forGetter { it.skyblockId }, + Codec.INT.fieldOf("count").forGetter { it.stackSize }, + ).apply(it) { id, count -> + SBItemStack(id, count) + } + } + val EMPTY = SBItemStack(SkyblockId.NULL, 0) + + private val BREAKING_POWER_REGEX = "Breaking Power (?[0-9]+)".toPattern() + operator fun invoke(itemStack: ItemStack): SBItemStack { + val skyblockId = itemStack.skyBlockId ?: SkyblockId.NULL + return SBItemStack( + skyblockId, + RepoManager.getNEUItem(skyblockId), + itemStack.count, + petData = itemStack.petData?.let { PetData.fromHypixel(it) }, + stars = itemStack.getUpgradeStars(), + reforge = itemStack.getReforgeId() + ) + } + + operator fun invoke(neuIngredient: NEUIngredient): SBItemStack? { + if (neuIngredient.skyblockId == SkyblockId.SENTINEL_EMPTY) return null // TODO: better fallback, maybe? + if (neuIngredient.skyblockId == SkyblockId.COINS) { + // TODO: specially handle coins to include the decimals + } + return SBItemStack(neuIngredient.skyblockId, neuIngredient.amount.toInt()) + } + + fun passthrough(itemStack: ItemStack): SBItemStack { + return SBItemStack(SkyblockId.NULL, null, itemStack.count, null, fallback = itemStack) + } + + fun parseStatBlock(itemStack: ItemStack): List { + return itemStack.loreAccordingToNbt + .map { parseStatLine(it) } + .takeWhile { it != null } + .filterNotNull() + } + + fun appendEnhancedStats( + itemStack: ItemStack, + reforgeStats: Map, + buffKind: BuffKind, + ) { + val namedReforgeStats = reforgeStats + .mapKeysTo(mutableMapOf()) { statIdToName(it.key) } + val loreMut = itemStack.loreAccordingToNbt.toMutableList() + var statBlockLastIndex = -1 + for (i in loreMut.indices) { + val statLine = parseStatLine(loreMut[i]) + if (statLine == null && statBlockLastIndex >= 0) { + break + } + if (statLine == null) { + continue + } + statBlockLastIndex = i + val statBuff = namedReforgeStats.remove(statLine.statName) ?: continue + loreMut[i] = statLine.addStat(statBuff, buffKind).reconstitute() + } + if (namedReforgeStats.isNotEmpty() && statBlockLastIndex == -1) { + loreMut.add(0, Text.literal("")) + } + // If there is no stat block the statBlockLastIndex falls through to -1 + // TODO: this is good enough for some items. some other items might have their stats at a different place. + for ((statName, statBuff) in namedReforgeStats) { + val statLine = StatLine(statName, null).addStat(statBuff, buffKind) + loreMut.add(statBlockLastIndex + 1, statLine.reconstitute()) + } + itemStack.loreAccordingToNbt = loreMut + } + + data class StatFormatting( + val postFix: String, + val color: Formatting, + val isStarAffected: Boolean = true, + ) + + val formattingOverrides = mapOf( + "Sea Creature Chance" to StatFormatting("%", Formatting.RED), + "Strength" to StatFormatting("", Formatting.RED), + "Damage" to StatFormatting("", Formatting.RED), + "Bonus Attack Speed" to StatFormatting("%", Formatting.RED), + "Shot Cooldown" to StatFormatting("s", Formatting.GREEN, false), + "Ability Damage" to StatFormatting("%", Formatting.RED), + "Crit Damage" to StatFormatting("%", Formatting.RED), + "Crit Chance" to StatFormatting("%", Formatting.RED), + "Ability Damage" to StatFormatting("%", Formatting.RED), + "Trophy Fish Chance" to StatFormatting("%", Formatting.GREEN), + "Health" to StatFormatting("", Formatting.GREEN), + "Defense" to StatFormatting("", Formatting.GREEN), + "Fishing Speed" to StatFormatting("", Formatting.GREEN), + "Double Hook Chance" to StatFormatting("%", Formatting.GREEN), + "Mining Speed" to StatFormatting("", Formatting.GREEN), + "Mining Fortune" to StatFormatting("", Formatting.GREEN), + "Heat Resistance" to StatFormatting("", Formatting.GREEN), + "Swing Range" to StatFormatting("", Formatting.GREEN), + "Rift Time" to StatFormatting("", Formatting.GREEN), + "Speed" to StatFormatting("", Formatting.GREEN), + "Farming Fortune" to StatFormatting("", Formatting.GREEN), + "True Defense" to StatFormatting("", Formatting.GREEN), + "Mending" to StatFormatting("", Formatting.GREEN), + "Foraging Wisdom" to StatFormatting("", Formatting.GREEN), + "Farming Wisdom" to StatFormatting("", Formatting.GREEN), + "Foraging Fortune" to StatFormatting("", Formatting.GREEN), + "Magic Find" to StatFormatting("", Formatting.GREEN), + "Ferocity" to StatFormatting("", Formatting.GREEN), + "Bonus Pest Chance" to StatFormatting("%", Formatting.GREEN), + "Cold Resistance" to StatFormatting("", Formatting.GREEN), + "Pet Luck" to StatFormatting("", Formatting.GREEN), + "Fear" to StatFormatting("", Formatting.GREEN), + "Mana Regen" to StatFormatting("%", Formatting.GREEN), + "Rift Damage" to StatFormatting("", Formatting.GREEN), + "Hearts" to StatFormatting("", Formatting.GREEN), + "Vitality" to StatFormatting("", Formatting.GREEN), + // TODO: make this a repo json + ) + + + private val statLabelRegex = "(?.*): ".toPattern() + + enum class BuffKind( + val color: Formatting, + val prefix: String, + val postFix: String, + val isHidden: Boolean, + ) { + REFORGE(Formatting.BLUE, "(", ")", false), + STAR_BUFF(Formatting.RESET, "", "", true), + CATA_STAR_BUFF(Formatting.DARK_GRAY, "(", ")", false), + ; + } + + data class StatLine( + val statName: String, + val value: Text?, + val rest: List = listOf(), + val valueNum: Double? = value?.directLiteralStringContent?.trim(' ', 's', '%', '+')?.toDoubleOrNull() + ) { + fun addStat(amount: Double, buffKind: BuffKind): StatLine { + val formattedAmount = FirmFormatters.formatCommas(amount, 1, includeSign = true) + return copy( + valueNum = (valueNum ?: 0.0) + amount, + value = null, + rest = rest + + if (buffKind.isHidden) emptyList() + else listOf( + Text.literal( + buffKind.prefix + formattedAmount + + statFormatting.postFix + + buffKind.postFix + " " + ) + .withColor(buffKind.color) + ) + ) + } + + fun formatValue() = + Text.literal( + FirmFormatters.formatCommas( + valueNum ?: 0.0, + 1, + includeSign = true + ) + statFormatting.postFix + " " + ) + .setStyle(Style.EMPTY.withColor(statFormatting.color)) + + val statFormatting = formattingOverrides[statName] ?: StatFormatting("", Formatting.GREEN) + private fun abbreviate(abbreviateTo: Int): String { + if (abbreviateTo >= statName.length) return statName + val segments = statName.split(" ") + return segments.joinToString(" ") { + it.substring(0, maxOf(1, abbreviateTo / segments.size)) + } + } + + fun reconstitute(abbreviateTo: Int = Int.MAX_VALUE): Text = + Text.literal("").setStyle(Style.EMPTY.withItalic(false)) + .append(Text.literal("${abbreviate(abbreviateTo)}: ").grey()) + .append(value ?: formatValue()) + .also { rest.forEach(it::append) } + } + + fun statIdToName(statId: String): String { + val segments = statId.split("_") + return segments.joinToString(" ") { it.replaceFirstChar { it.uppercaseChar() } } + } + + fun parseStatLine(line: Text): StatLine? { + val sibs = line.siblings + val stat = sibs.firstOrNull() ?: return null + if (stat.style.color != TextColor.fromFormatting(Formatting.GRAY)) return null + val statLabel = stat.directLiteralStringContent ?: return null + val statName = statLabelRegex.useMatch(statLabel) { group("statName") } ?: return null + return StatLine(statName, sibs[1], sibs.subList(2, sibs.size)) + } + } + + 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 + ) { + 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) { + val petData = this.petData ?: return + val petInfo = RepoManager.neuRepo.constants.petNumbers[petData.petId]?.get(petData.rarity) ?: return + if (petData.isStub) { + val mapLow = mutableMapOf() + injectReplacementDataForPetLevel(petInfo, petInfo.lowLevel, mapLow) + val mapHigh = mutableMapOf() + 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 fun appendReforgeInfo( + itemStack: ItemStack, + ) { + val rarity = Rarity.fromItem(itemStack) ?: return + val reforgeId = this.reforge ?: return + val reforge = ReforgeStore.modifierLut[reforgeId] ?: return + val reforgeStats = reforge.reforgeStats?.get(rarity) ?: mapOf() + itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy() + .prepend(Text.literal(reforge.reforgeName + " ").formatted(Rarity.colourMap[rarity] ?: Formatting.WHITE)) + val data = itemStack.extraAttributes.copy() + data.putString("modifier", reforgeId.id) + itemStack.extraAttributes = data + appendEnhancedStats(itemStack, reforgeStats, BuffKind.REFORGE) + reforge.reforgeAbility?.get(rarity)?.let { reforgeAbility -> + val formattedReforgeAbility = ItemCache.un189Lore(reforgeAbility) + .grey() + itemStack.modifyLore { + val lastBlank = it.indexOfLast { it.unformattedString.isBlank() } + val newList = mutableListOf() + newList.addAll(it.subList(0, lastBlank)) + newList.add(Text.literal("")) + newList.add(Text.literal("${reforge.reforgeName} Bonus").blue()) + MC.font.textHandler.wrapLines(formattedReforgeAbility, 180, Style.EMPTY).mapTo(newList) { + it.reconstitute() + } + newList.addAll(it.subList(lastBlank, it.size)) + return@modifyLore newList + } + } + } + + // TODO: avoid instantiating the item stack here + @ExpensiveItemCacheApi + val itemType: ItemType? get() = ItemType.fromItemStack(asImmutableItemStack()) + @ExpensiveItemCacheApi + val rarity: Rarity? get() = Rarity.fromItem(asImmutableItemStack()) + + private var itemStack_: ItemStack? = null + + val breakingPower: Int + get() = + BREAKING_POWER_REGEX.useMatch(neuItem?.lore?.firstOrNull()?.removeColorCodes()) { + group("power").toInt() + } ?: 0 + + @ExpensiveItemCacheApi + private val itemStack: ItemStack + get() { + val itemStack = itemStack_ ?: run { + if (skyblockId == SkyblockId.COINS) + return@run ItemCache.coinItem(stackSize).also { it.appendLore(extraLore) } + if (stackSize == 0) + return@run ItemStack.EMPTY + val replacementData = mutableMapOf() + injectReplacementDataForPets(replacementData) + val baseItem = neuItem.asItemStack(idHint = skyblockId, replacementData) + .withFallback(fallback) + .copyWithCount(stackSize) + val baseStats = parseStatBlock(baseItem) + appendReforgeInfo(baseItem) + baseItem.appendLore(extraLore) + enhanceStatsByStars(baseItem, stars, baseStats) + return@run baseItem + } + if (itemStack_ == null) + itemStack_ = itemStack + return itemStack + } + + + private fun starString(stars: Int): Text { + if (stars <= 0) return Text.empty() + // TODO: idk master stars + 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, baseStats: List) { + if (stars == 0) return + // TODO: increase stats and add the star level into the nbt data so star displays work + itemStack.modifyExtraAttributes { + it.putInt("upgrade_level", stars) + } + itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy() + .append(starString(stars)) + val isDungeon = ItemType.fromItemStack(itemStack)?.isDungeon ?: true + val truncatedStarCount = if (isDungeon) minOf(5, stars) else stars + appendEnhancedStats( + itemStack, + baseStats + .filter { it.statFormatting.isStarAffected } + .associate { + it.statName to ((it.valueNum ?: 0.0) * (truncatedStarCount * 0.02)) + }, + BuffKind.STAR_BUFF + ) + } + + fun isWarm(): Boolean { + if (itemStack_ != null) return true + if (ItemCache.hasCacheFor(skyblockId)) return true + return false + } + + @OptIn(ExpensiveItemCacheApi::class) + fun asLazyImmutableItemStack(): ItemStack? { + if (isWarm()) return asImmutableItemStack() + return null + } + + @ExpensiveItemCacheApi + fun asImmutableItemStack(): ItemStack { // TODO: add a "or fallback to painting" option to asLazyImmutableItemStack to be used in more places. + return itemStack + } + + @ExpensiveItemCacheApi + fun asCopiedItemStack(): ItemStack { + return itemStack.copy() + } +} diff --git a/src/main/kotlin/repo/recipes/GenericRecipeRenderer.kt b/src/main/kotlin/repo/recipes/GenericRecipeRenderer.kt new file mode 100644 index 0000000..3774f26 --- /dev/null +++ b/src/main/kotlin/repo/recipes/GenericRecipeRenderer.kt @@ -0,0 +1,21 @@ +package moe.nea.firmament.repo.recipes + +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEURecipe +import me.shedaniel.math.Rectangle +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.repo.SBItemStack + +interface GenericRecipeRenderer { + fun render(recipe: T, bounds: Rectangle, layouter: RecipeLayouter, mainItem: SBItemStack?) + fun getInputs(recipe: T): Collection + fun getOutputs(recipe: T): Collection + val icon: ItemStack + val title: Text + val identifier: Identifier + fun findAllRecipes(neuRepository: NEURepository): Iterable + val displayHeight: Int get() = 66 + val typ: Class +} diff --git a/src/main/kotlin/repo/recipes/RecipeLayouter.kt b/src/main/kotlin/repo/recipes/RecipeLayouter.kt new file mode 100644 index 0000000..ed0dca2 --- /dev/null +++ b/src/main/kotlin/repo/recipes/RecipeLayouter.kt @@ -0,0 +1,38 @@ +package moe.nea.firmament.repo.recipes + +import io.github.notenoughupdates.moulconfig.gui.GuiComponent +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import net.minecraft.text.Text +import moe.nea.firmament.repo.SBItemStack + +interface RecipeLayouter { + enum class SlotKind { + SMALL_INPUT, + SMALL_OUTPUT, + + /** + * Create a bigger background and mark the slot as output. The coordinates should still refer the upper left corner of the item stack, not of the bigger background. + */ + BIG_OUTPUT, + } + + fun createItemSlot( + x: Int, y: Int, + content: SBItemStack?, + slotKind: SlotKind, + ) + + fun createTooltip(rectangle: Rectangle, label: Text) + + fun createLabel( + x: Int, y: Int, + text: Text + ) + + fun createArrow(x: Int, y: Int): Rectangle + + fun createMoulConfig(x: Int, y: Int, w: Int, h: Int, component: GuiComponent) + fun createFire(ingredientsCenter: Point, animationTicks: Int) +} + diff --git a/src/main/kotlin/repo/recipes/SBCraftingRecipeRenderer.kt b/src/main/kotlin/repo/recipes/SBCraftingRecipeRenderer.kt new file mode 100644 index 0000000..e38380c --- /dev/null +++ b/src/main/kotlin/repo/recipes/SBCraftingRecipeRenderer.kt @@ -0,0 +1,60 @@ +package moe.nea.firmament.repo.recipes + +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEUCraftingRecipe +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import net.minecraft.block.Blocks +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.tr + +object SBCraftingRecipeRenderer : GenericRecipeRenderer { + override fun render( + recipe: NEUCraftingRecipe, + bounds: Rectangle, + layouter: RecipeLayouter, + mainItem: SBItemStack?, + ) { + val point = Point(bounds.centerX - 58, bounds.centerY - 27) + layouter.createArrow(point.x + 60, point.y + 18) + for (i in 0 until 3) { + for (j in 0 until 3) { + val item = recipe.inputs[i + j * 3] + layouter.createItemSlot( + point.x + 1 + i * 18, + point.y + 1 + j * 18, + SBItemStack(item), + RecipeLayouter.SlotKind.SMALL_INPUT + ) + } + } + layouter.createItemSlot( + point.x + 95, point.y + 19, + SBItemStack(recipe.output), + RecipeLayouter.SlotKind.BIG_OUTPUT + ) + } + + override val typ: Class + get() = NEUCraftingRecipe::class.java + + override fun getInputs(recipe: NEUCraftingRecipe): Collection { + return recipe.allInputs.mapNotNull { SBItemStack(it) } + } + + override fun getOutputs(recipe: NEUCraftingRecipe): Collection { + return SBItemStack(recipe.output)?.let(::listOf) ?: emptyList() + } + + override fun findAllRecipes(neuRepository: NEURepository): Iterable { + return neuRepository.items.items.values.flatMap { it.recipes }.filterIsInstance() + } + + override val icon: ItemStack = ItemStack(Blocks.CRAFTING_TABLE) + override val title: Text = tr("firmament.category.crafting", "SkyBlock Crafting") + override val identifier: Identifier = Firmament.identifier("crafting_recipe") +} diff --git a/src/main/kotlin/repo/recipes/SBEssenceUpgradeRecipeRenderer.kt b/src/main/kotlin/repo/recipes/SBEssenceUpgradeRecipeRenderer.kt new file mode 100644 index 0000000..d358e6a --- /dev/null +++ b/src/main/kotlin/repo/recipes/SBEssenceUpgradeRecipeRenderer.kt @@ -0,0 +1,76 @@ +package moe.nea.firmament.repo.recipes + +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEUForgeRecipe +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.repo.EssenceRecipeProvider +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.tr + +object SBEssenceUpgradeRecipeRenderer : GenericRecipeRenderer { + override fun render( + recipe: EssenceRecipeProvider.EssenceUpgradeRecipe, + bounds: Rectangle, + layouter: RecipeLayouter, + mainItem: SBItemStack? + ) { + val sourceItem = mainItem ?: SBItemStack(recipe.itemId) + layouter.createItemSlot( + bounds.minX + 12, + bounds.centerY - 8 - 18 / 2, + sourceItem.copy(stars = recipe.starCountAfter - 1), + RecipeLayouter.SlotKind.SMALL_INPUT + ) + layouter.createItemSlot( + bounds.minX + 12, bounds.centerY - 8 + 18 / 2, + SBItemStack(recipe.essenceIngredient), + RecipeLayouter.SlotKind.SMALL_INPUT + ) + layouter.createItemSlot( + bounds.maxX - 12 - 16, bounds.centerY - 8, + sourceItem.copy(stars = recipe.starCountAfter), + RecipeLayouter.SlotKind.SMALL_OUTPUT + ) + val extraItems = recipe.extraItems + layouter.createArrow( + bounds.centerX - 24 / 2, + if (extraItems.isEmpty()) bounds.centerY - 17 / 2 + else bounds.centerY + 18 / 2 + ) + for ((index, item) in extraItems.withIndex()) { + layouter.createItemSlot( + bounds.centerX - extraItems.size * 16 / 2 - 2 / 2 + index * 18, + bounds.centerY - 18 / 2, + SBItemStack(item), + RecipeLayouter.SlotKind.SMALL_INPUT, + ) + } + } + + override fun getInputs(recipe: EssenceRecipeProvider.EssenceUpgradeRecipe): Collection { + return recipe.allInputs.mapNotNull { SBItemStack(it) } + } + + override fun getOutputs(recipe: EssenceRecipeProvider.EssenceUpgradeRecipe): Collection { + return listOfNotNull(SBItemStack(recipe.itemId)) + } + + @OptIn(ExpensiveItemCacheApi::class) + override val icon: ItemStack get() = SBItemStack(SkyblockId("ESSENCE_WITHER")).asImmutableItemStack() + override val title: Text = tr("firmament.category.essence", "Essence Upgrades") + override val identifier: Identifier = Firmament.identifier("essence_upgrade") + override fun findAllRecipes(neuRepository: NEURepository): Iterable { + return RepoManager.essenceRecipeProvider.recipes + } + + override val typ: Class + get() = EssenceRecipeProvider.EssenceUpgradeRecipe::class.java +} diff --git a/src/main/kotlin/repo/recipes/SBForgeRecipeRenderer.kt b/src/main/kotlin/repo/recipes/SBForgeRecipeRenderer.kt new file mode 100644 index 0000000..9fdb756 --- /dev/null +++ b/src/main/kotlin/repo/recipes/SBForgeRecipeRenderer.kt @@ -0,0 +1,83 @@ +package moe.nea.firmament.repo.recipes + +import io.github.moulberry.repo.NEURepository +import io.github.moulberry.repo.data.NEUCraftingRecipe +import io.github.moulberry.repo.data.NEUForgeRecipe +import me.shedaniel.math.Point +import me.shedaniel.math.Rectangle +import kotlin.math.cos +import kotlin.math.sin +import kotlin.time.Duration.Companion.seconds +import net.minecraft.block.Blocks +import net.minecraft.item.ItemStack +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.tr + +object SBForgeRecipeRenderer : GenericRecipeRenderer { + override fun render( + recipe: NEUForgeRecipe, + bounds: Rectangle, + layouter: RecipeLayouter, + mainItem: SBItemStack?, + ) { + val arrow = layouter.createArrow(bounds.minX + 90, bounds.minY + 54 - 18 / 2) + layouter.createTooltip( + arrow, + Text.stringifiedTranslatable( + "firmament.recipe.forge.time", + recipe.duration.seconds + ) + ) + + val ingredientsCenter = Point(bounds.minX + 49 - 8, bounds.minY + 54 - 8) + layouter.createFire(ingredientsCenter, 25) + val count = recipe.inputs.size + if (count == 1) { + layouter.createItemSlot( + ingredientsCenter.x, ingredientsCenter.y - 18, + SBItemStack(recipe.inputs.single()), + RecipeLayouter.SlotKind.SMALL_INPUT, + ) + } else { + recipe.inputs.forEachIndexed { idx, ingredient -> + val rad = Math.PI * 2 * idx / count + layouter.createItemSlot( + (ingredientsCenter.x + cos(rad) * 30).toInt(), (ingredientsCenter.y + sin(rad) * 30).toInt(), + SBItemStack(ingredient), + RecipeLayouter.SlotKind.SMALL_INPUT, + ) + } + } + layouter.createItemSlot( + bounds.minX + 124, bounds.minY + 46, + SBItemStack(recipe.outputStack), + RecipeLayouter.SlotKind.BIG_OUTPUT + ) + } + + override val displayHeight: Int + get() = 104 + + override fun getInputs(recipe: NEUForgeRecipe): Collection { + return recipe.inputs.mapNotNull { SBItemStack(it) } + } + + override fun getOutputs(recipe: NEUForgeRecipe): Collection { + return listOfNotNull(SBItemStack(recipe.outputStack)) + } + + override val icon: ItemStack = ItemStack(Blocks.ANVIL) + override val title: Text = tr("firmament.category.forge", "Forge Recipes") + override val identifier: Identifier = Firmament.identifier("forge_recipe") + + override fun findAllRecipes(neuRepository: NEURepository): Iterable { + // TODO: theres gotta be an index for these tbh. + return neuRepository.items.items.values.flatMap { it.recipes }.filterIsInstance() + } + + override val typ: Class + get() = NEUForgeRecipe::class.java +} diff --git a/src/main/kotlin/util/AprilFoolsUtil.kt b/src/main/kotlin/util/AprilFoolsUtil.kt new file mode 100644 index 0000000..a940fa1 --- /dev/null +++ b/src/main/kotlin/util/AprilFoolsUtil.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.util + +import java.time.LocalDateTime +import java.time.Month + +object AprilFoolsUtil { + val isAprilFoolsDay = LocalDateTime.now().let { + it.dayOfMonth == 1 && it.month == Month.APRIL + } +} diff --git a/src/main/kotlin/util/Base64Util.kt b/src/main/kotlin/util/Base64Util.kt new file mode 100644 index 0000000..c39c601 --- /dev/null +++ b/src/main/kotlin/util/Base64Util.kt @@ -0,0 +1,17 @@ + +package moe.nea.firmament.util + +import java.util.Base64 + +object Base64Util { + fun decodeString(str: String): String { + return Base64.getDecoder().decode(str.padToValidBase64()) + .decodeToString() + } + + 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/util/BazaarPriceStrategy.kt b/src/main/kotlin/util/BazaarPriceStrategy.kt new file mode 100644 index 0000000..13b6d95 --- /dev/null +++ b/src/main/kotlin/util/BazaarPriceStrategy.kt @@ -0,0 +1,19 @@ + +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.asBazaarStock] ?: 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/util/ChromaColourUtil.kt b/src/main/kotlin/util/ChromaColourUtil.kt new file mode 100644 index 0000000..0130326 --- /dev/null +++ b/src/main/kotlin/util/ChromaColourUtil.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.util + +import io.github.notenoughupdates.moulconfig.ChromaColour +import java.awt.Color + +fun ChromaColour.getRGBAWithoutAnimation() = + Color(ChromaColour.specialToSimpleRGB(toLegacyString()), true) + +fun Color.toChromaWithoutAnimation(timeForFullRotationInMillis: Int = 0) = + ChromaColour.fromRGB(red, green, blue, timeForFullRotationInMillis, alpha) diff --git a/src/main/kotlin/util/ClipboardUtils.kt b/src/main/kotlin/util/ClipboardUtils.kt new file mode 100644 index 0000000..7b9b836 --- /dev/null +++ b/src/main/kotlin/util/ClipboardUtils.kt @@ -0,0 +1,24 @@ + + +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/util/CommonSoundEffects.kt b/src/main/kotlin/util/CommonSoundEffects.kt new file mode 100644 index 0000000..a97a2cb --- /dev/null +++ b/src/main/kotlin/util/CommonSoundEffects.kt @@ -0,0 +1,26 @@ + + +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/util/DurabilityBarEvent.kt b/src/main/kotlin/util/DurabilityBarEvent.kt new file mode 100644 index 0000000..993462c --- /dev/null +++ b/src/main/kotlin/util/DurabilityBarEvent.kt @@ -0,0 +1,20 @@ + +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() +} diff --git a/src/main/kotlin/util/ErrorBoundary.kt b/src/main/kotlin/util/ErrorBoundary.kt new file mode 100644 index 0000000..fbc5b37 --- /dev/null +++ b/src/main/kotlin/util/ErrorBoundary.kt @@ -0,0 +1,10 @@ + + +package moe.nea.firmament.util + + +fun errorBoundary(block: () -> T): T? { + // TODO: implement a proper error boundary here to avoid crashing minecraft code + return block() +} + diff --git a/src/main/kotlin/util/ErrorUtil.kt b/src/main/kotlin/util/ErrorUtil.kt new file mode 100644 index 0000000..3db4ecd --- /dev/null +++ b/src/main/kotlin/util/ErrorUtil.kt @@ -0,0 +1,97 @@ +@file:OptIn(ExperimentalContracts::class) + +package moe.nea.firmament.util + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import moe.nea.firmament.Firmament + +@Suppress("NOTHING_TO_INLINE") // Suppressed since i want the logger to not pick up the ErrorUtil stack-frame +object ErrorUtil { + var aggressiveErrors = run { + TestUtil.isInTest || Firmament.DEBUG + || ErrorUtil::class.java.desiredAssertionStatus() + } + + inline fun softCheck(message: String, check: Boolean) { + if (!check) softError(message) + } + + inline fun lazyCheck(message: String, func: () -> Boolean) { + contract { + callsInPlace(func, InvocationKind.AT_MOST_ONCE) + } + if (!aggressiveErrors) return + if (func()) return + error(message) + } + + inline fun softError(message: String, exception: Throwable) { + if (aggressiveErrors) throw IllegalStateException(message, exception) + else logError(message, exception) + } + + fun logError(message: String, exception: Throwable) { + Firmament.logger.error(message, exception) + } + fun logError(message: String) { + Firmament.logger.error(message) + } + + inline fun softError(message: String) { + if (aggressiveErrors) error(message) + else logError(message) + } + + fun Result.intoCatch(message: String): Catch { + return this.map { Catch.succeed(it) }.getOrElse { + softError(message, it) + Catch.fail(it) + } + } + + class Catch private constructor(val value: T?, val exc: Throwable?) { + fun orNull(): T? = value + + inline fun or(block: (exc: Throwable) -> T): T { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + if (exc != null) return block(exc) + @Suppress("UNCHECKED_CAST") + return value as T + } + + companion object { + fun fail(exception: Throwable): Catch = Catch(null, exception) + fun succeed(value: T): Catch = Catch(value, null) + } + } + + inline fun catch(message: String, block: () -> T): Catch { + try { + return Catch.succeed(block()) + } catch (exc: Throwable) { + softError(message, exc) + return Catch.fail(exc) + } + } + + inline fun notNullOr(nullable: T?, message: String, orElse: () -> T): T { + contract { + callsInPlace(orElse, InvocationKind.AT_MOST_ONCE) + } + if (nullable == null) { + softError(message) + return orElse() + } + return nullable + } + + fun softUserError(string: String) { + if (TestUtil.isInTest) + error(string) + MC.sendChat(tr("firmament.usererror", "Firmament encountered a user caused error: $string")) + } +} diff --git a/src/main/kotlin/util/FirmFormatters.kt b/src/main/kotlin/util/FirmFormatters.kt new file mode 100644 index 0000000..03dafc5 --- /dev/null +++ b/src/main/kotlin/util/FirmFormatters.kt @@ -0,0 +1,142 @@ +package moe.nea.firmament.util + +import com.google.common.math.IntMath.pow +import java.nio.file.Path +import kotlin.io.path.exists +import kotlin.io.path.fileSize +import kotlin.io.path.isDirectory +import kotlin.io.path.isReadable +import kotlin.io.path.isRegularFile +import kotlin.io.path.listDirectoryEntries +import kotlin.math.absoluteValue +import kotlin.math.roundToInt +import kotlin.time.Duration +import kotlin.time.Duration.Companion.seconds +import net.minecraft.text.Text +import net.minecraft.util.math.BlockPos + +object FirmFormatters { + + private inline fun shortIf( + value: Double, breakpoint: Double, char: String, + return_: (String) -> Nothing + ) { + if (value >= breakpoint) { + val broken = (value / breakpoint * 10).roundToInt() + if (broken > 99) + return_((broken / 10).toString() + char) + val decimals = broken.toString() + decimals.singleOrNull()?.let { + return_("0.$it$char") + } + return_("${decimals[0]}.${decimals[1]}$char") + } + } + + fun shortFormat(double: Double): String { + if (double < 0) return "-" + shortFormat(-double) + shortIf(double, 1_000_000_000_000.0, "t") { return it } + shortIf(double, 1_000_000_000.0, "b") { return it } + shortIf(double, 1_000_000.0, "m") { return it } + shortIf(double, 1_000.0, "k") { return it } + shortIf(double, 1.0, "") { return it } + return double.toString() + } + + fun formatCommas(int: Int, segments: Int = 3): String = formatCommas(int.toLong(), segments) + fun formatCommas(long: Long, segments: Int = 3, includeSign: Boolean = false): String { + if (long < 0 && long != Long.MIN_VALUE) { + return "-" + formatCommas(-long, segments, false) + } + val prefix = if (includeSign) "+" else "" + val α = long / 1000 + if (α != 0L) { + return prefix + formatCommas(α, segments) + "," + (long - α * 1000).toString().padStart(3, '0') + } + return prefix + long.toString() + } + + fun formatCommas(float: Float, fractionalDigits: Int): String = formatCommas(float.toDouble(), fractionalDigits) + fun formatCommas(double: Double, fractionalDigits: Int, includeSign: Boolean = false): 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, includeSign = includeSign) + (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") + } + val milliTime = nanoseconds / 1_000_000 + val deciseconds = milliTime / 100 + if (millis) { + sb.append(seconds).append("s") + sb.append(milliTime).append("ms") + } else if (duration.absoluteValue < 5.seconds && deciseconds != 0) { + sb.append(seconds).append('.').append(deciseconds.digitToChar()).append("s") + } else { + sb.append(seconds).append("s") + } + Unit + } + return sb.toString() + } + + fun debugPath(path: Path): Text { + if (!path.exists()) { + return tr("firmament.path.missing", "$path (missing)").red() + } + if (!path.isReadable()) { + return tr("firmament.path.unreadable", "$path (unreadable)").red() + } + if (path.isRegularFile()) { + return tr("firmament.path.regular", + "$path (exists ${formatFileSize(path.fileSize())})").lime() + } + if (path.isDirectory()) { + return tr("firmament.path.directory", "$path (${path.listDirectoryEntries().size} entries)").darkGreen() + } + return tr("firmament.path.unknown", "$path (unknown)").purple() + } + + fun formatFileSize(fileSizeInBytes: Long): String { + return "${fileSizeInBytes / 1024} KiB" + } + + fun formatBool( + boolean: Boolean, + trueIsGood: Boolean = true, + ): Text { + val text = Text.literal(boolean.toString()) + return if (boolean == trueIsGood) text.lime() else text.red() + } + + fun formatPosition(position: BlockPos): Text { + return Text.literal("x: ${position.x}, y: ${position.y}, z: ${position.z}") + } + + fun formatPercent(value: Double, decimals: Int = 1): String { + return "%.${decimals}f%%".format(value * 100) + } +} diff --git a/src/main/kotlin/util/FragmentGuiScreen.kt b/src/main/kotlin/util/FragmentGuiScreen.kt new file mode 100644 index 0000000..5e13d51 --- /dev/null +++ b/src/main/kotlin/util/FragmentGuiScreen.kt @@ -0,0 +1,93 @@ + + +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/util/HoveredItemStack.kt b/src/main/kotlin/util/HoveredItemStack.kt new file mode 100644 index 0000000..526820a --- /dev/null +++ b/src/main/kotlin/util/HoveredItemStack.kt @@ -0,0 +1,27 @@ +package moe.nea.firmament.util + +import com.google.auto.service.AutoService +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.item.ItemStack +import moe.nea.firmament.mixins.accessor.AccessorHandledScreen +import moe.nea.firmament.util.compatloader.CompatLoader + +interface HoveredItemStackProvider { + fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? + + companion object : CompatLoader(HoveredItemStackProvider::class) +} + +@AutoService(HoveredItemStackProvider::class) +class VanillaScreenProvider : HoveredItemStackProvider { + override fun provideHoveredItemStack(screen: HandledScreen<*>): ItemStack? { + screen as AccessorHandledScreen + val vanillaSlot = screen.focusedSlot_Firmament?.stack + return vanillaSlot + } +} + +val HandledScreen<*>.focusedItemStack: ItemStack? + get() = + HoveredItemStackProvider.allValidInstances + .firstNotNullOfOrNull { it.provideHoveredItemStack(this)?.takeIf { !it.isEmpty } } diff --git a/src/main/kotlin/util/IdentifierSerializer.kt b/src/main/kotlin/util/IdentifierSerializer.kt new file mode 100644 index 0000000..65c5b1c --- /dev/null +++ b/src/main/kotlin/util/IdentifierSerializer.kt @@ -0,0 +1,25 @@ + +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 { + 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/util/IdentityCharacteristics.kt b/src/main/kotlin/util/IdentityCharacteristics.kt new file mode 100644 index 0000000..f6054c4 --- /dev/null +++ b/src/main/kotlin/util/IdentityCharacteristics.kt @@ -0,0 +1,15 @@ + + +package moe.nea.firmament.util + +class IdentityCharacteristics(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/util/IntUtil.kt b/src/main/kotlin/util/IntUtil.kt new file mode 100644 index 0000000..2695906 --- /dev/null +++ b/src/main/kotlin/util/IntUtil.kt @@ -0,0 +1,12 @@ +package moe.nea.firmament.util + +object IntUtil { + data class RGBA(val r: Int, val g: Int, val b: Int, val a: Int) + + fun Int.toRGBA(): RGBA { + return RGBA( + r = (this shr 16) and 0xFF, g = (this shr 8) and 0xFF, b = this and 0xFF, a = (this shr 24) and 0xFF + ) + } + +} diff --git a/src/main/kotlin/util/JvmUtil.kt b/src/main/kotlin/util/JvmUtil.kt new file mode 100644 index 0000000..5be5ebd --- /dev/null +++ b/src/main/kotlin/util/JvmUtil.kt @@ -0,0 +1,32 @@ +package moe.nea.firmament.util + +import com.sun.tools.attach.VirtualMachine +import java.lang.management.ManagementFactory +import java.nio.file.Path +import kotlin.io.path.absolutePathString + +object JvmUtil { + fun guessJVMPid(): String { + val name = ManagementFactory.getRuntimeMXBean().name + val pid = name.substringBefore('@') + ErrorUtil.softCheck("Not a valid PID: $pid", pid.toIntOrNull() != null) + return pid + } + + fun getVM(): VirtualMachine { + return VirtualMachine.attach(guessJVMPid()) + } + + fun useVM(block: (VirtualMachine) -> Unit) { + val vm = getVM() + block(vm) + vm.detach() + } + + fun loadAgent(jarPath: Path, options: String? = null) { + useVM { + it.loadAgent(jarPath.absolutePathString(), options) + } + } + +} diff --git a/src/main/kotlin/util/LegacyFormattingCode.kt b/src/main/kotlin/util/LegacyFormattingCode.kt new file mode 100644 index 0000000..1a5d1dd --- /dev/null +++ b/src/main/kotlin/util/LegacyFormattingCode.kt @@ -0,0 +1,37 @@ +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); + + companion object { + val byCode = entries.associateBy { it.char } + } + + val modern = Formatting.byCode(char)!! + + val formattingCode = "§$char" + +} diff --git a/src/main/kotlin/util/LegacyTagParser.kt b/src/main/kotlin/util/LegacyTagParser.kt new file mode 100644 index 0000000..4e08da1 --- /dev/null +++ b/src/main/kotlin/util/LegacyTagParser.kt @@ -0,0 +1,245 @@ + + +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() + + 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/util/LegacyTagWriter.kt b/src/main/kotlin/util/LegacyTagWriter.kt new file mode 100644 index 0000000..9889b2c --- /dev/null +++ b/src/main/kotlin/util/LegacyTagWriter.kt @@ -0,0 +1,103 @@ +package moe.nea.firmament.util + +import kotlinx.serialization.json.JsonPrimitive +import net.minecraft.nbt.AbstractNbtList +import net.minecraft.nbt.NbtByte +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtDouble +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtEnd +import net.minecraft.nbt.NbtFloat +import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtLong +import net.minecraft.nbt.NbtShort +import net.minecraft.nbt.NbtString +import moe.nea.firmament.util.mc.SNbtFormatter.Companion.SIMPLE_NAME + +class LegacyTagWriter(val compact: Boolean) { + companion object { + fun stringify(nbt: NbtElement, compact: Boolean): String { + return LegacyTagWriter(compact).also { it.writeElement(nbt) } + .stringWriter.toString() + } + + fun NbtElement.toLegacyString(pretty: Boolean = false): String { + return stringify(this, !pretty) + } + } + + val stringWriter = StringBuilder() + var indent = 0 + fun newLine() { + if (compact) return + stringWriter.append('\n') + repeat(indent) { + stringWriter.append(" ") + } + } + + fun writeElement(nbt: NbtElement) { + when (nbt) { + is NbtInt -> stringWriter.append(nbt.value.toString()) + is NbtString -> stringWriter.append(escapeString(nbt.value)) + is NbtFloat -> stringWriter.append(nbt.value).append('F') + is NbtDouble -> stringWriter.append(nbt.value).append('D') + is NbtByte -> stringWriter.append(nbt.value).append('B') + is NbtLong -> stringWriter.append(nbt.value).append('L') + is NbtShort -> stringWriter.append(nbt.value).append('S') + is NbtCompound -> writeCompound(nbt) + is NbtEnd -> {} + is AbstractNbtList -> writeArray(nbt) + } + } + + fun writeArray(nbt: AbstractNbtList) { + stringWriter.append('[') + indent++ + newLine() + nbt.forEachIndexed { index, element -> + writeName(index.toString()) + writeElement(element) + if (index != nbt.size() - 1) { + stringWriter.append(',') + newLine() + } + } + indent-- + if (nbt.size() != 0) + newLine() + stringWriter.append(']') + } + + fun writeCompound(nbt: NbtCompound) { + stringWriter.append('{') + indent++ + newLine() + val entries = nbt.entrySet().sortedBy { it.key } + entries.forEachIndexed { index, it -> + writeName(it.key) + writeElement(it.value) + if (index != entries.lastIndex) { + stringWriter.append(',') + newLine() + } + } + indent-- + if (nbt.size != 0) + newLine() + stringWriter.append('}') + } + + fun escapeString(string: String): String { + return JsonPrimitive(string).toString() + } + + fun escapeName(key: String): String = + if (key.matches(SIMPLE_NAME)) key else escapeString(key) + + fun writeName(key: String) { + stringWriter.append(escapeName(key)) + stringWriter.append(':') + if (!compact) stringWriter.append(' ') + } +} diff --git a/src/main/kotlin/util/LoadResource.kt b/src/main/kotlin/util/LoadResource.kt new file mode 100644 index 0000000..4bc8704 --- /dev/null +++ b/src/main/kotlin/util/LoadResource.kt @@ -0,0 +1,20 @@ + +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/util/Locraw.kt b/src/main/kotlin/util/Locraw.kt new file mode 100644 index 0000000..9778bc7 --- /dev/null +++ b/src/main/kotlin/util/Locraw.kt @@ -0,0 +1,12 @@ + + +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/util/LogIfNull.kt b/src/main/kotlin/util/LogIfNull.kt new file mode 100644 index 0000000..600c5e6 --- /dev/null +++ b/src/main/kotlin/util/LogIfNull.kt @@ -0,0 +1,8 @@ + +package moe.nea.firmament.util + + +fun runNull(block: () -> Unit): Nothing? { + block() + return null +} diff --git a/src/main/kotlin/util/MC.kt b/src/main/kotlin/util/MC.kt new file mode 100644 index 0000000..e85b119 --- /dev/null +++ b/src/main/kotlin/util/MC.kt @@ -0,0 +1,152 @@ +package moe.nea.firmament.util + +import io.github.moulberry.repo.data.Coordinate +import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper +import java.util.concurrent.ConcurrentLinkedQueue +import kotlin.jvm.optionals.getOrNull +import net.minecraft.client.MinecraftClient +import net.minecraft.client.gui.hud.InGameHud +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.network.ClientPlayerEntity +import net.minecraft.client.render.GameRenderer +import net.minecraft.client.render.WorldRenderer +import net.minecraft.client.render.item.ItemRenderer +import net.minecraft.client.world.ClientWorld +import net.minecraft.entity.Entity +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket +import net.minecraft.registry.BuiltinRegistries +import net.minecraft.registry.Registry +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryKeys +import net.minecraft.registry.RegistryWrapper +import net.minecraft.resource.ReloadableResourceManagerImpl +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import net.minecraft.util.Util +import net.minecraft.util.math.BlockPos +import net.minecraft.world.World +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.events.WorldReadyEvent + +object MC { + + private val messageQueue = ConcurrentLinkedQueue() + + init { + TickEvent.subscribe("MC:push") { + if (inGameHud.chatHud != null && world != null) + while (true) { + inGameHud.chatHud.addMessage(messageQueue.poll() ?: break) + } + while (true) { + (nextTickTodos.poll() ?: break).invoke() + } + } + WorldReadyEvent.subscribe("MC:ready") { + this.lastWorld + } + } + + fun sendChat(text: Text) { + if (instance.isOnThread && inGameHud.chatHud != null && world != null) + inGameHud.chatHud.addMessage(text) + else + messageQueue.add(text) + } + + @Deprecated("Use checked method instead", replaceWith = ReplaceWith("sendCommand(command)")) + 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) { + // TODO: add a queue to this and sendServerChat + ErrorUtil.softCheck("Server commands have an implied /", !command.startsWith("/")) + 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 itemRenderer: ItemRenderer get() = instance.itemRenderer + inline val worldRenderer: WorldRenderer get() = instance.worldRenderer + inline val gameRenderer: GameRenderer get() = instance.gameRenderer + inline val networkHandler get() = player?.networkHandler + inline val instance get() = MinecraftClient.getInstance() + inline val keyboard get() = instance.keyboard + inline val interactionManager get() = instance.interactionManager + inline val textureManager get() = instance.textureManager + inline val options get() = instance.options + inline val inGameHud: InGameHud get() = instance.inGameHud + inline val font get() = instance.textRenderer + inline val soundManager get() = instance.soundManager + inline val player: ClientPlayerEntity? get() = TestUtil.unlessTesting { instance.player } + inline val camera: Entity? get() = instance.cameraEntity + inline val stackInHand: ItemStack get() = player?.mainHandStack ?: ItemStack.EMPTY + inline val guiAtlasManager get() = instance.guiAtlasManager + inline val world: ClientWorld? get() = TestUtil.unlessTesting { instance.world } + inline val playerName: String? get() = player?.name?.unformattedString + inline var screen: Screen? + get() = TestUtil.unlessTesting { instance.currentScreen } + set(value) = instance.setScreen(value) + val screenName get() = screen?.title?.unformattedString?.trim() + 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 by lazy { BuiltinRegistries.createWrapperLookup() } + inline val currentOrDefaultRegistries get() = currentRegistries ?: defaultRegistries + val defaultItems: RegistryWrapper.Impl by lazy { defaultRegistries.getOrThrow(RegistryKeys.ITEM) } + var currentTick = 0 + var lastWorld: World? = null + get() { + field = world ?: field + return field + } + private set + + val currentMoulConfigContext + get() = (screen as? GuiComponentWrapper)?.context + + fun openUrl(uri: String) { + Util.getOperatingSystem().open(uri) + } + + fun unsafeGetRegistryEntry(registry: RegistryKey>, identifier: Identifier) = + unsafeGetRegistryEntry(RegistryKey.of(registry, identifier)) + + + fun unsafeGetRegistryEntry(registryKey: RegistryKey): T? { + return currentOrDefaultRegistries + .getOrThrow(registryKey.registryRef) + .getOptional(registryKey) + .getOrNull() + ?.value() + } +} + + +val Coordinate.blockPos: BlockPos + get() = BlockPos(x, y, z) diff --git a/src/main/kotlin/util/MinecraftDispatcher.kt b/src/main/kotlin/util/MinecraftDispatcher.kt new file mode 100644 index 0000000..d1f22a9 --- /dev/null +++ b/src/main/kotlin/util/MinecraftDispatcher.kt @@ -0,0 +1,8 @@ + + +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/util/MoulConfigFragment.kt b/src/main/kotlin/util/MoulConfigFragment.kt new file mode 100644 index 0000000..28ccfd0 --- /dev/null +++ b/src/main/kotlin/util/MoulConfigFragment.kt @@ -0,0 +1,44 @@ + + +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.renderExtraLayers() + } + + override fun close() { + dismiss() + } +} diff --git a/src/main/kotlin/util/MoulConfigUtils.kt b/src/main/kotlin/util/MoulConfigUtils.kt new file mode 100644 index 0000000..51ff340 --- /dev/null +++ b/src/main/kotlin/util/MoulConfigUtils.kt @@ -0,0 +1,329 @@ +package moe.nea.firmament.util + +import io.github.notenoughupdates.moulconfig.common.IMinecraft +import io.github.notenoughupdates.moulconfig.common.MyResourceLocation +import io.github.notenoughupdates.moulconfig.gui.CloseEventListener +import io.github.notenoughupdates.moulconfig.gui.GuiComponent +import io.github.notenoughupdates.moulconfig.gui.GuiComponentWrapper +import io.github.notenoughupdates.moulconfig.gui.GuiContext +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 io.github.notenoughupdates.moulconfig.platform.ModernRenderContext +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.DrawContext +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.util.InputUtil +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 +import moe.nea.firmament.util.render.isUntranslatedGuiDrawContext + +object MoulConfigUtils { + @JvmStatic + fun main(args: Array) { + generateXSD(File("MoulConfig.xsd"), XMLUniverse.MOULCONFIG_XML_NS) + generateXSD(File("MoulConfig.Firmament.xsd"), firmUrl) + File("wrapper.xsd").writeText( + """ + + + + + + """.trimIndent() + ) + } + + 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 { + 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 { + return mapOf("progress" to true, "total" to true, "emptyColor" to true, "fillColor" to true) + } + }) + uni.registerLoader(object : XMLGuiLoader.Basic { + override fun createInstance(context: XMLContext<*>, element: Element): FirmHoverComponent { + return FirmHoverComponent( + context.getChildFragment(element), + context.getPropertyFromAttribute( + element, + QName("lines"), + List::class.java + ) as Supplier>, + 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 { + return mapOf( + "lines" to true, + "delay" to false, + ) + } + + }) + uni.registerLoader(object : XMLGuiLoader.Basic { + 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 { + return mapOf("onClick" to true, "enabled" to false, "noBackground" to false) + } + }) + uni.registerLoader(object : XMLGuiLoader.Basic { + 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 { + 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 { + 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 { + return mapOf("tick" to true) + } + }) + uni.registerLoader(object : XMLGuiLoader.Basic { + override fun createInstance(context: XMLContext<*>, element: Element): FixedComponent { + return FixedComponent( + context.getPropertyFromAttribute(element, QName("width"), Int::class.java), + context.getPropertyFromAttribute(element, QName("height"), Int::class.java), + context.getChildFragment(element) + ) + } + + override fun getName(): QName { + return QName(firmUrl, "Fixed") + } + + override fun getChildCount(): ChildCount { + return ChildCount.ONE + } + + override fun getAttributeNames(): Map { + return mapOf("width" to false, "height" to false) + } + }) + } + + fun generateXSD( + file: File, + namespace: String + ) { + val generator = XSDGenerator(universe, namespace) + generator.writeAll() + generator.dumpToFile(file) + } + + fun wrapScreen(guiContext: GuiContext, parent: Screen?, onClose: () -> Unit = {}): Screen { + return object : GuiComponentWrapper(guiContext) { + override fun close() { + if (context.onBeforeClose() == CloseEventListener.CloseAction.NO_OBJECTIONS_TO_CLOSE) { + client!!.setScreen(parent) + onClose() + } + } + } + } + + fun loadScreen(name: String, bindTo: Any, parent: Screen?): Screen { + return wrapScreen(loadGui(name, bindTo), parent) + } + + // TODO: move this utility into moulconfig (also rework guicontext into an interface so i can make this mesh better into vanilla) + fun GuiContext.adopt(element: GuiComponent) = element.foldRecursive(Unit, { comp, unit -> comp.context = this }) + + inline fun GetSetter.xmap(crossinline fromT: (T) -> R, crossinline toT: (R) -> T): GetSetter { + val outer = this + return object : GetSetter { + override fun get(): R { + return fromT(outer.get()) + } + + override fun set(newValue: R) { + outer.set(toT(newValue)) + } + } + } + + fun typeMCComponentInPlace( + component: GuiComponent, + x: Int, + y: Int, + w: Int, + h: Int, + keyboardEvent: KeyboardEvent + ): Boolean { + val immContext = createInPlaceFullContext(null, IMinecraft.instance.mouseX, IMinecraft.instance.mouseY) + if (component.keyboardEvent(keyboardEvent, immContext.translated(x, y, w, h))) + return true + if (component.context.getFocusedElement() != null) { + if (keyboardEvent is KeyboardEvent.KeyPressed + && keyboardEvent.pressed && keyboardEvent.keycode == InputUtil.GLFW_KEY_ESCAPE + ) { + component.context.setFocusedElement(null) + } + return true + } + return false + } + + fun clickMCComponentInPlace( + component: GuiComponent, + x: Int, + y: Int, + w: Int, + h: Int, + mouseX: Int, mouseY: Int, + mouseEvent: MouseEvent + ): Boolean { + val immContext = createInPlaceFullContext(null, mouseX, mouseY) + return component.mouseEvent(mouseEvent, immContext.translated(x, y, w, h)) + } + + fun createInPlaceFullContext(drawContext: DrawContext?, mouseX: Int, mouseY: Int): GuiImmediateContext { + assert(drawContext?.isUntranslatedGuiDrawContext() != false) + val context = drawContext?.let(::ModernRenderContext) + ?: IMinecraft.instance.provideTopLevelRenderContext() + val immContext = GuiImmediateContext( + context, + 0, 0, 0, 0, + mouseX, mouseY, + mouseX, mouseY, + mouseX.toFloat(), + mouseY.toFloat() + ) + return immContext + } + + fun DrawContext.drawMCComponentInPlace( + component: GuiComponent, + x: Int, + y: Int, + w: Int, + h: Int, + mouseX: Int, + mouseY: Int + ) { + val immContext = createInPlaceFullContext(this, mouseX, mouseY) + matrices.push() + matrices.translate(x.toFloat(), y.toFloat(), 0F) + component.render(immContext.translated(x, y, w, h)) + matrices.pop() + } + + + fun loadGui(name: String, bindTo: Any): GuiContext { + return GuiContext(universe.load(bindTo, MyResourceLocation("firmament", "gui/$name.xml"))) + } +} diff --git a/src/main/kotlin/util/Optionalutil.kt b/src/main/kotlin/util/Optionalutil.kt new file mode 100644 index 0000000..1cef2fe --- /dev/null +++ b/src/main/kotlin/util/Optionalutil.kt @@ -0,0 +1,5 @@ +package moe.nea.firmament.util + +import java.util.Optional + +fun T?.intoOptional(): Optional = Optional.ofNullable(this) diff --git a/src/main/kotlin/util/SBData.kt b/src/main/kotlin/util/SBData.kt new file mode 100644 index 0000000..1a4734c --- /dev/null +++ b/src/main/kotlin/util/SBData.kt @@ -0,0 +1,89 @@ +package moe.nea.firmament.util + +import java.time.ZoneId +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.ProfileSwitchEvent +import moe.nea.firmament.events.ServerConnectedEvent +import moe.nea.firmament.events.SkyblockServerUpdateEvent + +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 + get() { + // TODO: allow unfiltered access to this somehow + if (!isOnSkyblock) return null + return field + } + + /** + * Source: https://hypixel-skyblock.fandom.com/wiki/Time_Systems + */ + val hypixelTimeZone = ZoneId.of("US/Eastern") + private var hasReceivedProfile = false + var locraw: Locraw? = null + + /** + * The current server location the player is in. This will be null outside of SkyBlock. + */ + val skyblockLocation: SkyBlockIsland? get() = locraw?.skyblockLocation + val hasValidLocraw get() = locraw?.server !in listOf("limbo", null) + val isOnSkyblock get() = locraw?.gametype == "SKYBLOCK" + var profileIdCommandDebounce = TimeMark.farPast() + fun init() { + ServerConnectedEvent.subscribe("SBData:onServerConnected") { + HypixelModAPI.getInstance().subscribeToEventPacket(ClientboundLocationPacket::class.java) + } + HypixelModAPI.getInstance().createHandler(ClientboundLocationPacket::class.java) { + MC.onMainThread { + val lastLocraw = locraw + val oldProfileId = profileId + locraw = Locraw(it.serverName, + it.serverType.getOrNull()?.name?.uppercase(), + it.mode.getOrNull(), + it.map.getOrNull()) + SkyblockServerUpdateEvent.publish(SkyblockServerUpdateEvent(lastLocraw, locraw)) + if(oldProfileId != profileId) { + ProfileSwitchEvent.publish(ProfileSwitchEvent(oldProfileId, profileId)) + } + profileIdCommandDebounce = TimeMark.now() + } + } + SkyblockServerUpdateEvent.subscribe("SBData:sendProfileId") { + if (!hasReceivedProfile && isOnSkyblock && profileIdCommandDebounce.passedTime() > 10.seconds) { + profileIdCommandDebounce = TimeMark.now() + MC.sendServerCommand("profileid") + } + } + AllowChatEvent.subscribe("SBData:hideProfileSuggest") { event -> + if (event.unformattedString in profileSuggestTexts && profileIdCommandDebounce.passedTime() < 5.seconds) { + event.cancel() + } + } + ProcessChatEvent.subscribe(receivesCancelled = true, "SBData:loadProfile") { event -> + val profileMatch = profileRegex.matchEntire(event.unformattedString) + if (profileMatch != null) { + val oldProfile = profileId + try { + profileId = UUID.fromString(profileMatch.groupValues[1]) + hasReceivedProfile = true + } catch (e: IllegalArgumentException) { + profileId = null + e.printStackTrace() + } + if (oldProfile != profileId) { + ProfileSwitchEvent.publish(ProfileSwitchEvent(oldProfile, profileId)) + } + } + } + } +} diff --git a/src/main/kotlin/util/ScoreboardUtil.kt b/src/main/kotlin/util/ScoreboardUtil.kt new file mode 100644 index 0000000..0970892 --- /dev/null +++ b/src/main/kotlin/util/ScoreboardUtil.kt @@ -0,0 +1,55 @@ +package moe.nea.firmament.util + +import java.util.Optional +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 +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.TickEvent + +object ScoreboardUtil { + var scoreboardLines: List = listOf() + var simplifiedScoreboardLines: List = listOf() + + @Subscribe + fun onTick(event: TickEvent) { + scoreboardLines = getScoreboardLinesUncached() + simplifiedScoreboardLines = scoreboardLines.map { it.unformattedString } + } + + private fun getScoreboardLinesUncached(): List { + 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 { 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/util/ScreenUtil.kt b/src/main/kotlin/util/ScreenUtil.kt new file mode 100644 index 0000000..99d77fb --- /dev/null +++ b/src/main/kotlin/util/ScreenUtil.kt @@ -0,0 +1,38 @@ + + +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/util/SequenceUtil.kt b/src/main/kotlin/util/SequenceUtil.kt new file mode 100644 index 0000000..7b5bad0 --- /dev/null +++ b/src/main/kotlin/util/SequenceUtil.kt @@ -0,0 +1,11 @@ + + +package moe.nea.firmament.util + +fun T.iterate(iterator: (T) -> T?): Sequence = sequence { + var x: T? = this@iterate + while (x != null) { + yield(x) + x = iterator(x) + } +} diff --git a/src/main/kotlin/util/SkyBlockIsland.kt b/src/main/kotlin/util/SkyBlockIsland.kt new file mode 100644 index 0000000..e7f955a --- /dev/null +++ b/src/main/kotlin/util/SkyBlockIsland.kt @@ -0,0 +1,52 @@ +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 { + 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() + fun forMode(mode: String): SkyBlockIsland = allIslands.computeIfAbsent(mode, ::SkyBlockIsland) + val HUB = forMode("hub") + val DWARVEN_MINES = forMode("dwarven_mines") + val CRYSTAL_HOLLOWS = forMode("crystal_hollows") + val CRIMSON_ISLE = forMode("crimson_isle") + val PRIVATE_ISLAND = forMode("dynamic") + val RIFT = forMode("rift") + val MINESHAFT = forMode("mineshaft") + val GARDEN = forMode("garden") + val DUNGEON = forMode("dungeon") + val NIL = forMode("_") + } + + val hasCustomMining + get() = RepoManager.miningData.customMiningAreas[this]?.isSpecialMining ?: false + + val userFriendlyName + get() = RepoManager.neuRepo.constants.islands.areaNames + .getOrDefault(locrawMode, locrawMode) +} diff --git a/src/main/kotlin/util/SkyblockId.kt b/src/main/kotlin/util/SkyblockId.kt new file mode 100644 index 0000000..051ca86 --- /dev/null +++ b/src/main/kotlin/util/SkyblockId.kt @@ -0,0 +1,285 @@ +@file:UseSerializers(DashlessUUIDSerializer::class) + +package moe.nea.firmament.util + +import com.mojang.serialization.Codec +import io.github.moulberry.repo.data.NEUIngredient +import io.github.moulberry.repo.data.NEUItem +import io.github.moulberry.repo.data.Rarity +import java.time.Instant +import java.time.LocalDateTime +import java.time.format.DateTimeFormatterBuilder +import java.time.format.SignStyle +import java.time.temporal.ChronoField +import java.util.Optional +import java.util.UUID +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import kotlinx.serialization.json.Json +import kotlin.jvm.optionals.getOrNull +import net.minecraft.component.DataComponentTypes +import net.minecraft.component.type.NbtComponent +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import net.minecraft.nbt.NbtCompound +import net.minecraft.network.RegistryByteBuf +import net.minecraft.network.codec.PacketCodec +import net.minecraft.network.codec.PacketCodecs +import net.minecraft.util.Identifier +import moe.nea.firmament.repo.ExpLadders +import moe.nea.firmament.repo.ExpensiveItemCacheApi +import moe.nea.firmament.repo.ItemCache.asItemStack +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.repo.set +import moe.nea.firmament.util.collections.WeakCache +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) : Comparable { + 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 + } + + override fun compareTo(other: SkyblockId): Int { + return neuItem.compareTo(other.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) { + companion object { + fun fromSkyBlockId(skyblockId: SkyblockId): BazaarStock { + return BazaarStock(RepoManager.neuRepo.constants.bazaarStocks.getBazaarStockOrDefault(skyblockId.neuItem)) + } + } + } + + companion object { + val COINS: SkyblockId = SkyblockId(NEUIngredient.NEU_SENTINEL_COINS) + val SENTINEL_EMPTY: SkyblockId = SkyblockId(NEUIngredient.NEU_SENTINEL_EMPTY) + 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 CODEC = Codec.STRING.xmap({ SkyblockId(it) }, { it.neuItem }) + val PACKET_CODEC: PacketCodec = + PacketCodecs.STRING.xmap({ SkyblockId(it) }, { it.neuItem }) + } +} + +val NEUItem.skyblockId get() = SkyblockId(skyblockItemId) +val NEUIngredient.skyblockId get() = SkyblockId(itemId) +val SkyblockId.asBazaarStock get() = SkyblockId.BazaarStock.fromSkyBlockId(this) + +@ExpensiveItemCacheApi +fun NEUItem.guessRecipeId(): String? { + if (!skyblockItemId.contains(";")) return skyblockItemId + val item = this.asItemStack() + val (id, extraId) = skyblockItemId.split(";") + if (item.item == Items.ENCHANTED_BOOK) { + return "ENCHANTED_BOOK_${id}_${extraId}" + } + if (item.petData != null) return id + return null +} + +@Serializable +data class HypixelPetInfo( + val type: String, + val tier: Rarity, + val exp: Double = 0.0, + val candyUsed: Int = 0, + val uuid: UUID? = null, + val active: Boolean? = false, + val heldItem: String? = null, +) { + val skyblockId get() = SkyblockId("${type.uppercase()};${tier.ordinal}") // TODO: is this ordinal set up correctly? + val level get() = ExpLadders.getExpLadder(type, tier).getPetLevel(exp) +} + +private val jsonparser = Json { ignoreUnknownKeys = true } + +var ItemStack.extraAttributes: NbtCompound + set(value) { + set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(value)) + } + get() { + val customData = get(DataComponentTypes.CUSTOM_DATA) ?: run { + val component = NbtComponent.of(NbtCompound()) + set(DataComponentTypes.CUSTOM_DATA, component) + component + } + return customData.nbt + } + +fun ItemStack.modifyExtraAttributes(block: (NbtCompound) -> Unit) { + val baseNbt = get(DataComponentTypes.CUSTOM_DATA)?.copyNbt() ?: NbtCompound() + block(baseNbt) + set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(baseNbt)) +} + +val ItemStack.skyblockUUIDString: String? + get() = extraAttributes.getString("uuid").getOrNull()?.takeIf { it.isNotBlank() } + +private val timestampFormat = //"10/11/21 3:39 PM" + DateTimeFormatterBuilder().apply { + appendValue(ChronoField.MONTH_OF_YEAR, 2) + appendLiteral("/") + appendValue(ChronoField.DAY_OF_MONTH, 2) + appendLiteral("/") + appendValueReduced(ChronoField.YEAR, 2, 2, 1950) + appendLiteral(" ") + appendValue(ChronoField.HOUR_OF_AMPM, 1, 2, SignStyle.NEVER) + appendLiteral(":") + appendValue(ChronoField.MINUTE_OF_HOUR, 2) + appendLiteral(" ") + appendText(ChronoField.AMPM_OF_DAY) + }.toFormatter() +val ItemStack.timestamp + get() = + extraAttributes.getLong("timestamp").getOrNull()?.let { Instant.ofEpochMilli(it) } + ?: extraAttributes.getString("timestamp").getOrNull()?.let { + ErrorUtil.catch("Could not parse timestamp $it") { + LocalDateTime.from(timestampFormat.parse(it)).atZone(SBData.hypixelTimeZone) + .toInstant() + }.orNull() + } + +val ItemStack.skyblockUUID: UUID? + get() = skyblockUUIDString?.let { UUID.fromString(it) } + +private val petDataCache = WeakCache.memoize>("PetInfo") { + val jsonString = it.extraAttributes.getString("petInfo") + .getOrNull() + if (jsonString.isNullOrBlank()) return@memoize Optional.empty() + ErrorUtil.catch("Could not decode hypixel pet info") { + jsonparser.decodeFromString(jsonString) + } + .or { null }.intoOptional() +} + +fun ItemStack.getUpgradeStars(): Int { + return extraAttributes.getInt("upgrade_level").getOrNull()?.takeIf { it > 0 } + ?: extraAttributes.getInt("dungeon_item_level").getOrNull()?.takeIf { it > 0 } + ?: 0 +} + +@Serializable +@JvmInline +value class ReforgeId(val id: String) + +fun ItemStack.getReforgeId(): ReforgeId? { + return extraAttributes.getString("modifier").getOrNull()?.takeIf { it.isNotBlank() }?.let(::ReforgeId) +} + +val ItemStack.petData: HypixelPetInfo? + get() = petDataCache(this).getOrNull() + +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").getOrNull()) { + "", null -> { + null + } + + "PET" -> { + petData?.skyblockId ?: SkyblockId.PET_NULL + } + + "RUNE", "UNIQUE_RUNE" -> { + val runeData = extraAttributes.getCompound("runes") + .getOrNull() + val runeKind = runeData?.keys?.singleOrNull() + if (runeKind == null) SkyblockId("RUNE") + else SkyblockId("${runeKind.uppercase()}_RUNE;${runeData.getInt(runeKind).getOrNull()}") + } + + "ABICASE" -> { + SkyblockId("ABICASE_${extraAttributes.getString("model").getOrNull()?.uppercase()}") + } + + "ENCHANTED_BOOK" -> { + val enchantmentData = extraAttributes.getCompound("enchantments") + .getOrNull() + val enchantName = enchantmentData?.keys?.singleOrNull() + if (enchantName == null) SkyblockId("ENCHANTED_BOOK") + else SkyblockId("${enchantName.uppercase()};${enchantmentData.getInt(enchantName).getOrNull()}") + } + + "ATTRIBUTE_SHARD" -> { + val attributeData = extraAttributes.getCompound("attributes").getOrNull() + val attributeName = attributeData?.keys?.singleOrNull() + if (attributeName == null) SkyblockId("ATTRIBUTE_SHARD") + else SkyblockId( + "ATTRIBUTE_SHARD_${attributeName.uppercase()};${ + attributeData.getInt(attributeName).getOrNull() + }" + ) + } + + "POTION" -> { + val potionData = extraAttributes.getString("potion").getOrNull() + val potionName = extraAttributes.getString("potion_name").getOrNull() + val potionLevel = extraAttributes.getInt("potion_level").getOrNull() + val potionType = extraAttributes.getString("potion_type").getOrNull() + fun String.potionNormalize() = uppercase().replace(" ", "_") + when { + potionName != null -> SkyblockId("POTION_${potionName.potionNormalize()};$potionLevel") + potionData != null -> SkyblockId("POTION_${potionData.potionNormalize()};$potionLevel") + potionType != null -> SkyblockId("POTION_${potionType.potionNormalize()}") + else -> SkyblockId("WATER_BOTTLE") + } + } + + "PARTY_HAT_SLOTH", "PARTY_HAT_CRAB", "PARTY_HAT_CRAB_ANIMATED" -> { + val partyHatEmoji = extraAttributes.getString("party_hat_emoji").getOrNull() + val partyHatYear = extraAttributes.getInt("party_hat_year").getOrNull() + val partyHatColor = extraAttributes.getString("party_hat_color").getOrNull() + when { + partyHatEmoji != null -> SkyblockId("PARTY_HAT_SLOTH_${partyHatEmoji.uppercase()}") + partyHatYear == 2022 -> SkyblockId("PARTY_HAT_CRAB_${partyHatColor?.uppercase()}_ANIMATED") + else -> SkyblockId("PARTY_HAT_CRAB_${partyHatColor?.uppercase()}") + } + } + + "BALLOON_HAT_2024", "BALLOON_HAT_2025" -> { + val partyHatYear = extraAttributes.getInt("party_hat_year").getOrNull() + val partyHatColor = extraAttributes.getString("party_hat_color").getOrNull() + SkyblockId("BALLOON_HAT_${partyHatYear}_${partyHatColor?.uppercase()}") + } + + else -> { + SkyblockId(id.replace(":", "-")) + } + } + } + diff --git a/src/main/kotlin/util/SortedMapSerializer.kt b/src/main/kotlin/util/SortedMapSerializer.kt new file mode 100644 index 0000000..baa10ad --- /dev/null +++ b/src/main/kotlin/util/SortedMapSerializer.kt @@ -0,0 +1,25 @@ + + +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, V>(val keyDelegate: KSerializer, val valueDelegate: KSerializer) : + KSerializer> { + val mapSerializer = MapSerializer(keyDelegate, valueDelegate) + override val descriptor: SerialDescriptor + get() = mapSerializer.descriptor + + override fun deserialize(decoder: Decoder): SortedMap { + return (mapSerializer.deserialize(decoder).toSortedMap(Comparator.naturalOrder())) + } + + override fun serialize(encoder: Encoder, value: SortedMap) { + mapSerializer.serialize(encoder, value) + } +} diff --git a/src/main/kotlin/util/StringUtil.kt b/src/main/kotlin/util/StringUtil.kt new file mode 100644 index 0000000..50c5367 --- /dev/null +++ b/src/main/kotlin/util/StringUtil.kt @@ -0,0 +1,30 @@ +package moe.nea.firmament.util + +object StringUtil { + fun String.words(): Sequence { + return splitToSequence(" ") // TODO: better boundaries + } + + fun String.camelWords(): Sequence { + return splitToSequence(camelWordStart) + } + + private val camelWordStart = Regex("((?<=[a-z])(?=[A-Z]))| ") + + fun parseIntWithComma(string: String): Int { + return string.replace(",", "").toInt() + } + + fun String.title() = replaceFirstChar { it.titlecase() } + + fun Iterable.unwords() = joinToString(" ") + fun nextLexicographicStringOfSameLength(string: String): String { + val next = StringBuilder(string) + while (next.lastOrNull() == Character.MAX_VALUE) next.setLength(next.length - 1) + if (next.isEmpty()) return "" // There is no upper bound. Fall back to the empty string + val lastIdx = next.indices.last + next[lastIdx] = (next[lastIdx] + 1) + return next.toString() + } + +} diff --git a/src/main/kotlin/util/TemplateUtil.kt b/src/main/kotlin/util/TemplateUtil.kt new file mode 100644 index 0000000..f4ff37c --- /dev/null +++ b/src/main/kotlin/util/TemplateUtil.kt @@ -0,0 +1,86 @@ + + +package moe.nea.firmament.util + +import java.util.* +import kotlinx.serialization.DeserializationStrategy +import kotlinx.serialization.SerializationStrategy +import kotlinx.serialization.json.Json +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 encodeTemplate(sharePrefix: String, data: T): String = + encodeTemplate(sharePrefix, data, serializer()) + + fun encodeTemplate(sharePrefix: String, data: T, serializer: SerializationStrategy): String { + require(sharePrefix.endsWith("/")) + return intoBase64Encoded(sharePrefix + Firmament.tightJson.encodeToString(serializer, data)) + } + + inline fun maybeDecodeTemplate(sharePrefix: String, data: String): T? = + maybeDecodeTemplate(sharePrefix, data, serializer()) + + fun maybeDecodeTemplate(sharePrefix: String, data: String, serializer: DeserializationStrategy): 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(serializer, decoded.substring(sharePrefix.length)) + } catch (e: Exception) { + null + } + } + +} diff --git a/src/main/kotlin/util/TestUtil.kt b/src/main/kotlin/util/TestUtil.kt new file mode 100644 index 0000000..da8ba38 --- /dev/null +++ b/src/main/kotlin/util/TestUtil.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.util + +object TestUtil { + inline fun unlessTesting(block: () -> T): T? = if (isInTest) null else block() + @JvmField + val isInTest = + Thread.currentThread().stackTrace.any { + it.className.startsWith("org.junit.") || it.className.startsWith("io.kotest.") + } +} diff --git a/src/main/kotlin/util/TimeMark.kt b/src/main/kotlin/util/TimeMark.kt new file mode 100644 index 0000000..4a076ac --- /dev/null +++ b/src/main/kotlin/util/TimeMark.kt @@ -0,0 +1,52 @@ +package moe.nea.firmament.util + +import kotlin.time.Duration +import kotlin.time.Duration.Companion.milliseconds + +class TimeMark private constructor(private val timeMark: Long) : Comparable { + fun passedTime() = + if (timeMark == 0L) Duration.INFINITE + else (System.currentTimeMillis() - timeMark).milliseconds + + fun passedAt(fakeNow: TimeMark) = + if (timeMark == 0L) Duration.INFINITE + else (fakeNow.timeMark - 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 toString(): String { + return "https://time.is/$timeMark" + } + + override fun compareTo(other: TimeMark): Int { + return this.timeMark.compareTo(other.timeMark) + } +} diff --git a/src/main/kotlin/util/Timer.kt b/src/main/kotlin/util/Timer.kt new file mode 100644 index 0000000..6e9b467 --- /dev/null +++ b/src/main/kotlin/util/Timer.kt @@ -0,0 +1,25 @@ + + +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/util/WarpUtil.kt b/src/main/kotlin/util/WarpUtil.kt new file mode 100644 index 0000000..f733af7 --- /dev/null +++ b/src/main/kotlin/util/WarpUtil.kt @@ -0,0 +1,96 @@ +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.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.repo.RepoManager +import moe.nea.firmament.util.data.ProfileSpecificDataHolder + +object WarpUtil { + val warps: Sequence get() = RepoManager.neuRepo.constants.islands.warps + .asSequence() + .filter { it.warp !in ignoredWarps } + + val ignoredWarps = setOf("carnival", "") + + @Serializable + data class Data( + val excludedWarps: MutableSet = mutableSetOf(), + ) + + object DConfig : ProfileSpecificDataHolder(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.translatable("firmament.warp-util.no-warp-found", island.userFriendlyName)) + return + } + if (island == SBData.skyblockLocation + && sqrt(squaredDist(pos, nearestWarp)) > 1.1 * sqrt(squaredDist((MC.player ?: return).pos, nearestWarp)) + ) { + MC.sendChat(Text.translatable("firmament.warp-util.already-close", nearestWarp.warp)) + return + } + MC.sendChat(Text.translatable("firmament.warp-util.attempting-to-warp", nearestWarp.warp)) + lastWarpAttempt = TimeMark.now() + lastAttemptedWarp = nearestWarp.warp + MC.sendServerCommand("warp ${nearestWarp.warp}") + } + + @Subscribe + fun clearUnlockedWarpsCommand(event: CommandEvent.SubCommand) { + event.subcommand("clearwarps") { + thenExecute { + DConfig.data?.excludedWarps?.clear() + DConfig.markDirty() + source.sendFeedback(Text.translatable("firmament.warp-util.clear-excluded")) + } + } + } + + init { + ProcessChatEvent.subscribe("WarpUtil:processChat") { + 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.startsWith("You may now fast travel to")) { + DConfig.data?.excludedWarps?.clear() + DConfig.markDirty() + } + } + } +} diff --git a/src/main/kotlin/util/accessors/GetRectangle.kt b/src/main/kotlin/util/accessors/GetRectangle.kt new file mode 100644 index 0000000..37acfd9 --- /dev/null +++ b/src/main/kotlin/util/accessors/GetRectangle.kt @@ -0,0 +1,17 @@ + + +package moe.nea.firmament.util.accessors + +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/util/accessors/chathud.kt b/src/main/kotlin/util/accessors/chathud.kt new file mode 100644 index 0000000..effac7d --- /dev/null +++ b/src/main/kotlin/util/accessors/chathud.kt @@ -0,0 +1,8 @@ +package moe.nea.firmament.util.accessors + +import net.minecraft.client.gui.hud.ChatHud +import net.minecraft.client.gui.hud.ChatHudLine +import moe.nea.firmament.mixins.accessor.AccessorChatHud + +val ChatHud.messages: MutableList + get() = (this as AccessorChatHud).messages_firmament diff --git a/src/main/kotlin/util/asm/AsmAnnotationUtil.kt b/src/main/kotlin/util/asm/AsmAnnotationUtil.kt new file mode 100644 index 0000000..fb0e92c --- /dev/null +++ b/src/main/kotlin/util/asm/AsmAnnotationUtil.kt @@ -0,0 +1,89 @@ +package moe.nea.firmament.util.asm + +import com.google.common.base.Defaults +import java.lang.reflect.InvocationHandler +import java.lang.reflect.Method +import java.lang.reflect.Proxy +import org.objectweb.asm.Type +import org.objectweb.asm.tree.AnnotationNode + +object AsmAnnotationUtil { + class AnnotationProxy( + val originalType: Class, + val annotationNode: AnnotationNode, + ) : InvocationHandler { + val offsets = annotationNode.values.withIndex() + .chunked(2) + .map { it.first() } + .associate { (idx, value) -> value as String to idx + 1 } + + fun nestArrayType(depth: Int, comp: Class<*>): Class<*> = + if (depth == 0) comp + else java.lang.reflect.Array.newInstance(nestArrayType(depth - 1, comp), 0).javaClass + + fun unmap( + value: Any?, + comp: Class<*>, + depth: Int, + ): Any? { + value ?: return null + if (depth > 0) + return ((value as List) + .map { unmap(it, comp, depth - 1) } as java.util.List) + .toArray(java.lang.reflect.Array.newInstance(nestArrayType(depth - 1, comp), 0) as Array<*>) + if (comp.isEnum) { + comp as Class> + when (value) { + is String -> return java.lang.Enum.valueOf(comp, value) + is List<*> -> return java.lang.Enum.valueOf(comp, value[1] as String) + else -> error("Unknown enum variant $value for $comp") + } + } + when (value) { + is Type -> return Class.forName(value.className) + is AnnotationNode -> return createProxy(comp as Class, value) + is String, is Boolean, is Byte, is Double, is Int, is Float, is Long, is Short, is Char -> return value + } + error("Unknown enum variant $value for $comp") + } + + fun defaultFor(fullType: Class<*>): Any? { + if (fullType.isArray) return java.lang.reflect.Array.newInstance(fullType.componentType, 0) + if (fullType.isPrimitive) { + return Defaults.defaultValue(fullType) + } + if (fullType == String::class.java) + return "" + return null + } + + override fun invoke( + proxy: Any, + method: Method, + args: Array? + ): Any? { + val name = method.name + val ret = method.returnType + val retU = generateSequence(ret) { if (it.isArray) it.componentType else null } + .toList() + val arrayDepth = retU.size - 1 + val componentType = retU.last() + + val off = offsets[name] + if (off == null) { + return defaultFor(ret) + } + return unmap(annotationNode.values[off], componentType, arrayDepth) + } + } + + fun createProxy( + annotationClass: Class, + annotationNode: AnnotationNode + ): T { + require(Type.getType(annotationClass) == Type.getType(annotationNode.desc)) + return Proxy.newProxyInstance(javaClass.classLoader, + arrayOf(annotationClass), + AnnotationProxy(annotationClass, annotationNode)) as T + } +} diff --git a/src/main/kotlin/util/assertions.kt b/src/main/kotlin/util/assertions.kt new file mode 100644 index 0000000..86982be --- /dev/null +++ b/src/main/kotlin/util/assertions.kt @@ -0,0 +1,35 @@ +@file:OptIn(ExperimentalContracts::class) + +package moe.nea.firmament.util + +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +/** + * Less aggressive version of `require(obj != null)`, which fails in devenv but continues at runtime. + */ +inline fun assertNotNullOr(obj: T?, message: String? = null, block: () -> T): T { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + 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) { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + assert(condition) + if (!condition) block() +} + + diff --git a/src/main/kotlin/util/async/input.kt b/src/main/kotlin/util/async/input.kt new file mode 100644 index 0000000..2c546ba --- /dev/null +++ b/src/main/kotlin/util/async/input.kt @@ -0,0 +1,89 @@ +package moe.nea.firmament.util.async + +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.TextComponent +import io.github.notenoughupdates.moulconfig.gui.component.TextFieldComponent +import io.github.notenoughupdates.moulconfig.observer.GetSetter +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.resume +import net.minecraft.client.gui.screen.Screen +import moe.nea.firmament.events.HandledScreenKeyPressedEvent +import moe.nea.firmament.gui.FirmButtonComponent +import moe.nea.firmament.keybindings.IKeyBinding +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.MoulConfigUtils +import moe.nea.firmament.util.ScreenUtil + +private object InputHandler { + data class KeyInputContinuation(val keybind: IKeyBinding, val onContinue: () -> Unit) + + private val activeContinuations = mutableListOf() + + fun registerContinuation(keyInputContinuation: KeyInputContinuation): () -> Unit { + synchronized(InputHandler) { + activeContinuations.add(keyInputContinuation) + } + return { + synchronized(this) { + activeContinuations.remove(keyInputContinuation) + } + } + } + + init { + HandledScreenKeyPressedEvent.subscribe("Input:resumeAfterInput") { 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() + } +} + + +fun createPromptScreenGuiComponent(suggestion: String, prompt: String, action: Runnable) = (run { + val text = GetSetter.floating(suggestion) + GuiContext( + CenterComponent( + PanelComponent( + ColumnComponent( + TextFieldComponent(text, 120), + FirmButtonComponent(TextComponent(prompt), action = action) + ) + ) + ) + ) to text +}) + +suspend fun waitForTextInput(suggestion: String, prompt: String) = + suspendCancellableCoroutine { cont -> + lateinit var screen: Screen + lateinit var text: GetSetter + val action = { + if (MC.screen === screen) + MC.screen = null + // TODO: should this exit + cont.resume(text.get()) + } + val (gui, text_) = createPromptScreenGuiComponent(suggestion, prompt, action) + text = text_ + screen = MoulConfigUtils.wrapScreen(gui, null, onClose = action) + ScreenUtil.setScreenLater(screen) + cont.invokeOnCancellation { + action() + } + } diff --git a/src/main/kotlin/util/collections/InstanceList.kt b/src/main/kotlin/util/collections/InstanceList.kt new file mode 100644 index 0000000..fd8c786 --- /dev/null +++ b/src/main/kotlin/util/collections/InstanceList.kt @@ -0,0 +1,57 @@ +package moe.nea.firmament.util.collections + +import java.lang.ref.ReferenceQueue +import java.lang.ref.WeakReference + +class InstanceList(val name: String) { + val queue = object : ReferenceQueue() {} + val set = mutableSetOf() + + val size: Int + get() { + clearOldReferences() + return set.size + } + + fun clearOldReferences() { + while (true) { + val reference = queue.poll() ?: break + set.remove(reference) + } + } + + fun getAll(): List { + clearOldReferences() + return set.mapNotNull { it.get() } + } + + fun add(t: T) { + set.add(Ref(t)) + } + + init { + if (init) + allInstances.add(this) + } + + inner class Ref(referent: T) : WeakReference(referent) { + val hashCode = System.identityHashCode(referent) + override fun equals(other: Any?): Boolean { + return other is InstanceList<*>.Ref && hashCode == other.hashCode && get() === other.get() + } + + override fun hashCode(): Int { + return hashCode + } + } + + companion object { + private var init = false + val allInstances = InstanceList>("InstanceLists") + + init { + init = true + allInstances.add(allInstances) + } + } +} diff --git a/src/main/kotlin/util/collections/MutableMapWithMaxSize.kt b/src/main/kotlin/util/collections/MutableMapWithMaxSize.kt new file mode 100644 index 0000000..218bc55 --- /dev/null +++ b/src/main/kotlin/util/collections/MutableMapWithMaxSize.kt @@ -0,0 +1,40 @@ + +package moe.nea.firmament.util.collections + +import moe.nea.firmament.util.IdentityCharacteristics + +fun mutableMapWithMaxSize(maxSize: Int): MutableMap = object : LinkedHashMap() { + override fun removeEldestEntry(eldest: MutableMap.MutableEntry): Boolean { + return size > maxSize + } +} + +fun ((T) -> R).memoizeIdentity(maxCacheSize: Int): (T) -> R { + val memoized = { it: IdentityCharacteristics -> + 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 MutableMap.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).memoize(maxCacheSize: Int): (T) -> R { + val map = mutableMapWithMaxSize(maxCacheSize) + return { + map.computeNullableFunction(it) { this@memoize(it) } + } +} diff --git a/src/main/kotlin/util/collections/RangeUtil.kt b/src/main/kotlin/util/collections/RangeUtil.kt new file mode 100644 index 0000000..a7029ac --- /dev/null +++ b/src/main/kotlin/util/collections/RangeUtil.kt @@ -0,0 +1,40 @@ +package moe.nea.firmament.util.collections + +import kotlin.math.floor + +val ClosedFloatingPointRange.centre get() = (endInclusive + start) / 2 + +fun ClosedFloatingPointRange.nonNegligibleSubSectionsAlignedWith( + interval: Float +): Iterable { + require(interval.isFinite()) + val range = this + return object : Iterable { + override fun iterator(): Iterator { + return object : FloatIterator() { + var polledValue: Float = range.start + var lastValue: Float = polledValue + + override fun nextFloat(): Float { + if (!hasNext()) throw NoSuchElementException() + lastValue = polledValue + polledValue = Float.NaN + return lastValue + } + + override fun hasNext(): Boolean { + if (!polledValue.isNaN()) { + return true + } + if (lastValue == range.endInclusive) + return false + polledValue = (floor(lastValue / interval) + 1) * interval + if (polledValue > range.endInclusive) { + polledValue = range.endInclusive + } + return true + } + } + } + } +} diff --git a/src/main/kotlin/util/collections/WeakCache.kt b/src/main/kotlin/util/collections/WeakCache.kt new file mode 100644 index 0000000..4a48c63 --- /dev/null +++ b/src/main/kotlin/util/collections/WeakCache.kt @@ -0,0 +1,116 @@ +package moe.nea.firmament.util.collections + +import java.lang.ref.ReferenceQueue +import java.lang.ref.WeakReference +import moe.nea.firmament.features.debug.DebugLogger + +/** + * Cache class that uses [WeakReferences][WeakReference] to only cache values while there is still a life reference to + * the key. Each key can have additional extra data that is used to look up values. That extra data is not required to + * be a life reference. The main Key is compared using strict reference equality. This map is not synchronized. + */ +open class WeakCache(val name: String) { + private val queue = object : ReferenceQueue() {} + private val map = mutableMapOf() + + val size: Int + get() { + clearOldReferences() + return map.size + } + + fun clearOldReferences() { + var successCount = 0 + var totalCount = 0 + while (true) { + val reference = queue.poll() as WeakCache<*, *, *>.Ref? ?: break + totalCount++ + if (reference.shouldBeEvicted() && map.remove(reference) != null) + successCount++ + } + if (totalCount > 0) + logger.log("Cleared $successCount/$totalCount references from queue") + } + + open fun mkRef(key: Key, extraData: ExtraKey): Ref { + return Ref(key, extraData) + } + + fun get(key: Key, extraData: ExtraKey): Value? { + clearOldReferences() + return map[mkRef(key, extraData)] + } + + fun put(key: Key, extraData: ExtraKey, value: Value) { + clearOldReferences() + map[mkRef(key, extraData)] = value + } + + fun getOrPut(key: Key, extraData: ExtraKey, value: (Key, ExtraKey) -> Value): Value { + clearOldReferences() + return map.getOrPut(mkRef(key, extraData)) { value(key, extraData) } + } + + fun clear() { + map.clear() + } + + init { + allInstances.add(this) + } + + companion object { + val allInstances = InstanceList>("WeakCaches") + private val logger = DebugLogger("WeakCache") + fun memoize(name: String, function: (Key) -> Value): + CacheFunction.NoExtraData { + return CacheFunction.NoExtraData(WeakCache(name), function) + } + + fun dontMemoize(name: String, function: (Key, ExtraKey) -> Value) = function + fun memoize(name: String, function: (Key, ExtraKey) -> Value): + CacheFunction.WithExtraData { + return CacheFunction.WithExtraData(WeakCache(name), function) + } + } + + open inner class Ref( + weakInstance: Key, + val extraData: ExtraKey, + ) : WeakReference(weakInstance, queue) { + open fun shouldBeEvicted() = true + val hashCode = System.identityHashCode(weakInstance) * 31 + extraData.hashCode() + override fun equals(other: Any?): Boolean { + if (other !is WeakCache<*, *, *>.Ref) return false + return other.hashCode == this.hashCode + && other.get() === this.get() + && other.extraData == this.extraData + } + + override fun hashCode(): Int { + return hashCode + } + } + + interface CacheFunction { + val cache: WeakCache<*, *, *> + + data class NoExtraData( + override val cache: WeakCache, + val wrapped: (Key) -> Value, + ) : CacheFunction, (Key) -> Value { + override fun invoke(p1: Key): Value { + return cache.getOrPut(p1, Unit, { a, _ -> wrapped(a) }) + } + } + + data class WithExtraData( + override val cache: WeakCache, + val wrapped: (Key, ExtraKey) -> Value, + ) : CacheFunction, (Key, ExtraKey) -> Value { + override fun invoke(p1: Key, p2: ExtraKey): Value { + return cache.getOrPut(p1, p2, wrapped) + } + } + } +} diff --git a/src/main/kotlin/util/collections/listutil.kt b/src/main/kotlin/util/collections/listutil.kt new file mode 100644 index 0000000..7f85a30 --- /dev/null +++ b/src/main/kotlin/util/collections/listutil.kt @@ -0,0 +1,9 @@ + +package moe.nea.firmament.util.collections + +fun List.lastNotNullOfOrNull(func: (T) -> R?): R? { + for (i in indices.reversed()) { + return func(this[i]) ?: continue + } + return null +} diff --git a/src/main/kotlin/util/colorconversion.kt b/src/main/kotlin/util/colorconversion.kt new file mode 100644 index 0000000..d7a5dad --- /dev/null +++ b/src/main/kotlin/util/colorconversion.kt @@ -0,0 +1,13 @@ + + +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/util/compatloader/CompatLoader.kt b/src/main/kotlin/util/compatloader/CompatLoader.kt new file mode 100644 index 0000000..d1073af --- /dev/null +++ b/src/main/kotlin/util/compatloader/CompatLoader.kt @@ -0,0 +1,50 @@ +package moe.nea.firmament.util.compatloader + +import java.util.ServiceLoader +import net.fabricmc.loader.api.FabricLoader +import kotlin.reflect.KClass +import kotlin.streams.asSequence +import moe.nea.firmament.Firmament + +open class CompatLoader(val kClass: Class) { + constructor(kClass: KClass) : this(kClass.java) + + val loader: ServiceLoader = ServiceLoader.load(kClass) + val allValidInstances by lazy { + loader.reload() + loader.stream() + .asSequence() + .filter { provider -> + runCatching { + shouldLoad(provider.type()) + }.getOrElse { + Firmament.logger.error("Could not determine whether to load a ${kClass.name} subclass", it) + false + } + } + .mapNotNull { provider -> + runCatching { + provider.get() + }.getOrElse { + Firmament.logger.error( + "Could not load desired instance ${provider.type().name} for ${kClass.name}", + it) + null + } + } + .toList() + } + val singleInstance by lazy { allValidInstances.singleOrNull() } + + open fun shouldLoad(type: Class): Boolean { + return checkRequiredModsPresent(type) + } + + fun checkRequiredModsPresent(type: Class<*>): Boolean { + val requiredMods = type.getAnnotationsByType(RequireMod::class.java) + return requiredMods.all { FabricLoader.getInstance().isModLoaded(it.modId) } + } + + @Repeatable + annotation class RequireMod(val modId: String) +} diff --git a/src/main/kotlin/util/compatloader/CompatMeta.kt b/src/main/kotlin/util/compatloader/CompatMeta.kt new file mode 100644 index 0000000..cf63645 --- /dev/null +++ b/src/main/kotlin/util/compatloader/CompatMeta.kt @@ -0,0 +1,48 @@ +package moe.nea.firmament.util.compatloader + +import java.util.ServiceLoader +import moe.nea.firmament.events.subscription.SubscriptionList +import moe.nea.firmament.init.AutoDiscoveryPlugin +import moe.nea.firmament.util.ErrorUtil + +/** + * Declares the compat meta interface for the current source set. + * This is used by [CompatLoader], [SubscriptionList], and [AutoDiscoveryPlugin]. Annotate a [ICompatMeta] object with + * this. + */ +annotation class CompatMeta + +interface ICompatMetaGen { + fun owns(className: String): Boolean + val meta: ICompatMeta +} + +interface ICompatMeta { + fun shouldLoad(): Boolean + + companion object { + val allMetas = ServiceLoader + .load(ICompatMetaGen::class.java) + .toList() + + fun shouldLoad(className: String): Boolean { + // TODO: replace this with a more performant package lookup + val meta = if (ErrorUtil.aggressiveErrors) { + val fittingMetas = allMetas.filter { it.owns(className) } + require(fittingMetas.size == 1) { "Orphaned or duplicate owned class $className (${fittingMetas.map { it.meta }}). Consider adding a @CompatMeta object." } + fittingMetas.single() + } else { + allMetas.firstOrNull { it.owns(className) } + } + return meta?.meta?.shouldLoad() ?: true + } + } +} + +object CompatHelper { + fun isOwnedByPackage(className: String, vararg packages: String): Boolean { + // TODO: create package lookup structure once + val packageName = className.substringBeforeLast('.') + return packageName in packages + } +} diff --git a/src/main/kotlin/util/customgui/CoordRememberingSlot.kt b/src/main/kotlin/util/customgui/CoordRememberingSlot.kt new file mode 100644 index 0000000..c61c711 --- /dev/null +++ b/src/main/kotlin/util/customgui/CoordRememberingSlot.kt @@ -0,0 +1,14 @@ + +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/util/customgui/CustomGui.kt b/src/main/kotlin/util/customgui/CustomGui.kt new file mode 100644 index 0000000..35c60ac --- /dev/null +++ b/src/main/kotlin/util/customgui/CustomGui.kt @@ -0,0 +1,91 @@ +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 + + 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 + } + + open fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean { + return false + } + + open fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, deltaX: Double, deltaY: Double): Boolean { + return false + } + + open fun keyPressed(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return false + } + + open fun charTyped(chr: Char, modifiers: Int): Boolean { + return false + } + + open fun keyReleased(keyCode: Int, scanCode: Int, modifiers: Int): Boolean { + return false + } +} diff --git a/src/main/kotlin/util/customgui/HasCustomGui.kt b/src/main/kotlin/util/customgui/HasCustomGui.kt new file mode 100644 index 0000000..edead2e --- /dev/null +++ b/src/main/kotlin/util/customgui/HasCustomGui.kt @@ -0,0 +1,17 @@ + +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.customGui: CustomGui? + get() = (this as HasCustomGui).getCustomGui_Firmament() + set(value) { + (this as HasCustomGui).setCustomGui_Firmament(value) + } + diff --git a/src/main/kotlin/util/data/DataHolder.kt b/src/main/kotlin/util/data/DataHolder.kt new file mode 100644 index 0000000..21a6014 --- /dev/null +++ b/src/main/kotlin/util/data/DataHolder.kt @@ -0,0 +1,62 @@ + + +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( + val serializer: KSerializer, + val name: String, + val default: () -> T +) : IDataHolder { + + + 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/util/data/IDataHolder.kt b/src/main/kotlin/util/data/IDataHolder.kt new file mode 100644 index 0000000..1e9ba98 --- /dev/null +++ b/src/main/kotlin/util/data/IDataHolder.kt @@ -0,0 +1,71 @@ +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.text.Text +import moe.nea.firmament.Firmament +import moe.nea.firmament.events.ScreenChangeEvent +import moe.nea.firmament.util.MC + +interface IDataHolder { + companion object { + internal var badLoads: MutableList = CopyOnWriteArrayList() + private val allConfigs: MutableMap>, IDataHolder<*>> = mutableMapOf() + private val dirty: MutableSet>> = mutableSetOf() + + internal fun , K> putDataHolder(kClass: KClass, inst: IDataHolder) { + allConfigs[kClass] = inst + } + + fun , K> markDirty(kClass: KClass) { + 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() { + if (badLoads.isNotEmpty()) { + MC.sendChat( + Text.literal( + "The following configs have been reset: ${badLoads.joinToString(", ")}. " + + "This can be intentional, but probably isn't." + ) + ) + badLoads.clear() + } + } + + fun registerEvents() { + ScreenChangeEvent.subscribe("IDataHolder:saveOnScreenChange") { event -> + performSaves() + warnForResetConfigs() + } + ClientLifecycleEvents.CLIENT_STOPPING.register(ClientLifecycleEvents.ClientStopping { + performSaves() + }) + } + + } + + val data: T + fun save() + fun markDirty() + fun load() +} diff --git a/src/main/kotlin/util/data/MultiFileDataHolder.kt b/src/main/kotlin/util/data/MultiFileDataHolder.kt new file mode 100644 index 0000000..94c6f05 --- /dev/null +++ b/src/main/kotlin/util/data/MultiFileDataHolder.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.util.data + +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 + +abstract class MultiFileDataHolder( + val dataSerializer: KSerializer, + val configName: String +) { // TODO: abstract this + ProfileSpecificDataHolder + val configDirectory = Firmament.CONFIG_DIR.resolve(configName) + private var allData = readValues() + protected fun readValues(): MutableMap { + if (!configDirectory.exists()) { + configDirectory.createDirectories() + } + val profileFiles = configDirectory.listDirectoryEntries() + return profileFiles + .filter { it.extension == "json" } + .mapNotNull { + try { + 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 multi file data holder $it ($configName). This will reset that profiles config.", + e + ) + null + } + }.toMap().toMutableMap() + } + + fun save() { + if (!configDirectory.exists()) { + configDirectory.createDirectories() + } + val c = allData + 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)) + } + } + + fun list(): Map = allData + val validPathRegex = "[a-zA-Z0-9_][a-zA-Z0-9\\-_.]*".toPattern() + fun insert(name: String, value: T) { + require(validPathRegex.matcher(name).matches()) { "Not a valid name: $name" } + allData[name] = value + } +} diff --git a/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt new file mode 100644 index 0000000..1cd4f22 --- /dev/null +++ b/src/main/kotlin/util/data/ProfileSpecificDataHolder.kt @@ -0,0 +1,84 @@ + + +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( + private val dataSerializer: KSerializer, + val configName: String, + private val configDefault: () -> S +) : IDataHolder { + + var allConfigs: MutableMap + + 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 { + 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/util/json/BlockPosSerializer.kt b/src/main/kotlin/util/json/BlockPosSerializer.kt new file mode 100644 index 0000000..144b0a0 --- /dev/null +++ b/src/main/kotlin/util/json/BlockPosSerializer.kt @@ -0,0 +1,25 @@ +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 { + val delegate = serializer>() + + 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/util/json/DashlessUUIDSerializer.kt b/src/main/kotlin/util/json/DashlessUUIDSerializer.kt new file mode 100644 index 0000000..6bafebe --- /dev/null +++ b/src/main/kotlin/util/json/DashlessUUIDSerializer.kt @@ -0,0 +1,27 @@ + + +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 +import moe.nea.firmament.util.parsePotentiallyDashlessUUID + +object DashlessUUIDSerializer : KSerializer { + override val descriptor: SerialDescriptor = + PrimitiveSerialDescriptor("DashlessUUIDSerializer", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): UUID { + val str = decoder.decodeString() + return parsePotentiallyDashlessUUID(str) + } + + override fun serialize(encoder: Encoder, value: UUID) { + encoder.encodeString(value.toString().replace("-", "")) + } +} diff --git a/src/main/kotlin/util/json/FirmCodecs.kt b/src/main/kotlin/util/json/FirmCodecs.kt new file mode 100644 index 0000000..c0863bc --- /dev/null +++ b/src/main/kotlin/util/json/FirmCodecs.kt @@ -0,0 +1,20 @@ +package moe.nea.firmament.util.json + +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.Lifecycle +import com.mojang.util.UndashedUuid +import net.minecraft.util.Uuids + +object FirmCodecs { + @JvmField + val UUID_LENIENT_PREFER_INT_STREAM = Codec.withAlternative(Uuids.INT_STREAM_CODEC, Codec.STRING.comapFlatMap( + { + try { + DataResult.success(UndashedUuid.fromStringLenient(it), Lifecycle.stable()) + } catch (ex: IllegalArgumentException) { + DataResult.error { "Invalid UUID $it: ${ex.message}" } + } + }, + UndashedUuid::toString)) +} diff --git a/src/main/kotlin/util/json/InstantAsLongSerializer.kt b/src/main/kotlin/util/json/InstantAsLongSerializer.kt new file mode 100644 index 0000000..51b5f0a --- /dev/null +++ b/src/main/kotlin/util/json/InstantAsLongSerializer.kt @@ -0,0 +1,22 @@ + + +package moe.nea.firmament.util.json + +import java.time.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 { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("InstantAsLongSerializer", PrimitiveKind.LONG) + override fun deserialize(decoder: Decoder): Instant { + return Instant.ofEpochMilli(decoder.decodeLong()) + } + + override fun serialize(encoder: Encoder, value: Instant) { + encoder.encodeLong(value.toEpochMilli()) + } +} diff --git a/src/main/kotlin/util/json/KJsonOps.kt b/src/main/kotlin/util/json/KJsonOps.kt new file mode 100644 index 0000000..404ea5e --- /dev/null +++ b/src/main/kotlin/util/json/KJsonOps.kt @@ -0,0 +1,131 @@ +package moe.nea.firmament.util.json + +import com.google.gson.internal.LazilyParsedNumber +import com.mojang.datafixers.util.Pair +import com.mojang.serialization.DataResult +import com.mojang.serialization.DynamicOps +import java.util.stream.Stream +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonNull +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.boolean +import kotlinx.serialization.json.booleanOrNull +import kotlin.streams.asSequence + +class KJsonOps : DynamicOps { + companion object { + val INSTANCE = KJsonOps() + } + + override fun empty(): JsonElement { + return JsonNull + } + + override fun createNumeric(num: Number): JsonElement { + return JsonPrimitive(num) + } + + override fun createString(str: String): JsonElement { + return JsonPrimitive(str) + } + + override fun remove(input: JsonElement, key: String): JsonElement { + if (input is JsonObject) { + return JsonObject(input.filter { it.key != key }) + } else { + return input + } + } + + override fun createList(stream: Stream): JsonElement { + return JsonArray(stream.toList()) + } + + override fun getStream(input: JsonElement): DataResult> { + if (input is JsonArray) + return DataResult.success(input.stream()) + return DataResult.error { "Not a json array: $input" } + } + + override fun createMap(map: Stream>): JsonElement { + return JsonObject(map.asSequence() + .map { ((it.first as JsonPrimitive).content) to it.second } + .toMap()) + } + + override fun getMapValues(input: JsonElement): DataResult>> { + if (input is JsonObject) { + return DataResult.success(input.entries.stream().map { Pair.of(createString(it.key), it.value) }) + } + return DataResult.error { "Not a JSON object: $input" } + } + + override fun mergeToMap(map: JsonElement, key: JsonElement, value: JsonElement): DataResult { + if (key !is JsonPrimitive || key.isString) { + return DataResult.error { "key is not a string: $key" } + } + val jKey = key.content + val extra = mapOf(jKey to value) + if (map == empty()) { + return DataResult.success(JsonObject(extra)) + } + if (map is JsonObject) { + return DataResult.success(JsonObject(map + extra)) + } + return DataResult.error { "mergeToMap called with not a map: $map" } + } + + override fun mergeToList(list: JsonElement, value: JsonElement): DataResult { + if (list == empty()) + return DataResult.success(JsonArray(listOf(value))) + if (list is JsonArray) { + return DataResult.success(JsonArray(list + value)) + } + return DataResult.error { "mergeToList called with not a list: $list" } + } + + override fun getStringValue(input: JsonElement): DataResult { + if (input is JsonPrimitive && input.isString) { + return DataResult.success(input.content) + } + return DataResult.error { "Not a string: $input" } + } + + override fun getNumberValue(input: JsonElement): DataResult { + if (input is JsonPrimitive && !input.isString && input.booleanOrNull == null) + return DataResult.success(LazilyParsedNumber(input.content)) + return DataResult.error { "not a number: $input" } + } + + override fun createBoolean(value: Boolean): JsonElement { + return JsonPrimitive(value) + } + + override fun getBooleanValue(input: JsonElement): DataResult { + if (input is JsonPrimitive) { + if (input.booleanOrNull != null) + return DataResult.success(input.boolean) + return super.getBooleanValue(input) + } + return DataResult.error { "Not a boolean: $input" } + } + + override fun convertTo(output: DynamicOps, input: JsonElement): U { + if (input is JsonObject) + return output.createMap( + input.entries.stream().map { Pair.of(output.createString(it.key), convertTo(output, it.value)) }) + if (input is JsonArray) + return output.createList(input.stream().map { convertTo(output, it) }) + if (input is JsonNull) + return output.empty() + if (input is JsonPrimitive) { + if (input.isString) + return output.createString(input.content) + if (input.booleanOrNull != null) + return output.createBoolean(input.boolean) + } + error("Unknown json value: $input") + } +} diff --git a/src/main/kotlin/util/json/KJsonUtils.kt b/src/main/kotlin/util/json/KJsonUtils.kt new file mode 100644 index 0000000..b15119b --- /dev/null +++ b/src/main/kotlin/util/json/KJsonUtils.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.util.json + +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonPrimitive + +fun List.asJsonArray(): JsonArray { + return JsonArray(this) +} + +fun Iterable.toJsonArray(): JsonArray = map { JsonPrimitive(it) }.asJsonArray() diff --git a/src/main/kotlin/util/json/SingletonSerializableList.kt b/src/main/kotlin/util/json/SingletonSerializableList.kt new file mode 100644 index 0000000..aa543d6 --- /dev/null +++ b/src/main/kotlin/util/json/SingletonSerializableList.kt @@ -0,0 +1,31 @@ + +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(val child: KSerializer) : KSerializer> { + override val descriptor: SerialDescriptor + get() = JsonElement.serializer().descriptor + + override fun deserialize(decoder: Decoder): List { + 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) { + ListSerializer(child).serialize(encoder, value) + } +} diff --git a/src/main/kotlin/util/math/GChainReconciliation.kt b/src/main/kotlin/util/math/GChainReconciliation.kt new file mode 100644 index 0000000..37998d5 --- /dev/null +++ b/src/main/kotlin/util/math/GChainReconciliation.kt @@ -0,0 +1,102 @@ +package moe.nea.firmament.util.math + +import kotlin.math.min + +/** + * Algorithm for (sort of) cheap reconciliation of two cycles with missing frames. + */ +object GChainReconciliation { + // Step one: Find the most common element and shift the arrays until it is at the start in both (this could be just rotating until minimal levenshtein distance or smth. that would be way better for cycles with duplicates, but i do not want to implement levenshtein as well) + // Step two: Find the first different element. + // Step three: Find the next index of both of the elements. + // Step four: Insert the element that is further away. + + fun Iterable.frequencies(): Map { + val acc = mutableMapOf() + for (t in this) { + acc.compute(t, { _, old -> (old ?: 0) + 1 }) + } + return acc + } + + fun findMostCommonlySharedElement( + leftChain: List, + rightChain: List, + ): T { + val lf = leftChain.frequencies() + val rf = rightChain.frequencies() + val mostCommonlySharedElement = lf.maxByOrNull { min(it.value, rf[it.key] ?: 0) }?.key + if (mostCommonlySharedElement == null || mostCommonlySharedElement !in rf) + error("Could not find a shared element") + return mostCommonlySharedElement + } + + fun List.getMod(index: Int): T { + return this[index.mod(size)] + } + + fun List.rotated(offset: Int): List { + val newList = mutableListOf() + for (index in indices) { + newList.add(getMod(index - offset)) + } + return newList + } + + fun shiftToFront(list: List, element: T): List { + val shiftDistance = list.indexOf(element) + require(shiftDistance >= 0) + return list.rotated(-shiftDistance) + } + + fun List.indexOfOrMaxInt(element: T): Int = indexOf(element).takeUnless { it < 0 } ?: Int.MAX_VALUE + + fun reconcileCycles( + leftChain: List, + rightChain: List, + ): List { + val mostCommonElement = findMostCommonlySharedElement(leftChain, rightChain) + val left = shiftToFront(leftChain, mostCommonElement).toMutableList() + val right = shiftToFront(rightChain, mostCommonElement).toMutableList() + + var index = 0 + while (index < left.size && index < right.size) { + val leftEl = left[index] + val rightEl = right[index] + if (leftEl == rightEl) { + index++ + continue + } + val nextLeftInRight = right.subList(index, right.size) + .indexOfOrMaxInt(leftEl) + + val nextRightInLeft = left.subList(index, left.size) + .indexOfOrMaxInt(rightEl) + if (nextLeftInRight < nextRightInLeft) { + left.add(index, rightEl) + } else if (nextRightInLeft < nextLeftInRight) { + right.add(index, leftEl) + } else { + index++ + } + } + return if (left.size < right.size) right else left + } + + fun isValidCycle(longList: List, cycle: List): Boolean { + for ((i, value) in longList.withIndex()) { + if (cycle.getMod(i) != value) + return false + } + return true + } + + fun List.shortenCycle(): List { + for (i in (1.. register( + id: String, + builderOperator: (ComponentType.Builder) -> Unit + ): ComponentType { + return Registry.register( + Registries.DATA_COMPONENT_TYPE, + Firmament.identifier(id), + ComponentType.builder().also(builderOperator) + .build() + ) + } + + fun errorCodec(message: String): PacketCodec = + object : PacketCodec { + override fun decode(buf: ByteBuf?): T? { + error(message) + } + + override fun encode(buf: ByteBuf?, value: T?) { + error(message) + } + } + + fun > B.neverEncode(message: String = "This element should never be encoded or decoded"): B { + packetCodec(errorCodec(message)) + codec(null) + return this + } + + val IS_BROKEN = register( + "is_broken" + ) { + it.codec(Codec.BOOL.fieldOf("is_broken").codec()) + } + + val CUSTOM_MINING_BLOCK_DATA = register("custom_mining_block") { + it.neverEncode() + } + + +} diff --git a/src/main/kotlin/util/mc/InitLevel.kt b/src/main/kotlin/util/mc/InitLevel.kt new file mode 100644 index 0000000..2c3eedb --- /dev/null +++ b/src/main/kotlin/util/mc/InitLevel.kt @@ -0,0 +1,25 @@ +package moe.nea.firmament.util.mc + +enum class InitLevel { + STARTING, + MC_INIT, + RENDER_INIT, + RENDER, + MAIN_MENU, + ; + + companion object { + var initLevel = InitLevel.STARTING + private set + + @JvmStatic + fun isAtLeast(wantedLevel: InitLevel): Boolean = initLevel >= wantedLevel + + @JvmStatic + fun bump(nextLevel: InitLevel) { + if (nextLevel.ordinal != initLevel.ordinal + 1) + error("Cannot bump initLevel $nextLevel from $initLevel") + initLevel = nextLevel + } + } +} diff --git a/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt b/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt new file mode 100644 index 0000000..e546fd3 --- /dev/null +++ b/src/main/kotlin/util/mc/IntrospectableItemModelManager.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.util.Identifier + +interface IntrospectableItemModelManager { + fun hasModel_firmament(identifier: Identifier): Boolean +} diff --git a/src/main/kotlin/util/mc/InventoryUtil.kt b/src/main/kotlin/util/mc/InventoryUtil.kt new file mode 100644 index 0000000..74f7b9f --- /dev/null +++ b/src/main/kotlin/util/mc/InventoryUtil.kt @@ -0,0 +1,28 @@ +package moe.nea.firmament.util.mc + +import java.util.Spliterator +import java.util.Spliterators +import net.minecraft.inventory.Inventory +import net.minecraft.item.ItemStack + +val Inventory.indices get() = 0 until size() +val Inventory.iterableView + get() = object : Iterable { + override fun spliterator(): Spliterator { + return Spliterators.spliterator(iterator(), size().toLong(), 0) + } + + override fun iterator(): Iterator { + return object : Iterator { + var i = 0 + override fun hasNext(): Boolean { + return i < size() + } + + override fun next(): ItemStack { + if (!hasNext()) throw NoSuchElementException() + return getStack(i++) + } + } + } + } diff --git a/src/main/kotlin/util/mc/ItemUtil.kt b/src/main/kotlin/util/mc/ItemUtil.kt new file mode 100644 index 0000000..13519cf --- /dev/null +++ b/src/main/kotlin/util/mc/ItemUtil.kt @@ -0,0 +1,20 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.item.ItemStack +import net.minecraft.text.Text + +fun ItemStack.appendLore(args: List) { + if (args.isEmpty()) return + modifyLore { + val loreList = loreAccordingToNbt.toMutableList() + for (arg in args) { + loreList.add(arg) + } + loreList + } +} + +fun ItemStack.modifyLore(update: (List) -> List) { + val loreList = loreAccordingToNbt + loreAccordingToNbt = update(loreList) +} diff --git a/src/main/kotlin/util/mc/MCTabListAPI.kt b/src/main/kotlin/util/mc/MCTabListAPI.kt new file mode 100644 index 0000000..66bdd55 --- /dev/null +++ b/src/main/kotlin/util/mc/MCTabListAPI.kt @@ -0,0 +1,96 @@ +package moe.nea.firmament.util.mc + +import com.mojang.serialization.Codec +import com.mojang.serialization.codecs.RecordCodecBuilder +import java.util.Optional +import org.jetbrains.annotations.TestOnly +import net.minecraft.client.gui.hud.PlayerListHud +import net.minecraft.nbt.NbtOps +import net.minecraft.scoreboard.Team +import net.minecraft.text.Text +import net.minecraft.text.TextCodecs +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.commands.thenExecute +import moe.nea.firmament.commands.thenLiteral +import moe.nea.firmament.events.CommandEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.features.debug.DeveloperFeatures +import moe.nea.firmament.features.debug.ExportedTestConstantMeta +import moe.nea.firmament.mixins.accessor.AccessorPlayerListHud +import moe.nea.firmament.util.ClipboardUtils +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.intoOptional +import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString + +object MCTabListAPI { + + fun PlayerListHud.cast() = this as AccessorPlayerListHud + + @Subscribe + fun onTick(event: TickEvent) { + _currentTabList = null + } + + @Subscribe + fun devCommand(event: CommandEvent.SubCommand) { + event.subcommand(DeveloperFeatures.DEVELOPER_SUBCOMMAND) { + thenLiteral("copytablist") { + thenExecute { + currentTabList.body.forEach { + MC.sendChat(Text.literal(TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it).orThrow.toString())) + } + var compound = CurrentTabList.CODEC.encodeStart(NbtOps.INSTANCE, currentTabList).orThrow + compound = ExportedTestConstantMeta.SOURCE_CODEC.encode( + ExportedTestConstantMeta.current, + NbtOps.INSTANCE, + compound + ).orThrow + ClipboardUtils.setTextContent( + compound.toPrettyString() + ) + } + } + } + } + + @get:TestOnly + @set:TestOnly + var _currentTabList: CurrentTabList? = null + + val currentTabList get() = _currentTabList ?: getTabListNow().also { _currentTabList = it } + + data class CurrentTabList( + val header: Optional, + val footer: Optional, + val body: List, + ) { + companion object { + val CODEC: Codec = RecordCodecBuilder.create { + it.group( + TextCodecs.CODEC.optionalFieldOf("header").forGetter(CurrentTabList::header), + TextCodecs.CODEC.optionalFieldOf("footer").forGetter(CurrentTabList::footer), + TextCodecs.CODEC.listOf().fieldOf("body").forGetter(CurrentTabList::body), + ).apply(it, ::CurrentTabList) + } + } + } + + private fun getTabListNow(): CurrentTabList { + // This is a precondition for PlayerListHud.collectEntries to be valid + MC.networkHandler ?: return CurrentTabList(Optional.empty(), Optional.empty(), emptyList()) + val hud = MC.inGameHud.playerListHud.cast() + val entries = hud.collectPlayerEntries_firmament() + .map { + it.displayName ?: run { + val team = it.scoreboardTeam + val name = it.profile.name + Team.decorateName(team, Text.literal(name)) + } + } + return CurrentTabList( + header = hud.header_firmament.intoOptional(), + footer = hud.footer_firmament.intoOptional(), + body = entries, + ) + } +} diff --git a/src/main/kotlin/util/mc/NbtItemData.kt b/src/main/kotlin/util/mc/NbtItemData.kt new file mode 100644 index 0000000..0c49862 --- /dev/null +++ b/src/main/kotlin/util/mc/NbtItemData.kt @@ -0,0 +1,22 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.component.DataComponentTypes +import net.minecraft.component.type.LoreComponent +import net.minecraft.item.ItemStack +import net.minecraft.text.Text + +var ItemStack.loreAccordingToNbt: List + 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/util/mc/NbtPrism.kt b/src/main/kotlin/util/mc/NbtPrism.kt new file mode 100644 index 0000000..f034210 --- /dev/null +++ b/src/main/kotlin/util/mc/NbtPrism.kt @@ -0,0 +1,91 @@ +package moe.nea.firmament.util.mc + +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonPrimitive +import com.mojang.brigadier.StringReader +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.arguments.StringArgumentType +import com.mojang.brigadier.context.CommandContext +import com.mojang.brigadier.suggestion.Suggestions +import com.mojang.brigadier.suggestion.SuggestionsBuilder +import com.mojang.serialization.JsonOps +import java.util.concurrent.CompletableFuture +import kotlin.collections.indices +import kotlin.collections.map +import kotlin.jvm.optionals.getOrNull +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtList +import net.minecraft.nbt.NbtOps +import net.minecraft.nbt.NbtString +import moe.nea.firmament.util.Base64Util + +class NbtPrism(val path: List) { + companion object { + fun fromElement(path: JsonElement): NbtPrism? { + if (path is JsonArray) { + return NbtPrism(path.map { (it as JsonPrimitive).asString }) + } else if (path is JsonPrimitive && path.isString) { + return NbtPrism(path.asString.split(".")) + } + return null + } + } + + object Argument : ArgumentType { + override fun parse(reader: StringReader): NbtPrism? { + return fromElement(JsonPrimitive(StringArgumentType.string().parse(reader))) + } + + override fun getExamples(): Collection? { + return listOf("some.nbt.path", "some.other.*", "some.path.*json.in.a.json.string") + } + } + + override fun toString(): String { + return "Prism($path)" + } + + fun access(root: NbtElement): Collection { + var rootSet = mutableListOf(root) + var switch = mutableListOf() + for (pathSegment in path) { + if (pathSegment == ".") continue + if (pathSegment != "*" && pathSegment.startsWith("*")) { + if (pathSegment == "*json") { + for (element in rootSet) { + val eString = element.asString().getOrNull() ?: continue + val element = Gson().fromJson(eString, JsonElement::class.java) + switch.add(JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, element)) + } + } else if (pathSegment == "*base64") { + for (element in rootSet) { + val string = element.asString().getOrNull() ?: continue + switch.add(NbtString.of(Base64Util.decodeString(string))) + } + } + } + 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/util/mc/NbtUtil.kt b/src/main/kotlin/util/mc/NbtUtil.kt new file mode 100644 index 0000000..2cab1c7 --- /dev/null +++ b/src/main/kotlin/util/mc/NbtUtil.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtList + +fun Iterable.toNbtList() = NbtList().also { + for (element in this) { + it.add(element) + } +} diff --git a/src/main/kotlin/util/mc/PlayerUtil.kt b/src/main/kotlin/util/mc/PlayerUtil.kt new file mode 100644 index 0000000..53ef1f4 --- /dev/null +++ b/src/main/kotlin/util/mc/PlayerUtil.kt @@ -0,0 +1,7 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.entity.EquipmentSlot +import net.minecraft.entity.player.PlayerEntity + + +val PlayerEntity.mainHandStack get() = this.getEquippedStack(EquipmentSlot.MAINHAND) diff --git a/src/main/kotlin/util/mc/SNbtFormatter.kt b/src/main/kotlin/util/mc/SNbtFormatter.kt new file mode 100644 index 0000000..7617d17 --- /dev/null +++ b/src/main/kotlin/util/mc/SNbtFormatter.kt @@ -0,0 +1,142 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.nbt.AbstractNbtList +import net.minecraft.nbt.NbtByte +import net.minecraft.nbt.NbtByteArray +import net.minecraft.nbt.NbtCompound +import net.minecraft.nbt.NbtDouble +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtEnd +import net.minecraft.nbt.NbtFloat +import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtIntArray +import net.minecraft.nbt.NbtList +import net.minecraft.nbt.NbtLong +import net.minecraft.nbt.NbtLongArray +import net.minecraft.nbt.NbtShort +import net.minecraft.nbt.NbtString +import net.minecraft.nbt.visitor.NbtElementVisitor + +class SNbtFormatter private constructor() : NbtElementVisitor { + private val result = StringBuilder() + private var indent = 0 + private fun writeIndent() { + result.append("\t".repeat(indent)) + } + + private fun pushIndent() { + indent++ + } + + private fun popIndent() { + indent-- + } + + fun apply(element: NbtElement): StringBuilder { + element.accept(this) + return result + } + + + override fun visitString(element: NbtString) { + result.append(NbtString.escape(element.value)) + } + + override fun visitByte(element: NbtByte) { + result.append(element.numberValue()).append("b") + } + + override fun visitShort(element: NbtShort) { + result.append(element.shortValue()).append("s") + } + + override fun visitInt(element: NbtInt) { + result.append(element.intValue()) + } + + override fun visitLong(element: NbtLong) { + result.append(element.longValue()).append("L") + } + + override fun visitFloat(element: NbtFloat) { + result.append(element.floatValue()).append("f") + } + + override fun visitDouble(element: NbtDouble) { + result.append(element.doubleValue()).append("d") + } + + private fun visitArrayContents(array: AbstractNbtList) { + array.forEachIndexed { index, element -> + writeIndent() + element.accept(this) + if (array.size() != index + 1) { + result.append(",") + } + result.append("\n") + } + } + + private fun writeArray(arrayTypeTag: String, array: AbstractNbtList) { + result.append("[").append(arrayTypeTag).append("\n") + pushIndent() + visitArrayContents(array) + popIndent() + writeIndent() + result.append("]") + + } + + override fun visitByteArray(element: NbtByteArray) { + writeArray("B;", element) + } + + override fun visitIntArray(element: NbtIntArray) { + writeArray("I;", element) + } + + override fun visitLongArray(element: NbtLongArray) { + writeArray("L;", element) + } + + override fun visitList(element: NbtList) { + writeArray("", element) + } + + override fun visitCompound(compound: NbtCompound) { + result.append("{\n") + pushIndent() + val keys = compound.keys.sorted() + keys.forEachIndexed { index, key -> + writeIndent() + val element = compound[key] ?: error("Key '$key' found but not present in compound: $compound") + val escapedName = escapeName(key) + result.append(escapedName).append(": ") + element.accept(this) + if (keys.size != index + 1) { + result.append(",") + } + result.append("\n") + } + popIndent() + writeIndent() + result.append("}") + } + + override fun visitEnd(element: NbtEnd) { + result.append("END") + } + + companion object { + fun prettify(nbt: NbtElement): String { + return SNbtFormatter().apply(nbt).toString() + } + + fun NbtElement.toPrettyString() = prettify(this) + + fun escapeName(key: String): String = + if (key.matches(SIMPLE_NAME)) key else NbtString.escape(key) + + val SIMPLE_NAME = "[A-Za-z0-9._+-]+".toRegex() + } +} diff --git a/src/main/kotlin/util/mc/ScreenUtil.kt b/src/main/kotlin/util/mc/ScreenUtil.kt new file mode 100644 index 0000000..36feb6b --- /dev/null +++ b/src/main/kotlin/util/mc/ScreenUtil.kt @@ -0,0 +1,26 @@ +package moe.nea.firmament.util.mc + +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.entity.player.PlayerInventory +import net.minecraft.screen.slot.Slot + +object ScreenUtil { + private var lastScreen: Screen? = null + private var slotsByIndex: Map = mapOf() + + data class SlotIndex(val index: Int, val isPlayerInventory: Boolean) + + fun Screen.getSlotsByIndex(): Map { + if (this !is HandledScreen<*>) return mapOf() + if (lastScreen === this) return slotsByIndex + lastScreen = this + slotsByIndex = this.screenHandler.slots.associate { + SlotIndex(it.index, it.inventory is PlayerInventory) to it + } + return slotsByIndex + } + + fun Screen.getSlotByIndex( index: Int, isPlayerInventory: Boolean): Slot? = + getSlotsByIndex()[SlotIndex(index, isPlayerInventory)] +} diff --git a/src/main/kotlin/util/mc/SkullItemData.kt b/src/main/kotlin/util/mc/SkullItemData.kt new file mode 100644 index 0000000..3a4c508 --- /dev/null +++ b/src/main/kotlin/util/mc/SkullItemData.kt @@ -0,0 +1,86 @@ +@file:UseSerializers(DashlessUUIDSerializer::class, InstantAsLongSerializer::class) + +package moe.nea.firmament.util.mc + +import com.mojang.authlib.GameProfile +import com.mojang.authlib.minecraft.MinecraftProfileTexture +import com.mojang.authlib.properties.Property +import java.time.Instant +import java.util.UUID +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +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 = mapOf(), +) + +@Serializable +data class MinecraftTexturesPayloadKt( + val textures: Map = mapOf(), + val profileId: UUID? = null, + val profileName: String? = null, + val isPublic: Boolean = true, + val timestamp: Instant = Instant.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 arbitraryUUID = 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(json) + } catch (e: Exception) { + // Malformed profile data + if (Firmament.DEBUG) + e.printStackTrace() + null + } +} + diff --git a/src/main/kotlin/util/mc/SlotUtils.kt b/src/main/kotlin/util/mc/SlotUtils.kt new file mode 100644 index 0000000..9eb4918 --- /dev/null +++ b/src/main/kotlin/util/mc/SlotUtils.kt @@ -0,0 +1,47 @@ +package moe.nea.firmament.util.mc + +import org.lwjgl.glfw.GLFW +import net.minecraft.screen.ScreenHandler +import net.minecraft.screen.slot.Slot +import net.minecraft.screen.slot.SlotActionType +import moe.nea.firmament.util.MC + +object SlotUtils { + fun Slot.clickMiddleMouseButton(handler: ScreenHandler) { + MC.interactionManager?.clickSlot( + handler.syncId, + this.id, + GLFW.GLFW_MOUSE_BUTTON_MIDDLE, + SlotActionType.CLONE, + MC.player + ) + } + + fun Slot.swapWithHotBar(handler: ScreenHandler, hotbarIndex: Int) { + MC.interactionManager?.clickSlot( + handler.syncId, this.id, + hotbarIndex, SlotActionType.SWAP, + MC.player + ) + } + + fun Slot.clickRightMouseButton(handler: ScreenHandler) { + MC.interactionManager?.clickSlot( + handler.syncId, + this.id, + GLFW.GLFW_MOUSE_BUTTON_RIGHT, + SlotActionType.PICKUP, + MC.player + ) + } + + fun Slot.clickLeftMouseButton(handler: ScreenHandler) { + MC.interactionManager?.clickSlot( + handler.syncId, + this.id, + GLFW.GLFW_MOUSE_BUTTON_LEFT, + SlotActionType.PICKUP, + MC.player + ) + } +} diff --git a/src/main/kotlin/util/mc/TolerantRegistriesOps.kt b/src/main/kotlin/util/mc/TolerantRegistriesOps.kt new file mode 100644 index 0000000..ce596a0 --- /dev/null +++ b/src/main/kotlin/util/mc/TolerantRegistriesOps.kt @@ -0,0 +1,29 @@ +package moe.nea.firmament.util.mc + +import com.mojang.serialization.DynamicOps +import java.util.Optional +import net.minecraft.registry.Registry +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryOps +import net.minecraft.registry.RegistryWrapper +import net.minecraft.registry.entry.RegistryEntryOwner + +class TolerantRegistriesOps( + delegate: DynamicOps, + registryInfoGetter: RegistryInfoGetter +) : RegistryOps(delegate, registryInfoGetter) { + constructor(delegate: DynamicOps, registry: RegistryWrapper.WrapperLookup) : + this(delegate, CachedRegistryInfoGetter(registry)) + + class TolerantOwner : RegistryEntryOwner { + override fun ownerEquals(other: RegistryEntryOwner?): Boolean { + return true + } + } + + override fun getOwner(registryRef: RegistryKey>?): Optional> { + return super.getOwner(registryRef).map { + TolerantOwner() + } + } +} diff --git a/src/main/kotlin/util/mc/asFakeServer.kt b/src/main/kotlin/util/mc/asFakeServer.kt new file mode 100644 index 0000000..d3811bd --- /dev/null +++ b/src/main/kotlin/util/mc/asFakeServer.kt @@ -0,0 +1,37 @@ +package moe.nea.firmament.util.mc + +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource +import net.minecraft.server.command.CommandOutput +import net.minecraft.server.command.ServerCommandSource +import net.minecraft.text.Text + +fun FabricClientCommandSource.asFakeServer(): ServerCommandSource { + val source = this + return ServerCommandSource( + object : CommandOutput { + override fun sendMessage(message: Text?) { + source.player.sendMessage(message, false) + } + + override fun shouldReceiveFeedback(): Boolean { + return true + } + + override fun shouldTrackOutput(): Boolean { + return true + } + + override fun shouldBroadcastConsoleToOps(): Boolean { + return true + } + }, + source.position, + source.rotation, + null, + 0, + "FakeServerCommandSource", + Text.literal("FakeServerCommandSource"), + null, + source.player + ) +} diff --git a/src/main/kotlin/util/propertyutil.kt b/src/main/kotlin/util/propertyutil.kt new file mode 100644 index 0000000..795a0d2 --- /dev/null +++ b/src/main/kotlin/util/propertyutil.kt @@ -0,0 +1,9 @@ + + +package moe.nea.firmament.util + +import kotlin.properties.ReadOnlyProperty + +fun ReadOnlyProperty.map(mapper: (V) -> M): ReadOnlyProperty { + return ReadOnlyProperty { thisRef, property -> mapper(this@map.getValue(thisRef, property)) } +} diff --git a/src/main/kotlin/util/regex.kt b/src/main/kotlin/util/regex.kt new file mode 100644 index 0000000..be6bcfb --- /dev/null +++ b/src/main/kotlin/util/regex.kt @@ -0,0 +1,73 @@ +@file:OptIn(ExperimentalTypeInference::class, ExperimentalContracts::class) + +package moe.nea.firmament.util + +import java.util.regex.Matcher +import java.util.regex.Pattern +import org.intellij.lang.annotations.Language +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract +import kotlin.experimental.ExperimentalTypeInference +import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds + +inline fun String.ifMatches(regex: Regex, block: (MatchResult) -> T): T? = + regex.matchEntire(this)?.let(block) + +inline fun Pattern.useMatch(string: String?, block: Matcher.() -> T): T? { + contract { + callsInPlace(block, InvocationKind.AT_MOST_ONCE) + } + return string + ?.let(this::matcher) + ?.takeIf(Matcher::matches) + ?.let(block) +} + +fun String.ifDropLast(suffix: String, block: (String) -> T): T? { + if (endsWith(suffix)) { + return block(dropLast(suffix.length)) + } + return null +} + +@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 { + if (string.startsWith("-")) return -parseShortNumber(string.substring(1)) + if (string.startsWith("+")) return parseShortNumber(string.substring(1)) + 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/util/render/CustomRenderLayers.kt b/src/main/kotlin/util/render/CustomRenderLayers.kt new file mode 100644 index 0000000..2da1de7 --- /dev/null +++ b/src/main/kotlin/util/render/CustomRenderLayers.kt @@ -0,0 +1,106 @@ +package util.render + +import com.mojang.blaze3d.pipeline.BlendFunction +import com.mojang.blaze3d.pipeline.RenderPipeline +import com.mojang.blaze3d.platform.DepthTestFunction +import com.mojang.blaze3d.vertex.VertexFormat.DrawMode +import java.util.function.Function +import net.minecraft.client.gl.RenderPipelines +import net.minecraft.client.gl.UniformType +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.RenderPhase +import net.minecraft.client.render.VertexFormats +import net.minecraft.util.Identifier +import net.minecraft.util.TriState +import net.minecraft.util.Util +import moe.nea.firmament.Firmament + +object CustomRenderPipelines { + val GUI_TEXTURED_NO_DEPTH_TRIS = + RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET) + .withVertexFormat(VertexFormats.POSITION_TEXTURE_COLOR, DrawMode.TRIANGLES) + .withLocation(Firmament.identifier("gui_textured_overlay_tris")) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .withCull(false) + .withDepthWrite(false) + .build() + val OMNIPRESENT_LINES = RenderPipeline + .builder(RenderPipelines.RENDERTYPE_LINES_SNIPPET) + .withLocation(Firmament.identifier("lines")) + .withDepthWrite(false) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .build() + val COLORED_OMNIPRESENT_QUADS = + RenderPipeline.builder(RenderPipelines.MATRICES_COLOR_SNIPPET)// TODO: split this up to support better transparent ordering. + .withLocation(Firmament.identifier("colored_omnipresent_quads")) + .withVertexShader("core/position_color") + .withFragmentShader("core/position_color") + .withVertexFormat(VertexFormats.POSITION_COLOR, DrawMode.QUADS) + .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST) + .withCull(false) + .withDepthWrite(false) + .withBlend(BlendFunction.TRANSLUCENT) + .build() + + val CIRCLE_FILTER_TRANSLUCENT_GUI_TRIS = + RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET) + .withVertexFormat(VertexFormats.POSITION_TEXTURE_COLOR, DrawMode.TRIANGLES) + .withLocation(Firmament.identifier("gui_textured_overlay_tris_circle")) + .withUniform("InnerCutoutRadius", UniformType.FLOAT) + .withFragmentShader(Firmament.identifier("circle_discard_color")) + .withBlend(BlendFunction.TRANSLUCENT) + .build() + val PARALLAX_CAPE_SHADER = + RenderPipeline.builder(RenderPipelines.ENTITY_SNIPPET) + .withLocation(Firmament.identifier("parallax_cape")) + .withFragmentShader(Firmament.identifier("cape/parallax")) + .withSampler("Sampler0") + .withSampler("Sampler1") + .withSampler("Sampler3") + .withUniform("Animation", UniformType.FLOAT) + .build() +} + +object CustomRenderLayers { + inline fun memoizeTextured(crossinline func: (Identifier) -> RenderLayer) = memoize(func) + inline fun memoize(crossinline func: (T) -> R): Function { + return Util.memoize { it: T -> func(it) } + } + + val GUI_TEXTURED_NO_DEPTH_TRIS = memoizeTextured { texture -> + RenderLayer.of( + "firmament_gui_textured_overlay_tris", + RenderLayer.DEFAULT_BUFFER_SIZE, + CustomRenderPipelines.GUI_TEXTURED_NO_DEPTH_TRIS, + RenderLayer.MultiPhaseParameters.builder().texture( + RenderPhase.Texture(texture, TriState.DEFAULT, false) + ) + .build(false) + ) + } + val LINES = RenderLayer.of( + "firmament_lines", + RenderLayer.DEFAULT_BUFFER_SIZE, + CustomRenderPipelines.OMNIPRESENT_LINES, + RenderLayer.MultiPhaseParameters.builder() // TODO: accept linewidth here + .build(false) + ) + val COLORED_QUADS = RenderLayer.of( + "firmament_quads", + RenderLayer.DEFAULT_BUFFER_SIZE, + false, true, + CustomRenderPipelines.COLORED_OMNIPRESENT_QUADS, + RenderLayer.MultiPhaseParameters.builder() + .lightmap(RenderPhase.DISABLE_LIGHTMAP) + .build(false) + ) + + val TRANSLUCENT_CIRCLE_GUI = + RenderLayer.of( + "firmament_circle_gui", + RenderLayer.DEFAULT_BUFFER_SIZE, + CustomRenderPipelines.CIRCLE_FILTER_TRANSLUCENT_GUI_TRIS, + RenderLayer.MultiPhaseParameters.builder() + .build(false) + ) +} diff --git a/src/main/kotlin/util/render/DrawContextExt.kt b/src/main/kotlin/util/render/DrawContextExt.kt new file mode 100644 index 0000000..a833c86 --- /dev/null +++ b/src/main/kotlin/util/render/DrawContextExt.kt @@ -0,0 +1,68 @@ +package moe.nea.firmament.util.render + +import com.mojang.blaze3d.systems.RenderSystem +import me.shedaniel.math.Color +import org.joml.Matrix4f +import util.render.CustomRenderLayers +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.render.RenderLayer +import net.minecraft.util.Identifier +import moe.nea.firmament.util.MC + +fun DrawContext.isUntranslatedGuiDrawContext(): Boolean { + return (matrices.peek().positionMatrix.properties() and Matrix4f.PROPERTY_IDENTITY.toInt()) != 0 +} + +@Deprecated("Use the other drawGuiTexture") +fun DrawContext.drawGuiTexture( + x: Int, y: Int, z: Int, width: Int, height: Int, sprite: Identifier +) = this.drawGuiTexture(RenderLayer::getGuiTextured, sprite, x, y, width, height) + +fun DrawContext.drawGuiTexture( + sprite: Identifier, + x: Int, y: Int, width: Int, height: Int +) = this.drawGuiTexture(RenderLayer::getGuiTextured, sprite, x, y, width, height) + +fun DrawContext.drawTexture( + sprite: Identifier, + x: Int, + y: Int, + u: Float, + v: Float, + width: Int, + height: Int, + textureWidth: Int, + textureHeight: Int +) { + this.drawTexture(RenderLayer::getGuiTextured, + sprite, + x, + y, + u, + v, + width, + height, + width, + height, + textureWidth, + textureHeight) +} + +fun DrawContext.drawLine(fromX: Int, fromY: Int, toX: Int, toY: Int, color: Color) { + // TODO: push scissors + // TODO: use matrix translations and a different render layer + if (toY < fromY) { + drawLine(toX, toY, fromX, fromY, color) + return + } + RenderSystem.lineWidth(MC.window.scaleFactor.toFloat()) + draw { vertexConsumers -> + val buf = vertexConsumers.getBuffer(CustomRenderLayers.LINES) + val matrix = this.matrices.peek() + buf.vertex(matrix, fromX.toFloat(), fromY.toFloat(), 0F).color(color.color) + .normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F) + buf.vertex(matrix, toX.toFloat(), toY.toFloat(), 0F).color(color.color) + .normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F) + } +} + diff --git a/src/main/kotlin/util/render/FacingThePlayerContext.kt b/src/main/kotlin/util/render/FacingThePlayerContext.kt new file mode 100644 index 0000000..670beb6 --- /dev/null +++ b/src/main/kotlin/util/render/FacingThePlayerContext.kt @@ -0,0 +1,92 @@ + +package moe.nea.firmament.util.render + +import io.github.notenoughupdates.moulconfig.platform.next +import org.joml.Matrix4f +import net.minecraft.client.font.TextRenderer +import net.minecraft.client.render.LightmapTextureManager +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.VertexConsumer +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, + ) { + val buf = worldContext.vertexConsumers.getBuffer(RenderLayer.getGuiTexturedOverlay(texture)) + val hw = width / 2F + val hh = height / 2F + val matrix4f: Matrix4f = worldContext.matrixStack.peek().positionMatrix + 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() + worldContext.vertexConsumers.draw() + } + +} diff --git a/src/main/kotlin/util/render/FirmamentShaders.kt b/src/main/kotlin/util/render/FirmamentShaders.kt new file mode 100644 index 0000000..cc6cd49 --- /dev/null +++ b/src/main/kotlin/util/render/FirmamentShaders.kt @@ -0,0 +1,20 @@ +package moe.nea.firmament.util.render + +import com.mojang.blaze3d.vertex.VertexFormat +import net.minecraft.client.gl.CompiledShader +import net.minecraft.client.gl.Defines +import net.minecraft.client.gl.ShaderProgram +import net.minecraft.client.render.RenderPhase +import net.minecraft.client.render.VertexFormats +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.DebugInstantiateEvent +import moe.nea.firmament.util.MC + +object FirmamentShaders { + + @Subscribe + fun debugLoad(event: DebugInstantiateEvent) { + // TODO: do i still need to work with shaders like this? + } +} diff --git a/src/main/kotlin/util/render/LerpUtils.kt b/src/main/kotlin/util/render/LerpUtils.kt new file mode 100644 index 0000000..e7f226c --- /dev/null +++ b/src/main/kotlin/util/render/LerpUtils.kt @@ -0,0 +1,40 @@ +package moe.nea.firmament.util.render + +import me.shedaniel.math.Color +import kotlin.math.absoluteValue + +val Ï€ = Math.PI +val Ï„ = Math.PI * 2 +fun lerpAngle(a: Float, b: Float, progress: Float): Float { + // TODO: there is at least 10 mods to many in here lol + if (((b - a).absoluteValue - Ï€).absoluteValue < 0.0001) { + return lerp(a, b, progress) + } + val shortestAngle = ((((b.mod(Ï„) - a.mod(Ï„)).mod(Ï„)) + Ï„ + Ï€).mod(Ï„)) - Ï€ + return ((a + (shortestAngle) * progress).mod(Ï„)).toFloat() +} + +fun wrapAngle(angle: Float): Float = (angle.mod(Ï„) + Ï„).mod(Ï„).toFloat() +fun wrapAngle(angle: Double): Double = (angle.mod(Ï„) + Ï„).mod(Ï„) + +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/util/render/RenderCircleProgress.kt b/src/main/kotlin/util/render/RenderCircleProgress.kt new file mode 100644 index 0000000..81dde6f --- /dev/null +++ b/src/main/kotlin/util/render/RenderCircleProgress.kt @@ -0,0 +1,101 @@ +package moe.nea.firmament.util.render + +import com.mojang.blaze3d.systems.RenderSystem +import com.mojang.blaze3d.vertex.VertexFormat +import io.github.notenoughupdates.moulconfig.platform.next +import java.util.OptionalInt +import org.joml.Matrix4f +import util.render.CustomRenderLayers +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.render.BufferBuilder +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.util.BufferAllocator +import net.minecraft.util.Identifier +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.collections.nonNegligibleSubSectionsAlignedWith +import moe.nea.firmament.util.math.Projections + +object RenderCircleProgress { + + fun renderCircularSlice( + drawContext: DrawContext, + layer: RenderLayer, + u1: Float, + u2: Float, + v1: Float, + v2: Float, + angleRadians: ClosedFloatingPointRange, + color: Int = -1, + innerCutoutRadius: Float = 0F + ) { + drawContext.draw() + val sections = angleRadians.nonNegligibleSubSectionsAlignedWith((Ï„ / 8f).toFloat()) + .zipWithNext().toList() + BufferAllocator(layer.vertexFormat.vertexSize * sections.size * 3).use { allocator -> + + val bufferBuilder = BufferBuilder(allocator, VertexFormat.DrawMode.TRIANGLES, layer.vertexFormat) + val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix + + for ((sectionStart, sectionEnd) in sections) { + val firstPoint = Projections.Two.projectAngleOntoUnitBox(sectionStart.toDouble()) + val secondPoint = Projections.Two.projectAngleOntoUnitBox(sectionEnd.toDouble()) + fun ilerp(f: Float): Float = + ilerp(-1f, 1f, f) + + bufferBuilder + .vertex(matrix, secondPoint.x, secondPoint.y, 0F) + .texture(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y))) + .color(color) + .next() + bufferBuilder + .vertex(matrix, firstPoint.x, firstPoint.y, 0F) + .texture(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y))) + .color(color) + .next() + bufferBuilder + .vertex(matrix, 0F, 0F, 0F) + .texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F))) + .color(color) + .next() + } + + bufferBuilder.end().use { buffer -> + // TODO: write a better utility to pass uniforms :sob: ill even take a mixin at this point + if (innerCutoutRadius <= 0) { + layer.draw(buffer) + return + } + val vertexBuffer = layer.vertexFormat.uploadImmediateVertexBuffer(buffer.buffer) + val indexBufferConstructor = RenderSystem.getSequentialBuffer(VertexFormat.DrawMode.TRIANGLES) + val indexBuffer = indexBufferConstructor.getIndexBuffer(buffer.drawParameters.indexCount) + RenderSystem.getDevice().createCommandEncoder().createRenderPass( + MC.instance.framebuffer.colorAttachment, + OptionalInt.empty(), + ).use { renderPass -> + renderPass.setPipeline(layer.pipeline) + renderPass.setUniform("InnerCutoutRadius", innerCutoutRadius) + renderPass.setIndexBuffer(indexBuffer, indexBufferConstructor.indexType) + renderPass.setVertexBuffer(0, vertexBuffer) + renderPass.drawIndexed(0, buffer.drawParameters.indexCount) + } + } + } + } + + fun renderCircle( + drawContext: DrawContext, + texture: Identifier, + progress: Float, + u1: Float, + u2: Float, + v1: Float, + v2: Float, + ) { + renderCircularSlice( + drawContext, + CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture), + u1, u2, v1, v2, + (-Ï„ / 4).toFloat()..(progress * Ï„ - Ï„ / 4).toFloat() + ) + } +} diff --git a/src/main/kotlin/util/render/RenderContextDSL.kt b/src/main/kotlin/util/render/RenderContextDSL.kt new file mode 100644 index 0000000..9bb4431 --- /dev/null +++ b/src/main/kotlin/util/render/RenderContextDSL.kt @@ -0,0 +1,6 @@ + +package moe.nea.firmament.util.render + +@DslMarker +annotation class RenderContextDSL { +} diff --git a/src/main/kotlin/util/render/RenderInWorldContext.kt b/src/main/kotlin/util/render/RenderInWorldContext.kt new file mode 100644 index 0000000..c30ee19 --- /dev/null +++ b/src/main/kotlin/util/render/RenderInWorldContext.kt @@ -0,0 +1,316 @@ +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 util.render.CustomRenderLayers +import net.minecraft.client.render.Camera +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.RenderTickCounter +import net.minecraft.client.render.VertexConsumer +import net.minecraft.client.render.VertexConsumerProvider +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( + val matrixStack: MatrixStack, + private val camera: Camera, + private val tickCounter: RenderTickCounter, + val vertexConsumers: VertexConsumerProvider.Immediate, +) { + + + @Deprecated("stateful color management is no longer a thing") + fun color(color: me.shedaniel.math.Color) { + color(color.red / 255F, color.green / 255f, color.blue / 255f, color.alpha / 255f) + } + + @Deprecated("stateful color management is no longer a thing") + fun color(red: Float, green: Float, blue: Float, alpha: Float) { + RenderSystem.setShaderColor(red, green, blue, alpha) + } + + fun block(blockPos: BlockPos, color: Int) { + matrixStack.push() + matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat()) + buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color) + matrixStack.pop() + } + + fun sharedVoxelSurface(blocks: Set, color: Int) { + val m = BlockPos.Mutable() + val l = vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS) + blocks.forEach { + matrixStack.push() + matrixStack.translate(it.x.toFloat(), it.y.toFloat(), it.z.toFloat()) + val p = matrixStack.peek().positionMatrix + m.set(it) + if (m.setX(it.x + 1) !in blocks) { + buildFaceXP(p, l, color) + } + if (m.setX(it.x - 1) !in blocks) { + buildFaceXN(p, l, color) + } + m.set(it) + if (m.setY(it.y + 1) !in blocks) { + buildFaceYP(p, l, color) + } + if (m.setY(it.y - 1) !in blocks) { + buildFaceYN(p, l, color) + } + m.set(it) + if (m.setZ(it.z + 1) !in blocks) { + buildFaceZP(p, l, color) + } + if (m.setZ(it.z - 1) !in blocks) { + buildFaceZN(p, l, color) + } + 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, color: Int) { + matrixStack.push() + matrixStack.translate(vec3d.x, vec3d.y, vec3d.z) + matrixStack.scale(size, size, size) + matrixStack.translate(-.5, -.5, -.5) + buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color) + matrixStack.pop() + vertexConsumers.draw() + } + + fun wireframeCube(blockPos: BlockPos, lineWidth: Float = 10F) { + val buf = vertexConsumers.getBuffer(RenderLayer.LINES) + matrixStack.push() + // TODO: this does not render through blocks (or water layers) anymore + 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(), buf) + matrixStack.pop() + vertexConsumers.draw() + } + + 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, lineWidth: Float = 10F) { + RenderSystem.lineWidth(lineWidth) + val buffer = vertexConsumers.getBuffer(CustomRenderLayers.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() + } + + } + // TODO: put the favourite icons in front of items again + + companion object { + private fun doLine( + matrix: MatrixStack.Entry, + buf: VertexConsumer, + 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, buf: VertexConsumer) { + 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) + } + } + } + + private fun buildFaceZP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 0F, 0F, 1F).color(rgba) + buf.vertex(matrix, 0F, 1F, 1F).color(rgba) + buf.vertex(matrix, 1F, 1F, 1F).color(rgba) + buf.vertex(matrix, 1F, 0F, 1F).color(rgba) + } + + private fun buildFaceZN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 0F, 0F, 0F).color(rgba) + buf.vertex(matrix, 1F, 0F, 0F).color(rgba) + buf.vertex(matrix, 1F, 1F, 0F).color(rgba) + buf.vertex(matrix, 0F, 1F, 0F).color(rgba) + } + + private fun buildFaceXP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 1F, 0F, 0F).color(rgba) + buf.vertex(matrix, 1F, 1F, 0F).color(rgba) + buf.vertex(matrix, 1F, 1F, 1F).color(rgba) + buf.vertex(matrix, 1F, 0F, 1F).color(rgba) + } + + private fun buildFaceXN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 0F, 0F, 0F).color(rgba) + buf.vertex(matrix, 0F, 0F, 1F).color(rgba) + buf.vertex(matrix, 0F, 1F, 1F).color(rgba) + buf.vertex(matrix, 0F, 1F, 0F).color(rgba) + } + + private fun buildFaceYN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 0F, 0F, 0F).color(rgba) + buf.vertex(matrix, 0F, 0F, 1F).color(rgba) + buf.vertex(matrix, 1F, 0F, 1F).color(rgba) + buf.vertex(matrix, 1F, 0F, 0F).color(rgba) + } + + private fun buildFaceYP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) { + buf.vertex(matrix, 0F, 1F, 0F).color(rgba) + buf.vertex(matrix, 1F, 1F, 0F).color(rgba) + buf.vertex(matrix, 1F, 1F, 1F).color(rgba) + buf.vertex(matrix, 0F, 1F, 1F).color(rgba) + } + + private fun buildCube(matrix4f: Matrix4f, buf: VertexConsumer, rgba: Int) { + buildFaceXP(matrix4f, buf, rgba) + buildFaceXN(matrix4f, buf, rgba) + buildFaceYP(matrix4f, buf, rgba) + buildFaceYN(matrix4f, buf, rgba) + buildFaceZP(matrix4f, buf, rgba) + buildFaceZN(matrix4f, buf, rgba) + } + + fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) { + // TODO: there should be *no more global state*. the only thing we should be doing is render layers. that includes settings like culling, blending, shader color, and depth testing + // For now i will let these functions remain, but this needs to go before i do a full (non-beta) release +// 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( + event.matrices, + event.camera, + event.tickCounter, + event.vertexConsumers + ) + + block(ctx) + + event.matrices.pop() + event.vertexConsumers.draw() + RenderSystem.setShaderColor(1F, 1F, 1F, 1F) + } + } +} + + diff --git a/src/main/kotlin/util/render/TintedOverlayTexture.kt b/src/main/kotlin/util/render/TintedOverlayTexture.kt new file mode 100644 index 0000000..0677846 --- /dev/null +++ b/src/main/kotlin/util/render/TintedOverlayTexture.kt @@ -0,0 +1,35 @@ +package moe.nea.firmament.util.render + +import me.shedaniel.math.Color +import net.minecraft.client.render.OverlayTexture +import net.minecraft.util.math.ColorHelper +import moe.nea.firmament.util.ErrorUtil + +class TintedOverlayTexture : OverlayTexture() { + companion object { + val size = 16 + } + + private var lastColor: Color? = null + fun setColor(color: Color): TintedOverlayTexture { + val image = ErrorUtil.notNullOr(texture.image, "Disposed TintedOverlayTexture written to") { return this } + if (color == lastColor) return this + lastColor = color + + for (i in 0.., + val cooldown: Duration?, + ) + + @JvmInline + value class AbilityActivation( + val label: String + ) { + companion object { + val RIGHT_CLICK = AbilityActivation("RIGHT CLICK") + val SNEAK_RIGHT_CLICK = AbilityActivation("SNEAK RIGHT CLICK") + val SNEAK = AbilityActivation("SNEAK") + val EMPTY = AbilityActivation("") + fun of(text: String?): AbilityActivation { + val trimmed = text?.trim() + if (trimmed.isNullOrBlank()) + return EMPTY + return AbilityActivation(trimmed) + } + } + } + + private val abilityNameRegex = "Ability: (?.*?) *".toPattern() + private fun findAbility(iterator: ListIterator): ItemAbility? { + if (!iterator.hasNext()) { + return null + } + val line = iterator.next() + // The actual information about abilities is stored in the siblings + if (line.directLiteralStringContent != "") return null + var powerScroll: Boolean = false // This should instead determine the power scroll based on text colour + var abilityName: String? = null + var activation: String? = null + var hasProcessedActivation = false + for (sibling in line.siblings) { + val directContent = sibling.directLiteralStringContent ?: continue + if (directContent == "⦾ ") { + powerScroll = true + continue + } + if (!hasProcessedActivation && abilityName != null) { + hasProcessedActivation = true + activation = directContent + continue + } + abilityNameRegex.useMatch(directContent) { + abilityName = group("name") + continue + } + if (abilityName != null) { + ErrorUtil.softError("Found abilityName $abilityName without finding but encountered unprocessable element in: $line") + } + return null + } + if (abilityName == null) return null + val descriptionLines = mutableListOf() + var manaCost: Int? = null + var cooldown: Duration? = null + while (iterator.hasNext()) { + val descriptionLine = iterator.next() + if (descriptionLine.unformattedString == "") break + var nextIsManaCost = false + var isSpecialLine = false + var nextIsDuration = false + for (sibling in descriptionLine.siblings) { + val directContent = sibling.directLiteralStringContent ?: continue + if ("Mana Cost: " == directContent) { // TODO: 'Soulflow Cost: ' support (or maybe a generic 'XXX Cost: ') + nextIsManaCost = true + isSpecialLine = true + continue + } + if ("Cooldown: " == directContent) { + nextIsDuration = true + isSpecialLine = true + continue + } + if (nextIsDuration) { + nextIsDuration = false + cooldown = parseTimePattern(directContent) + continue + } + if (nextIsManaCost) { + nextIsManaCost = false + manaCost = parseShortNumber(directContent).toInt() + continue + } + if (isSpecialLine) { + ErrorUtil.softError("Unknown special line segment: '$sibling' in '$descriptionLine'") + } + } + if (!isSpecialLine) { + descriptionLines.add(descriptionLine) + } + } + return ItemAbility( + abilityName, + powerScroll, + AbilityActivation.of(activation), + manaCost, + descriptionLines, + cooldown + ) + } + + fun getAbilities(lore: List): List { + val iterator = lore.listIterator() + val abilities = mutableListOf() + while (iterator.hasNext()) { + findAbility(iterator)?.let(abilities::add) + } + + return abilities + } + + // TODO: memoize + fun getAbilities(itemStack: ItemStack): List { + return getAbilities(itemStack.loreAccordingToNbt) + } + +} diff --git a/src/main/kotlin/util/skyblock/DungeonUtil.kt b/src/main/kotlin/util/skyblock/DungeonUtil.kt new file mode 100644 index 0000000..488b158 --- /dev/null +++ b/src/main/kotlin/util/skyblock/DungeonUtil.kt @@ -0,0 +1,33 @@ +package moe.nea.firmament.util.skyblock + +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.ScoreboardUtil +import moe.nea.firmament.util.SkyBlockIsland +import moe.nea.firmament.util.TIME_PATTERN + +object DungeonUtil { + val isInDungeonIsland get() = SBData.skyblockLocation == SkyBlockIsland.DUNGEON + private val timeElapsedRegex = "Time Elapsed: $TIME_PATTERN".toRegex() + val isInActiveDungeon get() = isInDungeonIsland && ScoreboardUtil.simplifiedScoreboardLines.any { it.matches( + timeElapsedRegex) } + +/*Title: + +§f§lSKYBLOCK§B§L CO-OP + +' Late Spring 7th' +' §75:20am' +' §7⣠§cThe Catacombs §7(M3)' +' §7♲ §7Ironman' +' ' +'Keys: §câ–  §c✗ §8â–  §a1x' +'Time Elapsed: §a46s' +'Cleared: §660% §8(105)' +' ' +'§e[B] §b151_Dragon §e2,062§câ¤' +'§e[A] §6Lennart0312 §a17,165§c' +'§e[T] §b187i §a14,581§câ¤' +'§e[H] §bFlameeke §a8,998§câ¤' +' ' +'§ewww.hypixel.net'*/ +} diff --git a/src/main/kotlin/util/skyblock/ItemType.kt b/src/main/kotlin/util/skyblock/ItemType.kt new file mode 100644 index 0000000..7a776b5 --- /dev/null +++ b/src/main/kotlin/util/skyblock/ItemType.kt @@ -0,0 +1,75 @@ +package moe.nea.firmament.util.skyblock + +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.petData + + +@JvmInline +value class ItemType private constructor(val name: String) { + companion object { + fun ofName(name: String): ItemType { + return ItemType(name) + } + + private val obfuscatedRegex = "§[kK].*?(§[0-9a-fA-FrR]|$)".toRegex() + fun fromEscapeCodeLore(lore: String): ItemType? { + return lore.replace(obfuscatedRegex, "").trim().substringAfter(" ", "") + .takeIf { it.isNotEmpty() } + ?.let(::ofName) + } + + fun fromItemStack(itemStack: ItemStack): ItemType? { + if (itemStack.petData != null) + return PET + val typeText = + itemStack.loreAccordingToNbt.lastOrNull() + ?.siblings?.find { + !it.style.isObfuscated && !it.directLiteralStringContent.isNullOrBlank() + }?.directLiteralStringContent + if (typeText != null) { + val type = typeText.substringAfter(' ', missingDelimiterValue = "").trim() + if (type.isEmpty()) return null + return ofName(type) + } + return itemStack.loreAccordingToNbt.lastOrNull()?.directLiteralStringContent?.let(::fromEscapeCodeLore) + } + + // TODO: some of those are not actual in game item types, but rather ones included in the repository to splat to multiple in game types. codify those somehow + + val SWORD = ofName("SWORD") + val DRILL = ofName("DRILL") + val PICKAXE = ofName("PICKAXE") + val GAUNTLET = ofName("GAUNTLET") + val LONGSWORD = ofName("LONG SWORD") + val EQUIPMENT = ofName("EQUIPMENT") + val FISHING_WEAPON = ofName("FISHING WEAPON") + val CLOAK = ofName("CLOAK") + val BELT = ofName("BELT") + val NECKLACE = ofName("NECKLACE") + val BRACELET = ofName("BRACELET") + val GLOVES = ofName("GLOVES") + val ROD = ofName("ROD") + val FISHING_ROD = ofName("FISHING ROD") + val VACUUM = ofName("VACUUM") + val CHESTPLATE = ofName("CHESTPLATE") + val LEGGINGS = ofName("LEGGINGS") + val HELMET = ofName("HELMET") + val BOOTS = ofName("BOOTS") + val NIL = ofName("__NIL") + + /** + * This one is not really official (it never shows up in game). + */ + val PET = ofName("PET") + } + + val dungeonVariant get() = ofName("DUNGEON $name") + + val isDungeon get() = name.startsWith("DUNGEON ") + + override fun toString(): String { + return name + } +} diff --git a/src/main/kotlin/util/skyblock/Rarity.kt b/src/main/kotlin/util/skyblock/Rarity.kt new file mode 100644 index 0000000..2507256 --- /dev/null +++ b/src/main/kotlin/util/skyblock/Rarity.kt @@ -0,0 +1,99 @@ +package moe.nea.firmament.util.skyblock + +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.text.Style +import net.minecraft.text.Text +import net.minecraft.util.Formatting +import moe.nea.firmament.util.StringUtil.words +import moe.nea.firmament.util.collections.lastNotNullOfOrNull +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.petData +import moe.nea.firmament.util.unformattedString + +typealias RepoRarity = io.github.moulberry.repo.data.Rarity + +@Serializable(with = Rarity.Serializer::class) +enum class Rarity(vararg altNames: String) { + COMMON, + UNCOMMON, + RARE, + EPIC, + LEGENDARY("LEGENJERRY"), + MYTHIC, + DIVINE, + SUPREME, + SPECIAL, + VERY_SPECIAL, + ULTIMATE, + UNKNOWN + ; + + object Serializer : KSerializer { + override val descriptor: SerialDescriptor + get() = PrimitiveSerialDescriptor(Rarity::class.java.name, PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): Rarity { + return valueOf(decoder.decodeString().replace(" ", "_")) + } + + override fun serialize(encoder: Encoder, value: Rarity) { + encoder.encodeString(value.name) + } + } + + val names = setOf(name) + altNames + val text: Text get() = Text.literal(name).setStyle(Style.EMPTY.withColor(colourMap[this])) + val neuRepoRarity: RepoRarity? = RepoRarity.entries.find { it.name == name } + + companion object { + // TODO: inline those formattings as fields + val colourMap = mapOf( + Rarity.COMMON to Formatting.WHITE, + Rarity.UNCOMMON to Formatting.GREEN, + Rarity.RARE to Formatting.BLUE, + Rarity.EPIC to Formatting.DARK_PURPLE, + Rarity.LEGENDARY to Formatting.GOLD, + Rarity.MYTHIC to Formatting.LIGHT_PURPLE, + Rarity.DIVINE to Formatting.AQUA, + Rarity.SPECIAL to Formatting.RED, + Rarity.VERY_SPECIAL to Formatting.RED, + Rarity.SUPREME to Formatting.DARK_RED, + Rarity.ULTIMATE to Formatting.DARK_RED, + ) + val byName = entries.flatMap { en -> en.names.map { it to en } }.toMap() + val fromNeuRepo = entries.associateBy { it.neuRepoRarity } + + fun fromNeuRepo(repo: RepoRarity): Rarity? { + return fromNeuRepo[repo] + } + + fun fromString(name: String): Rarity? { + return byName[name] + } + + fun fromTier(tier: Int): Rarity? { + return entries.getOrNull(tier) + } + + fun fromItem(itemStack: ItemStack): Rarity? { + return fromLore(itemStack.loreAccordingToNbt) ?: fromPetItem(itemStack) + } + + fun fromPetItem(itemStack: ItemStack): Rarity? = + itemStack.petData?.tier?.let(::fromNeuRepo) + + fun fromLore(lore: List): Rarity? = + lore.lastNotNullOfOrNull { + it.unformattedString.words() + .firstNotNullOfOrNull(::fromString) + } + + } +} diff --git a/src/main/kotlin/util/skyblock/SBItemUtil.kt b/src/main/kotlin/util/skyblock/SBItemUtil.kt new file mode 100644 index 0000000..3901b60 --- /dev/null +++ b/src/main/kotlin/util/skyblock/SBItemUtil.kt @@ -0,0 +1,21 @@ +package moe.nea.firmament.util.skyblock + +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.unformattedString + +object SBItemUtil { + fun ItemStack.getSearchName(): String { + val name = this.name.unformattedString + if (name.contains("Enchanted Book")) { + val enchant = loreAccordingToNbt.firstOrNull()?.unformattedString + if (enchant != null) return enchant + } + if (name.startsWith("[Lvl")) { + val closing = name.indexOf(']') + if (closing > 0) + return name.substring(closing) + } + return name + } +} diff --git a/src/main/kotlin/util/skyblock/SackUtil.kt b/src/main/kotlin/util/skyblock/SackUtil.kt new file mode 100644 index 0000000..c46542e --- /dev/null +++ b/src/main/kotlin/util/skyblock/SackUtil.kt @@ -0,0 +1,115 @@ +package moe.nea.firmament.util.skyblock + +import kotlinx.serialization.Serializable +import kotlinx.serialization.serializer +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen +import net.minecraft.text.HoverEvent +import net.minecraft.text.Text +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.ChestInventoryUpdateEvent +import moe.nea.firmament.events.ProcessChatEvent +import moe.nea.firmament.repo.ItemNameLookup +import moe.nea.firmament.util.SHORT_NUMBER_FORMAT +import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.data.ProfileSpecificDataHolder +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.iterableView +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.parseShortNumber +import moe.nea.firmament.util.skyBlockId +import moe.nea.firmament.util.unformattedString +import moe.nea.firmament.util.useMatch + +object SackUtil { + @Serializable + data class SackContents( + // TODO: store the certainty of knowledge for each item. + val contents: MutableMap = mutableMapOf(), +// val sackTypes: + ) + + object Store : ProfileSpecificDataHolder(serializer(), "Sacks", ::SackContents) + + val items get() = Store.data?.contents ?: mutableMapOf() + val storedRegex = "^Stored: (?$SHORT_NUMBER_FORMAT)/(?$SHORT_NUMBER_FORMAT)$".toPattern() + + @Subscribe + fun storeDataFromInventory(event: ChestInventoryUpdateEvent) { + val screen = event.inventory as? GenericContainerScreen ?: return + if (!screen.title.unformattedString.endsWith(" Sack")) return + val inv = screen.screenHandler?.inventory ?: return + if (inv.size() < 18) return + val backSlot = inv.getStack(inv.size() - 5) + if (backSlot.displayNameAccordingToNbt.unformattedString != "Go Back") return + if (backSlot.loreAccordingToNbt.map { it.unformattedString } != listOf("To Sack of Sacks")) return + for (itemStack in inv.iterableView) { + // TODO: handle runes and gemstones + val stored = itemStack.loreAccordingToNbt.firstNotNullOfOrNull { + storedRegex.useMatch(it.unformattedString) { + val stored = parseShortNumber(group("stored")).toLong() + val max = parseShortNumber(group("max")).toLong() + stored + } + } ?: continue + val itemId = itemStack.skyBlockId ?: continue + items[itemId] = stored + } + Store.markDirty() + } + + @Subscribe + fun updateFromChat(event: ProcessChatEvent) { + if (!event.unformattedString.startsWith("[Sacks]")) return + getUpdatesFromMessage(event.text) + } + + fun getUpdatesFromMessage(text: Text): List { + val update = ChatUpdate() + text.siblings.forEach(update::updateFromHoverText) + return update.updates + } + + data class SackUpdate( + val itemId: SkyblockId?, + val itemName: String, + val changeAmount: Long, + ) + + private class ChatUpdate { + val updates = mutableListOf() + var foundAdded = false + var foundRemoved = false + + fun updateFromCleanText(cleanedText: String) { + cleanedText.split("\n").forEach { line -> + changePattern.useMatch(line) { + val amount = parseShortNumber(group("amount")).toLong() + val itemName = group("itemName") + val itemId = ItemNameLookup.guessItemByName(itemName, false) + updates.add(SackUpdate(itemId, itemName, amount)) + } + } + } + + fun updateFromHoverText(text: Text) { + text.siblings.forEach(::updateFromHoverText) + val hoverText = (text.style.hoverEvent as? HoverEvent.ShowText)?.value ?: return + val cleanedText = hoverText.unformattedString + if (cleanedText.startsWith("Added items:\n")) { + if (!foundAdded) { + updateFromCleanText(cleanedText) + foundAdded = true + } + } + if (cleanedText.startsWith("Removed items:\n")) { + if (!foundRemoved) { + updateFromCleanText(cleanedText) + foundRemoved = true + } + } + } + + } + + val changePattern = " (?[+\\-]$SHORT_NUMBER_FORMAT) (?[^(]+) \\(.*\\)".toPattern() +} diff --git a/src/main/kotlin/util/skyblock/SkyBlockItems.kt b/src/main/kotlin/util/skyblock/SkyBlockItems.kt new file mode 100644 index 0000000..32c4aab --- /dev/null +++ b/src/main/kotlin/util/skyblock/SkyBlockItems.kt @@ -0,0 +1,24 @@ +package moe.nea.firmament.util.skyblock + +import moe.nea.firmament.util.SkyblockId + +object SkyBlockItems { + val COINS = SkyblockId("SKYBLOCK_COIN") + val ROTTEN_FLESH = SkyblockId("ROTTEN_FLESH") + val ENCHANTED_DIAMOND = SkyblockId("ENCHANTED_DIAMOND") + val DIAMOND = SkyblockId("DIAMOND") + val ANCESTRAL_SPADE = SkyblockId("ANCESTRAL_SPADE") + val REFORGE_ANVIL = SkyblockId("REFORGE_ANVIL") + val SLICE_OF_BLUEBERRY_CAKE = SkyblockId("SLICE_OF_BLUEBERRY_CAKE") + val SLICE_OF_CHEESECAKE = SkyblockId("SLICE_OF_CHEESECAKE") + val SLICE_OF_GREEN_VELVET_CAKE = SkyblockId("SLICE_OF_GREEN_VELVET_CAKE") + val SLICE_OF_RED_VELVET_CAKE = SkyblockId("SLICE_OF_RED_VELVET_CAKE") + val SLICE_OF_STRAWBERRY_SHORTCAKE = SkyblockId("SLICE_OF_STRAWBERRY_SHORTCAKE") + val ASPECT_OF_THE_VOID = SkyblockId("ASPECT_OF_THE_VOID") + val ASPECT_OF_THE_END = SkyblockId("ASPECT_OF_THE_END") + val BONE_BOOMERANG = SkyblockId("BONE_BOOMERANG") + val STARRED_BONE_BOOMERANG = SkyblockId("STARRED_BONE_BOOMERANG") + val TRIBAL_SPEAR = SkyblockId("TRIBAL_SPEAR") + val BLOCK_ZAPPER = SkyblockId("BLOCK_ZAPPER") + val HUNTING_TOOLKIT = SkyblockId("HUNTING_TOOLKIT") +} diff --git a/src/main/kotlin/util/skyblock/TabListAPI.kt b/src/main/kotlin/util/skyblock/TabListAPI.kt new file mode 100644 index 0000000..6b937da --- /dev/null +++ b/src/main/kotlin/util/skyblock/TabListAPI.kt @@ -0,0 +1,41 @@ +package moe.nea.firmament.util.skyblock + +import org.intellij.lang.annotations.Language +import net.minecraft.text.Text +import moe.nea.firmament.util.StringUtil.title +import moe.nea.firmament.util.StringUtil.unwords +import moe.nea.firmament.util.mc.MCTabListAPI +import moe.nea.firmament.util.unformattedString + +object TabListAPI { + + fun getWidgetLines(widgetName: WidgetName, includeTitle: Boolean = false, from: MCTabListAPI.CurrentTabList = MCTabListAPI.currentTabList): List { + return from.body + .dropWhile { !widgetName.matchesTitle(it) } + .takeWhile { it.string.isNotBlank() && !it.string.startsWith(" ") } + .let { if (includeTitle) it else it.drop(1) } + } + + enum class WidgetName(regex: Regex?) { + COMMISSIONS, + SKILLS("Skills:( .*)?"), + PROFILE("Profile: (.*)"), + COLLECTION, + ESSENCE, + PET + ; + + fun matchesTitle(it: Text): Boolean { + return regex.matches(it.unformattedString) + } + + constructor() : this(null) + constructor(@Language("RegExp") regex: String) : this(Regex(regex)) + + val label = + name.split("_").map { it.lowercase().title() }.unwords() + val regex = regex ?: Regex.fromLiteral("$label:") + + } + +} diff --git a/src/main/kotlin/util/textutil.kt b/src/main/kotlin/util/textutil.kt new file mode 100644 index 0000000..cfda2e9 --- /dev/null +++ b/src/main/kotlin/util/textutil.kt @@ -0,0 +1,210 @@ +package moe.nea.firmament.util + +import java.util.Optional +import net.minecraft.text.ClickEvent +import net.minecraft.text.HoverEvent +import net.minecraft.text.MutableText +import net.minecraft.text.OrderedText +import net.minecraft.text.PlainTextContent +import net.minecraft.text.StringVisitable +import net.minecraft.text.Style +import net.minecraft.text.Text +import net.minecraft.text.TextColor +import net.minecraft.text.TranslatableTextContent +import net.minecraft.util.Formatting + + +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() +} + +fun OrderedText.reconstitute(): MutableText { + val base = Text.literal("") + base.setStyle(Style.EMPTY.withItalic(false)) + var lastColorCode = Style.EMPTY + val text = StringBuilder() + this.accept { index, style, codePoint -> + if (style != lastColorCode) { + if (text.isNotEmpty()) + base.append(Text.literal(text.toString()).setStyle(lastColorCode)) + lastColorCode = style + text.clear() + } + text.append(codePoint.toChar()) + true + } + if (text.isNotEmpty()) + base.append(Text.literal(text.toString()).setStyle(lastColorCode)) + return base + +} + +fun StringVisitable.reconstitute(): MutableText { + val base = Text.literal("") + base.setStyle(Style.EMPTY.withItalic(false)) + var lastColorCode = Style.EMPTY + val text = StringBuilder() + this.visit({ style, string -> + if (style != lastColorCode) { + if (text.isNotEmpty()) + base.append(Text.literal(text.toString()).setStyle(lastColorCode)) + lastColorCode = style + text.clear() + } + text.append(string) + Optional.empty() + }, Style.EMPTY) + if (text.isNotEmpty()) + base.append(Text.literal(text.toString()).setStyle(lastColorCode)) + return base + +} + +val Text.unformattedString: String + get() = string.removeColorCodes() // TODO: maybe shortcircuit this with .visit + +val Text.directLiteralStringContent: String? get() = (this.content as? PlainTextContent)?.string() + +fun Text.getLegacyFormatString(trimmed: Boolean = false): String = + run { + var lastCode = "§r" + val sb = StringBuilder() + fun appendCode(code: String) { + if (code != lastCode || !trimmed) { + sb.append(code) + lastCode = code + } + } + for (component in iterator()) { + if (component.directLiteralStringContent.isNullOrEmpty() && component.siblings.isEmpty()) { + continue + } + appendCode(component.style.let { style -> + var color = style.color?.toChatFormatting()?.toString() ?: "§r" + if (style.isBold) + color += LegacyFormattingCode.BOLD.formattingCode + if (style.isItalic) + color += LegacyFormattingCode.ITALIC.formattingCode + if (style.isUnderlined) + color += LegacyFormattingCode.UNDERLINE.formattingCode + if (style.isObfuscated) + color += LegacyFormattingCode.OBFUSCATED.formattingCode + if (style.isStrikethrough) + color += LegacyFormattingCode.STRIKETHROUGH.formattingCode + color + }) + sb.append(component.directLiteralStringContent) + if (!trimmed) + appendCode("§r") + } + sb.toString() + }.also { + var it = it + if (trimmed) { + it = it.removeSuffix("§r") + if (it.length == 2 && it.startsWith("§")) + it = "" + } + it + } + +private val textColorLUT = Formatting.entries + .mapNotNull { formatting -> formatting.colorValue?.let { it to formatting } } + .toMap() + +fun TextColor.toChatFormatting(): Formatting? { + return textColorLUT[this.rgb] +} + +fun Text.iterator(): Sequence { + return sequenceOf(this) + siblings.asSequence() + .flatMap { it.iterator() } // TODO: in theory we want to properly inherit styles here +} + +fun Text.allSiblings(): List = listOf(this) + siblings.flatMap { it.allSiblings() } + +fun MutableText.withColor(formatting: Formatting): MutableText = this.styled { + it.withColor(formatting) + .withItalic(false) + .withBold(false) +} + +fun MutableText.blue() = withColor(Formatting.BLUE) +fun MutableText.aqua() = withColor(Formatting.AQUA) +fun MutableText.lime() = withColor(Formatting.GREEN) +fun MutableText.darkGreen() = withColor(Formatting.DARK_GREEN) +fun MutableText.purple() = withColor(Formatting.DARK_PURPLE) +fun MutableText.pink() = withColor(Formatting.LIGHT_PURPLE) +fun MutableText.yellow() = withColor(Formatting.YELLOW) +fun MutableText.gold() = withColor(Formatting.GOLD) +fun MutableText.grey() = withColor(Formatting.GRAY) +fun MutableText.darkGrey() = withColor(Formatting.DARK_GRAY) +fun MutableText.red() = withColor(Formatting.RED) +fun MutableText.white() = withColor(Formatting.WHITE) +fun MutableText.bold(): MutableText = styled { it.withBold(true) } +fun MutableText.hover(text: Text): MutableText = styled { it.withHoverEvent(HoverEvent.ShowText(text)) } + + +fun MutableText.clickCommand(command: String): MutableText { + require(command.startsWith("/")) + return this.styled { + it.withClickEvent(ClickEvent.RunCommand(command)) + } +} + +fun MutableText.prepend(text: Text): MutableText { + siblings.addFirst(text) + return this +} + +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)) + } + } +} + +fun tr(key: String, default: String): MutableText = error("Compiler plugin did not run.") +fun trResolved(key: String, vararg args: Any): MutableText = Text.stringifiedTranslatable(key, *args) +fun titleCase(str: String): String { + return str + .lowercase() + .replace("_", " ") + .split(" ") + .joinToString(" ") { word -> + word.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() } + } +} + + diff --git a/src/main/kotlin/util/uuid.kt b/src/main/kotlin/util/uuid.kt new file mode 100644 index 0000000..14aa83d --- /dev/null +++ b/src/main/kotlin/util/uuid.kt @@ -0,0 +1,16 @@ +package moe.nea.firmament.util + +import java.math.BigInteger +import java.util.UUID + +fun parsePotentiallyDashlessUUID(unknownFormattedUUID: String): UUID { + if ("-" in unknownFormattedUUID) + return UUID.fromString(unknownFormattedUUID) + return parseDashlessUUID(unknownFormattedUUID) +} + +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()) +} diff --git a/src/main/resources/assets/firmament/filters/screen/always.json b/src/main/resources/assets/firmament/filters/screen/always.json new file mode 100644 index 0000000..6c21cc9 --- /dev/null +++ b/src/main/resources/assets/firmament/filters/screen/always.json @@ -0,0 +1,5 @@ +{ + "title": { + "regex": ".*" + } +} diff --git a/src/main/resources/assets/firmament/filters/screen/always.json.license b/src/main/resources/assets/firmament/filters/screen/always.json.license new file mode 100644 index 0000000..5f0659f --- /dev/null +++ b/src/main/resources/assets/firmament/filters/screen/always.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2024 Linnea Gräf + +SPDX-License-Identifier: CC0-1.0 diff --git a/src/main/resources/assets/firmament/gui/anniversary_pig.xml b/src/main/resources/assets/firmament/gui/anniversary_pig.xml new file mode 100644 index 0000000..7cefac3 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/anniversary_pig.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/firmament/gui/button_editor_fragment.xml b/src/main/resources/assets/firmament/gui/button_editor_fragment.xml new file mode 100644 index 0000000..6444236 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/button_editor_fragment.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/firmament/gui/carnival/minesweeper_tutorial.xml b/src/main/resources/assets/firmament/gui/carnival/minesweeper_tutorial.xml new file mode 100644 index 0000000..b03cb4a --- /dev/null +++ b/src/main/resources/assets/firmament/gui/carnival/minesweeper_tutorial.xml @@ -0,0 +1,49 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+
+
+
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/config/category.xml b/src/main/resources/assets/firmament/gui/config/category.xml new file mode 100644 index 0000000..e34b018 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/category.xml @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ + + +
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/config/macros/combos.xml b/src/main/resources/assets/firmament/gui/config/macros/combos.xml new file mode 100644 index 0000000..5141125 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/macros/combos.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/firmament/gui/config/macros/editor_combo.xml b/src/main/resources/assets/firmament/gui/config/macros/editor_combo.xml new file mode 100644 index 0000000..50a1d99 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/macros/editor_combo.xml @@ -0,0 +1,42 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/main/resources/assets/firmament/gui/config/macros/editor_wheel.xml b/src/main/resources/assets/firmament/gui/config/macros/editor_wheel.xml new file mode 100644 index 0000000..e4dc2b4 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/macros/editor_wheel.xml @@ -0,0 +1,43 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/main/resources/assets/firmament/gui/config/macros/index.xml b/src/main/resources/assets/firmament/gui/config/macros/index.xml new file mode 100644 index 0000000..f6a1545 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/macros/index.xml @@ -0,0 +1,27 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/main/resources/assets/firmament/gui/config/macros/wheel.xml b/src/main/resources/assets/firmament/gui/config/macros/wheel.xml new file mode 100644 index 0000000..19922fe --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/macros/wheel.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/firmament/gui/config/main.xml b/src/main/resources/assets/firmament/gui/config/main.xml new file mode 100644 index 0000000..8953ada --- /dev/null +++ b/src/main/resources/assets/firmament/gui/config/main.xml @@ -0,0 +1,29 @@ + + +
+ + + + + + + +
+ +
+ +
+ + + +
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/license_viewer/index.xml b/src/main/resources/assets/firmament/gui/license_viewer/index.xml new file mode 100644 index 0000000..c23153d --- /dev/null +++ b/src/main/resources/assets/firmament/gui/license_viewer/index.xml @@ -0,0 +1,65 @@ + + +
+ + +
+ + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+
+ + + + +
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/mining_block_info/index.xml b/src/main/resources/assets/firmament/gui/mining_block_info/index.xml new file mode 100644 index 0000000..6404995 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/mining_block_info/index.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + +
+ +
+ +
+ + + + + + + + +
+
+
+
+
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/npc_waypoints.xml b/src/main/resources/assets/firmament/gui/npc_waypoints.xml new file mode 100644 index 0000000..25027e3 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/npc_waypoints.xml @@ -0,0 +1,36 @@ + + +
+ + +
+ +
+ + + + + + + + + + + + + + + + + + + +
+
+
+
diff --git a/src/main/resources/assets/firmament/gui/pristine_profit.xml b/src/main/resources/assets/firmament/gui/pristine_profit.xml new file mode 100644 index 0000000..8787b8f --- /dev/null +++ b/src/main/resources/assets/firmament/gui/pristine_profit.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/main/resources/assets/firmament/gui/repo_reload.xml b/src/main/resources/assets/firmament/gui/repo_reload.xml new file mode 100644 index 0000000..9397bf1 --- /dev/null +++ b/src/main/resources/assets/firmament/gui/repo_reload.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/main/resources/assets/firmament/logo.png b/src/main/resources/assets/firmament/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..e3f063ac00da0345cbf0eb2e83016b8d8bb0b1e6 GIT binary patch literal 19770 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 RxqQLU80wkmzQ5-Z_b;_Id{_Vg literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/shaders/cape/parallax.fsh b/src/main/resources/assets/firmament/shaders/cape/parallax.fsh new file mode 100644 index 0000000..bc9a440 --- /dev/null +++ b/src/main/resources/assets/firmament/shaders/cape/parallax.fsh @@ -0,0 +1,53 @@ +#version 150 + +#moj_import +#define M_PI 3.1415926535897932384626433832795 +#define M_TAU (2.0 * M_PI) +uniform sampler2D Sampler0; +uniform sampler2D Sampler1; +uniform sampler2D Sampler3; + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; +uniform float Animation; + +in float vertexDistance; +in vec4 vertexColor; +in vec4 lightMapColor; +in vec4 overlayColor; +in vec2 texCoord0; + +out vec4 fragColor; + +float highlightDistance(vec2 coord, vec2 direction, float time) { + vec2 dir = normalize(direction); + float projection = dot(coord, dir); + float animationTime = sin(projection + time * 13 * M_TAU); + if (animationTime < 0.997) { + return 0.0; + } + return animationTime; +} + +void main() { + vec4 color = texture(Sampler0, texCoord0); + if (color.g > 0.99) { + // TODO: maybe this speed in each direction should be a uniform + color = texture(Sampler1, texCoord0 + Animation * vec2(3.0, -2.0)); + } + + vec4 highlightColor = texture(Sampler3, texCoord0); + if (highlightColor.a > 0.5) { + color = highlightColor; + float animationHighlight = highlightDistance(texCoord0, vec2(-12.0, 2.0), Animation); + color.rgb += (animationHighlight); + } + #ifdef ALPHA_CUTOUT + if (color.a < ALPHA_CUTOUT) { + discard; + } + #endif + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/main/resources/assets/firmament/shaders/circle_discard_color.fsh b/src/main/resources/assets/firmament/shaders/circle_discard_color.fsh new file mode 100644 index 0000000..ae46059 --- /dev/null +++ b/src/main/resources/assets/firmament/shaders/circle_discard_color.fsh @@ -0,0 +1,22 @@ +#version 150 + +in vec4 vertexColor; +in vec2 texCoord0; + +uniform vec4 ColorModulator; +uniform float InnerCutoutRadius; + +out vec4 fragColor; + +void main() { + vec4 color = vertexColor; + if (color.a == 0.0) { + discard; + } + float d = length(texCoord0 - vec2(0.5)); + if (d > 0.5 || d < InnerCutoutRadius) + { + discard; + } + fragColor = color * ColorModulator; +} diff --git a/src/main/resources/assets/firmament/shaders/core/rendertype_lines.fsh b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.fsh new file mode 100644 index 0000000..057f31f --- /dev/null +++ b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.fsh @@ -0,0 +1,18 @@ +#version 150 + +#moj_import + +uniform vec4 ColorModulator; +uniform float FogStart; +uniform float FogEnd; +uniform vec4 FogColor; + +in float vertexDistance; +in vec4 vertexColor; + +out vec4 fragColor; + +void main() { + vec4 color = vertexColor * ColorModulator; + fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); +} diff --git a/src/main/resources/assets/firmament/shaders/core/rendertype_lines.json b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.json new file mode 100644 index 0000000..e4537ca --- /dev/null +++ b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.json @@ -0,0 +1,17 @@ +{ + "vertex": "firmament:core/rendertype_lines", + "fragment": "firmament:core/rendertype_lines", + "samplers": [ + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, + { "name": "LineWidth", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] }, + { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, + { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, + { "name": "FogColor", "type": "float", "count": 4, "values": [ 0.0, 0.0, 0.0, 0.0 ] }, + { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } + ] +} diff --git a/src/main/resources/assets/firmament/shaders/core/rendertype_lines.vsh b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.vsh new file mode 100644 index 0000000..b2d0f99 --- /dev/null +++ b/src/main/resources/assets/firmament/shaders/core/rendertype_lines.vsh @@ -0,0 +1,62 @@ +#version 150 + +#moj_import + +in vec3 Position; +in vec4 Color; +in vec3 Normal; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; +uniform float LineWidth; +uniform vec2 ScreenSize; +uniform int FogShape; + +out float vertexDistance; +out vec4 vertexColor; + +const float VIEW_SHRINK = 1.0 - (1.0 / 256.0); +const mat4 VIEW_SCALE = mat4( + VIEW_SHRINK, 0.0, 0.0, 0.0, + 0.0, VIEW_SHRINK, 0.0, 0.0, + 0.0, 0.0, VIEW_SHRINK, 0.0, + 0.0, 0.0, 0.0, 1.0 +); + +void main() { + vec4 linePosStart = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position, 1.0); + vec4 linePosEnd = ProjMat * VIEW_SCALE * ModelViewMat * vec4(Position + Normal, 1.0); + + vec3 ndc1 = linePosStart.xyz / linePosStart.w; + vec3 ndc2 = linePosEnd.xyz / linePosEnd.w; + + bool linePosStartBehind = ndc1.z <= -1; + bool linePosEndBehind = ndc2.z <= -1; + + if ((linePosStartBehind && linePosEndBehind)) { + gl_Position = vec4(-2.0, -2.0, -2.0, 1.0); + return; // I don't care for these people + } + if ((linePosStartBehind || linePosEndBehind) && false) { + ndc1.z = 0.0; + ndc2.z = 0.0; + linePosStart.w = 1.0; + // TODO: use mx + b to find move the two coordinates around to extend lines + } + + vec2 lineScreenDirection = normalize((ndc2.xy - ndc1.xy) * ScreenSize); + vec2 lineOffset = vec2(-lineScreenDirection.y, lineScreenDirection.x) * LineWidth / ScreenSize; + + if (lineOffset.x < 0.0) { + lineOffset *= -1.0; + } + + if (gl_VertexID % 2 == 0) { + gl_Position = vec4((ndc1 + vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); + } else { + gl_Position = vec4((ndc1 - vec3(lineOffset, 0.0)) * linePosStart.w, linePosStart.w); + } + + vertexDistance = fog_distance(Position, FogShape); + vertexColor = Color; +} diff --git a/src/main/resources/assets/firmament/textures/cape/REUSE.toml b/src/main/resources/assets/firmament/textures/cape/REUSE.toml new file mode 100644 index 0000000..ba721f7 --- /dev/null +++ b/src/main/resources/assets/firmament/textures/cape/REUSE.toml @@ -0,0 +1,19 @@ +#SPDX-FileCopyrightText: 2025 Linnea Gräf +# +#SPDX-License-Identifier: CC0-1.0 +version = 1 + +[[annotations]] +path = ["firmament_star.png", "parallax_background.png", "parallax_template.png"] +SPDX-License-Identifier = "CC-BY-4.0" +SPDX-FileCopyrightText = ["ic22487", "Linnea Gräf"] + +[[annotations]] +path = ["firm_static.png"] +SPDX-License-Identifier = "CC-BY-4.0" +SPDX-FileCopyrightText = ["ic22487", "kathund"] + +[[annotations]] +path = ["fsr_static.png"] +SPDX-License-Identifier = "CC-BY-4.0" +SPDX-FileCopyrightText = ["Tendan"] diff --git a/src/main/resources/assets/firmament/textures/cape/firm_static.png b/src/main/resources/assets/firmament/textures/cape/firm_static.png new file mode 100644 index 0000000000000000000000000000000000000000..b01511c8378752d63e87e9237371f97bde51f1ed GIT binary patch literal 42249 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

%ak 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�J(7|Ys_GA+Y5Y!^^ywR>tKWP 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 Ri+1~Jbk*$2+e^3Z{||?RM0x-K literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/cape/firmament_star.png b/src/main/resources/assets/firmament/textures/cape/firmament_star.png new file mode 100644 index 0000000000000000000000000000000000000000..520d309c2d7c8398104aa567d63e4330a2508436 GIT binary patch literal 1141 zcmeAS@N?(olHy`uVBq!ia0y~yU<5K58aUX1%y{W;-5&-9 z7IjY-$B>G+w>S4@i3Ex;JlO1ba@nSB;zt_z6*}}4mI(xRwMN{Y<>Wg1MpSpl+NhO# z6`H0s32YRoVQ{>pvb$CC`x~owZzgycS*s-e(2F^A?*87-zUTh-PT&wwaA;s)WMZM5 zF@fp+`)}Ret}dpN6&)UYU=ib6zrxcqbwm1x`E?dOv$YMgm{gcp`kWSgWqa^FOeFQ+ zPo=WA59i-~Ex!C5f0Ciyv8S&W3R-mOulHe6Zj6)WlKk+rxNdLnjX#&<|Nr?=Dc~RP zf9k}7_0y*Atv6#hyhA`gJdK^v{N9$}^=9|Z8grCHCahyqsQz)}WW)J{^C4_CvTxrM ziS(OSZQSzNu1w7D+?;c635B~m9tP>>>5G4SvYKtd>Hj77)-p3m{yD$ir|4^GQQ!XS zCJ(Od)cCaT|JtKgY$k9u^xsUk2k)yK zCI3{;b!j;8kaJE((3QpE&Gm=B6iIzZ-fPAiG1rIl)yqdSPfm={Ua>6c#uBx6iVg{K zjmNSXZthM$`1H>Hm>s|4_2)&`?R+&q^X^Ph9xsTLSCx+ypC{F7l# z$&ZWQSijwNw{k&gX_=$GIM3&M`O=pkXD?~1hvxEs5wOBPg&6)%=fZ>eiC2o_Y+jAc)I$z JtaD0e0swY5VB`P* literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/cape/fsr_static.png b/src/main/resources/assets/firmament/textures/cape/fsr_static.png new file mode 100644 index 0000000000000000000000000000000000000000..de9cf354fa6af1aaaa578e90e8f4ae8d78185142 GIT binary patch literal 21747 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/cape/parallax_template.png b/src/main/resources/assets/firmament/textures/cape/parallax_template.png new file mode 100644 index 0000000000000000000000000000000000000000..7084c12db3d6db2037ff8e58c9fdf7b4b26b687e GIT binary patch literal 352 zcmeAS@N?(olHy`uVBq!ia0vp^4nVBH!3HE3&8=$zQk(@Ik;M!Q+(IDCcsop(5I?(+0?g?mb7Ek1g4`s$-M^E3LEDdaux+gg`ACu-fbH9Olc+i^CP zEJ}7XUz5Y4{?*E+I%G3`{i)&eXa(Shh0Fn4w2CfFVdQ&MBb@09y@?k^lez literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/bar.png b/src/main/resources/assets/firmament/textures/gui/bar.png new file mode 100644 index 0000000000000000000000000000000000000000..97a3ccc77d2c9855e24b122371893e0e5060ca02 GIT binary patch literal 679 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU~J8Fb`J1#c2+1T%1_J8No8Qr zm{>c}*5h!1NUMMFRwYqK>kf;Q6}xV@y2@mWb_FP2;aY1oW6u}&j7t-i?6BZk$I4zW zwwh1x+%BsfTul%7J63m3UerCMB0eZX@Nw($-xlxZ9j^Y)=(P8Y$!cZ3j9t0QCUY9j zjuv!Y|H6skuYiG?@#z^;mx$E7em$>h<+~)C)BE3_e--*!jG0NPaE|0M-#vaddo!iy zeD73Vqq6$Q^COSdVki8V_`2(O{+w<-ZX4sIv`fWD1d}%2IOZk2dD2Qje?j+9-{m!m zuQ#5m?A{!azT)`HUFIiNRyVIHmfy8L+d`4gG;QBRN)cp;zpCA76 zb4R!A_1yBK+Zj^MhBOM=E;+{YLQ+~WLZ9zJ(KW6U?eW|Wrt7c$oKP6^Fp|0B*{za8 z8*)sK^uB#*tas~ruKD}<#Rt;9O`EIZ(K~aEthLIqIIHIJZdQ&{atuP{SsV&~&P0Ft zcIK=k$C-IY&K=rQ{eb_&ZH5vTrrH~e_c`p;*r)nci*F9=$3@cn*q8m3jb^KGxY6_^ z$knBB#U(+9J5#@uxUQ5ur0pMB=fLn-PL1`%isg}vj`GTK%XNHQ&WJl(*O;vS6an-; h17B){XPU1sgBFm@0TKX$OTm*tl&7no%Q~loCIHXwh>ZXM literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/circle.png.license b/src/main/resources/assets/firmament/textures/gui/circle.png.license new file mode 100644 index 0000000..d3069b8 --- /dev/null +++ b/src/main/resources/assets/firmament/textures/gui/circle.png.license @@ -0,0 +1,4 @@ +SPDX-FileCopyrightText: 2024 june_hibiscus + +# This line is needed because of https://github.com/fsfe/reuse-tool/issues/1057 +SPDX-License-Identifier: CC-BY-4.0 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/completed_commission_background.png b/src/main/resources/assets/firmament/textures/gui/sprites/completed_commission_background.png new file mode 100644 index 0000000000000000000000000000000000000000..a19f2279a03b37492675d2352e409d30ed734d45 GIT binary patch literal 558 zcmV+}0@3}6P)EX>4Tx04R}tkv&MmKpe$iTcuK31nnT=kf92KT~x%eR-p(LLaorMgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7NufoI2gm(*ckglc4)8atOf`EFfT~$W zCY2O&`BfqKiVz|gz&L^uGxa%9Ov7`0-NVP%yExDCKKJK{CjWHa-`QDULg#c~(3vY`@B6UP))qkMnP zWrgz=XSG^q?R)YUh6~!tGS_L2AcaLNL4*JqbyQG=g*dGmDJC+spY-q#JARQ|GPx>X z zjFl*R-Q(ST-M#&LrrqBUd{}a-{5(Fe00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF;2#4H7B@`Mr!B0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN w7)eAyR4C75l=#m;5@2Fr7}YSUVYq4l0Em|XH+oKaUow-xSb|1`6yIT~f z7#==BA<;q+BCkLKu@Mr%0tG1rK~f27jG&~50bli9gPM9~cDrqr#59qA-O1g1?!D)H z=iKj}dv@o!lIc@3((g^jFf7Ac>?wu*ZfMzQH^VnI^Xd=KwWA8J;`L6z(qI6ZmQ>6F zlA&iw$k`yLScYIjpkD#)4v-BUqupz{$?RVQ`M!j_4&?C(9m9sPq+l7)H$r1U9uEC3 zXzI$iuR|akpEUFN6Wq;%QBObB>np)oD??j37ueIRO<-t&;c%7}IGbRn!M|m5Z$t*t z3x_v?1Ix2&VPT24un-SxAw{i57#3?>{EEByz5LA9$IJGW&dofHcMRJqd|FhLSvBJM zl2PZI^tZ9UdKX8B0wfy}N; z7Y?>vc(A@|_J|L@_G0UU8yd<>Ph6g}ynW))RmBOD!jzusDLqJ7EPw!Ckz6=^5G+?7A7E#=8}eE*WS@_xUtdsgH6UtT4=o4Z;U z<{qzax3)j&I@8s3Y47y&m5VDH-Gi($Dg-d9kOQIp0m!DBctf~Z+=^|DcTk7`mM8}c4=Nf z*0wI49lHW47*oqD^a|fJK?((|q8#!gYb+2p&I`-Qi-kq03hB5XRjNTZ(fRIS0#{`> zF~{zsec?j1KrLRRp|VBO%cVtC5-$^Zx#>AE0RRF>7x7r2Iv5dRZoWJM_TOi4h%$W1KJ^{_xu(P-2f<*XsCl45wC zr)ZX9SrRnJNL^4DV`MOrWkAF+JSZY*YFJl8LEOL;{h=D&O%Sk-_rw}r(IiwgiR|TyPu}6D!pX&i_KUux6?NeFi+z4)9%^3sSH{^ zpWq2eHAZ+|kDD<33vx(OWx*6hC+AS?te<3Q-a*=sB9gpcp-Emw9CC0BhY;Nd${UR6 zVo*W`6o6Y*z;W1RMdq9wsW^BZAQ*-8v#dzk94<+5*_}2&*B4@jrb1SV)qSHfpk#n@ zIh}T!o%fTp>~xYgT9!zc%<-gXr)`L{^LEb0o6*RUFeRh~L^w`0AXXwO9IP}K48nzi z60e(Jt#PmBOi8tbXt2pRS(nSsICz=`H@ve~X*SX#kckGS zSvt)X<5&dP3=k_Cc?tmLJnTg%)R3r$wDM4>+D#;jZgSZN*GU$2(Ie^zK$B&-yr&FL zq*;MZk|y{JC)_ek6in)-0o0V%zd+ zVe%H;>npnDN_xg{g1uJOnFmubucx5Axb3@7nlf7OTT@$>uG?AhYC-eLdroB!8%?0b z3Ed-(p53&WTR3LTUEi-f?G`wu)^%VY2Saqaf+^E>~tx6d7dy?)R8i`UFNwBzEX zv|)IDJ!VNs1>xf1mh(a7<)*ip^M5g?pSD!(-r1@+MxOaDck!HD3;TRl>2~zeVu%6r N7ESl;nf%1EzX5br(slp< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/generic_vanilla_widget.png.mcmeta b/src/main/resources/assets/firmament/textures/gui/sprites/generic_vanilla_widget.png.mcmeta new file mode 100644 index 0000000..9d84425 --- /dev/null +++ b/src/main/resources/assets/firmament/textures/gui/sprites/generic_vanilla_widget.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 24, + "height": 41, + "border": 5 + } + } +} diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/hotm_perk_preset.png b/src/main/resources/assets/firmament/textures/gui/sprites/hotm_perk_preset.png new file mode 100644 index 0000000000000000000000000000000000000000..a19f2279a03b37492675d2352e409d30ed734d45 GIT binary patch literal 558 zcmV+}0@3}6P)EX>4Tx04R}tkv&MmKpe$iTcuK31nnT=kf92KT~x%eR-p(LLaorMgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7NufoI2gm(*ckglc4)8atOf`EFfT~$W zCY2O&`BfqKiVz|gz&L^uGxa%9Ov7`0-NVP%yExDCKKJK{CjWHa-`QDULg#c~(3vY`@B6UP))qkMnP zWrgz=XSG^q?R)YUh6~!tGS_L2AcaLNL4*JqbyQG=g*dGmDJC+spY-q#JARQ|GPx>X z zjFl*R-Q(ST-M#&LrrqBUd{}a-{5(Fe00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF;2#4H7B@`Mr!B0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN w7)eAyR4C75l=#m;5@2Fr7}YSUVYq4l0Em|XH+oK0)+jEP)EX>4Tx04R}tkv&MmKpe$i(@I4vf_4yb2vVKwq9Ts93Pq?8YK2xEOfLO`CJjl8 zi=*ILaPVWX>fqw6tAnc`2!4RLx;QDiNQwVT3N2zhIPS;0dyl(!fY2y2%?iW-O|P1% zL|n{dSH<8fdJ#eZqZp8xWz0!Z5}xDh9zMR_MR}I@xj#prnzI<-6NzKYFssBH#50>! zgY!Odm=$G}_?&pcqze*1a$RxxjdQ_afoF!zbZVYBOe_{USm|I^G&SOB;)ts0lrLml zRyl8R*2*>3x+i~OD5tM1bDic05?I6%B#2N@LkVS65v5fp#X^eq;~xHD$1jmfAy)~E z91EyGgY5Xh|KNAGR(@*IO$x<7z2X4K(lV!-^aGyJOTXAz?I(iR~o?VC+YRJ z7C8d?w}Ff6wx;X>mpj1FlOdb3Bl&3x`8@D`M&FbL25*6$HMh6cK29HiGeSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{002`-L_t(I%k9*m5r9ApMA09HGEmn|D&7J>QN$_w2 zxk2TNl~1nm738uxK=l5kl-3Ra+Xr%9cM5WMB*n&}3M#0ef1r6I?w$f90hp~iwill@ V6cR?;Uqt`_002ovPDHLkV1h3B3h)2` literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/item_rarity_background.png b/src/main/resources/assets/firmament/textures/gui/sprites/item_rarity_background.png new file mode 100644 index 0000000000000000000000000000000000000000..c7192c3ce2d553bfb8c63468331608e9e725401e GIT binary patch literal 5061 zcmeHLYitzP6`nQmBL+KQnNm{GG~h#*|G zxF;M7hwmmTK(`PSw-Bx(&NV|WaV;Pgfc_AaYF7zS1N9LoHK4cgc3JK!b?Wbc{JEn1 zBaqh>F?N3j`c^^xb0{pxwNSqdMSrL;?%N>SSB3KnniyGFb7ys{*WD71bP^MH5yUoV zpR8@AoAofXhvR{fW;vObWL9#6z|k@<5GBNehsudM=yMf{>)7;s;c@D^&Pdg#4gh|? z9t?JdgF$!NG-7%J6GZM?Upp9ReZFzU3t!&$)ZI(V*MEH^G}1n}dC5y#_mk0z(;L5A zz2>o96_MqKYL~SCFRZMUbwHjyt`@f1kpdx-(?-F$v;-Rbu^cL`;qLGmDx+g z@Tt-0GgR5gQGBwd|MtV%m+bxi`=g7m(%)Ee;PIfzkX-XJV``` zH{AA%C;nKE_q?<1Sl^o$PW|waKb5;9+wU}X?+fmDy76q^%1ak}FI@Ns_wcn{#4CRD zchzU}Yaw`V*P}gFPozy&jid)@hJro0WZGFse?u;f)IMyv6&%-70rJwbzb4(f79hKQ z5jv6%;$FRVr-`@hY>%ot`&3CI8#Yw>b21Plv4z~ZWFnQ3a{qCXv)ZO8aD;G1HTATm8!5NVi4(DOh+P9^r=kI3*ZlL z4yC<}hxR6u-kCizR`Vc`6eo1u9+~J+8hg8N#uzYF+&qX=*6NuQ_C}jxuuY2V$+Tk> zIB(WqnmUC`510uDqp4n;z)2v@!2Fn5cuS8>J8Rb5>=wtInG=EGrub)}CvA7YfQm%q zkf9FPgN8!^(w?uZ8LFdD_R3MPE#$X_|AW>~)ZvI>P~y_0ZFr&IGbzhM5eIZF*`TH{B4` zlX#1TY^O1TBtU|sd6Dta0>@8-?!{&X0?y`iGO5#|sq!XZL=ZT762-AMor*gR_Oi%e z3^*3qaSF_i9&C}FJZhLx!$<_kspLG>9D(hmAq#~dt;1+j={h=@uGiD7Oc(63=^}=v z$ATlI`(m_v@Lu%ou%{=!q?F`+wK$?bMFg^bjK2^lnqHD{i{RcKOs zQ7VohdlbWUQmyue z_zJ?)Imq1WoE5xlHagpj?d1W7QM5#{lI<{-mwj~6Vcwf>BEyS3<{{8ERbeTf)kI2? z>S4oZ^*k$Z3@>mWbKngyQILJYr)Z)G%Ov_}Nmv4Q4vK^;;|4DXRpf* zFj10u@zXQWM=LP~sVpU74pThj9STW2PjNmW#!9>tV^rZrn`r+L`D~KEnm|=&HTPISBWb@r5})`w)V-&A8Gt&%p{A(# zdvzk8A6~Pdba&}Jd1c3rGaV=HZ!Rk<6OOp9)Ya8pIe20`pU<~1TD0ijZHsF6ZeFmd w>a#1#esg&*$tMpVeSEC!2MkS*96nz{w4JZs=)a9`0BR!K+#dSg#vObA2d&h9ga7~l literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/selected_pet_background.png b/src/main/resources/assets/firmament/textures/gui/sprites/selected_pet_background.png new file mode 100644 index 0000000000000000000000000000000000000000..a19f2279a03b37492675d2352e409d30ed734d45 GIT binary patch literal 558 zcmV+}0@3}6P)EX>4Tx04R}tkv&MmKpe$iTcuK31nnT=kf92KT~x%eR-p(LLaorMgUO{|(4-+r zad8w}3l4rPRvlcNb#-tR1i=pwX9p)m7b)?7NufoI2gm(*ckglc4)8atOf`EFfT~$W zCY2O&`BfqKiVz|gz&L^uGxa%9Ov7`0-NVP%yExDCKKJK{CjWHa-`QDULg#c~(3vY`@B6UP))qkMnP zWrgz=XSG^q?R)YUh6~!tGS_L2AcaLNL4*JqbyQG=g*dGmDJC+spY-q#JARQ|GPx>X z zjFl*R-Q(ST-M#&LrrqBUd{}a-{5(Fe00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF;2#4H7B@`Mr!B0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbN w7)eAyR4C75l=#m;5@2Fr7}YSUVYq4l0Em|XH+oKEX>4Tx04R}tkv&MmKpe$i(~43m6)Y&?kfA!+MMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx7Fxu3aNLh~_a1le0HIM~niYrxnr@rv zWJ1j5R>j^|1QEah!Wfd7Wz0!Z3ZCQZ9zMR_#dwzYxj#q0nztC>6N%%@Fm2)u;+aj` z;Ji;9VI^55J|~_q>4L>zBx-kgE(v zjs;YqL3aJ%fAG6ot1va$N(v=_o)^dY7z28Dfo9!tzK?&Kfh)b^uQq_$Ptxlh zEqVlmw}Ff6j;8DZmpj1llOdb3EBR>(g#z$?M&FbJ25*7jTC2DAK29Hi40V;d0S*p< z@gilfd%U}^ySIPOwEO!3MILgLpTsw-00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=L!T65jXV(D+2%k02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{001jVL_t(I%VS`mH~7!M@c%yp!+)|hqqCVPbrB;uwj%?I hUBJXJ3P!4nJ=qZCRW5rVYG6n|b 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png.mcmeta b/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png.mcmeta new file mode 100644 index 0000000..94b9a1d --- /dev/null +++ b/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 17, + "height": 18, + "border": 2 + } + } +} diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_knob.png b/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_knob.png new file mode 100644 index 0000000000000000000000000000000000000000..8ced28a93d76e73c98c85053168a5d696c153647 GIT binary patch literal 4583 zcmeHLYitx%6rL^es-c>uN~tKr6qJXv^Vr$P3|$KBE_8t{O z^WAg4d+wReJXKaYWl(lOHilt?f+hZP=m$W%c|bq-9osy99){WSP<2oZ2FF-4H-g{> z%$C-(rN=kJeU_~c)(86Mpyk-Iuw3X{pyh(x)Hhp!t*_OugYj+Y@kSVrO6!>R4A>5W z{sU+%jPs!11xH=JS;WeLg%E z*HtZyFf6%h-m~74Ps;Khn^CcLZROCD_>pC6gad)V(7Ici%ZBgIep6`q@Z3!=b0bFE zpI%tk-oASKxika z*2~eA2aKt^2hZHTckHAm@db1)yJ;yO{A}yykA8c7`Eh&urpuSEykUEvjM+H#;nE`UtG-VSYuk{#yrb>p#;p!nwU3)IwD8u?y>FbO*S8d$ z;pW``wei{D-|twzYO|;Ay?!SSF8`RmZ-3PbZKZX2+TGH?T>q%r*5-onh}v(0?<`w; z_W5V#Z~J4~FXg-L>07un>-b)L%Oj_YFL-CI=bXQe3{*_Gy5#4Fm)h1m(E5Y1>Xf`w zTaC5X9G-gW;t6v0`Q_)-swKm0i@x8wy}qjA{DRMKpMBxeWuXHr7QVZ(Yng4vyPA{~_V*C0psCc*~2Eo%ciT&C)8X zjq1>JLDnO7QPCx2Pex+aJ{A=xW1?J#3|vArTGUIN+VU}hYl@esa)#(o%!g{VlDTnI zF}Ji*o?9pL3Q;^hyC^9DKm-{go{WT}2_fkvEL;J`rkEmdOU0=364j7xK0S_b&d%9s zGLY07SYmuOUKCeUq1-j|XoW(8Uzh7m_kw;eVXiMI zx~wUJH5A@VQF0KnyFq$yLsEkY~0Jm#^qcEbI zc8NTRc#b1E74f7bNeoH56pzeG9H+RLE)X-~8f2vy?&_5ZrI=7OEin?Sk~ETd@J8iH zo&#@GSy4omXA$Q~d85d}WIY}cVLP>mSc9low8mP)BwUzS7W5LVo$i#Bg+)UJ11~XM zi`FMQCn~iFsxU;8O~%dAPPc>iIBD7e5p^ofMDYYEE=?!-E%r zK5Ti3mN4{qlO;->s0uVEb(gvgYt~W1aqCbBqMQmLAvPez@)NL9Q*x~stwB&d(&^eE z*Zv_D+)f7eOI1k;c_fk(T?*-89Efx>A}y<&$KiIW-O&@eYBY**G_eMF1g;=Gt>+j% z%G#*W-L)HQk+};%7)iTHhBgU<=N#uu6GmPC5G6OO(on%5JE3-QZU;kpTpWT^!y}gF z6u0DYcX#@~hiE>*{}y5qWtPQ`O)a9X+4ht|mpTg6q-0Q^q1;oMdY|UZtgP4ZN~ha( zTmhha7wHkdy>#``)guOaq}-cby>#`6fgUOMX4n5lS9a$cBZ|U5dX4ZtIDJHrhPTOn z(zGf5)YpMOeOu4nJ=qZCRW5rVYG6n{w z*`6+rAr*0NuN~}d3Se*zG`uX*8o)92g6Nc^3)svz%f4&-ENrf~CZ1g9`_{sbGx_X-u`-2T6~Yf;o1Ds zWf}s@bVkV$76NtWu5HWhPmMhEr8elZ&Hnl~uMLf4*uS)Xuah}$AAY|-zvkb~gjvh} z+8k~*zp~VxN&ofxWEL-#2kYZmYWFD|zOy%Ye@H}S!jgqLO2D+s;OXk;vd$@?2>?Md B=Wn z(3n^|(bnUzgUr$R;H9owd~X#VO;}jAsk_VSnwH2yrxl`6r3O2{aL?MJqN&%{lzs4E z|It;=-J93(t!q;F!T9LSgC#GNRR8H~Zt3{=V2Awsced~DF*>b2WwKeHF=JP1N|2}F z^mtL`^&AQv25AD5XGYGSyu`%j_;uTwn!Vkhb>0`(_c?A&FgllX!&u6qqs`llU}UpHJjye22(Nbr%s(94?f zCw8tWy7y>JsPvj*|9^)99OEOOS)C1BvY|uOLtx>8My^#G1eS-YA9ZQ_Hd*eU;Bozl z-iqO@Ju=)Y9Gl<#IQaiT`S!HJqC>u1s*V4|Z~v2EX4>trJM;GaC}CUe0+@&otv)P-jjXv_U(P+x&P`IZe1w4(0S#~I$*T0C3(BM0BIoj>Abrh zNO2Z;L>4nJ=qZCRW5rVYGN2%PiKnkC`wMmsVN2=T*XErE3Q3l@MwB?`=jNv7l`uFL zr6!i7rYMwWmSiZnd-?{1H}Z)C6(xGQIEG~0dwa={@qhvk!@+=HM~@{Bn6xXF$SrVg zw`R1jJ$*)Y`YNq!Q41Fr-^!f1bM-4NlVctCs$aaAQ#P+b-ayHXMLEd@gK9}GKKGYZ ccCNHOkIM#ef9rykK+70BUHx3vIVCg!08Z))BNTq&N#aB8wRq^pruEv0|xx83O~W znx~6nNJZS+DHnSW8HgM>@p9R#NwQ0-r);dsReg}alw~cX(J}vdy7uF5R=4+8UpM=3 zR$8L}q1^Ob`};Npo3}PTXFF!G*>->3H~)`f$CsLISohlS{m(~oqWf8E_TSfMy}V%` z@0rgvPWq>d_8mAMyl0=pI=??+AFd|Oy1%`V>6@jyptyn8a{grvwdVqlu=ZSf*{qo` zzgVP@adFA71g;y;Wn5zpXw0>nF{*Sl1V%$(Gz6#+0-wEw&wu`7_W%9A>^JGr*S~)I z`FyFTblk?qmOGJ_b{Pu@7NNr(M}guI0`vp&~BwsU3w878h$*>mSu(tBVr%HZkh K=d#Wzp$Py_SY1Q_ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png.mcmeta b/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png.mcmeta new file mode 100644 index 0000000..a29299d --- /dev/null +++ b/src/main/resources/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 176, + "height": 222, + "border": 10 + } + } +} diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/uuid_locked.png b/src/main/resources/assets/firmament/textures/gui/sprites/uuid_locked.png new file mode 100644 index 0000000000000000000000000000000000000000..9e66cb5be622856c4c2abe13e7c646ea782b8251 GIT binary patch literal 597 zcmV-b0;>IqP)EX>4Tx04R}tkv&MmKpe$i(~43m6)Y&?kfA!+MMWHI6^c+H)C#RSm|Xe=O&XFE z7e~Rh;NZt%)xpJCR|i)?5c~jfb#YR3krMxx7Fxu3aNLh~_a1le0HIM~niYrxnr@rv zWJ1j5R>j^|1QEah!Wfd7Wz0!Z3ZCQZ9zMR_#dwzYxj#q0nztC>6N%%@Fm2)u;+aj` z;Ji;9VI^55J|~_q>4L>zBx-kgE(v zjs;YqL3aJ%fAG6ot1va$N(v=_o)^dY7z28Dfo9!tzK?&Kfh)b^uQq_$Ptxlh zEqVlmw}Ff6j;8DZmpj1llOdb3EBR>(g#z$?M&FbJ25*7jTC2DAK29Hi40V;d0S*p< z@gilfd%U}^ySIPOwEO!3MILgLpTsw-00006VoOIv00000008+zyMF)x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=L!T65fLW{uKoZ302y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{001pXL_t(I%VS`mJNU2lADPQYu11LNYmAI!+s=56kt!}= jA~_78Hjjc)Ft`8!2!{*?!kh6q00000NkvXXu0mjfHYD(< literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/widget/button_active.png b/src/main/resources/assets/firmament/textures/gui/sprites/widget/button_active.png new file mode 100644 index 0000000000000000000000000000000000000000..36144a6a3ce612b2d4579ed5ef988ba9a5108763 GIT binary patch literal 8353 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_checked.png b/src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_checked.png new file mode 100644 index 0000000000000000000000000000000000000000..1b87c55ce4113c3b1708dc016b05abb6f74ca954 GIT binary patch literal 683 zcmV;c0#yBpP)EX>4Tx04R}tkv&MmP!xqvTcx6v4pvZc$WWc^q9Ts93Pq?8YK2xEOkVm2O&XFE z7e~Rh;NZ_<)xpJCR|i)?5c~mgc5qU3krMAq3N2#1@OU5R-E(;FKEU6oFxBje1FB{j z>10C4=2nH^EBY{uFnk!4n5oZ+VhW!1bx(a%cQKyj-S=npD|wRvK7lySbi*RvAfDN@ zbk6(45mu5E;&b8&gDyz?$aUG}H_kbWYY7*5n`d(!Ey()lA#h$6Gs(QqkMnX zWrgz=XSGset$XqphVt6VGS_L1B8f#TL4*JqHIz|-g&6G`DJIf%p78LGIDU~_GP%lN z5bWxZDATo^;8O94SD{Unl_YXY@@uVBi+$U32HwI>+e)kfB+nZh(VB zV7y4#>mKj!>73iYJ+1lu091T(nmX;sCIA2c24YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2j~kK4+RNh^%0i<000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0001jNklp(fy3i5UkONFAzzJMq=bx(9<^E0RVoBI9obQ Rey9Kd002ovPDHLkV1i>w9k&1g literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_unchecked.png b/src/main/resources/assets/firmament/textures/gui/sprites/widget/checkbox_unchecked.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd9aa49105a014786a8a40f986ccb7f6627f44b GIT binary patch literal 614 zcmV-s0-61ZP)EX>4Tx04R}tkv&MmP!xqvTcx6v4pvZc$WWc^q9Ts93Pq?8YK2xEOkVm2O&XFE z7e~Rh;NZ_<)xpJCR|i)?5c~mgc5qU3krMAq3N2#1@OU5R-E(;FKEU6oFxBje1FB{j z>10C4=2nH^EBY{uFnk!4n5oZ+VhW!1bx(a%cQKyj-S=npD|wRvK7lySbi*RvAfDN@ zbk6(45mu5E;&b8&gDyz?$aUG}H_kbWYY7*5n`d(!Ey()lA#h$6Gs(QqkMnX zWrgz=XSGset$XqphVt6VGS_L1B8f#TL4*JqHIz|-g&6G`DJIf%p78LGIDU~_GP%lN z5bWxZDATo^;8O94SD{Unl_YXY@@uVBi+$U32HwI>+e)kfB+nZh(VB zV7y4#>mKj!>73iYJ+1lu091T(nmX;sCIA2c24YJ`L;wH)0002_L%V+f000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2j~kK4+I;DS5ck-000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0000zNklx%2$z^)D2hEpaeH zA;WfGhRZg=>2E^{8Sgn9NjE-IE#j`MtYLm{_xF|=9}WdDpYlmyK5>cnDhor#M|syE TvngkQ&SUU&^>bP0l+XkKTqsA+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png b/src/main/resources/assets/firmament/textures/gui/waypoint_unselected.png new file mode 100644 index 0000000000000000000000000000000000000000..3c47e75571002b0ceb577db88c67423694b389a7 GIT binary patch literal 217 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 GEB^;-r=rsU literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/socials/git.png b/src/main/resources/assets/firmament/textures/socials/git.png new file mode 100644 index 0000000000000000000000000000000000000000..d7ab359ea7c7cea8049c117f0bcc47a5664959cf GIT binary patch literal 79519 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Ν zGQ!L`iAu${#Ss=+N}7nL@g&g2Cn6O5P7u@wheRbGL=)q(MxkF)L`_^r(h{~9A!`jV zl}aI|(MUD|dXOp3}SPefN^E8A2aO{t0D4eZ?@aZT$OX6+#MCIs5xD;_DoCVAj?J3naoVk7RZX?gC7_!T+cDz=C z1-}cQ%&I&av*zdjS+W$WEfqHooC$7wptaP86tx7mNJYu|H*fzZVTzSs3nOY8u<*g( znVtrjne6wj?N;6Q<6?t;VcVL^k4tsS|KM<00n~17vnprwJ9K z8M@Fp4SX~ey*#tcV)mXgL~&hd06DPI974J-Zs0ho$YsGa0)`|$3>fYz!om}1LMO>) zG<_7oX3P*a_9W}&oI^yIr8F7cCQ+UtQlx zWenj=R>fa{jA8(rGGH(<8=z`6(I&FP8=#7bOZr31;T|GX#iJ7%po%f0@o20ABWuXw z#J>%UOeQ1ahj?+4@jLT}(D{i7Pj%%GOPTaZ6*rs%=!|COV2~IXVbUjQ%x@UV2ht}( zIH`5`GI<$slC#dDR#X#zMkNeURm~(%WN*n}JQWe9idGD+#6G}`U~0gu&E7#qUZAlu zYsWJAf!wf>A4$d_hnNh^Q6M85hD3gf=rKW!k;6cN=`wCt21ce4u3tvkJJGNM8#Bd$UdAwn8}>@8;3sHLeN`>={_UPfyC+k5KYk}R&u0= z5Vjx*7*jlCWS7LG!eqNl=oZ)zY)CnAK$YH-rF79FF-r~9mPmn-(b0jlY4wniYchEp zDLFEVW6H3YL^EdbwM4#+A%oK7>Jr7djhjIRuskVs(VvF+w}|91oR}f1&NAt;!w_>O z5mgc{L_f<=6+)>Mx2|&~$3=PMK2V}1r zT6`iiLQ;8V&O$c^HG*jSQY0J2>mtFkwXqtnWy1~Fr=Wk!Y!fxVo>V!EKS>Sk_N zSJGmRPROgRxm!Ox4pwJXI%D`=@Bj8>NVrk9PscuTLh%?~1U*?XXJ1ED%;kjamIt{` z{kc$kFYqi>ytFjcNHlSNey~Q)Xh@oRh3+dm6mI?6P=x0Ibp7X1vnk5^UE`IkG|Nj( zw)du{9p$Z*>VJD?>6Dy{BJIY*4dcY92X%TsQ&j9Y^k3d}r&~**94;R-D9Ko|Y4+Z7 zrSrX{l`{N{*ZqnSsQ)7{=S_HFP-Z+$UeR;vct99ul5pbCfVA9 zd=k#awRLx%`_Hu-N!BqVas|LiASTWyJ5@;}Xyd-%_`(I4giu-7;`{v^lN|N5S~lN0Z+T$c%S54^f4~5=o|VxJ}H}sXiQA?x7f6nj%I1jC7fJ= z+-W2(%3E;0_R>USd+TWAeaITK<1Mj9o&ibiQz3n>Ma>iLeHNOgJ$3VPVh%HqYK|G| zF~8t~qO;Siy9fV4mDferNKZz~;aHUZ*B6Co9Q?yO3+?21>3njMFzF}`tsraswCm`9 ztwFvpsgV7zH3+vYG8X3EhHBQY2*njM2ucgx6D{lNAFvPVZjTUCAt^y^Bne>DzB&K( z1$t9D^!9(PAxr3(<8|X=_iw+C?f*acX-)kTpf=JPS(Gi8* z4A=*o<6&A9OIDC!<=zHQ7>VY{s2#JXn=sXRp~?sa8IOz=$R15w1pD4$ zvXjOLKx<8P-UY{3!$hY_>XK)F%&nL)0=^7xi|Ex;oug)tfPWBKl)k*?5-8<>P9yr( zJhXyEoPdSkXNI9amw=yiG))x@V;DLPKO*=s`F77ng4ZH4o6bwSFmnD`GXL>Z=hBh$ zSCjd3cxmsa4L2YG*|Al#^6i>O+Rr31zig`Wbw~t`3MS0lLjc_A79 zqccT$Fs`@C`AM-bAp6^Wz(kK@X`0r-h&c71B8)9B$)u414h^xqm^W zU^sY8YWcSLc9>5M2ahTvgmY!p5t_$oKqu7*mD6Vi_ENbt7E%#5(k&_yGe`2zuO5@0fOga$W`LTazf z&i(7@2vx|y<7oPqsm}k742l~G^Y_(g+=epcFlM?TwaMlICUPUdyUs!IrM$F8I8|nt z86o4s3ipshZBa#>Qecg--$_qaPvHEaN&uXAg1> zGh%D(Rl*wIeB%+|=b?tP=htY2z^vVV6D-45A&PUVX__kbs1U`oed^jJD9JE`6&m6zaWaS=g z`>r~s#=u4yf<7GIS`J1kg1$KNSQn;09P}c{<8%{bS}IgcpN#;|orv=t;e_SFpc_FZ z3se!EOt9PMBj-z#`B3+NKN9|Ogulr+V081KuP5x0!1>uw_N_1*&K?daUFJe7Li3#A z?Bt7~Dof4IJvfx>A^x63==pZS*&~FjjVI=8=#^+x8o|sM)IfP)rZ*(>!>Ws5Mdl$??QvJZH9HCidh-Lf^6rcgrUe64AQe0Mq zeKY)8Sk`m|3;f(jFg=TXFe>$(53eT`Z2@_%!e{9v_4lX%yE8&_8PYl=v=`do(#^wdnEWMlywwz z6{U_~W(H9)all?~1opom_LiriS7#*lZixK_052K|ema7;g@cFg5!hSDgRHm{Kvvcx zWR-#`g(V!9$qy#osHvQVNbGq1>lyyvUfKuGW$k}aDb8N4o|NPDExgjff2_zP=!1jH zi(FAYH2O~|tF(D=OQH3aOlypKO_M@bnu@7aLu8^-y|4aWeZ`2pKU5MPN);Q|r5$g3 zBKN}9(C3!2{-fHM1{s}I^SyTEcP7m@*Lgg@Z>f5T2CGEFrYKF`ESqH#WMb^M-q=x2 zD(y^B@DC8|`t-wV+ZD&!g_S9ZQ|uoJig2j00)s_cuKX26=br10roZpgH@W<7Ww_a+ zOL}b=pZUIfxNKwplhUR+iMelI8HrwI=-j_Wx)eqAaOauxyQ6tMw|Sk>Jl}oIyC^CKD~_=&R2w*k zqvg=%*Rw9mxNKDjjx*h(Y1XrLqjGQ40-fNOh0YzHj^r)5K1oYd*P)f$_VMMvM!Yy@ zWp$l8oA8x2dyfjgI+)6by`1an&Oq9w=DScJu8{c)5{u;X34%QobPA5rfZT^tCLjg z>g$WeD2YF6EbCgEzl;q_d!8Up3GHwlamQS7*ZXq--)AxDHUX;j0drZC)0_jpu2`JY za4#|O0Y`i1zT%q27iE0%=YHZTcpT@&lvR#`j351#G;YPpSX_uWnB-?YTVI?T{3%D-z-fol%=GqX2an@kT~GD4sI&6svrxoqlXbodSr0 zcgupxQqP*5Ykj41@uo@s_3IrF3~Hx=7D}NgLf|0x6tJW``})o7AcwfXCZi(t{$sq( z8x{Ug?Lmj{jvdr|vEs?%mPeqncjHrC!r>P41?Pg}y@I@qpFFRWpu7)a$?pd4wLM1z zEtWALs9yu#D+e|#j#Eqw^bhT9<#l!=$Y?Lv#&O9eBIYg7q6oA^erdg#+xj83t0X4q z$D|$)uP{YK^U6CwQ$S9uwC~hw(6@mNb2VCy{aev`ILqdIj$X|>0&y=wyoVl84*a+4 zSSeY~0X^0gEiFxx^NFE62e%e6Y9khq$gw<~_V(p+dVj0JY(d@S%IlvmtTpeb{fxT{d5lO?Wqe5SC{%Y87(*!yogmPn`<=%N74^@t@eLYBg*1CB74BL(IaMJI`l*&?qM*D-aoUEd8qUyUTbnZl*Cv$GQHo z6ved$jq8P4V)E8q2i|6Rt;tge${Ry(#$ukaaei_;RG4>wdl%V-mEXLPk$JOyGX3Z2 zSHT|-H61Gp@?X>XMe6D%|0z)5(%Y_bLTTA8@5fu3)hTM>El@s5=z`+P1HY18b`@XA zYIE&zd+W2Cl2-!5pnvlcn@BYpfZy=U{C%`_@#{Ng;kQFZQxf$cR<@@$pq{gT=Z=o{ zYghZMjXz$_8BI5>Qg4ob6)dW(SW1QL+;yPrie5t%kLQsJ$`YIM?0~|}<|UbXv!Q4~ z@7RmbuUt2nSQdZcs|qNhd|ccY1K`&41vmQ}&)GRI_|nZ2SzNyff%>}E)BLe$)FJnw z)WMHgwsaiF*m%&}QX%eNQxCUTspl+U<>t1_Qe1PJxTDK*1N#K6Q5Ck30bs5r3WGMi z29WOaj?S}kyXCK3tUAtXA*f-$4|`U^tWlI-{g4_`#Sf*vy@>XC zsa+RZR!eNXbyAapJTy1~%_gK!1)7fud;bL&I*>C-)*c$wD`^$8$)PVs?*Q>n&f&?K@NO~K-r zzgr6>e>;APLg3!O-loN-=bclKrw0|TMVL-WAeA5)ieBZ3OwF*h$hw($;_DIC7MEr% z%6nyzPjOZ7$J~kq6wf}(t<`LAsPj=?4CE@5cpwWeXu z>l?Mzk6J6>=;+LhQn<$9Ip57+Hg)OD4`#3>;%KSA$s%SBU%$HApMP;nWaU&TWg?&C zT{~0_J@+<67m%+pX}wbWayeDOGW!U6pHbNJEj(yk z@z;a18J5OSOFWvj(yF41bLxH@P|t%SElV3a{W9+Vo%H5a@%`=<5GtsOxeZwjEk^sD zn}49+;MZ?Y5CkUlB6qsD6Cmo>yUqGz#6Oh*6m`D2oXY0)?Z8(q^h5u)Wsd{+?B-GW$=@f!Ud?2Ra=2(Mfha4>JK`%s>h`=<0gtg6#V(=nMWH=p7c z?|ouA!@!p?0<2#f>r3lkLx+10s`;N<3ALg)#Vb`m46qIRU4>gv^|7I`krWy`5x7_&h{>eLOTp@c!0=W4+`6T z-|KfE;LC5)m-OoEd7WDZmD&|M(Af)d4z!90wU@RlFO62|Ek%^)OB0}`qu1TG{cgbJY<8On}l>7zUYYROuV-H^oeotB=eIVdl&u_IF zxY52>BMvA-QH=_Dgk-fPx%ItsHq9Rku8vZD0z;fR7-Xa&Hc$|dD(a*kFV1`aewmjp z>m5P)3A)oqj$mY=*o}Gsf=5Q7TYIAKJXWp|E7u-1d^5&;TRa>IMX~uSC7~HnQhN;V z>K`b(YgJY$#>wybEy`$(deB_feGE6!(OVa7@%G(!VDq2tG8Dfb4SmoC8J{Ygr~c*x z*gI4@F0oG)x~2=&Ie&Mm=Dq!JWI(T~3<%;xw%c@yC6e16F~|FIA=u#=12 z%yftSDs=`@#*7sea2J)j@yt8IG;Jt-YnH>jB5utjxl|kAFq2R)-vtvc}#nSM1e01)W;S9({dL zMm!lKXJm~@v5CE#|L!;IA(#qxp+QCzetNwxP$|i19IR~##}52lwOr5UN}g{9k{G)8 z$-C37o26uB5^ot(1HAxL`t-lSOYnQYhmkPeSvWPJ`yLw^1Xq_AKi?$AUKjr6z?ZPo zr%#8Q=9iUXAS`W)YimZU`2_-@&;S)L=4*L;R;nCmmTuBFk|Z@qsQsc+WAwZdssV3q z$TVR+NU%K<5AaD?=J2v5%=+6$JL zbvH=0)}wSt-hs8yS#SzR3HO6K>4S^twm0rBfOL*Vb>d)uCT#F2MU>svz}~bVRaPIS z!<;!RO{#hV=sngzsYYm^6o{Gws$0{}EA*#;toV4(!xK*>uoy~t!-*5O``ssJJ%xyV z9|T~60I7&H?%V+bMkCcK2sc7l8V7oO7sbwoY{di2q1)bPN zthpZ|-(x3iF*Fs%UOrpdA5o}s(K!ux>WYotlGp?02US7J(GmlM#YET;!d~tEg4%Da zn#ZVdTBo)y3cr8kml!!&jA5$SQEh;(TwCW&!!%jJw%3?Y@6AsG4@_m03|N!U1LWBV z7qlqh?;sXc7u5nC<9s*-g`#2`xDOFBOrNyvgE!#*wEK15KeFn*`;jsW*w69t_Jj}$ zMidvXN}QTM<6`0ohCAfvoA@&v!9bA!ey)Gx+kY-tNw1yYfOly8kTHtL81n~uRbG2{ zyj28ZM5`X1>tE+D0lgo3+rPL5xPFfflAu=Js8(||kSLCx*H~qP8G3=qD7mjUl2)35 z-=KrQ?l?z4x9C-$AslQz*Q!&R0Bt@rP{?157(p4B;{JgcEo(g-)4$s|E(KWKh-Ebq z_8ID<(OJShQU39k1D$WZ^h$IPWpBI}pl<~zYeAKpx}e?=Q2a1UHW&^3 zIzp)tXp=q`;TBkvA1V`^*FK6)^?%wYZI#6HDMhG{ZbUvi1m@VN1mtC)Yf7Gz)KgS3 zlk(fVth?p98l0D2(=ySoftIDlXta#a1lV6zPZaGB>4tVKbn8m<^B;T;M#8F+A-wXqXfmg zy7yI=4aE6YsrpO1pYl5QqQJ+Zz!xC@rXi>s3SB-Pe#J*Hm~awbdv>Z=T~uiK8ySiH zmfpz7jmXH1<>o5I+r%sdOX~aAqEt7JU{7@ofV9To?0U4=sP(X0P+t2u+VD(XeK{m( z+i>NJy9PpDGwg=wP%uZ1L*0Xx?t~-ChIX*Ja#G;@FkTf|dkO4BICx&lpN48ZPrc8j zc{~*uUD%q66f1!%=V)MJ$>kxOv*%?lE&k;E@-%BNgp0uadv~<<8|S<21l#nRRd71P z@b=bE)#uD`y9AjJ{WoMj)UE|ZtqxEmefU@^&j|^VhOCEk35wrbg4@ibf6K4gQ?}J# zWU0CH3f+}XOu3@1qlp#96>!`DZ%P0Vt*=+RI+Xj3o294~Y~gB~PfADT4Y2&iz^97V;>gSl)eP@?2{xQPiQ zzi65T`1J`MO;Tr-L7`lR6rBvEq!!~jjL3SVj;z4+&=N0hxn@Py_!QVt&%VBH`1Fl1 z;t^z7$#~`~jji~%XN7keB1A~yrVuYNQi`pI^ZGt^9=dKuN&Xv? z7Wgg#Q)m!p+IMk2gF}BBF7HyDBg+CFAC-1-3kRrWIp1oFFYwIB(nSzI*jV_Vi|)_c zJWK`bLDIo5y&aBVDKKI7bo>$Z%)97GxpJS_Jo62JsU_aLR@FvkIH9rXHy-Vh&{+IJ zNsR3cfi4lsB$t8P^1P8Dq#G+9<#6HwZYx1~l&eJX9dYVe%^Y93)^ z4GJJ7)%6wxMBjNCz1PngJo>Moe_UxKEGFJT8T`{2ip6s79gDVnC~Sos*eDMR%pzU)?qJ~Eilvs6a5JcB^~c(@W0q(-VhgR8^(yy z`oIHgY#E$^w=Hr`UTYXDw(-aDTgB)z_zTv7XW*5J!1<3B1lt3$!EU;EWs8rki0&Iw z44@c@4qo)Y)@$r9eY=S}@!S-)63QS}X8AWTS-G<`-ZnR|uy1SO&M9Ja>K-V2Xv0NC zN@N~-4(wq6Dk*q=Xf24AlDdkH3PPl#E&E7HZKnrC@y3CDl0#-} zKcc{NABbzxvgQ$^A>Z+bw2G8UKQF}JoKI|ZqDKpVZg^2x2>M3(iXqA?3CgGqqH^b_ z%Jv7=g9&BZGYFgHmw~QRpT*US&VT(^5#z%~$Xhbd1AbOOvAVtda){a$#oBA!cM9Sh zwduzZ2D%IOE;RD1H^vNtlW@0k8gQt3+Kr?*CD^zNl0dTZSSezUQZGy_t)v7=^>tn| zDA(&?wh`A2ZhlIEiev@!9tilTB7Z(m??2EyiE^xX0Gh>b{+>cp*>LNKzJoH8_@l7F zG%?vgoVM^^bRR|23zGB1KH4!*_@N}9T=X&Y6!n)X!SXrV`;T5^)#zaIkcmlNHnf(} zchI98I%QxqPAC=p3q%Nx$_O9pijQ*~!ka&1)K7pGDV}5{Ud|DtxDo?F6Z>5y@b?f6 zqhI{RD7$DCn8vw@`wS_tQZC*o6`ZV>!Ov)o$5L+B7efK)Af#ECRMC}a@P}?1elZ4T z>$sr^sW>-C>k6pM@XG)KCDr=zT4IU;fH?aQ3xN92YayV4r;S>`Q>Ze=Rkr>n?XokR zs(!S4neRt0sa8wWtFy3497=EK9gunpEx;1!wC-)qVwCPFkY|qx&U8TYLJeF2+ataY zE?OLejL}N`8zjkn3@HMa3&e@wy$GuMu#I_QDv&e@)R5vY#vj@EBVLQFF1W8}=nN+F zv_2BmGq^7H>4MsOEKRB#+%G9AQrg-k-H#!#l+!YaR}7$83}c@JbRqD+;L*Ff_W zf105t2dQlz>=T4uu#o<0kgMl`9T3hM|Jajni_Ek%21B2rywPcseKI7o=5PQlgtjWU zsChr}QVvDGYwLGu*}b(lyQMoUIJiu2)v8r~mJ=n-<6fw((OB2WZ*AQ({?A`8pHQsY z$635%rnu_*^dr*K&Z^E&IWhL5sry!m@fTLDc&2)Tcj9I1uABKAKkr;R`LAcfM_ZKT zQr7U6C!fujeYN=Ot3&s9>~>H5px@BlA6)kI!<_n6bz>9FqKo_c4Xdht?ky;pNm1Kf z9YRIw5ToR0qF!PC=KAi}n03^cISp8^y#EvehAG-WH6#?&nXJBj!R<-#rR!V2eb+^! zC|VEN<>6bH>IUtema1 zR!QkZgVC#=7rEfaGH)RmkAX{|938NB>V~$NqYh}((+4^+o1nSjB&3}3c>5*?Zv{4* zg4#+(fzCz+c7iS9sn9>Iqn$h7$rPZUB*> zT5_mbZ!BQfENQ#O@aAYL^A3bbNm{v14Bs=M*c#xv*c|oxb$${MZea^TCjbfL)-E^X zA42@M*RoXgcBngZJi3-E(OVGYwJ6)y8{m_(Se>NL;ts%|e(V7%6dmG|6@C_goO{T` z5Q@5q{que(;nzs_I~9}HYw<%CACNHs7cbNRX1;?qABt_J?tgG9H@0#kT$bmwAZbb{ z_{B(?-eW?9EbNqZVUx>O1KWF2aP8YKEl!S4T(ES+wsN+E56?!xFHoMhf3!ZZt?f=! zREaGWiy6`apW3$dMSFsqw4k2yhYdUl7@K7K09*Qttcwm)bTlY7sI|2K1J@9ZotZ>o^dQ#I>HUWi9IHBGWe=2=i0?%M8{H2;vP zT#oGC-V?AicuY`>*ad)mJon}o<&y5Byx}Sz46RP)mLfcJHWsVmXU!Kt5$)8|I(%RDnH%6;$)}de?-;9C; zifx0|u>eS4)NC3s9jcC$$gX|VYyrP6^CnvJzmKj)%DuN`X_6<0xX{H(Q7b@)=*_DL zaJceK{{Z_7Va0IC3WIS8OO*YSjbTZSrD|o9KUO$_rPiX7N6m~$+Z*=H0;;9_-()(X z5-83BJHvLTSFD-@yv(V(#o_$>3_#l(j+;1J5i7}(#lh{u6}eBw%G2}m>f@2wmZ3NW zu1;`N$doe0vJXBnV8ZuP%MRQEWueEz2`#M!_L2VQ%+~dpsBe2L zszLG=!M0iecLgXaByFTu7XW|7#g#E5$ zInCYqyIT9|sr6rwkUtpL8#sxw9!dW_h`80O6W-kP^SGXn@L)isS1j~`{hKCHuPd*8 z+n+nf#$5*zSenNxm;GD683NvFP&r>kIE|r9=N4oc`ZxaRZ(dAQzeo|SZaK<3j6Cx_ z49v&??pCiyW*q|k)RYsD_KN1L3F^T zQR*g;7@KZ!#O{WU_PYgGsE9pi}QL?cnPcBew5wvbJWO+C8-LQ>RqYB0*VJ*VP?^qR5{QzbiTm z3<)2;pki;tLD`8`GLJBDmY~?iU<8|xHY}l15hdnfE0bKP&kIrZ;VWA-QDpe84P5r5 zS7id)-)goPN~0_M`_+y8+|s=9Vt(g0rUk5p0`J zKJV>lJK%*bz=0CmrudUXj?d=VMn6Ce9Vb1?Z5-Qp)TQG}t`^JC8iFjP_}v8H^c(QN zTkrI%@;zPEhdQE^#5l(5>yM~x`BMbX=;6iPSO|H72afvL|2Tm)37XH}Zj+qNnQ~qx zb(%PJ92A3V1ME}T+w}QS`(b@Fr_3Bog^o^%0e2&iJPLAv22b|1#Wj}(gxq*DvdtM> zEcZQ_MfVL}=OVp@=HhL}i14(?bfqwc(y{kr8D9g2B zB3G~!@<5KfBFqqAn$&2%1}=R}v)NV*Mq=qSLh&7-ZXl1(MNn@Z8O5sDG)<>$+x*8W z_uS`oa&a-y-2uWvpgzT(il}X`uDpIo0|Qj-A4@+JC?Dq)AkP}dLwG(8)fp}^+b3(f z|16nEUHI|h#}+5h6zGp-`+{;NU`EfjP%kXB@StKtHI%=l?tf%iwe=KkY)B z)c2>{#_n&{HW*F6!-<$jauaOK;muSK$4WhTPj%B=G?>a)vTNhPXe5tN6ZtOaY-B!f zDxOI_scgGC(W-QP&SF*qiFz;*d||^rdNV{D>~*DRo4wcjRKVUX?-Z%X6~9=Yqhkz- zg!_+$Hk*>IK+(E&AjApmP(*V--un8rp|VSG)B*;@*`s47H~S^0T#}aBV}yp=k|gEpO0Dw;@o+#g`oKJLB;$)5^$3VaL9ddt6g%o zKmnG6!x%VSa)Z4Ow#7l~LAJNnm8x%*=Zbswz%zli|J(@fxEE35Yy6tLYhVylv$L-I z+~aWPY-mL-x+v1 znkd#KnJ%?2YJr<5wg(=E@#ljEh{C3<6MKgOiTJ&!l0`y+MGp3^ikXa=M-D9QDqVB~6%?mDZ8A~O7C(ru#DQm^HV@*l0 zGP~nZK~yhTEgll`;khxv>+$K}RY&Traib% z=j;DVs)AV9?g$Ag=hhcgX&H#oX&Vgpzy14mN=FF9Yoe@7s&lO#+}c(ivxceLZgwu9gfG+ zN27wN{%Dr(qhl2GmMq{0Os0gffX#xpz-p|1QL(X+Hr@Wfna|t*<5yI=*txh4o*7d! zps9{;3v$mO7Jk>pxaUxb3YDoBgM5Q2^cv&@ya20YL)YuyqVgR5Mo~BMRRTWT{SZWV?OIPyLZqrM zq+U)l>S&%4mnpIVb9;RTVj!RZ8-TO#fUaF+QuKaJ?d)1L3n)Ug4`Q(BDMWb()ObNi zLRR#PA)9?o`aX4`9gyP&M83wiZ>SjuzHQ0*>;>FOM_<5@`2rkCWyheN z8hpmM9QjHS09ye-Hr5`fjh9$d5_2?$NsgDAm38zf_Q;3<9vkC%Gv7*3}YC>=4!>ckR(G)zz$@p3qr5~k|l=IlEI8obR6#edhTfR_DT$B3` z>MmPC&#7aI`LGN3v408R6$#rYH zyta?I@gC}c@c#Wuw|p1v{TM#Z>Y+I0>7V9!cjMA@Hy`j0Q0Ai_5md zDB)ndfqgS2Fx{&OyFLG~sj>Q2Q^ija1!TR~FEHD$l=Imbn4Zx9yJTtx?A!5aMy?2n zw_X$0c{jdHwlc5x`Nc%I!cMn;_qeK0q<0rua= z@r^X9o7F3&$u*u zWxq?H!Ifp6H9h$15BJM=Mw(upX8=czWR88y-?D9a4--W%M+r{;S3n?+Z(set2A4n! zy`LV56L69L+;W?I=Z*e;^)41I6c_uLNJun&1Ol2xCg|>c)RgvV$^O1Fc%Yf+#*O_a7_n>;7rglRA7K-! zBN0}c1_GP|>_Xs{Dy$=Ya_iTMV;}lkA5IDOy$aQW8{50e4_|zrQaMwq7++-O6vLMj zzy7T;)~+KmK|FnfxF)}Ya8G?~<-U$%#Gg9c{PLjS+P?KI6Jh&C&Ahc|JhbLZ!b@3= z3sGE_Yy0vm`l1q11+QRJFRGw?`Z_;Ka0R_8w`A}6&iuB2C-&cl_YrS=D*4lC%KCl# zSgcR#Sg%O1*t5{2BCEEs%L^o-3k74prjoZ&&82?&(o&C;ZbBbgfn%|r;r{-s6Y=eA z?uQrcEkR3c6vBB~q(smFZ2M5EvNSAlsk7e%jx>&RD;Prm;K-8hBl{Hs-(5qM+2{7n$4Egv%q;&6GC=61o_gWy z`v}Ft;&>f{(bXp)nuOlo(}g`|P#dX=`*Qd6^%a-!iAnm3!+$0aknKXcB!a@y-21q* z6{z;!O8#0>7&nP=bM(MZBI5ZexEjT#NV+g^bu5Yz(hPHFs<4=c4`|qrPNR zYkW2Q!g5f@>Bi;@)N<SWZkm0$OM={jYoEG9qiyI%azHfnbI4lI|Xy?Az-XRi(3f#QB? zi^%Y8HuLFu*Aj45G>uy1vaA2o5tV{gUS<~l838}-g3^pl2LIG{-ueRmqZU+WQ9(V# zGVZp%Stei4Embn|xc~xM)bKz34i+9a;>MR!iBc)avv=-4l^9f=pA-XsVS{h*9mUCz z9Q=ZU6O8IfOD=JCFx=Z0j5&w@chyz=8xA2t@Wg_$%=a;lFGlWoG+1?i9L070pN=5} z(o8*6a8x~^kAvTEsnJ|3%_owm`6Y={MQ=S2~2SNl#s z9{Wr1vTr7f=;bdD)YZIvaMcJm(dc2b_Kg3)1iE{5hgMYIAl}ip)OLMpP|cgdqTUv; zPuHUF341x*X!OJ*Hi}-na*vi-&(DFqw-N&hGm6Fddjx%quP*WQ=Z+ zT(f!~ zLE5$XR%ESmVEq;6zKf7T`Z#MFjG~a^C0DIDQOu$)APZn-*?CCR|xK&0@%&k@;^-pS{b-M6RtO2iBTyC zUKJ5^$D>F*68f*ekpphfVW3Jhoh_+eb6TPGSYH2KhyLD z(mz7UpVv??Ok207A#GrLGM}===X)@_v)l*)mF*BS#n9LJdO{JA(HIvqxLEU{sUH7& z3OD6@*3Oe-vc|od^$*n2mfd!_4*t7uls$V3@g7^=9v$!=^lEd%Jh8bu{%6wjBxcHI z?s+@_g8$x>qwT={`!G7Z6R$IWhs)}#q_}s+5jMkt%7CTcfp>|y+t3$)C!G0x@H`9} z4-5{@+y;Z#i7Wh9e)btyeLV`+o&a4z$Oy z+5f>lN|wUH+}h;qZ}a=;H`s|xatl+a>Pld-AEG{VJ}Q3C6HW0m+&{rM)W-(L$AHejJ$W2| zH+=pWIPNmQ5)6!wm=ASXQg6hIhMSic4x}Ro;fa;yQ;6v3yTSoR+Ory?d|^uv$*O;&Q)#r3IHpFOIUe#@Z!Rv!I*68wjL0@aSFRY%y6GhDl@K z9yP-xcr68UEiZ-{rf|n;XdDi`ym0#mdlAS>hQ{Ii&wd!hQ{H7q!$ClfFam_}2W|*R?Zw$kS zdw-ODx(Q)3Z905B1jb3J3;GX+kDJ2yDrP>sV>v`GoM7HjB@T(YF{q5de|=TK!Dz-@ z^tYSTqlZTE7?jSyCgfOQkJrZ5X!zL z9Q*cr&HEsq-*+DVdYgI8%xjz1yw1#X_Amdwj%B+a(*<$uUB+gB@W8LWfYCt^u*7{> zwLWw+o&G+!dA4XQUMIFt4qag?37|VJDT(Q;m1Jg020viT^eDiEM-WZnsTdG0pg8^} zuL|UuI<*EqgI(aJzE7F@A%^+c0p9!hU0sp-;UDJrjJ3jUMz{J1B z4q&*scr1!Vz+vtsw!!&(W&C^&{Kf+}t(VyFmO!ZlAT5{{=CqtW0I^kx&gG!*%Pids zAXF;Ri5&EOIh|whef`4srRC`68n5Opl+y?~8`#FOjBU^0)cjWFFewVlhTjb@55QYP zh&&fuAzKQ$jo~}z z!uRF$TUU}lFAN``mY1~T8N5^^wlMs^mJJ`E_&yQL|$Fl&iAz5y52Un79@RT=XY4*Ik>5Zpm zj@|z7d2KRthYH((<+FXfnUb;>pDp#=lwVYObk)v%|MPzWCFL@c8~?x^`Xyy~yor(` z$o&3wxd}@N(4XNMFzDwoS`APn3+q?tW=bVGVhBYFK!g^@r3}y69A@e+wQSk^D&Yv* zeJ1xPmzHt$>z^#!cj7@mWVn~rPuaUd*qrGnG3#aYKfG9*oB_aPsNc_!$yyo@fZVpe zK)V4s=0CRrUenT`uC5SnZbvbrx+9)4gmY5M?77kt^Qy}vm?#%mp;Q)lT7dIdT8Iws zqqm~#l2E#rFVt|1gs`Bt-4Jmt>BEsd^aXj%0!Yf@5I$UAn~Wb70W!Ci4ei4L_>O+2 zMBkUs6OOy=TZnycL3F-E=gFF6{E+}ue>wd=_>SjG;Aw#6^y5~Nw=kn2YUMJ$A`(}U z7uE@CB}8$BD3*k<=P#-_GiboLU^}@usrb8FDEFDR0!J5qYt7YnE6Jng zO#X(4C`_fST?yZru>^K)najA^zLLz!bhL1e{P$$J53$rznZu+8E*qwb8dV%W{s0LU zzvbUy_zKM7Q@oacSD}iFGQUTVmZ=Wp!nyHN4UpYjrXuman|&ru#61^_|6RR zut&@5|GR}U`mG_dWhBv`vy9o0%AVWSYYhjyoVsM|`mSoa{PbnZPh)K2@E&U8)6U#v}7{69Mw`roOqj9jq1(;G-ub$WF-)diGBF z5mF-Ymn$P4Y%L7*F+O_AX?5F(2fyoloqI=Fk~5rwaq1b5z1r6@KVP3czAL+Ys%)gC z%Rb9C0^7zES-!&IfrR%?6 zICA2m#LK2@SN7EfKlmj2c=HK`1I1iBU+!LQa6rO-@9x^D>jK}dv$Og84C?y-@^9WsS)anuDX#oPcljCt~ZxALaRQ)_H8ezpBhPg)|<> ze(vWCM+M(S+=!KKvurmyPyL|Gb?%tQXz`l9A=*(s!JnFv{7KffIkCN41`abg5-ddK zr+tTpqSe@pKc~n(2}*dBXLC~R&_gR@ebsw1vwh?sQl7libiO-AHRC!rx`Q>I?*dNV zB?!oyQa|wEA&aK!xmDfW;MZp%fBUZc0@S;-VZ}xPk zeovTRGHmSUbqU6#?BFkNUd5{iU9GIkF29Z)7MF~!q|MwSq~zG_#6*AHOP;#TqQ`Lv z-*<%-VqOOi(M|d8B}cr^l6qHiXq&E!Ox@)1xGTJpqhCGC^BrAW-n50M7BopnNzJtC z>m+#{mr(MSctPtUwN9(q!>xhhHE|qVl+iV9$n$;=*^u1*@Vv8~VV2cYaiN-hg#;ok zb@ZLnE}~qRmK;w)?L?8s&(O0jyj_3Veo9M<)t>&3#&|)?I7Boy&RUCcajB4H%dj{$ z=B&Fe;g$_?1|n%*o-zO7$0g zwNJFwxus0 zbbFAx2VKk3Wn8>Y-`3VyDd+p+!44jGUcs@>kdH@rj{bQ@)W@+TUD>v^`whRE;Gh~o zoP&N zHm2(9OVHs1yf<0&A~pKCjd*MN zpWYbQ1(U#%4_}M*FlgiWnK!pBN)ekn(U6@kYxS#Jwf6qW86_c+Y+?tanKohAa}bLd zGz_%P>qFjwEOnt`2SvP~7*A8tH+Sq2rYeKLf2yjo^GxR2P74_8>yK{qZS^6x+MuQu zN7sVJP{iqrExMou``6^bJk7+NPaHI}Wvz8f;5qG~Q$2twB?7fYS>q2%r(CtMElGI) zqaBYLD3=?L8kF-KdAEX`6K661Swe;V@0kXY$>k&;9(jWAPb4iyj_&EGTPoy>Toha1 zt8lCu#nf$5e^J@9E?HS!YWnwXZr>Qcqxv>WBc*%FN(Y#YJ{@d zzi$mo7G+@Wu5;}`_*bK@sWifn0O61UXn*&KM3OKai(4PUj5IbJ6*$LYQ~V$6xT|H; z++F*$#(_Z}e|Hh0Mv(am%&83V{!4;EdJy}Lt*gnroy>_)X&`R}eIwWD_Pe&{Ra*?w zhih7Pm`W1XV@De=+7^Uryu0!riyqseTHk=PwNMlass+yR!t}etHuB3&Rb-_^4xUu3 z5mSt}LtHb9_uS8W_+76YYdpIpQ@V7?Oz%w*EF}Ic`zuXfE5|#tMimK;COv#mJHtDf z1%~v!0VUxu>Ut~Q-3p4e{5f6gfkCsCI{I}g@XHq{Vc2)6cL&AjXZO^xqg)X7`7ZE> z`>@roW)f*yAQADNz~TRs1@pA#J;%9&a^NO2aHQvOontxthjP0u+rF{H;{*E9Jo20b zp8)d}K_|IiES?3xJpX*xyO}k9m6YR%?Nu%F`yLCeU9N>Bn6aN6;K_YuvxXkw@ZoE_ zABksX9oAqd{3j7T^9O)lJ z;VfM|&aZb#t;ZWbH%N9QZ4Rt(P;s5^_R1NlNVPd3m6lLr2b8; z@sd_dDJbY?fD|HpQ;PF>>*a@D_*XlVT8B`@Hbd2~AO!10AtWLp90Q;Mo}LLbMG#cT*qsF4Cr8ul<_qp?yk9~6_rmS8HLJ;-H-WrztAN?!>+@v@i+?g;e`9JVQXfX6~tfTfVs+ZXORYU~8NwKQNN~9NPpj`m zgEf*yoRTlp(qVj}?}Axb;}?8pw_w?N*DCZGm9GD`ogqfVuC_T)ted_3h1Q%5oDH!u0j?@PnsH~aV|`JtfG zQGLYLe?bBYbw+xs-+K1Mo9!%O30zRSsbDZar_Wigs&evv4RuNdCIP^=tTNl%<%e#t z3NLVX?_0Q)UU-fB$;_qf*&+jCtB*P`#K`QnZQ#G$l+c{XEb*7-t}^%VECLpI^M2~+ z=cg}2BlQE>S-xM^Z*iMp6wTcoe@<&ej9fkmwVjVxYVR6F#zh9pZWXKzgwB!GoIg_Y zKEV>aA;WvCuj-iQjH%jWz7MS)skuIyhGe(Exs3(br!+WJ07V_2Mnw^LCDnF-^z(}{ zfQz!+6MbufX0T68MW^fn55kDBo%Zoo{$k-xvp^b>btOWTtnNg$#Z^6Pba6@KTDjA# z@3Eq`v}%$t?+W^Oe4~4dQb3%9a=|T}^x18?+)uJ>`^KtvpEP*I8owo5MPF6i`46r5 z15LPJQ}{iFz%;g>vrj@AENHZ8oNu;gcrCjkLT{(-VIwanI@dpmq?O&r`U>~)|847b z9&j*_I_a|7^Zt0ald=Pk39(H`uS}|auPDz$2p59BY-$wlCkK96oFz3CpXEmP z$(Kp#!>=S%JxNSnJR;OS-0^>8H4*kdvU0BF$(XMEA~iySu9DjmJon!}*_37L-1ETv zEV#t~Gt1csTc>>i=G4{K(Ymhz+J1n# zF=sm%JfqhXHtQSGmV`4V?RgTZzi-ieun}a`w-WPa#ahULXD#m2w3)nrMT*bkU1SQJ ziwCZB$Igz=C~6Gw5{4)}+p&na!1gt9B5dT3`nY}w-vo#+j{ zm1}ccfKh|>P579MztR(G*+xJdN2S~ON$-!^bKpywU)i;|hQExPs--_I<5j}hT?5K`M- zSZd1L^1YKqR+CL!`>yIoZA+LHtm;E-gp%BjyXu{w@PVN4E~2ValU2On0zjg?{apmT za*kxahE&%MzfXaKKD3?4EK#!yJCKQtPW#MU@tz39Ta1pbiHl|<7mi&sw!4%yH$rkL6UJkAH zC(It{TGb0PU0PYC6Ca0!TuyHr@EzvFy+vT#9oxjg4EMUg(kSiDNHaFFfJM_(9?ik5 z2X1~qS?!Jcu$pxKNxLg)cB%z+c)Rf`Jq>>8%<15hQHq_h0?^F&vBf#c>VgFWIElm$;wIm1(F^#kE4+tql%7JE?xFpxjo%C#GcRTAeF} zABiE)_6P(s=jJ)%ff%J?7#hd$Wi!wG@gYj_;BzyOYJ>Pxm46&7!O{`b4V9yxUN~jg zeg#)-zafEVs)sgl4LA@%kpHR?J>U8@tn`zbM~J58hUDSvr#IHsuvvMJG8K`sDdXm* z&Qi3Lw#Vj<|E(&^I8PY5fwXw->kKF;JiPDz*_WnQ#VNK}0a> zDx^s4p!ohlutU}tOC9v2S)gTwJ4HrorsJ+bx{;Ao`wnPq78XB$UTKE%vK&p7daPDT zwoS*0oO5#Y#?^1YtB!=+^TR@dALeyX*Pqq3+EenITxZv-c_?j#MK9}OU$%D1px{tF z-mlP_r?()~t01X-+$XnHa4rV;Q1R&Gr{2dc2YCsnDOB6u!bGDd+B5Da-4CJ`zhpJ& zH@#uIr{MF**s?hP9<2>2!pE6(Q17woC=xd>rK9m#N$P<7J=&+>8AH?v>wbld4Y`z8 zM+SM_a}s;Um6WoPJRbPZhqq-XW#(P@E0Q(-Wu(FUb)|;Nb~EN`q<9a`#nbuZ^LvPa5<`xN3U;buQENj=oqa-! zZTmufO<$l9`@6Ii_prIYDG-qOlOB6EXkM$G5xh?h54ABTD(KI-K91&*JN_d{LC{yQ zAF<^~T3tIUX}~CNh^ImShzF$Y)GX>HD*@aOo%tdCa-0 zSw6$%anUw$p7B(+QUA!~QzM+eYP!?*q{15#@=Seq`m(6+JM;%~&7@SPULr3TX>5DR zX-xmg3_THIF5af8YC=lxlW@FaOtuV6G6J?0+>P419BQ+`?a*#-b-{IIE|W6JvlYCbm5> z*X3xCIhEzL<(n|c!)exxk}9~8eW@vrWa3pce-#PyM9(&{PrWVITK%#hD4trA#27P| z*@=21=hXH**2!X7{RPAz{u4IJo%j3Yr`QOV_Nd`8$$5JLdkbgvbom!;tnufakBEFa zJ*yWTj!VJDdrNY}AK;vdjeHT}!NGPhoadCaVsJ0v zD}=3ifkd}R#Kf4319o#wJe2`k-bx>#OXWFF|F^Zr{pXhvyo;ZgMfl62c2Wl$mIc_< zV=2R*we$IW^9_;IzHE%PyFSaGJ@nmsWAfR|xilKN_GK5|UlS}-)dB8pTgb_{dpJSH zN;6s`!`+Fhqa(;{|Ld3t*dpPbmt5^L0A?`p^J-$bWPZYya@_o~%GZ)B{6Zj_iLkBX znT$j!5Mci47X1XSsZ0&|*Cf_>J)>DIfiSoU2&cZ^L-kZt{eg|a7hR3{EHuG*o=JB} zw5^qz{H)9Y{xh$0if2eun((_#HQpwT&6~%Y=7Za38ZoxsQ4bVP>Dr0neJQ4z*YEy@M z5TXyVNA3VEjr_+XsbP_r16Qa4B!gS{KorK&{*(pI_r0_Ml%k9Qpf>Qc;MR5-x|G|e zHiUQ@Ti;#E$(QE(?_DY)bYiw#Z>d{ z*$OPKWFY)ZHz18bp{`oY|8#r%w*{$7U|6Y|ud(}Z?RAL*ojXSOPB*z%zxhNgblyJl zlsVp;XuRr>C;H|~a%alKe^^Agb9RJ}vQc+PUa4UHQr%~W3+h_WTZEfHpu&Z3w9~IO zWmcq@U!?|Ecxu-c;X4`=0@2ha$?n> zQb7-LVyRjh^H#eDpNt?k{U-NMqPby_2R;PM2<6<^&w{ha108{;BwA zCp%IZJ)bFud8MEz`0m#5KhU^^lxNy!C9ad@!pA>fhUKyI0Bn#pu8(C(oZHWuN0X3g z!$yDjpxPop1N3ct_-XI3{pYTY*4&h+{mrQnJa`Wgr!zg}|7d~$;_oCE7dQZn8?&B9 zPju(Vloxw)-c)T}Vu|lu{X0LrK2_!UM9D25qhVigGwL5Ya|_FqJR#)-W)YYkhE|o% zsa|LoX85KR;4g0~i{tu&HR%_+JB>_0(6xaY_1v>}7R|deDt5LkGtcgz{wAqe{FgG! z$;7;FKwg-aCHYG{Z}xaKVJH)EzpdHUq0swjX3nph$j{mtauY0ij&H_?RB_THG0$~a zsb>u}>W>b_T-8RXZ=5%^N^`Er(AeQEOYPoj&2O6tLQ)TzvbCw^4`Rp2u??Tj^3%48 z;c6bmGZ^-%@8D5-iDYhqm?TbEfm1dh{EB;q%}Tmf+7A)=(b14L1>|}xv-4kHWkhj0 zS30thqwV_11VQuOYg?G3xhxoUs}JqXdf2H^@oI^?SHj|REhcfyuwS`Lo~3V9wKS=9 zRj4piQc_9Y6AC@6sZr*3V?W@^b2@VOrD}q?v!+Rs^O#Vbd_yHSPB>y`UhXwz+hjBv zd!)hwb(>bucR5wJ%umz?8FsJgf+hL5MUM*}e*hSk;M_2ZSA)thu9da{b2+#}d0H)Y zdHjy?jWU+n+3YvhylMJ&dzre{{fKAiE%5G^X-!WLjKq)07k?3ljXxyW$cnZd3_SIV zb-ViL`xsg21HX@1eo&R4SMtul7m;KhiDqQ=W#etuCdVGV0<;WN7&$J5MH3U+Q9|%E zgx$v7;Db79PUUsD$h$OSeJJv_D%hFb$drw+UdiQn8&*2qF}9hXV5Vk)J?S=< z1A^2vdL>IdIB7p@z*}dhg*Q zrz5q3N-L@t2Rt_iWB2)!I|IXK?+=Dj#j{&&hjN70GM575ha@@UEEZ~XR0$et#jswV zvb@8XM4og;$?1885m_d$X4<+aw7PS0vA z?8u*Tb2>^ciD>ao4oMH4?XYJf3%*+mKj}lMXw1v9yVk1Hvj!`B2)Gk#!9iPjUM-)? zlIp8VGS9$cDeO_uOmWpJOva#W@;K0puq2^qZBooc2h!x|XBOBVrtHB9et)Kw_!Cru zo?0`|0G)_FGM@e{5=*1iKWZ{eTp;IHBCe0+cJ?+3Xet%d;g(t=IZqeMPb3nx5>0du zGQ;3Ux9Xp6tLaix#cpWe=I>{fGxgX+pFog|7Voe^{ZU_}UAm;*vzpR8H-;OjH};+9 z)s}TE6wGz}SES%n1v zxdXxs%yPwcMmYSYh&ky7w0R--`d^2`kD(`TX8qQ%!Z|}I-RpG|QH3u>ZzE0a!_E%5 zZE>BBQUaj{g`|M?FZ7KW5EX5^U14t(;320EIKcPD5)y|{cs za%)Ev0FMJBE&(G#JvnCgM2UdKeSf!KAH3Rk$Ig}U{?#1|sUYflAlz+fhNLfgLo42! z7NfOpaZcyzx53ujqWWvQ1gW(TIW3jk{!iH|A}@Q3L=GC^ZuW4Ttc*VdDI=$9-1Vhc zsFKIei2~4kr%gfc{yRdA!petIILvIQgCHb&wHk7zrf;%bYBj8Ok%S{n>ed-uh&NuGSe&mOQqHG)kNP$7@xJdjrjRNmy~1~*Hu4yAnt&okP1np+1;ww;TF0Xt}_v5V2XeD;9*3>nZ#YU=T1cd zW(UkqKtBLbiYduQ0R$1sYG2rw$+t_%p9ZHj`LZ!_7p%}?I?4r)tMK3UF#1S`KbXnX z=TiY2QM=DNlAyQHk{)3Rlk)JdY6J6n6#lKO8kyPZsG~-c@)n3RR`EouY;K2~Limm= z9FiC-paFV|>3Tb4fEPpMmkV^(E#H!NEfb`*;Q^233$-8Yrs!W>hX;N<1s-K&7}l*O zW3HE`+RsPharFs;S?uw1RNM!#zF?{#XV5co12p_h_$hTC@m>=Ph4Q>ww+vcB5&b8G zx@vZ}zO4~dS!Icq+tv z-~mOUoySKc83SE@73u$Disar)lF zqGtujUQjk{7N8uif8l z-*aor{zm3LMMk|uL^u?q&*&(c0T?t`N~bex{8nF5VT(UNC!!J-<;@BHlH%4dz<7uv zUd5_2tnq^rrcZGO!fK+0gygzU*~t>b9I@l2MmZm)W2?K-L8dA?VgzAx6`4sO(AW~oy4x> zc0=xEA{gqFnz2z9EOL2Sp80N_b>-X?*{P1HRKlSq2WC)pLqkwE3HCblZ#<2uj%Spz z@LjX*K(t=`Ouv|k%vGvwX?y$M?TntzCwRwH>z8r;AXd4Q8OFu9Hc9u@>oMUICSP;x zXNJu39OhbPwC8jp7a|u&U0Xw4us6w)>vbFum>+j+?H4IOL|3yH-_8`P;VEx86vINz zJYjnlj2A|_)v~B_ES5@nFs*uS`J5yF0Co?bi)FmO?^54_I}OUc$=q+aPA+2PZn*6hi( z_nN2cX%i}S&P*10sYxaY0Z;FQW>_-r5Qa+7dSf4zHJWoPq0Dtf?e){qJodKo%socN zqmb4b@R=FOwVt(cBqG`?XZ2R5#U*A9X12(5VM0Wr{-k2lf|7R>2fEzmb6Dehw#Bil6xis;Eezxn=zH!#)oUoQw>eW*p6w>ux`H*n)VYw~ zhlhW_n5hJ!s&Sg%j!wOUWj@5j6Gg0n8TEF~ZmjV%+VLSyqnAwk>LjJe>1GG} z&tO)2d2UH|dpRZ-9{Ggy)&-hl-@je@uR$Y!1$FO1-JTqYwZ;?c-qDUr&N`Y|Gp95e z_s0JqRI^%_ugXfV8Y?2ri%PrY@f+Jvb;HAElR&kLnZ`)T8}5VOT;31E5+-Bf`4t&a zcUVYu9&$rv<0G&muWb>ZOrX6^NJ;Veicy$B;uzNJk}-&x5NdFTW1I8I9D zH4-35EQ_SfV<2zG=r%N#PGYHjQdnq4Dzp$0X8NygYTeANkA>?A*sTzWg$5|JZ1UB1 znm06o+ImU_zpnM!6I+WX^O#%rZrYVgN19Gat)Nu6qTS&(LLELD(>GFL)8SoHt&SYY ziMYEhbbmZJ&7444k>uQENF*E^FL)JT;YsU23tnP|>j1Bx$>Tn+F4#BHVj}0055aIMXq%57LGJ|BpTTJqZL~^jjeBc+v2cG0m>&7ppju!`$qrqLg#_@j;Ux zY;`OQvcGSvmBmU?7}(DXwr=b>lbyu%#KkIa(BKPp6;k{5FKC*OhGb6jW_(DQqBJNzcGGa?Rw+98@kvOIdrzdim$usw;Ei$Zk*sP&p&M^d zB;QoPojk`O0Z=#3nL+6xd_NwsWAxW4a8ot~>iQ;A1y9h}JkhTQULh7JHnurC=QYYU zIQj0cmL@n@Q}pj$X<}<+r~_^?6|N8)MMbJh7vE979l!WH-Vv%T?$>NU@RIlTc zyy*9FJtB^-zaXs%&HeK~czHUSCP(OHUVW+o9U{&O|}gD6h3x z-5lbEWF6kd)V3TFL#inDyvT{c@6s%=fP^9$?t`Glq4SGL_wW;{PW2-~h? zodlQOVs}155Hc^ROIhX};e%h^OUZ$$kn`ue-MvEw`#+{4#h`w$Ua?*HnC`ckD5FS` z1EDO*dpaC6Q3U5#WpQodSEYB;uet!_w3@i5UeX@@tR2DiiJIEZ#aEVK?_Y+IuV{SB z8tA2EPvX9Ukk_W@ueB0*xnT@D-tXJ(8J}DSdv7+L#V3)n>?P^69 z%H89FZa;b(eO$8r%KIB&p){R(DBvcm%+uFthD!|7{6vUE$!ug9FN@NZw+S|*-+jC9 zZMD2M;3@82(bHvTOHFeeOcAqHlixv@yDo({{6`_6S`)k&dB4U<^K5vNbU%`rl7{4L z+-rM_>}rmmy{Nm{ufEx&j+Vi(E@pQG$yQ#DZ&vTUV8bZ9)^_eCO2T+NpJ+qBp#1z8 znT^<(0l}2}7Q(p15WecrKj@03!Y>;Y;z3^yjr;_UGHZUNuGaUsCHf(50uJ9#i^Adi zypfja5J{DXAN+QIT`he1g3#)}Hz)<~*m+!L^P9I-_pXuspYMz~sd(J4DtTkiL%S_E z?ESXB$rgMdbbWVejlwR?gDgIK{uWK))na+|Tw%?#Hy?w2Z|tXE{@d=n`kN^0pR?~D zrNu`(N_EZ6mO17oesZ4}a+&c-^zBR-EPd#Z?Akh!-(BmTBfwIt96sCoJ~U+hw36`T zS`mES-!DjZxCfJN2V!0oWs|&wN`wze&f)3dtZf?W$nU9j&lf;G{i5`^%WkclB>iwa z-VQkvE$$DnjBxhk@m=4O05bNahOzN{`Eg&jXAF3#>BLNZ18=r_^b`JyRN!{&ua+bS zO{M;x4(3nL(Ezc*$X9tD4p7w*iT`mA`H)(7M1iOD8Y8DZb~~bMGb-_H^f0}_q0UGk zxRe2heaRy7oM^;H0Z6}M-l||@wI4~}znSHf#AN3`?f&zZ0fUm>8bvcPaP9kEfeb2$0+ z_R!S`lPMn^(TQQfp-I#fE?ir^{xA5)jssLlsl$#n94~m<@Ok=K&)rGWb{-t4>Dsn7 znMgD~oYprONs#9zsH$H_4XMX!E^q9p+DUCL@^zmIOGt8Zf*IOY6o)<`y^A`9#ia1` zyh)QDpD8qUyOe@7df>~?q|UAKx>mR!-$2yd^iILiPDs9U-FCVpPeay^ZG=Oo(QN;i zk93?V(0oA)oBNph3`sYtad0j-q)ibG4d%NG-d9+yUeXgfoqj(F6e6OeA@pPR`%xh* zCM{${GilP#wWWWwYdZ%FJZ~gnOkSN}f?zVCtiH3JEP5j>yWiKN1rQJwbW8ufmnW?J z4S^6Q-;f+;JJ^)j<)iLmw|7PS#_2I$3yBdQ<#rMduLK>#dzPzxgvgkgpSz?XgpyLz zt@e5Klblgn={NsvhbdnEThrT+;A?DxdZKW=ZtPJ# zf&}x0TCx(n?$tN$Jt9O2HyL6Bvoi&Gc<*$zA9NOd#jYwl(zHcl71kLaN}4b4GjE)& z+pDVcbN$^k>HNb1#N1R+YE-%v%Z)7iV@z(bO(ZHBNaPT;a#E1K|7(>qUB&A>_nL99 zWEJ!VOQ-uTEjU~O3p!*Kl4Oppxh14J^X_R~VtxjLow~oaWQV*u{|Sgu|qMT#)QsnKmz>Z`X$o~e-cd$V1Abmh+huEx+OwuPaVu7s#;XM zv15NUsr3WWl@UAPD8^J;_}sf6Rf=KpRk$vNH;&JT{KKEWn>c5%AS4k0iqa}LDQ2MJ z9s{#Cegc-XgHW#>kDZbaRVnb{uxOc$0t&Iih(cCl-i(Ce{n|9bA#DV!1i!hkawY@L zbja}Z$eZh>Fm|Vxhy3Stm1L3-^TVv>OzQeGrv0MKLNpGnfbdOMJKOuPmLa@)iDQ^z z*q6}tfVZOL$+#t^%8{FZ#_+g)rldx&P#U-bIW^UpLS#%WQT8Dxt|JoSje}wLRk|8z zfWXa+?Yr3oqf9dGt!Ay&2eIxuU#`tNDG39N9OUKaU)fFerU&s^9!XmVOsv%y$d!m1 z6ZdU>vY=~5fL7%2aQ#`w?m9rj?S7-^x6`~xG9Td;Q~0d%a+}-7CLBTqC1ZNw;vRZTue z&L(Adr<%BCFdk;cjA}kV*qAwf6@j%v_md+lci-S9d5n3_rUGteV8iFy6d}?b{uX$| zMQbi@2H znpa?-i~s%N-DfgUoIU@B@nAB>mAVawd4ziaLF>u%9U(2=69YUy3fDx4eCCs#fy{>% zQhkBygn!Jr=NMrY0epX&xDqJJ=!p<0BY@C(W1nE*$HxcG1E?z--Ly&Ga&$fM1K?)^ zz_d6iix7lHmCsZ;}%mM~%qLaV-^k(TE& zdOL4@G7-UdLZK?FTeiJDaDG06v4J`%^|~XLQ`K`k00tJKJs@Ht`&0zB9fcz2qW-Z! za5Yfq@1Fb1JKPxQ9uI0}5!JW%_TjMA>LS5yF3`vC@h=Q2zmdm3>1%d3VnP7Aftp}m zHg0M|L%Dr*=>P!t$g4(EekzG%`W!_3J$`C`o@e*SvbqmV-&-FvpNp#!!^%4H4v>=W z@eJ+~=Ey;3$vz^zk%UL!LcG3X%jqX>fac|C#=Ae$&_#G$HpJiUI`I1PA^04`& z0N$3Vq`=}wkDC4*9)Vy)=A7L~(I@MIBw!sDa=JxMdg1~rCk4PL@NrSzYB>#l4y@$g zFU$JfsTD^5M1h^#LqaRM~jhC~Hc>=*8>FW`2@Y>WMjLHQ ziK*n~_lKr*wA=h-_jC5F+Q8LCU70MZE0Y_(KOSJrvLWo2fl6X20RRv|tXsLlW#!^Yl`u-%7sX&B{8+({>6Fur@|@1$H#&4TfzUIEik>LwS@s^2~Rx zJ8!4zK|n6;HgT>?vJl@HI=@+RRsp;`T@WecQCd(^*e<%$x&_{SZoG5fE_kYTR6oqb z2{Pzmu9hRWe5-76CU8wm?Ei~ud-i?fcvE$cO`;Et4Otr$YOup(O7wyGf12MUoPl;G z>>A!Prk)c5c)O#bU;eqz;pDPyH(e_7|7Trhv1I<}UhSRsb?Zb?G_JX)}%B6JWt! zb4q?(({T2tom#qT!3dh9Mr-|Bu}zdx-v#-Ja!8(){BXcWe)nooiE4?Q)@g6m=`kAF z0M@@7n}d?d;LgOX=CIFv^=_H!J25oX|*wML8YA1S}_ec~+7~ z4(GVG$O<+*LD$BihzgYVwwIZ)w;UaNSfxnqmHIQ&P5Er?w=hyILf{O!fSlYxlh9D? zD$8OMk(N61F6m2e%rkNrnEOE$<^@Z$)DjaK^UU0r8H;3Qzr$<$ru5O?PvG=Q z>hlLYNA!|prltj}e9$t3PwXVqdq3A$Nmi!=)-uizk+_|qW8p377vHM`gsRhEQTx=k zPyCYewKw1zW-MS-uHQpHOI(_q7x&Ad=+q~w#>SwM(kL``*&`86EbPMt3a7PJvea%~ zbly2KA`(@h3|>a)hh?=7CXr=! zsqgEZ0mfG&c*lI9wz>kfX4O*dkx0Mvat-fh@Q%q0c8x@nZJ{%hw2W8Cg7>t>?IqHC zAEFTAvTEKzA|FEEL*>f%%aVosW#&6(JpiXsz3Y2tocpehPWSt?K?GiZv>5qhLzlF} zE6GN$&8Nd=mpkP4oRC)gOZz^`J+K&)-4K)gIN^L<)TQZiQtLxp7ykb3mKp2i9ee&< zGz6E9@Fz{uQy$|M*-nlX)GVBbl-sS9e|H8H3MWwT_ka3H5Ep$zC z?-&7QbRJZFerrplgsOLoCr?6^Gp=@7O4J&-#*feHQF+~6)%E=o6R_v5Z1JSQsitAX4{Zm#WRI2PRS0(k3gwt_ZTIVO z-VmPYa5av9j~z~(42T;ki46Cl0rnagMBqeh;Y#wIrRrh6R(TgMnf9|HpB})+daLz& zd$-bI4HwCUsj0i@Qn9!d|D_LRNApf*{SJv^e7E|#|CHpEkhgB>Gnve(Iv)|s z3x^NDGOpPRN-ledVa84z*bSA|xOJN-x(Lk>mF*XgcDQuCEv_8@*<$y>5qfF*Y`(+w zda5KNV5_AzvePqnlVC~HJ-wirWPiAPX!OY^bl$`a_n}-dx2DsLa$OL!B|lsz^h`#L zW0=|Ayx2`JosAYP_L|bewuB+HqC#N=l_{1QI9VEY zGjyIIPsb4^yNJX9#O4|%n{|0%o(BKJX1dmu_-oT2_lq9aQ&O9+>kUvHFV*li(skOP zQ#_lLJ9YDMu`frIzuZnj5KgJuMkx4+-pK(eEvGf}@+^8A7dahR5FpuQB<4rrN6C;K zz=IQ#M6|{4aENoYXlJ~+F$(Wm(^GG4+e?oHd?+*vO!%$}{HOC&p4lZ+#sO%vmQCPe zEyQ%qd<6cxw5~uH{O7w9v4B(}PFx6=_daZErA-ulZtwO+ilFVp&UlA3A9;f4BKK{C zB*9!Z?2*`z?uWI>S1$ek#u||)#UXADdKK{CJg7mv`;AXU`E$%TgxyBb`*`XWl6j1-cUx9aKGv?XA}1$6rOIqz_F^^7L?^9TgwEHiE*Tg=pibG>hIzz%|C15%|s8 zx_!KyPkKh5O+ZyZ&F9|_8G|2v)i3Q+k>{?Q&{E3DLhYMnq{*Ze@d&OPHB->fIok16 zPVA7~G}?Np`}{lkD7UAhT9G1+PDD<<$@IU1044Y}TKBP+!`m@par%+b^dL>r038o;+wa|~?}-0e*J zd41YH+LR3S5r#slo^H_ciUxgnID?u2ZXtLgwi7!2zsi!epe*8bG@iz1)nDbs4o#(?^v*NJ zuBk>~_<9ad)|{EImG9vh6i+WTixpU4!Gg6}z>6DM=h5P0b$IYsHas7MMRaQQ8)nb` zyjvyKEuSipJ9B2Tz_CRT5^3SjX|9s3w>k!5(m-a@3jbmDPQPbu2n zf%H#gy3`05(((5N5Vxt#B?N%oAjRp+xlDX7=q?@4AM0JOX7Ma+xU>>n-Q$qQT-mY` zRVGRr7VF`@F$10v~w)Vyb|i7WQhD;g?MY69Er}2p$zL`>nsv6Odn6fh-$77&T9Xj)))RbP<%cSk|->` z)}Gl~-YsW_zLLT-nAw9}u_V>!ihd;d5YnttyTf^<5EG{@aDA2SKkkHuP4w+3AioI@ zXB7ZMse3bLGUh3{UC^#wWA0Z&sPo)m<@Tyuf1IECFNKp`eAq{o?VE{&xfFI z7j{DFm`-q%1Pdlh%IiH3blUI~Nz4vF34wPXsA@gWY1vYO?$0L4U4B>RF0@FfbC~vg z%OB|N7&t#rXRGC;*zR&(NhTK@2D}y^{k02Vi;8e35ko*UfXNqawF-iy3DU%>LXoBv z=PbsqPCT>(TewQBdPB<)RD##siwyI)F&F^6c>)spavR`SAnO{z2YEM*=bFz|rhV!l zio_ z`;QZp_F}@&X1Gf#bZ}-etMRAvYetNly~C%X293jsrT1N~D;Wat%oz~vsS~Yn zEF?P9mQP&-9Vysy8*}aYaeSyturP>N81!uP>(3vWt{;3xypru_r)pPmM(aQKPxK7= zXw^Q1EIS+C{2uB5j%^0KE~Z)l=r67otKa>t)UW0{W~^-o*0LT%npzY^=pK z*P0Pc8$N?@Qi7(h@it!*bl7ij1$N~_M;yyudaESZPnfo-xeVR*# z?@kXZ&wP!SBNCxw6}P&?Ti=rTIE<}6ar%s!ehzJGQw)-sPFWu;z?U1*blLC$ch5}~ zZ%&nVUCFB0qRS_r=SUF`debh6908ynO_w{ES2ezrC@8N1#=>bm^?tI9+ljunv>A%p zeKzZMJ0+*X&#VsLfw`8gmEQj0^(S5uB(>Bg&kzWLszTAP|Kytw3L{8{ zZ4rdOgEXFUVa7aUCg9l)BGEL4fyG`%3x%0LorzzhqiTBwS`DED>YcwR-LZxJ7ThZi z1Ymgnd6IJ3WH#inw~S*NS?eC~%}WymtH$Rl8M*GH;o|vgGNVcGu%SegXXgv`0(~W= zNT7Wct@B#1C6qlaP$bJNrwAx3l5?Su6Fr`wa|`oIT?qBz|1Lfgp4w}Yj|wcrBH&9W zJgWhGQeYuQgLoP6#g39#wp%0IJZ4$_V8SzXGv$!TvP!h1qXI13N0wCrN|FH8w`-|V zgwNe1^s46i-<76-k|R_CfYAlo5k9n}M-qS_w5$?PS_PH%ENp>by}y4qi7d*pT^+&s zGs_pCqzsjwFRMgLA_EYmx;bJC(e{WZa{~Z#gy+vw_JFc}Xn2`B{`<4%W|Nc)@EJYx z!7MSmhPJ7zQI+u*r0`GFbp(?XKx4B(k5DXB0w8ju-SlSyzqJvJv^uOtZyZmfu7c37W7sbJgV?)F}DUkjQ}n#zy~WI`puv91^Nts%pH=-H5oA7M;EBNi1QpCI zf4L~5&H#3C;lqZ*&}uLJ*^#AIq7R_6V9e|6!X^Z^AqoVO(~c{Iuc$7~gY}q;@_{wU zF@OxaK!^d@j%mQOH%o*nf(rD%03zbqC59-N03mn>^9nqkx6sTL5dtp?xXlY+Vh|x1 zk;RhGA^cR7 z^g-4*d_7)G$8*9nk3@eqxUkQJuxK+#7M>$y{Vg@+yGh*!0M+_iYVgu;C7_dT_$@Vt zKM)e2n|}X2Y=Hv(4J(1riKW>Z?aec#tV!k~FU_`l-Ox5xK(SR|GU-;VrOUDs7X= z+sgpM4ydyWy=^!;v@PUcY<(wSg)%?UshdsSo&f-NzTcI&pb|XL(YeGLIy@%-mIo>= zX7ylS381G4+w$ z3QJ-l-c5>tC0+->#TQ1sYO~3)V=IJXHZ65FvM28*Y=BSwc7&Y((YI~4}k33mVDFqY#0&hjb*VnI(>`DF>qHA`<9xq z0+Q=Cz!B$Oa!wm~hPFXKxcLFO~?o0wHlC5L)60 zgLi1#mwP}6flK41LIMaWt`P2KU1Tk_0TF@`X)a0a3L*p}l3Q|4F^CY1XzJeL{3DJO z=vT0d1JrNBlGqf=LA2#yru3y@I|0Nis{#;OGOh~SRw1rU@Or|j zrP(GDOx{A+{T5qdk}z1(1}>n@jKpD_^oOVtyd<*J>cbY3w^aB*fQQPN6CtmJRuCur z`hQ)0c|gut_xKfJgr*UaHcv)HDTMYOw2i2g6qTM4Q`UCv^%#ScO32psSSl(B*-G^w z%2to96fIg*wC{VrbMD7GzxVsjKQnW?&-t8t?%D3S=boec?<7B*1ifPw{@uve7X~1X zH6i6+K8ia%FfA1L$W8d)U#)-wztzx?viM)DArLy-4Ln7+E&onxhrW_20IBikwKO5n znkoev!(wX$2BGQDXTZ$}x-%93XG8b|Ks!S_t#5|^PJ)W7Ze}p4>i2kPL7%qHE>jjk>$; zLXuFlseVxZp?8NR?4!K%ywzEwe;RnvOS`7qG*;w1<<#sdHd z9apB=Ak4h};K-?_u+$3)QV%cBYu1gfi}+e5G65>Jt^hCJsB^YpWAK{EinSdPPO7`_ zcT0=8|4HMZ4j+z(Mm3n^do)K@zE3LTm%oPCWsK)o40D$P-XPu&-F1UTy&(%tiVCymiqxIQDw z(alAj`8O*4`c;yS@pru5aAJeeRZ#8gt*l)wDIPD!SLv9-dyLJ8U)iuXLH{}rO3I|92T3c`d-`7K4IY`Y-u%$1nYjl? zpT%$KhR$-|kRQ2+pujXZ))Qi=Vp#05%Dby%W{7`@Gu%Hc)_kzb%XEEbtk|t=#EVk{ zgkSG+Mg|UzdsF(VKJQxvAq`i&gCx@*!J{eHb4h)s&urXMO?|3zyFYc!R*f)$sy=4T zy0BU3p) z39at)gcM}XFL-x>9QqOZ+kSY0$Ffzi5m1fqGsQbdx$s77U+1~7o1D(0`nioO3auJ< zi4D$T{`i%-{uD|rg4SGHXj~&3nk@IImbH8ueJmag;o#sE5VJfRIv^@`>oQWAcNRJ( zErupFABz7+d2sVO&S}28XX?|E06kNO;HInzN+v^wx7ycEJ)g@JEqnvz-!xZcCA zltlT-6{UAMM}1nx*v$*nLi2_feuesd-Sl&dUja?_1AlL$?cXvrTH$I*$`-@?=BbYO8pu1S^56uJwFdrt`l-8eF1%972-5Gflw2-mCy^e&@rox+%$ zWp)NdXE~5zPs%2LNMgAWUlHJXr~JWER^UVcrExlrmFwd>_`M8#0j;GNDf1op+PykO z3PPK>lHZv7fF-;GkRLQe`ylh@=}2nA78mQvLL(@RJBLqS8JBAqXbrX9jv{IC56I1a zP(jRjDxvoAnXdV8Yc_ZXF5Eq}v%H@!(Tabb!rFnCx`b_h{3drBNKKIOKhMSst8(+3 zgQ|PuLqhWUPe3v1Y4<|+zd0fL%O4L<#VBk3aoG5_Y35E%g)i?W{%&fnd}OEREkWyK zaaHAj{Q&9nzh=HZ}_+{tHq}+An+xs=*GerB!bo?8esA55$B@(9b>Kz~?*xK~<^TpzhvH zDFO2Dj?%BKv@s3~(b3fI{{eU9KN^cNRPHB9`4|@bPGvIf8<>I9@H={#=AAyOR9Kz( zX+?h?>~ybBU}Nci@0TmYI!7p|+0a}l9vg~Mza_rQt9a0LW2+`4QLN*>)y(#M70Y_o z7V1l_9sf3Pg&A-~t~@w-Tr*#t2H)X=gogouy-|Bnq)M#S?0ji>iGak?Pz9suXWcx3 zTv?^*>9Qd8kuEFbI&v?^S|-h^1x^_u8(ZVG)i*%h=1v#7k(vO1J1Ebl8+F>Qf!6WZ zAM^%Y)2qIS#kD!B+7beIknQp4Y0d%PUb&QER&4|QbIMk!wCDF7R(j@NnaXZNzohiJ z?y&5M)Vvoci!Ko+LX341;Izl7Xi9W*LfO=q*7fJP7nA*w>(m|Zu+Dt@f$L(7*oAl6?M4+7c_Ne$i* z>)eTp5qQGxottD!&>`juzlyG%qR=Nba092tRs?nE8)uCDb=7t;(#jtW;yuu=tY#h> zZkGh9PW_F=#iNi_&DP$~R<3_qe)LAD1Pv>~<$#bs=*|vhIyEw`OFyuT>Ch5V zLmrPH;%9c06eQV<`!>&G=O7aH#hut^86F%Qzey5s9&K@ZVteGsi&qK$U9QPFZIXam zR&`>W#F&Y}kS!(_3m^!`bq2d0cNiJnNWnPpmdqB{ha*=K{lEp_&0kegqB`SPXJqKW zDDok19UxJH&_xl869r{fF$e7f`VXmsG4y(M*GG0>n`GKS!va}K1!?GqqXDfr`ODF5 z<~Ypo49nNm^sHF{@=&SX89iF)DSh9tpbnXX9S(>?lG5bN4M;LuS7h2)MX_@> zf7;YcvXqPav1Mt>$gIzS%?T@i>aEJXd*Gl!364Ui&i>cDQ zplSb#wbMkBRs%igB`Y2{k00Lj@jd;Z=hdFmAZ6Dxas$RpB752>JD+@7x9rnWScER{ z2eua{B<@@O278Z>&_{EE+fu6>(UC$EcN^S5wH+Ylwh%VpdSiHt>wI==h@R?hE>oJ9lGjiJ^gd_OZ1*nThcc*~?`(jKd^ zchBlNMNMxK+X&P59meuIFb$j7P6281hW4uxG)$s<+H>=G$86bz;q{Qans)2YgJYdq zDfzRM&Qji3i94tOYZ6051@kq>o_=VX7+_jL9{gI?qNygUIc7~iZUi6y0dWPjwI~?= zHLpxRc7#B0dyb0zsiW{D?=8}^MhL{G^a2s#6rjiLwXL}QVerARS4qw!{m6_v-BBr8 zI#B-N!a5N| z;n?xqDdzQOLhxx1v0VgQ9tw1)AuquMk*B8}M+YG*y!3s2^5OAShJkdNhG^$(_5>i1 z@cB5+EQ^N6Dq`+bN^CF1Sq)7os~YXF0&Y)F@pAs~aQ*l?gE(c>(#1R6(C1YBDA#-n}?&sxPfHmX1sCodaH^_#(cLiv%jd{n7GcAMg5<$Rg{U z$;chH3W@U^noA+C0HVwQrf`9NQiP~v>QI>i+=3 zmvH;k?Xo?;J9Q`22>I`>%^Oa59nDbAADYbx8~r@L;Na_!H-5^}AcIvUEk^si`a^3u0UMyr`5yxNxBDpc zwl06_~92aK4@YWcF$MJB@<&Mz_fzeclb_Yq&?jYstdU9M>|{eslw5 z-)vOB_C4`9FeE6lc#s$uxTR)`perbGSG@ChM8M1zctF8BzN%PiXtO~JSPQ}}1{IKn zv`j);p0JGXrnv32PHmfR1HZI|eren}VD+*vcFPqj*T36X16RVt1tA4j=LulU z;M|-AK}TK#f=R!Brmh&WUn)4~-z#kR691oE0DVye`2actapyo_&5K|E`qGibq6dzL z(xaDP^xpa&2=0$M6HL8OmujI$odDdmrYN}DB0(x1fm=yt$^7%D&lXvN2! z2{iShG_^L3X}m+0@@+TgODXBpO(XmZpmwy7Cu!7Ui*jT2g*Z)USiFK%w7jeo4P53i zWPxm>4!!tzhk?O#QPp#P_qgf^cP>1U)S|o;LUdx`uUGJ|=&x}uxrW05+(?KFAE%)6(a84qJoUV0tv@P z?@Tx25~zLP3Y_b3Ce;`JO-?`*m}iVQ<9%(-RvEk0=Xw^1vh?`St{nMV16=nBXpO~l z##tD3mt(OSy~>t2w~gbQJ%_B;ykWCssr;?DBl5U!3*Z7Cg`3qd1P%ca?0R|)Y8S!R z(zRh>=FmHyxJ3Ss9hbNyRjAPSdSfz((=_%u>D>LVQdqTjQA=emMRwe8^9Jg!f$6ABu8Uf~PFUf_2AXjFhL^ zHRXLgG`XJu2GRbp5NQ&I2xAEJT!+j^;J@sfW`9g2YHO_<=B?gz)A{+tVvHvQtjH12y4GYwTx!R*yZq2rXGpeqI1O7L6>g0Wjb z7xL!;KiHl{n`JEn^$``&PILBuP=dct{@~q;pX@_lC*_$9#5Ev`W7p^Z@^ieNSd|2P ze-Q-6qUY_0UGpK}XM-*Yr+j8qA!pcnMgMTnB<>1O5}7PYuoF>^V{c1zwg4;0CV_iy zv{Ou(u(g3~+-{t;12&l3XQ~;T(j&~(GgTU#IgzL*!diBLoMl2oP{KWEYTa-wgnLT( zqb_O+H#2BZb{5VZ{8XgYwjZx-Tr0+#!L$zTtCb&)GG?3w4S68y5{QA+{Ed!zg@W;z zZT5=qAUQ)z17<=U@8iJH>2N2-rFjT07g`3_aE-2=YF`Frra+EuX9Lam;#H@B_3=ei zOak~>D}BG~8y7$-Iq)QOZR1adD1YW(pp;ZL`?;AK#L@okceHd?LM1oAC-nS4QOdYF zOOLYjEsZS^=HUPsx<^8RwvfH$w7*V!7e)nkq-odDZG$hL=Kb7U-47c>@e#yBdl3+;8Ml zS;BZVSb&G>86bD!_{NX> z_9e)eV5jD=*+i1Q44fOar5ow1NrdT*Y7E-IzqgpQ$1FJy7T6 zfQ5D5dqVcY6&Sw=2&RY^b(v#JgZGR)#;@n-k3D(uRIJkr$*KY-g$E{uM4*bd)z_>I zx2fvpqp;Mp;E6MdSy$G1;C0BzAnJIz&k4F3S^}z$KiFWBuwW9gg{wRQH;}~T%>R|x zrm!=UZOM(3d#m>nZj9Yec|8MuDbM}Cy}`ZmDH_{=DHrfx(tiSJJm)cFkLpzg8-q(i3vjj*N?56hHDIt!&So8ctN|>BKoNfnO*e_#SIgcr z;fslin%|51x$@5}aqTm3?e4fH3@z3C9k{<%K5^_lNQ6edSDC}pqOa9?kk5^?qG47R zG(IGp7|Xu6+3eV>9hJgFV+AZb0<1?y$qA4yh_2stk01dd(1+sd` zjpcWJ4s61m5GofPBsVN`?59F&IM5N2(3G70V?%4aU3yo|*-(v55PW36Z%7>rgheVl zdO&5Wn)06>3fTyb1TTh?E~9P{y8p#0hC_9*ueNzw-&MiyBZ6Q5CErYlxZtj+;JGx; zF{UmpX*J0Vw3Zw=Fp;2cI}6%Nu!jW#<(c+lB!+^?Hp}}A;crA-8WBeusF9)d9t zt^V@MhP4p+198fN902gkV8Lkfy5;h6q>sxZ0Qz#c4x#z{=Vl5f9l03W`5f`Gj>HkQU>HZ0C)yi}la^ zcz|&&-c8E_E2P0R?>+#SeE`lU)xjTMkB$Y4vK0`pI+7~rtb78zwdPubo?Q(F9i8n} zu-BN@$LltL6-EtCkmVimKp|6~a_1H=oO9CM4oehB8nN_ajx ze@+%y3T-1iPavQdq@QrN$DVwPpzgC2-RbOV+6cVHiDq!5Ewxx5|>-54TmFJjkM z44A~RC3m}x~Ips9)i7~PfEZUj8@eMp(fdIJx`NmhPPz!hI)8`EYIPc>3UT# zS+3ZQcL}5ha7EPdc7RbL+(j>yTor)>W*2pa0mE>&qpC&*;Ov48$P`AquD&HQ4UR&b zL5~7!SQg2JQzEg23^0-oJynUoBnJHRji=gI5sRZh&ZXe4lTv(c<01#DqoM#52d4*D ze+WT7$Njld|6t@(PtWfVmdM=qWGmsEfxl-8_!z}KTa#i9%s^`zZzvjH0;%Zxx@;w}I;gw(Q?&m>C5j=JaG(o9Jz_FW% zBcB@GSbx{~29eyC-ZdgeGQYvP)mXq+c!Z{#TaVF0TC2{20T1CsPjKmJ$!cNd#wDk zD;Oe0D}J5w_FiyGMTXq`AgnIfsFInMihR%yRa+4&IKK<@ym4~;51PjfhswKwEL`XU|N|t=C z-!g&s6?P9o0=xG%|3U(-9De^(nPft;A#ga5DC>Vn)Oyxx;F2tFjpa0)W{-q%S%mWn zQ1$vr(17e*m-o)?=YxY`rwv+S6J)}rKn?+?BmbeyMeqf|(*X_4nPKnsVwQQJGtRZ| z{afJxG{?ahlX?QM7w;=DykI$OVa?x3LpRUiIp9NHA>sRhE#^(eKVr;q1P zw|GDcJT`k_Y~A)qeuBIutSUF=Htd4$QrM3yNY#Q+%%1iyJJ$EUiLQMM4mWqpz**x1 z)gu*nhHCm`=lVqgiq9bdUj7Xqt1yL+NiY8|uJf3Ftoa70s-8_jw}S(apRXuKTGzql z6%lL~QYK9jXzX8EC-p>v=QE_(fFv3F8>u`McMqf< zFCRR%9%_b!J82(ypkvb<{#CzFh`@@PrjHj*;YQ+JhHa!)6uc{iqvG``oqZiXTM2f_ zj<1y+A_5e%nn26qgvUY>3ra+V2%3#z$g?3mTzHxebv-RN9Egk8hFV7KvY@Z~?Y8&z zSjL5h-a-=W02vpoftvxgD89Ljd!<%OSNPbUV#PF2^lO8rRD?Gb8hWhgrLF?gSzM*>9u=CC?uv zPp7b;(_uB`TZf*G;x{*shnArlKXC@|^*6u|VKgS;Mn;+s#!n0nUkm1eD&}0p#jZ$z zP;Kr1<;^hvmgYSpVK&8I#(UqbBiTE^3V-@o5;D?_J+2IBD!H^J2;_pM;9$ImMBsTruB^tGLb|yWJVGd)W6I{}s-rw%o z$?14!%&N7+WQ)=W;8W-j3z|+N9KGR(W}jiP-0j&d&7EJhLDjn4+0$`5Um7=TIc!J= zUaiv54KLraAg4>(XF9O4OPctg1Df+6*vvi-F8xT{X%I^PAK&ZD^=_v@ajjKad7eM+ zh5GIXCx@R629%`0v4J$gv6CD8QZqjX_Q>5tk@=?R)m;QlZ1w zevCIrL~L#>+t{Kz&; zjy?4`2D_I17dkL;m>|aw!}oByr*>Qqdk|dL^5xb$D{}F`pJmDCq8cCH3iZV_9{xpl zc>S-TIu}gGY-;d-WT~)*uS_If4w0RIN{?qjAbyp^tHZMR(9R1E9>jJIPPX<0DfVYQ zvy|LiwlQ$$cqan?F5>#R>vqbyT3drhSVxGn5!j5o3o1_$+m*P#3LYmKlSZ7tol!4; zXF2v3XvMa{IkVxmhCJYarev$?tdvUL3-=QIxsU|laRZ{ z@(qNq=gG6fw?^t9jHUkeo$qJ@0-TEgtr4K@3Iy1wt0{AMZ^oBV{#AXjfhff3t(N5K@#nVf= zCa&pyLPpx-w3`?FYM?3Zp62?mOo{_Qh7GY-LzGvphBNN6vfXwDea0eC z;x#<=YeyrnyUX8ub`RvE(^i4nDg76m?2XFB%f_sE5b#qOz-uVT}j&$>wln($a?JqWJCyw}zCWsi0AzrfX7mQLSIPbYTO|baZ5> ze3mct!J;wgVMtaC4sj}v!;Pkg(!FoYU>NX-5+5aJc4(Ug!2q3n*B!-1b|09_LU{ue3SSxUo!*Q+;&#T?K4Nq z9Q3uv8-QG;pV7LHC7J8o`!#wM`s3+EPav-aEoAy!Bt!JY^YI~yqD~cXI&C^}&i+hV z$X5SJd`0`NdMEuQU>QociUS#bya6)sLVwCsNz_~-_~oIQ`>U0AJTW&eb30sz_iA4* z?iO2ybq_N4!4ZuZJ)uAPFXdonVjbzIxk?wxy)Ga>7F5r({xE2R=ZgKfaw9a?;*hDr zHG8-;VSGRzv_3~yNTm(NG3v;?$#l3qyg@s;kxdn15>Ym@04G(YnJS5Yyw9qC$b3NN9}! z28-?d#VfG!Y`zW9V4H@==Td2<+WojSuMokoPJPP>TqDhUd*3hdoZc281vLYKq!s6` ztiOp@7+44+y)@cxRj#7L@&Q*d_g$z1{8S(sfJUFK1csAD{FjR$*rOVym0x1@4?8x= zv@lo`B|tbFkmg~`MxX()VMyBP?u0a>P2ixUxsTjaaSe|fKY*&x&ktNvmr3KZW)qk6 z|Euk6V+uW_$172n0T-P8;dwvb{pkz;W=JBsjYh%~(hf-kob8Cf7G?N{?#Tf=~? z!>yT(#{I^@`D1l=X_M?EA;O0Aq!DIg~6I7|2Z&P>OiRmh`u>J zOs(!ua)>pU!Iqb<$l9$_cDNsP@5Oznd)48X2kAlR1$C(<>*ANZMo;^7w1c2)oIbbj z+SsnEpJ;ufEf_XA2zphpIYDj`*;WWaJi&IQXQF1Wi)j^~kguOIR9xR^>WPnSnMO9^ zd6L&TvI$D8<9n&BQY+1d)f?Z)=-2{H6325`P*Gb1^;R*O&aA(|kKt~)h^M$8S#J=w z*4&ghz0AzL?_Yr;9BM7_2`cPPU92Y#`{}Y6@sI=!z`F}hykMJ6MB}aM*Kl%Cg!)G} z3stl0Z9EFnOyQ1zfgXmd#P?5G)_DyBv!X_JHqU13OMmu$nghv|U^suyGecv?QIRUY z)sVfpA&ALF;otsfo$C5oBcKWMoW?Zn)jhxQFcsRpFU8~~jR+v73m%*W^Zv)P*fk8T z^A0@v>)WAYu!QV($~Ts|>QEQ%1{jy&)Cftc<@D3JKv_(CwD07x{Gfr-ve6j$ z>Ve^R85_^Vr<(`c0<|Kt(9x)Xyb0p<64}x|Wk2|#E>Uq#d(VUwq(nJV)G@W(QzCU&)bR+}$^gWud;*R|F6S!vD|JS|V^&q$+h{^J8r>;Mec^E4Q>Y}z5EzUBdGWlsmjiyX;-ucJ41cxpOxl3Pwi|) z4X`&A;zPvfPlm+Jp)FC`L@-lze)5oyOu66Fo$%`%osoO115Gz8v_s+;QGat8HnwRo zZtQ%kfW|qV@%PZ$NLv=%pJ7$u<5f661Cm`_jybsowT7o9o$fa%=*7b{9F63NU^nil zf8+mk1J5?NrFQ$6wdg`p(yzRSGpnTE0Zxq@k6bai{><|`0m5?{efd| zZiegz^i~9oMV2{gNz`AUngj{I9S+(g7f#FE(!t22@S_2;*`pDvAOkLEOR74*hnwjw z12gvpl{W)?K2rQXQhd4Qz3uj@LG?6XlS1B{Y=7Y7)?8N-5EA(bW7f?4CGduVaNp7F ztfG&3KZy?a1U`;lyL%&-wENe<uDw0z?Jje@@ztKiuC(Hj`NDPngfMjhj=TbXRE3ZWWZ=PS z&%SVPx*T4cbO6FXZ^d5%1;sqZ)& z(f?W>^kU{%y3Xa z%lF#-C{O#RDB+=_2{No8!3822Ja3unX^&OPUh8zYL5gmL_Px5Jue#;*BsE7rQgXm< z5!PkYF1+Iy)isK_Z#=DJ-UPO`ef;;YK~ax({eT*kLg_b*4_2vNNb|}E@RH7`p*tGE z(I?K!Fo#ssNsBcs{~O6-hYj5OsunUbP<-Pv7=Y5}x1?7ekWTJ_&JLKWqwx&WZP6`Z ze%+|XxN@;@6xdexyZ1|3-Ftgq=|hhB12y=+pCUl z`N@;?6PoymElo|Wu{WdaTf-TzLHYAnsojl`=7pNpj0$Ju_j*X&r4_w)|3?jQ?_ioV zaf!u?EeP6(mCMExo^Hm*Xi@3%yS>ujainM+{2cLqQ@qZvXlO1Q;;IJG-_Bf*{==4+ zV$F{FU65ep#oSm54=Ed8t<%0g;%nCFDYi^8cM6yU(6c}V_>tQLYM=6BzmMcXnqdOS z=1^0|4Le8M8C?NZ1-N;P>B$rV(d3GtEFXL+=J;B3JYsL3)QCZ|ia?>zwR$8wJ45eR zvD2tvoZ+gF*j`HQp=GS^*ya@9iG12#A)|HvkEL^ekzW2_H}8<#wL0}l|IAu{>GgX z@Q1GO`h&F{Un_0e1HMlg+B)LZb4#HY>bjWXM^@rTj364ztsQkTc+^l4U^eCe-?&`Z z{;0Vk;{2$Y*XRvI>@&K2(>Z5BL$M=fKKfB_JnZLVXV6|Zo1AGDk*}TT+@{lWZ|r=# zLgqES%i5leZ>n#-^$t-57r6y|Kq3sUR0u!ROjg%7sOQeCw}mkXb;sN;#yb62Y-l9r+dSl}UC;38b$o{{|pBic7}8xJd3i5`-Q z)AR3+Sk@k*!aDE=Xb{^_{KO>u#BtPblHE;1)mmk(qmN6*-}jIEd|!6*Nnu-dgJEMr zm9O30PN;pl8mYJdsThqCx(HeMV$b+*%Z97=w)@qHTB#mV()F+Zrk$M^65!?Tjmvq0 z8bBT**yrd-fpWv8$~(Gv zuR)%}9SAYu!>Q|9@x#!zvLSQ*{#jG1g1+ZlMjcuZG}61eEx^A-BtNIUwvbi3!m1s_ zv$hK)dlD*Fy2AB|O_zt83-x+0->*J6K3b9_Gx0}L)U%e?Q$%xrX9cffWtf0y+d{?* z;b2&vi@|@38^#S}o%TtQ5lZvzDURJ<=3S|3P!K`)6VJRGAj6cL#N@5-9}OR+ z#J&mX_^v-%Q+>5cDBQQDxGebbqu6nK11U;&NSq~{9SD9p>`2E@le5C*s3lgQC4^VE z4-FhHZ)YpSBO&fKG-dGgdji>s30^AARh2&7vbt^~kEd9vUYZeA z<^F1}_nipYFerOfpo~0$ij-SG!D|Ke)bzeBF*A_0NroLf0fj~L&wF<}=6xTSGM+wM zUHzw8kU{?^>D56S^?&54vbM|S{UXHP_%GATsmMaA#&Rsoquv~y5mg+~ist-TRcFyneZA%{I7W+XQYNqXWqaPro~6HQfbTib%0;b(lO z>xC9)6(XyK{7Q-wMMdZwRcv9P0jHi*Th>Raq55-15i%RMHJ?Z{u zUs6<)jCNPW%@(J+9Qo{K@h6895s3crTzdU-Pfd)*#s_mcWfhjlhj;yyhZDFw#4o60R{jsDHkB?to!_$kWRH zkj1?+$==^OzRv9%PVjf~>QoWyJnGg8QF(M+iZE)zlf&evrQOvI1(iXv?GL^spKfoD ze5TVY_x!DFc=?4XqLq?j)sha6lvsKzdZDVCC59D>ARCGB)PPrr-9Ufn1J%p5 z8c*>5?VNv8#LdAkxuY#%?(ZWfsVFw?EypKIT;~!%C#o4oxh7MGtCttMPcAYlF7KI;>DmUI5W%* z3mgrr#|^zIb8c$-cFATtEi>0mT{U{^yzarSlLyOYfHw*UVOOX(b-v6{hI?)TWN z`C{&ivV9f5Rn|H5m>YOSxfYBZ&&}!6>+4bt8ZXR2DtRmcDh0KyyT9H2K;4&*IXn8o zLdR0|vTX{|^A`_2&|_sB2Z`_zBGw)te>^voziA+U-0AT@vIjot)E+O_(W~+qEpPhE zIma)qHD_#Jb)mvRZ})?Gv5A$w2kTm@%JUkxySERI-3f0xH@Xh=LP5Oam}cWQ^R}wH z&Shief%ihLM2$MkRc#(R5TYMG`nIIsC+L2NUigx~#BMeX`}!HQNPis{CZ8Z(f$*q* zwLTt|>Up1bO!Kuk6cIX5KbTlzSn$kTx-EQMG(~TT{dFPo5=H77Wwafj&zh_&)Aixl z0WXY;UK;y=j)f<+2)5Ix5A*XoOto`x0PQRC?1;IwU)rq>pW%eaF`v zJf#nyzF-JFxN9Gjd*Q#6-D?~apuAvZsqu&>*hKgz0?o$e*AVXGKGy+@`GYltx*Yzp z0Z+mfnsDr3A2t96BIGm%+|*H~1d8D85W>HPnkxcNhU$0&3XeSSu+3hF3>SeZP4Jc% z<3$3fXaI*2ivOR8za(Cm$*~x?dr?-^k-zv%XB0j^M>1{~a?Tk0UK;fcfj0kp>)5#%n76OJ*dAj$kZ> zzl|BeBo?ATN2$e(nC!l_|K7SIt2N0Ax9 zYko4FuGEDYNv0#HWBAvYk-z8&U3(KVvWSkD;hcrc$PVB)VuWWY&T>k6IVhR{36ZGn z)RZV^sNsbnxq_x!O_Ld6=3qeRBvX<>0v!0ISIIDA+uk?$o?El z+`&@}KTX7KS3|ZWTbW&^>~j)Dh`SH`M-Y+O$O$I6EcO zVIn$Ajitt}E zKO$#}D2Gu==Kh7~6rrEQy-X40VKxT2jr`5ipy;^Z9S64sWmxeP1(S+kcvC4DN(=5D z1fzJAf&uMD2oI{Q!ABsqjPRHuM%O5qTEylWgH0F(V}f8(8Eke?Fch0q1{)0uhGL^d zu~B5eAU4++Y;IF9(W)pvn{_rk-i4HFX37@iHr`g8@_?yibe4|nrXx(X znK^XC4@W*Re0&f!EElp?C9UXz^nV=ykVD>~hf~hwooq_X= zj$oz-r`vJgk6GjJx;5g|H4tFf>j(-9UOVIUu(Bf@lq8UXeh zI)d3MWMp3@PigamUKI7jIS#qb0J$B2$VNgFUk3>;xPLh;$az=79n z@PY_Z_?Z(RA#zYx4q<}elUY<^$J-boSUPeYVX!mBAb zN8mGVsQ-W{n^1J-(Kq`}9$eK4Toq4^1$c9lDaM|-21Q!lnn&?d z!~_j8jmr5o3T7Hg7WZ!|YpE2>-zZr;`ZSH3iePwZ2<94PW!^NzMv*RjF~vra0Yk9~ zqx%rXfT7q>D+0O^!Jzj>t})n5MKISWHj61XMHI|picJ{B<~9WrMzQgri=zG!j|vv! zAW{DaK;oh#DK;kP7mygVPV9A*2mYYn#=|gip>oc#q~C@rQ|PSV-knF+fk;xuF{0l# z!b@bX5&bsi<`C{C3T6QXL(3g9&^e1KoH=M{NGUUi!Z}OllrnQDoU?R}Fx{+a6wVepN0_dC z8iliknM3(v8iiBJ%)zWN5CX)ol+H1taF$az!gQrZ6wY!AM;KjcVnpFAr*MSnx{N5C zT5oQh@p>7nv zi0;Kg+zU1p0M0_(FAn8gIqF8KK@}~~ol2+$Pf~u8z*reMPua4F+Ej*pOsKlpiHXpl z^^p@6(q-MIWIl^R0!L!xmU4=+25e3F`Yi|ObhsZ++>iLNpcrpbJN~Qf_{R=&Dq+6|EZNH=C9ew$xUfAo?5$P<60MqN$|y#9fgxwwQA zX1KrV7rPl_o)_fd{4 zp93Tny+=z9@2>h17_5DuDL@`)-+&KjH|iH;WegkB!lO*%r^_!Ih^P#c|& zU~UKb1l2HMgq|HGDI8mBGdPAgXEB9iOVvMT1|6YrY#GS3vC(1*$CmC4hn`axGjJHl za`>xh3>>JJ3EyJV5e5z(&IyM@M;JIzE)zy3(Gdzqg287Yjx48eBp6~C&=Cp;dS~IU zcG3|FM*_oTgd;>p7&r_*EF6JqxWGFns8^tdPXfTfLBbnR9ekd?;QfVeg%Q<)Cg?`- zCm~~yS(H^4qH^FEARlm#(+#A3Yt)2rNBRFuf?XlUQOqTvRtF$L%_Da@a*qV{qU124 zoUkb$q~ir5IZ2l#Cyxkjp(vYBZ|o$#kt3$)Gm(W9ogy^x+{qN>bV{MuSrH2!b)BU^Y|N&;soNyOe^7q1bFj zY)&%R7&2fGo1F|8Dp>4^2xcn-hGHY2w4tsIcl|FYvXaOHCK&1=7Vv%%DCC4cI!&2t zGoJd10Baub7t(Lfpx;)<6;qE^Ui(N`>dChM^z?|eD>Z;JGxCRnSSCxt7JOvtRroj?~%+ACf0nA@1 zZkc$&CxFr}FyD?D!S`nZs#oET4y{n8I*u?fwV9FMV8jBmnh6o1wjpyljwmrBu}L!U z2lm66U%L5E#VYrUb(-T{&UESk@+~Q8(;N7@qB=T>t#~?ENjEc79cspaX$Uortm=AM z9$05!@JJc%Be}DwVA#?l5%)0&Dt9f_0Jiu(1bWE=6}V5BIpK8VF^;TdMq=s6Cj8ZF z`YQ?QOmg4i$OdMF>SyjI{MBpvD+#;}z!N#nVMeHP!uVOUp7V1K^||Cwe$=RCg7_m6`6T-15}0rczSUIZVH0G>>6jo& z_*W^-7NYMaOqD3dgKqb2xQ8UARME=elVXhP06mvbCOOG0D;-h(oi5Y_BVgdz0LuKo z=^_>~=$ImcP$C8Z+@@Mf&JIT~1PdcnYsu|}ks2DWhH?g^RG51j|x4 zN0ixTDazt#Dc>;Y-~&jIe^3i-Px|ql7{()PcR)ulow80jHLn)v5Nu|^h%sQ$A^1qa zSl~-H00W}Q_NHLOF+NDxoyCEpdvCTS#wUg@%`n3o*lK2%k$)i+6$~74 zY1oJ;V%!MAGe9XG4I7a#s?B*AIHF-A!ma%UH-!d{XxNDGXxxaTf{V?iVIwAP1Ym$` zn6MEOH-ab+fT3X{!liK|CU8WjMoi#{ zhK&FsCEo*NSQ<7WJQ_D*0!K7##Keu5z!4KRV&X6=`WZK30!MUb znYa-R95G=dl1aT)q6`5aCTv79Y21h?L%@d#8<9*JHzFhE0sV8F%Dl_mNAmjyPH9~F zYCQ~>6x|nr&p-B)=?jI9BmuMn3 zP3Yn7g`evGp^W zZuD->Dcg=^wz0w(FqI}1Z@v&Pg$oTI6D&>+tTYGLAVTGm1Dyk5B+~@=WE<6zq?`IX zTs;tHfe;l#TN-SF*T7RnpvDe*27DpPle{PpAa&}@08o?#5(KAC9t~OnP`X_bh|&xO zB|QcuF0eaR4~F?YRJRggh+DB|P?UI46eTru0QWE`1yPycE&!A)CQ_6n7?h?XN{l{H zlViTdg0C@N5QobELJ#mLJ;RZS3?Lyudpaig6LOTg1LO!`Bmq4eU}QRj5tav6qdq;6 zpdmUafDTKGqU@ozlYWd={tjZ6CPY7GF$+F6hq`X$2xWSn5qwOUx_1PcrU3ESZ{TC+ zr_hgyGYCoI#~3Y$9cKWG58%9U=Tqy%-pBxY4uI@2{THf$i)b-BCJj5*w1iUHiyBFcV)ZbaszqH&2sup^;Y3q56KtY{ zu2~6RpUkY{82vhTHT>)~wK7DDI+X;PPAhXY=_JDZY6vh~O)d0KKaP9>pRp#Jg68j~ z3**l?o=K|c;gLL|t{w3OlZB7(l>@8%5WxeVca(?OAdeFY%;KA)6fXv zLXQ{31Dm>RquwxiP2DQe1eF{GZWK0$VLoC; z0lXJ5cwc5vIs~L#$)Geu9V;>&49qnKCBbS2CAbv?vBh%}H;-BFMA*qa3`#xmRAwZg zJ+B2+=YUBP^wyN9si(+1aP_`=;VDa*L*r9WX_>MiFw>tC*3pwI5vINonGV%bBz~i; zp+lz*ex8 z`Tjj-u~$MfX?+Ix{tafYo{Rmt#+lg$eB=#)A{IXRyOi1_62V|32^ig=kw{vS1m>t; zoGP--m~y5%z9xWZk&f7$EWAyF|D+)tBACWfc3}__Fm{W#5)iUw5W2-6lm-a7GX%N9 zAXEwnIWY)5XArsp2tm^Y#O(%y&^AB_pMAr~HX7g}S%A>uh*#KDk)uE7Kn)9=6W6GhwY##YsOUZ|hb%bIJpA$Q zh5iVci#m?}zrYMWZ!(4PhNK0@^-Q;t00M6eOuV^q}35ETkrN4#lVX`_~$6YE5C}Vo^ajf zzA{P&x>!O&^hKr7r#*ugqAFKt`rYXH4JLB`?3%U~{~h|kbG+X4&Ykx;p7r^VcYaYp z_x87MIU!r=R(nOyN57eDS1`V6m9t9!3`+*yd`NOuC5^=H?UN0;+Vd*{VGf0)%-uh* zWtL{jO@jh>7sN|mYMc?gyS2b-7@h{gG({Q;Asvg7pRdlp`LYwz{-HGWhxK9Ix!WZj z_1(R0_lP63ca%}cYPGw=RlU}(eH?>*@EC2+f`;~QO|9GRhjiIDE5SVCZ4rYfRbt`% zqhI>McNK@*Dl9C9zTQ+RXf!5kUmE4j8sjh2sZyKbSCSBIWm6oiXBeob^TDY9^;M~S zZ7uf}Q7eO`y21d62Q8QpV7J?zvQNIybc}TXC~~xZZRAL__ms#GXqFCtelQs^Rb}#}<`9COb^Du*rCZTyj38cQ|rGlIfCr29f!&65)l$ zSB;ZPO7a{jjoq9M@Nv5BKkw_D5{ooPcN;u{=P^yE=Xyq(--y*%waFg}l@sl>Mro&Rv#Vr+GKQz1M%J1-N)>Shf zkM|h5v2vF2IP}YgiQHtyEI>uE;(#iLr0;2Bo$z#l6PfTbS}(7S|F)6YHJ8hfXpQq% zZPjRFZeorNz2rKGKeY{X-rx#-dFKT@4nsvRZLJSHTOJy|rT;QD- z{Ij32o)Ukr(9da>&P|eseBP*-svb`#6Y*lYpW2uzR*iVEVzOoSy-lF7#)pzcGkI<2d z_Bm6v_DT=ynbV!&zwCs=88>8OYIN1 zGHj;f;6EKEvTYdB?)ly`(MdnX_}$^?x~E^Ij>$F~h83o6?-eu^SV74%cnd@X-ZR_a zUt~|)VCSt{Ma_@JZ)vkq-vuasYY-o7_s{K_@?)mV@EV4;BdQDn>*6Xk?;T8DpJ=A3 zCoKlpJ{62On|0c}>MA<7MOvfl={qNc=_}7ne;OFlUn*;-r`;VL*X1l<8=us#re>ZJ zm-lF=Vejg+KADG>6m3$*@U6?W5x31L<|kTDnB+@}$xgkgu)U1ECtePbLv z!E!6@`}Z~nitDeSQj69RSC26GLZIA*q9Y8g}J;F#v)(4Tg*e&+QqZ3Uv z$JZJRSs0`%<{m#EDL(93P&W4CNcp<{4QAVy=%RFTpE1Aj;y1T`c71t&`xx7xVwTcD z<4Abo@cm@Cn7bOQJ=de#^w_F4-NE(EYj7DoQPke>oXpzFAG9Pdx!-0YrY{?bfU3uI|F(T8l{Ez&D?6xuzVuVgn5=;h)2dL^M6Pqg`0qcex@u?UB4kOK7O}de=QX zk?2~t?@6vbsTV@*siveKntqIah+7u8cewBOv;z+x`CUytSRdCO9tx#z1DYLH_Ux$F zkc>_|aVGE9H~y{mt5C=hbuoF$Y)j42;x;Ke?O13Lnx*8iFYHVqYsc1Rhjr?wJxAoM z2OU`{t|iGj4}-@$ohMN>WWXq^^C_nT?p6E0iaA&HK76DtuGZoD-1+j)o`-rlH}4NW zBVW70Anvsi6re2W@zA;uFgO4H*W=gEiMS$r@{$=j>UoB8_h6MruY+|)Fsr|-QYqwuOzoDPySsn#pp|)e+%Ur`l zzkBQZsIZpi4h<%WcX|{@%Rlpq)QM*;HA+pkQcd=J`Cjvx*GfAFlRIU_=p*Pq3W0iV dggtjeRH^76jX#bb;^X)KFf=pBSj+kQ{{atUrA7b% literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/firmament/textures/socials/modrinth.png b/src/main/resources/assets/firmament/textures/socials/modrinth.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc94035dd89b9e0da7fd317268405a425e13091 GIT binary patch literal 4521 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", + "fabric-language-kotlin": ">=${fabric_kotlin_version}", + "minecraft": ">=${minecraft_version}" + }, + "custom": { + "configured": { + "providers": [ + "moe.nea.firmament.compat.configured.ConfiguredCompat" + ] + }, + "modmenu": { + "links": { + "modmenu.discord": "https://discord.gg/64pFP94AWA" + } + }, + "mc-publish": { + "dependencies": [ + "roughlyenoughitems(recommended){modrinth:rei}" + ] + } + } +} diff --git a/src/main/resources/fabric.mod.json.license b/src/main/resources/fabric.mod.json.license new file mode 100644 index 0000000..c01d463 --- /dev/null +++ b/src/main/resources/fabric.mod.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Linnea Gräf + +SPDX-License-Identifier: CC0-1.0 diff --git a/src/main/resources/firmament.accesswidener b/src/main/resources/firmament.accesswidener new file mode 100644 index 0000000..0b7b830 --- /dev/null +++ b/src/main/resources/firmament.accesswidener @@ -0,0 +1,36 @@ +accessWidener v2 named +accessible class net/minecraft/client/render/RenderLayer$MultiPhase +accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters +accessible class net/minecraft/client/font/TextRenderer$Drawer + +accessible field net/minecraft/client/gui/hud/InGameHud SCOREBOARD_ENTRY_COMPARATOR Ljava/util/Comparator; + +accessible field net/minecraft/client/network/ClientPlayNetworkHandler combinedDynamicRegistries Lnet/minecraft/registry/DynamicRegistryManager$Immutable; +accessible method net/minecraft/registry/RegistryOps (Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/registry/RegistryOps$RegistryInfoGetter;)V +accessible class net/minecraft/registry/RegistryOps$CachedRegistryInfoGetter +accessible class net/minecraft/client/render/model/ModelBaker$BakerImpl +accessible method net/minecraft/client/render/model/ModelBaker$BakerImpl (Lnet/minecraft/client/render/model/ModelBaker;Lnet/minecraft/client/render/model/ErrorCollectingSpriteGetter;)V + +accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData; +accessible method net/minecraft/entity/decoration/ArmorStandEntity setSmall (Z)V +accessible method net/minecraft/resource/NamespaceResourceManager loadMetadata (Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/metadata/ResourceMetadata; +accessible method net/minecraft/client/gui/DrawContext drawTexturedQuad (Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIIIFFFFI)V + +accessible class net/minecraft/client/render/model/BlockStatesLoader$LoadedBlockStateDefinition +accessible field net/minecraft/client/render/model/BlockStatesLoader FINDER Lnet/minecraft/resource/ResourceFinder; +accessible method net/minecraft/client/render/model/BlockStatesLoader$LoadedBlockStateDefinition (Ljava/lang/String;Lnet/minecraft/client/render/model/json/BlockModelDefinition;)V +accessible method net/minecraft/client/render/model/BlockStatesLoader combine (Lnet/minecraft/util/Identifier;Lnet/minecraft/state/StateManager;Ljava/util/List;)Lnet/minecraft/client/render/model/BlockStatesLoader$LoadedModels; + +mutable field net/minecraft/screen/slot/Slot x I +mutable field net/minecraft/screen/slot/Slot y I + +accessible field net/minecraft/entity/player/PlayerEntity PLAYER_MODEL_PARTS Lnet/minecraft/entity/data/TrackedData; +accessible field net/minecraft/client/render/WorldRenderer chunks Lnet/minecraft/client/render/BuiltChunkStorage; +accessible field net/minecraft/client/render/OverlayTexture texture Lnet/minecraft/client/texture/NativeImageBackedTexture; + +accessible method net/minecraft/client/render/RenderPhase$Texture getId ()Ljava/util/Optional; +accessible field net/minecraft/client/render/RenderLayer$MultiPhase phases Lnet/minecraft/client/render/RenderLayer$MultiPhaseParameters; +accessible field net/minecraft/client/render/RenderLayer$MultiPhaseParameters texture Lnet/minecraft/client/render/RenderPhase$TextureBase; +accessible field net/minecraft/client/network/ClientPlayerInteractionManager currentBreakingPos Lnet/minecraft/util/math/BlockPos; + +mutable field net/minecraft/client/render/entity/state/LivingEntityRenderState headItemRenderState Lnet/minecraft/client/render/item/ItemRenderState; diff --git a/src/main/resources/firmament.accesswidener.license b/src/main/resources/firmament.accesswidener.license new file mode 100644 index 0000000..c01d463 --- /dev/null +++ b/src/main/resources/firmament.accesswidener.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2023 Linnea Gräf + +SPDX-License-Identifier: CC0-1.0 diff --git a/src/main/resources/firmament.mixins.json b/src/main/resources/firmament.mixins.json new file mode 100644 index 0000000..d78d124 --- /dev/null +++ b/src/main/resources/firmament.mixins.json @@ -0,0 +1,10 @@ +{ + "required": true, + "plugin": "moe.nea.firmament.init.MixinPlugin", + "package": "moe.nea.firmament.mixins", + "compatibilityLevel": "JAVA_21", + "refmap": "Firmament-refmap.json", + "injectors": { + "defaultRequire": 1 + } +} diff --git a/src/main/resources/firmament.mixins.json.license b/src/main/resources/firmament.mixins.json.license new file mode 100644 index 0000000..5f0659f --- /dev/null +++ b/src/main/resources/firmament.mixins.json.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2024 Linnea Gräf + +SPDX-License-Identifier: CC0-1.0 diff --git a/src/main/resources/hotswap-agent.properties b/src/main/resources/hotswap-agent.properties new file mode 100644 index 0000000..36b065f --- /dev/null +++ b/src/main/resources/hotswap-agent.properties @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2023 Linnea Gräf +# +# SPDX-License-Identifier: CC0-1.0 + +disabledPlugins=Log4j2,Proxy +LOGGER=info diff --git a/src/main/resources/legacy_data/effects.json b/src/main/resources/legacy_data/effects.json new file mode 100644 index 0000000..0b885b5 --- /dev/null +++ b/src/main/resources/legacy_data/effects.json @@ -0,0 +1,140 @@ +[ + { + "id": 1, + "name": "Speed", + "displayName": "Speed", + "type": "good" + }, + { + "id": 2, + "name": "Slowness", + "displayName": "Slowness", + "type": "bad" + }, + { + "id": 3, + "name": "Haste", + "displayName": "Haste", + "type": "good" + }, + { + "id": 4, + "name": "MiningFatigue", + "displayName": "Mining Fatigue", + "type": "bad" + }, + { + "id": 5, + "name": "Strength", + "displayName": "Strength", + "type": "good" + }, + { + "id": 6, + "name": "InstantHealth", + "displayName": "Instant Health", + "type": "good" + }, + { + "id": 7, + "name": "InstantDamage", + "displayName": "Instant Damage", + "type": "bad" + }, + { + "id": 8, + "name": "JumpBoost", + "displayName": "Jump Boost", + "type": "good" + }, + { + "id": 9, + "name": "Nausea", + "displayName": "Nausea", + "type": "bad" + }, + { + "id": 10, + "name": "Regeneration", + "displayName": "Regeneration", + "type": "good" + }, + { + "id": 11, + "name": "Resistance", + "displayName": "Resistance", + "type": "good" + }, + { + "id": 12, + "name": "FireResistance", + "displayName": "Fire Resistance", + "type": "good" + }, + { + "id": 13, + "name": "WaterBreathing", + "displayName": "Water Breathing", + "type": "good" + }, + { + "id": 14, + "name": "Invisibility", + "displayName": "Invisibility", + "type": "good" + }, + { + "id": 15, + "name": "Blindness", + "displayName": "Blindness", + "type": "bad" + }, + { + "id": 16, + "name": "NightVision", + "displayName": "Night Vision", + "type": "good" + }, + { + "id": 17, + "name": "Hunger", + "displayName": "Hunger", + "type": "bad" + }, + { + "id": 18, + "name": "Weakness", + "displayName": "Weakness", + "type": "bad" + }, + { + "id": 19, + "name": "Poison", + "displayName": "Poison", + "type": "bad" + }, + { + "id": 20, + "name": "Wither", + "displayName": "Wither", + "type": "bad" + }, + { + "id": 21, + "name": "HealthBoost", + "displayName": "Health Boost", + "type": "good" + }, + { + "id": 22, + "name": "Absorption", + "displayName": "Absorption", + "type": "good" + }, + { + "id": 23, + "name": "Saturation", + "displayName": "Saturation", + "type": "good" + } +] diff --git a/src/main/resources/legacy_data/enchantments.json b/src/main/resources/legacy_data/enchantments.json new file mode 100644 index 0000000..8eeaa6e --- /dev/null +++ b/src/main/resources/legacy_data/enchantments.json @@ -0,0 +1,560 @@ +[ + { + "id": 0, + "name": "protection", + "displayName": "Protection", + "maxLevel": 4, + "minCost": { + "a": 11, + "b": -10 + }, + "maxCost": { + "a": 11, + "b": 1 + }, + "exclude": [ + "blast_protection", + "fire_protection", + "projectile_protection" + ], + "category": "armor", + "weight": 10, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 1, + "name": "fire_protection", + "displayName": "Fire Protection", + "maxLevel": 4, + "minCost": { + "a": 8, + "b": 2 + }, + "maxCost": { + "a": 8, + "b": 10 + }, + "exclude": [ + "blast_protection", + "protection", + "projectile_protection" + ], + "category": "armor", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 2, + "name": "feather_falling", + "displayName": "Feather Falling", + "maxLevel": 4, + "minCost": { + "a": 6, + "b": -1 + }, + "maxCost": { + "a": 6, + "b": 5 + }, + "exclude": [], + "category": "armor_feet", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 3, + "name": "blast_protection", + "displayName": "Blast Protection", + "maxLevel": 4, + "minCost": { + "a": 8, + "b": -3 + }, + "maxCost": { + "a": 8, + "b": 5 + }, + "exclude": [ + "fire_protection", + "protection", + "projectile_protection" + ], + "category": "armor", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 4, + "name": "projectile_protection", + "displayName": "Projectile Protection", + "maxLevel": 4, + "minCost": { + "a": 6, + "b": -3 + }, + "maxCost": { + "a": 6, + "b": 3 + }, + "exclude": [ + "protection", + "blast_protection", + "fire_protection" + ], + "category": "armor", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 5, + "name": "respiration", + "displayName": "Respiration", + "maxLevel": 3, + "minCost": { + "a": 10, + "b": 0 + }, + "maxCost": { + "a": 10, + "b": 30 + }, + "exclude": [], + "category": "armor_head", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 6, + "name": "aqua_affinity", + "displayName": "Aqua Affinity", + "maxLevel": 1, + "minCost": { + "a": 0, + "b": 1 + }, + "maxCost": { + "a": 0, + "b": 41 + }, + "exclude": [], + "category": "armor_head", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 7, + "name": "thorns", + "displayName": "Thorns", + "maxLevel": 3, + "minCost": { + "a": 20, + "b": -10 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "armor_chest", + "weight": 1, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 8, + "name": "depth_strider", + "displayName": "Depth Strider", + "maxLevel": 3, + "minCost": { + "a": 10, + "b": 0 + }, + "maxCost": { + "a": 10, + "b": 15 + }, + "exclude": [ + "frost_walker" + ], + "category": "armor_feet", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 16, + "name": "sharpness", + "displayName": "Sharpness", + "maxLevel": 5, + "minCost": { + "a": 11, + "b": -10 + }, + "maxCost": { + "a": 11, + "b": 10 + }, + "exclude": [ + "smite", + "bane_of_arthropods" + ], + "category": "weapon", + "weight": 10, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 17, + "name": "smite", + "displayName": "Smite", + "maxLevel": 5, + "minCost": { + "a": 8, + "b": -3 + }, + "maxCost": { + "a": 8, + "b": 17 + }, + "exclude": [ + "sharpness", + "bane_of_arthropods" + ], + "category": "weapon", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 18, + "name": "bane_of_arthropods", + "displayName": "Bane of Arthropods", + "maxLevel": 5, + "minCost": { + "a": 8, + "b": -3 + }, + "maxCost": { + "a": 8, + "b": 17 + }, + "exclude": [ + "smite", + "sharpness" + ], + "category": "weapon", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 19, + "name": "knockback", + "displayName": "Knockback", + "maxLevel": 2, + "minCost": { + "a": 20, + "b": -15 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "weapon", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 20, + "name": "fire_aspect", + "displayName": "Fire Aspect", + "maxLevel": 2, + "minCost": { + "a": 20, + "b": -10 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "weapon", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 21, + "name": "looting", + "displayName": "Looting", + "maxLevel": 3, + "minCost": { + "a": 9, + "b": 6 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "weapon", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 32, + "name": "efficiency", + "displayName": "Efficiency", + "maxLevel": 5, + "minCost": { + "a": 10, + "b": -9 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "digger", + "weight": 10, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 33, + "name": "silk_touch", + "displayName": "Silk Touch", + "maxLevel": 1, + "minCost": { + "a": 0, + "b": 15 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [ + "fortune" + ], + "category": "digger", + "weight": 1, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 34, + "name": "unbreaking", + "displayName": "Unbreaking", + "maxLevel": 3, + "minCost": { + "a": 8, + "b": -3 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "breakable", + "weight": 5, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 35, + "name": "fortune", + "displayName": "Fortune", + "maxLevel": 3, + "minCost": { + "a": 9, + "b": 6 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [ + "silk_touch" + ], + "category": "digger", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 48, + "name": "power", + "displayName": "Power", + "maxLevel": 5, + "minCost": { + "a": 10, + "b": -9 + }, + "maxCost": { + "a": 10, + "b": 6 + }, + "exclude": [], + "category": "bow", + "weight": 10, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 49, + "name": "punch", + "displayName": "Punch", + "maxLevel": 2, + "minCost": { + "a": 20, + "b": -8 + }, + "maxCost": { + "a": 20, + "b": 17 + }, + "exclude": [], + "category": "bow", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 50, + "name": "flame", + "displayName": "Flame", + "maxLevel": 1, + "minCost": { + "a": 0, + "b": 20 + }, + "maxCost": { + "a": 0, + "b": 50 + }, + "exclude": [], + "category": "bow", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 51, + "name": "infinity", + "displayName": "Infinity", + "maxLevel": 1, + "minCost": { + "a": 0, + "b": 20 + }, + "maxCost": { + "a": 0, + "b": 50 + }, + "exclude": [ + "mending" + ], + "category": "bow", + "weight": 1, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 61, + "name": "luck_of_the_sea", + "displayName": "Luck of the Sea", + "maxLevel": 3, + "minCost": { + "a": 9, + "b": 6 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "fishing_rod", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + }, + { + "id": 62, + "name": "lure", + "displayName": "Lure", + "maxLevel": 3, + "minCost": { + "a": 9, + "b": 6 + }, + "maxCost": { + "a": 10, + "b": 51 + }, + "exclude": [], + "category": "fishing_rod", + "weight": 2, + "treasureOnly": false, + "curse": false, + "tradeable": true, + "discoverable": true + } +] diff --git a/src/main/resources/legacy_data/items.json b/src/main/resources/legacy_data/items.json new file mode 100644 index 0000000..a32702c --- /dev/null +++ b/src/main/resources/legacy_data/items.json @@ -0,0 +1,3733 @@ +[ + { + "id": 1, + "displayName": "Stone", + "name": "stone", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Stone" + }, + { + "metadata": 1, + "displayName": "Granite" + }, + { + "metadata": 2, + "displayName": "Polished Granite" + }, + { + "metadata": 3, + "displayName": "Diorite" + }, + { + "metadata": 4, + "displayName": "Polished Diorite" + }, + { + "metadata": 5, + "displayName": "Andesite" + }, + { + "metadata": 6, + "displayName": "Polished Andesite" + } + ] + }, + { + "id": 2, + "displayName": "Grass Block", + "name": "grass", + "stackSize": 64 + }, + { + "id": 3, + "displayName": "Dirt", + "name": "dirt", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Dirt" + }, + { + "metadata": 1, + "displayName": "Coarse Dirt" + }, + { + "metadata": 2, + "displayName": "Podzol" + } + ] + }, + { + "id": 4, + "displayName": "Cobblestone", + "name": "cobblestone", + "stackSize": 64 + }, + { + "id": 5, + "displayName": "Wooden Planks", + "name": "planks", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Oak Wood Planks" + }, + { + "metadata": 1, + "displayName": "Spruce Wood Planks" + }, + { + "metadata": 2, + "displayName": "Birch Wood Planks" + }, + { + "metadata": 3, + "displayName": "Jungle Wood Planks" + }, + { + "metadata": 4, + "displayName": "Acacia Wood Planks" + }, + { + "metadata": 5, + "displayName": "Dark Oak Wood Planks" + } + ] + }, + { + "id": 6, + "displayName": "Sapling", + "name": "sapling", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Oak Sapling" + }, + { + "metadata": 1, + "displayName": "Spruce Sapling" + }, + { + "metadata": 2, + "displayName": "Birch Sapling" + }, + { + "metadata": 3, + "displayName": "Jungle Sapling" + }, + { + "metadata": 4, + "displayName": "Acacia Sapling" + }, + { + "metadata": 5, + "displayName": "Dark Oak Sapling" + } + ] + }, + { + "id": 7, + "displayName": "Bedrock", + "name": "bedrock", + "stackSize": 64 + }, + { + "id": 12, + "displayName": "Sand", + "name": "sand", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Sand" + }, + { + "metadata": 1, + "displayName": "Red Sand" + } + ] + }, + { + "id": 13, + "displayName": "Gravel", + "name": "gravel", + "stackSize": 64 + }, + { + "id": 14, + "displayName": "Gold Ore", + "name": "gold_ore", + "stackSize": 64 + }, + { + "id": 15, + "displayName": "Iron Ore", + "name": "iron_ore", + "stackSize": 64 + }, + { + "id": 16, + "displayName": "Coal Ore", + "name": "coal_ore", + "stackSize": 64 + }, + { + "id": 17, + "displayName": "Wood", + "name": "log", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Oak Wood" + }, + { + "metadata": 1, + "displayName": "Spruce Wood" + }, + { + "metadata": 2, + "displayName": "Birch Wood" + }, + { + "metadata": 3, + "displayName": "Jungle Wood" + }, + { + "metadata": 4, + "displayName": "Acacia Wood" + }, + { + "metadata": 5, + "displayName": "Dark Oak Wood" + } + ] + }, + { + "id": 18, + "displayName": "Leaves", + "name": "leaves", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Oak Leaves" + }, + { + "metadata": 1, + "displayName": "Spruce Leaves" + }, + { + "metadata": 2, + "displayName": "Birch Leaves" + }, + { + "metadata": 3, + "displayName": "Jungle Leaves" + } + ] + }, + { + "id": 19, + "displayName": "Sponge", + "name": "sponge", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Sponge" + }, + { + "metadata": 1, + "displayName": "Wet Sponge" + } + ] + }, + { + "id": 20, + "displayName": "Glass", + "name": "glass", + "stackSize": 64 + }, + { + "id": 21, + "displayName": "Lapis Lazuli Ore", + "name": "lapis_ore", + "stackSize": 64 + }, + { + "id": 22, + "displayName": "Lapis Lazuli Block", + "name": "lapis_block", + "stackSize": 64 + }, + { + "id": 23, + "displayName": "Dispenser", + "name": "dispenser", + "stackSize": 64 + }, + { + "id": 24, + "displayName": "Sandstone", + "name": "sandstone", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Sandstone" + }, + { + "metadata": 1, + "displayName": "Chiseled Sandstone" + }, + { + "metadata": 2, + "displayName": "Smooth Sandstone" + } + ] + }, + { + "id": 25, + "displayName": "Note Block", + "name": "noteblock", + "stackSize": 64 + }, + { + "id": 27, + "displayName": "Powered Rail", + "name": "golden_rail", + "stackSize": 64 + }, + { + "id": 28, + "displayName": "Detector Rail", + "name": "detector_rail", + "stackSize": 64 + }, + { + "id": 29, + "displayName": "Sticky Piston", + "name": "sticky_piston", + "stackSize": 64 + }, + { + "id": 30, + "displayName": "Cobweb", + "name": "web", + "stackSize": 64 + }, + { + "id": 31, + "displayName": "Grass", + "name": "tallgrass", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Shrub" + }, + { + "metadata": 1, + "displayName": "Tall Grass" + }, + { + "metadata": 2, + "displayName": "Fern" + } + ] + }, + { + "id": 32, + "displayName": "Dead Bush", + "name": "deadbush", + "stackSize": 64 + }, + { + "id": 33, + "displayName": "Piston", + "name": "piston", + "stackSize": 64 + }, + { + "id": 35, + "displayName": "Wool", + "name": "wool", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "White Wool" + }, + { + "metadata": 1, + "displayName": "Orange Wool" + }, + { + "metadata": 2, + "displayName": "Magenta Wool" + }, + { + "metadata": 3, + "displayName": "Light blue Wool" + }, + { + "metadata": 4, + "displayName": "Yellow Wool" + }, + { + "metadata": 5, + "displayName": "Lime Wool" + }, + { + "metadata": 6, + "displayName": "Pink Wool" + }, + { + "metadata": 7, + "displayName": "Gray Wool" + }, + { + "metadata": 8, + "displayName": "Light gray Wool" + }, + { + "metadata": 9, + "displayName": "Cyan Wool" + }, + { + "metadata": 10, + "displayName": "Purple Wool" + }, + { + "metadata": 11, + "displayName": "Blue Wool" + }, + { + "metadata": 12, + "displayName": "Brown Wool" + }, + { + "metadata": 13, + "displayName": "Green Wool" + }, + { + "metadata": 14, + "displayName": "Red Wool" + }, + { + "metadata": 15, + "displayName": "Black Wool" + } + ] + }, + { + "id": 37, + "displayName": "Dandelion", + "name": "yellow_flower", + "stackSize": 64 + }, + { + "id": 38, + "displayName": "Poppy", + "name": "red_flower", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Poppy" + }, + { + "metadata": 1, + "displayName": "Blue Orchid" + }, + { + "metadata": 2, + "displayName": "Allium" + }, + { + "metadata": 3, + "displayName": "Azure Bluet" + }, + { + "metadata": 4, + "displayName": "Red Tulip" + }, + { + "metadata": 5, + "displayName": "Orange Tulip" + }, + { + "metadata": 6, + "displayName": "White Tulip" + }, + { + "metadata": 7, + "displayName": "Pink Tulip" + }, + { + "metadata": 8, + "displayName": "Oxeye Daisy" + } + ] + }, + { + "id": 39, + "displayName": "Brown Mushroom", + "name": "brown_mushroom", + "stackSize": 64 + }, + { + "id": 40, + "displayName": "Red Mushroom", + "name": "red_mushroom", + "stackSize": 64 + }, + { + "id": 41, + "displayName": "Block of Gold", + "name": "gold_block", + "stackSize": 64 + }, + { + "id": 42, + "displayName": "Block of Iron", + "name": "iron_block", + "stackSize": 64 + }, + { + "id": 44, + "displayName": "Stone Slab", + "name": "stone_slab", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Stone Slab" + }, + { + "metadata": 1, + "displayName": "Sandstone Slab" + }, + { + "metadata": 2, + "displayName": "Wooden Slab" + }, + { + "metadata": 3, + "displayName": "Cobblestone Slab" + }, + { + "metadata": 4, + "displayName": "Bricks Slab" + }, + { + "metadata": 5, + "displayName": "Stone Bricks Slab" + }, + { + "metadata": 6, + "displayName": "Nether Brick Slab" + }, + { + "metadata": 7, + "displayName": "Quartz Slab" + } + ] + }, + { + "id": 45, + "displayName": "Brick", + "name": "brick_block", + "stackSize": 64 + }, + { + "id": 46, + "displayName": "TNT", + "name": "tnt", + "stackSize": 64 + }, + { + "id": 47, + "displayName": "Bookshelf", + "name": "bookshelf", + "stackSize": 64 + }, + { + "id": 48, + "displayName": "Moss Stone", + "name": "mossy_cobblestone", + "stackSize": 64 + }, + { + "id": 49, + "displayName": "Obsidian", + "name": "obsidian", + "stackSize": 64 + }, + { + "id": 50, + "displayName": "Torch", + "name": "torch", + "stackSize": 64 + }, + { + "id": 52, + "displayName": "Monster Spawner", + "name": "mob_spawner", + "stackSize": 64 + }, + { + "id": 53, + "displayName": "Oak Wood Stairs", + "name": "oak_stairs", + "stackSize": 64 + }, + { + "id": 54, + "displayName": "Chest", + "name": "chest", + "stackSize": 64 + }, + { + "id": 56, + "displayName": "Diamond Ore", + "name": "diamond_ore", + "stackSize": 64 + }, + { + "id": 57, + "displayName": "Block of Diamond", + "name": "diamond_block", + "stackSize": 64 + }, + { + "id": 58, + "displayName": "Crafting Table", + "name": "crafting_table", + "stackSize": 64 + }, + { + "id": 60, + "displayName": "Farmland", + "name": "farmland", + "stackSize": 64 + }, + { + "id": 61, + "displayName": "Furnace", + "name": "furnace", + "stackSize": 64 + }, + { + "id": 65, + "displayName": "Ladder", + "name": "ladder", + "stackSize": 64 + }, + { + "id": 66, + "displayName": "Rail", + "name": "rail", + "stackSize": 64 + }, + { + "id": 67, + "displayName": "Cobblestone Stairs", + "name": "stone_stairs", + "stackSize": 64 + }, + { + "id": 69, + "displayName": "Lever", + "name": "lever", + "stackSize": 64 + }, + { + "id": 70, + "displayName": "Stone Pressure Plate", + "name": "stone_pressure_plate", + "stackSize": 64 + }, + { + "id": 72, + "displayName": "Wooden Pressure Plate", + "name": "wooden_pressure_plate", + "stackSize": 64 + }, + { + "id": 73, + "displayName": "Redstone Ore", + "name": "redstone_ore", + "stackSize": 64 + }, + { + "id": 76, + "displayName": "Redstone Torch", + "name": "redstone_torch", + "stackSize": 64 + }, + { + "id": 77, + "displayName": "Stone Button", + "name": "stone_button", + "stackSize": 64 + }, + { + "id": 78, + "displayName": "Snow", + "name": "snow_layer", + "stackSize": 64 + }, + { + "id": 79, + "displayName": "Ice", + "name": "ice", + "stackSize": 64 + }, + { + "id": 80, + "displayName": "Snow", + "name": "snow", + "stackSize": 64 + }, + { + "id": 81, + "displayName": "Cactus", + "name": "cactus", + "stackSize": 64 + }, + { + "id": 82, + "displayName": "Clay", + "name": "clay", + "stackSize": 64 + }, + { + "id": 84, + "displayName": "Jukebox", + "name": "jukebox", + "stackSize": 64 + }, + { + "id": 85, + "displayName": "Oak Fence", + "name": "fence", + "stackSize": 64 + }, + { + "id": 86, + "displayName": "Pumpkin", + "name": "pumpkin", + "stackSize": 64 + }, + { + "id": 87, + "displayName": "Netherrack", + "name": "netherrack", + "stackSize": 64 + }, + { + "id": 88, + "displayName": "Soul Sand", + "name": "soul_sand", + "stackSize": 64 + }, + { + "id": 89, + "displayName": "Glowstone", + "name": "glowstone", + "stackSize": 64 + }, + { + "id": 91, + "displayName": "Jack o'Lantern", + "name": "lit_pumpkin", + "stackSize": 64 + }, + { + "id": 95, + "displayName": "Stained Glass", + "name": "stained_glass", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "White Stained Glass" + }, + { + "metadata": 1, + "displayName": "Orange Stained Glass" + }, + { + "metadata": 2, + "displayName": "Magenta Stained Glass" + }, + { + "metadata": 3, + "displayName": "Light Blue Stained Glass" + }, + { + "metadata": 4, + "displayName": "Yellow Stained Glass" + }, + { + "metadata": 5, + "displayName": "Lime Stained Glass" + }, + { + "metadata": 6, + "displayName": "Pink Stained Glass" + }, + { + "metadata": 7, + "displayName": "Gray Stained Glass" + }, + { + "metadata": 8, + "displayName": "Light Gray Stained Glass" + }, + { + "metadata": 9, + "displayName": "Cyan Stained Glass" + }, + { + "metadata": 10, + "displayName": "Purple Stained Glass" + }, + { + "metadata": 11, + "displayName": "Blue Stained Glass" + }, + { + "metadata": 12, + "displayName": "Brown Stained Glass" + }, + { + "metadata": 13, + "displayName": "Green Stained Glass" + }, + { + "metadata": 14, + "displayName": "Red Stained Glass" + }, + { + "metadata": 15, + "displayName": "Black Stained Glass" + } + ] + }, + { + "id": 96, + "displayName": "Wooden Trapdoor", + "name": "trapdoor", + "stackSize": 64 + }, + { + "id": 97, + "displayName": "Monster Egg", + "name": "monster_egg", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Stone Monster Egg" + }, + { + "metadata": 1, + "displayName": "Cobblestone Monster Egg" + }, + { + "metadata": 2, + "displayName": "Stone Brick Monster Egg" + }, + { + "metadata": 3, + "displayName": "Mossy Stone Brick Monster Egg" + }, + { + "metadata": 4, + "displayName": "Cracked Stone Brick Monster Egg" + }, + { + "metadata": 5, + "displayName": "Chiseled Stone Brick Monster Egg" + } + ] + }, + { + "id": 98, + "displayName": "Stone Bricks", + "name": "stonebrick", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Stone Bricks" + }, + { + "metadata": 1, + "displayName": "Mossy Stone Bricks" + }, + { + "metadata": 2, + "displayName": "Cracked Stone Bricks" + }, + { + "metadata": 3, + "displayName": "Chiseled Stone Bricks" + } + ] + }, + { + "id": 99, + "displayName": "Brown Mushroom Block", + "name": "brown_mushroom_block", + "stackSize": 64 + }, + { + "id": 100, + "displayName": "Red Mushroom Block", + "name": "red_mushroom_block", + "stackSize": 64 + }, + { + "id": 101, + "displayName": "Iron Bars", + "name": "iron_bars", + "stackSize": 64 + }, + { + "id": 102, + "displayName": "Glass Pane", + "name": "glass_pane", + "stackSize": 64 + }, + { + "id": 103, + "displayName": "Melon", + "name": "melon_block", + "stackSize": 64 + }, + { + "id": 106, + "displayName": "Vines", + "name": "vine", + "stackSize": 64 + }, + { + "id": 107, + "displayName": "Oak Fence Gate", + "name": "fence_gate", + "stackSize": 64 + }, + { + "id": 108, + "displayName": "Brick Stairs", + "name": "brick_stairs", + "stackSize": 64 + }, + { + "id": 109, + "displayName": "Stone Brick Stairs", + "name": "stone_brick_stairs", + "stackSize": 64 + }, + { + "id": 110, + "displayName": "Mycelium", + "name": "mycelium", + "stackSize": 64 + }, + { + "id": 111, + "displayName": "Lily Pad", + "name": "waterlily", + "stackSize": 64 + }, + { + "id": 112, + "displayName": "Nether Brick", + "name": "nether_brick", + "stackSize": 64 + }, + { + "id": 113, + "displayName": "Nether Brick Fence", + "name": "nether_brick_fence", + "stackSize": 64 + }, + { + "id": 114, + "displayName": "Nether Brick Stairs", + "name": "nether_brick_stairs", + "stackSize": 64 + }, + { + "id": 116, + "displayName": "Enchantment Table", + "name": "enchanting_table", + "stackSize": 64 + }, + { + "id": 120, + "displayName": "End Portal Frame", + "name": "end_portal_frame", + "stackSize": 64 + }, + { + "id": 121, + "displayName": "End Stone", + "name": "end_stone", + "stackSize": 64 + }, + { + "id": 122, + "displayName": "Dragon Egg", + "name": "dragon_egg", + "stackSize": 64 + }, + { + "id": 123, + "displayName": "Redstone Lamp", + "name": "redstone_lamp", + "stackSize": 64 + }, + { + "id": 126, + "displayName": "Wood Slab", + "name": "wooden_slab", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Oak Wood Slab" + }, + { + "metadata": 1, + "displayName": "Spruce Wood Slab" + }, + { + "metadata": 2, + "displayName": "Birch Wood Slab" + }, + { + "metadata": 3, + "displayName": "Jungle Wood Slab" + }, + { + "metadata": 4, + "displayName": "Acacia Wood Slab" + }, + { + "metadata": 5, + "displayName": "Dark Oak Wood Slab" + } + ] + }, + { + "id": 128, + "displayName": "Sandstone Stairs", + "name": "sandstone_stairs", + "stackSize": 64 + }, + { + "id": 129, + "displayName": "Emerald Ore", + "name": "emerald_ore", + "stackSize": 64 + }, + { + "id": 130, + "displayName": "Ender Chest", + "name": "ender_chest", + "stackSize": 64 + }, + { + "id": 131, + "displayName": "Tripwire Hook", + "name": "tripwire_hook", + "stackSize": 64 + }, + { + "id": 133, + "displayName": "Block of Emerald", + "name": "emerald_block", + "stackSize": 64 + }, + { + "id": 134, + "displayName": "Spruce Wood Stairs", + "name": "spruce_stairs", + "stackSize": 64 + }, + { + "id": 135, + "displayName": "Birch Wood Stairs", + "name": "birch_stairs", + "stackSize": 64 + }, + { + "id": 136, + "displayName": "Jungle Wood Stairs", + "name": "jungle_stairs", + "stackSize": 64 + }, + { + "id": 137, + "displayName": "Command Block", + "name": "command_block", + "stackSize": 64 + }, + { + "id": 138, + "displayName": "Beacon", + "name": "beacon", + "stackSize": 64 + }, + { + "id": 139, + "displayName": "Cobblestone Wall", + "name": "cobblestone_wall", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Cobblestone Wall" + }, + { + "metadata": 1, + "displayName": "Mossy Cobblestone Wall" + } + ] + }, + { + "id": 143, + "displayName": "Wooden Button", + "name": "wooden_button", + "stackSize": 64 + }, + { + "id": 145, + "displayName": "Anvil", + "name": "anvil", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Anvil" + }, + { + "metadata": 1, + "displayName": "Slightly Damaged Anvil" + }, + { + "metadata": 2, + "displayName": "Very Damaged Anvil" + } + ] + }, + { + "id": 146, + "displayName": "Trapped Chest", + "name": "trapped_chest", + "stackSize": 64 + }, + { + "id": 147, + "displayName": "Weighted Pressure Plate (Light)", + "name": "light_weighted_pressure_plate", + "stackSize": 64 + }, + { + "id": 148, + "displayName": "Weighted Pressure Plate (Heavy)", + "name": "heavy_weighted_pressure_plate", + "stackSize": 64 + }, + { + "id": 151, + "displayName": "Daylight Detector", + "name": "daylight_detector", + "stackSize": 64 + }, + { + "id": 152, + "displayName": "Block of Redstone", + "name": "redstone_block", + "stackSize": 64 + }, + { + "id": 153, + "displayName": "Nether Quartz", + "name": "quartz_ore", + "stackSize": 64 + }, + { + "id": 154, + "displayName": "Hopper", + "name": "hopper", + "stackSize": 64 + }, + { + "id": 155, + "displayName": "Block of Quartz", + "name": "quartz_block", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Block of Quartz" + }, + { + "metadata": 1, + "displayName": "Chiseled Quartz Block" + }, + { + "metadata": 2, + "displayName": "Pillar Quartz Block" + } + ] + }, + { + "id": 156, + "displayName": "Quartz Stairs", + "name": "quartz_stairs", + "stackSize": 64 + }, + { + "id": 157, + "displayName": "Activator Rail", + "name": "activator_rail", + "stackSize": 64 + }, + { + "id": 158, + "displayName": "Dropper", + "name": "dropper", + "stackSize": 64 + }, + { + "id": 159, + "displayName": "Stained Clay", + "name": "stained_hardened_clay", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "White Stained Clay" + }, + { + "metadata": 1, + "displayName": "Orange Stained Clay" + }, + { + "metadata": 2, + "displayName": "Magenta Stained Clay" + }, + { + "metadata": 3, + "displayName": "Light Blue Stained Clay" + }, + { + "metadata": 4, + "displayName": "Yellow Stained Clay" + }, + { + "metadata": 5, + "displayName": "Lime Stained Clay" + }, + { + "metadata": 6, + "displayName": "Pink Stained Clay" + }, + { + "metadata": 7, + "displayName": "Gray Stained Clay" + }, + { + "metadata": 8, + "displayName": "Light Gray Stained Clay" + }, + { + "metadata": 9, + "displayName": "Cyan Stained Clay" + }, + { + "metadata": 10, + "displayName": "Purple Stained Clay" + }, + { + "metadata": 11, + "displayName": "Blue Stained Clay" + }, + { + "metadata": 12, + "displayName": "Brown Stained Clay" + }, + { + "metadata": 13, + "displayName": "Green Stained Clay" + }, + { + "metadata": 14, + "displayName": "Red Stained Clay" + }, + { + "metadata": 15, + "displayName": "Black Stained Clay" + } + ] + }, + { + "id": 160, + "displayName": "Stained Glass Pane", + "name": "stained_glass_pane", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "White Stained Glass Pane" + }, + { + "metadata": 1, + "displayName": "Orange Stained Glass Pane" + }, + { + "metadata": 2, + "displayName": "Magenta Stained Glass Pane" + }, + { + "metadata": 3, + "displayName": "Light Blue Stained Glass Pane" + }, + { + "metadata": 4, + "displayName": "Yellow Stained Glass Pane" + }, + { + "metadata": 5, + "displayName": "Lime Stained Glass Pane" + }, + { + "metadata": 6, + "displayName": "Pink Stained Glass Pane" + }, + { + "metadata": 7, + "displayName": "Gray Stained Glass Pane" + }, + { + "metadata": 8, + "displayName": "Light Gray Stained Glass Pane" + }, + { + "metadata": 9, + "displayName": "Cyan Stained Glass Pane" + }, + { + "metadata": 10, + "displayName": "Purple Stained Glass Pane" + }, + { + "metadata": 11, + "displayName": "Blue Stained Glass Pane" + }, + { + "metadata": 12, + "displayName": "Brown Stained Glass Pane" + }, + { + "metadata": 13, + "displayName": "Green Stained Glass Pane" + }, + { + "metadata": 14, + "displayName": "Red Stained Glass Pane" + }, + { + "metadata": 15, + "displayName": "Black Stained Glass Pane" + } + ] + }, + { + "id": 161, + "displayName": "Leaves", + "name": "leaves2", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Acacia Leaves" + }, + { + "metadata": 1, + "displayName": "Dark Oak Leaves" + } + ] + }, + { + "id": 162, + "displayName": "Wood", + "name": "log2", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Acacia Wood" + }, + { + "metadata": 1, + "displayName": "Dark Oak Wood" + } + ] + }, + { + "id": 163, + "displayName": "Acacia Wood Stairs", + "name": "acacia_stairs", + "stackSize": 64 + }, + { + "id": 164, + "displayName": "Dark Oak Wood Stairs", + "name": "dark_oak_stairs", + "stackSize": 64 + }, + { + "id": 165, + "displayName": "Slime Block", + "name": "slime", + "stackSize": 64 + }, + { + "id": 166, + "displayName": "Barrier", + "name": "barrier", + "stackSize": 64 + }, + { + "id": 167, + "displayName": "Iron Trapdoor", + "name": "iron_trapdoor", + "stackSize": 64 + }, + { + "id": 168, + "displayName": "Prismarine", + "name": "prismarine", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Prismarine" + }, + { + "metadata": 1, + "displayName": "Prismarine Bricks" + }, + { + "metadata": 2, + "displayName": "Dark Prismarine" + } + ] + }, + { + "id": 169, + "displayName": "Sea Lantern", + "name": "sea_lantern", + "stackSize": 64 + }, + { + "id": 170, + "displayName": "Hay Bale", + "name": "hay_block", + "stackSize": 64 + }, + { + "id": 171, + "displayName": "Carpet", + "name": "carpet", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "White Carpet" + }, + { + "metadata": 1, + "displayName": "Orange Carpet" + }, + { + "metadata": 2, + "displayName": "Magenta Carpet" + }, + { + "metadata": 3, + "displayName": "Light Blue Carpet" + }, + { + "metadata": 4, + "displayName": "Yellow Carpet" + }, + { + "metadata": 5, + "displayName": "Lime Carpet" + }, + { + "metadata": 6, + "displayName": "Pink Carpet" + }, + { + "metadata": 7, + "displayName": "Gray Carpet" + }, + { + "metadata": 8, + "displayName": "Light Gray Carpet" + }, + { + "metadata": 9, + "displayName": "Cyan Carpet" + }, + { + "metadata": 10, + "displayName": "Purple Carpet" + }, + { + "metadata": 11, + "displayName": "Blue Carpet" + }, + { + "metadata": 12, + "displayName": "Brown Carpet" + }, + { + "metadata": 13, + "displayName": "Green Carpet" + }, + { + "metadata": 14, + "displayName": "Red Carpet" + }, + { + "metadata": 15, + "displayName": "Black Carpet" + } + ] + }, + { + "id": 172, + "displayName": "Hardened Clay", + "name": "hardened_clay", + "stackSize": 64 + }, + { + "id": 173, + "displayName": "Block of Coal", + "name": "coal_block", + "stackSize": 64 + }, + { + "id": 174, + "displayName": "Packed Ice", + "name": "packed_ice", + "stackSize": 64 + }, + { + "id": 175, + "displayName": "Large Flowers", + "name": "double_plant", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Sunflower" + }, + { + "metadata": 1, + "displayName": "Lilac" + }, + { + "metadata": 2, + "displayName": "Double Tallgrass" + }, + { + "metadata": 3, + "displayName": "Large Fern" + }, + { + "metadata": 4, + "displayName": "Rose Bush" + }, + { + "metadata": 5, + "displayName": "Peony" + } + ] + }, + { + "id": 179, + "displayName": "Red Sandstone", + "name": "red_sandstone", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Red Sandstone" + }, + { + "metadata": 1, + "displayName": "Chiseled Red Sandstone" + }, + { + "metadata": 2, + "displayName": "Smooth Red Sandstone" + } + ] + }, + { + "id": 180, + "displayName": "Red Sandstone Stairs", + "name": "red_sandstone_stairs", + "stackSize": 64 + }, + { + "id": 182, + "displayName": "Red Sandstone Slab", + "name": "stone_slab2", + "stackSize": 64 + }, + { + "id": 183, + "displayName": "Spruce Fence Gate", + "name": "spruce_fence_gate", + "stackSize": 64 + }, + { + "id": 184, + "displayName": "Birch Fence Gate", + "name": "birch_fence_gate", + "stackSize": 64 + }, + { + "id": 185, + "displayName": "Jungle Fence Gate", + "name": "jungle_fence_gate", + "stackSize": 64 + }, + { + "id": 186, + "displayName": "Dark Oak Fence Gate", + "name": "dark_oak_fence_gate", + "stackSize": 64 + }, + { + "id": 187, + "displayName": "Acacia Fence Gate", + "name": "acacia_fence_gate", + "stackSize": 64 + }, + { + "id": 188, + "displayName": "Spruce Fence", + "name": "spruce_fence", + "stackSize": 64 + }, + { + "id": 189, + "displayName": "Birch Fence", + "name": "birch_fence", + "stackSize": 64 + }, + { + "id": 190, + "displayName": "Jungle Fence", + "name": "jungle_fence", + "stackSize": 64 + }, + { + "id": 191, + "displayName": "Dark Oak Fence", + "name": "dark_oak_fence", + "stackSize": 64 + }, + { + "id": 192, + "displayName": "Acacia Fence", + "name": "acacia_fence", + "stackSize": 64 + }, + { + "id": 256, + "displayName": "Iron Shovel", + "name": "iron_shovel", + "stackSize": 1, + "maxDurability": 250, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 257, + "displayName": "Iron Pickaxe", + "name": "iron_pickaxe", + "stackSize": 1, + "maxDurability": 250, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 258, + "displayName": "Iron Axe", + "name": "iron_axe", + "stackSize": 1, + "maxDurability": 250, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 259, + "displayName": "Flint and Steel", + "name": "flint_and_steel", + "stackSize": 1, + "maxDurability": 64, + "enchantCategories": [ + "breakable", + "vanishable" + ] + }, + { + "id": 260, + "displayName": "Apple", + "name": "apple", + "stackSize": 64 + }, + { + "id": 261, + "displayName": "Bow", + "name": "bow", + "stackSize": 1, + "maxDurability": 384, + "enchantCategories": [ + "breakable", + "bow", + "vanishable" + ] + }, + { + "id": 262, + "displayName": "Arrow", + "name": "arrow", + "stackSize": 64 + }, + { + "id": 263, + "displayName": "Coal", + "name": "coal", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Coal" + }, + { + "metadata": 1, + "displayName": "Charcoal" + } + ] + }, + { + "id": 264, + "displayName": "Diamond", + "name": "diamond", + "stackSize": 64 + }, + { + "id": 265, + "displayName": "Iron Ingot", + "name": "iron_ingot", + "stackSize": 64 + }, + { + "id": 266, + "displayName": "Gold Ingot", + "name": "gold_ingot", + "stackSize": 64 + }, + { + "id": 267, + "displayName": "Iron Sword", + "name": "iron_sword", + "stackSize": 1, + "maxDurability": 250, + "enchantCategories": [ + "weapon", + "breakable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 268, + "displayName": "Wooden Sword", + "name": "wooden_sword", + "stackSize": 1, + "maxDurability": 59, + "enchantCategories": [ + "weapon", + "breakable", + "vanishable" + ], + "repairWith": [ + "oak_planks", + "spruce_planks", + "birch_planks", + "jungle_planks", + "acacia_planks", + "dark_oak_planks", + "crimson_planks", + "warped_planks" + ] + }, + { + "id": 269, + "displayName": "Wooden Shovel", + "name": "wooden_shovel", + "stackSize": 1, + "maxDurability": 59, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "oak_planks", + "spruce_planks", + "birch_planks", + "jungle_planks", + "acacia_planks", + "dark_oak_planks", + "crimson_planks", + "warped_planks" + ] + }, + { + "id": 270, + "displayName": "Wooden Pickaxe", + "name": "wooden_pickaxe", + "stackSize": 1, + "maxDurability": 59, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "oak_planks", + "spruce_planks", + "birch_planks", + "jungle_planks", + "acacia_planks", + "dark_oak_planks", + "crimson_planks", + "warped_planks" + ] + }, + { + "id": 271, + "displayName": "Wooden Axe", + "name": "wooden_axe", + "stackSize": 1, + "maxDurability": 59, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "oak_planks", + "spruce_planks", + "birch_planks", + "jungle_planks", + "acacia_planks", + "dark_oak_planks", + "crimson_planks", + "warped_planks" + ] + }, + { + "id": 272, + "displayName": "Stone Sword", + "name": "stone_sword", + "stackSize": 1, + "maxDurability": 131, + "enchantCategories": [ + "weapon", + "breakable", + "vanishable" + ], + "repairWith": [ + "cobblestone", + "blackstone" + ] + }, + { + "id": 273, + "displayName": "Stone Shovel", + "name": "stone_shovel", + "stackSize": 1, + "maxDurability": 131, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "cobblestone", + "blackstone" + ] + }, + { + "id": 274, + "displayName": "Stone Pickaxe", + "name": "stone_pickaxe", + "stackSize": 1, + "maxDurability": 131, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "cobblestone", + "blackstone" + ] + }, + { + "id": 275, + "displayName": "Stone Axe", + "name": "stone_axe", + "stackSize": 1, + "maxDurability": 131, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "cobblestone", + "blackstone" + ] + }, + { + "id": 276, + "displayName": "Diamond Sword", + "name": "diamond_sword", + "stackSize": 1, + "maxDurability": 1561, + "enchantCategories": [ + "weapon", + "breakable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 277, + "displayName": "Diamond Shovel", + "name": "diamond_shovel", + "stackSize": 1, + "maxDurability": 1561, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 278, + "displayName": "Diamond Pickaxe", + "name": "diamond_pickaxe", + "stackSize": 1, + "maxDurability": 1561, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 279, + "displayName": "Diamond Axe", + "name": "diamond_axe", + "stackSize": 1, + "maxDurability": 1561, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 280, + "displayName": "Stick", + "name": "stick", + "stackSize": 64 + }, + { + "id": 281, + "displayName": "Bowl", + "name": "bowl", + "stackSize": 64 + }, + { + "id": 282, + "displayName": "Mushroom Stew", + "name": "mushroom_stew", + "stackSize": 1 + }, + { + "id": 283, + "displayName": "Golden Sword", + "name": "golden_sword", + "stackSize": 1, + "maxDurability": 32, + "enchantCategories": [ + "weapon", + "breakable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 284, + "displayName": "Golden Shovel", + "name": "golden_shovel", + "stackSize": 1, + "maxDurability": 32, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 285, + "displayName": "Golden Pickaxe", + "name": "golden_pickaxe", + "stackSize": 1, + "maxDurability": 32, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 286, + "displayName": "Golden Axe", + "name": "golden_axe", + "stackSize": 1, + "maxDurability": 32, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 287, + "displayName": "String", + "name": "string", + "stackSize": 64 + }, + { + "id": 288, + "displayName": "Feather", + "name": "feather", + "stackSize": 64 + }, + { + "id": 289, + "displayName": "Gunpowder", + "name": "gunpowder", + "stackSize": 64 + }, + { + "id": 290, + "displayName": "Wooden Hoe", + "name": "wooden_hoe", + "stackSize": 1, + "maxDurability": 59, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "oak_planks", + "spruce_planks", + "birch_planks", + "jungle_planks", + "acacia_planks", + "dark_oak_planks", + "crimson_planks", + "warped_planks" + ] + }, + { + "id": 291, + "displayName": "Stone Hoe", + "name": "stone_hoe", + "stackSize": 1, + "maxDurability": 131, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "cobblestone", + "blackstone" + ] + }, + { + "id": 292, + "displayName": "Iron Hoe", + "name": "iron_hoe", + "stackSize": 1, + "maxDurability": 250, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 293, + "displayName": "Diamond Hoe", + "name": "diamond_hoe", + "stackSize": 1, + "maxDurability": 1561, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 294, + "displayName": "Golden Hoe", + "name": "golden_hoe", + "stackSize": 1, + "maxDurability": 32, + "enchantCategories": [ + "digger", + "breakable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 295, + "displayName": "Seeds", + "name": "wheat_seeds", + "stackSize": 64 + }, + { + "id": 296, + "displayName": "Wheat", + "name": "wheat", + "stackSize": 64 + }, + { + "id": 297, + "displayName": "Bread", + "name": "bread", + "stackSize": 64 + }, + { + "id": 298, + "displayName": "Leather Cap", + "name": "leather_helmet", + "stackSize": 1, + "maxDurability": 55, + "enchantCategories": [ + "armor", + "armor_head", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "leather" + ] + }, + { + "id": 299, + "displayName": "Leather Tunic", + "name": "leather_chestplate", + "stackSize": 1, + "maxDurability": 80, + "enchantCategories": [ + "armor", + "armor_chest", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "leather" + ] + }, + { + "id": 300, + "displayName": "Leather Pants", + "name": "leather_leggings", + "stackSize": 1, + "maxDurability": 75, + "enchantCategories": [ + "armor", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "leather" + ] + }, + { + "id": 301, + "displayName": "Leather Boots", + "name": "leather_boots", + "stackSize": 1, + "maxDurability": 65, + "enchantCategories": [ + "armor", + "armor_feet", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "leather" + ] + }, + { + "id": 302, + "displayName": "Chain Helmet", + "name": "chainmail_helmet", + "stackSize": 1, + "maxDurability": 165, + "enchantCategories": [ + "armor", + "armor_head", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 303, + "displayName": "Chain Chestplate", + "name": "chainmail_chestplate", + "stackSize": 1, + "maxDurability": 240, + "enchantCategories": [ + "armor", + "armor_chest", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 304, + "displayName": "Chain Leggings", + "name": "chainmail_leggings", + "stackSize": 1, + "maxDurability": 225, + "enchantCategories": [ + "armor", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 305, + "displayName": "Chain Boots", + "name": "chainmail_boots", + "stackSize": 1, + "maxDurability": 195, + "enchantCategories": [ + "armor", + "armor_feet", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 306, + "displayName": "Iron Helmet", + "name": "iron_helmet", + "stackSize": 1, + "maxDurability": 165, + "enchantCategories": [ + "armor", + "armor_head", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 307, + "displayName": "Iron Chestplate", + "name": "iron_chestplate", + "stackSize": 1, + "maxDurability": 240, + "enchantCategories": [ + "armor", + "armor_chest", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 308, + "displayName": "Iron Leggings", + "name": "iron_leggings", + "stackSize": 1, + "maxDurability": 225, + "enchantCategories": [ + "armor", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 309, + "displayName": "Iron Boots", + "name": "iron_boots", + "stackSize": 1, + "maxDurability": 195, + "enchantCategories": [ + "armor", + "armor_feet", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "iron_ingot" + ] + }, + { + "id": 310, + "displayName": "Diamond Helmet", + "name": "diamond_helmet", + "stackSize": 1, + "maxDurability": 363, + "enchantCategories": [ + "armor", + "armor_head", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 311, + "displayName": "Diamond Chestplate", + "name": "diamond_chestplate", + "stackSize": 1, + "maxDurability": 528, + "enchantCategories": [ + "armor", + "armor_chest", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 312, + "displayName": "Diamond Leggings", + "name": "diamond_leggings", + "stackSize": 1, + "maxDurability": 495, + "enchantCategories": [ + "armor", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 313, + "displayName": "Diamond Boots", + "name": "diamond_boots", + "stackSize": 1, + "maxDurability": 429, + "enchantCategories": [ + "armor", + "armor_feet", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "diamond" + ] + }, + { + "id": 314, + "displayName": "Golden Helmet", + "name": "golden_helmet", + "stackSize": 1, + "maxDurability": 77, + "enchantCategories": [ + "armor", + "armor_head", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 315, + "displayName": "Golden Chestplate", + "name": "golden_chestplate", + "stackSize": 1, + "maxDurability": 112, + "enchantCategories": [ + "armor", + "armor_chest", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 316, + "displayName": "Golden Leggings", + "name": "golden_leggings", + "stackSize": 1, + "maxDurability": 105, + "enchantCategories": [ + "armor", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 317, + "displayName": "Golden Boots", + "name": "golden_boots", + "stackSize": 1, + "maxDurability": 91, + "enchantCategories": [ + "armor", + "armor_feet", + "breakable", + "wearable", + "vanishable" + ], + "repairWith": [ + "gold_ingot" + ] + }, + { + "id": 318, + "displayName": "Flint", + "name": "flint", + "stackSize": 64 + }, + { + "id": 319, + "displayName": "Raw Porkchop", + "name": "porkchop", + "stackSize": 64 + }, + { + "id": 320, + "displayName": "Cooked Porkchop", + "name": "cooked_porkchop", + "stackSize": 64 + }, + { + "id": 321, + "displayName": "Painting", + "name": "painting", + "stackSize": 64 + }, + { + "id": 322, + "displayName": "Golden Apple", + "name": "golden_apple", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Golden Apple" + }, + { + "metadata": 1, + "displayName": "Enchanted Golden Apple" + } + ] + }, + { + "id": 323, + "displayName": "Sign", + "name": "sign", + "stackSize": 16 + }, + { + "id": 324, + "displayName": "Oak Door", + "name": "wooden_door", + "stackSize": 64 + }, + { + "id": 325, + "displayName": "Bucket", + "name": "bucket", + "stackSize": 16 + }, + { + "id": 326, + "displayName": "Water Bucket", + "name": "water_bucket", + "stackSize": 1 + }, + { + "id": 327, + "displayName": "Lava Bucket", + "name": "lava_bucket", + "stackSize": 1 + }, + { + "id": 328, + "displayName": "Minecart", + "name": "minecart", + "stackSize": 1 + }, + { + "id": 329, + "displayName": "Saddle", + "name": "saddle", + "stackSize": 1 + }, + { + "id": 330, + "displayName": "Iron Door", + "name": "iron_door", + "stackSize": 64 + }, + { + "id": 331, + "displayName": "Redstone", + "name": "redstone", + "stackSize": 64 + }, + { + "id": 332, + "displayName": "Snowball", + "name": "snowball", + "stackSize": 16 + }, + { + "id": 333, + "displayName": "Boat", + "name": "boat", + "stackSize": 1 + }, + { + "id": 334, + "displayName": "Leather", + "name": "leather", + "stackSize": 64 + }, + { + "id": 335, + "displayName": "Milk", + "name": "milk_bucket", + "stackSize": 1 + }, + { + "id": 336, + "displayName": "Brick", + "name": "brick", + "stackSize": 64 + }, + { + "id": 337, + "displayName": "Clay", + "name": "clay_ball", + "stackSize": 64 + }, + { + "id": 338, + "displayName": "Sugar Canes", + "name": "reeds", + "stackSize": 64 + }, + { + "id": 339, + "displayName": "Paper", + "name": "paper", + "stackSize": 64 + }, + { + "id": 340, + "displayName": "Book", + "name": "book", + "stackSize": 64 + }, + { + "id": 341, + "displayName": "Slimeball", + "name": "slime_ball", + "stackSize": 64 + }, + { + "id": 342, + "displayName": "Minecart with Chest", + "name": "chest_minecart", + "stackSize": 1 + }, + { + "id": 343, + "displayName": "Minecart with Furnace", + "name": "furnace_minecart", + "stackSize": 1 + }, + { + "id": 344, + "displayName": "Egg", + "name": "egg", + "stackSize": 16 + }, + { + "id": 345, + "displayName": "Compass", + "name": "compass", + "stackSize": 64 + }, + { + "id": 346, + "displayName": "Fishing Rod", + "name": "fishing_rod", + "stackSize": 1, + "maxDurability": 64, + "enchantCategories": [ + "breakable", + "fishing_rod", + "vanishable" + ] + }, + { + "id": 347, + "displayName": "Clock", + "name": "clock", + "stackSize": 64 + }, + { + "id": 348, + "displayName": "Glowstone Dust", + "name": "glowstone_dust", + "stackSize": 64 + }, + { + "id": 349, + "displayName": "Fish", + "name": "fish", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Raw Fish" + }, + { + "metadata": 1, + "displayName": "Raw Salmon" + }, + { + "metadata": 2, + "displayName": "Clownfish" + }, + { + "metadata": 3, + "displayName": "Pufferfish" + } + ] + }, + { + "id": 350, + "displayName": "Cooked Fish", + "name": "cooked_fish", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Cooked Fish" + }, + { + "metadata": 1, + "displayName": "Cooked Salmon" + } + ] + }, + { + "id": 351, + "displayName": "Dye", + "name": "dye", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Ink Sac" + }, + { + "metadata": 1, + "displayName": "Rose Red" + }, + { + "metadata": 2, + "displayName": "Cactus Green" + }, + { + "metadata": 3, + "displayName": "Cocoa Beans" + }, + { + "metadata": 4, + "displayName": "Lapis Lazuli" + }, + { + "metadata": 5, + "displayName": "Purple Dye" + }, + { + "metadata": 6, + "displayName": "Cyan Dye" + }, + { + "metadata": 7, + "displayName": "Light Gray Dye" + }, + { + "metadata": 8, + "displayName": "Gray Dye" + }, + { + "metadata": 9, + "displayName": "Pink Dye" + }, + { + "metadata": 10, + "displayName": "Lime Dye" + }, + { + "metadata": 11, + "displayName": "Dandelion Yellow" + }, + { + "metadata": 12, + "displayName": "Light Blue Dye" + }, + { + "metadata": 13, + "displayName": "Magenta Dye" + }, + { + "metadata": 14, + "displayName": "Orange Dye" + }, + { + "metadata": 15, + "displayName": "Bone Meal" + } + ] + }, + { + "id": 352, + "displayName": "Bone", + "name": "bone", + "stackSize": 64 + }, + { + "id": 353, + "displayName": "Sugar", + "name": "sugar", + "stackSize": 64 + }, + { + "id": 354, + "displayName": "Cake", + "name": "cake", + "stackSize": 1 + }, + { + "id": 355, + "displayName": "Bed", + "name": "bed", + "stackSize": 1 + }, + { + "id": 356, + "displayName": "Redstone Repeater", + "name": "repeater", + "stackSize": 64 + }, + { + "id": 357, + "displayName": "Cookie", + "name": "cookie", + "stackSize": 64 + }, + { + "id": 358, + "displayName": "Map", + "name": "filled_map", + "stackSize": 64 + }, + { + "id": 359, + "displayName": "Shears", + "name": "shears", + "stackSize": 1, + "maxDurability": 238, + "enchantCategories": [ + "breakable", + "vanishable" + ] + }, + { + "id": 360, + "displayName": "Melon", + "name": "melon", + "stackSize": 64 + }, + { + "id": 361, + "displayName": "Pumpkin Seeds", + "name": "pumpkin_seeds", + "stackSize": 64 + }, + { + "id": 362, + "displayName": "Melon Seeds", + "name": "melon_seeds", + "stackSize": 64 + }, + { + "id": 363, + "displayName": "Raw Beef", + "name": "beef", + "stackSize": 64 + }, + { + "id": 364, + "displayName": "Steak", + "name": "cooked_beef", + "stackSize": 64 + }, + { + "id": 365, + "displayName": "Raw Chicken", + "name": "chicken", + "stackSize": 64 + }, + { + "id": 366, + "displayName": "Cooked Chicken", + "name": "cooked_chicken", + "stackSize": 64 + }, + { + "id": 367, + "displayName": "Rotten Flesh", + "name": "rotten_flesh", + "stackSize": 64 + }, + { + "id": 368, + "displayName": "Ender Pearl", + "name": "ender_pearl", + "stackSize": 16 + }, + { + "id": 369, + "displayName": "Blaze Rod", + "name": "blaze_rod", + "stackSize": 64 + }, + { + "id": 370, + "displayName": "Ghast Tear", + "name": "ghast_tear", + "stackSize": 64 + }, + { + "id": 371, + "displayName": "Gold Nugget", + "name": "gold_nugget", + "stackSize": 64 + }, + { + "id": 372, + "displayName": "Nether Wart", + "name": "nether_wart", + "stackSize": 64 + }, + { + "id": 373, + "displayName": "Potion", + "name": "potion", + "stackSize": 1 + }, + { + "id": 374, + "displayName": "Glass Bottle", + "name": "glass_bottle", + "stackSize": 64 + }, + { + "id": 375, + "displayName": "Spider Eye", + "name": "spider_eye", + "stackSize": 64 + }, + { + "id": 376, + "displayName": "Fermented Spider Eye", + "name": "fermented_spider_eye", + "stackSize": 64 + }, + { + "id": 377, + "displayName": "Blaze Powder", + "name": "blaze_powder", + "stackSize": 64 + }, + { + "id": 378, + "displayName": "Magma Cream", + "name": "magma_cream", + "stackSize": 64 + }, + { + "id": 379, + "displayName": "Brewing Stand", + "name": "brewing_stand", + "stackSize": 64 + }, + { + "id": 380, + "displayName": "Cauldron", + "name": "cauldron", + "stackSize": 64 + }, + { + "id": 381, + "displayName": "Eye of Ender", + "name": "ender_eye", + "stackSize": 64 + }, + { + "id": 382, + "displayName": "Glistering Melon", + "name": "speckled_melon", + "stackSize": 64 + }, + { + "id": 383, + "displayName": "Spawn Egg", + "name": "spawn_egg", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Spawn" + }, + { + "metadata": 1, + "displayName": "Spawn Dropped item" + }, + { + "metadata": 7, + "displayName": "Spawn Thrown egg" + }, + { + "metadata": 8, + "displayName": "Spawn Lead knot" + }, + { + "metadata": 10, + "displayName": "Spawn Shot arrow" + }, + { + "metadata": 11, + "displayName": "Spawn Thrown snowball" + }, + { + "metadata": 12, + "displayName": "Spawn Ghast fireball" + }, + { + "metadata": 13, + "displayName": "Spawn Blaze fireball" + }, + { + "metadata": 14, + "displayName": "Spawn Thrown Ender Pearl" + }, + { + "metadata": 15, + "displayName": "Spawn Thrown Eye of Ender" + }, + { + "metadata": 16, + "displayName": "Spawn Thrown splash potion" + }, + { + "metadata": 17, + "displayName": "Spawn Thrown Bottle o' Enchanting" + }, + { + "metadata": 18, + "displayName": "Spawn Item Frame" + }, + { + "metadata": 19, + "displayName": "Spawn Wither Skull" + }, + { + "metadata": 20, + "displayName": "Spawn Primed TNT" + }, + { + "metadata": 21, + "displayName": "Spawn Falling block" + }, + { + "metadata": 21, + "displayName": "Spawn Falling block" + }, + { + "metadata": 22, + "displayName": "Spawn Firework Rocket" + }, + { + "metadata": 30, + "displayName": "Spawn Armor Stand" + }, + { + "metadata": 41, + "displayName": "Spawn Boat" + }, + { + "metadata": 42, + "displayName": "Spawn Minecart" + }, + { + "metadata": 42, + "displayName": "Spawn Minecart" + }, + { + "metadata": 42, + "displayName": "Spawn Minecart" + }, + { + "metadata": 48, + "displayName": "Spawn Mob" + }, + { + "metadata": 49, + "displayName": "Spawn Monster" + }, + { + "metadata": 50, + "displayName": "Spawn Creeper" + }, + { + "metadata": 51, + "displayName": "Spawn Skeleton" + }, + { + "metadata": 52, + "displayName": "Spawn Spider" + }, + { + "metadata": 53, + "displayName": "Spawn Giant" + }, + { + "metadata": 54, + "displayName": "Spawn Zombie" + }, + { + "metadata": 55, + "displayName": "Spawn Slime" + }, + { + "metadata": 56, + "displayName": "Spawn Ghast" + }, + { + "metadata": 57, + "displayName": "Spawn Zombie Pigman" + }, + { + "metadata": 58, + "displayName": "Spawn Enderman" + }, + { + "metadata": 59, + "displayName": "Spawn Cave Spider" + }, + { + "metadata": 60, + "displayName": "Spawn Silverfish" + }, + { + "metadata": 61, + "displayName": "Spawn Blaze" + }, + { + "metadata": 62, + "displayName": "Spawn Magma Cube" + }, + { + "metadata": 63, + "displayName": "Spawn Ender Dragon" + }, + { + "metadata": 64, + "displayName": "Spawn Wither" + }, + { + "metadata": 65, + "displayName": "Spawn Bat" + }, + { + "metadata": 66, + "displayName": "Spawn Witch" + }, + { + "metadata": 67, + "displayName": "Spawn Endermite" + }, + { + "metadata": 68, + "displayName": "Spawn Guardian" + }, + { + "metadata": 90, + "displayName": "Spawn Pig" + }, + { + "metadata": 91, + "displayName": "Spawn Sheep" + }, + { + "metadata": 92, + "displayName": "Spawn Cow" + }, + { + "metadata": 93, + "displayName": "Spawn Chicken" + }, + { + "metadata": 94, + "displayName": "Spawn Squid" + }, + { + "metadata": 95, + "displayName": "Spawn Wolf" + }, + { + "metadata": 96, + "displayName": "Spawn Mooshroom" + }, + { + "metadata": 97, + "displayName": "Spawn Snow Golem" + }, + { + "metadata": 98, + "displayName": "Spawn Ocelot" + }, + { + "metadata": 99, + "displayName": "Spawn Iron Golem" + }, + { + "metadata": 100, + "displayName": "Spawn Horse" + }, + { + "metadata": 101, + "displayName": "Spawn Rabbit" + }, + { + "metadata": 120, + "displayName": "Spawn Villager" + }, + { + "metadata": 200, + "displayName": "Spawn Ender Crystal" + } + ] + }, + { + "id": 384, + "displayName": "Bottle o' Enchanting", + "name": "experience_bottle", + "stackSize": 64 + }, + { + "id": 385, + "displayName": "Fire Charge", + "name": "fire_charge", + "stackSize": 64 + }, + { + "id": 386, + "displayName": "Book and Quill", + "name": "writable_book", + "stackSize": 1 + }, + { + "id": 387, + "displayName": "Written Book", + "name": "written_book", + "stackSize": 16 + }, + { + "id": 388, + "displayName": "Emerald", + "name": "emerald", + "stackSize": 64 + }, + { + "id": 389, + "displayName": "Item Frame", + "name": "item_frame", + "stackSize": 64 + }, + { + "id": 390, + "displayName": "Flower Pot", + "name": "flower_pot", + "stackSize": 64 + }, + { + "id": 391, + "displayName": "Carrot", + "name": "carrot", + "stackSize": 64 + }, + { + "id": 392, + "displayName": "Potato", + "name": "potato", + "stackSize": 64 + }, + { + "id": 393, + "displayName": "Baked Potato", + "name": "baked_potato", + "stackSize": 64 + }, + { + "id": 394, + "displayName": "Poisonous Potato", + "name": "poisonous_potato", + "stackSize": 64 + }, + { + "id": 395, + "displayName": "Empty Map", + "name": "map", + "stackSize": 64 + }, + { + "id": 396, + "displayName": "Golden Carrot", + "name": "golden_carrot", + "stackSize": 64 + }, + { + "id": 397, + "displayName": "Skull", + "name": "skull", + "stackSize": 64, + "variations": [ + { + "metadata": 0, + "displayName": "Skeleton Skull" + }, + { + "metadata": 1, + "displayName": "Wither Skeleton Skull" + }, + { + "metadata": 2, + "displayName": "Zombie Head" + }, + { + "metadata": 3, + "displayName": "Head" + }, + { + "metadata": 4, + "displayName": "Creeper Head" + } + ] + }, + { + "id": 398, + "displayName": "Carrot on a Stick", + "name": "carrot_on_a_stick", + "stackSize": 1, + "maxDurability": 25, + "enchantCategories": [ + "breakable", + "vanishable" + ] + }, + { + "id": 399, + "displayName": "Nether Star", + "name": "nether_star", + "stackSize": 64 + }, + { + "id": 400, + "displayName": "Pumpkin Pie", + "name": "pumpkin_pie", + "stackSize": 64 + }, + { + "id": 401, + "displayName": "Firework Rocket", + "name": "fireworks", + "stackSize": 64 + }, + { + "id": 402, + "displayName": "Firework Star", + "name": "firework_charge", + "stackSize": 64 + }, + { + "id": 403, + "displayName": "Enchanted Book", + "name": "enchanted_book", + "stackSize": 1 + }, + { + "id": 404, + "displayName": "Redstone Comparator", + "name": "comparator", + "stackSize": 64 + }, + { + "id": 405, + "displayName": "Nether Brick", + "name": "netherbrick", + "stackSize": 64 + }, + { + "id": 406, + "displayName": "Nether Quartz", + "name": "quartz", + "stackSize": 64 + }, + { + "id": 407, + "displayName": "Minecart with TNT", + "name": "tnt_minecart", + "stackSize": 1 + }, + { + "id": 408, + "displayName": "Minecart with Hopper", + "name": "hopper_minecart", + "stackSize": 1 + }, + { + "id": 409, + "displayName": "Prismarine Shard", + "name": "prismarine_shard", + "stackSize": 64 + }, + { + "id": 410, + "displayName": "Prismarine Crystals", + "name": "prismarine_crystals", + "stackSize": 64 + }, + { + "id": 411, + "displayName": "Raw Rabbit", + "name": "rabbit", + "stackSize": 64 + }, + { + "id": 412, + "displayName": "Cooked Rabbit", + "name": "cooked_rabbit", + "stackSize": 64 + }, + { + "id": 413, + "displayName": "Rabbit Stew", + "name": "rabbit_stew", + "stackSize": 1 + }, + { + "id": 414, + "displayName": "Rabbit's Foot", + "name": "rabbit_foot", + "stackSize": 64 + }, + { + "id": 415, + "displayName": "Rabbit Hide", + "name": "rabbit_hide", + "stackSize": 64 + }, + { + "id": 416, + "displayName": "Armor Stand", + "name": "armor_stand", + "stackSize": 16 + }, + { + "id": 417, + "displayName": "Iron Horse Armor", + "name": "iron_horse_armor", + "stackSize": 1 + }, + { + "id": 418, + "displayName": "Gold Horse Armor", + "name": "golden_horse_armor", + "stackSize": 1 + }, + { + "id": 419, + "displayName": "Diamond Horse Armor", + "name": "diamond_horse_armor", + "stackSize": 1 + }, + { + "id": 420, + "displayName": "Lead", + "name": "lead", + "stackSize": 64 + }, + { + "id": 421, + "displayName": "Name Tag", + "name": "name_tag", + "stackSize": 64 + }, + { + "id": 422, + "displayName": "Minecart with Command Block", + "name": "command_block_minecart", + "stackSize": 1 + }, + { + "id": 423, + "displayName": "Raw Mutton", + "name": "mutton", + "stackSize": 64 + }, + { + "id": 424, + "displayName": "Cooked Mutton", + "name": "cooked_mutton", + "stackSize": 64 + }, + { + "id": 425, + "displayName": "Banner", + "name": "banner", + "stackSize": 16, + "variations": [ + { + "metadata": 0, + "displayName": "Black Banner" + }, + { + "metadata": 1, + "displayName": "Red Banner" + }, + { + "metadata": 2, + "displayName": "Green Banner" + }, + { + "metadata": 3, + "displayName": "Brown Banner" + }, + { + "metadata": 4, + "displayName": "Blue Banner" + }, + { + "metadata": 5, + "displayName": "Purple Banner" + }, + { + "metadata": 6, + "displayName": "Cyan Banner" + }, + { + "metadata": 7, + "displayName": "Light Gray Banner" + }, + { + "metadata": 8, + "displayName": "Gray Banner" + }, + { + "metadata": 9, + "displayName": "Pink Banner" + }, + { + "metadata": 10, + "displayName": "Lime Banner" + }, + { + "metadata": 11, + "displayName": "Yellow Banner" + }, + { + "metadata": 12, + "displayName": "Light Blue Banner" + }, + { + "metadata": 13, + "displayName": "Magenta Banner" + }, + { + "metadata": 14, + "displayName": "Orange Banner" + }, + { + "metadata": 15, + "displayName": "White Banner" + } + ] + }, + { + "id": 427, + "displayName": "Spruce Door", + "name": "spruce_door", + "stackSize": 64 + }, + { + "id": 428, + "displayName": "Birch Door", + "name": "birch_door", + "stackSize": 64 + }, + { + "id": 429, + "displayName": "Jungle Door", + "name": "jungle_door", + "stackSize": 64 + }, + { + "id": 430, + "displayName": "Acacia Door", + "name": "acacia_door", + "stackSize": 64 + }, + { + "id": 431, + "displayName": "Dark Oak Door", + "name": "dark_oak_door", + "stackSize": 64 + }, + { + "id": 2256, + "displayName": "13 Disc", + "name": "record_13", + "stackSize": 1 + }, + { + "id": 2257, + "displayName": "Cat Disc", + "name": "record_cat", + "stackSize": 1 + }, + { + "id": 2258, + "displayName": "Blocks Disc", + "name": "record_blocks", + "stackSize": 1 + }, + { + "id": 2259, + "displayName": "Chirp Disc", + "name": "record_chirp", + "stackSize": 1 + }, + { + "id": 2260, + "displayName": "Far Disc", + "name": "record_far", + "stackSize": 1 + }, + { + "id": 2261, + "displayName": "Mall Disc", + "name": "record_mall", + "stackSize": 1 + }, + { + "id": 2262, + "displayName": "Mellohi Disc", + "name": "record_mellohi", + "stackSize": 1 + }, + { + "id": 2263, + "displayName": "Stal Disc", + "name": "record_stal", + "stackSize": 1 + }, + { + "id": 2264, + "displayName": "Strad Disc", + "name": "record_strad", + "stackSize": 1 + }, + { + "id": 2265, + "displayName": "Ward Disc", + "name": "record_ward", + "stackSize": 1 + }, + { + "id": 2266, + "displayName": "11 Disc", + "name": "record_11", + "stackSize": 1 + }, + { + "id": 2267, + "displayName": "Wait Disc", + "name": "record_wait", + "stackSize": 1 + } +] \ No newline at end of file diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/inventory_button_background.png b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/inventory_button_background.png new file mode 100644 index 0000000000000000000000000000000000000000..46c86f41eb7031bf60b79bbb6fb424c0dca93e2e GIT binary patch literal 122 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|M^6{WkcznE1c!$IDM=z9?5(V3 z>Gb4CL>#zt=gth7HH#NBo9A3ncvEpj;SdPVP-AQ4W#*jFJdw9i+D(m(nPHuYtH+j4 SZF)e%7(8A5T-G@yGywo3?Itz= literal 0 HcmV?d00001 diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/player_inventory.png b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/player_inventory.png new file mode 100644 index 0000000000000000000000000000000000000000..1831ef3b6d6640cd522a334ccbe5b0a9ad3c29fd GIT binary patch literal 639 zcmeAS@N?(olHy`uVBq!ia0vp^JAgQvgAGU?cnWu|m zNX4ADcQ^VeC5p5?G?uoOdf!;K>!!>5*6y2c{${4H{LavM>zvsJ!9xP>GKXty{FlFY zsDJN~xb2NCxwo%398LOI{lajENPd1kzjOcJUniRn`0uW)s*ATJU-ORiC-qcpBK-%_M%%M4ld*=l=-hN@2URIp*<-oK9ooY~*&ceg&jjMRE>)jjm zy<2z%i=UYuck8#j2-H49*!H*^e-7BA__RY5{J)rd?#(lwZ5NrRzX*A-P6Oh(ErH(0 zx4k;Mv&FJK`s?x=tIRfFzDqz6wi;Is} zw-EAqyxBhG-Iv_kepL!T^o~EW`_;+(S7mwQ`|>SM>%FX!PE1^p{TP^{7(8A5T-G@y GGywn*BQv!C literal 0 HcmV?d00001 diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/scroll_bar_background.png new file mode 100644 index 0000000000000000000000000000000000000000..5b774b21a57bfc1ec91245757f1a212e48794662 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^f{M~?>Fs^(dAX6fN6IMc#0o{`3=ZyH s2lm(h_b_X@c<9ih{hKx!x#}@84nJa0`JjpT9~{l>kRQ`sstPc|gBGbNtdG)fN75P0={)BVHWo&`O=E_;6Y z<;)#-^JX(g{BB!+{k4JbW#!K?-zs*-Tzi-I>(Adh`!{jGL=-&3TzAu@v-%fKf9=}) wr+!~p*r~ivH{LV;{=z-qKIg_lhZ(zopr0KFAmM*si- literal 0 HcmV?d00001 diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png.mcmeta b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png.mcmeta new file mode 100644 index 0000000..5964a6f --- /dev/null +++ b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_controls.png.mcmeta @@ -0,0 +1,10 @@ +{ + "gui": { + "scaling": { + "type": "nine_slice", + "width": 91, + "height": 184, + "border": 7 + } + } +} diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png new file mode 100644 index 0000000000000000000000000000000000000000..61e9ee5065710b5a11060f8529eaf8dfd9e047c6 GIT binary patch literal 203 zcmeAS@N?(olHy`uVBq!ia0vp^i-1^&gAGXDuwcytQY^(zo*^7SP{WbZ0pvG%x;Tbp zG`_uLD0o0Yfc2uXFk{7nh071dsxeJ$VAqQJaA4^V-jVM;8J#CA`UsN*t%}YBHBzI?E$)m N!PC{xWt~$(6963cJCgta literal 0 HcmV?d00001 diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png.mcmeta b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png.mcmeta new file mode 100644 index 0000000..cd2857e --- /dev/null +++ b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/storage_row.png.mcmeta @@ -0,0 +1,9 @@ +{ + "gui": { + "scaling": { + "type": "tile", + "width": 162, + "height": 18 + } + } +} diff --git a/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png b/src/main/resources/resourcepacks/transparent_overlay/assets/firmament/textures/gui/sprites/storageoverlay/upper_background.png new file mode 100644 index 0000000000000000000000000000000000000000..653a99edb56d7a43a73994e0de759622cbc48d6a GIT binary patch literal 795 zcmeAS@N?(olHy`uVBq!ia0vp^8-Vy82OE%_>)BNTq*#ibJVQ8upoSx*gMoqRlBbJf zNX4AD*VazFogm?MG2B|y-N2!Dhu8K^0irwDxV4W=elsIwkHWdRmhCT|3s)Rqje6E! zydbf1pQZlv)3di7$X<8-^_j(Y`vvt4Z*Mzm^G~AAM*d#j_WA#-1ok|#=sRB;n|}ZM z=f|%bD^~ve@mu}Fe<6cRCN = MC.currentOrDefaultRegistries.getOps(NbtOps.INSTANCE) + + fun tryMigrateNbt( + nbtCompound: NbtCompound, + typ: DSL.TypeReference?, + ): NbtElement { + val source = nbtCompound.get("source", ExportedTestConstantMeta.CODEC) + nbtCompound.remove("source") + if (source.isPresent) { + val wrappedNbtSource = if (typ == TypeReferences.TEXT_COMPONENT && source.get().dataVersion < 4325) { + // Per 1.21.5 text components are wrapped in a string, which firmament unwrapped in the snbt files + NbtString.of( + NbtOps.INSTANCE.convertTo(JsonOps.INSTANCE, nbtCompound) + .toString() + ) + } else { + nbtCompound + } + if (typ != null) { + return Schemas.getFixer() + .update( + typ, + Dynamic(NbtOps.INSTANCE, wrappedNbtSource), + source.get().dataVersion, + SharedConstants.getGameVersion().saveVersion.id + ).value + } else { + wrappedNbtSource + } + } + return nbtCompound + } + + fun loadTablist(name: String): MCTabListAPI.CurrentTabList { + return MCTabListAPI.CurrentTabList.CODEC.parse( + getNbtOps(), + tryMigrateNbt(loadSNbt("testdata/tablist/$name.snbt"), null), + ).getOrThrow { IllegalStateException("Could not load tablist '$name': $it") } + } + + fun loadText(name: String): Text { + return TextCodecs.CODEC.parse( + getNbtOps(), + tryMigrateNbt(loadSNbt("testdata/chat/$name.snbt"), TypeReferences.TEXT_COMPONENT) + ).getOrThrow { IllegalStateException("Could not load test chat '$name': $it") } + } + + fun loadItem(name: String): ItemStack { + try { + val itemNbt = loadSNbt("testdata/items/$name.snbt") + return ItemStack.CODEC.parse(getNbtOps(), tryMigrateNbt(itemNbt, TypeReferences.ITEM_STACK)).orThrow + } catch (ex: Exception) { + throw RuntimeException("Could not load item resource '$name'", ex) + } + } +} diff --git a/src/test/kotlin/util/ColorCodeTest.kt b/src/test/kotlin/util/ColorCodeTest.kt new file mode 100644 index 0000000..7c581c5 --- /dev/null +++ b/src/test/kotlin/util/ColorCodeTest.kt @@ -0,0 +1,57 @@ +package moe.nea.firmament.test.util + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import moe.nea.firmament.util.removeColorCodes + + +class ColorCodeTest { + @Test + fun testWhatever() { + Assertions.assertEquals("", "".removeColorCodes()) + Assertions.assertEquals("", "§".removeColorCodes()) + Assertions.assertEquals("", "§a".removeColorCodes()) + Assertions.assertEquals("ab", "a§ab".removeColorCodes()) + Assertions.assertEquals("ab", "a§ab§§".removeColorCodes()) + Assertions.assertEquals("abc", "a§ab§§c".removeColorCodes()) + Assertions.assertEquals("bc", "§ab§§c".removeColorCodes()) + Assertions.assertEquals("b§lc", "§ab§l§§c".removeColorCodes(true)) + Assertions.assertEquals("b§lc§l", "§ab§l§§c§l".removeColorCodes(true)) + Assertions.assertEquals("§lb§lc", "§l§ab§l§§c".removeColorCodes(true)) + } + + @Test + fun testEdging() { + Assertions.assertEquals("", "§".removeColorCodes()) + Assertions.assertEquals("a", "a§".removeColorCodes()) + Assertions.assertEquals("b", "§ab§".removeColorCodes()) + } + + @Test + fun `testDouble§`() { + Assertions.assertEquals("1", "§§1".removeColorCodes()) + } + + @Test + fun testKeepNonColor() { + Assertions.assertEquals("§k§l§m§n§o§r", "§k§l§m§f§n§o§r".removeColorCodes(true)) + } + + @Test + fun testPlainString() { + Assertions.assertEquals("bcdefgp", "bcdefgp".removeColorCodes()) + Assertions.assertEquals("", "".removeColorCodes()) + } + + @Test + fun testSomeNormalTestCases() { + Assertions.assertEquals( + "You are not currently in a party.", + "§r§cYou are not currently in a party.§r".removeColorCodes() + ) + Assertions.assertEquals( + "Ancient Necron's Chestplate ✪✪✪✪", + "§dAncient Necron's Chestplate §6✪§6✪§6✪§6✪".removeColorCodes() + ) + } +} diff --git a/src/test/kotlin/util/TextUtilText.kt b/src/test/kotlin/util/TextUtilText.kt new file mode 100644 index 0000000..94ab222 --- /dev/null +++ b/src/test/kotlin/util/TextUtilText.kt @@ -0,0 +1,18 @@ +package moe.nea.firmament.test.util + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.getLegacyFormatString + +class TextUtilText { + @Test + fun testThing() { + // TODO: add more tests that are directly validated with 1.8.9 code + val text = ItemResources.loadText("all-chat") + Assertions.assertEquals( + "§r§r§8[§r§9302§r§8] §r§6♫ §r§b[MVP§r§d+§r§b] lrg89§r§f: test§r", + text.getLegacyFormatString() + ) + } +} diff --git a/src/test/kotlin/util/math/GChainReconciliationTest.kt b/src/test/kotlin/util/math/GChainReconciliationTest.kt new file mode 100644 index 0000000..380ea5c --- /dev/null +++ b/src/test/kotlin/util/math/GChainReconciliationTest.kt @@ -0,0 +1,75 @@ +package moe.nea.firmament.test.util.math + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.Test +import moe.nea.firmament.util.math.GChainReconciliation +import moe.nea.firmament.util.math.GChainReconciliation.rotated + +class GChainReconciliationTest { + + fun assertEqualCycles( + expected: List, + actual: List + ) { + for (offset in expected.indices) { + val rotated = expected.rotated(offset) + val matchesAtRotation = run { + for ((i, v) in actual.withIndex()) { + if (rotated[i % rotated.size] != v) + return@run false + } + true + } + if (matchesAtRotation) + return + } + assertEquals(expected, actual, "Expected arrays to be cycle equivalent") + } + + @Test + fun testUnfixableCycleNotBeingModified() { + assertEquals( + listOf(1, 2, 3, 4, 6, 1, 2, 3, 4, 6), + GChainReconciliation.reconcileCycles( + listOf(1, 2, 3, 4, 6, 1, 2, 3, 4, 6), + listOf(2, 3, 4, 5, 1, 2, 3, 4, 5, 1) + ) + ) + } + + @Test + fun testMultipleIndependentHoles() { + assertEqualCycles( + listOf(1, 2, 3, 4, 5, 6), + GChainReconciliation.reconcileCycles( + listOf(1, 3, 4, 5, 6, 1, 3, 4, 5, 6), + listOf(2, 3, 4, 5, 1, 2, 3, 4, 5, 1) + ) + ) + + } + + @Test + fun testBigHole() { + assertEqualCycles( + listOf(1, 2, 3, 4, 5, 6), + GChainReconciliation.reconcileCycles( + listOf(1, 4, 5, 6, 1, 4, 5, 6), + listOf(2, 3, 4, 5, 1, 2, 3, 4, 5, 1) + ) + ) + + } + + @Test + fun testOneMissingBeingDetected() { + assertEqualCycles( + listOf(1, 2, 3, 4, 5, 6), + GChainReconciliation.reconcileCycles( + listOf(1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6), + listOf(2, 3, 4, 5, 1, 2, 3, 4, 5, 1) + ) + ) + } +} diff --git a/src/test/kotlin/util/math/ProjectionsBoxTest.kt b/src/test/kotlin/util/math/ProjectionsBoxTest.kt new file mode 100644 index 0000000..04720a3 --- /dev/null +++ b/src/test/kotlin/util/math/ProjectionsBoxTest.kt @@ -0,0 +1,28 @@ +package moe.nea.firmament.test.util.math + +import java.util.stream.Stream +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.DynamicTest +import org.junit.jupiter.api.TestFactory +import kotlin.streams.asStream +import net.minecraft.util.math.Vec2f +import moe.nea.firmament.util.math.Projections + +class ProjectionsBoxTest { + val Double.degrees get() = Math.toRadians(this) + + @TestFactory + fun testProjections(): Stream { + return sequenceOf( + 0.0.degrees to Vec2f(1F, 0F), + 63.4349.degrees to Vec2f(0.5F, 1F), + ).map { (angle, expected) -> + DynamicTest.dynamicTest("ProjectionsBoxTest::projectAngleOntoUnitBox(${angle})") { + val actual = Projections.Two.projectAngleOntoUnitBox(angle) + fun msg() = "Expected (${expected.x}, ${expected.y}) got (${actual.x}, ${actual.y})" + Assertions.assertEquals(expected.x, actual.x, 0.0001F, ::msg) + Assertions.assertEquals(expected.y, actual.y, 0.0001F, ::msg) + } + }.asStream() + } +} diff --git a/src/test/kotlin/util/skyblock/AbilityUtilsTest.kt b/src/test/kotlin/util/skyblock/AbilityUtilsTest.kt new file mode 100644 index 0000000..9d25aad --- /dev/null +++ b/src/test/kotlin/util/skyblock/AbilityUtilsTest.kt @@ -0,0 +1,87 @@ +package moe.nea.firmament.test.util.skyblock + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds +import net.minecraft.text.Text +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.skyblock.AbilityUtils +import moe.nea.firmament.util.unformattedString + +class AbilityUtilsTest { + + fun List.stripDescriptions() = map { + it.copy(descriptionLines = it.descriptionLines.map { Text.literal(it.unformattedString) }) + } + + @Test + fun testUnpoweredDrill() { + Assertions.assertEquals( + listOf( + AbilityUtils.ItemAbility( + "Pickobulus", + false, + AbilityUtils.AbilityActivation.RIGHT_CLICK, + null, + listOf( + "Throw your pickaxe to create an", + "explosion mining all ores in a 3 block", + "radius." + ).map(Text::literal), + 48.seconds + ) + ), + AbilityUtils.getAbilities(ItemResources.loadItem("titanium-drill")).stripDescriptions() + ) + } + + @Test + fun testPoweredPickaxe() { + Assertions.assertEquals( + listOf( + AbilityUtils.ItemAbility( + "Mining Speed Boost", + true, + AbilityUtils.AbilityActivation.RIGHT_CLICK, + null, + listOf( + "Grants +200% ⸕ Mining Speed for", + "10s." + ).map(Text::literal), + 2.minutes + ) + ), + AbilityUtils.getAbilities(ItemResources.loadItem("diamond-pickaxe")).stripDescriptions() + ) + } + + @Test + fun testAOTV() { + Assertions.assertEquals( + listOf( + AbilityUtils.ItemAbility( + "Instant Transmission", true, AbilityUtils.AbilityActivation.RIGHT_CLICK, 23, + listOf( + "Teleport 12 blocks ahead of you and", + "gain +50 ✦ Speed for 3 seconds." + ).map(Text::literal), + null + ), + AbilityUtils.ItemAbility( + "Ether Transmission", + false, + AbilityUtils.AbilityActivation.SNEAK_RIGHT_CLICK, + 90, + listOf( + "Teleport to your targeted block up", + "to 61 blocks away.", + "Soulflow Cost: 1" + ).map(Text::literal), + null + ) + ), + AbilityUtils.getAbilities(ItemResources.loadItem("aspect-of-the-void")).stripDescriptions() + ) + } +} diff --git a/src/test/kotlin/util/skyblock/ItemTypeTest.kt b/src/test/kotlin/util/skyblock/ItemTypeTest.kt new file mode 100644 index 0000000..c0ef2a3 --- /dev/null +++ b/src/test/kotlin/util/skyblock/ItemTypeTest.kt @@ -0,0 +1,28 @@ +package moe.nea.firmament.test.util.skyblock + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.DynamicTest +import org.junit.jupiter.api.TestFactory +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.skyblock.ItemType + +class ItemTypeTest { + @TestFactory + fun fromItemstack() = + listOf( + "pets/lion-item" to ItemType.PET, + "pets/rabbit-selected" to ItemType.PET, + "pets/mithril-golem-not-selected" to ItemType.PET, + "aspect-of-the-void" to ItemType.SWORD, + "titanium-drill" to ItemType.DRILL, + "diamond-pickaxe" to ItemType.PICKAXE, + "gemstone-gauntlet" to ItemType.GAUNTLET, + ).map { (name, typ) -> + DynamicTest.dynamicTest("return $typ for $name") { + Assertions.assertEquals( + typ, + ItemType.fromItemStack(ItemResources.loadItem(name)) + ) + } + } +} diff --git a/src/test/kotlin/util/skyblock/SackUtilTest.kt b/src/test/kotlin/util/skyblock/SackUtilTest.kt new file mode 100644 index 0000000..e0e3e63 --- /dev/null +++ b/src/test/kotlin/util/skyblock/SackUtilTest.kt @@ -0,0 +1,29 @@ +package moe.nea.firmament.test.util.skyblock + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.skyblock.SackUtil +import moe.nea.firmament.util.skyblock.SkyBlockItems + +class SackUtilTest { + @Test + fun testOneRottenFlesh() { + Assertions.assertEquals( + listOf( + SackUtil.SackUpdate(SkyBlockItems.ROTTEN_FLESH, "Rotten Flesh", 1) + ), + SackUtil.getUpdatesFromMessage(ItemResources.loadText("sacks/gain-rotten-flesh")) + ) + } + + @Test + fun testAFewRegularItems() { + Assertions.assertEquals( + listOf( + SackUtil.SackUpdate(SkyBlockItems.ROTTEN_FLESH, "Rotten Flesh", 1) + ), + SackUtil.getUpdatesFromMessage(ItemResources.loadText("sacks/gain-and-lose-regular")) + ) + } +} diff --git a/src/test/kotlin/util/skyblock/TabListAPITest.kt b/src/test/kotlin/util/skyblock/TabListAPITest.kt new file mode 100644 index 0000000..26eafe0 --- /dev/null +++ b/src/test/kotlin/util/skyblock/TabListAPITest.kt @@ -0,0 +1,48 @@ +package moe.nea.firmament.test.util.skyblock + +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.skyblock.TabListAPI + +class TabListAPITest { + val tablist = ItemResources.loadTablist("dungeon_hub") + + @Test + fun checkWithTitle() { + Assertions.assertEquals( + listOf( + "Profile: Strawberry", + " SB Level: [210] 26/100 XP", + " Bank: 1.4B", + " Interest: 12 Hours (689.1k)", + ), + TabListAPI.getWidgetLines(TabListAPI.WidgetName.PROFILE, includeTitle = true, from = tablist).map { it.string }) + } + + @Test + fun checkEndOfColumn() { + Assertions.assertEquals( + listOf( + " Bonzo IV: 110/150", + " Scarf II: 25/50", + " The Professor IV: 141/150", + " Thorn I: 29/50", + " Livid II: 91/100", + " Sadan V: 388/500", + " Necron VI: 531/750", + ), + TabListAPI.getWidgetLines(TabListAPI.WidgetName.COLLECTION, from = tablist).map { it.string } + ) + } + + @Test + fun checkWithoutTitle() { + Assertions.assertEquals( + listOf( + " Undead: 1,907", + " Wither: 318", + ), + TabListAPI.getWidgetLines(TabListAPI.WidgetName.ESSENCE, from = tablist).map { it.string }) + } +} diff --git a/src/test/kotlin/util/skyblock/TimestampTest.kt b/src/test/kotlin/util/skyblock/TimestampTest.kt new file mode 100644 index 0000000..b960cb9 --- /dev/null +++ b/src/test/kotlin/util/skyblock/TimestampTest.kt @@ -0,0 +1,28 @@ +package moe.nea.firmament.test.util.skyblock + +import java.time.Instant +import java.time.ZonedDateTime +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import moe.nea.firmament.test.testutil.ItemResources +import moe.nea.firmament.util.SBData +import moe.nea.firmament.util.timestamp + +class TimestampTest { + + @Test + fun testLongTimestamp() { + Assertions.assertEquals( + Instant.ofEpochSecond(1658091600), + ItemResources.loadItem("hyperion").timestamp + ) + } + + @Test + fun testStringTimestamp() { + Assertions.assertEquals( + ZonedDateTime.of(2021, 10, 11, 15, 39, 0, 0, SBData.hypixelTimeZone).toInstant(), + ItemResources.loadItem("backpack-in-menu").timestamp + ) + } +} diff --git a/src/test/resources/testdata/chat/all-chat.snbt b/src/test/resources/testdata/chat/all-chat.snbt new file mode 100644 index 0000000..386194b --- /dev/null +++ b/src/test/resources/testdata/chat/all-chat.snbt @@ -0,0 +1,165 @@ +{ + source: { + dataVersion: 4189, + }, + extra: [ + { + bold: 0b, + color: "#555555", + hoverEvent: { + action: "show_text", + contents: { + clickEvent: { + action: "run_command", + value: "command" + }, + strikethrough: 0b, + text: "§b[MVP§d+§b] lrg89§f + +§7SkyBlock Level: §8[§9302§8] +§7Skill Average: §648.1 + +§7Emblem: §6♫ +§8Harp Master + +§7§8Unlocked for All Harp Songs Perfected. + +§7Perfect Completions: §b37" + } + }, + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "[", + underlined: 0b + }, + { + bold: 0b, + color: "#5555FF", + hoverEvent: { + action: "show_text", + contents: { + clickEvent: { + action: "run_command", + value: "command" + }, + strikethrough: 0b, + text: "§b[MVP§d+§b] lrg89§f + +§7SkyBlock Level: §8[§9302§8] +§7Skill Average: §648.1 + +§7Emblem: §6♫ +§8Harp Master + +§7§8Unlocked for All Harp Songs Perfected. + +§7Perfect Completions: §b37" + } + }, + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "302", + underlined: 0b + }, + { + bold: 0b, + color: "#555555", + hoverEvent: { + action: "show_text", + contents: { + clickEvent: { + action: "run_command", + value: "command" + }, + strikethrough: 0b, + text: "§b[MVP§d+§b] lrg89§f + +§7SkyBlock Level: §8[§9302§8] +§7Skill Average: §648.1 + +§7Emblem: §6♫ +§8Harp Master + +§7§8Unlocked for All Harp Songs Perfected. + +§7Perfect Completions: §b37" + } + }, + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "] ", + underlined: 0b + }, + { + bold: 0b, + color: "#FFAA00", + hoverEvent: { + action: "show_text", + contents: { + clickEvent: { + action: "run_command", + value: "command" + }, + strikethrough: 0b, + text: "§b[MVP§d+§b] lrg89§f + +§7SkyBlock Level: §8[§9302§8] +§7Skill Average: §648.1 + +§7Emblem: §6♫ +§8Harp Master + +§7§8Unlocked for All Harp Songs Perfected. + +§7Perfect Completions: §b37" + } + }, + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "♫ ", + underlined: 0b + }, + { + bold: 0b, + color: "#55FFFF", + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "[MVP", + underlined: 0b + }, + { + bold: 0b, + color: "#FF55FF", + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "+", + underlined: 0b + }, + { + bold: 0b, + color: "#55FFFF", + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "] lrg89", + underlined: 0b + }, + { + bold: 0b, + color: "#FFFFFF", + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: ": test", + underlined: 0b + } + ], + strikethrough: 0b, + text: "" +} diff --git a/src/test/resources/testdata/chat/sacks/gain-and-lose-regular.snbt b/src/test/resources/testdata/chat/sacks/gain-and-lose-regular.snbt new file mode 100644 index 0000000..d7b8b90 --- /dev/null +++ b/src/test/resources/testdata/chat/sacks/gain-and-lose-regular.snbt @@ -0,0 +1,104 @@ +{ + source: { + dataVersion: 4189, + }, + color: "#FFAA00", + extra: [ + { + color: "#55FF55", + hoverEvent: { + action: "show_text", + contents: { + color: "#55FF55", + extra: [ + { + color: "#55FF55", + strikethrough: 0b, + text: " +1 " + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "Rotten Flesh" + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Combat Sack)" + }, + { + strikethrough: 0b, + text: " + +" + }, + { + color: "#555555", + strikethrough: 0b, + text: "This message can be disabled in the settings." + } + ], + strikethrough: 0b, + text: "Added items: +" + } + }, + strikethrough: 0b, + text: "+1" + }, + { + color: "#FFFF55", + hoverEvent: { + action: "show_text", + contents: { + color: "#55FF55", + extra: [ + { + color: "#55FF55", + strikethrough: 0b, + text: " +1 " + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "Rotten Flesh" + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Combat Sack)" + }, + { + strikethrough: 0b, + text: " + +" + }, + { + color: "#555555", + strikethrough: 0b, + text: "This message can be disabled in the settings." + } + ], + strikethrough: 0b, + text: "Added items: +" + } + }, + strikethrough: 0b, + text: " item" + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "." + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Last 5s.)" + } + ], + strikethrough: 0b, + text: "[Sacks] " +} diff --git a/src/test/resources/testdata/chat/sacks/gain-rotten-flesh.snbt b/src/test/resources/testdata/chat/sacks/gain-rotten-flesh.snbt new file mode 100644 index 0000000..d7b8b90 --- /dev/null +++ b/src/test/resources/testdata/chat/sacks/gain-rotten-flesh.snbt @@ -0,0 +1,104 @@ +{ + source: { + dataVersion: 4189, + }, + color: "#FFAA00", + extra: [ + { + color: "#55FF55", + hoverEvent: { + action: "show_text", + contents: { + color: "#55FF55", + extra: [ + { + color: "#55FF55", + strikethrough: 0b, + text: " +1 " + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "Rotten Flesh" + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Combat Sack)" + }, + { + strikethrough: 0b, + text: " + +" + }, + { + color: "#555555", + strikethrough: 0b, + text: "This message can be disabled in the settings." + } + ], + strikethrough: 0b, + text: "Added items: +" + } + }, + strikethrough: 0b, + text: "+1" + }, + { + color: "#FFFF55", + hoverEvent: { + action: "show_text", + contents: { + color: "#55FF55", + extra: [ + { + color: "#55FF55", + strikethrough: 0b, + text: " +1 " + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "Rotten Flesh" + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Combat Sack)" + }, + { + strikethrough: 0b, + text: " + +" + }, + { + color: "#555555", + strikethrough: 0b, + text: "This message can be disabled in the settings." + } + ], + strikethrough: 0b, + text: "Added items: +" + } + }, + strikethrough: 0b, + text: " item" + }, + { + color: "#FFFF55", + strikethrough: 0b, + text: "." + }, + { + color: "#555555", + strikethrough: 0b, + text: " (Last 5s.)" + } + ], + strikethrough: 0b, + text: "[Sacks] " +} diff --git a/src/test/resources/testdata/items/aspect-of-the-void.snbt b/src/test/resources/testdata/items/aspect-of-the-void.snbt new file mode 100644 index 0000000..9ffd385 --- /dev/null +++ b/src/test/resources/testdata/items/aspect-of-the-void.snbt @@ -0,0 +1,62 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + donated_museum: 1b, + enchantments: { + ultimate_wise: 5 + }, + ethermerge: 1b, + gems: { + }, + id: "ASPECT_OF_THE_VOID", + modifier: "heroic", + originTag: "ASPECT_OF_THE_VOID", + power_ability_scroll: "SAPPHIRE_POWER_SCROLL", + timestamp: 1641640380000L, + tuned_transmission: 4, + uuid: "b0572534-eb14-46cd-90c6-0df878fd56a2" + }, + "minecraft:custom_name": '{"extra":[{"color":"dark_purple","text":"Heroic Aspect of the Void"}],"italic":false,"text":""}', + "minecraft:enchantment_glint_override": 1b, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"gray","text":"Damage: "},{"color":"red","text":"+120"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Strength: "},{"color":"red","text":"+132 "},{"color":"blue","text":"(+32)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Bonus Attack Speed: "},{"color":"red","text":"+3% "},{"color":"blue","text":"(+3%)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Intelligence: "},{"color":"green","text":"+80 "},{"color":"blue","text":"(+80)"}],"italic":false,"text":""}', + '{"extra":[" ",{"color":"dark_gray","text":"["},{"color":"gray","text":"✎"},{"color":"dark_gray","text":"]"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":""},{"bold":true,"color":"light_purple","text":"Ultimate Wise V"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Reduces the ability mana cost of this"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"item by "},{"color":"green","text":"50%"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"aqua","text":"⦾ "},{"color":"gold","text":"Ability: Instant Transmission "},{"bold":true,"color":"yellow","text":"RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Teleport "},{"color":"green","text":"12 blocks"},{"color":"gray","text":" ahead of you and"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"gain "},{"color":"green","text":"+50 "},{"color":"white","text":"✦ Speed"},{"color":"gray","text":" for "},{"color":"green","text":"3 seconds"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Mana Cost: "},{"color":"dark_aqua","text":"23"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Ether Transmission "},{"bold":true,"color":"yellow","text":"SNEAK RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Teleport to your targeted block up"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"to "},{"color":"green","text":"61 blocks "},{"color":"gray","text":"away."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"Soulflow Cost: "},{"color":"dark_aqua","text":"1"}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Mana Cost: "},{"color":"dark_aqua","text":"90"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_gray","text":"* "},{"color":"dark_gray","text":"Co-op Soulbound "},{"bold":true,"color":"dark_gray","text":"*"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_purple","text":"EPIC SWORD"}],"italic":false,"text":""}' + ], + "minecraft:unbreakable": { + show_in_tooltip: 0b + } + }, + count: 1, + id: "minecraft:diamond_shovel" +} diff --git a/src/test/resources/testdata/items/backpack-in-menu.snbt b/src/test/resources/testdata/items/backpack-in-menu.snbt new file mode 100644 index 0000000..2f22768 --- /dev/null +++ b/src/test/resources/testdata/items/backpack-in-menu.snbt @@ -0,0 +1,122 @@ +{ + components: { + "minecraft:custom_data": { + backpack_color: "BROWN", + originTag: "CRAFTING_GRID_COLLECT", + timestamp: "10/11/21 3:39 PM", + uuid: "3d7c83e8-c619-4603-8cfb-c95ceed90864" + }, + "minecraft:custom_name": { + extra: [ + { + color: "gold", + text: "Backpack Slot 3" + } + ], + italic: 0b, + text: "" + }, + "minecraft:lore": [ + { + extra: [ + { + color: "gold", + text: "Jumbo Backpack" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "gray", + text: "" + }, + { + color: "gray", + text: "This backpack has " + }, + { + color: "green", + text: "45" + }, + { + color: "gray", + text: " slots." + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " " + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "gray", + text: "" + }, + { + color: "yellow", + text: "Left-click to open!" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "gray", + text: "" + }, + { + color: "yellow", + text: "Right-click to remove!" + } + ], + italic: 0b, + text: "" + } + ], + "minecraft:profile": { + id: [I; + 1252359403, + 1319582828, + -1927151386, + 833492163 + ], + properties: [ + { + name: "textures", + signature: "U/49v6SXIw8bAmqM6T7t1BIR736N3Adpx7MlWncnT8zcFEm97zwRx9/tyaUy/XxBHaPGSL6BbgW2TdBtfb9gf0emCAZyWmnzSTtqDGiWpxnQM8v3+gHS8zD7Xrho0a/hU33xTbQ2knj2iRz8C+FReoJFxCjS++aXq6IqliIb3GhqB5b1egaiG2Q3t+yerl2Xue4nhdYM3wtGsYApC/ClR3TEuBcJv1WUVZM8rEoU29pbVnyMCKineG6mIN7W86SmzcT2SF+zMVyD0/mI7R2hRT2lbXnkMpM6FFscdnlvzjjPB9brtAWY7JGJ63b9C+khnvZUlhlQ/3E/08dFnON31VeabJXOmfrbfAgsF0Hgfs7Io+HzoXSXr/FCxNCCFMWlSwORmG2WCT4VRFzG2SThatPVPGJkuR/tLLOLzXo4RKOMzY5EIwa2XSxRUI4+5z2SZY11ofGic3bZD3wvICs2EZ54Pi508ZOda0qI9w5Q/TazC+jX/I5Nq2TLqLj+uU/+UX8eKXvHdk8QpBynyv9SyHo21jVXpiUgL1AsdzBp9cTZHNJuYtBxgDogr3SyAKPmw3BOzVeUi6qW8k4lgtefLKYteVSh52PjFgvQZUR1GNmFaJ+hlgKz8yONp+wXhw3nyL4dMOd2Z/dVVSywBp0tyHuN5l3PfaInK4s8qSydaW0=", + value: "ewogICJ0aW1lc3RhbXAiIDogMTcxOTUzODgxNTgyNCwKICAicHJvZmlsZUlkIiA6ICJkOWYxNTlhYWYxZjY0NGZlOTEwOTg0NzI2ZDBjMWJjMCIsCiAgInByb2ZpbGVOYW1lIiA6ICJtYW5vbmFtaXNzaW9uRyIsCiAgInNpZ25hdHVyZVJlcXVpcmVkIiA6IHRydWUsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS81YWQwYjQwNTIxMjYyYjdhM2Y5OWU2M2JkZGQ0YTNlNTQxOTY1Njc3ZTE0MTRlYWZhMTQyZThiYmE5ZGZlNDgxIiwKICAgICAgIm1ldGFkYXRhIiA6IHsKICAgICAgICAibW9kZWwiIDogInNsaW0iCiAgICAgIH0KICAgIH0KICB9Cn0=" + } + ] + }, + "minecraft:tooltip_display": { + hidden_components: [ + "minecraft:jukebox_playable", + "minecraft:painting/variant", + "minecraft:map_id", + "minecraft:fireworks", + "minecraft:attribute_modifiers", + "minecraft:unbreakable", + "minecraft:written_book_content", + "minecraft:banner_patterns", + "minecraft:trim", + "minecraft:potion_contents", + "minecraft:block_entity_data", + "minecraft:dyed_color" + ] + } + }, + count: 3, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/books/feather_falling.snbt b/src/test/resources/testdata/items/books/feather_falling.snbt new file mode 100644 index 0000000..4a0b7c6 --- /dev/null +++ b/src/test/resources/testdata/items/books/feather_falling.snbt @@ -0,0 +1,39 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + enchantments: { + feather_falling: 6 + }, + id: "ENCHANTED_BOOK", + timestamp: 1737123521091L, + uuid: "b8128489-9ed0-4a1a-94c0-d3279ffe45ac" + }, + "minecraft:custom_name": '{"extra":[{"color":"blue","text":"Enchanted Book"}],"italic":false,"text":""}', + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"blue","text":"Feather Falling VI"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Increases how high you can fall"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"before taking fall damage by "},{"color":"green","text":"6"},{"color":"gray","text":" and"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"reduces fall damage by "},{"color":"green","text":"30%"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Applicable on: "},{"color":"blue","text":"Boots"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Apply Cost: "},{"color":"dark_aqua","text":"60 Exp Levels"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Use this on an item in an Anvil to"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"apply it!"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"blue","text":"RARE"}],"italic":false,"text":""}' + ] + }, + count: 1, + id: "minecraft:enchanted_book" +} diff --git a/src/test/resources/testdata/items/diamond-pickaxe.snbt b/src/test/resources/testdata/items/diamond-pickaxe.snbt new file mode 100644 index 0000000..aa5e590 --- /dev/null +++ b/src/test/resources/testdata/items/diamond-pickaxe.snbt @@ -0,0 +1,51 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + enchantments: { + efficiency: 10 + }, + id: "DIAMOND_PICKAXE", + power_ability_scroll: "SAPPHIRE_POWER_SCROLL", + timestamp: 1659795180000L, + uuid: "d213f48e-d927-4748-a58c-eb80735025b7" + }, + "minecraft:custom_name": '{"extra":[{"color":"green","text":"Diamond Pickaxe"}],"italic":false,"text":""}', + "minecraft:enchantments": { + levels: { + } + }, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Breaking Power 4"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Damage: "},{"color":"red","text":"+30"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Speed: "},{"color":"green","text":"+220"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Efficiency X"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Increases how quickly your tool"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"breaks blocks."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"aqua","text":"⦾ "},{"color":"gold","text":"Ability: Mining Speed Boost "},{"bold":true,"color":"yellow","text":"RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"gold","text":"+200% "},{"color":"gold","text":"⸕ Mining Speed "},{"color":"gray","text":"for"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"green","text":"10s"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Cooldown: "},{"color":"green","text":"120s"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"This item can be reforged!"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"green","text":"UNCOMMON PICKAXE"}],"italic":false,"text":""}' + ], + "minecraft:unbreakable": { + show_in_tooltip: 0b + } + }, + count: 1, + id: "minecraft:diamond_pickaxe" +} diff --git a/src/test/resources/testdata/items/gemstone-gauntlet.snbt b/src/test/resources/testdata/items/gemstone-gauntlet.snbt new file mode 100644 index 0000000..92bb806 --- /dev/null +++ b/src/test/resources/testdata/items/gemstone-gauntlet.snbt @@ -0,0 +1,106 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + compact_blocks: 287507, + donated_museum: 1b, + enchantments: { + compact: 8, + critical: 5, + efficiency: 5, + experience: 3, + first_strike: 4, + fortune: 4, + giant_killer: 5, + pristine: 3, + scavenger: 3, + sharpness: 5, + telekinesis: 1 + }, + gems: { + AMBER_0: "FINE", + AMETHYST_0: "FINE", + JADE_0: "FINE", + SAPPHIRE_0: "FINE", + TOPAZ_0: "FINE" + }, + id: "GEMSTONE_GAUNTLET", + modifier: "auspicious", + originTag: "QUICK_CRAFTING", + timestamp: 1642718160000L, + uuid: "af56dd7b-c4b1-4e26-8d09-1854680a93c3" + }, + "minecraft:custom_name": '{"extra":[{"color":"gold","text":"Auspicious Gemstone Gauntlet"}],"italic":false,"text":""}', + "minecraft:enchantments": { + levels: { + "minecraft:efficiency": 5 + } + }, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Breaking Power 8"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Damage: "},{"color":"red","text":"+300"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Strength: "},{"color":"red","text":"+50"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Crit Damage: "},{"color":"red","text":"+50%"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Defense: "},{"color":"green","text":"+10 "},{"color":"light_purple","text":"(+10)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Intelligence: "},{"color":"green","text":"+11 "},{"color":"light_purple","text":"(+11)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Speed: "},{"color":"green","text":"+886 "},{"color":"blue","text":"(+50) "},{"color":"light_purple","text":"(+36)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Pristine: "},{"color":"green","text":"+2.7 "},{"color":"light_purple","text":"(+1.2)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Fortune: "},{"color":"green","text":"+81 "},{"color":"blue","text":"(+16) "},{"color":"light_purple","text":"(+20)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Wisdom: "},{"color":"green","text":"+8"}],"italic":false,"text":""}', + '{"extra":[" ",{"color":"blue","text":"["},{"color":"green","text":"☘"},{"color":"blue","text":"] "},{"color":"blue","text":"["},{"color":"gold","text":"⸕"},{"color":"blue","text":"] "},{"color":"blue","text":"["},{"color":"yellow","text":"✧"},{"color":"blue","text":"] "},{"color":"blue","text":"["},{"color":"aqua","text":"✎"},{"color":"blue","text":"] "},{"color":"blue","text":"["},{"color":"dark_purple","text":"âˆ"},{"color":"blue","text":"]"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Compact VIII"},{"color":"blue","text":", "},{"color":"blue","text":"Critical V"},{"color":"blue","text":", "},{"color":"blue","text":"Efficiency V"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Experience III"},{"color":"blue","text":", "},{"color":"blue","text":"First Strike IV"},{"color":"blue","text":", "},{"color":"blue","text":"Fortune IV"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Giant Killer V"},{"color":"blue","text":", "},{"color":"blue","text":"Prismatic III"},{"color":"blue","text":", "},{"color":"blue","text":"Scavenger III"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Sharpness V"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gold","text":"Ability: Reduced To Atoms"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mobs killed on "},{"color":"aqua","text":"Mining Islands "},{"color":"gray","text":"drop the same"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"light_purple","text":"Gemstones "},{"color":"gray","text":"as your filled Gemstone Slots."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"(2s cooldown)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gold","text":"Ability: Kinetic"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Killing mobs on "},{"color":"aqua","text":"Mining Islands "},{"color":"gray","text":"reduces your"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gold","text":"Forge Timers "},{"color":"gray","text":"by "},{"color":"green","text":"0s"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"(+0.5s per Perfect Gemstone)"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Mining Speed Boost "},{"bold":true,"color":"yellow","text":"RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"gold","text":"+200% "},{"color":"gold","text":"⸕ Mining Speed "},{"color":"gray","text":"for"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"green","text":"10s"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Cooldown: "},{"color":"green","text":"120s"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Auspicious Bonus"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"gold","text":"+0.8% "},{"color":"gold","text":"☘ Mining Fortune"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_gray","text":"* "},{"color":"dark_gray","text":"Co-op Soulbound "},{"bold":true,"color":"dark_gray","text":"*"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"gold","text":"LEGENDARY GAUNTLET"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + -861744046, + -959235637, + -1231724855, + 724395817 + ], + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTYxODUyMTY2MzY1NCwKICAicHJvZmlsZUlkIiA6ICIxZDUyMzNkMzg4NjI0YmFmYjAwZTMxNTBhN2FhM2E4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICIwMDAwMDAwMDAwMDAwMDBKIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdiZjAxYzE5OGY2ZTE2OTY1ZTIzMDIzNWNkMjJhNWE5ZjRhNDBlNDA5NDEyMzQ0Nzg5NDhmZjlhNTZlNTE3NzUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ==" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/hyperion.snbt b/src/test/resources/testdata/items/hyperion.snbt new file mode 100644 index 0000000..f0025b9 --- /dev/null +++ b/src/test/resources/testdata/items/hyperion.snbt @@ -0,0 +1,99 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + ability_scroll: [ + "IMPLOSION_SCROLL", + "WITHER_SHIELD_SCROLL", + "SHADOW_WARP_SCROLL" + ], + art_of_war_count: 1, + champion_combat_xp: 1.3556020889209766E7d, + donated_museum: 1b, + enchantments: { + champion: 10, + cleave: 5, + critical: 6, + cubism: 5, + ender_slayer: 6, + execute: 5, + experience: 3, + fire_aspect: 2, + first_strike: 4, + giant_killer: 6, + impaling: 3, + lethality: 5, + looting: 4, + luck: 6, + scavenger: 4, + smite: 7, + syphon: 4, + thunderlord: 6, + ultimate_wise: 5, + vampirism: 5, + venomous: 5 + }, + hot_potato_count: 15, + id: "HYPERION", + modifier: "heroic", + rarity_upgrades: 1, + stats_book: 65934, + timestamp: 1658091600000L, + upgrade_level: 5, + uuid: "a45337aa-9eaa-4e6f-aa27-26a42f8eca95" + }, + "minecraft:custom_name": '{"extra":[{"color":"light_purple","text":"Heroic Hyperion "},{"color":"gold","text":"✪✪✪✪✪"}],"italic":false,"text":""}', + "minecraft:enchantment_glint_override": 1b, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"gray","text":"Gear Score: "},{"color":"light_purple","text":"1145 "},{"color":"dark_gray","text":"(4271)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Damage: "},{"color":"red","text":"+355 "},{"color":"yellow","text":"(+30) "},{"color":"dark_gray","text":"(+1,490.37)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Strength: "},{"color":"red","text":"+250 "},{"color":"yellow","text":"(+30) "},{"color":"gold","text":"[+5] "},{"color":"blue","text":"(+50) "},{"color":"dark_gray","text":"(+1,064.55)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Crit Damage: "},{"color":"red","text":"+70% "},{"color":"dark_gray","text":"(+317.1%)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Bonus Attack Speed: "},{"color":"red","text":"+7% "},{"color":"blue","text":"(+7%) "},{"color":"dark_gray","text":"(+10.5%)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Intelligence: "},{"color":"green","text":"+588 "},{"color":"blue","text":"(+125) "},{"color":"dark_gray","text":"(+2,505.09)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Ferocity: "},{"color":"green","text":"+33 "},{"color":"dark_gray","text":"(+45)"}],"italic":false,"text":""}', + '{"extra":[" ",{"color":"dark_gray","text":"["},{"color":"dark_gray","text":"✎"},{"color":"dark_gray","text":"] "},{"color":"dark_gray","text":"["},{"color":"dark_gray","text":"âš”"},{"color":"dark_gray","text":"]"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"light_purple","text":""},{"bold":true,"color":"light_purple","text":"Ultimate Wise V"},{"color":"blue","text":", "},{"color":"blue","text":"Champion X"},{"color":"blue","text":", "},{"color":"blue","text":"Cleave V"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Critical VI"},{"color":"blue","text":", "},{"color":"blue","text":"Cubism V"},{"color":"blue","text":", "},{"color":"blue","text":"Ender Slayer VI"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Execute V"},{"color":"blue","text":", "},{"color":"blue","text":"Experience III"},{"color":"blue","text":", "},{"color":"blue","text":"Fire Aspect II"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"First Strike IV"},{"color":"blue","text":", "},{"color":"blue","text":"Giant Killer VI"},{"color":"blue","text":", "},{"color":"blue","text":"Impaling III"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Lethality V"},{"color":"blue","text":", "},{"color":"blue","text":"Looting IV"},{"color":"blue","text":", "},{"color":"blue","text":"Luck VI"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Scavenger IV"},{"color":"blue","text":", "},{"color":"blue","text":"Smite VII"},{"color":"blue","text":", "},{"color":"blue","text":"Syphon IV"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Thunderlord VI"},{"color":"blue","text":", "},{"color":"blue","text":"Vampirism V"},{"color":"blue","text":", "},{"color":"blue","text":"Venomous V"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Deals "},{"color":"red","text":"+50% "},{"color":"gray","text":"damage to Withers."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"red","text":"+1 "},{"color":"red","text":"â Damage "},{"color":"gray","text":"and "},{"color":"green","text":"+2 "},{"color":"aqua","text":"✎"}],"italic":false,"text":""}', + '{"extra":[{"color":"aqua","text":"Intelligence "},{"color":"gray","text":"per "},{"color":"red","text":"Catacombs "},{"color":"gray","text":"level."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"green","text":"Scroll Abilities:"}],"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Wither Impact "},{"bold":true,"color":"yellow","text":"RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Teleport "},{"color":"green","text":"10 blocks"},{"color":"gray","text":" ahead of you."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Then implode dealing "},{"color":"red","text":"21,658 "},{"color":"gray","text":"damage"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"to nearby enemies. Also applies the"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"wither shield scroll ability reducing"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"damage taken and granting an"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"absorption shield for "},{"color":"yellow","text":"5 "},{"color":"gray","text":"seconds."}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Mana Cost: "},{"color":"dark_aqua","text":"150"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"white","text":"Kills: "},{"color":"gold","text":"65,934"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_gray","text":"* "},{"color":"dark_gray","text":"Co-op Soulbound "},{"bold":true,"color":"dark_gray","text":"*"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"},"",{"bold":false,"extra":[" "],"italic":false,"obfuscated":false,"strikethrough":false,"text":"","underlined":false},{"bold":true,"color":"light_purple","text":"MYTHIC DUNGEON SWORD "},{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"}],"italic":false,"text":""}' + ], + "minecraft:unbreakable": { + show_in_tooltip: 0b + } + }, + count: 1, + id: "minecraft:iron_sword" +} diff --git a/src/test/resources/testdata/items/implosion-belt.snbt b/src/test/resources/testdata/items/implosion-belt.snbt new file mode 100644 index 0000000..875047d --- /dev/null +++ b/src/test/resources/testdata/items/implosion-belt.snbt @@ -0,0 +1,108 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + attributes: { + dominance: 1, + experience: 1 + }, + id: "IMPLOSION_BELT", + timestamp: "12/5/22 5:17 PM", + uuid: "5c04f47e-7c6c-4ced-96b1-b8f83187b0a5" + }, + "minecraft:custom_name": '{"extra":[{"color":"dark_purple","text":"Implosion Belt"}],"italic":false,"text":""}', + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"gray","text":"Defense: "},{"color":"green","text":"+70"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"red","text":"Dominance I ✖"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Gain "},{"color":"red","text":"+1.5% "},{"color":"gray","text":"damage when at full health."}],"italic":false,"text":""}', + '{"extra":[{"color":"aqua","text":"Experience I"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Gain "},{"color":"green","text":"+10% "},{"color":"gray","text":"more experience orbs"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"from killing mobs."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Consolidated "}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Increases all explosion damage dealt by "},{"color":"green","text":"25%"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"This item can be reforged!"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_purple","text":"EPIC BELT"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + -896440193, + -59755884, + -1280665573, + -1297214643 + ], + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTY0MzYwMjI5OTA2MSwKICAicHJvZmlsZUlkIiA6ICI0ZTMwZjUwZTdiYWU0M2YzYWZkMmE3NDUyY2ViZTI5YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJfdG9tYXRvel8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFkMmIwMzZkZDY2NGJiOTBjOWQ0NDNjMTk5OGZiNTI2Mzk4YWI0ZGRkZWI3OWI4NDAxYjE2YjlhNGQxMGJhMyIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +}{ + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + attributes: { + dominance: 1, + experience: 1 + }, + id: "IMPLOSION_BELT", + timestamp: "12/5/22 5:17 PM", + uuid: "5c04f47e-7c6c-4ced-96b1-b8f83187b0a5" + }, + "minecraft:custom_name": '{"extra":[{"color":"dark_purple","text":"Implosion Belt"}],"italic":false,"text":""}', + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"gray","text":"Defense: "},{"color":"green","text":"+70"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"red","text":"Dominance I ✖"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Gain "},{"color":"red","text":"+1.5% "},{"color":"gray","text":"damage when at full health."}],"italic":false,"text":""}', + '{"extra":[{"color":"aqua","text":"Experience I"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Gain "},{"color":"green","text":"+10% "},{"color":"gray","text":"more experience orbs"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"from killing mobs."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Consolidated "}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Increases all explosion damage dealt by "},{"color":"green","text":"25%"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"dark_gray","text":"This item can be reforged!"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_purple","text":"EPIC BELT"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + -896440193, + -59755884, + -1280665573, + -1297214643 + ], + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTY0MzYwMjI5OTA2MSwKICAicHJvZmlsZUlkIiA6ICI0ZTMwZjUwZTdiYWU0M2YzYWZkMmE3NDUyY2ViZTI5YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJfdG9tYXRvel8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFkMmIwMzZkZDY2NGJiOTBjOWQ0NDNjMTk5OGZiNTI2Mzk4YWI0ZGRkZWI3OWI4NDAxYjE2YjlhNGQxMGJhMyIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" + } diff --git a/src/test/resources/testdata/items/necron-boots.snbt b/src/test/resources/testdata/items/necron-boots.snbt new file mode 100644 index 0000000..fd740ce --- /dev/null +++ b/src/test/resources/testdata/items/necron-boots.snbt @@ -0,0 +1,71 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + enchantments: { + depth_strider: 3, + feather_falling: 10, + growth: 5, + protection: 5 + }, + id: "POWER_WITHER_BOOTS", + modifier: "ancient", + rarity_upgrades: 1, + timestamp: 1704550620000L, + upgrade_level: 5, + uuid: "8b6c7485-cb59-44d3-ac8f-9e52a611cc64" + }, + "minecraft:custom_name": '{"extra":[{"color":"light_purple","text":"Ancient Necron\'s Boots "},{"color":"gold","text":"✪✪✪✪✪"}],"italic":false,"text":""}', + "minecraft:dyed_color": { + rgb: 15167036, + show_in_tooltip: 0b + }, + "minecraft:enchantments": { + levels: { + "minecraft:depth_strider": 3 + } + }, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"gray","text":"Gear Score: "},{"color":"light_purple","text":"713 "},{"color":"dark_gray","text":"(2753)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Strength: "},{"color":"red","text":"+79 "},{"color":"blue","text":"(+35) "},{"color":"dark_gray","text":"(+333.75)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Crit Chance: "},{"color":"red","text":"+15% "},{"color":"blue","text":"(+15%) "},{"color":"dark_gray","text":"(+23.1%)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Crit Damage: "},{"color":"red","text":"+71% "},{"color":"blue","text":"(+38%) "},{"color":"dark_gray","text":"(+302.6%)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Health: "},{"color":"green","text":"+241.5 "},{"color":"blue","text":"(+7) "},{"color":"dark_gray","text":"(+1,010.15)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Defense: "},{"color":"green","text":"+120.5 "},{"color":"blue","text":"(+7) "},{"color":"dark_gray","text":"(+498.4)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Intelligence: "},{"color":"green","text":"+36 "},{"color":"blue","text":"(+25) "},{"color":"dark_gray","text":"(+155.75)"}],"italic":false,"text":""}', + '{"extra":[" ",{"color":"dark_gray","text":"["},{"color":"dark_gray","text":"â"},{"color":"dark_gray","text":"] "},{"color":"dark_gray","text":"["},{"color":"dark_gray","text":"âš”"},{"color":"dark_gray","text":"]"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Depth Strider III"},{"color":"blue","text":", "},{"color":"blue","text":"Feather Falling X"},{"color":"blue","text":", "},{"color":"blue","text":"Growth V"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Protection V"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Reduces the damage you take from"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"withers by "},{"color":"red","text":"10%"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Full Set Bonus: Witherborn "},{"color":"gray","text":"(3/4)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Spawns a wither minion every "},{"color":"yellow","text":"30"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":""},{"color":"gray","text":"seconds up to a maximum "},{"color":"green","text":"1 "},{"color":"gray","text":"wither."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Your withers will travel to and"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"explode on nearby enemies."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Ancient Bonus"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"green","text":"+1 "},{"color":"blue","text":"☠ Crit Damage "},{"color":"gray","text":"per"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"red","text":"Catacombs "},{"color":"gray","text":"level."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"},"",{"bold":false,"extra":[" "],"italic":false,"obfuscated":false,"strikethrough":false,"text":"","underlined":false},{"bold":true,"color":"light_purple","text":"MYTHIC DUNGEON BOOTS "},{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"}],"italic":false,"text":""}' + ], + "minecraft:unbreakable": { + show_in_tooltip: 0b + } + }, + count: 1, + id: "minecraft:leather_boots" +} diff --git a/src/test/resources/testdata/items/pets/lion-item.snbt b/src/test/resources/testdata/items/pets/lion-item.snbt new file mode 100644 index 0000000..c364032 --- /dev/null +++ b/src/test/resources/testdata/items/pets/lion-item.snbt @@ -0,0 +1,65 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + id: "PET", + petInfo: '{"type":"LION","active":false,"exp":0.0,"tier":"LEGENDARY","hideInfo":false,"candyUsed":0,"uuid":"c7f57149-458e-4fde-a9bc-fcc14932310a","uniqueId":"d668f085-26a6-48fe-b75b-c7b8227b5ac8","hideRightClick":false,"noMove":false}', + timestamp: 1732719293542L, + uuid: "c7f57149-458e-4fde-a9bc-fcc14932310a" + }, + "minecraft:custom_name": '{"extra":[{"color":"gray","text":"[Lvl 1] "},{"color":"gold","text":"Lion"}],"italic":false,"text":""}', + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Foraging Pet"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Speed: "},{"color":"green","text":"+0.25"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Strength: "},{"color":"red","text":"+0.5"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Ferocity: "},{"color":"green","text":"+0.05"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Primal Force"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Adds "},{"color":"red","text":"+0.2 "},{"color":"red","text":"â Damage "},{"color":"gray","text":"and "},{"color":"red","text":"+0.2 "},{"color":"red","text":"â"}],"italic":false,"text":""}', + '{"extra":[{"color":"red","text":"Strength "},{"color":"gray","text":"to your weapons."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"First Pounce"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"First Strike"},{"color":"gray","text":", Triple-Strike"},{"color":"gray","text":", and"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"bold":true,"color":"light_purple","text":"Combo "},{"color":"gray","text":"are "},{"color":"green","text":"1% "},{"color":"gray","text":"more effective."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"King of the Jungle"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Deal "},{"color":"red","text":"+1.5% "},{"color":"red","text":"â Damage "},{"color":"gray","text":"against mobs"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"that have attacked you."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Progress to Level 2: "},{"color":"yellow","text":"0%"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"white","strikethrough":true,"text":" "},"",{"bold":false,"extra":[" "],"italic":false,"obfuscated":false,"strikethrough":false,"text":"","underlined":false},{"color":"yellow","text":"0"},{"color":"gold","text":"/"},{"color":"yellow","text":"660"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"yellow","text":"Right-click to add this pet to your"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"pet menu!"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"gold","text":"LEGENDARY"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + 100496274, + -783272221, + -1215808471, + -1437268588 + ], + properties: [ + { + name: "textures", + signature: "", + value: "eyJ0aW1lc3RhbXAiOjE1MDMzMTY0Njg1ODAsInByb2ZpbGVJZCI6ImUzYjQ0NWM4NDdmNTQ4ZmI4YzhmYTNmMWY3ZWZiYThlIiwicHJvZmlsZU5hbWUiOiJNaW5pRGlnZ2VyVGVzdCIsInNpZ25hdHVyZVJlcXVpcmVkIjp0cnVlLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzhmZjQ3M2JkNTJiNGRiMmMwNmYxYWM4N2ZlMTM2N2JjZTc1NzRmYWMzMzBmZmFjNzk1NjIyOWY4MmVmYmExIn19fQ==" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/pets/mithril-golem-not-selected.snbt b/src/test/resources/testdata/items/pets/mithril-golem-not-selected.snbt new file mode 100644 index 0000000..79f32c9 --- /dev/null +++ b/src/test/resources/testdata/items/pets/mithril-golem-not-selected.snbt @@ -0,0 +1,55 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:custom_data": { + id: "PET", + petInfo: '{"type":"MITHRIL_GOLEM","active":false,"exp":9232689.767527012,"tier":"LEGENDARY","hideInfo":false,"candyUsed":0,"uuid":"2ebbdaff-c9b6-4fe1-8b87-44905eb5867d","uniqueId":"26be73f1-2955-4003-9e6a-72848cea8e08","hideRightClick":false,"noMove":false}', + uuid: "2ebbdaff-c9b6-4fe1-8b87-44905eb5867d" + }, + "minecraft:custom_name": '{"extra":[{"color":"gray","text":"[Lvl 86] "},{"color":"gold","text":"Mithril Golem"}],"italic":false,"text":""}', + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Mining Pet"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"True Defense: "},{"color":"green","text":"+43"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Fortune: "},{"color":"green","text":"+21.5"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Mithril Affinity"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Grants "},{"color":"gold","text":"+172⸕ Mining Speed "},{"color":"gray","text":"when"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"mining "},{"color":"dark_green","text":"Mithril"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Subterranean Battler"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Grants "},{"color":"green","text":"+17.2% "},{"color":"gray","text":"of most combat stats"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"while on "},{"color":"aqua","text":"Mining Islands"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"The Smell Of Powder"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Grants "},{"color":"dark_green","text":"+17.2% á … Mithril Powder "},{"color":"gray","text":"from"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"all sources."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Progress to Level 87: "},{"color":"yellow","text":"89%"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_green","strikethrough":true,"text":" "},{"bold":true,"color":"white","strikethrough":true,"text":" "},"",{"bold":false,"extra":[" "],"italic":false,"obfuscated":false,"strikethrough":false,"text":"","underlined":false},{"color":"yellow","text":"593,259.8"},{"color":"gold","text":"/"},{"color":"yellow","text":"666.7k"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"yellow","text":"Left-click to summon!"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"yellow","text":"Shift Left-click to toggle as favorite!"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"Right-click to convert to an item!"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + 972784821, + 1926443553, + -1284265423, + 1586851459 + ], + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTYxMDY0OTEwODI4NCwKICAicHJvZmlsZUlkIiA6ICI2ZmU4OTUxZDVhY2M0NDc3OWI2ZmYxMmU3YzFlOTQ2MyIsCiAgInByb2ZpbGVOYW1lIiA6ICJlcGhlbXJhIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2MxYjJkZmU4ZWQ1ZGZmYzViMTY4N2JjMWMyNDljMzlkZTJkOGE2YzNkOTAzMDVjOTVmNmQxYTFhMzMwYTBiMSIKICAgIH0KICB9Cn0=" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/pets/rabbit-selected.snbt b/src/test/resources/testdata/items/pets/rabbit-selected.snbt new file mode 100644 index 0000000..d4c7235 --- /dev/null +++ b/src/test/resources/testdata/items/pets/rabbit-selected.snbt @@ -0,0 +1,63 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:custom_data": { + id: "PET", + petInfo: '{"type":"RABBIT","active":true,"exp":3.429132435816353E7,"tier":"MYTHIC","hideInfo":false,"heldItem":"YELLOW_BANDANA","candyUsed":0,"uuid":"30a05aae-2ccd-41c0-a686-5bce0df15e2d","uniqueId":"71a8949b-7444-4ead-9464-999fe549e703","hideRightClick":false,"noMove":false}', + uuid: "30a05aae-2ccd-41c0-a686-5bce0df15e2d" + }, + "minecraft:custom_name": '{"extra":[{"color":"gray","text":"[Lvl 100] "},{"color":"light_purple","text":"Rabbit"}],"italic":false,"text":""}', + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Farming Pet"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Health: "},{"color":"green","text":"+100"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Speed: "},{"color":"green","text":"+20"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Farming Fortune: "},{"color":"green","text":"+30"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Happy Feet"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Jump potions also give "},{"color":"green","text":"+50 "},{"color":"gray","text":"speed"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Farming Wisdom Boost"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":""},{"color":"gray","text":"Grants "},{"color":"dark_aqua","text":"+30☯ Farming Wisdom"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Efficient Farming"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Farming minions work "},{"color":"green","text":"30% "},{"color":"gray","text":"faster"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"while on your island"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Chocolate Injections"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Increases "},{"color":"gold","text":"Chocolate Factory"}],"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":""},{"color":"gray","text":"production by "},{"color":"green","text":"+0.05x"},{"color":"gray","text":". Duplicate"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"green","text":"Chocolate Rabbits "},{"color":"gray","text":"that you find"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"grant "},{"color":"gold","text":"+33% Chocolate"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Held Item: "},{"color":"blue","text":"Yellow Bandana"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"gold","text":"+30☘ Farming Fortune"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"aqua","text":"MAX LEVEL"}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"â–¸ 34,291,324 XP"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"red","text":"Click to despawn!"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"yellow","text":"Shift Left-click to toggle as favorite!"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"Right-click to convert to an item!"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: [I; + -363097213, + -1822870885, + -1670199288, + -1615169037 + ], + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTYwNDU4NjI3ODg1NywKICAicHJvZmlsZUlkIiA6ICI0ZTMwZjUwZTdiYWU0M2YzYWZkMmE3NDUyY2ViZTI5YyIsCiAgInByb2ZpbGVOYW1lIiA6ICJfdG9tYXRvel8iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjM0Mzg1NTVlODk5YmQ5YTA1MWE5NWRiZWE0OWViMmVjZmE1MmE2OWRiYmE4OTk4ZjM2NzM4MTllMjc3ZmRmNSIKICAgIH0KICB9Cn0=" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/rune-in-sack.snbt b/src/test/resources/testdata/items/rune-in-sack.snbt new file mode 100644 index 0000000..4624c0f --- /dev/null +++ b/src/test/resources/testdata/items/rune-in-sack.snbt @@ -0,0 +1,34 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:custom_data": { + }, + "minecraft:custom_name": '{"extra":[{"color":"dark_blue","text":"â—† "},{"bold":true,"color":"dark_blue","text":"Tidal Rune"}],"italic":false,"text":""}', + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Rune Sack"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"I"},{"color":"gray","text":": "},{"color":"yellow","text":"1"},{"color":"gray","text":"/64"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"II"},{"color":"gray","text":": "},{"color":"dark_gray","text":"0"},{"color":"gray","text":"/64"}],"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"III"},{"color":"gray","text":": "},{"color":"dark_gray","text":"0"},{"color":"gray","text":"/64"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Tier: "},{"color":"gold","text":"Legendary"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"yellow","text":"Click to pickup!"}],"italic":false,"text":""}' + ], + "minecraft:profile": { + id: "30ea28d50755386a90924ae91af1b7e5", + name: "30ea28d50755386a", + properties: [ + { + name: "textures", + signature: "", + value: "ewogICJ0aW1lc3RhbXAiIDogMTcxOTUwMzQ3NzI1MSwKICAicHJvZmlsZUlkIiA6ICIxOWY1YzkwMWEzMjQ0YzVmYTM4NThjZGVhNDk5ZWMwYSIsCiAgInByb2ZpbGVOYW1lIiA6ICJzb2RpdW16aXAiLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjk2NzEwNDdjNmFkZThhOWM0ZDZhNTgxYmMyNmQyODRhNTRhZTMyZTg1YzM0Y2U2OWQ4MWY5Mjc5OWJmM2ZiYiIsCiAgICAgICJtZXRhZGF0YSIgOiB7CiAgICAgICAgIm1vZGVsIiA6ICJzbGltIgogICAgICB9CiAgICB9CiAgfQp9" + } + ] + } + }, + count: 1, + id: "minecraft:player_head" +} diff --git a/src/test/resources/testdata/items/titanium-drill.snbt b/src/test/resources/testdata/items/titanium-drill.snbt new file mode 100644 index 0000000..e49c6b0 --- /dev/null +++ b/src/test/resources/testdata/items/titanium-drill.snbt @@ -0,0 +1,100 @@ +{ + source: { + dataVersion: 4189, + }, + components: { + "minecraft:attribute_modifiers": { + modifiers: [ + ], + show_in_tooltip: 0b + }, + "minecraft:custom_data": { + compact_blocks: 1023815, + donated_museum: 1b, + drill_fuel: 16621, + drill_part_fuel_tank: "titanium_fuel_tank", + drill_part_upgrade_module: "goblin_omelette_blue_cheese", + enchantments: { + compact: 10, + efficiency: 5, + experience: 3, + fortune: 3, + paleontologist: 2, + pristine: 5 + }, + gems: { + AMBER_0: { + quality: "PERFECT", + uuid: "d28be6ae-75eb-49e4-90d8-31759db18d79" + }, + JADE_0: { + quality: "PERFECT", + uuid: "657fea0b-88e2-483d-9d2c-0b821797a55a" + }, + MINING_0: { + quality: "PERFECT", + uuid: "257bdcd2-585b-48b9-9517-a2e841dc0574" + }, + MINING_0_gem: "TOPAZ", + unlocked_slots: [ + "JADE_0", + "MINING_0" + ] + }, + id: "TITANIUM_DRILL_4", + modifier: "auspicious", + rarity_upgrades: 1, + timestamp: 1700577120000L, + uuid: "367b85ab-5bb4-43b6-a055-084cbaaafc1c" + }, + "minecraft:custom_name": '{"extra":[{"color":"light_purple","text":"Auspicious Titanium Drill DR-X655"}],"italic":false,"text":""}', + "minecraft:enchantment_glint_override": 1b, + "minecraft:hide_additional_tooltip": { + }, + "minecraft:lore": [ + '{"extra":[{"color":"dark_gray","text":"Breaking Power 9"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Damage: "},{"color":"red","text":"+75"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Speed: "},{"color":"green","text":"+1,885 "},{"color":"blue","text":"(+75) "},{"color":"light_purple","text":"(+100)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Pristine: "},{"color":"green","text":"+4.5 "},{"color":"light_purple","text":"(+2)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Fortune: "},{"color":"green","text":"+220 "},{"color":"blue","text":"(+20) "},{"color":"light_purple","text":"(+50)"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Mining Wisdom: "},{"color":"green","text":"+10"}],"italic":false,"text":""}', + '{"extra":[" ",{"color":"gold","text":"["},{"color":"gold","text":"⸕"},{"color":"gold","text":"] "},{"color":"gold","text":"["},{"color":"green","text":"☘"},{"color":"gold","text":"] "},{"color":"gold","text":"["},{"color":"yellow","text":"✦"},{"color":"gold","text":"]"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Compact X"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Efficiency V"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Experience III"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Fortune III"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Paleontologist II"}],"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Prismatic V"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"green","text":"Titanium-Infused Fuel Tank."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":""},{"color":"dark_green","text":"25,000 Max Fuel Capacity."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":""},{"color":"green","text":"-4% Pickaxe Ability Cooldown."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Drill Engine: "},{"color":"red","text":"Not Installed"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Increases "},{"color":"gold","text":"⸕ Mining Speed "},{"color":"gray","text":"with part"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"installed."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"green","text":"Blue Cheese Goblin Omelette Part."}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Adds "},{"color":"green","text":"+1 Level "},{"color":"gray","text":"to all of your unlocked "},{"color":"dark_purple","text":"Heart of"}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_purple","text":"the Mountain "},{"color":"gray","text":"perks."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":""},{"color":"gray","text":"Fuel: "},{"color":"dark_green","text":"16,621"},{"color":"dark_gray","text":"/25k"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"gold","text":"Ability: Pickobulus "},{"bold":true,"color":"yellow","text":"RIGHT CLICK"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Throw your pickaxe to create an"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"explosion mining all ores in a "},{"color":"green","text":"3 "},{"color":"gray","text":"block"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"radius."}],"italic":false,"text":""}', + '{"extra":[{"color":"dark_gray","text":"Cooldown: "},{"color":"green","text":"48s"}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"color":"blue","text":"Auspicious Bonus"}],"italic":false,"text":""}', + '{"extra":[{"color":"gray","text":"Grants "},{"color":"gold","text":"+0.9% "},{"color":"gold","text":"☘ Mining Fortune"},{"color":"gray","text":"."}],"italic":false,"text":""}', + '{"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"dark_gray","text":"* "},{"color":"dark_gray","text":"Co-op Soulbound "},{"bold":true,"color":"dark_gray","text":"*"}],"italic":false,"text":""}', + '{"extra":[{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"},"",{"bold":false,"extra":[" "],"italic":false,"obfuscated":false,"strikethrough":false,"text":"","underlined":false},{"bold":true,"color":"light_purple","text":"MYTHIC DRILL "},{"bold":true,"color":"light_purple","obfuscated":true,"text":"a"}],"italic":false,"text":""}' + ] + }, + count: 1, + id: "minecraft:prismarine_shard" +} diff --git a/src/test/resources/testdata/tablist/dungeon_hub.snbt b/src/test/resources/testdata/tablist/dungeon_hub.snbt new file mode 100644 index 0000000..fed57ad --- /dev/null +++ b/src/test/resources/testdata/tablist/dungeon_hub.snbt @@ -0,0 +1,1170 @@ +{ + body: [ + { + extra: [ + " ", + { + bold: 1b, + color: "green", + text: "Players " + }, + { + color: "white", + text: "(15)" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "aqua", + text: "210" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "lrg89" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "light_purple", + text: "322" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "Basilickk" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "light_purple", + text: "330" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "Schauli23 " + }, + { + color: "gray", + text: "Σ" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_green", + text: "187" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "bombardiro13" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "yellow", + text: "119" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "Horuu" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_green", + text: "188" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "Kirito_Hacker " + }, + { + bold: 1b, + color: "gray", + text: "ê•" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "blue", + text: "281" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "LasseFTW1N " + }, + { + bold: 1b, + color: "dark_purple", + text: "࿇" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_aqua", + text: "274" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "VN_Tuan " + }, + { + bold: 1b, + color: "aqua", + text: "á›" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "aqua", + text: "205" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "buttonpurse_1212" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_green", + text: "193" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "Moly____ " + }, + { + bold: 1b, + color: "gray", + text: "âš›" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_green", + text: "187" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "BehavingTurtle4" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "dark_green", + text: "169" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "Kalmaria " + }, + { + color: "gold", + text: "à¯" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "yellow", + text: "84" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "green", + text: "Cxter" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "white", + text: "48" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "gray", + text: "FredyFazballs" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + color: "dark_gray", + text: "[" + }, + { + color: "gray", + text: "21" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "gray", + text: "Finn1446" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + bold: 1b, + color: "green", + text: "Players " + }, + { + color: "white", + text: "(15)" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + bold: 1b, + color: "dark_aqua", + text: "Info" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "aqua", + text: "Area: " + }, + { + color: "gray", + text: "Dungeon Hub" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Server: ", + { + color: "dark_gray", + text: "mini90J" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Gems: ", + { + color: "green", + text: "65" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Fairy Souls: ", + { + color: "light_purple", + text: "7" + }, + { + color: "dark_purple", + text: "/" + }, + { + color: "light_purple", + text: "7" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Unclaimed chests: ", + { + color: "gold", + text: "0" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + text: "" + }, + { + bold: 1b, + color: "yellow", + text: "Profile: " + }, + { + color: "green", + text: "Strawberry" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " SB Level", + { + color: "white", + text: ": " + }, + { + color: "dark_gray", + text: "[" + }, + { + color: "aqua", + text: "210" + }, + { + color: "dark_gray", + text: "] " + }, + { + color: "aqua", + text: "26" + }, + { + color: "dark_aqua", + text: "/" + }, + { + color: "aqua", + text: "100 XP" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Bank: ", + { + color: "gold", + text: "1.4B" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Interest: ", + { + color: "yellow", + text: "12 Hours" + }, + { + color: "gold", + text: " (689.1k)" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "yellow", + text: "Collection:" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Bonzo IV: ", + { + color: "yellow", + text: "110" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "150" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Scarf II: ", + { + color: "yellow", + text: "25" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "50" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " The Professor IV: ", + { + color: "yellow", + text: "141" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "150" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Thorn I: ", + { + color: "yellow", + text: "29" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "50" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Livid II: ", + { + color: "yellow", + text: "91" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "100" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Sadan V: ", + { + color: "yellow", + text: "388" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "500" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Necron VI: ", + { + color: "yellow", + text: "531" + }, + { + color: "gold", + text: "/" + }, + { + color: "yellow", + text: "750" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + bold: 1b, + color: "dark_aqua", + text: "Info" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "gold", + text: "Dungeons:" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + color: "white", + text: "Catacombs 39: " + }, + { + color: "green", + text: "15%" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + color: "green", + text: "Mage 36: " + }, + { + color: "green", + text: "12.9%" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "light_purple", + text: "RNG Meter" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + color: "green", + text: "Catacombs Floor I" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " ", + { + color: "gray", + text: "None" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "aqua", + text: "Essence:" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Undead: ", + { + color: "light_purple", + text: "1,907" + } + ], + italic: 0b, + text: "" + }, + { + extra: [ + " Wither: ", + { + color: "light_purple", + text: "318" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + extra: [ + { + bold: 1b, + color: "aqua", + text: "Party: " + }, + { + color: "gray", + text: "No party" + } + ], + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + }, + { + italic: 0b, + text: "" + } + ], + footer: { + extra: [ + "\n", + { + extra: [ + { + bold: 1b, + color: "green", + text: "Active Effects" + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + color: "gray", + text: "" + }, + { + color: "gray", + text: "You have " + }, + { + color: "yellow", + text: "2 " + }, + { + color: "gray", + text: 'active effects. Use "' + }, + { + color: "gold", + text: "/effects" + }, + { + color: "gray", + text: '" to see them!' + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + color: "yellow", + text: "Haste II" + }, + "", + { + bold: 0b, + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "", + underlined: 0b + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + "", + { + bold: 0b, + extra: [ + "§s" + ], + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "", + underlined: 0b + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + bold: 1b, + color: "light_purple", + text: "Cookie Buff" + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + color: "gray", + text: "" + }, + { + color: "gray", + text: "Not active! Obtain booster cookies from the community" + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + color: "gray", + text: "shop in the hub." + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + "", + { + bold: 0b, + extra: [ + "§s" + ], + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "", + underlined: 0b + } + ], + italic: 0b, + text: "" + }, + "\n", + { + extra: [ + { + color: "green", + extra: [ + { + bold: 1b, + color: "red", + text: "STORE.HYPIXEL.NET" + } + ], + text: "Ranks, Boosters & MORE! " + } + ], + italic: 0b, + text: "" + } + ], + italic: 0b, + text: "" + }, + header: { + extra: [ + { + color: "aqua", + extra: [ + { + bold: 1b, + color: "yellow", + text: "MC.HYPIXEL.NET" + } + ], + text: "You are playing on " + }, + "\n", + { + extra: [ + "", + { + bold: 0b, + extra: [ + "§s" + ], + italic: 0b, + obfuscated: 0b, + strikethrough: 0b, + text: "", + underlined: 0b + } + ], + italic: 0b, + text: "" + } + ], + italic: 0b, + text: "" + }, + source: { + dataVersion: 4325, + modVersion: "Firmament 3.1.0-dev+mc1.21.5+g2de6cfb" + } +} diff --git a/src/texturePacks/README.md b/src/texturePacks/README.md new file mode 100644 index 0000000..8932817 --- /dev/null +++ b/src/texturePacks/README.md @@ -0,0 +1,13 @@ + + +# Technical Notes for the texture pack implementation + +Relevant classes: + +`ItemModelManager` can be used to select an `ItemModel`. This is done from the `ITEM_MODEL` component which is defaulted by the `Item` class. + +The list of available `ItemModel`s (as in `Identifier` -> `ItemModel` maps) is loaded by `BakedModelManager`. To this end, item models in particular are loaded from `ItemAssetsLoader#load`. Those `ItemAssets` are found in `assets//items/` directly (not in the model folder) and can be used to select other models, similar to how predicates used to work diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/Compat.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/Compat.kt new file mode 100644 index 0000000..d95712b --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/Compat.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.features.texturepack + +import moe.nea.firmament.util.compatloader.CompatMeta +import moe.nea.firmament.util.compatloader.ICompatMeta + +@CompatMeta +object Compat : ICompatMeta { + override fun shouldLoad(): Boolean { + return true + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt new file mode 100644 index 0000000..2d7a978 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt @@ -0,0 +1,453 @@ +@file:UseSerializers(BlockPosSerializer::class, IdentifierSerializer::class) + +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonParseException +import com.google.gson.JsonParser +import com.mojang.serialization.JsonOps +import java.util.concurrent.CompletableFuture +import java.util.concurrent.Executor +import java.util.function.Function +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.block.Blocks +import net.minecraft.client.render.model.Baker +import net.minecraft.client.render.model.BlockStateModel +import net.minecraft.client.render.model.BlockStatesLoader +import net.minecraft.client.render.model.ReferencedModelsCollector +import net.minecraft.client.render.model.SimpleBlockStateModel +import net.minecraft.client.render.model.json.BlockModelDefinition +import net.minecraft.client.render.model.json.ModelVariant +import net.minecraft.registry.Registries +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryKeys +import net.minecraft.resource.Resource +import net.minecraft.resource.ResourceManager +import net.minecraft.resource.SinglePreparationResourceReloader +import net.minecraft.state.StateManager +import net.minecraft.util.Identifier +import net.minecraft.util.math.BlockPos +import net.minecraft.util.profiler.Profiler +import net.minecraft.util.thread.AsyncHelper +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.EarlyResourceReloadEvent +import moe.nea.firmament.events.FinalizeResourceManagerEvent +import moe.nea.firmament.events.SkyblockServerUpdateEvent +import moe.nea.firmament.features.texturepack.CustomBlockTextures.createBakedModels +import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger +import moe.nea.firmament.util.ErrorUtil +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, + val area: List? = null, + val replacements: Map, + ) + + @Serializable(with = Replacement.Serializer::class) + data class Replacement( + val block: Identifier, + val sound: Identifier?, + ) { + fun replace(block: BlockState): BlockStateModel? { + blockStateMap?.let { return it[block] } + return blockModel + } + + @Transient + lateinit var overridingBlock: Block + + @Transient + val blockModelIdentifier get() = block.withPrefixedPath("block/") + + /** + * Guaranteed to be set after [BakedReplacements.modelBakingFuture] is complete, if [unbakedBlockStateMap] is set. + */ + @Transient + var blockStateMap: Map? = null + + @Transient + var unbakedBlockStateMap: Map? = null + + /** + * Guaranteed to be set after [BakedReplacements.modelBakingFuture] is complete. Prefer [blockStateMap] if present. + */ + @Transient + lateinit var blockModel: BlockStateModel + + @OptIn(ExperimentalSerializationApi::class) + @kotlinx.serialization.Serializer(Replacement::class) + object DefaultSerializer : KSerializer + + object Serializer : KSerializer { + val delegate = serializer() + 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> + ) { + init { + lookup.forEach { (block, replacements) -> + for (replacement in replacements) { + replacement.replacement.overridingBlock = block + } + } + } + } + + data class BlockReplacement( + val checks: List?, + 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) { + /** + * Fulfilled by [createBakedModels] which is called during model baking. Once completed, all [Replacement.blockModel] will be set. + */ + val modelBakingFuture = CompletableFuture() + + /** + * @returns a list of all [Replacement]s. + */ + fun collectAllReplacements(): Sequence { + return data.values.asSequence() + .flatMap { it.lookup.values } + .flatten() + .map { it.replacement } + } + } + + 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 { + val r = Class.forName("moe.nea.firmament.compat.sodium.SodiumChunkReloader") + .getConstructor() + .newInstance() as Runnable + r.run() + r + }.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?): BlockStateModel? { + return getReplacement(block, blockPos)?.replace(block) + } + + @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 + @get:JvmStatic + var preparationFuture: CompletableFuture = 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 + ) + } + + private fun prepare(manager: ResourceManager): BakedReplacements { + val resources = manager.findResources("overrides/blocks") { + it.namespace == "firmskyblock" && it.path.endsWith(".json") + } + val map = mutableMapOf>>() + for ((file, resource) in resources) { + val json = + Firmament.tryDecodeJsonFromStream(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.getOrThrow(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) }) + } + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + event.resourceManager.registerReloader(object : + SinglePreparationResourceReloader() { + override fun prepare(manager: ResourceManager, profiler: Profiler): BakedReplacements { + return preparationFuture.join().also { + it.modelBakingFuture.join() + } + } + + override fun apply(prepared: BakedReplacements, manager: ResourceManager, profiler: Profiler?) { + allLocationReplacements = prepared + refreshReplacements() + } + }) + } + + fun simpleBlockModel(blockId: Identifier): SimpleBlockStateModel.Unbaked { + // TODO: does this need to be shared between resolving and baking? I think not, but it would probably be wise to do so in the future. + return SimpleBlockStateModel.Unbaked( + ModelVariant(blockId) + ) + } + + /** + * Used by [moe.nea.firmament.init.SectionBuilderRiser] + */ + + @JvmStatic + fun patchIndigo(original: BlockStateModel, pos: BlockPos?, state: BlockState): BlockStateModel { + return getReplacementModel(state, pos) ?: original + } + + @JvmStatic + fun collectExtraModels(modelsCollector: ReferencedModelsCollector) { + preparationFuture.join().collectAllReplacements() + .forEach { + modelsCollector.resolve(simpleBlockModel(it.blockModelIdentifier)) + it.unbakedBlockStateMap?.values?.forEach { + modelsCollector.resolve(it) + } + } + } + + @JvmStatic + fun createBakedModels(baker: Baker, executor: Executor): CompletableFuture { + return preparationFuture.thenComposeAsync(Function { replacements -> + val allBlockStates = CompletableFuture.allOf( + *replacements.collectAllReplacements().filter { it.unbakedBlockStateMap != null }.map { + CompletableFuture.supplyAsync({ + it.blockStateMap = it.unbakedBlockStateMap + ?.map { + it.key to it.value.bake(it.key, baker) + } + ?.toMap() + }, executor) + }.toList().toTypedArray() + ) + val byModel = replacements.collectAllReplacements().groupBy { it.blockModelIdentifier } + val modelBakingTask = AsyncHelper.mapValues(byModel, { blockId, replacements -> + val unbakedModel = SimpleBlockStateModel.Unbaked( + ModelVariant(blockId) + ) + val baked = unbakedModel.bake(baker) + replacements.forEach { + it.blockModel = baked + } + }, executor) + modelBakingTask.thenComposeAsync { + allBlockStates + }.thenAcceptAsync { + replacements.modelBakingFuture.complete(Unit) + } + }, executor) + } + + @JvmStatic + fun collectExtraBlockStateMaps( + extra: BakedReplacements, + original: Map>, + stateManagers: Function?> + ) { + extra.collectAllReplacements().forEach { + val blockId = Registries.BLOCK.getKey(it.overridingBlock).getOrNull()?.value ?: return@forEach + val allModels = mutableListOf() + val stateManager = stateManagers.apply(blockId) ?: return@forEach + for (resource in original[BlockStatesLoader.FINDER.toResourcePath(it.block)] ?: return@forEach) { + try { + resource.reader.use { reader -> + val jsonElement = JsonParser.parseReader(reader) + val blockModelDefinition = + BlockModelDefinition.CODEC.parse(JsonOps.INSTANCE, jsonElement) + .getOrThrow { msg: String? -> JsonParseException(msg) } + allModels.add( + BlockStatesLoader.LoadedBlockStateDefinition( + resource.getPackId(), + blockModelDefinition + ) + ) + } + } catch (exception: Exception) { + ErrorUtil.softError( + "Failed to load custom blockstate definition ${it.block} from pack ${resource.packId}", + exception + ) + } + } + + try { + it.unbakedBlockStateMap = BlockStatesLoader.combine( + blockId, + stateManager, + allModels + ).models + } catch (exception: Exception) { + ErrorUtil.softError("Failed to combine custom blockstate definitions for ${it.block}", exception) + } + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt new file mode 100644 index 0000000..8a2bde5 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt @@ -0,0 +1,180 @@ +@file:UseSerializers(IdentifierSerializer::class) + +package moe.nea.firmament.features.texturepack + +import java.util.Optional +import java.util.concurrent.atomic.AtomicInteger +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlinx.serialization.UseSerializers +import net.minecraft.client.render.entity.equipment.EquipmentModel +import net.minecraft.component.type.EquippableComponent +import net.minecraft.entity.EquipmentSlot +import net.minecraft.item.ItemStack +import net.minecraft.item.equipment.EquipmentAssetKeys +import net.minecraft.registry.RegistryKey +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.features.texturepack.CustomGlobalTextures.logger +import moe.nea.firmament.util.IdentifierSerializer +import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.intoOptional +import moe.nea.firmament.util.skyBlockId + +object CustomGlobalArmorOverrides { + @Serializable + data class ArmorOverride( + @SerialName("item_ids") + val itemIds: List, + val layers: List? = null, + val model: Identifier? = null, + val overrides: List = listOf(), + ) { + @Transient + lateinit var modelIdentifier: Identifier + fun bake(manager: ResourceManager) { + modelIdentifier = bakeModel(model, layers) + overrides.forEach { it.bake(manager) } + } + + init { + require(layers != null || model != null) { "Either model or layers must be specified for armor override" } + require(layers == null || model == null) { "Can't specify both model and layers for armor override" } + } + } + + @Serializable + data class ArmorOverrideLayer( + val tint: Boolean = false, + val identifier: Identifier, + val suffix: String = "", + ) + + @Serializable + data class ArmorOverrideOverride( + val predicate: FirmamentModelPredicate, + val layers: List? = null, + val model: Identifier? = null, + ) { + init { + require(layers != null || model != null) { "Either model or layers must be specified for armor override override" } + require(layers == null || model == null) { "Can't specify both model and layers for armor override override" } + } + + @Transient + lateinit var modelIdentifier: Identifier + fun bake(manager: ResourceManager) { + modelIdentifier = bakeModel(model, layers) + } + } + + + private fun resolveComponent(slot: EquipmentSlot, model: Identifier): EquippableComponent { + return EquippableComponent( + slot, + null, + Optional.of(RegistryKey.of(EquipmentAssetKeys.REGISTRY_KEY, model)), + Optional.empty(), + Optional.empty(), + false, + false, + false, + false + ) + } + + // TODO: BipedEntityRenderer.getEquippedStack create copies of itemstacks for rendering. This means this cache is essentially useless + // If i figure out how to circumvent this (maybe track the origin of those copied itemstacks in some sort of variable in the itemstack to track back the original instance) i should reenable this cache. + // Then also re add this to the cache clearing function + val overrideCache = + WeakCache.dontMemoize>("ArmorOverrides") { stack, slot -> + val id = stack.skyBlockId ?: return@dontMemoize Optional.empty() + val override = overrides[id.neuItem] ?: return@dontMemoize Optional.empty() + for (suboverride in override.overrides) { + if (suboverride.predicate.test(stack)) { + return@dontMemoize resolveComponent(slot, suboverride.modelIdentifier).intoOptional() + } + } + return@dontMemoize resolveComponent(slot, override.modelIdentifier).intoOptional() + } + + var overrides: Map = mapOf() + private var bakedOverrides: MutableMap = mutableMapOf() + private val sentinelFirmRunning = AtomicInteger() + + private fun bakeModel(model: Identifier?, layers: List?): Identifier { + require(model == null || layers == null) + if (model != null) { + return model + } else if (layers != null) { + val idNumber = sentinelFirmRunning.incrementAndGet() + val identifier = Identifier.of("firmament:sentinel/armor/$idNumber") + val equipmentLayers = layers.map { + EquipmentModel.Layer( + it.identifier, if (it.tint) { + Optional.of(EquipmentModel.Dyeable(Optional.of(0xFFA06540.toInt()))) + } else { + Optional.empty() + }, + false + ) + } + bakedOverrides[identifier] = EquipmentModel( + mapOf( + EquipmentModel.LayerType.HUMANOID to equipmentLayers, + EquipmentModel.LayerType.HUMANOID_LEGGINGS to equipmentLayers, + ) + ) + return identifier + } else { + error("Either model or layers must be non null") + } + } + + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + event.resourceManager.registerReloader(object : + SinglePreparationResourceReloader>() { + override fun prepare(manager: ResourceManager, profiler: Profiler): Map { + val overrideFiles = manager.findResources("overrides/armor_models") { + it.namespace == "firmskyblock" && it.path.endsWith(".json") + } + val overrides = overrideFiles.mapNotNull { + Firmament.tryDecodeJsonFromStream(it.value.inputStream).getOrElse { ex -> + logger.error("Failed to load armor texture override at ${it.key}", ex) + null + } + } + bakedOverrides.clear() + val associatedMap = overrides.flatMap { obj -> obj.itemIds.map { it to obj } } + .toMap() + associatedMap.forEach { it.value.bake(manager) } + return associatedMap + } + + override fun apply(prepared: Map, manager: ResourceManager, profiler: Profiler) { + overrides = prepared + } + }) + } + + @JvmStatic + fun overrideArmor(itemStack: ItemStack, slot: EquipmentSlot): Optional { + if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return Optional.empty() + return overrideCache.invoke(itemStack, slot) + } + + @JvmStatic + fun overrideArmorLayer(id: Identifier): EquipmentModel? { + if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return null + return bakedOverrides[id] + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt new file mode 100644 index 0000000..403e3bd --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt @@ -0,0 +1,143 @@ +@file:UseSerializers(IdentifierSerializer::class, FirmamentRootPredicateSerializer::class) + +package moe.nea.firmament.features.texturepack + + +import java.util.concurrent.CompletableFuture +import org.slf4j.LoggerFactory +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers +import kotlin.jvm.optionals.getOrNull +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.CustomItemModelEvent +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.ErrorUtil +import moe.nea.firmament.util.IdentifierSerializer +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.json.SingletonSerializableList +import moe.nea.firmament.util.runNull + +object CustomGlobalTextures : SinglePreparationResourceReloader(), + SubscriptionOwner { + override val delegateFeature: FirmamentFeature + get() = CustomSkyBlockTextures + + class CustomGuiTextureOverride( + val classes: List + ) + + @Serializable + data class GlobalItemOverride( + val screen: @Serializable(SingletonSerializableList::class) List, + val model: Identifier, + val predicate: FirmamentModelPredicate, + ) + + @Serializable + data class ScreenFilter( + val title: StringMatcher, + ) + + data class ItemOverrideCollection( + val screenFilter: ScreenFilter, + val overrides: List, + ) + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + MC.resourceManager.registerReloader(this) + } + + @Subscribe + fun onEarlyReload(event: EarlyResourceReloadEvent) { + preparationFuture = CompletableFuture + .supplyAsync( + { + prepare(event.resourceManager) + }, event.preparationExecutor) + } + + @Volatile + var preparationFuture: CompletableFuture = CompletableFuture.completedFuture( + CustomGuiTextureOverride(listOf())) + + override fun prepare(manager: ResourceManager?, profiler: Profiler?): CustomGuiTextureOverride { + return preparationFuture.join() + } + + override fun apply(prepared: CustomGuiTextureOverride, manager: ResourceManager?, profiler: Profiler?) { + 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(it.value.inputStream).getOrElse { ex -> + ErrorUtil.softError("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 { + ErrorUtil.softError("Failed to locate screen filter at $key used by ${it.value.map { it.first }}") + } + val screenFilter = + Firmament.tryDecodeJsonFromStream(guiClassResource.inputStream) + .getOrElse { ex -> + ErrorUtil.softError("Failed to load screen filter at $key used by ${it.value.map { it.first }}", 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 = setOf() + + @Subscribe + fun onOpenGui(event: ScreenChangeEvent) { + val newTitle = event.new?.title ?: Text.empty() + matchingOverrides = guiClassOverrides.classes + .filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) } + } + + @Subscribe + fun replaceGlobalModel(event: CustomItemModelEvent) { + val override = matchingOverrides + .firstNotNullOfOrNull { + it.overrides + .asSequence() + .filter { it.predicate.test(event.itemStack) } + .map { it.model } + .firstOrNull() + } + + if (override != null) + event.overrideIfExists(override) + } + + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt new file mode 100644 index 0000000..1da840d --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt @@ -0,0 +1,123 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import com.mojang.datafixers.util.Pair +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.Decoder +import com.mojang.serialization.DynamicOps +import com.mojang.serialization.Encoder +import net.minecraft.client.render.item.model.ItemModelTypes +import net.minecraft.item.ItemStack +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.FinalizeResourceManagerEvent +import moe.nea.firmament.features.texturepack.predicates.AndPredicate +import moe.nea.firmament.features.texturepack.predicates.CastPredicate +import moe.nea.firmament.features.texturepack.predicates.DisplayNamePredicate +import moe.nea.firmament.features.texturepack.predicates.ExtraAttributesPredicate +import moe.nea.firmament.features.texturepack.predicates.GenericComponentPredicate +import moe.nea.firmament.features.texturepack.predicates.ItemPredicate +import moe.nea.firmament.features.texturepack.predicates.LorePredicate +import moe.nea.firmament.features.texturepack.predicates.NotPredicate +import moe.nea.firmament.features.texturepack.predicates.OrPredicate +import moe.nea.firmament.features.texturepack.predicates.PetPredicate +import moe.nea.firmament.features.texturepack.predicates.PullingPredicate +import moe.nea.firmament.features.texturepack.predicates.SkullPredicate +import moe.nea.firmament.util.json.KJsonOps + +object CustomModelOverrideParser { + + val LEGACY_CODEC: Codec = + Codec.of( + Encoder.error("cannot encode legacy firmament model predicates"), + object : Decoder { + override fun decode( + ops: DynamicOps, + input: T + ): DataResult> { + try { + val pred = Firmament.json.decodeFromJsonElement( + FirmamentRootPredicateSerializer, + ops.convertTo(KJsonOps.INSTANCE, input)) + return DataResult.success(Pair.of(pred, ops.empty())) + } catch (ex: Exception) { + return DataResult.error { "Could not deserialize ${ex.message}" } + } + } + } + ) + + val predicateParsers = mutableMapOf() + + + 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) + registerPredicateParser("component", GenericComponentPredicate.Parser) + registerPredicateParser("skull", SkullPredicate.Parser) + } + + private val neverPredicate = listOf( + object : FirmamentModelPredicate { + override fun test(stack: ItemStack): Boolean { + return false + } + } + ) + + fun parsePredicates(predicates: JsonObject?): List { + if (predicates == null) return neverPredicate + val parsedPredicates = mutableListOf() + for (predicateName in predicates.keySet()) { + if (predicateName == "cast") { // 1.21.4 + parsedPredicates.add(CastPredicate.Parser.parse(predicates[predicateName]) ?: return neverPredicate) + } + if (predicateName == "pull") { + parsedPredicates.add(PullingPredicate.Parser.parse(predicates[predicateName]) ?: return neverPredicate) + } + if (predicateName == "pulling") { + parsedPredicates.add(PullingPredicate.AnyPulling) + } + 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? { + val predicates = (jsonObject["predicate"] as? JsonObject) ?: return null + val parsedPredicates = parsePredicates(predicates) + if (parsedPredicates.isEmpty()) + return null + return parsedPredicates.toTypedArray() + } + + @Subscribe + fun finalizeResources(event: FinalizeResourceManagerEvent) { + ItemModelTypes.ID_MAPPER.put( + Firmament.identifier("predicates/legacy"), + PredicateModel.Unbaked.CODEC + ) + ItemModelTypes.ID_MAPPER.put( + Firmament.identifier("head_model"), + HeadModelChooser.Unbaked.CODEC + ) + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomScreenLayouts.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomScreenLayouts.kt new file mode 100644 index 0000000..4785e90 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomScreenLayouts.kt @@ -0,0 +1,224 @@ +package moe.nea.firmament.features.texturepack + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import net.minecraft.client.font.TextRenderer +import net.minecraft.client.gui.DrawContext +import net.minecraft.client.gui.screen.Screen +import net.minecraft.client.gui.screen.ingame.HandledScreen +import net.minecraft.client.render.RenderLayer +import net.minecraft.registry.Registries +import net.minecraft.resource.ResourceManager +import net.minecraft.resource.SinglePreparationResourceReloader +import net.minecraft.screen.slot.Slot +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.FinalizeResourceManagerEvent +import moe.nea.firmament.events.ScreenChangeEvent +import moe.nea.firmament.features.texturepack.CustomScreenLayouts.Alignment.CENTER +import moe.nea.firmament.features.texturepack.CustomScreenLayouts.Alignment.LEFT +import moe.nea.firmament.features.texturepack.CustomScreenLayouts.Alignment.RIGHT +import moe.nea.firmament.mixins.accessor.AccessorHandledScreen +import moe.nea.firmament.util.ErrorUtil.intoCatch +import moe.nea.firmament.util.IdentifierSerializer + +object CustomScreenLayouts : SinglePreparationResourceReloader>() { + + @Serializable + data class CustomScreenLayout( + val predicates: Preds, + val background: BackgroundReplacer? = null, + val slots: List = listOf(), + val playerTitle: TitleReplacer? = null, + val containerTitle: TitleReplacer? = null, + val repairCostTitle: TitleReplacer? = null, + val nameField: ComponentMover? = null, + ) + + @Serializable + data class ComponentMover( + val x: Int, + val y: Int, + val width: Int? = null, + val height: Int? = null, + ) + + @Serializable + data class Preds( + val label: StringMatcher, + @Serializable(with = IdentifierSerializer::class) + val screenType: Identifier? = null, + ) { + fun matches(screen: Screen): Boolean { + // TODO: does this deserve the restriction to handled screen + val s = screen as? HandledScreen<*>? ?: return false + val typeMatches = screenType == null || s.screenHandler.type.equals(Registries.SCREEN_HANDLER + .get(screenType)); + + return label.matches(s.title) && typeMatches + } + } + + @Serializable + data class BackgroundReplacer( + @Serializable(with = IdentifierSerializer::class) + val texture: Identifier, + // TODO: allow selectively still rendering some components (recipe button, trade backgrounds, furnace flame progress, arrows) + val x: Int, + val y: Int, + val width: Int, + val height: Int, + ) { + fun renderGeneric(context: DrawContext, screen: HandledScreen<*>) { + screen as AccessorHandledScreen + val originalX: Int = (screen.width - screen.backgroundWidth_Firmament) / 2 + val originalY: Int = (screen.height - screen.backgroundHeight_Firmament) / 2 + val modifiedX = originalX + this.x + val modifiedY = originalY + this.y + val textureWidth = this.width + val textureHeight = this.height + context.drawTexture( + RenderLayer::getGuiTextured, + this.texture, + modifiedX, + modifiedY, + 0.0f, + 0.0f, + textureWidth, + textureHeight, + textureWidth, + textureHeight + ) + + } + } + + @Serializable + data class SlotReplacer( + // TODO: override getRecipeBookButtonPos as well + // TODO: is this index or id (i always forget which one is duplicated per inventory) + val index: Int, + val x: Int, + val y: Int, + ) { + fun move(slots: List) { + val slot = slots.getOrNull(index) ?: return + slot.x = x + slot.y = y + } + } + + @Serializable + enum class Alignment { + @SerialName("left") + LEFT, + + @SerialName("center") + CENTER, + + @SerialName("right") + RIGHT + } + + @Serializable + data class TitleReplacer( + val x: Int? = null, + val y: Int? = null, + val align: Alignment = Alignment.LEFT, + val replace: String? = null + ) { + @Transient + val replacedText: Text? = replace?.let(Text::literal) + + fun replaceText(text: Text): Text { + if (replacedText != null) return replacedText + return text + } + + fun replaceY(y: Int): Int { + return this.y ?: y + } + + fun replaceX(font: TextRenderer, text: Text, x: Int): Int { + val baseX = this.x ?: x + return baseX + when (this.align) { + LEFT -> 0 + CENTER -> -font.getWidth(text) / 2 + RIGHT -> -font.getWidth(text) + } + } + + /** + * Not technically part of the package, but it does allow for us to later on seamlessly integrate a color option into this class as well + */ + fun replaceColor(text: Text, color: Int): Int { + return CustomTextColors.mapTextColor(text, color) + } + } + + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + event.resourceManager.registerReloader(CustomScreenLayouts) + } + + override fun prepare( + manager: ResourceManager, + profiler: Profiler + ): List { + val allScreenLayouts = manager.findResources( + "overrides/screen_layout", + { it.path.endsWith(".json") && it.namespace == "firmskyblock" }) + val allParsedLayouts = allScreenLayouts.mapNotNull { (path, stream) -> + Firmament.tryDecodeJsonFromStream(stream.inputStream) + .intoCatch("Could not read custom screen layout from $path").orNull() + } + return allParsedLayouts + } + + var customScreenLayouts = listOf() + + override fun apply( + prepared: List, + manager: ResourceManager?, + profiler: Profiler? + ) { + this.customScreenLayouts = prepared + } + + @get:JvmStatic + var activeScreenOverride = null as CustomScreenLayout? + + val DO_NOTHING_TEXT_REPLACER = TitleReplacer() + + @JvmStatic + fun getMover(selector: (CustomScreenLayout)-> (T?)) = + activeScreenOverride?.let(selector) + + @JvmStatic + fun getTextMover(selector: (CustomScreenLayout) -> (TitleReplacer?)) = + getMover(selector) ?: DO_NOTHING_TEXT_REPLACER + + @Subscribe + fun onScreenOpen(event: ScreenChangeEvent) { + if (!CustomSkyBlockTextures.TConfig.allowLayoutChanges) { + activeScreenOverride = null + return + } + activeScreenOverride = event.new?.let { screen -> + customScreenLayouts.find { it.predicates.matches(screen) } + } + + val screen = event.new as? HandledScreen<*> ?: return + val handler = screen.screenHandler + activeScreenOverride?.let { override -> + override.slots.forEach { slotReplacer -> + slotReplacer.move(handler.slots) + } + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt new file mode 100644 index 0000000..18949ff --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt @@ -0,0 +1,119 @@ +package moe.nea.firmament.features.texturepack + +import com.mojang.authlib.minecraft.MinecraftProfileTexture +import com.mojang.authlib.properties.Property +import java.util.Optional +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable +import kotlin.jvm.optionals.getOrNull +import net.minecraft.block.SkullBlock +import net.minecraft.client.MinecraftClient +import net.minecraft.client.render.RenderLayer +import net.minecraft.component.type.ProfileComponent +import net.minecraft.util.Identifier +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.CustomItemModelEvent +import moe.nea.firmament.events.FinalizeResourceManagerEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.features.debug.PowerUserTools +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.mc.decodeProfileTextureProperty +import moe.nea.firmament.util.skyBlockId + +object CustomSkyBlockTextures : FirmamentFeature { + override val identifier: String + get() = "custom-skyblock-textures" + + object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) { // TODO: should this be its own thing? + val enabled by toggle("enabled") { true } + val skullsEnabled by toggle("skulls-enabled") { true } + val cacheForever by toggle("cache-forever") { true } + val cacheDuration by integer("cache-duration", 0, 100) { 1 } + val enableModelOverrides by toggle("model-overrides") { true } + val enableArmorOverrides by toggle("armor-overrides") { true } + val enableBlockOverrides by toggle("block-overrides") { true } + val enableLegacyMinecraftCompat by toggle("legacy-minecraft-path-support") { true } + val enableLegacyCIT by toggle("legacy-cit") { true } + val allowRecoloringUiText by toggle("recolor-text") { true } + val allowLayoutChanges by toggle("screen-layouts") { true } + } + + override val config: ManagedConfig + get() = TConfig + + val allItemCaches by lazy { + listOf( + skullTextureCache.cache, + CustomItemModelEvent.cache.cache, + // TODO: re-add this once i figure out how to make the cache useful again CustomGlobalArmorOverrides.overrideCache.cache + ) + } + + init { + PowerUserTools.getSkullId = ::getSkullTexture + } + + fun clearAllCaches() { + allItemCaches.forEach(WeakCache<*, *, *>::clear) + } + + @Subscribe + fun onTick(it: TickEvent) { + if (TConfig.cacheForever) return + if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) { + clearAllCaches() + } + } + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + event.registerOnApply("Clear firmament CIT caches") { + clearAllCaches() + } + } + + @Subscribe + fun onCustomModelId(it: CustomItemModelEvent) { + if (!TConfig.enabled) return + val id = it.itemStack.skyBlockId ?: return + it.overrideIfEmpty(Identifier.of("firmskyblock", id.identifier.path)) + } + + private val skullTextureCache = + WeakCache.memoize>("SkullTextureCache") { component -> + val id = getSkullTexture(component) ?: return@memoize Optional.empty() + if (!MinecraftClient.getInstance().resourceManager.getResource(id).isPresent) { + return@memoize Optional.empty() + } + return@memoize Optional.of(id) + } + + 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 + ) { + if (type != SkullBlock.Type.PLAYER) return + if (!TConfig.skullsEnabled) return + if (component == null) return + + val n = skullTextureCache.invoke(component).getOrNull() ?: return + cir.returnValue = RenderLayer.getEntityTranslucent(n) + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt new file mode 100644 index 0000000..3ac895a --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt @@ -0,0 +1,80 @@ +package moe.nea.firmament.features.texturepack + +import java.util.Optional +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlin.jvm.optionals.getOrNull +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.FinalizeResourceManagerEvent +import moe.nea.firmament.util.collections.WeakCache + +object CustomTextColors : SinglePreparationResourceReloader() { + @Serializable + data class TextOverrides( + val defaultColor: Int, + val overrides: List = listOf() + ) { + /** + * Stub custom text color to allow always returning a text override + */ + @Transient + val baseOverride = TextOverride( + StringMatcher.Equals("", false), + defaultColor, + 0, + 0 + ) + } + + @Serializable + data class TextOverride( + val predicate: StringMatcher, + val override: Int, + val x: Int = 0, + val y: Int = 0, + ) + + @Subscribe + fun registerTextColorReloader(event: FinalizeResourceManagerEvent) { + event.resourceManager.registerReloader(this) + } + + val cache = WeakCache.memoize>("CustomTextColor") { text -> + val override = textOverrides ?: return@memoize Optional.empty() + Optional.ofNullable(override.overrides.find { it.predicate.matches(text) }) + } + + fun mapTextColor(text: Text, oldColor: Int): Int { + val override = cache(text).orElse(null) + return override?.override ?: textOverrides?.defaultColor ?: oldColor + } + + override fun prepare( + manager: ResourceManager, + profiler: Profiler + ): TextOverrides? { + val resource = manager.getResource(Identifier.of("firmskyblock", "overrides/text_colors.json")).getOrNull() + ?: return null + return Firmament.tryDecodeJsonFromStream(resource.inputStream) + .getOrElse { + Firmament.logger.error("Could not parse text_colors.json", it) + null + } + } + + var textOverrides: TextOverrides? = null + + override fun apply( + prepared: TextOverrides?, + manager: ResourceManager, + profiler: Profiler + ) { + textOverrides = prepared + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt new file mode 100644 index 0000000..e020d66 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt @@ -0,0 +1,11 @@ +package moe.nea.firmament.features.texturepack + +import kotlinx.serialization.Serializable +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemStack + +@Serializable(with = FirmamentRootPredicateSerializer::class) +interface FirmamentModelPredicate { + fun test(stack: ItemStack, holder: LivingEntity?): Boolean = test(stack) + fun test(stack: ItemStack): Boolean = test(stack, null) +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt new file mode 100644 index 0000000..3ed0c67 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt @@ -0,0 +1,8 @@ + +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonElement + +interface FirmamentModelPredicateParser { + fun parse(jsonElement: JsonElement): FirmamentModelPredicate? +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt new file mode 100644 index 0000000..0b8ae8e --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt @@ -0,0 +1,23 @@ +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 moe.nea.firmament.features.texturepack.predicates.AndPredicate + +object FirmamentRootPredicateSerializer : KSerializer { + 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(CustomModelOverrideParser.parsePredicates(json).toTypedArray()) + } + + override fun serialize(encoder: Encoder, value: FirmamentModelPredicate) { + TODO("Cannot serialize firmament predicates") + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/HeadModelChooser.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/HeadModelChooser.kt new file mode 100644 index 0000000..3e8cc4e --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/HeadModelChooser.kt @@ -0,0 +1,90 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.client.item.ItemModelManager +import net.minecraft.client.render.item.ItemRenderState +import net.minecraft.client.render.item.model.BasicItemModel +import net.minecraft.client.render.item.model.ItemModel +import net.minecraft.client.render.item.model.ItemModelTypes +import net.minecraft.client.render.model.ResolvableModel +import net.minecraft.client.world.ClientWorld +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemDisplayContext +import net.minecraft.item.ItemStack +import net.minecraft.util.Identifier + +object HeadModelChooser { + val IS_CHOOSING_HEAD_MODEL = ThreadLocal.withInitial { false } + + interface HasExplicitHeadModelMarker { + fun markExplicitHead_Firmament() + fun isExplicitHeadModel_Firmament(): Boolean + companion object{ + @JvmStatic + fun cast(state: ItemRenderState) = state as HasExplicitHeadModelMarker + } + } + + data class Baked(val head: ItemModel, val regular: ItemModel) : ItemModel { + override fun update( + state: ItemRenderState, + stack: ItemStack?, + resolver: ItemModelManager?, + displayContext: ItemDisplayContext, + world: ClientWorld?, + user: LivingEntity?, + seed: Int + ) { + val instance = + if (IS_CHOOSING_HEAD_MODEL.get()) { + HasExplicitHeadModelMarker.cast(state).markExplicitHead_Firmament() + head + } else { + regular + } + instance.update(state, stack, resolver, displayContext, world, user, seed) + } + } + + data class Unbaked( + val head: ItemModel.Unbaked, + val regular: ItemModel.Unbaked, + ) : ItemModel.Unbaked { + override fun getCodec(): MapCodec { + return CODEC + } + + override fun bake(context: ItemModel.BakeContext): ItemModel { + return Baked( + head.bake(context), + regular.bake(context) + ) + } + + override fun resolve(resolver: ResolvableModel.Resolver) { + head.resolve(resolver) + regular.resolve(resolver) + } + + companion object { + @JvmStatic + fun fromLegacyJson(jsonObject: JsonObject, unbakedModel: ItemModel.Unbaked): ItemModel.Unbaked { + val model = jsonObject["firmament:head_model"] ?: return unbakedModel + val modelUrl = model.asJsonPrimitive.asString + val headModel = BasicItemModel.Unbaked(Identifier.of(modelUrl), listOf()) + return Unbaked(headModel, unbakedModel) + } + + val CODEC = RecordCodecBuilder.mapCodec { + it.group( + ItemModelTypes.CODEC.fieldOf("head") + .forGetter(Unbaked::head), + ItemModelTypes.CODEC.fieldOf("regular") + .forGetter(Unbaked::regular), + ).apply(it, ::Unbaked) + } + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt new file mode 100644 index 0000000..e6b5bcf --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt @@ -0,0 +1,105 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.client.item.ItemModelManager +import net.minecraft.client.render.item.ItemRenderState +import net.minecraft.client.render.item.model.BasicItemModel +import net.minecraft.client.render.item.model.ItemModel +import net.minecraft.client.render.item.model.ItemModelTypes +import net.minecraft.client.render.model.ResolvableModel +import net.minecraft.client.world.ClientWorld +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemDisplayContext +import net.minecraft.item.ItemStack +import net.minecraft.util.Identifier +import moe.nea.firmament.features.texturepack.predicates.AndPredicate + +class PredicateModel { + data class Baked( + val fallback: ItemModel, + val overrides: List + ) : ItemModel { + data class Override( + val model: ItemModel, + val predicate: FirmamentModelPredicate, + ) + + override fun update( + state: ItemRenderState?, + stack: ItemStack, + resolver: ItemModelManager?, + displayContext: ItemDisplayContext?, + world: ClientWorld?, + user: LivingEntity?, + seed: Int + ) { + val model = + overrides + .findLast { it.predicate.test(stack, user) } + ?.model + ?: fallback + model.update(state, stack, resolver, displayContext, world, user, seed) + } + } + + data class Unbaked( + val fallback: ItemModel.Unbaked, + val overrides: List, + ) : ItemModel.Unbaked { + companion object { + @JvmStatic + fun fromLegacyJson(jsonObject: JsonObject, fallback: ItemModel.Unbaked): ItemModel.Unbaked { + val legacyOverrides = jsonObject.getAsJsonArray("overrides") ?: return fallback + val newOverrides = ArrayList() + for (legacyOverride in legacyOverrides) { + legacyOverride as JsonObject + val overrideModel = Identifier.tryParse(legacyOverride.get("model")?.asString ?: continue) ?: continue + val predicate = CustomModelOverrideParser.parsePredicates(legacyOverride.getAsJsonObject("predicate")) + newOverrides.add(Override( + BasicItemModel.Unbaked(overrideModel, listOf()), + AndPredicate(predicate.toTypedArray()) + )) + } + return Unbaked(fallback, newOverrides) + } + + val OVERRIDE_CODEC: Codec = RecordCodecBuilder.create { + it.group( + ItemModelTypes.CODEC.fieldOf("model").forGetter(Override::model), + CustomModelOverrideParser.LEGACY_CODEC.fieldOf("predicate").forGetter(Override::predicate), + ).apply(it, Unbaked::Override) + } + val CODEC: MapCodec = + RecordCodecBuilder.mapCodec { + it.group( + ItemModelTypes.CODEC.fieldOf("fallback").forGetter(Unbaked::fallback), + OVERRIDE_CODEC.listOf().fieldOf("overrides").forGetter(Unbaked::overrides), + ).apply(it, ::Unbaked) + } + } + + data class Override( + val model: ItemModel.Unbaked, + val predicate: FirmamentModelPredicate, + ) + + override fun resolve(resolver: ResolvableModel.Resolver) { + fallback.resolve(resolver) + overrides.forEach { it.model.resolve(resolver) } + } + + override fun getCodec(): MapCodec { + return CODEC + } + + override fun bake(context: ItemModel.BakeContext): ItemModel { + return Baked( + fallback.bake(context), + overrides.map { Baked.Override(it.model.bake(context), it.predicate) } + ) + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt new file mode 100644 index 0000000..634a171 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt @@ -0,0 +1,69 @@ + +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 = + "(?[\\[\\(])(?$allRarities)?,(?$allRarities)?(?[\\]\\)])" + .toPattern() + + fun parseRange(string: String): RangeMatcher? { + intervalSpec.useMatch(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/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt new file mode 100644 index 0000000..dd28d9f --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt @@ -0,0 +1,160 @@ + +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 kotlin.jvm.optionals.getOrNull +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.value + 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 = 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 { + 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, 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/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt new file mode 100644 index 0000000..53df184 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt @@ -0,0 +1,75 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive +import moe.nea.firmament.util.ErrorUtil + +data class TintOverrides( + val layerMap: Map = mapOf() +) { + val hasOverrides by lazy { layerMap.values.any { it !is Reset } } + + companion object { + val EMPTY = TintOverrides() + private val threadLocal = object : ThreadLocal() {} + fun enter(overrides: TintOverrides?) { + ErrorUtil.softCheck("Double entered tintOverrides", + threadLocal.get() == null) + threadLocal.set(overrides ?: EMPTY) + } + + fun exit(overrides: TintOverrides?) { + ErrorUtil.softCheck("Exited with non matching enter tintOverrides", + threadLocal.get() == (overrides ?: EMPTY)) + threadLocal.remove() + } + + fun getCurrentOverrides(): TintOverrides { + return ErrorUtil.notNullOr(threadLocal.get(), "Got current tintOverrides without entering") { + EMPTY + } + } + + fun parse(jsonObject: JsonObject): TintOverrides { + val map = mutableMapOf() + for ((key, value) in jsonObject.entrySet()) { + val layerIndex = + ErrorUtil.notNullOr(key.toIntOrNull(), + "Unknown layer index $value. Should be integer") { continue } + if (value.isJsonNull) { + map[layerIndex] = Reset + continue + } + val override = (value as? JsonPrimitive) + ?.takeIf(JsonPrimitive::isNumber) + ?.asInt + ?.let(TintOverrides::Fixed) + if (override == null) { + ErrorUtil.softError("Invalid tint override for a layer: $value") + continue + } + map[layerIndex] = override + } + return TintOverrides(map) + } + } + + fun mergeWithParent(parent: TintOverrides): TintOverrides { + val mergedMap = parent.layerMap.toMutableMap() + mergedMap.putAll(this.layerMap) + return TintOverrides(mergedMap) + } + + fun hasOverrides(): Boolean = hasOverrides + fun getOverride(tintIndex: Int): Int? { + return when (val tint = layerMap[tintIndex]) { + is Reset -> null + is Fixed -> tint.color + null -> null + } + } + + sealed interface TintOverride + data object Reset : TintOverride + data class Fixed(val color: Int) : TintOverride +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt new file mode 100644 index 0000000..7e0ddb1 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt @@ -0,0 +1,19 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt new file mode 100644 index 0000000..70eb814 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt @@ -0,0 +1,29 @@ +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import net.minecraft.entity.LivingEntity +import moe.nea.firmament.features.texturepack.CustomModelOverrideParser +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import net.minecraft.item.ItemStack + +class AndPredicate(val children: Array) : FirmamentModelPredicate { + override fun test(stack: ItemStack, holder: LivingEntity?): Boolean { + return children.all { it.test(stack, holder) } + } + + 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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/CastPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/CastPredicate.kt new file mode 100644 index 0000000..321f87c --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/CastPredicate.kt @@ -0,0 +1,25 @@ +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import net.minecraft.entity.LivingEntity +import net.minecraft.entity.player.PlayerEntity +import net.minecraft.item.ItemStack +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser + +class CastPredicate : FirmamentModelPredicate { + object Parser : FirmamentModelPredicateParser { + override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? { + if (jsonElement.asDouble >= 1) return CastPredicate() + return NotPredicate(arrayOf(CastPredicate())) + } + } + + override fun test(stack: ItemStack, holder: LivingEntity?): Boolean { + return (holder as? PlayerEntity)?.fishHook != null && holder.mainHandStack === stack + } + + override fun test(stack: ItemStack): Boolean { + return false + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt new file mode 100644 index 0000000..04c7a2b --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt @@ -0,0 +1,22 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.features.texturepack.StringMatcher +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.mc.displayNameAccordingToNbt + +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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt new file mode 100644 index 0000000..8115739 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt @@ -0,0 +1,241 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.google.gson.JsonPrimitive +import kotlin.jvm.optionals.getOrDefault +import kotlin.jvm.optionals.getOrNull +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.features.texturepack.StringMatcher +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtByte +import net.minecraft.nbt.NbtDouble +import net.minecraft.nbt.NbtElement +import net.minecraft.nbt.NbtFloat +import net.minecraft.nbt.NbtInt +import net.minecraft.nbt.NbtLong +import net.minecraft.nbt.NbtShort +import moe.nea.firmament.util.extraAttributes +import moe.nea.firmament.util.mc.NbtPrism + +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 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.asString().getOrNull() == string + } + + override fun toString(): String { + return "MatchNbtStringExactly($string)" + } + } + + class MatchString(val string: StringMatcher) : NbtMatcher { + override fun matches(nbt: NbtElement): Boolean { + return nbt.asString().map(string::matches).getOrDefault(false) + } + + 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 prism = NbtPrism.fromElement(path) ?: return null + val matcher = NbtMatcher.Parser.parse(jsonElement.get("match") ?: jsonElement) + ?: return null + return ExtraAttributesPredicate(prism, matcher) + } + } + + override fun test(stack: ItemStack): Boolean { + return path.access(stack.extraAttributes) + .any { matcher.matches(it) } + } +} + diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/GenericComponentPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/GenericComponentPredicate.kt new file mode 100644 index 0000000..71392ef --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/GenericComponentPredicate.kt @@ -0,0 +1,58 @@ +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import com.mojang.serialization.Codec +import kotlin.jvm.optionals.getOrNull +import net.minecraft.component.ComponentType +import net.minecraft.component.type.NbtComponent +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NbtOps +import net.minecraft.registry.RegistryKey +import net.minecraft.registry.RegistryKeys +import net.minecraft.util.Identifier +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.mc.NbtPrism + +data class GenericComponentPredicate( + val componentType: ComponentType, + val codec: Codec, + val path: NbtPrism, + val matcher: NbtMatcher, +) : FirmamentModelPredicate { + constructor(componentType: ComponentType, path: NbtPrism, matcher: NbtMatcher) + : this(componentType, componentType.codecOrThrow, path, matcher) + + override fun test(stack: ItemStack, holder: LivingEntity?): Boolean { + val component = stack.get(componentType) ?: return false + // TODO: cache this + val nbt = + if (component is NbtComponent) component.nbt + else codec.encodeStart(NbtOps.INSTANCE, component) + .resultOrPartial().getOrNull() ?: return false + return path.access(nbt).any { matcher.matches(it) } + } + + object Parser : FirmamentModelPredicateParser { + override fun parse(jsonElement: JsonElement): GenericComponentPredicate<*>? { + if (jsonElement !is JsonObject) return null + val path = jsonElement.get("path") ?: return null + val prism = NbtPrism.fromElement(path) ?: return null + val matcher = NbtMatcher.Parser.parse(jsonElement.get("match") ?: jsonElement) + ?: return null + val component = MC.currentOrDefaultRegistries + .getOrThrow(RegistryKeys.DATA_COMPONENT_TYPE) + .getOrThrow( + RegistryKey.of( + RegistryKeys.DATA_COMPONENT_TYPE, + Identifier.of(jsonElement.get("component").asString) + ) + ).value() + return GenericComponentPredicate(component, prism, matcher) + } + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt new file mode 100644 index 0000000..4833dc0 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt @@ -0,0 +1,34 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.google.gson.JsonPrimitive +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +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.isOf(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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt new file mode 100644 index 0000000..f0b4737 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt @@ -0,0 +1,22 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.features.texturepack.StringMatcher +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.mc.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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt new file mode 100644 index 0000000..4986ad9 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt @@ -0,0 +1,21 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.firmament.features.texturepack.CustomModelOverrideParser +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import net.minecraft.item.ItemStack + +class NotPredicate(val children: Array) : 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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt new file mode 100644 index 0000000..b0d5178 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt @@ -0,0 +1,124 @@ +package moe.nea.firmament.features.texturepack.predicates + +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 = + "(?[\\[\\(])(?[0-9.]+)?,(?[0-9.]+)?(?[\\]\\)])" + .toPattern() + + fun parseRange(string: String): RangeMatcher? { + intervalSpec.useMatch(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.entries.joinToString("|") { it.operator }})(?[0-9.]+)".toPattern() + + fun parseOperator(string: String): OperatorMatcher? { + return operatorPattern.useMatch(string) { + val operatorName = group("operator") + val operator = Operator.entries.find { it.operator == operatorName }!! + val value = group("value").toDouble() + OperatorMatcher(operator, value) + } + } + + 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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt new file mode 100644 index 0000000..e3093cd --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt @@ -0,0 +1,29 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonArray +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.firmament.features.texturepack.CustomModelOverrideParser +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import net.minecraft.item.ItemStack + +class OrPredicate(val children: Array) : 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/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt new file mode 100644 index 0000000..b30b7c9 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt @@ -0,0 +1,66 @@ + +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.google.gson.JsonObject +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.features.texturepack.RarityMatcher +import moe.nea.firmament.features.texturepack.StringMatcher +import net.minecraft.item.ItemStack +import moe.nea.firmament.repo.ExpLadders +import moe.nea.firmament.util.petData + +data 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, + ) + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PullingPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PullingPredicate.kt new file mode 100644 index 0000000..fa46a70 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PullingPredicate.kt @@ -0,0 +1,26 @@ +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import net.minecraft.entity.LivingEntity +import net.minecraft.item.BowItem +import net.minecraft.item.ItemStack +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser + +class PullingPredicate(val percentage: Double) : FirmamentModelPredicate { + companion object { + val AnyPulling = PullingPredicate(0.1) + } + + object Parser : FirmamentModelPredicateParser { + override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? { + return PullingPredicate(jsonElement.asDouble) + } + } + + override fun test(stack: ItemStack, holder: LivingEntity?): Boolean { + if (holder == null) return false + return BowItem.getPullProgress(holder.itemUseTime) >= percentage + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/SkullPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/SkullPredicate.kt new file mode 100644 index 0000000..416e86c --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/SkullPredicate.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.features.texturepack.predicates + +import com.google.gson.JsonElement +import com.mojang.authlib.minecraft.MinecraftProfileTexture +import java.util.UUID +import kotlin.jvm.optionals.getOrNull +import net.minecraft.component.DataComponentTypes +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemStack +import net.minecraft.item.Items +import moe.nea.firmament.features.texturepack.FirmamentModelPredicate +import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser +import moe.nea.firmament.features.texturepack.StringMatcher +import moe.nea.firmament.util.mc.decodeProfileTextureProperty +import moe.nea.firmament.util.parsePotentiallyDashlessUUID + +class SkullPredicate( + val profileId: UUID?, + val textureProfileId: UUID?, + val skinUrl: StringMatcher?, + val textureValue: StringMatcher?, +) : FirmamentModelPredicate { + object Parser : FirmamentModelPredicateParser { + override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? { + val obj = jsonElement.asJsonObject + val profileId = obj.getAsJsonPrimitive("profileId") + ?.asString?.let(::parsePotentiallyDashlessUUID) + val textureProfileId = obj.getAsJsonPrimitive("textureProfileId") + ?.asString?.let(::parsePotentiallyDashlessUUID) + val textureValue = obj.get("textureValue")?.let(StringMatcher::parse) + val skinUrl = obj.get("skinUrl")?.let(StringMatcher::parse) + return SkullPredicate(profileId, textureProfileId, skinUrl, textureValue) + } + } + + override fun test(stack: ItemStack, holder: LivingEntity?): Boolean { + if (!stack.isOf(Items.PLAYER_HEAD)) return false + val profile = stack.get(DataComponentTypes.PROFILE) ?: return false + val textureProperty = profile.properties["textures"].firstOrNull() + val textureMode = lazy(LazyThreadSafetyMode.NONE) { + decodeProfileTextureProperty(textureProperty ?: return@lazy null) + } + when { + profileId != null + && profileId != profile.id.getOrNull() -> + return false + + textureValue != null + && !textureValue.matches(textureProperty?.value ?: "") -> + return false + + skinUrl != null + && !skinUrl.matches(textureMode.value?.textures?.get(MinecraftProfileTexture.Type.SKIN)?.url ?: "") -> + return false + + textureProfileId != null + && textureProfileId != textureMode.value?.profileId -> + return false + + else -> return true + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java new file mode 100644 index 0000000..4665829 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java @@ -0,0 +1,23 @@ + +package moe.nea.firmament.mixins.custommodels; + +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.client.render.entity.state.LivingEntityRenderState; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.decoration.DisplayEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LivingEntityRenderer.class) +public class ApplyHeadModelInItemRenderer> { + // TODO: replace head_model with a condition model (if possible, automatically) + // TODO: ItemAsset.CODEC should upgrade partials + @Inject(method = "updateRenderState(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;F)V", + at = @At("TAIL")) + private void updateHeadState(T livingEntity, S livingEntityRenderState, float f, CallbackInfo ci) { + + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/BuildExtraBlockStateModels.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/BuildExtraBlockStateModels.java new file mode 100644 index 0000000..6b3c929 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/BuildExtraBlockStateModels.java @@ -0,0 +1,24 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.client.render.model.Baker; +import net.minecraft.client.render.model.ModelBaker; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; + +@Mixin(ModelBaker.class) +public class BuildExtraBlockStateModels { + @ModifyReturnValue(method = "bake", at = @At("RETURN")) + private CompletableFuture injectMoreBlockModels(CompletableFuture original, @Local ModelBaker.BakerImpl baker, @Local(argsOnly = true) Executor executor) { + Baker b = baker; + return original.thenCombine( + CustomBlockTextures.createBakedModels(b, executor), + (a, _void) -> a + ); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java new file mode 100644 index 0000000..fede766 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java @@ -0,0 +1,26 @@ + + +package moe.nea.firmament.mixins.custommodels; + +import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; +import net.minecraft.block.SkullBlock; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer; +import net.minecraft.component.type.ProfileComponent; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(SkullBlockEntityRenderer.class) +public class CustomSkullTexturePatch { + @Inject( + method = "getRenderLayer(Lnet/minecraft/block/SkullBlock$SkullType;Lnet/minecraft/component/type/ProfileComponent;Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;", + at = @At("HEAD"), + cancellable = true + ) + private static void onGetRenderLayer(SkullBlock.SkullType type, ProfileComponent profile, Identifier texture, CallbackInfoReturnable cir) { + CustomSkyBlockTextures.INSTANCE.modifySkullTexture(type, profile, cir); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/InsertExtraBlockModelDependencies.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/InsertExtraBlockModelDependencies.java new file mode 100644 index 0000000..91779e7 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/InsertExtraBlockModelDependencies.java @@ -0,0 +1,28 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.client.item.ItemAssetsLoader; +import net.minecraft.client.render.model.BakedModelManager; +import net.minecraft.client.render.model.BlockStatesLoader; +import net.minecraft.client.render.model.ReferencedModelsCollector; +import net.minecraft.client.render.model.UnbakedModel; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.Map; + +@Mixin(BakedModelManager.class) +public class InsertExtraBlockModelDependencies { + @Inject(method = "collect", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/ReferencedModelsCollector;addSpecialModel(Lnet/minecraft/util/Identifier;Lnet/minecraft/client/render/model/UnbakedModel;)V", shift = At.Shift.AFTER)) + private static void insertExtraModels( + Map modelMap, + BlockStatesLoader.LoadedModels stateDefinition, + ItemAssetsLoader.Result result, + CallbackInfoReturnable cir, @Local ReferencedModelsCollector modelsCollector) { + CustomBlockTextures.collectExtraModels(modelsCollector); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ItemRenderStateExtraInfo.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ItemRenderStateExtraInfo.java new file mode 100644 index 0000000..2872dd1 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ItemRenderStateExtraInfo.java @@ -0,0 +1,28 @@ +package moe.nea.firmament.mixins.custommodels; + +import moe.nea.firmament.features.texturepack.HeadModelChooser; +import net.minecraft.client.render.item.ItemRenderState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(ItemRenderState.class) +public class ItemRenderStateExtraInfo implements HeadModelChooser.HasExplicitHeadModelMarker { + boolean hasExplicitHead_firmament = false; + + @Inject(method = "clear", at = @At("HEAD")) + private void clear(CallbackInfo ci) { + hasExplicitHead_firmament = false; + } + + @Override + public void markExplicitHead_Firmament() { + hasExplicitHead_firmament = true; + } + + @Override + public boolean isExplicitHeadModel_Firmament() { + return hasExplicitHead_firmament; + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java new file mode 100644 index 0000000..c33fd04 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/LoadExtraBlockStates.java @@ -0,0 +1,34 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.model.BlockStatesLoader; +import net.minecraft.resource.Resource; +import net.minecraft.state.StateManager; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Function; + +@Mixin(BlockStatesLoader.class) +public class LoadExtraBlockStates { + @ModifyExpressionValue(method = "load", at = @At(value = "INVOKE", target = "Ljava/util/concurrent/CompletableFuture;supplyAsync(Ljava/util/function/Supplier;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private static CompletableFuture>> loadExtraModels( + CompletableFuture>> x, + @Local(argsOnly = true) Executor executor, + @Local Function> stateManagers + ) { + return x.thenCombineAsync(CustomBlockTextures.getPreparationFuture(), (original, extra) -> { + CustomBlockTextures.collectExtraBlockStateMaps(extra, original, stateManagers); + return original; + }, executor); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java new file mode 100644 index 0000000..669da63 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java @@ -0,0 +1,30 @@ + +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; +import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; +import net.minecraft.component.ComponentType; +import net.minecraft.component.type.EquippableComponent; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ArmorFeatureRenderer.class) +public class PatchArmorTexture { + @ModifyExpressionValue( + method = "renderArmor", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;")) + private Object overrideLayers( + Object original, @Local(argsOnly = true) ItemStack itemStack, @Local(argsOnly = true) EquipmentSlot slot + ) { + var overrides = CustomGlobalArmorOverrides.overrideArmor(itemStack, slot); + return overrides.orElse((EquippableComponent) original); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java new file mode 100644 index 0000000..951e3be --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java @@ -0,0 +1,22 @@ +package moe.nea.firmament.mixins.custommodels; + +import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; +import net.minecraft.client.render.entity.equipment.EquipmentModel; +import net.minecraft.client.render.entity.equipment.EquipmentModelLoader; +import net.minecraft.item.equipment.EquipmentAsset; +import net.minecraft.registry.RegistryKey; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +// TODO: auto import legacy models, maybe!!! in a later patch tho +@Mixin(EquipmentModelLoader.class) +public class PatchLegacyArmorLayerSupport { + @Inject(method = "get", at = @At(value = "HEAD"), cancellable = true) + private void patchModelLayers(RegistryKey assetKey, CallbackInfoReturnable cir) { + var modelOverride = CustomGlobalArmorOverrides.overrideArmorLayer(assetKey.getValue()); + if (modelOverride != null) + cir.setReturnValue(modelOverride); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyTexturePathsIntoArmorLayers.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyTexturePathsIntoArmorLayers.java new file mode 100644 index 0000000..0fb6bf8 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyTexturePathsIntoArmorLayers.java @@ -0,0 +1,37 @@ +package moe.nea.firmament.mixins.custommodels; + + +import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; +import moe.nea.firmament.util.MC; +import net.minecraft.client.render.entity.equipment.EquipmentModel; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(EquipmentModel.Layer.class) +public class PatchLegacyTexturePathsIntoArmorLayers { + @Shadow + @Final + private Identifier textureId; + + @Inject(method = "getFullTextureId", at = @At("HEAD"), cancellable = true) + private void replaceWith1201TextureIfExists(EquipmentModel.LayerType layerType, CallbackInfoReturnable cir) { + if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableLegacyMinecraftCompat()) + return; + var resourceManager = MC.INSTANCE.getResourceManager(); + // legacy format: "assets/{identifier.namespace}/textures/models/armor/{identifier.path}_layer_{isLegs ? 2 : 1}{suffix}.png" + // suffix is sadly not available to us here. this means leather armor will look a bit shite + var legacyIdentifier = this.textureId.withPath((textureName) -> { + return "textures/models/armor/" + textureName + "_layer_" + + (layerType == EquipmentModel.LayerType.HUMANOID_LEGGINGS ? 2 : 1) + + ".png"; + }); + if (resourceManager.getResource(legacyIdentifier).isPresent()) { + cir.setReturnValue(legacyIdentifier); + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java new file mode 100644 index 0000000..9401889 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java @@ -0,0 +1,27 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.sound.BlockSoundGroup; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(WorldRenderer.class) +public class ReplaceBlockBreakSoundPatch { +// Sadly hypixel does not send a world event here and instead plays the sound on the server directly +// @WrapOperation(method = "processWorldEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/sound/BlockSoundGroup;getBreakSound()Lnet/minecraft/sound/SoundEvent;")) +// private SoundEvent replaceBreakSoundEvent(BlockSoundGroup instance, Operation original, +// @Local(argsOnly = true) BlockPos pos, @Local BlockState blockState) { +// var replacement = CustomBlockTextures.getReplacement(blockState, pos); +// if (replacement != null && replacement.getSound() != null) { +// return SoundEvent.of(replacement.getSound()); +// } +// return original.call(instance); +// } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java new file mode 100644 index 0000000..95e7dce --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.block.BlockState; +import net.minecraft.client.network.ClientPlayerInteractionManager; +import net.minecraft.client.sound.PositionedSoundInstance; +import net.minecraft.sound.SoundCategory; +import net.minecraft.sound.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ClientPlayerInteractionManager.class) +public class ReplaceBlockHitSoundPatch { + @WrapOperation(method = "updateBlockBreakingProgress", + at = @At(value = "NEW", target = "(Lnet/minecraft/sound/SoundEvent;Lnet/minecraft/sound/SoundCategory;FFLnet/minecraft/util/math/random/Random;Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/client/sound/PositionedSoundInstance;")) + private PositionedSoundInstance replaceSound( + SoundEvent sound, SoundCategory category, float volume, float pitch, + Random random, BlockPos pos, Operation original, + @Local BlockState blockState) { + var replacement = CustomBlockTextures.getReplacement(blockState, pos); + if (replacement != null && replacement.getSound() != null) { + sound = SoundEvent.of(replacement.getSound()); + } + return original.call(sound, category, volume, pitch, random, pos); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java new file mode 100644 index 0000000..8d2ba38 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java @@ -0,0 +1,37 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.block.BlockRenderManager; +import net.minecraft.client.render.chunk.SectionBuilder; +import net.minecraft.client.render.model.BlockStateModel; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(SectionBuilder.class) +public class ReplaceBlockRenderManagerBlockModel { + @WrapOperation(method = "build", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockRenderManager;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BlockStateModel;")) + private BlockStateModel replaceModelInRenderBlock(BlockRenderManager instance, BlockState state, Operation original, @Local(ordinal = 2) BlockPos pos) { + var replacement = CustomBlockTextures.getReplacementModel(state, pos); + if (replacement != null) return replacement; + CustomBlockTextures.enterFallbackCall(); + var fallback = original.call(instance, state); + CustomBlockTextures.exitFallbackCall(); + return fallback; + } +//TODO: cover renderDamage model +// @WrapOperation(method = "renderDamage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/block/BlockModels;getModel(Lnet/minecraft/block/BlockState;)Lnet/minecraft/client/render/model/BakedModel;")) +// private BakedModel replaceModelInRenderDamage( +// BlockModels instance, BlockState state, Operation original, @Local(argsOnly = true) BlockPos pos) { +// var replacement = CustomBlockTextures.getReplacementModel(state, pos); +// if (replacement != null) return replacement; +// CustomBlockTextures.enterFallbackCall(); +// var fallback = original.call(instance, state); +// CustomBlockTextures.exitFallbackCall(); +// return fallback; +// } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java new file mode 100644 index 0000000..455fbf1 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java @@ -0,0 +1,21 @@ +package moe.nea.firmament.mixins.custommodels; + +import moe.nea.firmament.features.texturepack.CustomBlockTextures; +import net.minecraft.block.BlockState; +import net.minecraft.client.render.block.BlockModels; +import net.minecraft.client.render.model.BlockStateModel; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(BlockModels.class) +public class ReplaceFallbackBlockModel { + // TODO: add check to BlockDustParticle + @Inject(method = "getModel", at = @At("HEAD"), cancellable = true) + private void getModel(BlockState state, CallbackInfoReturnable cir) { + var replacement = CustomBlockTextures.getReplacementModel(state, null); + if (replacement != null) + cir.setReturnValue(replacement); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceHeadModel.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceHeadModel.java new file mode 100644 index 0000000..f445f02 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceHeadModel.java @@ -0,0 +1,51 @@ +package moe.nea.firmament.mixins.custommodels; + +import moe.nea.firmament.features.texturepack.HeadModelChooser; +import net.minecraft.client.item.ItemModelManager; +import net.minecraft.client.render.entity.LivingEntityRenderer; +import net.minecraft.client.render.entity.model.EntityModel; +import net.minecraft.client.render.entity.state.LivingEntityRenderState; +import net.minecraft.client.render.item.ItemRenderState; +import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemDisplayContext; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(LivingEntityRenderer.class) +public class ReplaceHeadModel> { + @Shadow + @Final + protected ItemModelManager itemModelResolver; + + @Unique + private ItemRenderState tempRenderState = new ItemRenderState(); + + @Inject( + method = "updateRenderState(Lnet/minecraft/entity/LivingEntity;Lnet/minecraft/client/render/entity/state/LivingEntityRenderState;F)V", + at = @At("TAIL") + ) + private void replaceHeadModel( + T livingEntity, S livingEntityRenderState, float f, CallbackInfo ci + ) { + var headItemStack = livingEntity.getEquippedStack(EquipmentSlot.HEAD); + + HeadModelChooser.INSTANCE.getIS_CHOOSING_HEAD_MODEL().set(true); + tempRenderState.clear(); + this.itemModelResolver.updateForLivingEntity(tempRenderState, headItemStack, ItemDisplayContext.HEAD, livingEntity); + HeadModelChooser.INSTANCE.getIS_CHOOSING_HEAD_MODEL().set(false); + + if (HeadModelChooser.HasExplicitHeadModelMarker.cast(tempRenderState) + .isExplicitHeadModel_Firmament()) { + livingEntityRenderState.wearingSkullType = null; + var temp = livingEntityRenderState.headItemRenderState; + livingEntityRenderState.headItemRenderState = tempRenderState; + tempRenderState = temp; + } + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java new file mode 100644 index 0000000..f2a7409 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java @@ -0,0 +1,43 @@ +package moe.nea.firmament.mixins.custommodels; + + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.events.CustomItemModelEvent; +import moe.nea.firmament.util.mc.IntrospectableItemModelManager; +import net.minecraft.client.item.ItemModelManager; +import net.minecraft.client.render.item.model.ItemModel; +import net.minecraft.client.render.item.model.MissingItemModel; +import net.minecraft.component.ComponentType; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.function.Function; + +@Mixin(ItemModelManager.class) +public class ReplaceItemModelPatch implements IntrospectableItemModelManager { + @Shadow + @Final + private Function modelGetter; + + @WrapOperation( + method = "update", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;")) + private Object replaceItemModelByIdentifier(ItemStack instance, ComponentType componentType, Operation original) { + var override = CustomItemModelEvent.getModelIdentifier(instance, this); + if (override != null && hasModel_firmament(override)) { + return override; + } + return original.call(instance, componentType); + } + + @Override + public boolean hasModel_firmament(@NotNull Identifier identifier) { + return !(modelGetter.apply(identifier) instanceof MissingItemModel); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/SupplyFakeModelPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/SupplyFakeModelPatch.java new file mode 100644 index 0000000..75cedf8 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/SupplyFakeModelPatch.java @@ -0,0 +1,97 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.google.gson.JsonObject; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.Firmament; +import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; +import moe.nea.firmament.features.texturepack.HeadModelChooser; +import moe.nea.firmament.features.texturepack.PredicateModel; +import moe.nea.firmament.util.ErrorUtil; +import net.minecraft.client.item.ItemAsset; +import net.minecraft.client.item.ItemAssetsLoader; +import net.minecraft.client.render.item.model.BasicItemModel; +import net.minecraft.client.render.item.model.ItemModel; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceManager; +import net.minecraft.resource.ResourcePack; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +@Mixin(ItemAssetsLoader.class) +public class SupplyFakeModelPatch { + + @ModifyReturnValue( + method = "load", + at = @At("RETURN") + ) + private static CompletableFuture injectFakeGeneratedModels( + CompletableFuture original, + @Local(argsOnly = true) ResourceManager resourceManager, + @Local(argsOnly = true) Executor executor + ) { + return original.thenCompose(oldModels -> CompletableFuture.supplyAsync(() -> supplyExtraModels(resourceManager, oldModels), executor)); + } + + private static ItemAssetsLoader.Result supplyExtraModels(ResourceManager resourceManager, ItemAssetsLoader.Result oldModels) { + if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableLegacyMinecraftCompat()) return oldModels; + Map newModels = new HashMap<>(oldModels.contents()); + var resources = resourceManager.findResources( + "models/item", + id -> (id.getNamespace().equals("firmskyblock") || id.getNamespace().equals("cittofirmgenerated")) + && id.getPath().endsWith(".json")); + for (Map.Entry model : resources.entrySet()) { + var resource = model.getValue(); + var itemModelId = model.getKey().withPath(it -> it.substring("models/item/".length(), it.length() - ".json".length())); + var genericModelId = itemModelId.withPrefixedPath("item/"); + var itemAssetId = itemModelId.withPrefixedPath("items/"); + // TODO: inject tint indexes based on the json data here + ItemModel.Unbaked unbakedModel = new BasicItemModel.Unbaked(genericModelId, List.of()); + // TODO: add a filter using the pack.mcmeta to opt out of this behaviour + try (var is = resource.getInputStream()) { + var jsonObject = Firmament.INSTANCE.getGson().fromJson(new InputStreamReader(is), JsonObject.class); + unbakedModel = PredicateModel.Unbaked.fromLegacyJson(jsonObject, unbakedModel); + unbakedModel = HeadModelChooser.Unbaked.fromLegacyJson(jsonObject, unbakedModel); + } catch (Exception e) { + ErrorUtil.INSTANCE.softError("Could not create resource for fake model supplication: " + model.getKey(), e); + } + if (resourceManager.getResource(itemAssetId.withSuffixedPath(".json")) + .map(Resource::getPack) + .map(it -> isResourcePackNewer(resourceManager, it, resource.getPack())) + .orElse(true)) { + newModels.put(itemModelId, new ItemAsset( + unbakedModel, + new ItemAsset.Properties(true) + )); + } + } + return new ItemAssetsLoader.Result(newModels); + } + + private static boolean isResourcePackNewer( + ResourceManager manager, + ResourcePack null_, ResourcePack proposal) { + var pack = manager.streamResourcePacks() + .filter(it -> it == null_ || it == proposal) + .collect(findLast()); + return pack.orElse(null_) != null_; + } + + private static Collector> findLast() { + return Collectors.reducing(Optional.empty(), Optional::of, + (left, right) -> right.isPresent() ? right : left); + + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ExpandScreenBoundaries.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ExpandScreenBoundaries.java new file mode 100644 index 0000000..e2cae45 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ExpandScreenBoundaries.java @@ -0,0 +1,21 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.screen.ingame.RecipeBookScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin({HandledScreen.class, RecipeBookScreen.class}) +public class ExpandScreenBoundaries { + @Inject(method = "isClickOutsideBounds", at = @At("HEAD"), cancellable = true) + private void onClickOutsideBounds(double mouseX, double mouseY, int left, int top, int button, CallbackInfoReturnable cir) { + var background = CustomScreenLayouts.getMover(CustomScreenLayouts.CustomScreenLayout::getBackground); + if (background == null) return; + var x = background.getX() + left; + var y = background.getY() + top; + cir.setReturnValue(mouseX < (double) x || mouseY < (double) y || mouseX >= (double) (x + background.getWidth()) || mouseY >= (double) (y + background.getHeight())); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceAnvilScreen.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceAnvilScreen.java new file mode 100644 index 0000000..7c5dc45 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceAnvilScreen.java @@ -0,0 +1,55 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.AnvilScreen; +import net.minecraft.client.gui.screen.ingame.ForgingScreen; +import net.minecraft.client.gui.widget.TextFieldWidget; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.AnvilScreenHandler; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(AnvilScreen.class) +public abstract class ReplaceAnvilScreen extends ForgingScreen { + @Shadow + private TextFieldWidget nameField; + + public ReplaceAnvilScreen(AnvilScreenHandler handler, PlayerInventory playerInventory, Text title, Identifier texture) { + super(handler, playerInventory, title, texture); + } + + @Inject(method = "setup", at = @At("TAIL")) + private void moveNameField(CallbackInfo ci) { + var override = CustomScreenLayouts.getMover(CustomScreenLayouts.CustomScreenLayout::getNameField); + if (override == null) return; + int baseX = (this.width - this.backgroundWidth) / 2; + int baseY = (this.height - this.backgroundHeight) / 2; + nameField.setX(baseX + override.getX()); + nameField.setY(baseY + override.getY()); + if (override.getWidth() != null) + nameField.setWidth(override.getWidth()); + if (override.getHeight() != null) + nameField.setHeight(override.getHeight()); + } + + @WrapOperation(method = "drawForeground", + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTextWithShadow(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;III)I"), + allow = 1) + private int onDrawRepairCost(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, Operation original) { + var textOverride = CustomScreenLayouts.getTextMover(CustomScreenLayouts.CustomScreenLayout::getRepairCostTitle); + return original.call(instance, textRenderer, + textOverride.replaceText(text), + textOverride.replaceX(textRenderer, text, x), + textOverride.replaceY(y), + textOverride.replaceColor(text, color)); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceForgingScreen.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceForgingScreen.java new file mode 100644 index 0000000..6e9023d --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceForgingScreen.java @@ -0,0 +1,9 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import net.minecraft.client.gui.screen.ingame.ForgingScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Inject; + +@Mixin(ForgingScreen.class) +public class ReplaceForgingScreen { +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceFurnaceBackgrounds.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceFurnaceBackgrounds.java new file mode 100644 index 0000000..6b076db --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceFurnaceBackgrounds.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.AbstractFurnaceScreen; +import net.minecraft.client.gui.screen.ingame.RecipeBookScreen; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.AbstractFurnaceScreenHandler; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import java.util.function.Function; + +@Mixin(AbstractFurnaceScreen.class) +public abstract class ReplaceFurnaceBackgrounds extends RecipeBookScreen { + public ReplaceFurnaceBackgrounds(T handler, RecipeBookWidget recipeBook, PlayerInventory inventory, Text title) { + super(handler, recipeBook, inventory, title); + } + + @WrapWithCondition(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIFFIIII)V"), allow = 1) + private boolean onDrawBackground(DrawContext instance, Function renderLayers, Identifier sprite, int x, int y, float u, float v, int width, int height, int textureWidth, int textureHeight) { + final var override = CustomScreenLayouts.getActiveScreenOverride(); + if (override == null || override.getBackground() == null) return true; + override.getBackground().renderGeneric(instance, this); + return false; + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceGenericBackgrounds.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceGenericBackgrounds.java new file mode 100644 index 0000000..bd12177 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceGenericBackgrounds.java @@ -0,0 +1,28 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.*; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.text.Text; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin({CraftingScreen.class, CrafterScreen.class, Generic3x3ContainerScreen.class, GenericContainerScreen.class, HopperScreen.class, ShulkerBoxScreen.class,}) +public abstract class ReplaceGenericBackgrounds extends HandledScreen { + // TODO: split out screens with special background components like flames, arrows, etc. (maybe arrows deserve generic handling tho) + public ReplaceGenericBackgrounds(ScreenHandler handler, PlayerInventory inventory, Text title) { + super(handler, inventory, title); + } + + @Inject(method = "drawBackground", at = @At("HEAD"), cancellable = true) + private void replaceDrawBackground(DrawContext context, float deltaTicks, int mouseX, int mouseY, CallbackInfo ci) { + final var override = CustomScreenLayouts.getActiveScreenOverride(); + if (override == null || override.getBackground() == null) return; + override.getBackground().renderGeneric(context, this); + ci.cancel(); + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplacePlayerBackgrounds.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplacePlayerBackgrounds.java new file mode 100644 index 0000000..e02a821 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplacePlayerBackgrounds.java @@ -0,0 +1,50 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import com.llamalad7.mixinextras.injector.v2.WrapWithCondition; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.screen.ingame.RecipeBookScreen; +import net.minecraft.client.gui.screen.recipebook.RecipeBookWidget; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.screen.PlayerScreenHandler; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.function.Function; + +@Mixin(InventoryScreen.class) +public abstract class ReplacePlayerBackgrounds extends RecipeBookScreen { + public ReplacePlayerBackgrounds(PlayerScreenHandler handler, RecipeBookWidget recipeBook, PlayerInventory inventory, Text title) { + super(handler, recipeBook, inventory, title); + } + + + @WrapOperation(method = "drawForeground", + allow = 1, + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I")) + private int onDrawForegroundText(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, boolean shadow, Operation original) { + var textOverride = CustomScreenLayouts.getTextMover(CustomScreenLayouts.CustomScreenLayout::getContainerTitle); + return original.call(instance, textRenderer, + textOverride.replaceText(text), + textOverride.replaceX(textRenderer, text, x), + textOverride.replaceY(y), + textOverride.replaceColor(text, color), + shadow); + } + + @WrapWithCondition(method = "drawBackground", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;drawTexture(Ljava/util/function/Function;Lnet/minecraft/util/Identifier;IIFFIIII)V")) + private boolean onDrawBackground(DrawContext instance, Function renderLayers, Identifier sprite, int x, int y, float u, float v, int width, int height, int textureWidth, int textureHeight) { + final var override = CustomScreenLayouts.getActiveScreenOverride(); + if (override == null || override.getBackground() == null) return true; + override.getBackground().renderGeneric(instance, this); + return false; + } + // TODO: allow moving the player +} diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceTextColorInHandledScreen.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceTextColorInHandledScreen.java new file mode 100644 index 0000000..4f0905a --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/screenlayouts/ReplaceTextColorInHandledScreen.java @@ -0,0 +1,65 @@ +package moe.nea.firmament.mixins.custommodels.screenlayouts; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.features.texturepack.CustomScreenLayouts; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.AnvilScreen; +import net.minecraft.client.gui.screen.ingame.BeaconScreen; +import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.screen.ingame.MerchantScreen; +import net.minecraft.text.Text; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Slice; + +@Mixin(HandledScreen.class) +// TODO: MerchantScreen.class, BeaconScreen.class +public class ReplaceTextColorInHandledScreen { + + @WrapOperation( + method = "drawForeground", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I"), + slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;title:Lnet/minecraft/text/Text;", opcode = Opcodes.GETFIELD), + to = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;playerInventoryTitle:Lnet/minecraft/text/Text;", opcode = Opcodes.GETFIELD) + ), + allow = 1, + require = 1) + private int replaceContainerTitle(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, boolean shadow, Operation original) { + var textOverride = CustomScreenLayouts.getTextMover(CustomScreenLayouts.CustomScreenLayout::getContainerTitle); + return original.call(instance, textRenderer, + textOverride.replaceText(text), + textOverride.replaceX(textRenderer, text, x), + textOverride.replaceY(y), + textOverride.replaceColor(text, color), + shadow); + } + + @WrapOperation( + method = "drawForeground", + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/gui/DrawContext;drawText(Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;IIIZ)I"), + slice = @Slice( + from = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/ingame/HandledScreen;playerInventoryTitle:Lnet/minecraft/text/Text;", opcode = Opcodes.GETFIELD), + to = @At(value = "TAIL") + ), + allow = 1, + require = 1) + private int replacePlayerTitle(DrawContext instance, TextRenderer textRenderer, Text text, int x, int y, int color, boolean shadow, Operation original) { + var textOverride = CustomScreenLayouts.getTextMover(CustomScreenLayouts.CustomScreenLayout::getPlayerTitle); + return original.call(instance, textRenderer, + textOverride.replaceText(text), + textOverride.replaceX(textRenderer, text, x), + textOverride.replaceY(y), + textOverride.replaceColor(text, color), + shadow); + } +} diff --git a/symbols/build.gradle.kts b/symbols/build.gradle.kts new file mode 100644 index 0000000..2084af4 --- /dev/null +++ b/symbols/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + kotlin("jvm") + id("com.google.devtools.ksp") + id("firmament.common") +} + +dependencies { + ksp("dev.zacsweers.autoservice:auto-service-ksp:1.1.0") + implementation("com.google.auto.service:auto-service-annotations:1.1.1") + implementation("com.google.devtools.ksp:symbol-processing-api:1.9.23-1.0.20") + implementation("com.google.code.gson:gson:2.11.0") +} diff --git a/symbols/src/main/kotlin/Subscribe.kt b/symbols/src/main/kotlin/Subscribe.kt new file mode 100644 index 0000000..a6b173f --- /dev/null +++ b/symbols/src/main/kotlin/Subscribe.kt @@ -0,0 +1,7 @@ + +package moe.nea.firmament.annotations + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.SOURCE) +annotation class Subscribe + diff --git a/symbols/src/main/kotlin/process/CompatMetaProcessor.kt b/symbols/src/main/kotlin/process/CompatMetaProcessor.kt new file mode 100644 index 0000000..0753e4c --- /dev/null +++ b/symbols/src/main/kotlin/process/CompatMetaProcessor.kt @@ -0,0 +1,63 @@ +package moe.nea.firmament.annotations.process + +import com.google.auto.service.AutoService +import com.google.devtools.ksp.processing.CodeGenerator +import com.google.devtools.ksp.processing.Dependencies +import com.google.devtools.ksp.processing.KSPLogger +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSName + +class CompatMetaProcessor(val logger: KSPLogger, val codeGenerator: CodeGenerator, val sourceSetName: String) : + SymbolProcessor { + override fun process(resolver: Resolver): List { + val files = resolver.getAllFiles().toList() + val packages = files.mapTo(mutableSetOf()) { it.packageName.asString() } + packages.add("moe.nea.firmament.annotations.generated.$sourceSetName") + val compatMeta = resolver.getSymbolsWithAnnotation("moe.nea.firmament.util.compatloader.CompatMeta") + .singleOrNull() as KSClassDeclaration? ?: return listOf() + val dependencies = Dependencies(aggregating = true, *files.toTypedArray()) + val generatedFileName = "GeneratedCompat${sourceSetName.replaceFirstChar { it.uppercaseChar() }}" + val compatFile = + codeGenerator.createNewFile(dependencies, "moe.nea.firmament.annotations.generated.$sourceSetName", generatedFileName) + .bufferedWriter() + compatFile.appendLine("// This file is @generated by SubscribeAnnotationProcessor") + compatFile.appendLine("// Do not edit") + compatFile.appendLine("package moe.nea.firmament.annotations.generated.$sourceSetName") + compatFile.appendLine("class $generatedFileName : moe.nea.firmament.util.compatloader.ICompatMetaGen {") + compatFile.appendLine(""" + override fun owns(className: String): Boolean { + return moe.nea.firmament.util.compatloader.CompatHelper.isOwnedByPackage(className, ${ + packages.joinToString { "\"" + it + "\"" } + }) + } + + override val meta: moe.nea.firmament.util.compatloader.ICompatMeta + get() = ${compatMeta.qualifiedName!!.asString()} +""") + compatFile.appendLine("}") + compatFile.close() + val metaInf = codeGenerator.createNewFileByPath( + dependencies, + "META-INF/services/moe.nea.firmament.util.compatloader.ICompatMetaGen", extensionName = "") + .bufferedWriter() + metaInf.append("moe.nea.firmament.annotations.generated.$sourceSetName.") + metaInf.appendLine(generatedFileName) + metaInf.close() + return listOf() + } + + + @AutoService(SymbolProcessorProvider::class) + class Provider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { + return CompatMetaProcessor(environment.logger, + environment.codeGenerator, + environment.options["firmament.sourceset"] ?: "main") + } + } +} diff --git a/symbols/src/main/kotlin/process/GameTestContainingClassProcessor.kt b/symbols/src/main/kotlin/process/GameTestContainingClassProcessor.kt new file mode 100644 index 0000000..4fcf91f --- /dev/null +++ b/symbols/src/main/kotlin/process/GameTestContainingClassProcessor.kt @@ -0,0 +1,80 @@ +package moe.nea.firmament.annotations.process + +import com.google.auto.service.AutoService +import com.google.devtools.ksp.containingFile +import com.google.devtools.ksp.processing.CodeGenerator +import com.google.devtools.ksp.processing.Dependencies +import com.google.devtools.ksp.processing.KSPLogger +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSFile +import com.google.gson.Gson +import com.google.gson.JsonArray +import com.google.gson.JsonObject +import java.io.OutputStreamWriter +import java.nio.charset.StandardCharsets +import java.util.TreeSet + +class GameTestContainingClassProcessor( + val logger: KSPLogger, + val codeGenerator: CodeGenerator, + val sourceSetName: String, +) : SymbolProcessor { + + + @AutoService(SymbolProcessorProvider::class) + class Provider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { + return GameTestContainingClassProcessor( + environment.logger, + environment.codeGenerator, + environment.options["firmament.sourceset"] ?: "main") + } + } + + val allClasses: MutableSet = TreeSet() + val allSources = mutableSetOf() + + override fun process(resolver: Resolver): List { + val annotated = resolver.getSymbolsWithAnnotation("net.minecraft.test.GameTest").toList() + annotated.forEach { + val containingClass = it.parent as KSClassDeclaration + allClasses.add(containingClass.qualifiedName!!.asString()) + allSources.add(it.containingFile!!) + } + return emptyList() + } + + fun createJson(): JsonObject { + return JsonObject().apply { + addProperty("schemaVersion", 1) + addProperty("id", "firmament-gametest") + addProperty("name", "Firmament Gametest") + addProperty("version", "1.0.0") + addProperty("environment", "*") + add("entrypoints", JsonObject().apply { + add("fabric-gametest", JsonArray().apply { + allClasses.forEach { + add(it) + } + }) + }) + } + } + + override fun finish() { + if (allClasses.isEmpty()) return + val stream = codeGenerator.createNewFile(Dependencies(aggregating = true, *allSources.toTypedArray()), + "", + "fabric.mod", + "json") + val output = OutputStreamWriter(stream, StandardCharsets.UTF_8) + Gson().toJson(createJson(), output) + output.close() + } + +} diff --git a/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt b/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt new file mode 100644 index 0000000..3eaf3d6 --- /dev/null +++ b/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt @@ -0,0 +1,136 @@ +package moe.nea.firmament.annotations.process + +import com.google.auto.service.AutoService +import com.google.devtools.ksp.processing.CodeGenerator +import com.google.devtools.ksp.processing.Dependencies +import com.google.devtools.ksp.processing.KSPLogger +import com.google.devtools.ksp.processing.Resolver +import com.google.devtools.ksp.processing.SymbolProcessor +import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.processing.SymbolProcessorProvider +import com.google.devtools.ksp.symbol.ClassKind +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSFunctionDeclaration +import com.google.devtools.ksp.symbol.KSType +import com.google.devtools.ksp.symbol.Nullability +import com.google.devtools.ksp.validate +import moe.nea.firmament.annotations.Subscribe + +class SubscribeAnnotationProcessor( + val logger: KSPLogger, + val codeGenerator: CodeGenerator, + val sourceSetName: String, +) : SymbolProcessor { + override fun finish() { + subscriptions.sort() + if (subscriptions.isEmpty()) return + val subscriptionSet = subscriptions.mapTo(mutableSetOf()) { it.cf } + val dependencies = Dependencies( + aggregating = true, + *subscriptionSet.toTypedArray()) + val generatedFileName = "AllSubscriptions${sourceSetName.replaceFirstChar { it.uppercaseChar() }}" + val subscriptionsFile = + codeGenerator + .createNewFile(dependencies, "moe.nea.firmament.annotations.generated.$sourceSetName", generatedFileName) + .bufferedWriter() + subscriptionsFile.apply { + appendLine("// This file is @generated by SubscribeAnnotationProcessor") + appendLine("// Do not edit") + appendLine("package moe.nea.firmament.annotations.generated.$sourceSetName") + appendLine() + appendLine("import moe.nea.firmament.events.subscription.*") + appendLine() + appendLine("@Suppress()") + appendLine("class $generatedFileName : SubscriptionList {") + appendLine(" override fun provideSubscriptions(addSubscription: (Subscription<*>) -> Unit) {") + for (subscription in subscriptions) { + val owner = subscription.pQName.asString() + val method = subscription.child.simpleName.asString() + val type = subscription.type.declaration.qualifiedName!!.asString() + appendLine(" addSubscription(Subscription<$type>(") + appendLine(" ${owner},") + appendLine(" ${owner}::${method},") + appendLine(" ${type},") + appendLine(" \"${method}\"))") + } + appendLine(" }") + appendLine("}") + } + subscriptionsFile.close() + val metaInf = codeGenerator.createNewFileByPath( + dependencies, + "META-INF/services/moe.nea.firmament.events.subscription.SubscriptionList", extensionName = "") + .bufferedWriter() + metaInf.append("moe.nea.firmament.annotations.generated.$sourceSetName.") + metaInf.appendLine(generatedFileName) + metaInf.close() + } + + data class Subscription( + val parent: KSClassDeclaration, + val child: KSFunctionDeclaration, + val type: KSType, + ) : Comparable { + val cf = parent.containingFile!! + val pQName = parent.qualifiedName!! + val tName = type.declaration.qualifiedName!! + override fun compareTo(other: Subscription): Int { + var compare = pQName.asString().compareTo(other.pQName.asString()) + if (compare != 0) return compare + compare = other.child.simpleName.asString().compareTo(child.simpleName.asString()) + if (compare != 0) return compare + compare = other.tName.asString().compareTo(tName.asString()) + if (compare != 0) return compare + return 0 + } + } + + val subscriptions = mutableListOf() + + fun processCandidates(list: List) { + for (element in list) { + if (element !is KSFunctionDeclaration) { + logger.error("@Subscribe annotation on a not-function", element) + continue + } + if (element.isAbstract) { + logger.error("@Subscribe annotation on an abstract function", element) + continue + } + val parent = element.parentDeclaration + if (parent !is KSClassDeclaration || parent.classKind != ClassKind.OBJECT) { + logger.error("@Subscribe on a non-object", element) + continue + } + val param = element.parameters.singleOrNull() + if (param == null) { + logger.error("@Subscribe annotated functions need to take exactly one parameter", element) + continue + } + val type = param.type.resolve() + if (type.nullability != Nullability.NOT_NULL) { + logger.error("@Subscribe annotated functions cannot take a nullable event", element) + continue + } + subscriptions.add(Subscription(parent, element, type)) + } + } + + override fun process(resolver: Resolver): List { + val candidates = resolver.getSymbolsWithAnnotation(Subscribe::class.qualifiedName!!).toList() + val valid = candidates.filter { it.validate() } + val invalid = candidates.filter { !it.validate() } + processCandidates(valid) + return invalid + } +} + +@AutoService(SymbolProcessorProvider::class) +class SubscribeAnnotationProcessorProvider : SymbolProcessorProvider { + override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor { + return SubscribeAnnotationProcessor(environment.logger, + environment.codeGenerator, + environment.options["firmament.sourceset"] ?: "main") + } +} diff --git a/testagent/build.gradle.kts b/testagent/build.gradle.kts new file mode 100644 index 0000000..cf7c15b --- /dev/null +++ b/testagent/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + java + id("firmament.common") + id("com.gradleup.shadow") +} +dependencies { + implementation(libs.asm) +} +tasks.withType { + val agentMain = "moe.nea.firmament.testagent.AgentMain" + manifest.attributes( + "Agent-Class" to agentMain, + "Premain-Class" to agentMain, + ) +} diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java b/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java new file mode 100644 index 0000000..79023d8 --- /dev/null +++ b/testagent/src/main/java/moe/nea/firmament/testagent/AgentMain.java @@ -0,0 +1,21 @@ +package moe.nea.firmament.testagent; + +import java.lang.instrument.Instrumentation; + +public class AgentMain { + + public static void premain( + String agentArgs, Instrumentation inst) { + System.out.println("Pre-Main Firmament Test Agent"); + AgentMain.inject(inst); + } + + public static void agentmain( + String agentArgs, Instrumentation inst) { + System.out.println("Injected Firmament Test Agent"); + AgentMain.inject(inst); + } + + private static void inject(Instrumentation inst) { + inst.addTransformer(new ProtectedToPublicClassTransformer(inst)); } +} diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java new file mode 100644 index 0000000..7d9aa56 --- /dev/null +++ b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassRewriter.java @@ -0,0 +1,31 @@ +package moe.nea.firmament.testagent; + +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class ProtectedToPublicClassRewriter extends ClassVisitor { + public ProtectedToPublicClassRewriter(ClassWriter writer) { + super(Opcodes.ASM9, writer); + } + + int makePublic(int flags) { + if ((flags & Opcodes.ACC_PROTECTED) != 0) + return (flags & ~Opcodes.ACC_PROTECTED) | Opcodes.ACC_PUBLIC; + if ((flags & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PROTECTED | Opcodes.ACC_PRIVATE)) == 0) + return flags | Opcodes.ACC_PUBLIC; + return flags; + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + return super.visitField(makePublic(access), name, descriptor, signature, value); + } + + @Override + public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { + return super.visitMethod(makePublic(access), name, descriptor, signature, exceptions); + } +} diff --git a/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java new file mode 100644 index 0000000..5d59035 --- /dev/null +++ b/testagent/src/main/java/moe/nea/firmament/testagent/ProtectedToPublicClassTransformer.java @@ -0,0 +1,30 @@ +package moe.nea.firmament.testagent; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassWriter; + +import java.lang.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; + +public class ProtectedToPublicClassTransformer implements ClassFileTransformer { + public ProtectedToPublicClassTransformer(Instrumentation inst) { + } + + @Override + public byte[] transform(ClassLoader loader, + String className, + Class classBeingRedefined, + ProtectionDomain protectionDomain, + byte[] classfileBuffer) + throws IllegalClassFormatException { + if (!className.startsWith("net/minecraft/")) return classfileBuffer; + if (classfileBuffer == null) return null; + var reader = new ClassReader(classfileBuffer); + var writer = new ClassWriter(0); + var transformer = new ProtectedToPublicClassRewriter(writer); + reader.accept(transformer, 0); + return writer.toByteArray(); + } +} diff --git a/translations/en_us.json b/translations/en_us.json new file mode 100644 index 0000000..b902206 --- /dev/null +++ b/translations/en_us.json @@ -0,0 +1,552 @@ +{ + "firmament.carnival.tutorial.minesweeper": "§eClick here to check out Firmaments Tutorial for this minigame!", + "firmament.command.toggle.no-config-found": "Could not find config %s", + "firmament.command.toggle.no-property-found": "Could not find property %s", + "firmament.command.toggle.not-a-toggle": "Property %s is not a toggle", + "firmament.command.toggle.toggled": "Toggled %s / %s %s", + "firmament.command.waypoint.added": "Added waypoint %s %s %s.", + "firmament.command.waypoint.clear": "Cleared waypoints.", + "firmament.command.waypoint.import": "Imported %s waypoints from clipboard.", + "firmament.command.waypoint.ordered.toggle.false": "Disabled ordered waypoints", + "firmament.command.waypoint.ordered.toggle.true": "Enabled ordered waypoints", + "firmament.command.waypoint.remove": "Removed waypoint %s. Other waypoints may have different indexes now.", + "firmament.command.waypoint.remove.error": "Could not find waypoint with that index to delete.", + "firmament.command.waypoint.skip": "Skipped 1 waypoint", + "firmament.command.waypoint.skip.error": "Could not skip a waypoint. Are you in ordered waypoint mode with waypoints loaded?", + "firmament.config.all-configs": "- All Configs -", + "firmament.config.anniversary": "Anniversary Features", + "firmament.config.anniversary.pig-hud": "Pig Tracker Hud", + "firmament.config.anniversary.pig-hud.description": "A HUD showing rewards pulled from shiny pigs", + "firmament.config.anniversary.shiny-pigs": "Shiny Pigs Tracker", + "firmament.config.anniversary.shiny-pigs.description": "Track rewards from shiny pigs, as well as how much time you have left to collect your pig.", + "firmament.config.auto-completions": "Hypixel Command Improvements", + "firmament.config.auto-completions.warp-complete": "Auto Complete /warp", + "firmament.config.auto-completions.warp-complete.description": "Auto complete warp destinations in chat. This may include warps you have not yet unlocked.", + "firmament.config.auto-completions.warp-is": "Redirect /warp is to /warp island", + "firmament.config.auto-completions.warp-is.description": "Redirects /warp is to /warp island, since hypixel does not recognize /warp is as a warp destination.", + "firmament.config.block-zapper-overlay": "Block Zapper Overlay", + "firmament.config.block-zapper-overlay.block-zapper-overlay": "Block Zapper Overlay", + "firmament.config.block-zapper-overlay.block-zapper-overlay.description": "Shows what blocks will be zapped", + "firmament.config.block-zapper-overlay.color": "Colour", + "firmament.config.block-zapper-overlay.color.description": "The color that the blocks will be highlighted in", + "firmament.config.block-zapper-overlay.undo-key": "Undo Keybind", + "firmament.config.block-zapper-overlay.undo-key.description": "Keybind to undo your zap", + "firmament.config.bonemerang-overlay": "Bonemerang Overlay", + "firmament.config.bonemerang-overlay.bonemerang-overlay": "Bonemerang Overlay", + "firmament.config.bonemerang-overlay.bonemerang-overlay-hud": "Bonemerang Overlay Hud", + "firmament.config.bonemerang-overlay.bonemerang-overlay-hud.description": "Shows how many targets your bonemerang will hit", + "firmament.config.bonemerang-overlay.bonemerang-overlay.description": "Display an overlay that tells you what block you will warp to.", + "firmament.config.bonemerang-overlay.bonemerang-overlay.display": "Bonemerang Targets: %s", + "firmament.config.bonemerang-overlay.highlight-hit-entities": "Highlight Target Entities", + "firmament.config.bonemerang-overlay.highlight-hit-entities.description": "Highlight entities that will be hit", + "firmament.config.carnival": "Carnival Features", + "firmament.config.carnival.bombs-solver": "Minesweeper Helper", + "firmament.config.carnival.bombs-solver.description": "Display bombs surrounding each block in minesweeper.", + "firmament.config.carnival.tutorials": "Tutorial Reminder", + "firmament.config.carnival.tutorials.description": "Show a tutorial hint every time you start a game with a Firmament tutorial.", + "firmament.config.category.chat": "Chat", + "firmament.config.category.chat.description": "Chat related features", + "firmament.config.category.dev": "Developer & Debug", + "firmament.config.category.dev.description": "Settings for texture pack devs and programmers", + "firmament.config.category.events": "Events", + "firmament.config.category.events.description": "Settings for temporary or repeating events", + "firmament.config.category.garden": "Garden", + "firmament.config.category.garden.description": "Features for the No. 1 Macro Free Island on SkyBlock", + "firmament.config.category.integrations": "Integrations & Textures", + "firmament.config.category.integrations.description": "Integrations with other mods, as well as texture packs", + "firmament.config.category.inventory": "Inventory", + "firmament.config.category.inventory.description": "Features for anything that happens in a chest or inventory", + "firmament.config.category.items": "Items", + "firmament.config.category.items.description": "Features for items", + "firmament.config.category.meta": "Meta & Firmament", + "firmament.config.category.meta.description": "Settings for Firmament and the item repo", + "firmament.config.category.mining": "Mining", + "firmament.config.category.mining.description": "Mining related features", + "firmament.config.category.misc": "Miscellaneous", + "firmament.config.category.misc.description": "Miscellaneous features that don't fit elsewhere", + "firmament.config.centuryraffle": "Century Raffle", + "firmament.config.centuryraffle.highlight-cake-players": "Highlight Players in Team", + "firmament.config.centuryraffle.highlight-cake-players.description": "Highlight the players you can feed while holding a Slice of Century Cake", + "firmament.config.chat-links": "Chat Links", + "firmament.config.chat-links.allow-all-hosts": "Allow all Image Hosts", + "firmament.config.chat-links.allow-all-hosts.description": "Allow displaying images no matter where it is hosted.", + "firmament.config.chat-links.allowed-hosts": "Allowed Image Hosts", + "firmament.config.chat-links.allowed-hosts.description": "Prevent yourself from requesting images from other servers, to prevent your IP from being leaked.", + "firmament.config.chat-links.image-enabled": "Enable Image Preview", + "firmament.config.chat-links.image-enabled.description": "Show a preview of images when hovering over links in chat", + "firmament.config.chat-links.links-enabled": "Enable Clickable Links", + "firmament.config.chat-links.links-enabled.description": "Make links in chat clickable", + "firmament.config.chat-links.position": "Chat Image Preview", + "firmament.config.chat-links.position.description": "Edit where the images are shown", + "firmament.config.commissions": "Commissions", + "firmament.config.commissions.highlight-completed": "Highlight Completed", + "firmament.config.commissions.highlight-completed.description": "Highlight completed commissions in the commission menu", + "firmament.config.compatibility": "Intermod Features", + "firmament.config.compatibility.explosion-enabled": "Redirect Enhanced Explosions", + "firmament.config.compatibility.explosion-enabled.description": "Redirect explosion particles to be rendered by enhanced explosions.", + "firmament.config.compatibility.explosion-power": "Enhanced Explosion Power", + "firmament.config.compatibility.explosion-power.description": "Choose how big explosions will be rendered by enhanced explosions", + "firmament.config.composter": "Composter", + "firmament.config.composter.no-more-noises": "Mute Composter", + "firmament.config.composter.no-more-noises.description": "Muffle all noises and sounds made by the composter", + "firmament.config.configconfig": "Firmaments Config", + "firmament.config.configconfig.enable-moulconfig": "Use MoulConfig", + "firmament.config.configconfig.enable-moulconfig.description": "Uses the MoulConfig config UI. Turn off to fall back to the built in config.", + "firmament.config.configconfig.enable-yacl": "Use YACL Config", + "firmament.config.configconfig.enable-yacl.description": "Uses the YACL config UI. Turn off to fall back to the built in config. Needs YACL to be installed separately.", + "firmament.config.configconfig.wide-moulconfig": "Wide MoulConfig", + "firmament.config.configconfig.wide-moulconfig.description": "Use a wider editor for MoulConfig", + "firmament.config.copy-chat": "Copy Chat", + "firmament.config.copy-chat.copy-chat": "Copy Chat", + "firmament.config.copy-chat.copy-chat.description": "Right click a message to copy", + "firmament.config.custom-skyblock-textures": "Custom SkyBlock Item Textures", + "firmament.config.custom-skyblock-textures.armor-overrides": "Enable Armor re-texturing", + "firmament.config.custom-skyblock-textures.armor-overrides.description": "Allows texture pack authors to re-texture (but not re-model) SkyBlock armors.", + "firmament.config.custom-skyblock-textures.block-overrides": "Enable Block re-modelling", + "firmament.config.custom-skyblock-textures.block-overrides.description": "Allows texture pack authors replacing block models depending on block position and SkyBlock island.", + "firmament.config.custom-skyblock-textures.cache-duration": "Model Cache Duration", + "firmament.config.custom-skyblock-textures.cache-duration.description": "How long texture models should be cached for.", + "firmament.config.custom-skyblock-textures.cache-forever": "Disable cache clearing", + "firmament.config.custom-skyblock-textures.cache-forever.description": "Disables clearing the cache entirely. Since you will be sent new item stacks from the server if something changes, this should not cause issues.", + "firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures", + "firmament.config.custom-skyblock-textures.enabled.description": "Allow replacing items for texture packs. Turning this off does not disable custom predicates", + "firmament.config.custom-skyblock-textures.legacy-cit": "Enable legacy CIT Resewn compat", + "firmament.config.custom-skyblock-textures.legacy-cit.description": "Allow CIT resewn texture packs written for 1.20.4 to be loaded on newer versions.", + "firmament.config.custom-skyblock-textures.legacy-minecraft-path-support": "Enable Legacy Paths", + "firmament.config.custom-skyblock-textures.legacy-minecraft-path-support.description": "Allow texture packs to load textures from some legacy paths. I.e.: Allows loading 1.21.0 armor textures on 1.21.4.", + "firmament.config.custom-skyblock-textures.model-overrides": "Enable model overrides/predicates", + "firmament.config.custom-skyblock-textures.model-overrides.description": "Enable Firmament's model predicates. This will apply to vanilla models as well, if that vanilla model has Firmament predicates.", + "firmament.config.custom-skyblock-textures.recolor-text": "Allow packs to recolor text", + "firmament.config.custom-skyblock-textures.recolor-text.description": "Allows texture packs to recolor UI texts.", + "firmament.config.custom-skyblock-textures.screen-layouts": "Allow packs screen relayouts", + "firmament.config.custom-skyblock-textures.screen-layouts.description": "Allows texture packs to move UI elements like slots around, as well as replace the background of screens.", + "firmament.config.custom-skyblock-textures.skulls-enabled": "Enable Custom Placed Skull Textures", + "firmament.config.custom-skyblock-textures.skulls-enabled.description": "Allow replacing the textures of placed skulls.", + "firmament.config.developer": "Developer Settings", + "firmament.config.developer-capes": "Developer Capes", + "firmament.config.developer-capes.show-cape": "Show Developer Capes", + "firmament.config.developer-capes.show-cape.description": "Allows you to see the developer capes.", + "firmament.config.developer.auto-rebuild": "Automatically rebuild resources", + "firmament.config.developer.auto-rebuild.description": "Executes ./gradlew processResources before F3+T is executed.", + "firmament.config.diana": "Diana", + "firmament.config.diana.ancestral-spade": "Ancestral Spade Solver", + "firmament.config.diana.ancestral-spade.description": "Automatically guess your next burrow based on particles and sounds spawned from the Ancestral Spade's Echo ability.", + "firmament.config.diana.ancestral-teleport": "Warp near guess", + "firmament.config.diana.ancestral-teleport.description": "Click to teleport near the guessed burrow.", + "firmament.config.diana.nearby-waypoints": "Nearby Waypoints Highlighter", + "firmament.config.diana.nearby-waypoints.description": "Highlight nearby diana burrows.", + "firmament.config.etherwarp-overlay": "Etherwarp Overlay", + "firmament.config.etherwarp-overlay.cube": "Cube", + "firmament.config.etherwarp-overlay.cube-colour": "Cube Color", + "firmament.config.etherwarp-overlay.cube-colour.description": "Choose the colour of the etherwarp target block.", + "firmament.config.etherwarp-overlay.cube.description": "Displays a full cube on the block", + "firmament.config.etherwarp-overlay.etherwarp-overlay": "Etherwarp Overlay", + "firmament.config.etherwarp-overlay.etherwarp-overlay.description": "Display an overlay that tells you what block you will warp to.", + "firmament.config.etherwarp-overlay.only-show-while-sneaking": "Only show while sneaking", + "firmament.config.etherwarp-overlay.only-show-while-sneaking.description": "Displays the Etherwarp overlay only while sneaking.", + "firmament.config.etherwarp-overlay.wireframe": "Outline", + "firmament.config.etherwarp-overlay.wireframe.description": "Displays a full outline on the block", + "firmament.config.fairy-souls": "Fairy Souls", + "firmament.config.fairy-souls.reset": "Reset Collected Fairy Souls", + "firmament.config.fairy-souls.reset.description": "Reset all collected fairy souls, allowing you to restart from null.", + "firmament.config.fairy-souls.show": "Show Fairy Soul Waypoints", + "firmament.config.fairy-souls.show.description": "Show unclaimed Fairy Soul waypoints in the world you are currently in.", + "firmament.config.fishing-warning": "Fishing Warning", + "firmament.config.fishing-warning.display-warning": "Display a warning when you are about to hook a fish", + "firmament.config.fishing-warning.highlight-wake-chain": "Highlight fishing particles", + "firmament.config.fixes": "Fixes", + "firmament.config.fixes.auto-sprint": "Auto Sprint", + "firmament.config.fixes.auto-sprint-hud": "Sprint State Hud", + "firmament.config.fixes.auto-sprint-hud.description": "Show your current sprint state on your screen. Only visible if no auto sprint keybind is set.", + "firmament.config.fixes.auto-sprint-keybinding": "Auto Sprint KeyBinding", + "firmament.config.fixes.auto-sprint-keybinding.description": "Toggle auto sprint via this keybinding.", + "firmament.config.fixes.auto-sprint-underwater": "Sprint Under Water", + "firmament.config.fixes.auto-sprint-underwater.description": "Also Toggle Sprint under water. Sprinting under water puts you in the swimming animation which changes your camera and hitbox, which can be confusing if you stop and start moving a lot.", + "firmament.config.fixes.auto-sprint.description": "This is different from vanilla sprint in the way that it only marks the keybinding pressed for the first tick of walking.", + "firmament.config.fixes.disable-hurt-cam": "No Hurt Cam", + "firmament.config.fixes.disable-hurt-cam.description": "Disable the damage screen shake animation.", + "firmament.config.fixes.hide-mob-effects": "Hide Potion Effects", + "firmament.config.fixes.hide-mob-effects.description": "Hide Potion effects on the right side of your player inventory.", + "firmament.config.fixes.hide-off-hand": "No Off Hand", + "firmament.config.fixes.hide-off-hand.description": "Remove the recipe slot from your inventory", + "firmament.config.fixes.hide-potion-effects-hud": "Hide Potion Effects HUD", + "firmament.config.fixes.hide-potion-effects-hud.description": "Hides the potion effects HUD in the top right.", + "firmament.config.fixes.hide-recipe-book": "No Recipe Book", + "firmament.config.fixes.hide-recipe-book.description": "Remove the recipe book from your inventory", + "firmament.config.fixes.hide-slot-highlights": "Hide Slot Highlights", + "firmament.config.fixes.hide-slot-highlights.description": "Hide slot highlights for items with disabled tooltip. This makes /sbmenu look nicer with smooth texture packs.", + "firmament.config.fixes.peek-chat": "Peek Chat", + "firmament.config.fixes.peek-chat.description": "Hold this keybinding to view the chat as if you have it opened, but while still being able to control your character.", + "firmament.config.fixes.player-skins": "Fix unsigned Player Skins", + "firmament.config.fixes.player-skins.description": "Mark all player skins as signed, preventing console spam, and some rendering issues.", + "firmament.config.hud": "HUD", + "firmament.config.hud.day-count": "Day Count", + "firmament.config.hud.day-count-hud": "Day Count HUD", + "firmament.config.hud.day-count-hud.description": "Shows day.", + "firmament.config.hud.day-count-hud.display": "Day: %s", + "firmament.config.hud.day-count.description": "A HUD showing current day.", + "firmament.config.hud.fps-count": "FPS Count", + "firmament.config.hud.fps-count-hud": "FPS Count HUD", + "firmament.config.hud.fps-count-hud.description": "Shows FPS.", + "firmament.config.hud.fps-count-hud.display": "FPS: %s", + "firmament.config.hud.fps-count.description": "A HUD showing current FPS.", + "firmament.config.hud.ping-count": "Ping Count", + "firmament.config.hud.ping-count-hud": "Ping Count HUD", + "firmament.config.hud.ping-count-hud.description": "Shows Ping.", + "firmament.config.hud.ping-count-hud.display": "Ping %s", + "firmament.config.hud.ping-count.description": "A HUD showing current Ping.", + "firmament.config.inventory-buttons-config": "Inventory Buttons", + "firmament.config.inventory-buttons-config.hover-text": "Hover Tooltip", + "firmament.config.inventory-buttons-config.hover-text.description": "Hovering over inventory buttons will show the command they run.", + "firmament.config.inventory-buttons-config.only-inv": "Inventory Only", + "firmament.config.inventory-buttons-config.only-inv.description": "Only shows buttons while in the inventory", + "firmament.config.inventory-buttons-config.open-editor": "Open Editor", + "firmament.config.inventory-buttons-config.open-editor.description": "Click anywhere to create a new inventory button or to edit one. Hold SHIFT to grid align.", + "firmament.config.item-hotkeys": "Item Hotkeys", + "firmament.config.item-hotkeys.global-trade-interface": "Search on Bazaar/AH", + "firmament.config.item-hotkeys.global-trade-interface.description": "Press this button to search the hovered item on the bazaar or auction house.", + "firmament.config.item-rarity-cosmetics": "Item Rarity Cosmetics", + "firmament.config.item-rarity-cosmetics.background": "Slot Background Rarity", + "firmament.config.item-rarity-cosmetics.background-hotbar": "Hotbar Background Rarity", + "firmament.config.item-rarity-cosmetics.background-hotbar.description": "Show item rarity background in the hotbar.", + "firmament.config.item-rarity-cosmetics.background.description": "Show a background behind each item, depending on its rarity.", + "firmament.config.jade-integration": "Jade / WAILA", + "firmament.config.jade-integration.blocks": "Enable Custom Blocks", + "firmament.config.jade-integration.blocks.description": "Show custom block descriptions and hardness levels in Jade.", + "firmament.config.jade-integration.progress": "Enable Custom Mining Progress", + "firmament.config.jade-integration.progress.description": "Show the custom mining progress in Jade, when in a world with mining fatigue.", + "firmament.config.junk-highlighter": "Junk Highlighter", + "firmament.config.junk-highlighter.description": "Highlight items using regex to search for items in your inventory", + "firmament.config.junk-highlighter.highlight": "Highlight Keybind", + "firmament.config.junk-highlighter.highlight.description": "Highlight found items when this keybind is held", + "firmament.config.junk-highlighter.regex": "Search Regex", + "firmament.config.junk-highlighter.regex.description": "The RegEx (Regular Expression) to use when searching", + "firmament.config.lore-timers": "Item Timestamps", + "firmament.config.lore-timers.format": "Time Format", + "firmament.config.lore-timers.format.choice.american": "§9Ame§cri§fcan", + "firmament.config.lore-timers.format.choice.local": "System Time Format", + "firmament.config.lore-timers.format.choice.rfc": "RFC", + "firmament.config.lore-timers.format.choice.rfcprecise": "RFC (Milliseconds)", + "firmament.config.lore-timers.format.choice.socialist": "European-ish", + "firmament.config.lore-timers.format.description": "Choose the time format in which resolved timers are displayed.", + "firmament.config.lore-timers.show": "Show Lore Timers", + "firmament.config.lore-timers.show-creation": "Show Creation", + "firmament.config.lore-timers.show-creation.description": "Shows the creation or craft timestamp of the item. Sometimes this timestamp is retained when upgrading an item, so it isn't necessarily the craft time of this specific item, but rather one of its components.", + "firmament.config.lore-timers.show.description": "Shows when a timer in a lore (such as interest, auction duration) would end.", + "firmament.config.party-commands": "Party Commands", + "firmament.config.party-commands.cooldown": "Cooldown", + "firmament.config.party-commands.cooldown.description": "Prevent people from spamming commands with a delay between party commands.", + "firmament.config.party-commands.enable": "Enable Party Commands", + "firmament.config.party-commands.enable.description": "Allow people in your party to use commands like !warp, !coords, !ptme and so on. See /firm partycommands for a list", + "firmament.config.party-commands.ignore-own": "Ignore Own Messages", + "firmament.config.party-commands.ignore-own.description": "Prevent your own messages from triggering party commands", + "firmament.config.pets": "Pets", + "firmament.config.pets.highlight-pet": "Highlight active pet", + "firmament.config.pets.highlight-pet.description": "Highlight your currently selected pet in the /pets menu.", + "firmament.config.pets.pet-overlay": "Pet Info", + "firmament.config.pets.pet-overlay-hud": "Pet Info Hud", + "firmament.config.pets.pet-overlay-hud.description": "A HUD showing current active pet and the pet exp.", + "firmament.config.pets.pet-overlay.description": "Shows current active pet and pet exp on screen.", + "firmament.config.pickaxe-info": "Pickaxes & Drills", + "firmament.config.pickaxe-info.ability-cooldown": "Pickaxe Ability Cooldown", + "firmament.config.pickaxe-info.ability-cooldown-toast": "Pickaxe Ability Ready Toast", + "firmament.config.pickaxe-info.ability-cooldown-toast.description": "Shows a toast when your pickaxe ability is ready.", + "firmament.config.pickaxe-info.ability-cooldown.description": "Show a cooldown on your cross-hair for your pickaxe ability.", + "firmament.config.pickaxe-info.ability-scale": "Ability Cooldown Scale", + "firmament.config.pickaxe-info.ability-scale.description": "Resize the cooldown around your cross-hair for your pickaxe ability.", + "firmament.config.pickaxe-info.block-on-dynamic": "Block on Private Island", + "firmament.config.pickaxe-info.block-on-dynamic.choice.always": "Always Block", + "firmament.config.pickaxe-info.block-on-dynamic.choice.never": "Never Block", + "firmament.config.pickaxe-info.block-on-dynamic.choice.only_destructive": "Only with dangerous", + "firmament.config.pickaxe-info.block-on-dynamic.description": "Block pickaxe abilities on private islands by preventing you from right clicking.", + "firmament.config.pickaxe-info.disable-in-dungeons": "Disable cross-hair cooldown in Dungeons", + "firmament.config.pickaxe-info.disable-in-dungeons.description": "Disables the cooldown around your cross-hair while in Dungeons.", + "firmament.config.pickaxe-info.fuel-bar": "Drill Fuel Durability Bar", + "firmament.config.pickaxe-info.fuel-bar.description": "Replace the item durability bar of your drills with one that shows the remaining fuel.", + "firmament.config.power-user": "Power Users", + "firmament.config.power-user.copy-item-id": "Copy SkyBlock Id", + "firmament.config.power-user.copy-item-id.description": "Press this button to copy the NEU repo SkyBlock id. This is not the raw id, but instead contains some extra transformations for things like runes, pets and enchant books.", + "firmament.config.power-user.copy-item-stack": "Copy ItemStack", + "firmament.config.power-user.copy-item-stack.description": "Copy the entire item stack metadata. This can be used in tests to recreate the item in code.", + "firmament.config.power-user.copy-lore": "Copy Name + Lore", + "firmament.config.power-user.copy-lore.description": "Copy the items name and lore as json encoded text", + "firmament.config.power-user.copy-nbt-data": "Copy ExtraAttributes data", + "firmament.config.power-user.copy-nbt-data.description": "Copy only the ExtraAttributes, so the hypixel specific item data.", + "firmament.config.power-user.copy-skull-texture": "Copy Placed Skull Id", + "firmament.config.power-user.copy-skull-texture.description": "Copy the texture location that can be used to re-texture the skull under your cross-hair.", + "firmament.config.power-user.copy-texture-pack-id": "Copy Texture Pack Id", + "firmament.config.power-user.copy-texture-pack-id.description": "Copy the texture pack id that is used for the item stack under your cursor.", + "firmament.config.power-user.copy-title": "Copy Inventory Title", + "firmament.config.power-user.copy-title.description": "Copies Inventory and Screen Titles", + "firmament.config.power-user.dont-highlight-semicolon-items": "Remove Semicolon Highlight", + "firmament.config.power-user.dont-highlight-semicolon-items.description": "Removes the highlight from items that contain a semicolon e.g Pets or Enchanted Books.", + "firmament.config.power-user.entity-data": "Show Entity Data", + "firmament.config.power-user.entity-data.description": "Print out information about the entity under your cross-hair.", + "firmament.config.power-user.export-item-stack": "Export Item Stack", + "firmament.config.power-user.export-item-stack.description": "Exports the hovered item to the repo data folder", + "firmament.config.power-user.export-npc-location": "Export NPC Location", + "firmament.config.power-user.export-npc-location.description": "Export the NPC's location to the repo data", + "firmament.config.power-user.export-recipe": "Export Recipe Data", + "firmament.config.power-user.export-recipe.description": "Export Recipe Data to the repo data", + "firmament.config.power-user.highlight-non-overlay": "Highlight Missing Items", + "firmament.config.power-user.highlight-non-overlay.description": "Highlights items that don't exist in the repo.", + "firmament.config.power-user.show-item-id": "Show SkyBlock Ids", + "firmament.config.power-user.show-item-id.description": "Show the SkyBlock id of items underneath them.", + "firmament.config.price-data": "Price Data", + "firmament.config.price-data.avg-lowest-bin-days": "AVG Lowest Bin Days", + "firmament.config.price-data.avg-lowest-bin-days.choice.off": "Off", + "firmament.config.price-data.avg-lowest-bin-days.choice.onedayavglowestbin": "1 Day", + "firmament.config.price-data.avg-lowest-bin-days.choice.sevendayavglowestbin": "7 Days", + "firmament.config.price-data.avg-lowest-bin-days.choice.threedayavglowestbin": "3 Days", + "firmament.config.price-data.avg-lowest-bin-days.description": "Select if and for how long the AVG Lowest BIN should show.", + "firmament.config.price-data.enable-always": "Enable Item Price", + "firmament.config.price-data.enable-always.description": "Show item auction/bazaar prices on SkyBlock items", + "firmament.config.price-data.enable-keybind": "Enable only with Keybinding", + "firmament.config.price-data.enable-keybind.description": "Only show auction/bazaar prices when holding this keybinding. Unbind to always show.", + "firmament.config.price-data.stack-size-keybind": "Stack Size Multiplier Keybinding", + "firmament.config.price-data.stack-size-keybind.description": "Press this key while hovering over an item to show its price multiplied by the number of items you have.", + "firmament.config.pristine-profit": "Pristine Profit Tracker", + "firmament.config.pristine-profit.fine-gemstones": "Use Fine Gemstones", + "firmament.config.pristine-profit.fine-gemstones.description": "Use the (more stable) price of fine gemstones, instead of flawed gemstones.", + "firmament.config.pristine-profit.position": "Pristine Profit HUD", + "firmament.config.pristine-profit.position.description": "Edit the pristine profit hud location.", + "firmament.config.pristine-profit.timeout": "Timeout (0 = disabled)", + "firmament.config.pristine-profit.timeout.description": "Track the profit you make from pristine gemstones while mining. Set to 0 seconds to disable the HUD.", + "firmament.config.quick-commands": "Quick Commands", + "firmament.config.quick-commands.dh": "Enable /dh", + "firmament.config.quick-commands.dh.description": "Warps you to the dungeon hub.", + "firmament.config.quick-commands.join": "Enable /join", + "firmament.config.quick-commands.join.description": "Join various types of instances like dungeons using short hands like /join f1, /join k1, /join m7", + "firmament.config.repo": "Firmament Repo Settings", + "firmament.config.repo.autoUpdate": "Auto Update", + "firmament.config.repo.autoUpdate.description": "Automatically download new items for the item list on every startup.", + "firmament.config.repo.branch": "Repo Branch", + "firmament.config.repo.branch.description": "Git Branch to pull item data from.", + "firmament.config.repo.branch.hint": "dangerous", + "firmament.config.repo.disable-item-groups": "Disable Item Groups", + "firmament.config.repo.disable-item-groups.description": "Disabling item groups can increase performance, but will no longer collect similar items (like minions, enchantments) together.", + "firmament.config.repo.enable-rei": "Enable REI", + "firmament.config.repo.enable-rei.description": "REI is required for viewing Firmaments item list. If you want to use another item list provider like SkyBlockers, you can turn it off here. Without other mods this will make you revert back to the vanilla item list.", + "firmament.config.repo.enable-super-craft": "Always use Super Craft", + "firmament.config.repo.enable-super-craft.description": "Always use super craft when clicking the craft button in REI, instead of just when holding shift.", + "firmament.config.repo.perfect-renders": "Perfect Render", + "firmament.config.repo.perfect-renders.choice.nothing": "Broken (Fastest)", + "firmament.config.repo.perfect-renders.choice.render": "Fixed Visual (Fast)", + "firmament.config.repo.perfect-renders.choice.render_and_text": "Perfect (Slowest)", + "firmament.config.repo.perfect-renders.description": "Speed up item list loading by allowing items to be loaded in partially incorrectly at first. They will be corrected down the line when the background reload completes.", + "firmament.config.repo.redownload": "Redownload Item List", + "firmament.config.repo.redownload.description": "Force re-download the item list. This is automatically done on restart.", + "firmament.config.repo.reload": "Reload Item List", + "firmament.config.repo.reload.description": "Force reload the item list. This will not download the item list again.", + "firmament.config.repo.reponame": "Repo Name", + "firmament.config.repo.reponame.description": "The GitHub repository name to pull item data from.", + "firmament.config.repo.reponame.hint": "NotEnoughUpdates-REPO", + "firmament.config.repo.reset": "Reset", + "firmament.config.repo.reset.description": "Reset the Git download location.", + "firmament.config.repo.username": "Repo Username", + "firmament.config.repo.username.description": "The GitHub repository organization to pull item data from.", + "firmament.config.repo.username.hint": "NotEnoughUpdates", + "firmament.config.repo.warn-for-missing-item-list-mod": "Warn for missing item list", + "firmament.config.repo.warn-for-missing-item-list-mod.description": "Warn if there is no compatible item list mod, like REI, installed.", + "firmament.config.save-cursor-position": "Save Cursor Position", + "firmament.config.save-cursor-position.enable": "Enable", + "firmament.config.save-cursor-position.enable.description": "Save your cursor position when switching GUIs.", + "firmament.config.save-cursor-position.tolerance": "Tolerance", + "firmament.config.save-cursor-position.tolerance.description": "Select how long your cursor position last between GUIs before resetting back to the middle of the screen.", + "firmament.config.slot-locking": "Slot Locking", + "firmament.config.slot-locking.bind": "Bind Slot", + "firmament.config.slot-locking.bind-render": "Show Slot Bindings", + "firmament.config.slot-locking.bind-render.choice.everything": "Always", + "firmament.config.slot-locking.bind-render.choice.nothing": "Only when hovered", + "firmament.config.slot-locking.bind-render.choice.only_boxes": "Only boxes", + "firmament.config.slot-locking.bind-render.description": "Disable rendering of the slot binding lines (or all of the slot binding rendering), unless the relevant slot is being hovered.", + "firmament.config.slot-locking.bind.description": "Bind a hotbar slot to another slot. This allows quick switching between the slots by shift clicking on either slot.", + "firmament.config.slot-locking.drop-in-dungeons": "Allow Dungeon Abilities", + "firmament.config.slot-locking.drop-in-dungeons.description": "Allow dropping items in dungeons, to use your dungeon ultimate abilities.", + "firmament.config.slot-locking.hunting-box": "Protect Hunting Box", + "firmament.config.slot-locking.hunting-box.description": "The Hunting Box frequently changes its UUID, and as such cannot be reliably protected using UUID locking. Instead this option can be used to block from dropping any Hunting Box.", + "firmament.config.slot-locking.lock": "Lock Slot", + "firmament.config.slot-locking.lock-uuid": "Lock UUID (Lock Item)", + "firmament.config.slot-locking.lock-uuid.description": "Lock a SkyBlock item by it's UUID. This blocks a specific item from being dropped/sold, but still allows moving it around.", + "firmament.config.slot-locking.lock.description": "Lock a slot, preventing any item from being moved from, dropped from, or placed into this slot.", + "firmament.config.slot-locking.multi-bind": "Allow Multi Binding", + "firmament.config.slot-locking.multi-bind.description": "Allow binding the same hotbar slot to multiple inventory slots.", + "firmament.config.slot-locking.require-quick-move": "Require Shift-Click for Bound Slots", + "firmament.config.slot-locking.require-quick-move.description": "If turned off, allows to switch between bound slots without holding shift.", + "firmament.config.storage-overlay": "Storage Overlay", + "firmament.config.storage-overlay.always-replace": "Always Open Overlay", + "firmament.config.storage-overlay.always-replace.description": "Always replace the ender chest with Firmament's storage overlay.", + "firmament.config.storage-overlay.block-item-scrolling": "Block Scrolling on Items", + "firmament.config.storage-overlay.block-item-scrolling.description": "Disables scrolling the storage overlay screen while you are hovering over an item. Useful if you have a tooltip scrolling mod.", + "firmament.config.storage-overlay.height": "Storage Height", + "firmament.config.storage-overlay.height.description": "The height of the scrollable storage panel.", + "firmament.config.storage-overlay.highlight-search-results": "Highlight Search Results", + "firmament.config.storage-overlay.highlight-search-results-colour": "Highlight Search Colour", + "firmament.config.storage-overlay.highlight-search-results-colour.description": "Change the colour of the highlighted search result.", + "firmament.config.storage-overlay.highlight-search-results.description": "Highlight the search results in the ender chest overlay.", + "firmament.config.storage-overlay.inverse-scroll": "Invert Scroll", + "firmament.config.storage-overlay.inverse-scroll.description": "Invert the mouse wheel scrolling in Firmament's storage overlay.", + "firmament.config.storage-overlay.margin": "Margin", + "firmament.config.storage-overlay.margin.description": "Margin inside of the storage overview.", + "firmament.config.storage-overlay.outline-active-page": "Outline Active Page", + "firmament.config.storage-overlay.outline-active-page-colour": "Outline Colour", + "firmament.config.storage-overlay.outline-active-page-colour.description": "Change the colour of the border around your selected storage page.", + "firmament.config.storage-overlay.outline-active-page.description": "Put a border around the selected storage page in the storage overlay.", + "firmament.config.storage-overlay.padding": "Padding", + "firmament.config.storage-overlay.padding.description": "Padding inside of the storage overview.", + "firmament.config.storage-overlay.retain-scroll": "Retain Scroll Position", + "firmament.config.storage-overlay.retain-scroll.description": "Retain scroll position when closing storage overlay and overview.", + "firmament.config.storage-overlay.rows": "Columns", + "firmament.config.storage-overlay.rows.description": "Max columns used by the storage overlay and overview.", + "firmament.config.storage-overlay.scroll-speed": "Scroll Speed", + "firmament.config.storage-overlay.scroll-speed.description": "Scroll speed inside of the storage overlay and overview.", + "firmament.config.wardrobe-keybinds": "Wardrobe Keybinds", + "firmament.config.wardrobe-keybinds.change-page": "Change Page", + "firmament.config.wardrobe-keybinds.change-page.description": "Changes the active page", + "firmament.config.wardrobe-keybinds.next-page": "Next Page", + "firmament.config.wardrobe-keybinds.next-page.description": "Goes to the next page", + "firmament.config.wardrobe-keybinds.previous-page": "Previous Page", + "firmament.config.wardrobe-keybinds.previous-page.description": "Goes to the previous page", + "firmament.config.wardrobe-keybinds.slot-1": "Slot 1", + "firmament.config.wardrobe-keybinds.slot-1.description": "Keybind to toggle the first set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-2": "Slot 2", + "firmament.config.wardrobe-keybinds.slot-2.description": "Keybind to toggle the second set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-3": "Slot 3", + "firmament.config.wardrobe-keybinds.slot-3.description": "Keybind to toggle the third set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-4": "Slot 4", + "firmament.config.wardrobe-keybinds.slot-4.description": "Keybind to toggle the fourth set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-5": "Slot 5", + "firmament.config.wardrobe-keybinds.slot-5.description": "Keybind to toggle the fifth set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-6": "Slot 6", + "firmament.config.wardrobe-keybinds.slot-6.description": "Keybind to toggle the sixth set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-7": "Slot 7", + "firmament.config.wardrobe-keybinds.slot-7.description": "Keybind to toggle the seventh set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-8": "Slot 8", + "firmament.config.wardrobe-keybinds.slot-8.description": "Keybind to toggle the eighth set in your wardrobe", + "firmament.config.wardrobe-keybinds.slot-9": "Slot 9", + "firmament.config.wardrobe-keybinds.slot-9.description": "Keybind to toggle the ninth set in your wardrobe", + "firmament.config.wardrobe-keybinds.wardrobe-keybinds": "Keybinds for your wardrobe", + "firmament.config.wardrobe-keybinds.wardrobe-keybinds.description": "Lets you use your number keys to quickly change your wardrobe", + "firmament.config.waypoints": "Waypoints", + "firmament.config.waypoints.reset-order-on-swap": "Reset Ordered Waypoints On Hop", + "firmament.config.waypoints.reset-order-on-swap.description": "Resets Ordered Waypoint progress after swapping to another world.", + "firmament.config.waypoints.show-index": "Show ordered waypoint indexes", + "firmament.config.waypoints.show-index.description": "Show the number of an ordered waypoint in the world.", + "firmament.config.waypoints.skip-to-nearest": "Allow skipping waypoints", + "firmament.config.waypoints.skip-to-nearest.description": "Allow skipping waypoints in an ordered list. If disabled you will need to walk to the next point, before being allowed to the next one after.", + "firmament.config.waypoints.temp-waypoint-duration": "Temporary Waypoint Duration", + "firmament.config.waypoints.temp-waypoint-duration.description": "Display waypoints sent by other players using /firm sendcoords in the world.", + "firmament.debug.skyblockid": "SkyBlock ID: %s", + "firmament.debug.skyblockid.copy": "Click to copy SkyBlock ID", + "firmament.dev.resourcerebuild.done": "Gradle resource rebuild done in %s", + "firmament.dev.resourcerebuild.start": "Invoking gradle resource rebuild (./gradlew :processResources)", + "firmament.download": "Click here to download %s", + "firmament.download.already": " (Already downloaded)", + "firmament.fixes.auto-sprint.not-sprinting": "Not Sprinting", + "firmament.fixes.auto-sprint.on": "Sprint toggled", + "firmament.fixes.auto-sprint.sprinting": "Sprinting", + "firmament.hotmpreset.copied": "Collected all HOTM perks to clipboard. Use /firm importhotm to import.", + "firmament.hotmpreset.failedimport": "Could not find a HOTM perk preset in your clipboard. You can export your current HOTM perks with /firm exporthotm", + "firmament.hotmpreset.okayimport": "Imported a HOTM perk preset.", + "firmament.hotmpreset.openinghotm": "Opening /hotm menu for export.", + "firmament.hotmpreset.scrolled": "Just scrolled. Waiting on server to update items.", + "firmament.hotmpreset.scrollprompt": "We need to scroll! Please click anywhere to continue.", + "firmament.hud.edit": "Edit %s", + "firmament.inventory-buttons.all-warps-preset": "All Warps Preset", + "firmament.inventory-buttons.delete": "Hold L-CTRL and click to delete", + "firmament.inventory-buttons.import-failed": "One of your buttons could only be imported partially", + "firmament.inventory-buttons.info": "Hold SHIFT to grid align", + "firmament.inventory-buttons.load-preset": "Load Preset", + "firmament.inventory-buttons.reset": "Reset buttons", + "firmament.inventory-buttons.save-preset": "Save Preset", + "firmament.inventory-buttons.simple-preset": "Simple Preset", + "firmament.key.category": "Firmament", + "firmament.keybinding.external": "%s", + "firmament.modapi.event": "Received mod API event: %s", + "firmament.poweruser.entity.armor": "Entity Armor:", + "firmament.poweruser.entity.armor.item": " - %s", + "firmament.poweruser.entity.fail": "No entity found under cursor", + "firmament.poweruser.entity.name": "Entity Name: %s", + "firmament.poweruser.entity.passengers": "%s Passengers", + "firmament.poweruser.entity.position": "Position: %s", + "firmament.poweruser.entity.type": "Entity Type: %s", + "firmament.price": "Checking price for %s", + "firmament.price.bazaar": "Bazaar stats:", + "firmament.price.bazaar.buy.order": "Buy orders: %d", + "firmament.price.bazaar.buy.price": "Buy Price: %s", + "firmament.price.bazaar.productid": "Stock id: %s", + "firmament.price.bazaar.sell.order": "Sell orders: %d", + "firmament.price.bazaar.sell.price": "Sell Price: %s", + "firmament.price.lowestbin": "Lowest BIN: %s", + "firmament.pristine-profit.collection": "Collection: %s/h", + "firmament.pristine-profit.money": "Money: %s/h", + "firmament.pv.lookingup": "Looking up %s", + "firmament.pv.noplayer": "%s is not a Minecraft player", + "firmament.pv.noprofile": "%s has no SkyBlock profiles", + "firmament.pv.pets": "Pets", + "firmament.pv.skills": "Skills", + "firmament.pv.skills.alchemy": "Alchemy", + "firmament.pv.skills.carpentry": "Carpentry", + "firmament.pv.skills.combat": "Combat", + "firmament.pv.skills.enchanting": "Enchanting", + "firmament.pv.skills.farming": "Farming", + "firmament.pv.skills.fishing": "Fishing", + "firmament.pv.skills.foraging": "Foraging", + "firmament.pv.skills.mining": "Mining", + "firmament.pv.skills.rift": "Rift", + "firmament.pv.skills.runecrafting": "Runecrafting", + "firmament.pv.skills.social": "Social", + "firmament.pv.skills.taming": "Taming", + "firmament.pv.skills.total": "Total Exp: %s", + "firmament.quick-commands.join.explain": "Join a dungeon or kuudra floor by using commands like /join f1, /join m7, /join fe or /join khot", + "firmament.quick-commands.join.success": "Joining: %s", + "firmament.quick-commands.join.unknown": "Could not find instance for %s", + "firmament.quick-commands.join.unknown-catacombs": "Unknown catacombs floor %s", + "firmament.quick-commands.join.unknown-kuudra": "Unknown kuudra floor %s", + "firmament.recipe.forge.time": "Forging Time: %s", + "firmament.recipe.mobs.coins": "§eCoins: %s", + "firmament.recipe.mobs.combat": "§bCombat Experience: %s", + "firmament.recipe.mobs.drops": "§e§lDrop Chance: %s", + "firmament.recipe.mobs.exp": "§6Experience: %s", + "firmament.recipe.mobs.name": "§8[§7Lv %d§8] §c%s", + "firmament.recipe.mobs.name.nolevel": "§c%s", + "firmament.recipe.novanilla": "Hypixel cannot super craft vanilla recipes", + "firmament.reiwarning": "Firmament needs RoughlyEnoughItems to display its item list!", + "firmament.reiwarning.disable": "Click here to disable this warning", + "firmament.reiwarning.disabled": "Disabled the RoughlyEnoughItems warning. Keep in mind that you will not have an item list without REI.", + "firmament.repo.brokenitem": "Failed to render item: %s", + "firmament.repo.cache": "Recaching items", + "firmament.repo.reload.disk": "Reloading repository from disk. This may lag a bit.", + "firmament.repo.reload.network": "Trying to redownload the repository", + "firmament.sbinfo.gametype": "Locraw Gametype: %s", + "firmament.sbinfo.map": "Locraw Map: %s", + "firmament.sbinfo.mode": "Locraw Mode: %s", + "firmament.sbinfo.nolocraw": "No locraw data available", + "firmament.sbinfo.profile": "Current profile cutename: %s", + "firmament.sbinfo.server": "Locraw Server: %s", + "firmament.toggle.false": "Off", + "firmament.toggle.true": "On", + "firmament.tooltip.copied.lore": "Copied Name and Lore", + "firmament.tooltip.copied.modelid": "Copied Texture Id: %s", + "firmament.tooltip.copied.modelid.fail": "Failed to copy Texture Id", + "firmament.tooltip.copied.nbt": "Copied NBT data", + "firmament.tooltip.copied.skull": "Copied Skull Id: %s", + "firmament.tooltip.copied.skull-id": "Copied Skull Id: %s", + "firmament.tooltip.copied.skull-id.fail.no-profile": "Skull has no profile", + "firmament.tooltip.copied.skull-id.fail.no-skull": "That isn't a skull", + "firmament.tooltip.copied.skull-id.fail.no-texture": "Skull has no texture", + "firmament.tooltip.copied.skull.fail": "Failed to copy skull id.", + "firmament.tooltip.copied.skyblockid": "Copied SkyBlock Id: %s", + "firmament.tooltip.copied.skyblockid.fail": "Failed to copy SkyBlock Id", + "firmament.tooltip.copied.stack": "Copied ItemStack", + "firmament.tooltip.skyblockid": "SkyBlock Id: %s", + "firmament.ursa.debugrequest.result": "Ursa request succeeded: %s", + "firmament.ursa.debugrequest.start": "Ursa request launched", + "firmament.warp-util.already-close": "Already closer to destination than /warp %s", + "firmament.warp-util.attempting-to-warp": "Trying to warp to /warp %s", + "firmament.warp-util.clear-excluded": "Marked all /warp commands as potentially available.", + "firmament.warp-util.mark-excluded": "Firmament: Tried to warp to %s, but it was not unlocked. I will avoid warping there again.", + "firmament.warp-util.no-warp-found": "Could not find an unlocked warp in %s", + "firmament.waypoint.temporary": "Temporary Waypoint: %s", + "zzzzzzzzz.lastentry": "Here so every real firmament entry has a trailing ," +} diff --git a/translations/extra.json b/translations/extra.json new file mode 100644 index 0000000..cb21fc9 --- /dev/null +++ b/translations/extra.json @@ -0,0 +1,6 @@ +{ + // These are require by jade, but i don't think they are actually rendered in game. + // Jade throws exceptions if they are not present however. + "config.jade.plugin_firmament.toolprovider": "Firmament Tool Provider", + "config.jade.plugin_firmament.custom_mining_hardness": "Firmament Mining Hardness" +} diff --git a/translations/extra_zh_cn.json b/translations/extra_zh_cn.json new file mode 100644 index 0000000..43abe89 --- /dev/null +++ b/translations/extra_zh_cn.json @@ -0,0 +1,6 @@ +{ + // These are require by jade, but i don't think they are actually rendered in game. + // Jade throws exceptions if they are not present however. + "config.jade.plugin_firmament.toolprovider": "Firmament工具æä¾›è€…", + "config.jade.plugin_firmament.custom_mining_hardness": "Firmament挖掘硬度" +} diff --git a/translations/zh_cn.json b/translations/zh_cn.json new file mode 100644 index 0000000..5759b64 --- /dev/null +++ b/translations/zh_cn.json @@ -0,0 +1,552 @@ +{ + "firmament.carnival.tutorial.minesweeper": "§eç‚¹å‡»è¿™é‡ŒæŸ¥çœ‹è¿™ä¸ªå°æ¸¸æˆçš„æ•™ç¨‹ï¼", + "firmament.command.toggle.no-config-found": "找ä¸åˆ°é…ç½®%s", + "firmament.command.toggle.no-property-found": "找ä¸åˆ°å±žæ€§%s", + "firmament.command.toggle.not-a-toggle": "属性%s䏿˜¯ä¸€ä¸ªå¼€å…³", + "firmament.command.toggle.toggled": "已切æ¢%s/%s%s", + "firmament.command.waypoint.added": "已添加路径点%s%s%s。", + "firmament.command.waypoint.clear": "已清除路径点。", + "firmament.command.waypoint.import": "从剪贴æ¿å¯¼å…¥äº†%s个路径点。", + "firmament.command.waypoint.ordered.toggle.false": "å·²ç¦ç”¨æœ‰åºè·¯å¾„点", + "firmament.command.waypoint.ordered.toggle.true": "å·²å¯ç”¨æœ‰åºè·¯å¾„点", + "firmament.command.waypoint.remove": "已移除路径点%s。其他路径点的索引å¯èƒ½ä¼šå˜åŒ–。", + "firmament.command.waypoint.remove.error": "索引对应的路径点ä¸å­˜åœ¨ï¼Œæ— æ³•删除。", + "firmament.command.waypoint.skip": "跳过了1个路径点", + "firmament.command.waypoint.skip.error": "æ— æ³•è·³è¿‡è·¯å¾„ç‚¹ã€‚æ˜¯ä¸æ˜¯æ²¡æœ‰ä½¿ç”¨æœ‰åºè·¯å¾„点或没有加载了数æ®ï¼Ÿ", + "firmament.config.all-configs": "- 所有é…ç½® -", + "firmament.config.anniversary": "周年活动功能", + "firmament.config.anniversary.pig-hud": "闪亮猪HUD", + "firmament.config.anniversary.pig-hud.description": "一个显示闪亮猪掉è½å¥–励的HUD", + "firmament.config.anniversary.shiny-pigs": "闪亮猪追踪器", + "firmament.config.anniversary.shiny-pigs.description": "è¿½è¸ªé—ªäº®çŒªçš„å¥–åŠ±ï¼Œå¹¶æ˜¾ç¤ºæŠ“çŒªçš„é™æ—¶ã€‚", + "firmament.config.auto-completions": "Hypixel命令优化", + "firmament.config.auto-completions.warp-complete": "自动补全/warp", + "firmament.config.auto-completions.warp-complete.description": "在èŠå¤©ä¸­è‡ªåŠ¨è¡¥å…¨warp目的地。这å¯èƒ½åŒ…括你尚未解é”的地点。", + "firmament.config.auto-completions.warp-is": "å°†/warp isé‡å®šå‘到/warp island", + "firmament.config.auto-completions.warp-is.description": "å°†/warp isé‡å®šå‘到/warp island,因为hypixelä¸è¯†åˆ«/warp is为warp目的地。", + "firmament.config.block-zapper-overlay": "Block Zapper Overlay", + "firmament.config.block-zapper-overlay.block-zapper-overlay": "Block Zapper Overlay", + "firmament.config.block-zapper-overlay.block-zapper-overlay.description": "Shows what blocks will be zapped", + "firmament.config.block-zapper-overlay.color": "Colour", + "firmament.config.block-zapper-overlay.color.description": "The color that the blocks will be highlighted in", + "firmament.config.block-zapper-overlay.undo-key": "Undo Keybind", + "firmament.config.block-zapper-overlay.undo-key.description": "Keybind to undo your zap", + "firmament.config.bonemerang-overlay": "骨回旋镖覆盖层", + "firmament.config.bonemerang-overlay.bonemerang-overlay": "骨回旋镖覆盖层", + "firmament.config.bonemerang-overlay.bonemerang-overlay-hud": "骨回旋镖覆盖层HUD", + "firmament.config.bonemerang-overlay.bonemerang-overlay-hud.description": "显示你的骨回旋镖将击中多少目标", + "firmament.config.bonemerang-overlay.bonemerang-overlay.description": "显示骨回旋镖的信æ¯ã€‚", + "firmament.config.bonemerang-overlay.bonemerang-overlay.display": "骨回旋镖目标:%s", + "firmament.config.bonemerang-overlay.highlight-hit-entities": "高亮目标实体", + "firmament.config.bonemerang-overlay.highlight-hit-entities.description": "高亮将被击中的实体", + "firmament.config.carnival": "嘉年åŽåŠŸèƒ½", + "firmament.config.carnival.bombs-solver": "扫雷助手", + "firmament.config.carnival.bombs-solver.description": "在扫雷中显示æ¯ä¸ªæ–¹å—周围的炸弹。", + "firmament.config.carnival.tutorials": "教程æé†’", + "firmament.config.carnival.tutorials.description": "æ¯æ¬¡å¼€å§‹Firmamentæä¾›äº†æ•™ç¨‹çš„æ¸¸æˆæ—¶ï¼Œæ˜¾ç¤ºä¸€ä¸ªæ•™ç¨‹æç¤ºã€‚", + "firmament.config.category.chat": "èŠå¤©", + "firmament.config.category.chat.description": "èŠå¤©ç›¸å…³åŠŸèƒ½", + "firmament.config.category.dev": "å¼€å‘与调试", + "firmament.config.category.dev.description": "纹ç†åŒ…å¼€å‘者和程åºå‘˜ä½¿ç”¨çš„设置", + "firmament.config.category.events": "活动", + "firmament.config.category.events.description": "å„ç§æ¸¸æˆæ´»åŠ¨çš„è®¾ç½®", + "firmament.config.category.garden": "花园", + "firmament.config.category.garden.description": "花园相关功能", + "firmament.config.category.integrations": "è”动与纹ç†", + "firmament.config.category.integrations.description": "与其他模组和纹ç†åŒ…çš„è”动", + "firmament.config.category.inventory": "ç‰©å“æ ", + "firmament.config.category.inventory.description": "ç‰©å“æ ï¼Œç®±å­å’Œå„UI功能", + "firmament.config.category.items": "物å“", + "firmament.config.category.items.description": "物å“相关功能", + "firmament.config.category.meta": "元数æ®ä¸ŽFirmament", + "firmament.config.category.meta.description": "Firmament和数æ®ä»“库的设置", + "firmament.config.category.mining": "挖矿", + "firmament.config.category.mining.description": "挖矿相关功能", + "firmament.config.category.misc": "æ‚项", + "firmament.config.category.misc.description": "一些æ‚项功能", + "firmament.config.centuryraffle": "世纪抽奖", + "firmament.config.centuryraffle.highlight-cake-players": "高亮队ä¼ä¸­çš„玩家", + "firmament.config.centuryraffle.highlight-cake-players.description": "高亮å¯ä»¥èµ ä¸Žæ‰‹æŒä¸–纪蛋糕片的玩家", + "firmament.config.chat-links": "èŠå¤©é“¾æŽ¥", + "firmament.config.chat-links.allow-all-hosts": "å…è®¸æ‰€æœ‰å›¾ç‰‡æ¥æº", + "firmament.config.chat-links.allow-all-hosts.description": "å…è®¸æ˜¾ç¤ºä»»ä½•æ¥æºçš„图片。", + "firmament.config.chat-links.allowed-hosts": "å…è®¸çš„å›¾ç‰‡æ¥æº", + "firmament.config.chat-links.allowed-hosts.description": "防止你从其他æœåŠ¡å™¨è¯·æ±‚å›¾ç‰‡ï¼Œä»¥é˜²æ­¢ä½ çš„IP泄露。", + "firmament.config.chat-links.image-enabled": "å¯ç”¨å›¾ç‰‡é¢„览", + "firmament.config.chat-links.image-enabled.description": "在èŠå¤©ä¸­å°†é¼ æ ‡æ‚¬åœåœ¨é“¾æŽ¥ä¸Šæ—¶æ˜¾ç¤ºå›¾ç‰‡é¢„览", + "firmament.config.chat-links.links-enabled": "å¯ç”¨å¯ç‚¹å‡»é“¾æŽ¥", + "firmament.config.chat-links.links-enabled.description": "使èŠå¤©ä¸­çš„链接å¯ç‚¹å‡»", + "firmament.config.chat-links.position": "èŠå¤©å›¾ç‰‡é¢„览", + "firmament.config.chat-links.position.description": "编辑图片显示ä½ç½®", + "firmament.config.commissions": "委托任务", + "firmament.config.commissions.highlight-completed": "高亮已完æˆ", + "firmament.config.commissions.highlight-completed.description": "在委托èœå•中高亮已完æˆçš„委托任务", + "firmament.config.compatibility": "兼容功能", + "firmament.config.compatibility.explosion-enabled": "接管爆炸粒å­", + "firmament.config.compatibility.explosion-enabled.description": "接管爆炸粒å­çš„æ¸²æŸ“。", + "firmament.config.compatibility.explosion-power": "增强爆炸å¨åŠ›", + "firmament.config.compatibility.explosion-power.description": "选择爆炸粒å­çš„大å°", + "firmament.config.composter": "堆肥桶", + "firmament.config.composter.no-more-noises": "é™éŸ³å †è‚¥æ¡¶", + "firmament.config.composter.no-more-noises.description": "消除堆肥桶å‘出的所有噪音和声音", + "firmament.config.configconfig": "Firmamenté…ç½®", + "firmament.config.configconfig.enable-moulconfig": "使用MoulConfig", + "firmament.config.configconfig.enable-moulconfig.description": "使用MoulConfigé…ç½®UI。关闭以回退到内置é…置。", + "firmament.config.configconfig.enable-yacl": "使用YACLé…ç½®", + "firmament.config.configconfig.enable-yacl.description": "使用YACLé…ç½®UI。关闭以回退到内置é…置。需è¦å•独安装YACL。", + "firmament.config.configconfig.wide-moulconfig": "更宽的MoulConfig UI", + "firmament.config.configconfig.wide-moulconfig.description": "使MoulConfigçš„UIå˜å¾—更宽", + "firmament.config.copy-chat": "å¤åˆ¶èŠå¤©", + "firmament.config.copy-chat.copy-chat": "å¤åˆ¶èŠå¤©", + "firmament.config.copy-chat.copy-chat.description": "å³é”®æ¶ˆæ¯è¿›è¡Œå¤åˆ¶", + "firmament.config.custom-skyblock-textures": "自定义空岛物å“纹ç†", + "firmament.config.custom-skyblock-textures.armor-overrides": "å¯ç”¨ç›”甲纹ç†", + "firmament.config.custom-skyblock-textures.armor-overrides.description": "å…许纹ç†åŒ…作者修改(但ä¸èƒ½ä¿®æ”¹æ¨¡åž‹ï¼‰ç©ºå²›ç›”甲的纹ç†ã€‚", + "firmament.config.custom-skyblock-textures.block-overrides": "å¯ç”¨æ–¹å—模型", + "firmament.config.custom-skyblock-textures.block-overrides.description": "å…许纹ç†åŒ…ä½œè€…æ ¹æ®æ–¹å—ä½ç½®å’Œæ‰€å¤„åŒºåŸŸæ›¿æ¢æ–¹å—模型。", + "firmament.config.custom-skyblock-textures.cache-duration": "模型缓存æŒç»­æ—¶é—´", + "firmament.config.custom-skyblock-textures.cache-duration.description": "çº¹ç†æ¨¡åž‹åº”缓存多长时间。", + "firmament.config.custom-skyblock-textures.cache-forever": "ç¦ç”¨ç¼“存清除", + "firmament.config.custom-skyblock-textures.cache-forever.description": "å®Œå…¨ä¸æ¸…é™¤ç¼“å­˜ã€‚è‹¥ç‰©å“æ•°æ®å˜åŒ–,æœåŠ¡å™¨ä¼šå‘ä½ å‘逿–°çš„ç‰©å“æ•°æ®ï¼Œå¤§æ¦‚ä¸ä¼šæœ‰é—®é¢˜ã€‚", + "firmament.config.custom-skyblock-textures.enabled": "å¯ç”¨è‡ªå®šä¹‰ç‰©å“纹ç†", + "firmament.config.custom-skyblock-textures.enabled.description": "å…许为纹ç†åŒ…替æ¢ç‰©å“。关闭此选项ä¸ä¼šç¦ç”¨è‡ªå®šä¹‰çº¹ç†åŒ¹é…", + "firmament.config.custom-skyblock-textures.legacy-cit": "å¯ç”¨æ—§ç‰ˆCIT Resewn兼容性", + "firmament.config.custom-skyblock-textures.legacy-cit.description": "å…许在更新版本上加载为 1.20.4 编写的CIT resewn纹ç†åŒ…。", + "firmament.config.custom-skyblock-textures.legacy-minecraft-path-support": "å¯ç”¨æ—§ç‰ˆçº¹ç†åŒ…路径", + "firmament.config.custom-skyblock-textures.legacy-minecraft-path-support.description": "å…许纹ç†åŒ…以旧版的方å¼åŠ è½½çº¹ç†ã€‚例如:å…许在 1.21.4 上加载 1.21.0 的盔甲纹ç†ã€‚", + "firmament.config.custom-skyblock-textures.model-overrides": "å¯ç”¨æ¨¡åž‹è¦†ç›–/æ¡ä»¶", + "firmament.config.custom-skyblock-textures.model-overrides.description": "å¯ç”¨Firmament的模型匹é…。这也适用于原版模型,如果该原版模型具有Firmament的断言。", + "firmament.config.custom-skyblock-textures.recolor-text": "å…许纹ç†åŒ…釿–°ç€è‰²æ–‡æœ¬", + "firmament.config.custom-skyblock-textures.recolor-text.description": "å…许纹ç†åŒ…釿–°ç€è‰²UI文本。", + "firmament.config.custom-skyblock-textures.screen-layouts": "å…许纹ç†åŒ…釿–°å¸ƒå±€å±å¹•", + "firmament.config.custom-skyblock-textures.screen-layouts.description": "å…许纹ç†åŒ…移动槽ä½ç­‰UIå…ƒç´ ï¼Œä»¥åŠæ›¿æ¢å±å¹•背景。", + "firmament.config.custom-skyblock-textures.skulls-enabled": "å¯ç”¨è‡ªå®šä¹‰æ”¾ç½®å¤´é¢…纹ç†", + "firmament.config.custom-skyblock-textures.skulls-enabled.description": "å…è®¸æ›¿æ¢æ”¾ä¸‹çš„头颅的纹ç†ã€‚", + "firmament.config.developer": "å¼€å‘者设置", + "firmament.config.developer-capes": "å¼€å‘者披风", + "firmament.config.developer-capes.show-cape": "显示开å‘者披风", + "firmament.config.developer-capes.show-cape.description": "让你看到开å‘者披风。", + "firmament.config.developer.auto-rebuild": "自动é‡å»ºèµ„æº", + "firmament.config.developer.auto-rebuild.description": "在执行F3+T之剿‰§è¡Œ./gradlew processResources。", + "firmament.config.diana": "Diana", + "firmament.config.diana.ancestral-spade": "Diana铲解æžå™¨", + "firmament.config.diana.ancestral-spade.description": "æ ¹æ®é“²å­çš„能力产生的粒å­å’Œå£°éŸ³ï¼Œè‡ªåŠ¨çŒœæµ‹ä½ çš„ä¸‹ä¸€ä¸ªç‚¹ä½ã€‚", + "firmament.config.diana.ancestral-teleport": "ä¼ é€è‡³çŒœæµ‹ç‚¹é™„è¿‘", + "firmament.config.diana.ancestral-teleport.description": "点击传é€è‡³çŒœæµ‹ç‚¹é™„近。", + "firmament.config.diana.nearby-waypoints": "附近路径点高亮器", + "firmament.config.diana.nearby-waypoints.description": "高亮附近的Diana猜测点。", + "firmament.config.etherwarp-overlay": "Etherwarp显示", + "firmament.config.etherwarp-overlay.cube": "实心方å—", + "firmament.config.etherwarp-overlay.cube-colour": "æ–¹å—颜色", + "firmament.config.etherwarp-overlay.cube-colour.description": "选择Etherwarp目标方å—的颜色。", + "firmament.config.etherwarp-overlay.cube.description": "ä½¿æ–¹å—æ•´ä½“å˜è‰²", + "firmament.config.etherwarp-overlay.etherwarp-overlay": "Etherwarp显示", + "firmament.config.etherwarp-overlay.etherwarp-overlay.description": "显示一个告诉你你将传é€åˆ°å“ªä¸ªæ–¹å—的覆盖层。", + "firmament.config.etherwarp-overlay.only-show-while-sneaking": "åªåœ¨æ½œè¡Œæ—¶æ˜¾ç¤º", + "firmament.config.etherwarp-overlay.only-show-while-sneaking.description": "仅在潜行时显示Etherwarp覆盖层。", + "firmament.config.etherwarp-overlay.wireframe": "空心方框", + "firmament.config.etherwarp-overlay.wireframe.description": "åœ¨æŒ‡å‘æ–¹å—上显示的轮廓", + "firmament.config.fairy-souls": "仙女之魂", + "firmament.config.fairy-souls.reset": "é‡ç½®å·²æ”¶é›†ä»™å¥³ä¹‹é­‚", + "firmament.config.fairy-souls.reset.description": "é‡ç½®æ‰€æœ‰å·²æ”¶é›†çš„仙女之魂,å…许你从头开始。", + "firmament.config.fairy-souls.show": "显示仙女之魂路径点", + "firmament.config.fairy-souls.show.description": "æ˜¾ç¤ºä½ å½“å‰æ‰€åœ¨ä¸–界中未收集的仙女之魂路径点。", + "firmament.config.fishing-warning": "钓鱼警告", + "firmament.config.fishing-warning.display-warning": "当你å³å°†é’“到鱼时显示警告", + "firmament.config.fishing-warning.highlight-wake-chain": "高亮钓鱼粒å­", + "firmament.config.fixes": "ä¿®å¤", + "firmament.config.fixes.auto-sprint": "自动疾跑", + "firmament.config.fixes.auto-sprint-hud": "疾跑状æ€HUD", + "firmament.config.fixes.auto-sprint-hud.description": "在å±å¹•上显示你当å‰çš„疾跑状æ€ã€‚ä»…åœ¨æœªè®¾ç½®è‡ªåŠ¨ç–¾è·‘é”®ä½æ—¶å¯è§ã€‚", + "firmament.config.fixes.auto-sprint-keybinding": "自动疾跑键ä½", + "firmament.config.fixes.auto-sprint-keybinding.description": "通过此键ä½åˆ‡æ¢è‡ªåŠ¨ç–¾è·‘ã€‚", + "firmament.config.fixes.auto-sprint-underwater": "水下疾跑", + "firmament.config.fixes.auto-sprint-underwater.description": "也在水下切æ¢ç–¾è·‘。在水下疾跑会让你进入游泳动画,这会改å˜ä½ çš„视角和碰撞箱,如果你ç»å¸¸åœæ­¢å’Œç§»åŠ¨ï¼Œè¿™å¯èƒ½ä¼šä»¤äººå›°æƒ‘。", + "firmament.config.fixes.auto-sprint.description": "这与原版疾跑ä¸åŒï¼Œå®ƒåªåœ¨è¡Œèµ°çš„第一刻标记键ä½è¢«æŒ‰ä¸‹ã€‚", + "firmament.config.fixes.disable-hurt-cam": "关闭å—伤时视角抖动", + "firmament.config.fixes.disable-hurt-cam.description": "ç¦ç”¨å—伤害时的å±å¹•抖动动画。", + "firmament.config.fixes.hide-mob-effects": "éšè—è¯æ°´æ•ˆæžœ", + "firmament.config.fixes.hide-mob-effects.description": "éšè—çŽ©å®¶ç‰©å“æ å³ä¾§çš„è¯æ°´æ•ˆæžœã€‚", + "firmament.config.fixes.hide-off-hand": "No Off Hand", + "firmament.config.fixes.hide-off-hand.description": "Remove the recipe slot from your inventory", + "firmament.config.fixes.hide-potion-effects-hud": "éšè—è¯æ°´æ•ˆæžœHUD", + "firmament.config.fixes.hide-potion-effects-hud.description": "éšè—å³ä¸Šè§’çš„è¯æ°´æ•ˆæžœHUD。", + "firmament.config.fixes.hide-recipe-book": "ç§»é™¤åˆæˆä¹¦", + "firmament.config.fixes.hide-recipe-book.description": "ä»Žä½ çš„ç‰©å“æ ä¸­ç§»é™¤åˆæˆä¹¦", + "firmament.config.fixes.hide-slot-highlights": "éšè—æ’æ§½é«˜äº®", + "firmament.config.fixes.hide-slot-highlights.description": "éšè—ç¦ç”¨å·¥å…·æç¤ºçš„物å“的槽ä½é«˜äº®ã€‚这使得/sbmenu在使用平滑纹ç†åŒ…æ—¶çœ‹èµ·æ¥æ›´å¥½ã€‚", + "firmament.config.fixes.peek-chat": "窥视èŠå¤©", + "firmament.config.fixes.peek-chat.description": "æŒ‰ä½æ­¤é”®ä½å¯ä»¥æŸ¥çœ‹èŠå¤©ï¼Œå°±åƒä½ æ‰“开了èŠå¤©æ¡†ä¸€æ ·ï¼Œä½†ä»ç„¶å¯ä»¥æŽ§åˆ¶ä½ çš„角色。", + "firmament.config.fixes.player-skins": "ä¿®å¤æœªç­¾å的玩家皮肤", + "firmament.config.fixes.player-skins.description": "将所有玩家皮肤标记为已签å,防止控制å°åžƒåœ¾ä¿¡æ¯å’Œä¸€äº›æ¸²æŸ“问题。", + "firmament.config.hud": "HUD", + "firmament.config.hud.day-count": "显示天数", + "firmament.config.hud.day-count-hud": "显示天数HUD", + "firmament.config.hud.day-count-hud.description": "显示天数。", + "firmament.config.hud.day-count-hud.display": "天数:%s", + "firmament.config.hud.day-count.description": "一个显示当å‰å¤©æ•°çš„HUD。", + "firmament.config.hud.fps-count": "显示帧数", + "firmament.config.hud.fps-count-hud": "显示帧数HUD", + "firmament.config.hud.fps-count-hud.description": "显示帧数。", + "firmament.config.hud.fps-count-hud.display": "FPS:%s", + "firmament.config.hud.fps-count.description": "一个显示当å‰å¸§æ•°çš„HUD。", + "firmament.config.hud.ping-count": "显示延迟", + "firmament.config.hud.ping-count-hud": "显示延迟HUD", + "firmament.config.hud.ping-count-hud.description": "显示延迟。", + "firmament.config.hud.ping-count-hud.display": "Ping:%s", + "firmament.config.hud.ping-count.description": "一个显示当å‰å»¶è¿Ÿçš„HUD。", + "firmament.config.inventory-buttons-config": "ç‰©å“æ æŒ‰é’®", + "firmament.config.inventory-buttons-config.hover-text": "悬åœå·¥å…·æç¤º", + "firmament.config.inventory-buttons-config.hover-text.description": "将鼠标悬åœåœ¨ç‰©å“æ æŒ‰é’®ä¸Šä¼šæ˜¾ç¤ºå®ƒä»¬è¿è¡Œçš„命令。", + "firmament.config.inventory-buttons-config.only-inv": "ä»…ç‰©å“æ ", + "firmament.config.inventory-buttons-config.only-inv.description": "ä»…åœ¨ç‰©å“æ ä¸­æ˜¾ç¤ºæŒ‰é’®", + "firmament.config.inventory-buttons-config.open-editor": "打开编辑器", + "firmament.config.inventory-buttons-config.open-editor.description": "点击任æ„ä½ç½®åˆ›å»ºä¸€ä¸ªç‰©å“æ æŒ‰é’®æˆ–编辑现有按钮。按ä½SHIFT坿Œ‰ç½‘格对é½ã€‚", + "firmament.config.item-hotkeys": "物å“å¿«æ·é”®", + "firmament.config.item-hotkeys.global-trade-interface": "在集市/æ‹å–行æœç´¢", + "firmament.config.item-hotkeys.global-trade-interface.description": "按下此按钮å¯åœ¨é›†å¸‚或æ‹å–行æœç´¢é¼ æ ‡æ‰€æŒ‡çš„物å“。", + "firmament.config.item-rarity-cosmetics": "物å“稀有度外观", + "firmament.config.item-rarity-cosmetics.background": "ç‰©å“æ èƒŒæ™¯ç¨€æœ‰åº¦", + "firmament.config.item-rarity-cosmetics.background-hotbar": "å¿«æ·æ èƒŒæ™¯ç¨€æœ‰åº¦", + "firmament.config.item-rarity-cosmetics.background-hotbar.description": "åœ¨å¿«æ·æ ä¸­æ˜¾ç¤ºç‰©å“稀有度背景。", + "firmament.config.item-rarity-cosmetics.background.description": "æ ¹æ®ç‰©å“稀有度在æ¯ä¸ªç‰©å“åŽé¢æ˜¾ç¤ºèƒŒæ™¯ã€‚", + "firmament.config.jade-integration": "Jade/WAILA集æˆ", + "firmament.config.jade-integration.blocks": "å¯ç”¨è‡ªå®šä¹‰æ–¹å—", + "firmament.config.jade-integration.blocks.description": "在Jadeä¸­æ˜¾ç¤ºè‡ªå®šä¹‰æ–¹å—æè¿°å’Œç¡¬åº¦ç­‰çº§ã€‚", + "firmament.config.jade-integration.progress": "å¯ç”¨è‡ªå®šä¹‰æŒ–矿进度", + "firmament.config.jade-integration.progress.description": "在存在挖掘疲劳的世界中让Jade显示自定义挖矿进度。", + "firmament.config.junk-highlighter": "Junk Highlighter", + "firmament.config.junk-highlighter.description": "Highlight items using regex to search for items in your inventory", + "firmament.config.junk-highlighter.highlight": "Highlight Keybind", + "firmament.config.junk-highlighter.highlight.description": "Highlight found items when this keybind is held", + "firmament.config.junk-highlighter.regex": "Search Regex", + "firmament.config.junk-highlighter.regex.description": "The RegEx (Regular Expression) to use when searching", + "firmament.config.lore-timers": "ç‰©å“æ—¶é—´æˆ³", + "firmament.config.lore-timers.format": "æ—¶é—´æ ¼å¼", + "firmament.config.lore-timers.format.choice.american": "§9美§få¼", + "firmament.config.lore-timers.format.choice.local": "系统时间格å¼", + "firmament.config.lore-timers.format.choice.rfc": "RFC", + "firmament.config.lore-timers.format.choice.rfcprecise": "RFC (毫秒)", + "firmament.config.lore-timers.format.choice.socialist": "欧å¼", + "firmament.config.lore-timers.format.description": "选择解æžè®¡æ—¶å™¨æ˜¾ç¤ºçš„æ—¶é—´æ ¼å¼ã€‚", + "firmament.config.lore-timers.show": "æ˜¾ç¤ºç‰©å“æè¿°è®¡æ—¶å™¨", + "firmament.config.lore-timers.show-creation": "显示创建时间", + "firmament.config.lore-timers.show-creation.description": "显示物å“的创建时间戳。有时此时间戳在å‡çº§ç‰©å“时会ä¿ç•™ï¼Œå› æ­¤å®ƒä¸ä¸€å®šæ˜¯æ­¤ç‰¹å®šç‰©å“的制作时间,而是其组件之一的制作时间。", + "firmament.config.lore-timers.show.description": "æ˜¾ç¤ºç‰©å“æè¿°ä¸­çš„è®¡æ—¶å™¨ï¼ˆä¾‹å¦‚åˆ©æ¯ã€æ‹å–æŒç»­æ—¶é—´ï¼‰ä½•时结æŸã€‚", + "firmament.config.party-commands": "队ä¼å‘½ä»¤", + "firmament.config.party-commands.cooldown": "冷崿—¶é—´", + "firmament.config.party-commands.cooldown.description": "è®¾ç½®å†·å´æ¥é˜²æ­¢å‘½ä»¤åˆ·å±ã€‚", + "firmament.config.party-commands.enable": "å¯ç”¨é˜Ÿä¼å‘½ä»¤", + "firmament.config.party-commands.enable.description": "å…许你队ä¼ä¸­çš„人使用 !warpã€!coordsã€!ptme 等命令。请å‚阅/firm partycommands获å–列表", + "firmament.config.party-commands.ignore-own": "忽略自己的消æ¯", + "firmament.config.party-commands.ignore-own.description": "防止你自己的消æ¯è§¦å‘队ä¼å‘½ä»¤", + "firmament.config.pets": "宠物", + "firmament.config.pets.highlight-pet": "高亮当å‰å® ç‰©", + "firmament.config.pets.highlight-pet.description": "在/petsèœå•中高亮你当å‰é€‰æ‹©çš„宠物。", + "firmament.config.pets.pet-overlay": "宠物信æ¯", + "firmament.config.pets.pet-overlay-hud": "宠物信æ¯HUD", + "firmament.config.pets.pet-overlay-hud.description": "一个显示当å‰å® ç‰©å’Œå® ç‰©ç»éªŒçš„HUD。", + "firmament.config.pets.pet-overlay.description": "在å±å¹•上显示当å‰å® ç‰©å’Œå® ç‰©ç»éªŒã€‚", + "firmament.config.pickaxe-info": "é•å­å’Œé’»å¤´", + "firmament.config.pickaxe-info.ability-cooldown": "é•å­èƒ½åЛ冷å´", + "firmament.config.pickaxe-info.ability-cooldown-toast": "é•å­èƒ½åŠ›å°±ç»ªæç¤º", + "firmament.config.pickaxe-info.ability-cooldown-toast.description": "当你的é•å­èƒ½åŠ›å‡†å¤‡å°±ç»ªæ—¶æ˜¾ç¤ºä¸€ä¸ªæç¤ºã€‚", + "firmament.config.pickaxe-info.ability-cooldown.description": "在你的准星上显示é•å­èƒ½åŠ›çš„å†·å´æ—¶é—´ã€‚", + "firmament.config.pickaxe-info.ability-scale": "能力冷å´ç¼©æ”¾", + "firmament.config.pickaxe-info.ability-scale.description": "调整准星æ—é•å­èƒ½åЛ冷崿—¶é—´çš„大å°ã€‚", + "firmament.config.pickaxe-info.block-on-dynamic": "阻止在ç§äººå²›å±¿ä½¿ç”¨", + "firmament.config.pickaxe-info.block-on-dynamic.choice.always": "总是阻止", + "firmament.config.pickaxe-info.block-on-dynamic.choice.never": "从ä¸é˜»æ­¢", + "firmament.config.pickaxe-info.block-on-dynamic.choice.only_destructive": "仅在å±é™©æ—¶", + "firmament.config.pickaxe-info.block-on-dynamic.description": "阻止你在ç§äººå²›å±¿ä¸Šå³é”®é•å­ä½¿ç”¨èƒ½åŠ›", + "firmament.config.pickaxe-info.disable-in-dungeons": "Disable cross-hair cooldown in Dungeons", + "firmament.config.pickaxe-info.disable-in-dungeons.description": "Disables the cooldown around your cross-hair while in Dungeons.", + "firmament.config.pickaxe-info.fuel-bar": "钻头燃料è€ä¹…度", + "firmament.config.pickaxe-info.fuel-bar.description": "用显示剩余燃料的è€ä¹…åº¦æ¡æ›¿æ¢ä½ çš„钻头的物å“è€ä¹…度æ¡ã€‚", + "firmament.config.power-user": "高级", + "firmament.config.power-user.copy-item-id": "å¤åˆ¶ç©ºå²›ç”Ÿå­˜ç‰©å“ID", + "firmament.config.power-user.copy-item-id.description": "按下此按钮å¤åˆ¶NEU Repo空岛生存物å“ID,会包å«å® ç‰©å“质,符文类型,附魔类型等é¢å¤–ä¿¡æ¯ã€‚", + "firmament.config.power-user.copy-item-stack": "å¤åˆ¶ItemStack", + "firmament.config.power-user.copy-item-stack.description": "å¤åˆ¶ItemStack的数æ®ã€‚è¿™å¯ä»¥åœ¨ç”¨äºŽåœ¨ä»£ç ä¸­è¿˜åŽŸæ­¤ç»„ç‰©å“。", + "firmament.config.power-user.copy-lore": "å¤åˆ¶åç§°+æè¿°", + "firmament.config.power-user.copy-lore.description": "将物å“åç§°å’Œæè¿°å¤åˆ¶ä¸ºJSONç¼–ç æ–‡æœ¬", + "firmament.config.power-user.copy-nbt-data": "å¤åˆ¶ExtraAttributesæ•°æ®", + "firmament.config.power-user.copy-nbt-data.description": "ä»…å¤åˆ¶ExtraAttributes,å³Hypixelç‹¬æœ‰çš„ç‰©å“æ•°æ®ã€‚", + "firmament.config.power-user.copy-skull-texture": "å¤åˆ¶æ”¾ç½®å¤´é¢…ID", + "firmament.config.power-user.copy-skull-texture.description": "å¤åˆ¶å‡†å¿ƒæŒ‡å‘的放下的头颅的数æ®ã€‚", + "firmament.config.power-user.copy-texture-pack-id": "å¤åˆ¶çº¹ç†åŒ…ID", + "firmament.config.power-user.copy-texture-pack-id.description": "å¤åˆ¶ç”¨äºŽé¼ æ ‡æŒ‡å‘物å“的纹ç†åŒ…ID。", + "firmament.config.power-user.copy-title": "å¤åˆ¶ç‰©å“æ æ ‡é¢˜", + "firmament.config.power-user.copy-title.description": "å¤åˆ¶ç‰©å“æ å’Œå±å¹•标题", + "firmament.config.power-user.dont-highlight-semicolon-items": "移除分å·é«˜äº®", + "firmament.config.power-user.dont-highlight-semicolon-items.description": "移除ID包å«åˆ†å·çš„物å“(例如宠物或附魔书)的高亮。", + "firmament.config.power-user.entity-data": "显示实体数æ®", + "firmament.config.power-user.entity-data.description": "打å°å‡ºå‡†æ˜ŸæŒ‡å‘实体的信æ¯ã€‚", + "firmament.config.power-user.export-item-stack": "导出ItemStack", + "firmament.config.power-user.export-item-stack.description": "将鼠标指å‘的档物å“å¯¼å‡ºåˆ°ä»“åº“æ•°æ®æ–‡ä»¶å¤¹", + "firmament.config.power-user.export-npc-location": "导出NPCä½ç½®", + "firmament.config.power-user.export-npc-location.description": "å°†NPCçš„ä½ç½®å¯¼å‡ºåˆ°æ•°æ®ä»“库", + "firmament.config.power-user.export-recipe": "å¯¼å‡ºåˆæˆæ•°æ®", + "firmament.config.power-user.export-recipe.description": "å°†åˆæˆæ•°æ®å¯¼å‡ºåˆ°æ•°æ®ä»“库", + "firmament.config.power-user.highlight-non-overlay": "高亮缺失物å“", + "firmament.config.power-user.highlight-non-overlay.description": "高亮数æ®ä»“库中ä¸å­˜åœ¨çš„物å“。", + "firmament.config.power-user.show-item-id": "显示空岛ID", + "firmament.config.power-user.show-item-id.description": "在物å“下方显示其空岛物å“ID。", + "firmament.config.price-data": "价格数æ®", + "firmament.config.price-data.avg-lowest-bin-days": "平凿œ€ä½Žä»·æ ¼BIN物å“天数", + "firmament.config.price-data.avg-lowest-bin-days.choice.off": "关闭", + "firmament.config.price-data.avg-lowest-bin-days.choice.onedayavglowestbin": "1天", + "firmament.config.price-data.avg-lowest-bin-days.choice.sevendayavglowestbin": "7天", + "firmament.config.price-data.avg-lowest-bin-days.choice.threedayavglowestbin": "3天", + "firmament.config.price-data.avg-lowest-bin-days.description": "选择是å¦ä»¥åŠæ˜¾ç¤ºæœ€ä½ŽBINå¹³å‡å¤©æ•°ã€‚", + "firmament.config.price-data.enable-always": "å¯ç”¨ç‰©å“ä»·æ ¼", + "firmament.config.price-data.enable-always.description": "在空岛物å“ä¸Šæ˜¾ç¤ºç‰©å“æ‹å–/集市价格", + "firmament.config.price-data.enable-keybind": "仅在按下绑定按键键时å¯ç”¨", + "firmament.config.price-data.enable-keybind.description": "ä»…åœ¨æŒ‰ä½æ­¤ç»‘定键时显示æ‹å–/集市价格。解绑以始终显示。", + "firmament.config.price-data.stack-size-keybind": "ç»Ÿè®¡æ‹¥æœ‰ç‰©å“æ€»ä»·çš„绑定按键", + "firmament.config.price-data.stack-size-keybind.description": "在悬åœç‰©å“æ—¶æŒ‰ä¸‹æ­¤é”®å¯æ˜¾ç¤ºå…¶ä»·æ ¼ä¹˜ä»¥ä½ æ‹¥æœ‰çš„ç‰©å“æ•°é‡ã€‚", + "firmament.config.pristine-profit": "Pristine收入追踪器", + "firmament.config.pristine-profit.fine-gemstones": "基于Fineå®çŸ³", + "firmament.config.pristine-profit.fine-gemstones.description": "使用Fine类型å®çŸ³ï¼ˆæ›´ç¨³å®šï¼‰çš„ä»·æ ¼ï¼Œè€Œä¸æ˜¯Flawed类型。", + "firmament.config.pristine-profit.position": "Pristine收入追踪器HUD", + "firmament.config.pristine-profit.position.description": "编辑Pristine收入追踪器ä½ç½®ã€‚", + "firmament.config.pristine-profit.timeout": "é—´éš”(0=ç¦ç”¨)", + "firmament.config.pristine-profit.timeout.description": "追踪你在挖矿时Pristine触å‘获得的利润。设置为0秒以ç¦ç”¨HUD。", + "firmament.config.quick-commands": "å¿«æ·å‘½ä»¤", + "firmament.config.quick-commands.dh": "å¯ç”¨/dh", + "firmament.config.quick-commands.dh.description": "将你传é€åˆ°åœ°ç‰¢å¤§åŽ…ã€‚", + "firmament.config.quick-commands.join": "å¯ç”¨/join", + "firmament.config.quick-commands.join.description": "使用/join f1ã€/join k1ã€/join m7等简写加入å„ç§ç±»åž‹çš„临时æœåŠ¡å™¨ï¼Œä¾‹å¦‚åœ°ç‰¢ã€‚", + "firmament.config.repo": "Firmamentæ•°æ®ä»“库设置", + "firmament.config.repo.autoUpdate": "自动更新", + "firmament.config.repo.autoUpdate.description": "æ¯æ¬¡å¯åŠ¨æ—¶è‡ªåŠ¨ä¸‹è½½æ–°ç‰©å“到物å“列表。", + "firmament.config.repo.branch": "仓库分支", + "firmament.config.repo.branch.description": "从中拉å–ç‰©å“æ•°æ®çš„Git分支。", + "firmament.config.repo.branch.hint": "å±é™©/ä¸ç¨³å®š", + "firmament.config.repo.disable-item-groups": "ç¦ç”¨ç‰©å“组", + "firmament.config.repo.disable-item-groups.description": "ç¦ç”¨ç‰©å“组å¯ä»¥æé«˜æ€§èƒ½ï¼Œä½†å°†ä¸å†æŠŠç›¸ä¼¼ç‰©å“(如仆从ã€é™„魔)集åˆä¸ºä¸€é¡¹æ˜¾ç¤ºã€‚", + "firmament.config.repo.enable-rei": "å¯ç”¨REI", + "firmament.config.repo.enable-rei.description": "Firmament显示其å“列表需è¦REI。若想使用其他物å“列表æä¾›æ¨¡ç»„(如SkyBlockers)å¯ä»¥åœ¨è¿™é‡Œå…³é—­å®ƒã€‚如果没有此类模组å¯ç”¨åŽå°†æ˜¾ç¤ºåŽŸç‰ˆç‰©å“列表。", + "firmament.config.repo.enable-super-craft": "始终使用Supercraft", + "firmament.config.repo.enable-super-craft.description": "在REIä¸­ç‚¹å‡»åˆæˆæŒ‰é’®æ—¶ï¼Œå§‹ç»ˆä½¿ç”¨Supercraftï¼Œè€Œä¸æ˜¯åªåœ¨æŒ‰ä½shift时。", + "firmament.config.repo.perfect-renders": "完美渲染", + "firmament.config.repo.perfect-renders.choice.nothing": "æŸå (最快)", + "firmament.config.repo.perfect-renders.choice.render": "è§†è§‰ä¿®å¤ (å¿«)", + "firmament.config.repo.perfect-renders.choice.render_and_text": "完美 (最慢)", + "firmament.config.repo.perfect-renders.description": "通过å…许物å“éƒ¨åˆ†å…ˆä¸æ­£ç¡®åŠ è½½æ¥åŠ å¿«ç‰©å“列表加载速度。当åŽå°é‡æ–°åŠ è½½å®Œæˆæ—¶ï¼Œå®ƒä»¬ç¨åŽä¼šæ¢å¤æ­£å¸¸ã€‚", + "firmament.config.repo.redownload": "釿–°ä¸‹è½½ç‰©å“列表", + "firmament.config.repo.redownload.description": "å¼ºåˆ¶é‡æ–°ä¸‹è½½ç‰©å“列表。这会在é‡å¯åŽå®Œæˆã€‚", + "firmament.config.repo.reload": "釿–°åŠ è½½ç‰©å“列表", + "firmament.config.repo.reload.description": "å¼ºåˆ¶é‡æ–°åŠ è½½ç‰©å“列表。但ä¸ä¼šå†æ¬¡ä¸‹è½½ç‰©å“列表。", + "firmament.config.repo.reponame": "æ•°æ®ä»“库åç§°", + "firmament.config.repo.reponame.description": "从中拉å–ç‰©å“æ•°æ®çš„GitHub仓库å称。", + "firmament.config.repo.reponame.hint": "NotEnoughUpdates-REPO", + "firmament.config.repo.reset": "é‡ç½®", + "firmament.config.repo.reset.description": "é‡ç½®Git拉å–仓库。", + "firmament.config.repo.username": "仓库用户å", + "firmament.config.repo.username.description": "从中拉å–ç‰©å“æ•°æ®çš„GitHub仓库用户。", + "firmament.config.repo.username.hint": "NotEnoughUpdates", + "firmament.config.repo.warn-for-missing-item-list-mod": "缺少物å“列表模组警告", + "firmament.config.repo.warn-for-missing-item-list-mod.description": "如果未安装兼容的物å“列表模组(如REI),则å‘出警告。", + "firmament.config.save-cursor-position": "ä¿å­˜å…‰æ ‡ä½ç½®", + "firmament.config.save-cursor-position.enable": "å¯ç”¨", + "firmament.config.save-cursor-position.enable.description": "切æ¢GUIæ—¶ä¿å­˜å…‰æ ‡ä½ç½®ã€‚", + "firmament.config.save-cursor-position.tolerance": "容å¿åº¦", + "firmament.config.save-cursor-position.tolerance.description": "在å¤ä½åˆ°å±å¹•中间之å‰ï¼Œé€‰æ‹©å…‰æ ‡åœ¨gui之间åœç•™çš„æ—¶é—´ã€‚", + "firmament.config.slot-locking": "é”å®šç‰©å“æ æ§½ä½", + "firmament.config.slot-locking.bind": "ç»‘å®šç‰©å“æ æ§½ä½", + "firmament.config.slot-locking.bind-render": "æ˜¾ç¤ºç»‘å®šçš„ç‰©å“æ ", + "firmament.config.slot-locking.bind-render.choice.everything": "总是显示", + "firmament.config.slot-locking.bind-render.choice.nothing": "ä»…åœ¨æ‚¬åœæ—¶", + "firmament.config.slot-locking.bind-render.choice.only_boxes": "仅显示方框", + "firmament.config.slot-locking.bind-render.description": "åªåœ¨ç›¸å…³æ§½ä½è¢«æ‚¬åœæ—¶æ‰æ˜¾ç¤ºç»‘定的连线。", + "firmament.config.slot-locking.bind.description": "å°†å¿«æ·æ æ§½ä½ç»‘定到å¦ä¸€ä¸ªæ§½ä½ã€‚è¿™å…è®¸é€šè¿‡æŒ‰ä½ Shift é”®ç‚¹å‡»ä»»ä¸€æ’æ§½æ¥å¿«é€Ÿåˆ‡æ¢æ’槽。", + "firmament.config.slot-locking.drop-in-dungeons": "å…许在地牢中丢弃物å“", + "firmament.config.slot-locking.drop-in-dungeons.description": "å…è®¸åœ¨åœ°ç‰¢ä¸­ä¸¢å¼ƒç‰©å“æ¥åœ¨åœ°ç‰¢é‡Œå¼€å¤§ã€‚", + "firmament.config.slot-locking.hunting-box": "ä¿æŠ¤ç‹©çŒŽé™·é˜±ç‰©å“", + "firmament.config.slot-locking.hunting-box.description": "狩猎陷阱的UUID会å˜åŒ–,因此根æ®UUIDåŽ»ä¿æŠ¤ç‰¹å®šé™·é˜±ã€‚æ­¤é€‰é¡¹å¯ç”¨äºŽé˜»æ­¢ä¸¢å¼ƒä»»ä½•狩猎陷阱。", + "firmament.config.slot-locking.lock": "é”定槽ä½", + "firmament.config.slot-locking.lock-uuid": "é”定带有特定UUID的物å“", + "firmament.config.slot-locking.lock-uuid.description": "通过UUIDé”定空岛物å“。这会阻止特定物å“被丢弃/出售,但ä»ç„¶å…许移动它。", + "firmament.config.slot-locking.lock.description": "é”定一个槽ä½ï¼Œé˜²æ­¢æ§½ä½å†…物å“被移动或丢弃,替æ¢ã€‚", + "firmament.config.slot-locking.multi-bind": "å…许多é‡ç»‘定", + "firmament.config.slot-locking.multi-bind.description": "å…许将åŒä¸€ä¸ªå¿«æ·æ æ§½ä½ç»‘定到多个槽ä½ã€‚", + "firmament.config.slot-locking.require-quick-move": "åªèƒ½ä½¿ç”¨Shift-Clickæ¥åˆ‡æ¢ç»‘定的物å“", + "firmament.config.slot-locking.require-quick-move.description": "如果关闭,无需按ä½shiftå°±å¯ä»¥è¿›è¡Œåˆ‡æ¢ã€‚", + "firmament.config.storage-overlay": "存储UI", + "firmament.config.storage-overlay.always-replace": "始终使用存储UI", + "firmament.config.storage-overlay.always-replace.description": "始终使用Firmament的存储UI替æ¢åŽŸç‰ˆæœ«å½±ç®±æ˜¾ç¤ºã€‚", + "firmament.config.storage-overlay.block-item-scrolling": "阻止滚动å±å¹•", + "firmament.config.storage-overlay.block-item-scrolling.description": "在你悬åœåœ¨ç‰©å“上时ç¦ç”¨å­˜å‚¨UI的滚动。å¯ä»¥å…¼å®¹ç‰©å“æè¿°æ»šåŠ¨æ¨¡ç»„ã€‚", + "firmament.config.storage-overlay.height": "存储UI高度", + "firmament.config.storage-overlay.height.description": "坿»šåŠ¨çš„å­˜å‚¨UI的高度。", + "firmament.config.storage-overlay.highlight-search-results": "高亮æœç´¢ç»“æžœ", + "firmament.config.storage-overlay.highlight-search-results-colour": "高亮æœç´¢é¢œè‰²", + "firmament.config.storage-overlay.highlight-search-results-colour.description": "更改高亮æœç´¢ç»“果的颜色。", + "firmament.config.storage-overlay.highlight-search-results.description": "在存储UI中高亮æœç´¢ç»“果。", + "firmament.config.storage-overlay.inverse-scroll": "å转滚动", + "firmament.config.storage-overlay.inverse-scroll.description": "å转Firmament存储å åŠ ä¸­çš„é¼ æ ‡æ»šè½®æ»šåŠ¨ã€‚", + "firmament.config.storage-overlay.margin": "è¾¹è·", + "firmament.config.storage-overlay.margin.description": "存储概览内部的边è·ã€‚", + "firmament.config.storage-overlay.outline-active-page": "选定页é¢è½®å»“", + "firmament.config.storage-overlay.outline-active-page-colour": "轮廓颜色", + "firmament.config.storage-overlay.outline-active-page-colour.description": "更改你选择的存储页é¢å‘¨å›´è¾¹æ¡†çš„颜色。", + "firmament.config.storage-overlay.outline-active-page.description": "在存储UIä¸­ä¸ºä½ é€‰æ‹©çš„å­˜å‚¨é¡µé¢æ·»åŠ è¾¹æ¡†ã€‚", + "firmament.config.storage-overlay.padding": "å¡«å……", + "firmament.config.storage-overlay.padding.description": "存储概览内部如何填充。", + "firmament.config.storage-overlay.retain-scroll": "ä¿ç•™æ»šåЍä½ç½®", + "firmament.config.storage-overlay.retain-scroll.description": "关闭存储UI和概览时ä¿ç•™æ»šåЍä½ç½®ã€‚", + "firmament.config.storage-overlay.rows": "列", + "firmament.config.storage-overlay.rows.description": "存储UI和概览使用的最大列数。", + "firmament.config.storage-overlay.scroll-speed": "滚动速度", + "firmament.config.storage-overlay.scroll-speed.description": "存储å åŠ å’Œæ¦‚è§ˆå†…éƒ¨çš„æ»šåŠ¨é€Ÿåº¦ã€‚", + "firmament.config.wardrobe-keybinds": "衣柜快æ·é”®", + "firmament.config.wardrobe-keybinds.change-page": "更改页é¢", + "firmament.config.wardrobe-keybinds.change-page.description": "更改当å‰é€‰ä¸­çš„页é¢", + "firmament.config.wardrobe-keybinds.next-page": "下一页", + "firmament.config.wardrobe-keybinds.next-page.description": "å‰å¾€ä¸‹ä¸€é¡µ", + "firmament.config.wardrobe-keybinds.previous-page": "上一页", + "firmament.config.wardrobe-keybinds.previous-page.description": "å‰å¾€ä¸Šä¸€é¡µ", + "firmament.config.wardrobe-keybinds.slot-1": "æ§½ä½1", + "firmament.config.wardrobe-keybinds.slot-1.description": "切æ¢åˆ°ç¬¬ä¸€å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-2": "æ§½ä½2", + "firmament.config.wardrobe-keybinds.slot-2.description": "切æ¢åˆ°ç¬¬äºŒå¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-3": "æ§½ä½3", + "firmament.config.wardrobe-keybinds.slot-3.description": "切æ¢åˆ°ç¬¬ä¸‰å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-4": "æ§½ä½4", + "firmament.config.wardrobe-keybinds.slot-4.description": "切æ¢åˆ°ç¬¬å››å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-5": "æ§½ä½5", + "firmament.config.wardrobe-keybinds.slot-5.description": "切æ¢åˆ°ç¬¬äº”套装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-6": "æ§½ä½6", + "firmament.config.wardrobe-keybinds.slot-6.description": "切æ¢åˆ°ç¬¬å…­å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-7": "æ§½ä½7", + "firmament.config.wardrobe-keybinds.slot-7.description": "切æ¢åˆ°ç¬¬ä¸ƒå¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-8": "æ§½ä½8", + "firmament.config.wardrobe-keybinds.slot-8.description": "切æ¢åˆ°ç¬¬å…«å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.slot-9": "æ§½ä½9", + "firmament.config.wardrobe-keybinds.slot-9.description": "切æ¢åˆ°ç¬¬ä¹å¥—装备的键ä½", + "firmament.config.wardrobe-keybinds.wardrobe-keybinds": "衣柜快æ·é”®", + "firmament.config.wardrobe-keybinds.wardrobe-keybinds.description": "使用数字按键快速穿上衣柜内的装备", + "firmament.config.waypoints": "路径点", + "firmament.config.waypoints.reset-order-on-swap": "切æ¢ä¸–界时é‡ç½®æœ‰åºè·¯å¾„点", + "firmament.config.waypoints.reset-order-on-swap.description": "切æ¢åˆ°å¦ä¸€ä¸ªä¸–界åŽé‡ç½®æœ‰åºè·¯å¾„点的进度。", + "firmament.config.waypoints.show-index": "显示有åºè·¯å¾„点索引", + "firmament.config.waypoints.show-index.description": "在世界中显示有åºè·¯å¾„点的编å·ã€‚", + "firmament.config.waypoints.skip-to-nearest": "å…许跳过路径点", + "firmament.config.waypoints.skip-to-nearest.description": "å…许跳过有åºåˆ—表中的路径点。如果ç¦ç”¨ï¼Œæ˜¾ç¤ºä¸‹ä¸€ä¸ªè·¯å¾„点å‰å¿…须移动至当å‰è·¯å¾„点周围。", + "firmament.config.waypoints.temp-waypoint-duration": "临时路径点æŒç»­æ—¶é—´", + "firmament.config.waypoints.temp-waypoint-duration.description": "在世界中显示其他玩家使用/firm sendcoordså‘é€çš„路径点。", + "firmament.debug.skyblockid": "空岛ID: %s", + "firmament.debug.skyblockid.copy": "点击å¤åˆ¶ç©ºå²›ID", + "firmament.dev.resourcerebuild.done": "Gradle资æºé‡å»ºå®ŒæˆäºŽ %s", + "firmament.dev.resourcerebuild.start": "正在调用gradle资æºé‡å»º(./gradlew :processResources)", + "firmament.download": "点击这里下载%s", + "firmament.download.already": " (已下载)", + "firmament.fixes.auto-sprint.not-sprinting": "未在疾跑", + "firmament.fixes.auto-sprint.on": "已切æ¢ç–¾è·‘状æ€", + "firmament.fixes.auto-sprint.sprinting": "正在疾跑", + "firmament.hotmpreset.copied": "已将所有HOTM技能点å¤åˆ¶åˆ°å‰ªè´´æ¿ã€‚使用/firm importhotm导入。", + "firmament.hotmpreset.failedimport": "在你的剪贴æ¿ä¸­æ‰¾ä¸åˆ°HOTM技能点预设。你å¯ä»¥ä½¿ç”¨/firm exporthotm 导出你当å‰çš„HOTM技能点", + "firmament.hotmpreset.okayimport": "已导入HOTM技能点预设。", + "firmament.hotmpreset.openinghotm": "正在打开/hotmèœå•进行导出。", + "firmament.hotmpreset.scrolled": "刚刚进行了一次滚动。正在等待æœåŠ¡å™¨æ›´æ–°ç‰©å“。", + "firmament.hotmpreset.scrollprompt": "æˆ‘ä»¬éœ€è¦æ»šåЍï¼è¯·ç‚¹å‡»ä»»æ„ä½ç½®ç»§ç»­ã€‚", + "firmament.hud.edit": "编辑%s", + "firmament.inventory-buttons.all-warps-preset": "所有传é€é¢„设", + "firmament.inventory-buttons.delete": "按ä½L-CTRL并点击删除", + "firmament.inventory-buttons.import-failed": "你的一个按钮没有完整导入", + "firmament.inventory-buttons.info": "按ä½SHIFT坿Œ‰ç½‘格对é½", + "firmament.inventory-buttons.load-preset": "加载预设", + "firmament.inventory-buttons.reset": "é‡ç½®æŒ‰é’®", + "firmament.inventory-buttons.save-preset": "ä¿å­˜é¢„设", + "firmament.inventory-buttons.simple-preset": "简å•预设", + "firmament.key.category": "Firmament", + "firmament.keybinding.external": "%s", + "firmament.modapi.event": "收到模组API事件:%s", + "firmament.poweruser.entity.armor": "实体盔甲:", + "firmament.poweruser.entity.armor.item": " - %s", + "firmament.poweruser.entity.fail": "光标下未找到实体", + "firmament.poweruser.entity.name": "实体åç§°:%s", + "firmament.poweruser.entity.passengers": "%s乘客", + "firmament.poweruser.entity.position": "ä½ç½®:%s", + "firmament.poweruser.entity.type": "实体类型:%s", + "firmament.price": "正在检查 %s 的价格", + "firmament.price.bazaar": "集市统计:", + "firmament.price.bazaar.buy.order": "购买订å•:%d", + "firmament.price.bazaar.buy.price": "è´­ä¹°ä»·æ ¼:%s", + "firmament.price.bazaar.productid": "库存ID:%s", + "firmament.price.bazaar.sell.order": "出售订å•:%d", + "firmament.price.bazaar.sell.price": "出售价格:%s", + "firmament.price.lowestbin": "æœ€ä½Žå³æ—¶è´­ä¹°ä»·æ ¼:%s", + "firmament.pristine-profit.collection": "收集:%s/å°æ—¶", + "firmament.pristine-profit.money": "金钱:%s/å°æ—¶", + "firmament.pv.lookingup": "正在查找%s", + "firmament.pv.noplayer": "%s䏿˜¯ä¸€ä¸ª Minecraft 玩家", + "firmament.pv.noprofile": "%s没有空岛档案", + "firmament.pv.pets": "宠物", + "firmament.pv.skills": "技能", + "firmament.pv.skills.alchemy": "炼è¯", + "firmament.pv.skills.carpentry": "åˆæˆ", + "firmament.pv.skills.combat": "战斗", + "firmament.pv.skills.enchanting": "附魔", + "firmament.pv.skills.farming": "农业", + "firmament.pv.skills.fishing": "é’“é±¼", + "firmament.pv.skills.foraging": "ç æ ‘", + "firmament.pv.skills.mining": "挖矿", + "firmament.pv.skills.rift": "裂隙", + "firmament.pv.skills.runecrafting": "符文锻造", + "firmament.pv.skills.social": "社交", + "firmament.pv.skills.taming": "宠物", + "firmament.pv.skills.total": "总ç»éªŒ:%s", + "firmament.quick-commands.join.explain": "使用/join f1,/join m7,/join fe或/join khot等命令加入地牢或kuudraæœåŠ¡å™¨ã€‚", + "firmament.quick-commands.join.success": "正在加入:%s", + "firmament.quick-commands.join.unknown": "找ä¸åˆ°%s的实例", + "firmament.quick-commands.join.unknown-catacombs": "未知的地牢层数%s", + "firmament.quick-commands.join.unknown-kuudra": "未知的kuudra等级%s", + "firmament.recipe.forge.time": "锻造时间:%s", + "firmament.recipe.mobs.coins": "§e金å¸:%s", + "firmament.recipe.mobs.combat": "§b战斗ç»éªŒ:%s", + "firmament.recipe.mobs.drops": "§e§l掉è½å‡ çއ:%s", + "firmament.recipe.mobs.exp": "§6ç»éªŒ:%s", + "firmament.recipe.mobs.name": "§8[§7等级%d§8]§c%s", + "firmament.recipe.mobs.name.nolevel": "§c%s", + "firmament.recipe.novanilla": "Hypixelæ— æ³•å¯¹åŽŸç‰ˆé…æ–¹è¿›è¡ŒSupercraft", + "firmament.reiwarning": "Firmament需è¦RoughlyEnoughItemsæ¥æ˜¾ç¤ºå…¶ç‰©å“列表ï¼", + "firmament.reiwarning.disable": "点击此处ç¦ç”¨æ­¤è­¦å‘Š", + "firmament.reiwarning.disabled": "å·²ç¦ç”¨RoughlyEnoughItems警告。但没有REI物å“列表将无法显示。", + "firmament.repo.brokenitem": "渲染物å“失败:%s", + "firmament.repo.cache": "æ­£åœ¨é‡æ–°ç¼“存物å“", + "firmament.repo.reload.disk": "正在从ç£ç›˜é‡æ–°åŠ è½½ä»“åº“ã€‚è¿™å¯èƒ½ä¼šæœ‰ç‚¹å¡é¡¿ã€‚", + "firmament.repo.reload.network": "正在å°è¯•釿–°ä¸‹è½½ä»“库", + "firmament.sbinfo.gametype": "Locraw游æˆç±»åž‹: %s", + "firmament.sbinfo.map": "Locraw地图: %s", + "firmament.sbinfo.mode": "Locraw模å¼: %s", + "firmament.sbinfo.nolocraw": "æ— Locrawæ•°æ®å¯ç”¨", + "firmament.sbinfo.profile": "当剿¡£æ¡ˆæ˜µç§°:%s", + "firmament.sbinfo.server": "LocrawæœåС噍:%s", + "firmament.toggle.false": "关闭", + "firmament.toggle.true": "å¼€å¯", + "firmament.tooltip.copied.lore": "å·²å¤åˆ¶åç§°å’Œæè¿°", + "firmament.tooltip.copied.modelid": "å·²å¤åˆ¶çº¹ç†ID:%s", + "firmament.tooltip.copied.modelid.fail": "å¤åˆ¶çº¹ç†ID失败", + "firmament.tooltip.copied.nbt": "å·²å¤åˆ¶NBTæ•°æ®", + "firmament.tooltip.copied.skull": "å·²å¤åˆ¶å¤´é¢…ID:%s", + "firmament.tooltip.copied.skull-id": "å·²å¤åˆ¶å¤´é¢…ID:%s", + "firmament.tooltip.copied.skull-id.fail.no-profile": "头颅没有档案", + "firmament.tooltip.copied.skull-id.fail.no-skull": "è¿™ä¸æ˜¯å¤´é¢…", + "firmament.tooltip.copied.skull-id.fail.no-texture": "头颅没有纹ç†", + "firmament.tooltip.copied.skull.fail": "å¤åˆ¶å¤´é¢…ID失败。", + "firmament.tooltip.copied.skyblockid": "å·²å¤åˆ¶ç©ºå²›ID:%s", + "firmament.tooltip.copied.skyblockid.fail": "å¤åˆ¶ç©ºå²›ID失败", + "firmament.tooltip.copied.stack": "å·²å¤åˆ¶ItemStack", + "firmament.tooltip.skyblockid": "空岛ID:%s", + "firmament.ursa.debugrequest.result": "Ursa请求æˆåŠŸ:%s", + "firmament.ursa.debugrequest.start": "Ursa请求已å¯åЍ", + "firmament.warp-util.already-close": "å·²ç»åœ¨ç›®çš„地,无法使用/warp %s", + "firmament.warp-util.attempting-to-warp": "正在å°è¯•ä¼ é€åˆ°/warp %s", + "firmament.warp-util.clear-excluded": "已将所有/warp命令标记为å¯èƒ½å¯ç”¨ã€‚", + "firmament.warp-util.mark-excluded": "Firmament:å°è¯•ä¼ é€åˆ°%s,但它未解é”。我将é¿å…冿¬¡ä¼ é€åˆ°é‚£é‡Œã€‚", + "firmament.warp-util.no-warp-found": "找ä¸åˆ°/warp %s", + "firmament.waypoint.temporary": "临时路径点:%s", + "zzzzzzzzz.lastentry": "æ­¤å¤„ä¸ºç¡®ä¿æ¯ä¸ªçœŸæ­£çš„Firmamentæ¡ç›®éƒ½æœ‰ä¸€ä¸ªå°¾éšé€—å·" +} diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000..f6f4a0b --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,28 @@ +#SPDX-FileCopyrightText: 2024 Linnea Gräf +# +#SPDX-License-Identifier: CC0-1.0 + +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/web/.vscode/extensions.json b/web/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/web/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/web/.vscode/launch.json b/web/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/web/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/web/REUSE.toml b/web/REUSE.toml new file mode 100644 index 0000000..951c8b9 --- /dev/null +++ b/web/REUSE.toml @@ -0,0 +1,20 @@ +#SPDX-FileCopyrightText: 2024 Linnea Gräf +# +#SPDX-License-Identifier: CC0-1.0 + +version = 1 + +[[annotations]] +path = ["src/**/*"] +SPDX-License-Identifier = "GPL-3.0-or-later" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] + +[[annotations]] +path = ["pnpm-lock.yaml"] +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Auto Generated"] + +[[annotations]] +path = ["*.json", "*.mjs", ".vscode/*"] +SPDX-License-Identifier = "CC0-1.0" +SPDX-FileCopyrightText = ["Linnea Gräf ", "Firmament Contributors"] diff --git a/web/astro.config.mjs b/web/astro.config.mjs new file mode 100644 index 0000000..061f596 --- /dev/null +++ b/web/astro.config.mjs @@ -0,0 +1,12 @@ +// @ts-check +import { defineConfig } from 'astro/config'; + +import tailwind from '@astrojs/tailwind'; + +// https://astro.build/config +export default defineConfig({ + integrations: [tailwind()], + redirects: { + "/discord": "https://discord.com/invite/64pFP94AWA", + }, +}); diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..0cf9347 --- /dev/null +++ b/web/package.json @@ -0,0 +1,21 @@ +{ + "packageManager": "pnpm@9.3.0", + "name": "", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "start": "astro dev", + "build": "astro check && astro build", + "preview": "astro preview", + "astro": "astro" + }, + "dependencies": { + "@astrojs/check": "^0.9.4", + "@astrojs/tailwind": "^5.1.2", + "astro": "^4.16.13", + "sharp": "^0.33.5", + "tailwindcss": "^3.4.15", + "typescript": "^5.6.3" + } +} diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml new file mode 100644 index 0000000..eb1b894 --- /dev/null +++ b/web/pnpm-lock.yaml @@ -0,0 +1,4487 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@astrojs/check': + specifier: ^0.9.4 + version: 0.9.4(typescript@5.6.3) + '@astrojs/tailwind': + specifier: ^5.1.2 + version: 5.1.2(astro@4.16.13(rollup@4.27.2)(typescript@5.6.3))(tailwindcss@3.4.15) + astro: + specifier: ^4.16.13 + version: 4.16.13(rollup@4.27.2)(typescript@5.6.3) + sharp: + specifier: ^0.33.5 + version: 0.33.5 + tailwindcss: + specifier: ^3.4.15 + version: 3.4.15 + typescript: + specifier: ^5.6.3 + version: 5.6.3 + +packages: + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@astrojs/check@0.9.4': + resolution: {integrity: sha512-IOheHwCtpUfvogHHsvu0AbeRZEnjJg3MopdLddkJE70mULItS/Vh37BHcI00mcOJcH1vhD3odbpvWokpxam7xA==} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + + '@astrojs/compiler@2.10.3': + resolution: {integrity: sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==} + + '@astrojs/internal-helpers@0.4.1': + resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} + + '@astrojs/language-server@2.15.4': + resolution: {integrity: sha512-JivzASqTPR2bao9BWsSc/woPHH7OGSGc9aMxXL4U6egVTqBycB3ZHdBJPuOCVtcGLrzdWTosAqVPz1BVoxE0+A==} + hasBin: true + peerDependencies: + prettier: ^3.0.0 + prettier-plugin-astro: '>=0.11.0' + peerDependenciesMeta: + prettier: + optional: true + prettier-plugin-astro: + optional: true + + '@astrojs/markdown-remark@5.3.0': + resolution: {integrity: sha512-r0Ikqr0e6ozPb5bvhup1qdWnSPUvQu6tub4ZLYaKyG50BXZ0ej6FhGz3GpChKpH7kglRFPObJd/bDyf2VM9pkg==} + + '@astrojs/prism@3.1.0': + resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==} + engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + + '@astrojs/tailwind@5.1.2': + resolution: {integrity: sha512-IvOF0W/dtHElcXvhrPR35nHmhyV3cfz1EzPitMGtU7sYy9Hci3BNK1To6FWmVuuNKPxza1IgCGetSynJZL7fOg==} + peerDependencies: + astro: ^3.0.0 || ^4.0.0 || ^5.0.0-beta.0 + tailwindcss: ^3.0.24 + + '@astrojs/telemetry@3.1.0': + resolution: {integrity: sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA==} + engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} + + '@astrojs/yaml2ts@0.2.2': + resolution: {integrity: sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==} + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.2': + resolution: {integrity: sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.0': + resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.26.2': + resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.25.9': + resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.25.9': + resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.0': + resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.2': + resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.25.9': + resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.25.9': + resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.25.9': + resolution: {integrity: sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.0': + resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} + engines: {node: '>=6.9.0'} + + '@emmetio/abbreviation@2.3.3': + resolution: {integrity: sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==} + + '@emmetio/css-abbreviation@2.1.8': + resolution: {integrity: sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==} + + '@emmetio/css-parser@0.4.0': + resolution: {integrity: sha512-z7wkxRSZgrQHXVzObGkXG+Vmj3uRlpM11oCZ9pbaz0nFejvCDmAiNDpY75+wgXOcffKpj4rzGtwGaZxfJKsJxw==} + + '@emmetio/html-matcher@1.3.0': + resolution: {integrity: sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==} + + '@emmetio/scanner@1.0.4': + resolution: {integrity: sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==} + + '@emmetio/stream-reader-utils@0.1.0': + resolution: {integrity: sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==} + + '@emmetio/stream-reader@2.2.0': + resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@img/sharp-darwin-arm64@0.33.5': + resolution: {integrity: sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.33.5': + resolution: {integrity: sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.0.4': + resolution: {integrity: sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.0.4': + resolution: {integrity: sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.0.4': + resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.0.5': + resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.0.4': + resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.0.4': + resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.33.5': + resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.33.5': + resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-s390x@0.33.5': + resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.33.5': + resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.33.5': + resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.33.5': + resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.33.5': + resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-ia32@0.33.5': + resolution: {integrity: sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.33.5': + resolution: {integrity: sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.27.2': + resolution: {integrity: sha512-Tj+j7Pyzd15wAdSJswvs5CJzJNV+qqSUcr/aCD+jpQSBtXvGnV0pnrjoc8zFTe9fcKCatkpFpOO7yAzpO998HA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.27.2': + resolution: {integrity: sha512-xsPeJgh2ThBpUqlLgRfiVYBEf/P1nWlWvReG+aBWfNv3XEBpa6ZCmxSVnxJgLgkNz4IbxpLy64h2gCmAAQLneQ==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.27.2': + resolution: {integrity: sha512-KnXU4m9MywuZFedL35Z3PuwiTSn/yqRIhrEA9j+7OSkji39NzVkgxuxTYg5F8ryGysq4iFADaU5osSizMXhU2A==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.27.2': + resolution: {integrity: sha512-Hj77A3yTvUeCIx/Vi+4d4IbYhyTwtHj07lVzUgpUq9YpJSEiGJj4vXMKwzJ3w5zp5v3PFvpJNgc/J31smZey6g==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.27.2': + resolution: {integrity: sha512-RjgKf5C3xbn8gxvCm5VgKZ4nn0pRAIe90J0/fdHUsgztd3+Zesb2lm2+r6uX4prV2eUByuxJNdt647/1KPRq5g==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.27.2': + resolution: {integrity: sha512-duq21FoXwQtuws+V9H6UZ+eCBc7fxSpMK1GQINKn3fAyd9DFYKPJNcUhdIKOrMFjLEJgQskoMoiuizMt+dl20g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.27.2': + resolution: {integrity: sha512-6npqOKEPRZkLrMcvyC/32OzJ2srdPzCylJjiTJT2c0bwwSGm7nz2F9mNQ1WrAqCBZROcQn91Fno+khFhVijmFA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.27.2': + resolution: {integrity: sha512-V9Xg6eXtgBtHq2jnuQwM/jr2mwe2EycnopO8cbOvpzFuySCGtKlPCI3Hj9xup/pJK5Q0388qfZZy2DqV2J8ftw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.27.2': + resolution: {integrity: sha512-uCFX9gtZJoQl2xDTpRdseYuNqyKkuMDtH6zSrBTA28yTfKyjN9hQ2B04N5ynR8ILCoSDOrG/Eg+J2TtJ1e/CSA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.27.2': + resolution: {integrity: sha512-/PU9P+7Rkz8JFYDHIi+xzHabOu9qEWR07L5nWLIUsvserrxegZExKCi2jhMZRd0ATdboKylu/K5yAXbp7fYFvA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.27.2': + resolution: {integrity: sha512-eCHmol/dT5odMYi/N0R0HC8V8QE40rEpkyje/ZAXJYNNoSfrObOvG/Mn+s1F/FJyB7co7UQZZf6FuWnN6a7f4g==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.27.2': + resolution: {integrity: sha512-DEP3Njr9/ADDln3kNi76PXonLMSSMiCir0VHXxmGSHxCxDfQ70oWjHcJGfiBugzaqmYdTC7Y+8Int6qbnxPBIQ==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.27.2': + resolution: {integrity: sha512-NHGo5i6IE/PtEPh5m0yw5OmPMpesFnzMIS/lzvN5vknnC1sXM5Z/id5VgcNPgpD+wHmIcuYYgW+Q53v+9s96lQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.27.2': + resolution: {integrity: sha512-PaW2DY5Tan+IFvNJGHDmUrORadbe/Ceh8tQxi8cmdQVCCYsLoQo2cuaSj+AU+YRX8M4ivS2vJ9UGaxfuNN7gmg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.27.2': + resolution: {integrity: sha512-dOlWEMg2gI91Qx5I/HYqOD6iqlJspxLcS4Zlg3vjk1srE67z5T2Uz91yg/qA8sY0XcwQrFzWWiZhMNERylLrpQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.27.2': + resolution: {integrity: sha512-euMIv/4x5Y2/ImlbGl88mwKNXDsvzbWUlT7DFky76z2keajCtcbAsN9LUdmk31hAoVmJJYSThgdA0EsPeTr1+w==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.27.2': + resolution: {integrity: sha512-RsnE6LQkUHlkC10RKngtHNLxb7scFykEbEwOFDjr3CeCMG+Rr+cKqlkKc2/wJ1u4u990urRHCbjz31x84PBrSQ==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.27.2': + resolution: {integrity: sha512-foJM5vv+z2KQmn7emYdDLyTbkoO5bkHZE1oth2tWbQNGW7mX32d46Hz6T0MqXdWS2vBZhaEtHqdy9WYwGfiliA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@1.23.0': + resolution: {integrity: sha512-J4Fo22oBlfRHAXec+1AEzcowv+Qdf4ZQkuP/X/UHYH9+KA9LvyFXSXyS+HxuBRFfon+u7bsmKdRBjoZlbDVRkQ==} + + '@shikijs/engine-javascript@1.23.0': + resolution: {integrity: sha512-CcrppseWShG+8Efp1iil9divltuXVdCaU4iu+CKvzTGZO5RmXyAiSx668M7VbX8+s/vt1ZKu75Vn/jWi8O3G/Q==} + + '@shikijs/engine-oniguruma@1.23.0': + resolution: {integrity: sha512-gS8bZLqVvmZXX+E5JUMJICsBp+kx6gj79MH/UEpKHKIqnUzppgbmEn6zLa6mB5D+sHse2gFei3YYJxQe1EzZXQ==} + + '@shikijs/types@1.23.0': + resolution: {integrity: sha512-HiwzsihRao+IbPk7FER/EQT/D0dEEK3n5LAtHDzL5iRT+JMblA7y9uitUnjEnHeLkKigNM+ZplrP7MuEyyc5kA==} + + '@shikijs/vscode-textmate@9.3.0': + resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/mdast@4.0.4': + resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + + '@types/ms@0.7.34': + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/unist@3.0.3': + resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + '@volar/kit@2.4.10': + resolution: {integrity: sha512-ul+rLeO9RlFDgkY/FhPWMnpFqAsjvjkKz8VZeOY5YCJMwTblmmSBlNJtFNxSBx9t/k1q80nEthLyxiJ50ZbIAg==} + peerDependencies: + typescript: '*' + + '@volar/language-core@2.4.10': + resolution: {integrity: sha512-hG3Z13+nJmGaT+fnQzAkS0hjJRa2FCeqZt6Bd+oGNhUkQ+mTFsDETg5rqUTxyzIh5pSOGY7FHCWUS8G82AzLCA==} + + '@volar/language-server@2.4.10': + resolution: {integrity: sha512-odQsgrJh8hOXfxkSj/BSnpjThb2/KDhbxZnG/XAEx6E3QGDQv4hAOz9GWuKoNs0tkjgwphQGIwDMT1JYaTgRJw==} + + '@volar/language-service@2.4.10': + resolution: {integrity: sha512-VxUiWS11rnRzakkqw5x1LPhsz+RBfD0CrrFarLGW2/voliYXEdCuSOM3r8JyNRvMvP4uwhD38ccAdTcULQEAIQ==} + + '@volar/source-map@2.4.10': + resolution: {integrity: sha512-OCV+b5ihV0RF3A7vEvNyHPi4G4kFa6ukPmyVocmqm5QzOd8r5yAtiNvaPEjl8dNvgC/lj4JPryeeHLdXd62rWA==} + + '@volar/typescript@2.4.10': + resolution: {integrity: sha512-F8ZtBMhSXyYKuBfGpYwqA5rsONnOwAVvjyE7KPYJ7wgZqo2roASqNWUnianOomJX5u1cxeRooHV59N0PhvEOgw==} + + '@vscode/emmet-helper@2.10.0': + resolution: {integrity: sha512-UHw1EQRgLbSYkyB73/7wR/IzV6zTBnbzEHuuU4Z6b95HKf2lmeTdGwBIwspWBSRrnIA1TI2x2tetBym6ErA7Gw==} + + '@vscode/l10n@0.0.18': + resolution: {integrity: sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + astro@4.16.13: + resolution: {integrity: sha512-Mtd76+BC0zLWqoXpf9xc731AhdH4MNh5JFHYdLRvSH0Nqn48hA64dPGh/cWsJvh/DZFmC0NTZusM1Qq2gyNaVg==} + engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.24.2: + resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + caniuse-lite@1.0.30001680: + resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.1: + resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} + engines: {node: '>= 14.16.0'} + + ci-info@4.1.0: + resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + cli-cursor@5.0.0: + resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==} + engines: {node: '>=18'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cross-spawn@7.0.5: + resolution: {integrity: sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + + devalue@5.1.1: + resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.5.62: + resolution: {integrity: sha512-t8c+zLmJHa9dJy96yBZRXGQYoiCEnHYgFwn1asvSPZSUdVxnB62A4RASd7k41ytG3ErFBA0TpHlKg9D9SQBmLg==} + + emmet@2.4.11: + resolution: {integrity: sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==} + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + extend-shallow@2.0.1: + resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} + engines: {node: '>=0.10.0'} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-uri@3.0.3: + resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} + + fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-east-asian-width@1.3.0: + resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==} + engines: {node: '>=18'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + gray-matter@4.0.3: + resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} + engines: {node: '>=6.0'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-raw@9.1.0: + resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} + + hast-util-to-html@9.0.3: + resolution: {integrity: sha512-M17uBDzMJ9RPCqLMO92gNNUDuBSq10a25SDBI08iCCxmorf4Yy6sYHK57n9WAbRAAaU+DuR4W6GN9K4DFZesYg==} + + hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.15.1: + resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} + engines: {node: '>= 0.4'} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extendable@0.1.1: + resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} + engines: {node: '>=0.10.0'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + + is-unicode-supported@2.1.0: + resolution: {integrity: sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==} + engines: {node: '>=18'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonc-parser@2.3.1: + resolution: {integrity: sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==} + + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + magic-string@0.30.12: + resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + markdown-table@3.0.4: + resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + + mdast-util-from-markdown@2.0.2: + resolution: {integrity: sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==} + + mdast-util-gfm-autolink-literal@2.0.1: + resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} + + mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.2.0: + resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==} + + mdast-util-to-markdown@2.1.2: + resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-core-commonmark@2.0.2: + resolution: {integrity: sha512-FKjQKbxd1cibWMM1P9N+H8TwlgGgSkWZMmfuVucLCHaYqeSvJ0hFeHsIa65pA2nYbes0f8LDHPMrd9X7Ujxg9w==} + + micromark-extension-gfm-autolink-literal@2.1.0: + resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} + + micromark-extension-gfm-footnote@2.1.0: + resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} + + micromark-extension-gfm-strikethrough@2.1.0: + resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} + + micromark-extension-gfm-table@2.1.0: + resolution: {integrity: sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.1.0: + resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-factory-destination@2.0.1: + resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} + + micromark-factory-label@2.0.1: + resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} + + micromark-factory-space@2.0.1: + resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} + + micromark-factory-title@2.0.1: + resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} + + micromark-factory-whitespace@2.0.1: + resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} + + micromark-util-character@2.1.1: + resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} + + micromark-util-chunked@2.0.1: + resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} + + micromark-util-classify-character@2.0.1: + resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} + + micromark-util-combine-extensions@2.0.1: + resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} + + micromark-util-decode-numeric-character-reference@2.0.2: + resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} + + micromark-util-decode-string@2.0.1: + resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} + + micromark-util-encode@2.0.1: + resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} + + micromark-util-html-tag-name@2.0.1: + resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} + + micromark-util-normalize-identifier@2.0.1: + resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} + + micromark-util-resolve-all@2.0.1: + resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} + + micromark-util-sanitize-uri@2.0.1: + resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} + + micromark-util-subtokenize@2.0.2: + resolution: {integrity: sha512-xKxhkB62vwHUuuxHe9Xqty3UaAsizV2YKq5OV344u3hFBbf8zIYrhYOWhAQb94MtMPkjTOzzjJ/hid9/dR5vFA==} + + micromark-util-symbol@2.0.1: + resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} + + micromark-util-types@2.0.1: + resolution: {integrity: sha512-534m2WhVTddrcKVepwmVEVnUAmtrx9bfIjNoQHRqfnvdaHQiFytEhJoTgpWJvDEXCO5gLTQh3wYC1PgOJA4NSQ==} + + micromark@4.0.1: + resolution: {integrity: sha512-eBPdkcoCNvYcxQOAKAlceo5SNdzZWfF+FcSupREAzdAh9rRmE239CEQAiTwIgblwnoM8zzj35sZ5ZwvSEOF6Kw==} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mimic-function@5.0.1: + resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} + engines: {node: '>=18'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + muggle-string@0.4.1: + resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-releases@2.0.18: + resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + onetime@7.0.0: + resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} + engines: {node: '>=18'} + + oniguruma-to-es@0.1.2: + resolution: {integrity: sha512-sBYKVJlIMB0WPO+tSu/NNB1ytSFeHyyJZ3Ayxfx3f/QUuXu0lvZk0VB4K7npmdlHSC0ldqanzh/sUSlAbgCTfw==} + + ora@8.1.1: + resolution: {integrity: sha512-YWielGi1XzG1UTvOaCFaNgEnuhZVMSHYkW/FQ7UX8O26PtlpdM84c0f7wLPlkvx2RfiQmnzd61d/MGxmpQeJPw==} + engines: {node: '>=18'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + + p-timeout@6.1.3: + resolution: {integrity: sha512-UJUyfKbwvr/uZSV6btANfb+0t/mOhKV/KXcCUTp8FcQI+v/0d+wXqH4htrW0E4rR6WiEO/EPvUFiV9D5OI4vlw==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.2.1: + resolution: {integrity: sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==} + + path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + + preferred-pm@4.0.0: + resolution: {integrity: sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==} + engines: {node: '>=18.12'} + + prettier@2.8.7: + resolution: {integrity: sha512-yPngTo3aXUUmyuTjeTUT75txrf+aMh9FiD7q9ZE/i6r0bPb22g4FsE6Y338PQX1bmfy08i9QQCB7/rcUAVntfw==} + engines: {node: '>=10.13.0'} + hasBin: true + + prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@6.5.0: + resolution: {integrity: sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.0.2: + resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} + engines: {node: '>= 14.16.0'} + + regex-recursion@4.2.1: + resolution: {integrity: sha512-QHNZyZAeKdndD1G3bKAbBEKOSSK4KOHQrAJ01N1LJeb0SoH4DJIeFhp0uUpETgONifS4+P3sOgoA1dhzgrQvhA==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@4.4.0: + resolution: {integrity: sha512-uCUSuobNVeqUupowbdZub6ggI5/JZkYyJdDogddJr60L764oxC2pMZov1fQ3wM9bdyzUILDG+Sqx6NAKAz9rKQ==} + + rehype-parse@9.0.1: + resolution: {integrity: sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.1: + resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + request-light@0.5.8: + resolution: {integrity: sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==} + + request-light@0.7.0: + resolution: {integrity: sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + restore-cursor@5.1.0: + resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} + engines: {node: '>=18'} + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.2.0: + resolution: {integrity: sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.27.2: + resolution: {integrity: sha512-KreA+PzWmk2yaFmZVwe6GB2uBD86nXl86OsDkt1bJS9p3vqWuEQ6HnJJ+j/mZi/q0920P99/MVRlB4L3crpF5w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + section-matter@1.0.0: + resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} + engines: {node: '>=4'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.33.5: + resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@1.23.0: + resolution: {integrity: sha512-xfdu9DqPkIpExH29cmiTlgo0/jBki5la1Tkfhsv+Wu5TT3APLNHslR1acxuKJOCWqVdSc+pIbs/2ozjVRGppdg==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + stringify-entities@4.0.4: + resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom-string@1.0.0: + resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} + engines: {node: '>=0.10.0'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwindcss@3.4.15: + resolution: {integrity: sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.2.0: + resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsconfck@3.1.4: + resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + type-fest@4.27.0: + resolution: {integrity: sha512-3IMSWgP7C5KSQqmo1wjhKrwsvXAtF33jO3QY+Uy++ia7hqvgSK6iXbbg5PbDBc1P2ZbNEDgejOrN4YooXvhwCw==} + engines: {node: '>=16'} + + typesafe-path@0.2.2: + resolution: {integrity: sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==} + + typescript-auto-import-cache@0.3.5: + resolution: {integrity: sha512-fAIveQKsoYj55CozUiBoj4b/7WpN0i4o74wiGY5JVUEoD0XiqDk1tJqTEjgzL2/AizKQrXxyRosSebyDzBZKjw==} + + typescript@5.6.3: + resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==} + engines: {node: '>=14.17'} + hasBin: true + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + update-browserslist-db@1.1.1: + resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-location@5.0.3: + resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + + vitefu@1.0.3: + resolution: {integrity: sha512-iKKfOMBHob2WxEJbqbJjHAkmYgvFDPhuqrO82om83S8RLk+17FtyMBfcyeH8GqD0ihShtkMW/zzJgiA51hCNCQ==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0-beta.0 + peerDependenciesMeta: + vite: + optional: true + + volar-service-css@0.0.62: + resolution: {integrity: sha512-JwNyKsH3F8PuzZYuqPf+2e+4CTU8YoyUHEHVnoXNlrLe7wy9U3biomZ56llN69Ris7TTy/+DEX41yVxQpM4qvg==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-emmet@0.0.62: + resolution: {integrity: sha512-U4dxWDBWz7Pi4plpbXf4J4Z/ss6kBO3TYrACxWNsE29abu75QzVS0paxDDhI6bhqpbDFXlpsDhZ9aXVFpnfGRQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-html@0.0.62: + resolution: {integrity: sha512-Zw01aJsZRh4GTGUjveyfEzEqpULQUdQH79KNEiKVYHZyuGtdBRYCHlrus1sueSNMxwwkuF5WnOHfvBzafs8yyQ==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-prettier@0.0.62: + resolution: {integrity: sha512-h2yk1RqRTE+vkYZaI9KYuwpDfOQRrTEMvoHol0yW4GFKc75wWQRrb5n/5abDrzMPrkQbSip8JH2AXbvrRtYh4w==} + peerDependencies: + '@volar/language-service': ~2.4.0 + prettier: ^2.2 || ^3.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + prettier: + optional: true + + volar-service-typescript-twoslash-queries@0.0.62: + resolution: {integrity: sha512-KxFt4zydyJYYI0kFAcWPTh4u0Ha36TASPZkAnNY784GtgajerUqM80nX/W1d0wVhmcOFfAxkVsf/Ed+tiYU7ng==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-typescript@0.0.62: + resolution: {integrity: sha512-p7MPi71q7KOsH0eAbZwPBiKPp9B2+qrdHAd6VY5oTo9BUXatsOAdakTm9Yf0DUj6uWBAaOT01BSeVOPwucMV1g==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + volar-service-yaml@0.0.62: + resolution: {integrity: sha512-k7gvv7sk3wa+nGll3MaSKyjwQsJjIGCHFjVkl3wjaSP2nouKyn9aokGmqjrl39mi88Oy49giog2GkZH526wjig==} + peerDependencies: + '@volar/language-service': ~2.4.0 + peerDependenciesMeta: + '@volar/language-service': + optional: true + + vscode-css-languageservice@6.3.1: + resolution: {integrity: sha512-1BzTBuJfwMc3A0uX4JBdJgoxp74cjj4q2mDJdp49yD/GuAq4X0k5WtK6fNcMYr+FfJ9nqgR6lpfCSZDkARJ5qQ==} + + vscode-html-languageservice@5.3.1: + resolution: {integrity: sha512-ysUh4hFeW/WOWz/TO9gm08xigiSsV/FOAZ+DolgJfeLftna54YdmZ4A+lIn46RbdO3/Qv5QHTn1ZGqmrXQhZyA==} + + vscode-json-languageservice@4.1.8: + resolution: {integrity: sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==} + engines: {npm: '>=7.0.0'} + + vscode-jsonrpc@6.0.0: + resolution: {integrity: sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg==} + engines: {node: '>=8.0.0 || >=10.0.0'} + + vscode-jsonrpc@8.2.0: + resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} + engines: {node: '>=14.0.0'} + + vscode-languageserver-protocol@3.16.0: + resolution: {integrity: sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==} + + vscode-languageserver-protocol@3.17.5: + resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} + + vscode-languageserver-textdocument@1.0.12: + resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} + + vscode-languageserver-types@3.16.0: + resolution: {integrity: sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA==} + + vscode-languageserver-types@3.17.5: + resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} + + vscode-languageserver@7.0.0: + resolution: {integrity: sha512-60HTx5ID+fLRcgdHfmz0LDZAXYEV68fzwG0JWwEPBode9NuMYTIxuYXPg4ngO8i8+Ou0lM7y6GzaYWbiDL0drw==} + hasBin: true + + vscode-languageserver@9.0.1: + resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} + hasBin: true + + vscode-nls@5.2.0: + resolution: {integrity: sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==} + + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + which-pm@3.0.0: + resolution: {integrity: sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==} + engines: {node: '>=18.12'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + xxhash-wasm@1.0.2: + resolution: {integrity: sha512-ibF0Or+FivM9lNrg+HGJfVX8WJqgo+kCLDc4vx6xMeTce7Aj+DLttKbxxRR/gNLSAelRc1omAPlJ77N/Jem07A==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml-language-server@1.15.0: + resolution: {integrity: sha512-N47AqBDCMQmh6mBLmI6oqxryHRzi33aPFPsJhYy3VTUGCdLHYjGh4FZzpUjRlphaADBBkDmnkM/++KNIOHi5Rw==} + hasBin: true + + yaml@2.2.2: + resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} + engines: {node: '>= 14'} + + yaml@2.6.0: + resolution: {integrity: sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + zod-to-json-schema@3.23.5: + resolution: {integrity: sha512-5wlSS0bXfF/BrL4jPAbz9da5hDlDptdEppYfe+x4eIJ7jioqKG9uUxOwPzqof09u/XeVdrgFu29lZi+8XNDJtA==} + peerDependencies: + zod: ^3.23.3 + + zod-to-ts@1.2.0: + resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + + '@astrojs/check@0.9.4(typescript@5.6.3)': + dependencies: + '@astrojs/language-server': 2.15.4(typescript@5.6.3) + chokidar: 4.0.1 + kleur: 4.1.5 + typescript: 5.6.3 + yargs: 17.7.2 + transitivePeerDependencies: + - prettier + - prettier-plugin-astro + + '@astrojs/compiler@2.10.3': {} + + '@astrojs/internal-helpers@0.4.1': {} + + '@astrojs/language-server@2.15.4(typescript@5.6.3)': + dependencies: + '@astrojs/compiler': 2.10.3 + '@astrojs/yaml2ts': 0.2.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@volar/kit': 2.4.10(typescript@5.6.3) + '@volar/language-core': 2.4.10 + '@volar/language-server': 2.4.10 + '@volar/language-service': 2.4.10 + fast-glob: 3.3.2 + muggle-string: 0.4.1 + volar-service-css: 0.0.62(@volar/language-service@2.4.10) + volar-service-emmet: 0.0.62(@volar/language-service@2.4.10) + volar-service-html: 0.0.62(@volar/language-service@2.4.10) + volar-service-prettier: 0.0.62(@volar/language-service@2.4.10) + volar-service-typescript: 0.0.62(@volar/language-service@2.4.10) + volar-service-typescript-twoslash-queries: 0.0.62(@volar/language-service@2.4.10) + volar-service-yaml: 0.0.62(@volar/language-service@2.4.10) + vscode-html-languageservice: 5.3.1 + vscode-uri: 3.0.8 + transitivePeerDependencies: + - typescript + + '@astrojs/markdown-remark@5.3.0': + dependencies: + '@astrojs/prism': 3.1.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.1.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + remark-smartypants: 3.0.2 + shiki: 1.23.0 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.0.0 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@3.1.0': + dependencies: + prismjs: 1.29.0 + + '@astrojs/tailwind@5.1.2(astro@4.16.13(rollup@4.27.2)(typescript@5.6.3))(tailwindcss@3.4.15)': + dependencies: + astro: 4.16.13(rollup@4.27.2)(typescript@5.6.3) + autoprefixer: 10.4.20(postcss@8.4.49) + postcss: 8.4.49 + postcss-load-config: 4.0.2(postcss@8.4.49) + tailwindcss: 3.4.15 + transitivePeerDependencies: + - ts-node + + '@astrojs/telemetry@3.1.0': + dependencies: + ci-info: 4.1.0 + debug: 4.3.7 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.0 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + + '@astrojs/yaml2ts@0.2.2': + dependencies: + yaml: 2.6.0 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.2': {} + + '@babel/core@7.26.0': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/helper-compilation-targets': 7.25.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) + '@babel/helpers': 7.26.0 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + convert-source-map: 2.0.0 + debug: 4.3.7 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.26.2': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.0.2 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.26.0 + + '@babel/helper-compilation-targets@7.25.9': + dependencies: + '@babel/compat-data': 7.26.2 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.25.9': {} + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helpers@7.26.0': + dependencies: + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + + '@babel/parser@7.26.2': + dependencies: + '@babel/types': 7.26.0 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-plugin-utils': 7.25.9 + + '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/types': 7.26.0 + transitivePeerDependencies: + - supports-color + + '@babel/template@7.25.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + + '@babel/traverse@7.25.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.2 + '@babel/parser': 7.26.2 + '@babel/template': 7.25.9 + '@babel/types': 7.26.0 + debug: 4.3.7 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.0': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@emmetio/abbreviation@2.3.3': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-abbreviation@2.1.8': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/css-parser@0.4.0': + dependencies: + '@emmetio/stream-reader': 2.2.0 + '@emmetio/stream-reader-utils': 0.1.0 + + '@emmetio/html-matcher@1.3.0': + dependencies: + '@emmetio/scanner': 1.0.4 + + '@emmetio/scanner@1.0.4': {} + + '@emmetio/stream-reader-utils@0.1.0': {} + + '@emmetio/stream-reader@2.2.0': {} + + '@emnapi/runtime@1.3.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@img/sharp-darwin-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.4 + optional: true + + '@img/sharp-darwin-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.4 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.5': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.4': + optional: true + + '@img/sharp-linux-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.4 + optional: true + + '@img/sharp-linux-arm@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.5 + optional: true + + '@img/sharp-linux-s390x@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.4 + optional: true + + '@img/sharp-linux-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + optional: true + + '@img/sharp-wasm32@0.33.5': + dependencies: + '@emnapi/runtime': 1.3.1 + optional: true + + '@img/sharp-win32-ia32@0.33.5': + optional: true + + '@img/sharp-win32-x64@0.33.5': + optional: true + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + + '@oslojs/encoding@1.1.0': {} + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@rollup/pluginutils@5.1.3(rollup@4.27.2)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.27.2 + + '@rollup/rollup-android-arm-eabi@4.27.2': + optional: true + + '@rollup/rollup-android-arm64@4.27.2': + optional: true + + '@rollup/rollup-darwin-arm64@4.27.2': + optional: true + + '@rollup/rollup-darwin-x64@4.27.2': + optional: true + + '@rollup/rollup-freebsd-arm64@4.27.2': + optional: true + + '@rollup/rollup-freebsd-x64@4.27.2': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.27.2': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.27.2': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.27.2': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.27.2': + optional: true + + '@rollup/rollup-linux-x64-musl@4.27.2': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.27.2': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.27.2': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.27.2': + optional: true + + '@shikijs/core@1.23.0': + dependencies: + '@shikijs/engine-javascript': 1.23.0 + '@shikijs/engine-oniguruma': 1.23.0 + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + + '@shikijs/engine-javascript@1.23.0': + dependencies: + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + oniguruma-to-es: 0.1.2 + + '@shikijs/engine-oniguruma@1.23.0': + dependencies: + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + + '@shikijs/types@1.23.0': + dependencies: + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + + '@shikijs/vscode-textmate@9.3.0': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.0 + + '@types/cookie@0.6.0': {} + + '@types/debug@4.1.12': + dependencies: + '@types/ms': 0.7.34 + + '@types/estree@1.0.6': {} + + '@types/hast@3.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/mdast@4.0.4': + dependencies: + '@types/unist': 3.0.3 + + '@types/ms@0.7.34': {} + + '@types/nlcst@2.0.3': + dependencies: + '@types/unist': 3.0.3 + + '@types/unist@3.0.3': {} + + '@ungap/structured-clone@1.2.0': {} + + '@volar/kit@2.4.10(typescript@5.6.3)': + dependencies: + '@volar/language-service': 2.4.10 + '@volar/typescript': 2.4.10 + typesafe-path: 0.2.2 + typescript: 5.6.3 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + + '@volar/language-core@2.4.10': + dependencies: + '@volar/source-map': 2.4.10 + + '@volar/language-server@2.4.10': + dependencies: + '@volar/language-core': 2.4.10 + '@volar/language-service': 2.4.10 + '@volar/typescript': 2.4.10 + path-browserify: 1.0.1 + request-light: 0.7.0 + vscode-languageserver: 9.0.1 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + + '@volar/language-service@2.4.10': + dependencies: + '@volar/language-core': 2.4.10 + vscode-languageserver-protocol: 3.17.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + + '@volar/source-map@2.4.10': {} + + '@volar/typescript@2.4.10': + dependencies: + '@volar/language-core': 2.4.10 + path-browserify: 1.0.1 + vscode-uri: 3.0.8 + + '@vscode/emmet-helper@2.10.0': + dependencies: + emmet: 2.4.11 + jsonc-parser: 2.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + + '@vscode/l10n@0.0.18': {} + + acorn@8.14.0: {} + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-align@3.0.1: + dependencies: + string-width: 4.2.3 + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-query@5.3.2: {} + + array-iterate@2.0.1: {} + + astro@4.16.13(rollup@4.27.2)(typescript@5.6.3): + dependencies: + '@astrojs/compiler': 2.10.3 + '@astrojs/internal-helpers': 0.4.1 + '@astrojs/markdown-remark': 5.3.0 + '@astrojs/telemetry': 3.1.0 + '@babel/core': 7.26.0 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.0) + '@babel/types': 7.26.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.1.3(rollup@4.27.2) + '@types/babel__core': 7.20.5 + '@types/cookie': 0.6.0 + acorn: 8.14.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.1.0 + clsx: 2.1.1 + common-ancestor-path: 1.0.1 + cookie: 0.7.2 + cssesc: 3.0.0 + debug: 4.3.7 + deterministic-object-hash: 2.0.2 + devalue: 5.1.1 + diff: 5.2.0 + dlv: 1.1.3 + dset: 3.1.4 + es-module-lexer: 1.5.4 + esbuild: 0.21.5 + estree-walker: 3.0.3 + fast-glob: 3.3.2 + flattie: 1.1.1 + github-slugger: 2.0.0 + gray-matter: 4.0.3 + html-escaper: 3.0.3 + http-cache-semantics: 4.1.1 + js-yaml: 4.1.0 + kleur: 4.1.5 + magic-string: 0.30.12 + magicast: 0.3.5 + micromatch: 4.0.8 + mrmime: 2.0.0 + neotraverse: 0.6.18 + ora: 8.1.1 + p-limit: 6.1.0 + p-queue: 8.0.1 + preferred-pm: 4.0.0 + prompts: 2.4.2 + rehype: 13.0.2 + semver: 7.6.3 + shiki: 1.23.0 + tinyexec: 0.3.1 + tsconfck: 3.1.4(typescript@5.6.3) + unist-util-visit: 5.0.0 + vfile: 6.0.3 + vite: 5.4.11 + vitefu: 1.0.3(vite@5.4.11) + which-pm: 3.0.0 + xxhash-wasm: 1.0.2 + yargs-parser: 21.1.1 + zod: 3.23.8 + zod-to-json-schema: 3.23.5(zod@3.23.8) + zod-to-ts: 1.2.0(typescript@5.6.3)(zod@3.23.8) + optionalDependencies: + sharp: 0.33.5 + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - rollup + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - typescript + + autoprefixer@10.4.20(postcss@8.4.49): + dependencies: + browserslist: 4.24.2 + caniuse-lite: 1.0.30001680 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + + axobject-query@4.1.0: {} + + bail@2.0.2: {} + + balanced-match@1.0.2: {} + + base-64@1.0.0: {} + + binary-extensions@2.3.0: {} + + boxen@8.0.1: + dependencies: + ansi-align: 3.0.1 + camelcase: 8.0.0 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 7.2.0 + type-fest: 4.27.0 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.24.2: + dependencies: + caniuse-lite: 1.0.30001680 + electron-to-chromium: 1.5.62 + node-releases: 2.0.18 + update-browserslist-db: 1.1.1(browserslist@4.24.2) + + camelcase-css@2.0.1: {} + + camelcase@8.0.0: {} + + caniuse-lite@1.0.30001680: {} + + ccount@2.0.1: {} + + chalk@5.3.0: {} + + character-entities-html4@2.1.0: {} + + character-entities-legacy@3.0.0: {} + + character-entities@2.0.2: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.1: + dependencies: + readdirp: 4.0.2 + + ci-info@4.1.0: {} + + cli-boxes@3.0.0: {} + + cli-cursor@5.0.0: + dependencies: + restore-cursor: 5.1.0 + + cli-spinners@2.9.2: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@4.2.3: + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + + comma-separated-tokens@2.0.3: {} + + commander@4.1.1: {} + + common-ancestor-path@1.0.1: {} + + convert-source-map@2.0.0: {} + + cookie@0.7.2: {} + + cross-spawn@7.0.5: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + cssesc@3.0.0: {} + + debug@4.3.7: + dependencies: + ms: 2.1.3 + + decode-named-character-reference@1.0.2: + dependencies: + character-entities: 2.0.2 + + dequal@2.0.3: {} + + detect-libc@2.0.3: {} + + deterministic-object-hash@2.0.2: + dependencies: + base-64: 1.0.0 + + devalue@5.1.1: {} + + devlop@1.1.0: + dependencies: + dequal: 2.0.3 + + didyoumean@1.2.2: {} + + diff@5.2.0: {} + + dlv@1.1.3: {} + + dset@3.1.4: {} + + eastasianwidth@0.2.0: {} + + electron-to-chromium@1.5.62: {} + + emmet@2.4.11: + dependencies: + '@emmetio/abbreviation': 2.3.3 + '@emmetio/css-abbreviation': 2.1.8 + + emoji-regex-xs@1.0.0: {} + + emoji-regex@10.4.0: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + entities@4.5.0: {} + + es-module-lexer@1.5.4: {} + + esbuild@0.21.5: + optionalDependencies: + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + escalade@3.2.0: {} + + escape-string-regexp@5.0.0: {} + + esprima@4.0.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + eventemitter3@5.0.1: {} + + extend-shallow@2.0.1: + dependencies: + is-extendable: 0.1.1 + + extend@3.0.2: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.2: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-uri@3.0.3: {} + + fastq@1.17.1: + dependencies: + reusify: 1.0.4 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up-simple@1.0.0: {} + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-yarn-workspace-root2@1.2.16: + dependencies: + micromatch: 4.0.8 + pkg-dir: 4.2.0 + + flattie@1.1.1: {} + + foreground-child@3.3.0: + dependencies: + cross-spawn: 7.0.5 + signal-exit: 4.1.0 + + fraction.js@4.3.7: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-east-asian-width@1.3.0: {} + + github-slugger@2.0.0: {} + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob@10.4.5: + dependencies: + foreground-child: 3.3.0 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + globals@11.12.0: {} + + graceful-fs@4.2.11: {} + + gray-matter@4.0.3: + dependencies: + js-yaml: 3.14.1 + kind-of: 6.0.3 + section-matter: 1.0.0 + strip-bom-string: 1.0.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hast-util-from-html@2.0.3: + dependencies: + '@types/hast': 3.0.4 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.2.1 + vfile: 6.0.3 + vfile-message: 4.0.2 + + hast-util-from-parse5@8.0.1: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.5.0 + vfile: 6.0.3 + vfile-location: 5.0.3 + web-namespaces: 2.0.1 + + hast-util-is-element@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-parse-selector@4.0.0: + dependencies: + '@types/hast': 3.0.4 + + hast-util-raw@9.1.0: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + parse5: 7.2.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-html@9.0.3: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.2.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.4 + zwitch: 2.0.4 + + hast-util-to-parse5@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + + hast-util-to-text@4.0.2: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.3 + hast-util-is-element: 3.0.0 + unist-util-find-after: 5.0.0 + + hast-util-whitespace@3.0.0: + dependencies: + '@types/hast': 3.0.4 + + hastscript@8.0.0: + dependencies: + '@types/hast': 3.0.4 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.5.0 + space-separated-tokens: 2.0.2 + + html-escaper@3.0.3: {} + + html-void-elements@3.0.0: {} + + http-cache-semantics@4.1.1: {} + + import-meta-resolve@4.1.0: {} + + is-arrayish@0.3.2: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.15.1: + dependencies: + hasown: 2.0.2 + + is-docker@3.0.0: {} + + is-extendable@0.1.1: {} + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-interactive@2.0.0: {} + + is-number@7.0.0: {} + + is-plain-obj@4.1.0: {} + + is-unicode-supported@1.3.0: {} + + is-unicode-supported@2.1.0: {} + + is-wsl@3.1.0: + dependencies: + is-inside-container: 1.0.0 + + isexe@2.0.0: {} + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jiti@1.21.6: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.0.2: {} + + json-schema-traverse@1.0.0: {} + + json5@2.2.3: {} + + jsonc-parser@2.3.1: {} + + jsonc-parser@3.3.1: {} + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + kleur@4.1.5: {} + + lilconfig@2.1.0: {} + + lilconfig@3.1.2: {} + + lines-and-columns@1.2.4: {} + + load-yaml-file@0.2.0: + dependencies: + graceful-fs: 4.2.11 + js-yaml: 3.14.1 + pify: 4.0.1 + strip-bom: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + lodash@4.17.21: {} + + log-symbols@6.0.0: + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + + longest-streak@3.1.0: {} + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + magic-string@0.30.12: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.2 + '@babel/types': 7.26.0 + source-map-js: 1.2.1 + + markdown-table@3.0.4: {} + + mdast-util-definitions@6.0.0: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + unist-util-visit: 5.0.0 + + mdast-util-find-and-replace@3.0.1: + dependencies: + '@types/mdast': 4.0.4 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + mdast-util-from-markdown@2.0.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-decode-string: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-autolink-literal@2.0.1: + dependencies: + '@types/mdast': 4.0.4 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.1.1 + + mdast-util-gfm-footnote@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + micromark-util-normalize-identifier: 2.0.1 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-strikethrough@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-table@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + markdown-table: 3.0.4 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm-task-list-item@2.0.0: + dependencies: + '@types/mdast': 4.0.4 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.2 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-gfm@3.0.0: + dependencies: + mdast-util-from-markdown: 2.0.2 + mdast-util-gfm-autolink-literal: 2.0.1 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.2 + transitivePeerDependencies: + - supports-color + + mdast-util-phrasing@4.1.0: + dependencies: + '@types/mdast': 4.0.4 + unist-util-is: 6.0.0 + + mdast-util-to-hast@13.2.0: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.1 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.3 + + mdast-util-to-markdown@2.1.2: + dependencies: + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-classify-character: 2.0.1 + micromark-util-decode-string: 2.0.1 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + + mdast-util-to-string@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + + merge2@1.4.1: {} + + micromark-core-commonmark@2.0.2: + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.1 + micromark-factory-label: 2.0.1 + micromark-factory-space: 2.0.1 + micromark-factory-title: 2.0.1 + micromark-factory-whitespace: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-html-tag-name: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-subtokenize: 2.0.2 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-autolink-literal@2.1.0: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-footnote@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-core-commonmark: 2.0.2 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-strikethrough@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-classify-character: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-table@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm-tagfilter@2.0.0: + dependencies: + micromark-util-types: 2.0.1 + + micromark-extension-gfm-task-list-item@2.1.0: + dependencies: + devlop: 1.1.0 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-extension-gfm@3.0.0: + dependencies: + micromark-extension-gfm-autolink-literal: 2.1.0 + micromark-extension-gfm-footnote: 2.1.0 + micromark-extension-gfm-strikethrough: 2.1.0 + micromark-extension-gfm-table: 2.1.0 + micromark-extension-gfm-tagfilter: 2.0.0 + micromark-extension-gfm-task-list-item: 2.1.0 + micromark-util-combine-extensions: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-destination@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-label@2.0.1: + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-space@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-types: 2.0.1 + + micromark-factory-title@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-factory-whitespace@2.0.1: + dependencies: + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-character@2.1.1: + dependencies: + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-chunked@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-classify-character@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-combine-extensions@2.0.1: + dependencies: + micromark-util-chunked: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-decode-numeric-character-reference@2.0.2: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-decode-string@2.0.1: + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-symbol: 2.0.1 + + micromark-util-encode@2.0.1: {} + + micromark-util-html-tag-name@2.0.1: {} + + micromark-util-normalize-identifier@2.0.1: + dependencies: + micromark-util-symbol: 2.0.1 + + micromark-util-resolve-all@2.0.1: + dependencies: + micromark-util-types: 2.0.1 + + micromark-util-sanitize-uri@2.0.1: + dependencies: + micromark-util-character: 2.1.1 + micromark-util-encode: 2.0.1 + micromark-util-symbol: 2.0.1 + + micromark-util-subtokenize@2.0.2: + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.1 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + + micromark-util-symbol@2.0.1: {} + + micromark-util-types@2.0.1: {} + + micromark@4.0.1: + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.7 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.2 + micromark-factory-space: 2.0.1 + micromark-util-character: 2.1.1 + micromark-util-chunked: 2.0.1 + micromark-util-combine-extensions: 2.0.1 + micromark-util-decode-numeric-character-reference: 2.0.2 + micromark-util-encode: 2.0.1 + micromark-util-normalize-identifier: 2.0.1 + micromark-util-resolve-all: 2.0.1 + micromark-util-sanitize-uri: 2.0.1 + micromark-util-subtokenize: 2.0.2 + micromark-util-symbol: 2.0.1 + micromark-util-types: 2.0.1 + transitivePeerDependencies: + - supports-color + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mimic-function@5.0.1: {} + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minipass@7.1.2: {} + + mrmime@2.0.0: {} + + ms@2.1.3: {} + + muggle-string@0.4.1: {} + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoid@3.3.7: {} + + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + + node-releases@2.0.18: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + onetime@7.0.0: + dependencies: + mimic-function: 5.0.1 + + oniguruma-to-es@0.1.2: + dependencies: + emoji-regex-xs: 1.0.0 + regex: 4.4.0 + regex-recursion: 4.2.1 + + ora@8.1.1: + dependencies: + chalk: 5.3.0 + cli-cursor: 5.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.1.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@6.1.0: + dependencies: + yocto-queue: 1.1.1 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-queue@8.0.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 6.1.3 + + p-timeout@6.1.3: {} + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + parse-latin@7.0.0: + dependencies: + '@types/nlcst': 2.0.3 + '@types/unist': 3.0.3 + nlcst-to-string: 4.0.0 + unist-util-modify-children: 4.0.0 + unist-util-visit-children: 3.0.0 + vfile: 6.0.3 + + parse5@7.2.1: + dependencies: + entities: 4.5.0 + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.2: {} + + pify@2.3.0: {} + + pify@4.0.1: {} + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + postcss-import@15.1.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.8 + + postcss-js@4.0.1(postcss@8.4.49): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.4.49 + + postcss-load-config@4.0.2(postcss@8.4.49): + dependencies: + lilconfig: 3.1.2 + yaml: 2.6.0 + optionalDependencies: + postcss: 8.4.49 + + postcss-nested@6.2.0(postcss@8.4.49): + dependencies: + postcss: 8.4.49 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.4.49: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preferred-pm@4.0.0: + dependencies: + find-up-simple: 1.0.0 + find-yarn-workspace-root2: 1.2.16 + which-pm: 3.0.0 + + prettier@2.8.7: + optional: true + + prismjs@1.29.0: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + property-information@6.5.0: {} + + queue-microtask@1.2.3: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.0.2: {} + + regex-recursion@4.2.1: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@4.4.0: {} + + rehype-parse@9.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 + unified: 11.0.5 + + rehype-raw@7.0.0: + dependencies: + '@types/hast': 3.0.4 + hast-util-raw: 9.1.0 + vfile: 6.0.3 + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.3 + unified: 11.0.5 + + rehype@13.0.2: + dependencies: + '@types/hast': 3.0.4 + rehype-parse: 9.0.1 + rehype-stringify: 10.0.1 + unified: 11.0.5 + + remark-gfm@4.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-gfm: 3.0.0 + micromark-extension-gfm: 3.0.0 + remark-parse: 11.0.0 + remark-stringify: 11.0.0 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-parse@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-from-markdown: 2.0.2 + micromark-util-types: 2.0.1 + unified: 11.0.5 + transitivePeerDependencies: + - supports-color + + remark-rehype@11.1.1: + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + mdast-util-to-hast: 13.2.0 + unified: 11.0.5 + vfile: 6.0.3 + + remark-smartypants@3.0.2: + dependencies: + retext: 9.0.0 + retext-smartypants: 6.2.0 + unified: 11.0.5 + unist-util-visit: 5.0.0 + + remark-stringify@11.0.0: + dependencies: + '@types/mdast': 4.0.4 + mdast-util-to-markdown: 2.1.2 + unified: 11.0.5 + + request-light@0.5.8: {} + + request-light@0.7.0: {} + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + resolve@1.22.8: + dependencies: + is-core-module: 2.15.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + restore-cursor@5.1.0: + dependencies: + onetime: 7.0.0 + signal-exit: 4.1.0 + + retext-latin@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + parse-latin: 7.0.0 + unified: 11.0.5 + + retext-smartypants@6.2.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unist-util-visit: 5.0.0 + + retext-stringify@4.0.0: + dependencies: + '@types/nlcst': 2.0.3 + nlcst-to-string: 4.0.0 + unified: 11.0.5 + + retext@9.0.0: + dependencies: + '@types/nlcst': 2.0.3 + retext-latin: 4.0.0 + retext-stringify: 4.0.0 + unified: 11.0.5 + + reusify@1.0.4: {} + + rollup@4.27.2: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.27.2 + '@rollup/rollup-android-arm64': 4.27.2 + '@rollup/rollup-darwin-arm64': 4.27.2 + '@rollup/rollup-darwin-x64': 4.27.2 + '@rollup/rollup-freebsd-arm64': 4.27.2 + '@rollup/rollup-freebsd-x64': 4.27.2 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.2 + '@rollup/rollup-linux-arm-musleabihf': 4.27.2 + '@rollup/rollup-linux-arm64-gnu': 4.27.2 + '@rollup/rollup-linux-arm64-musl': 4.27.2 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.2 + '@rollup/rollup-linux-riscv64-gnu': 4.27.2 + '@rollup/rollup-linux-s390x-gnu': 4.27.2 + '@rollup/rollup-linux-x64-gnu': 4.27.2 + '@rollup/rollup-linux-x64-musl': 4.27.2 + '@rollup/rollup-win32-arm64-msvc': 4.27.2 + '@rollup/rollup-win32-ia32-msvc': 4.27.2 + '@rollup/rollup-win32-x64-msvc': 4.27.2 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + section-matter@1.0.0: + dependencies: + extend-shallow: 2.0.1 + kind-of: 6.0.3 + + semver@6.3.1: {} + + semver@7.6.3: {} + + sharp@0.33.5: + dependencies: + color: 4.2.3 + detect-libc: 2.0.3 + semver: 7.6.3 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.33.5 + '@img/sharp-darwin-x64': 0.33.5 + '@img/sharp-libvips-darwin-arm64': 1.0.4 + '@img/sharp-libvips-darwin-x64': 1.0.4 + '@img/sharp-libvips-linux-arm': 1.0.5 + '@img/sharp-libvips-linux-arm64': 1.0.4 + '@img/sharp-libvips-linux-s390x': 1.0.4 + '@img/sharp-libvips-linux-x64': 1.0.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.0.4 + '@img/sharp-libvips-linuxmusl-x64': 1.0.4 + '@img/sharp-linux-arm': 0.33.5 + '@img/sharp-linux-arm64': 0.33.5 + '@img/sharp-linux-s390x': 0.33.5 + '@img/sharp-linux-x64': 0.33.5 + '@img/sharp-linuxmusl-arm64': 0.33.5 + '@img/sharp-linuxmusl-x64': 0.33.5 + '@img/sharp-wasm32': 0.33.5 + '@img/sharp-win32-ia32': 0.33.5 + '@img/sharp-win32-x64': 0.33.5 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shiki@1.23.0: + dependencies: + '@shikijs/core': 1.23.0 + '@shikijs/engine-javascript': 1.23.0 + '@shikijs/engine-oniguruma': 1.23.0 + '@shikijs/types': 1.23.0 + '@shikijs/vscode-textmate': 9.3.0 + '@types/hast': 3.0.4 + + signal-exit@4.1.0: {} + + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + + sisteransi@1.0.5: {} + + source-map-js@1.2.1: {} + + space-separated-tokens@2.0.2: {} + + sprintf-js@1.0.3: {} + + stdin-discarder@0.2.2: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string-width@7.2.0: + dependencies: + emoji-regex: 10.4.0 + get-east-asian-width: 1.3.0 + strip-ansi: 7.1.0 + + stringify-entities@4.0.4: + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom-string@1.0.0: {} + + strip-bom@3.0.0: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.5 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-preserve-symlinks-flag@1.0.0: {} + + tailwindcss@3.4.15: + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.6.0 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.2 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.6 + lilconfig: 2.1.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.4.49 + postcss-import: 15.1.0(postcss@8.4.49) + postcss-js: 4.0.1(postcss@8.4.49) + postcss-load-config: 4.0.2(postcss@8.4.49) + postcss-nested: 6.2.0(postcss@8.4.49) + postcss-selector-parser: 6.1.2 + resolve: 1.22.8 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + tinyexec@0.3.1: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + trim-lines@3.0.1: {} + + trough@2.2.0: {} + + ts-interface-checker@0.1.13: {} + + tsconfck@3.1.4(typescript@5.6.3): + optionalDependencies: + typescript: 5.6.3 + + tslib@2.8.1: + optional: true + + type-fest@4.27.0: {} + + typesafe-path@0.2.2: {} + + typescript-auto-import-cache@0.3.5: + dependencies: + semver: 7.6.3 + + typescript@5.6.3: {} + + unified@11.0.5: + dependencies: + '@types/unist': 3.0.3 + bail: 2.0.2 + devlop: 1.1.0 + extend: 3.0.2 + is-plain-obj: 4.1.0 + trough: 2.2.0 + vfile: 6.0.3 + + unist-util-find-after@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-is@6.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-modify-children@4.0.0: + dependencies: + '@types/unist': 3.0.3 + array-iterate: 2.0.1 + + unist-util-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-remove-position@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-visit: 5.0.0 + + unist-util-stringify-position@4.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-children@3.0.0: + dependencies: + '@types/unist': 3.0.3 + + unist-util-visit-parents@6.0.1: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + + unist-util-visit@5.0.0: + dependencies: + '@types/unist': 3.0.3 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + + update-browserslist-db@1.1.1(browserslist@4.24.2): + dependencies: + browserslist: 4.24.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + util-deprecate@1.0.2: {} + + vfile-location@5.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile: 6.0.3 + + vfile-message@4.0.2: + dependencies: + '@types/unist': 3.0.3 + unist-util-stringify-position: 4.0.0 + + vfile@6.0.3: + dependencies: + '@types/unist': 3.0.3 + vfile-message: 4.0.2 + + vite@5.4.11: + dependencies: + esbuild: 0.21.5 + postcss: 8.4.49 + rollup: 4.27.2 + optionalDependencies: + fsevents: 2.3.3 + + vitefu@1.0.3(vite@5.4.11): + optionalDependencies: + vite: 5.4.11 + + volar-service-css@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-css-languageservice: 6.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-emmet@0.0.62(@volar/language-service@2.4.10): + dependencies: + '@emmetio/css-parser': 0.4.0 + '@emmetio/html-matcher': 1.3.0 + '@vscode/emmet-helper': 2.10.0 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-html@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-html-languageservice: 5.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-prettier@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-typescript-twoslash-queries@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-typescript@0.0.62(@volar/language-service@2.4.10): + dependencies: + path-browserify: 1.0.1 + semver: 7.6.3 + typescript-auto-import-cache: 0.3.5 + vscode-languageserver-textdocument: 1.0.12 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + optionalDependencies: + '@volar/language-service': 2.4.10 + + volar-service-yaml@0.0.62(@volar/language-service@2.4.10): + dependencies: + vscode-uri: 3.0.8 + yaml-language-server: 1.15.0 + optionalDependencies: + '@volar/language-service': 2.4.10 + + vscode-css-languageservice@6.3.1: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + + vscode-html-languageservice@5.3.1: + dependencies: + '@vscode/l10n': 0.0.18 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-uri: 3.0.8 + + vscode-json-languageservice@4.1.8: + dependencies: + jsonc-parser: 3.3.1 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + + vscode-jsonrpc@6.0.0: {} + + vscode-jsonrpc@8.2.0: {} + + vscode-languageserver-protocol@3.16.0: + dependencies: + vscode-jsonrpc: 6.0.0 + vscode-languageserver-types: 3.16.0 + + vscode-languageserver-protocol@3.17.5: + dependencies: + vscode-jsonrpc: 8.2.0 + vscode-languageserver-types: 3.17.5 + + vscode-languageserver-textdocument@1.0.12: {} + + vscode-languageserver-types@3.16.0: {} + + vscode-languageserver-types@3.17.5: {} + + vscode-languageserver@7.0.0: + dependencies: + vscode-languageserver-protocol: 3.16.0 + + vscode-languageserver@9.0.1: + dependencies: + vscode-languageserver-protocol: 3.17.5 + + vscode-nls@5.2.0: {} + + vscode-uri@3.0.8: {} + + web-namespaces@2.0.1: {} + + which-pm-runs@1.1.0: {} + + which-pm@3.0.0: + dependencies: + load-yaml-file: 0.2.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + widest-line@5.0.0: + dependencies: + string-width: 7.2.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + xxhash-wasm@1.0.2: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml-language-server@1.15.0: + dependencies: + ajv: 8.17.1 + lodash: 4.17.21 + request-light: 0.5.8 + vscode-json-languageservice: 4.1.8 + vscode-languageserver: 7.0.0 + vscode-languageserver-textdocument: 1.0.12 + vscode-languageserver-types: 3.17.5 + vscode-nls: 5.2.0 + vscode-uri: 3.0.8 + yaml: 2.2.2 + optionalDependencies: + prettier: 2.8.7 + + yaml@2.2.2: {} + + yaml@2.6.0: {} + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@1.1.1: {} + + zod-to-json-schema@3.23.5(zod@3.23.8): + dependencies: + zod: 3.23.8 + + zod-to-ts@1.2.0(typescript@5.6.3)(zod@3.23.8): + dependencies: + typescript: 5.6.3 + zod: 3.23.8 + + zod@3.23.8: {} + + zwitch@2.0.4: {} diff --git a/web/src/components/Hero.astro b/web/src/components/Hero.astro new file mode 100644 index 0000000..94c7e34 --- /dev/null +++ b/web/src/components/Hero.astro @@ -0,0 +1,19 @@ +--- +import {type ImageMetadata} from "astro"; +import {Picture} from "astro:assets"; + +export type Props = { + image: ImageMetadata, + alt: string +} +--- +
+
+ +
+
+
+ +
+
diff --git a/web/src/components/NavBar.astro b/web/src/components/NavBar.astro new file mode 100644 index 0000000..d98094f --- /dev/null +++ b/web/src/components/NavBar.astro @@ -0,0 +1,26 @@ +--- +import NavLink from "./NavLink.astro"; +export type Props = { + navStyle?: 'transparent' | 'full' +} + +const navbar = Astro.props.navStyle ?? 'full'; +--- + + diff --git a/web/src/components/NavLink.astro b/web/src/components/NavLink.astro new file mode 100644 index 0000000..dce002b --- /dev/null +++ b/web/src/components/NavLink.astro @@ -0,0 +1,11 @@ +--- +type Props = { + link: string +}; +--- + +
  • + + + +
  • diff --git a/web/src/env.d.ts b/web/src/env.d.ts new file mode 100644 index 0000000..e16c13c --- /dev/null +++ b/web/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/web/src/layouts/Base.astro b/web/src/layouts/Base.astro new file mode 100644 index 0000000..da71f41 --- /dev/null +++ b/web/src/layouts/Base.astro @@ -0,0 +1,13 @@ +--- +import Head, {type Props as HeadProps} from "./Head.astro"; +type Props = { +} & HeadProps; +--- + + + + + +
    + + diff --git a/web/src/layouts/Content.astro b/web/src/layouts/Content.astro new file mode 100644 index 0000000..51ad0b8 --- /dev/null +++ b/web/src/layouts/Content.astro @@ -0,0 +1,63 @@ +--- +--- + +
    + +
    + diff --git a/web/src/layouts/Head.astro b/web/src/layouts/Head.astro new file mode 100644 index 0000000..2732105 --- /dev/null +++ b/web/src/layouts/Head.astro @@ -0,0 +1,12 @@ +--- +export type Props = { + title: string +} +--- + + + + + + {Astro.props.title} + diff --git a/web/src/pages/docs/_texture-pack-format.md b/web/src/pages/docs/_texture-pack-format.md new file mode 100644 index 0000000..3575cfc --- /dev/null +++ b/web/src/pages/docs/_texture-pack-format.md @@ -0,0 +1,832 @@ + + +# Custom SkyBlock Items Texture Pack Format + +## Items by internal id (ExtraAttributes) + +Find the internal id of the item. This is usually stored in the ExtraAttributes tag (Check the Power User Config for +keybinds). Once you found it, create an item model in a resource pack like you would for +a vanilla item model, but at the coordinate `firmskyblock:`. So for an aspect of the end, this would be +`firmskyblock:models/item/aspect_of_the_end.json` (or `assets/firmskyblock/models/item/aspect_of_the_end.json`). Then, +just use a normal minecraft item model. See https://github.com/nea89o/BadSkyblockTP/blob/master/assets/firmskyblock/models/item/magma_rod.json +as an example. The id is first turned to lower case, then gets `:` replaced with `___`, `;` with `__` and all other +characters that cannot be used in a minecraft resource location with `__XXXX` where `XXXX` is the 4 digit hex code for +the character. + +## (Placed) Skulls by texture id + +Find the texture id of a skull. This is the hash part of an url like +`https://textures.minecraft.net/texture/bc8ea1f51f253ff5142ca11ae45193a4ad8c3ab5e9c6eec8ba7a4fcb7bac40` (so after the +/texture/). You can find it in game for placed skulls using the keybinding in the Power User Config. Then place the +replacement texture at `firmskyblock:textures/placedskulls/.png`. Keep in mind that you will probably replace +the texture with another skin texture, meaning that skin texture has its own hash. Do not mix those up, you need to use +the hash of the old skin. + +## Armor Skull Models + +You can replace the models of skull items (or other items) by specifying the `firmament:head_model` property on your +model. Note that this is resolved *after* all [overrides](#predicates) and further predicates are not resolved on the +head model. + +```json5 +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "firmskyblock:item/regular_texture" + }, + "firmament:head_model": "minecraft:block/diamond_block" // when wearing on the head render a diamond block instead (can be any item model, including custom ones) +} +``` + +## Tint Overrides + +Some items get naturally tinted by Minecraft's rendering. Examples include leather armour, spawn eggs, potions and more. +If you want to avoid your textures getting tinted, one thing you can do is use a higher texture layer: + +```json +{ + "parent": "minecraft:item/generated", + "textures": { + // Notice the layer1 instead of layer0 here + "layer1": "firmskyblock:item/regular_texture" + } +} +``` + +Some items, however, tint *all* layers. For those items you can instead specify a tint override: + +```json +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "firmskyblock:item/regular_texture" + }, + "firmament:tint_overrides": { + "0": -1 + } +} +``` + +This forces layer 0 to be tinted with the color `-1` (pure white, aka no tint). This property is inherited, so if you +attach it to one of your root models that you `"parent"` other models to, all those models will have their tints +overridden. When the property is inherited, only layers specified in the child actually overwrite the parent layers. +You can use `"0": null` to remove the tint override in a child, which will cause a fallback to the vanilla tinting +behaviour. + +## Predicates + +Firmament adds the ability for more complex [item model predicates](https://minecraft.wiki/w/Tutorials/Models#Item_predicates). +Those predicates work on any model, including models for vanilla items, but they don't mix very well with vanilla model overrides. +Vanilla predicates only ever get parsed at the top level, so including a vanilla predicate inside of a more complex +firmament parser will result in an ignored predicate. + +### Example usage + +```json +{ + "parent": "minecraft:item/handheld", + "textures": { + "layer0": "firmskyblock:item/bat_wand" + }, + "overrides": [ + { + "predicate": { + "firmament:display_name": { + "regex": ".*§d.*", + "color": "preserve" + } + }, + "model": "firmskyblock:item/recombobulated_bat_wand" + } + ] +} +``` + +You specify an override like normally, with a `model` that will replace the current model and a list of `predicate`s +that must match before that override takes place. + +At the top level `predicate` you can still use all the normal vanilla predicates, as well as the custom ones, which are +all prefixed with `firmament:`. + +#### Display Name + +Matches the display name against a [string matcher](#string-matcher) + +```json +"firmament:display_name": "Display Name Test" +``` + +#### Lore + +Tries to find at least one lore line that matches the given [string matcher](#string-matcher). + +```json +"firmament:lore": { + "regex": "Mode: Red Mushrooms", + "color": "strip" +} +``` + +#### Item type + +Filter by item type: + +```json +"firmament:item": "minecraft:clock" +``` + +#### Skulls + +You can match skulls using the skull textures and other properties using the skull predicate. If there are no properties specified this is equivalent to checking if the item is a `minecraft:player_head`. + +```json +"firmament:skull": { + "profileId": "cca2d452-c6d3-39cb-b695-5ec92b2d6729", + "textureProfileId": "1d5233d388624bafb00e3150a7aa3a89", + "skinUrl": "http://textures.minecraft.net/texture/7bf01c198f6e16965e230235cd22a5a9f4a40e40941234478948ff9a56e51775", + "textureValue": "ewogICJ0aW1lc3RhbXAiIDogMTYxODUyMTY2MzY1NCwKICAicHJvZmlsZUlkIiA6ICIxZDUyMzNkMzg4NjI0YmFmYjAwZTMxNTBhN2FhM2E4OSIsCiAgInByb2ZpbGVOYW1lIiA6ICIwMDAwMDAwMDAwMDAwMDBKIiwKICAic2lnbmF0dXJlUmVxdWlyZWQiIDogdHJ1ZSwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzdiZjAxYzE5OGY2ZTE2OTY1ZTIzMDIzNWNkMjJhNWE5ZjRhNDBlNDA5NDEyMzQ0Nzg5NDhmZjlhNTZlNTE3NzUiLAogICAgICAibWV0YWRhdGEiIDogewogICAgICAgICJtb2RlbCIgOiAic2xpbSIKICAgICAgfQogICAgfQogIH0KfQ" +} +``` + +| Name | Type | Description | +|--------------------|---------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `profileId` | UUID | Match the uuid of the profile component directly. | +| `textureProfileId` | UUID | Match the uuid of the skin owner in the encoded texture value. This is more expensive, but can deviate from the profile id of the profile owner. | +| `skinUrl` | [string](#string-matcher) | Match the texture url of the skin. This starts with `http://`, not with `https:/` in most cases. | +| `textureValue` | [string](#string-matcher) | Match the texture value. This is the encoded base64 string of the texture url along with metadata. It is faster to query than the `skinUrl`, but it can out of changed without causing any semantic changes, and is less readable than the skinUrl. | + +#### Extra attributes + +Filter by extra attribute NBT data: + +Specify a `path` (using an [nbt prism](#nbt-prism)) to look at, separating sub elements with a `.`. You can use a `*` to check any child. + +Then either specify a `match` sub-object or directly inline that object in the format of an [nbt matcher](#nbt-matcher). + +Inlined match: + +```json5 +"firmament:extra_attributes": { + "path": "gems.JADE_0", + "string": "PERFECT" +} +``` + +Sub object match: + +```json5 +"firmament:extra_attributes": { + "path": "gems.JADE_0", + "match": { + "string": "PERFECT" + } +} +``` + +#### Components + +You can match generic components similarly to [extra attributes](#extra-attributes). If you want to match an extra +attribute match directly using that, for better performance. + +You can specify a `path` (using an [nbt prism](#nbt-prism)) and match similar to extra attributes, but in addition you can also specify a `component`. This +variable is the identifier of a component type that will then be encoded to nbt and matched according to the `match` +using a [nbt matcher](#nbt-matcher). + +```json5 +"firmament:component": { + "path": "rgb", + "component": "minecraft:dyed_color", + "int": 255 +} +// Alternatively +"firmament:component": { + "path": "rgb", + "component": "minecraft:dyed_color", + "match": { + "int": 255 + } +} +``` + + +#### Pet Data + +Filter by pet information. While you can already filter by the skyblock id for pet type and tier, this allows you to +further filter by level and some other pet info. + +```json5 +"firmament:pet" { + "id": "WOLF", + "exp": ">=25353230", + "tier": "[RARE,LEGENDARY]", + "level": "[50,)", + "candyUsed": 0 +} +``` + +| Name | Type | Description | +|-------------|------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| `id` | [String](#string-matcher) | The id of the pet | +| `exp` | [Number](#number-matcher) | The total experience of the pet | +| `tier` | Rarity (like [Number](#number-matcher), but with rarity names instead) | The total experience of the pet | +| `level` | [Number](#number-matcher) | The current level of the pet | +| `candyUsed` | [Number](#number-matcher) | The number of pet candies used on the pet. This is present even if they are not shown in game (such as on a level 100 legendary pet) | + +Every part of this matcher is optional. + + +#### Logic Operators + +Logic operators allow to combine other firmament predicates into one. This is done by building boolean operators: + +```json5 +"firmament:any": [ + { + "firmament:display_name": "SkyBlock Menu (Click)" + }, + { + "firmament:display_name": "SkyBlock", + "firmament:lore": "Some Lore Requirement" + } +] +``` + +This `firmament:any` test if the display name is either "SkyBlock Menu (Click)" or "SkyBlock" (aka any of the child predicates match). + +Similarly, there is `firmament:all`, which requires all of its children to match. + +There is also `firmament:not`, which requires none of its children to match. Unlike `any` or `all`, however, `not` +only takes in one predicate `{}` directly, not an array of predicates `[{}]`. + +Note also that by default all predicate dictionaries require all predicates in it to match, so you can imagine that all +things are wrapped in an implicit `firmament:all` element. + +### String Matcher + +A string matcher allows you to match almost any string. Whenever a string matcher is expected, you can use any of these +styles of creating one. + +#### Direct + +```json +"firmament:display_name": "Test" +``` + +Directly specifying a raw string value expects the string to be *exactly* equal, after removing all formatting codes. + +#### Complex + +A complex string matcher allows you to specify whether the string will get its color codes removed or not before matching + + +```json5 +"firmament:display_name": { + "color": "strip", + "color": "preserve", + // When omitting the color property alltogether, you will fall back to "strip" +} +``` +In that same object you can then also specify how the string will be matched using another property. You can only ever +specify one of these other matchers and one color preserving property. + +```json5 +"firmament:display_name": { + "color": "strip", + // You can use a "regex" property to use a java.util.Pattern regex. It will try to match the entire string. + "regex": "So[me] Regex", + // You can use an "equals" property to test if the entire string is equal to some value. + // Equals is faster than regex, but also more limited. + "equals": "Some Text" +} +``` + +### Number Matchers + +This matches a number against either a range or a specific number. + +#### Direct number + +You can directly specify a number using that value directly: +```json5 +"firmament:pet": { + "level": 100 +} +``` + +This is best for whole numbers, since decimal numbers can be really close together but still be different. + +#### Intervals + +For ranges you can instead use an interval. This uses the standard mathematical notation for those as a string: + + +```json5 +"firmament:pet": { + "level": "(50,100]" +} +``` + +This is in the format of `(min,max)` or `[min,max]`. Either min or max can be omitted, which results in that boundary +being ignored (so `[50,)` would be 50 until infinity). You can also vary the parenthesis on either side independently. + +Specifying round parenthesis `()` means the number is exclusive, so not including this number. For example `(50,100)` +would not match just the number `50` or `100`, but would match `51`. + +Specifying square brackets `[]` means the number is inclusive. For example `[50,100]` would match both `50` and `100`. + +You can mix and match parenthesis and brackets, they only ever affect the number next to it. + +For more information in intervals check out [Wikipedia](https://en.wikipedia.org/wiki/Interval_(mathematics)). + +#### Operators + +If instead of specifying a range you just need to specify one boundary you can also use the standard operators to +compare your number: + +```json5 +"firmament:pet": { + "level": "<50" +} +``` + +This example would match if the level is less than fifty. The available operators are `<`, `>`, `<=` and `>=`. The +operator needs to be specified on the left. The versions of the operator with `=` also allow the number to be equal. + +### Nbt Prism + +An nbt prism (or path) is used to specify where in a complex nbt construct to look for a value. A basic prism just looks +like a dot-separated path (`parent.child.grandchild`), but more complex paths can be constructed. + +First the specified path is split into dot separated chunks: `"a.b.c"` -> `["a", "b", "c"]`. You can also directly +specify the list if you would like. Any entry in that list not starting with a `*` is treated as an attribute name or +an index: + +```json +{ + "propA": { + "propB": { + "propC": 100, + "propD": 1000 + } + }, + "someOtherProp": "hello", + "someThirdProp": "{\"innerProp\": true}", + "someFourthProp": "aGlkZGVuIHZhbHVl" +} +``` + +In this example json (which is supposed to represent a corresponding nbt object), you can use a path like +`propA.propB.propC` to directly extract the value `100`. + +If you want to extract all of the innermost values of `propB` +(for example if `propB` was an array instead), you could use `propA.propB.*`. You can use the `*` at any level: +`*.*.*` for example extracts all properties that are exactly at the third level. In that case you would try to match any +of the values of `[100, 1000]` to your match object. + +Sometimes values are encoded in a non-nbt format inside a string. For those you can use other star based directives like +`*base64` or `*json` to decode those entries. + +`*base64` turns a base64 encoded string into the base64 decoded counterpart. `*json` decodes a string into the json +object represented by that string. Note that json to nbt conversion isn't always straightforwards and the types can +end up being mangled (for example what could have been a byte ends up an int). + +| Path | Result | +|---------------------------------|---------------------------------| +| `propA.propB` | `{"propC": 100, "propD": 1000}` | +| `propA.propB.propC` | `100` | +| `propA.*.propC` | `100` | +| `propA.propB.*` | `100`, `1000` | +| `someOtherProp` | `"hello"` | +| `someThirdProp` | "{\"innerProp\": true}" | +| `someThirdProp.*json` | {"innerProp": true} | +| `someThirdProp.*json.innerProp` | true | +| `someFourthProp` | `"aGlkZGVuIHZhbHVl"` | +| `someFourthProp.*base64` | `"hidden value"` | + + +### Nbt Matcher + +This matches a single nbt element. + +Have the type of the nbt element as json key. Can be `string`, `int`, `float`, `double`, `long`, `short` and `byte`. + +The `string` type matches like a regular [string matcher](#string-matcher): + +```json +"string": { + "color": "strip", + "regex": "^aaa bbb$" +} +``` + +The other (numeric) types can either be matched directly against a number: + +```json +"int": 10 +``` + +Or as a range: + +```json +"long": { + "min": 0, + "max": 1000 +} +``` + +Min and max are both optional, but you need to specify at least one. By default `min` is inclusive and `max` is exclusive. +You can override that like so: + +```json +"short": { + "min": 0, + "max": 1000, + "minExclusive": true, + "maxExclusive": false +} +``` + + +> [!WARNING] +> This syntax for numbers is *just* for **NBT values**. This is also why specifying the type of the number is necessary. +> For other number matchers, use [the number matchers](#number-matchers) + +## Armor textures + +You can re-*texture* armors, but not re-*model* them with firmament. + +To retexture a piece of armor place a json file at `assets/firmskyblock/overrides/armor_models/*.json`. + +```json +{ + "item_ids": [ + "TARANTULA_BOOTS", + "TARANTULA_LEGGINGS", + // ETC + ], + "layers": [ + { + "identifier": "firmskyblock:tarantula" + } + ] +} +``` + +Only one such file can exist per item id, but multiple item ids can share one texture file this way. + +The `item_ids` is the items to which this override will apply when worn. Those are neu repo ids (so what will be shown +in game as the regular SkyBlock id, not the resource pack identifier). + +### Layers + +The `layers` specify the multiple texture layers that will be used when rendering. For non leather armor, or armor +ignoring the leather armor tint just one layer is enough. + +If you want to apply armor tint to the texture you will usually want two layers. The first layer has a tint applied: + +```json +{ + "identifier": "firmskyblock:angler", + "tint": true +} +``` + +This will tint the texture before it is being rendered. + +The second layer will have no tint applied, but will have a suffix: + +```json +{ + "identifier": "firmskyblock:angler", + "suffix": "_overlay" +} +``` + +This second layer is used for the countours of the armor. + +The layer identifier will resolve to a texture file path according to vanilla armor texture rules like so: + +`assets/{identifier.namespace}/textures/models/armor/{identifier.path}_layer_{isLegs ? 2 : 1}{suffix}.png` + +Note that there is no automatic underscore insertion for suffix, so you will need to manually specify it if you want. + +The leg armor piece uses a different texture, same as with vanilla. + +### Overrides + +You can also apply overrides to these layers. These work similar to item predicate overrides, but only the custom +Firmament predicates will work. You will also just directly specify new layers instead of delegating to another file. + +```json +{ + "item_ids": [ + "TARANTULA_BOOTS", + "TARANTULA_LEGGINGS", + // ETC + ], + "layers": [ + { + "identifier": "firmskyblock:tarantula" + } + ], + "overrides": [ + { + "layers": [ + { + "identifier": "firmskyblock:tarantula_maxed" + } + ], + "predicate": { + "firmament:lore": { + "regex": "Piece Bonus: +285.*" + } + } + } + ] +} +``` + +## UI Text Color Replacement + +This allows you to replace the color of text in your inventory. This includes inventory UIs like chests and anvils, but +not screens from other mods. You can also target specific texts via a [string matcher](#string-matcher). + +```json +// This file is at assets/firmskyblock/overrides/text_colors.json +{ + "defaultColor": -10496, + "overrides": [ + { + "predicate": "Crafting", + "override": -16711936 + } + ] +} +``` + +| Field | Required | Description | +|-----------------------|----------|----------------------------------------------------------------------------------------------------| +| `defaultColor` | true | The default color to use in case no override matches | +| `overrides` | false | Allows you to replace colors for specific strings. Is an array. | +| `overrides.predicate` | true | This is a [string matcher](#string-matcher) that allows you to match on the text you are replacing | +| `overrides.override` | true | This is the replacement color that will be used if the predicate matches. | + +## Screen Layout Replacement + +You can change the layout of an entire screen by using screen layout overrides. These get placed in `firmskyblock:overrides/screen_layout/*.json`, with one file per screen. You can match on the title of a screen, the type of screen, replace the background texture (including extending the background canvas further than vanilla allows you) and move slots around. + +### Selecting a screen + +```json +{ + "predicates": { + "label": { + "regex": "Hyper Furnace" + }, + "screenType": "minecraft:furnace" + } +} +``` + +The `label` property is a regular [string matcher](#string-matcher) and matches against the screens title (typically the chest title, or "Crafting" for the players inventory). + +The `screenType` property is an optional namespaced identifier that allows matching to a [screen type](https://minecraft.wiki/w/Java_Edition_protocol/Inventory#Types). + +### Changing the background + +```json +{ + "predicates": { + "label": { + "regex": "Hyper Furnace" + } + }, + "background": { + "texture": "firmskyblock:textures/furnace.png", + "x": -21, + "y": -30, + "width": 197, + "height": 196 + } +} +``` + +You need to specify an x and y offset relative to where the regular screen would render. This means you just check where the upper left corner of the UI texture would be in your texture (and turn it into a negative number). You also need to specify a width and height of your texture. This is the width in pixels rendered. If you want a higher or lower resolution texture, you can scale the actual texture up (tho it is expected to meet the same aspect ratio as the one defined here). + +### Moving slots around + +```json +{ + "predicates": { + "label": { + "regex": "Hyper Furnace" + } + }, + "slots": [ + { + "index": 10, + "x": -5000, + "y": -5000 + } + ] +} +``` + +You can move slots around by a specific index. This is not the index in the inventory, but rather the index in the screen (so if you have a chest screen then all the player inventory slots would be a higher index since the chest slots move them down the list). The x and y are relative to where the regular screen top left would be. Set to large values to effectively "delete" a slot by moving it offscreen. + +### Moving text around + +```json +{ + "predicates": { + "label": { + "regex": "Hyper Furnace" + } + }, + "playerTitle": { + "x": 0, + "y": 0, + "align": "left", + "replace": "a" + } +} +``` + +You can move the window title around. The x and y are relative to the top left of the regular screen (like slots). Set to large values to effectively "delete" a slot by moving it offscreen. + +The align only specifies the direction the text grows in, it does not the actual anchor point, so if you want right aligned text you will also need to move the origin of the text to the right (or it will just grow out of the left side of your screen). + +You can replace the text with another text to render instead. + +Available titles are + +- `containerTitle` for the title of the open container, typically at the very top. +- `playerTitle` for the players inventory title. Note that in the player inventory without a chest or something open, the `containerTitle` is also used for the "Crafting" text. +- `repairCostTitle` for the repair cost label in anvils. + +### Moving components around + +```json +{ + "predicates": { + "label": { + "regex": "Hyper Furnace" + } + }, + "nameField": { + "x": 10, + "y": 10, + "width": 100, + "height": 12 + } +} +``` + +Some other components can also be moved. These components might be buttons, text inputs or other things not fitting into any category. They can have a x, y (relative to the top left of the screen), as well as sometimes a width, height, and other properties. This is more of a wild card category, and which options work depends on the type of object. + +Available options + +- `nameField`: x, y, width & height are all available to move the field to set the name of the item in an anvil. + +### All together + +| Field | Required | Description | +|---------------------------|----------|--------------------------------------------------------------------------------------------------------------------------| +| `predicates` | true | A list of predicates that need to match in order to change the layout of a screen | +| `predicates.label` | true | A [string matcher](#string-matcher) for the screen title | +| `background` | false | Allows replacing the background texture | +| `background.texture` | true | The texture of the background as an identifier | +| `background.x` | true | The x offset of the background relative to where the regular background would be rendered. | +| `background.y` | true | The y offset of the background relative to where the regular background would be rendered. | +| `background.width` | true | The width of the background texture. | +| `background.height` | true | The height of the background texture. | +| `slots` | false | An array of slots to move around. | +| `slots[*].index` | true | The index in the array of all slots on the screen (not inventory). | +| `slots[*].x` | true | The x coordinate of the slot relative to the top left of the screen | +| `slots[*].y` | true | The y coordinate of the slot relative to the top left of the screen | +| `Title` | false | The title mover (see above for valid options) | +| `Title.x` | false | The x coordinate of text relative to the top left of the screen | +| `Title.y` | false | The y coordinate of text relative to the top left of the screen | +| `Title.align` | false | How you want the text to align. "left", "center" or "right". This only changes the text direction, not its anchor point. | +| `Title.replace` | false | Replace the text with your own text | +| `` | false | Allows you to move button components and similar around | +| `.x` | true | The new x coordinate of the component relative to the top left of the screen | +| `.x` | true | The new y coordinate of the component relative to the top left of the screen | +| `.width` | false | The new width of the component | +| `.height` | false | The new height of the component | + + + +## Global Item Texture Replacement + +Most texture replacement is done based on the SkyBlock id of the item. However, some items you might want to re-texture +do not have an id. The next best alternative you had before was just to replace the vanilla item and add a bunch of +predicates. This tries to fix this problem, at the cost of being more performance intensive than the other re-texturing +methods. + +The entrypoint to global overrides is `firmskyblock:overrides/item`. Put your overrides into that folder, with one file +per override. + +```json5 +{ + "screen": "testrp:chocolate_factory", + "model": "testrp:time_tower", + "predicate": { + "firmament:display_name": { + "regex": "Time Tower.*" + } + } +} +``` + +There are three parts to the override. + +The `model` is an *item id* that the item will be replaced with. This means the +model will be loaded from `assets//models/item/.json`. Make sure to use your own namespace to +avoid collisions with other texture packs that might use the same id for a gui. + +The `predicate` is just a normal [predicate](#predicates). This one does not support the vanilla predicates. You can +still use vanilla predicates in the resolved model, but this will not allow you to fall back to other global overrides. + +The `screen` specifies which screens your override will work on. This is purely for performance reasons, your filter +should work purely based on predicates if possible. You can specify multiply screens by using a json array. + +### Global item texture Screens + +In order to improve performance not all overrides are tested all the time. Instead you can prefilter by the screen that +is open. First the gui is resolved to `assets//filters/screen/.json`. Make sure to use your own namespace +to avoid collisions with other texture packs that might use the same id for a screen. + +```json +{ + "title": "Chocolate Factory" +} +``` + +Currently, the only supported filter is `title`, which accepts a [string matcher](#string-matcher). You can also use +`firmament:always` as an always on filter (this is the recommended way). + +## Block Model Replacements + +Firmament adds the ability to retexture block models. Supported renderers are vanilla, indigo (fabric), sodium (and +anything sodium based). Firmament performs gentle world reloading so that even when the world data gets updated very +late by the server there should be no flicker. + +If you want to replace block textures in the world you can do so using block overrides. Those are stored in +`assets/firmskyblock/overrides/blocks/.json`. The id does not matter, all overrides are loaded. This file specifies +which block models are replaced under which conditions: + +```json +{ + "modes": [ + "mining_3" + ], + "area": [ + { + "min": [ + -31, + 200, + -117 + ], + "max": [ + 12, + 223, + -95 + ] + } + ], + "replacements": { + "minecraft:blue_wool": "firmskyblock:mithril_deep", + "minecraft:light_blue_wool": { + "block": "firmskyblock:mithril_deep", + "sound": "minecraft:block.wet_sponge.hit" + } + } +} +``` + +The referenced `block` can either be a regular json block model (like the ones in `assets/minecraft/blocks/`), or it can +reference a blockstates json like in `assets//blockstates/.json`. The blockstates.json is prefered and +needs to match the vanilla format, so it is best to copy over the vanilla blockstates.json for the block you are editing +and replace all block model paths with your own custom block models. + +| Field | Required | Description | +|-------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `modes` | yes | A list of `/locraw` mode names. | +| `area` | no | A list of areas. Blocks outside of the coordinate range will be ignored. If the block is in *any* range it will be considered inside | +| `area.min` | yes | The lowest coordinate in the area. Is included in the area. | +| `area.max` | yes | The highest coordinate in the area. Is included in the area. | +| `replacements` | yes | A map of block id to replacement mappings | +| `replacements` (string) | yes | You can directly specify a string. Equivalent to just setting `replacements.block`. | +| `replacements.block` | yes | You can specify a block model to be used instead of the regular one. The model will be loaded from `assets//models/block/.json` like regular block models. | +| `replacements.sound` | no | You can also specify a sound override. This is only used for the "hit" sound effect that repeats while the block is mined. The "break" sound effect played after a block was finished mining is sadly sent by hypixel directly and cannot be replaced reliably. | + +> A quick note about optimization: Not specifying an area (by just omitting the `area` field) is quicker than having an +> area encompass the entire map. +> +> If you need to use multiple `area`s for unrelated sections of the world it might be a performance improvement to move +> unrelated models to different files to reduce the amount of area checks being done for each block. diff --git a/web/src/pages/docs/texture-pack-format.astro b/web/src/pages/docs/texture-pack-format.astro new file mode 100644 index 0000000..0714aea --- /dev/null +++ b/web/src/pages/docs/texture-pack-format.astro @@ -0,0 +1,15 @@ +--- +import Base from "../../layouts/Base.astro"; +import NavBar from "../../components/NavBar.astro"; +import Content from "../../layouts/Content.astro"; +import MarkDown from './_texture-pack-format.md'; +--- + + + + + + + + + diff --git a/web/src/pages/index.astro b/web/src/pages/index.astro new file mode 100644 index 0000000..4baa867 --- /dev/null +++ b/web/src/pages/index.astro @@ -0,0 +1,20 @@ +--- +import Hero from "../components/Hero.astro" +import Base from "../layouts/Base.astro"; +import Image from "../panorama.png"; +import NavBar from "../components/NavBar.astro"; +import Content from "../layouts/Content.astro"; +--- + + + +

    Firmament

    +

    Hypixel SkyBlock Utility Mod

    + Download now +
    + + + Firmament is a 1.21 Minecraft mod for Hypixel SkyBlock. It has a variety of features such as an item list, + mining features. + + diff --git a/web/src/pages/texture-packs.astro b/web/src/pages/texture-packs.astro new file mode 100644 index 0000000..ee511f9 --- /dev/null +++ b/web/src/pages/texture-packs.astro @@ -0,0 +1,9 @@ +--- +import Base from "../layouts/Base.astro"; +import NavBar from "../components/NavBar.astro"; +--- + + + + + diff --git a/web/src/panorama.png b/web/src/panorama.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ef600b9c6b922366432bdd56404ee5c4469504 GIT binary patch literal 2282096 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

    tL>B?azLvXG8i92bj`5h#PnpjYSV?-9kReqm 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'-%-W@2aLfF-}pt(9m-u`!x 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ð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 z zKxR~@K|@A1-|pe2ypMsIK@8OQ9{y`6$@3_H+y8Nh4N(6AzO}hb|!t=G($#;~7 z*wM`iSM!7hAUpojc^aI!bTmi+GTed^?xR3$oReoLaoR0Z>ro$jLQ_x5xe}AElVZtc zxt4UInQ4>t53bv7N;yR$&v#4|(iJR0OWkMcS+oNgK5v@p{i9=&I=;}q?|5sq~TS2+n@{Jt2pX*UeLbrE#tfBvFh&asquwPw+bPajjdb$?x@UZ zB>v_5zrj!zw_wiDh`PXIlwxZG@wtq$zK+|A*>FP8^~Xc91FT1NZbBO3q4McO4< z-yH=);L=b9;k<=t#$3W|9y<&AV2S^P+iAWQDfF=v9uZ_)xOjkY1j_Wm6@R&l5O|fMt$w^JO~uuv45^+R_L;!hh)My z@=r+9baNPUm1PV=s6Lpd#vjmYkXm-nenf!V;wTLrW(EL3f zK-z$zqOX!3J1tXmPXulfqY85mqL~vC38LeN);Pl}P4qQZS`j4pIUpQ^KKjjW{*&{Z z5y_3=k_FFjHz_j6)^hQbKtx))GHbJ(b zR5vNyGg~g0iWGn$=yN0J)%}3&)8p_G1F=|Luf^bp*pPLa{lQLij`4k+hz+N|%+j4- z+`MP){qa$60`a{h)$esG2&*o-#P+!%niO9a2pnC@=z#$ciJ5ejXcKC?A&!kvW{%8g zB}!C3GUFxeOaY!iCoZiU8|^2 z40uBl#|;d&_~V7J=wwbY6~3q|0Zc!AKr~2wc&S`|C+k}JaO1aQq~q@Gc8s|$afkF7 zv4lmgRPaW{S$H(l3f|waJ7;f`uln+Wa??u9EnjccDPGyPvEY{4@&KiO-#l9yF@)>7 z)j^1FrXv|{U$~Fm8Q~ronOyb-iHFa|Od_WZ0Wi(`gUmi(DOXfoemMTJ8eYfJeix_H zFbo83WryMmAs|K-J3EXSpcf2*7}0|mwpTd3>;Y1GoZX&m;lT9r#>_DL{i)|_S2(vK z7nV?S)?sele#3d}aOG3~F4fhgxL&y~5iLbcc$-4Fx4djO^yJ5bUUxEM%aY4hJr*d* zHk??({ZwX2p*%M2+xLo8GT-*t3`^a}9BO4(M70Gz+<9=`jPe4-1V1vi+Llx}WfJ+0uQH{@@aSV-eO4=R8zK6&qK}l3akg3(C9b$0 z>40pIm%slzPQ2R6!U=YXi#Y3%!4QM``kr7k?;v)MU(>=xwm&Nikq)xma7IaTa^gXh zpQ(~X^m5Q`azoXzRgUwd* z=<%&bxALNze;W_I-qq&@)dJsXf7eG44`Yb2=@R!IjpIg5D{t9HJK61aj$PfawSSnB zdJ1ricdo~;IY#szrN`))WnV|}7d=2_v_`$H!ELIZ-_QwZHmyjg<}_lk?v+e|g}Q=V zSz>o3qfk{BFgpJC+|PcttDMW14e5ujnME{qH(VK()GtwgD`fQSf7sz}d8hKJ+vNB7 z%l-Bfz#*~ZW^3o0yMT&XR^dJ_Fzuv~LckNHDcQ&}v>*DtN>^KnJi*f%+97iVu_J!S zh|!l(ql<6$b#f9#F?qI5S|>U{6xc=>8v*}SUaPn5m$9diIsi8rqu&_L5bBIU$5u^E z8?V02H#ipJFr(jx&e`aUf!43GtVbx>XGf4)HZ;cGNvOdn_vGb^Wp&WiVZ}7o9*Kql$jqXQAvq~%f96DN%#K>h)FXDJ=i5}rak-KaAA6+U|3Ys2`k zcU@eNd!q2y$>Wc?OA>b%N8fc-5hs|2j`Y;uvzc!ZmwGR3Db^VaZ*#$SpTPaRu`llE zfR24b101-iGY6+Gt1`9=(-%ZBRVHo_#6~%ri|>fi4ehMdJ1rLs`Z-lP$08GmyY47- z-a7@Ng~HHUr%g7p3Pw%0!JP|_R${T5E%g^uAA~)G0q^Y2b6@B6k+w#J%QbM&W_m(7 zVtCMg{7MU{7h3Uqxpgg&wzs61SU}m^C(^VPV>Mz2HL+xw^QL46TIxpnK}F-KhxcQJbl5Mpzea zGBn7jdz}R)n%&RsP0?4?lJIapnLx(OU?!^rY*iMNKh>?>zGSIzSqA=H+_(aeAn3*X6civ#Sda9}9{ zBOE|6*XP<3WX)#+H#ou&g186&0Nu0^Ur4IN^Vmqp*C*nb*T{Q|?$3UbuF4+VRNdV4 zqagb^c^pkjt^7f6q(L;>9z~~@WfAW;cDLO5us^WP%E`0jfYt|48a=B>UT5NI=ImmY zad#EuS3K1}%cbSQEm>gvhDa~FbU1_I+iHonD+`R@BXskF9xc10=RTr+=PZYgH#vV= z%R1S zCvywX=utcR$u7q8`9Gu6Itd&0Jxnluc8cG=r!8GF@XzSsLdPvl23Iw|D%4ZPy*8R+ z{UO#XnclssFXFF3&-*tZ0Z?Kuea51;d_XFbQ5+g^LYco{Il9qC!NLRX@tWy3kQ@nj z(20;$d$Qb?G7(snw<>OlCXW}|%pp=rC+MOa8{Ybqc8Wo>!i+|du_mU)y6l~u-K%R$uFaLd(} zZ@RukU)Y54PiL1oVW1-vneY$A(@iyYOZ|v5PxH((8gaL51tl-HEzJ~r`Zry@O$>4+ z27<2JwTxbe)YNJDe~1-S{K@0QC-TrNX>M!X`9FjrRlZfAL$)IT#mZgv%I3b}blb3u z&$ui)vR?glbaF_SrfMY!`B(DA7IBVQl1EEW&H5yuKoW$5Ju(+IQ#lEEc;roCX|wq zA6{i%t$pWCcG&w9J*T`V$w_hz20N?MRU@PWOsaY8s@ce|M}X^z(72fxrAi}grMV67 z*D9qKub1A)l-*mWJ2$Z-$D)p{Q(6nVJ%ifkD~Z{kYDP8v}948sd@PdEQ z%-f)gd_JRah-5%kzxnSvuGRGP+>s_u=p6M-3OF^qLgSoA8<@Pf-Q?~cmcQ#_aHW33 zmZPx7<+qd}#X^;mDIcN&zWnUuH%eh5SGQ&?}FDqB8D=ZXxyX_H59*O9X7X=pKINjV2?b~$grPFR&3e4*f^fx(KOzbPklW*yK zqY(%2Q16|j=le-s0H$&5NW(2U@jUHyb-tCyWfdDqW zoAl=$j{zkR=IS?y_x85#y&l@2234igP5~Jwt&wirmT_^=~W{Ij(OJZQMwr zrhAh~ad6<9MwEtpgXFO!AL6xI(kjEQs8-RkRAYj5BGgL-2mO<9H9Yf|h#DCY#p;Ne zDa%bFBzP5vJGSmF$QQ|1sDt#>`N3^R~JQ zO@(c`>{qp5yI4M^oZP0vXV$llYU5*poB;kgL({>D<7II)`N zFG(r84M!Lagy0e5p)1WP5+8Y+xe-RF4r6+4ytZCz@C{C>>erk9$75~fw=3GRkqXPu zssiQ`JnFwwSwGnRq)>+vlLB-R`7i$t%coYpq7*8aVKcOzbF&T^=`?EH-)k#ee(n5Y zBs**Ll!BuXY>i0w$70Q5Em!uRHX>d-oJZ+eKpO#vv$AH;bL78y<<=2sQL;5z#rNVn z!=wL47CE4;*F9jP|U z)0fsO_SX&OY?(5BXnHARgGnz|-gHV?aTyL8g+hr2RY6}aY+ z;V(H1UOrI4F8-!t$L>ef_(PU-WW1yAK_|Ds!4N1YT*c zoh@&Lub&YBJV&<$K`i%n z`}L)Ld&TnIGM@QBy2O`2!(Qep|E0|}Y=@ih=W96re-=?^oAW9&Xlb@NYEI@|4x$}p z-V&fdBZRLaxRo^OfJEsu>9Mf_M>6WvB-=ZoBn7$~T|>kD?Dqvb4>E7AZ``i)YJpY= zl+B1nKz0CW3@&cI>o|t zfybAx)5=XSH{QMlwhrz_xR82_tsU`B9=Qm!kM#)z0GLovRu8VN4(=AZMFtw=v~1-_ z?8weHWxZq|6>+cs<|IPdJS5!HZBa!Nz9r=pfMKY0>dL zjtXZSUa{)qzYgNxbsrR)#-jWs+96G#*qdq*dutNQdyuUD4Z|S})t6G7Y>(r+-v7>l2FmHGvz@LG3uD^+cm3AR87~# zBm`XhIMP+na*RIIzwpeeTfUWEF{DKRt+`I>viYYORA; zG`*=^oPp&ZE~yhQHbb@sfR055A={SLCKO;xTA1HwexD9p4P1N$amg18*65b9b#P+) zd69@PaFqb@|NROb(N%kXN$S>L=9w(jD$?q=x4#4b@Dt;yi5d+ffCdWfftbzRd}>Ux zVjT*MgXTp_k8X~i=0V?cSpj29aL;4TTZLvUaNvGlSpA8C>kx79NiBxksrLCVzv*?f zPI&R}*}wEq(`RwBQX&7C2#dt2TeHd)xB(lF-%qKKZPcAEIFPe4*c-^Jol_{D#M#=m3{Q=7h7I(b&C(`;SH$vU(#4|}ONbYnR3 z-N4(7N+Y+_r>ymEYrz)CNyPt*#EX}WE;8aAvKj{v{M^#f2KL|5)z5l_UTBBEiDho}}+IxzYtrFv4w79=8Y}g>nKa~1OZu77sRVLNF z8_zA*vQ%-RWoHGD9+rJ*I4mbS&(~$nqL^MICY0?`wGe#o_jutco7g{WeoqsiRsY1y zJHmzOFc&|pkfF(F`yM~;21&Gtnc`n8UI6~P5#P3L8ZzE6@z3LI4-0T?y>)dlXs+pT(?Oh+I$-4uOJdr zCPLPC;HO});%_9`SMVL6Pr6V&-Ja$3$V9L#<(JWd23^t<7O^05wG2CLIqJ+PKbOP8 zNUoYJ?`Ks>jH)}ZI6ZfARfG^f1tHeg@zchMlT+Z0+P(AUug^7GqQC!{ zlAK6Q>mwlK_LD$N>B&ymaPJsr1g2z6kGCfYizEv2kU{~g`cwvVJ-;A7VMGP!(R=n3 zp8V!KFCd87=DQ)xtKnP2j2d0(G zS5-FqQnhiO$bQ@!QDie;<~`&246zp^%4xefM(Bjci=d4#esvmkOcM{t%!^k9c8m5|45hXBKv@)!71&xh^FH=v%I|El>b}Oq0ERcdH8RS&Y+1hZbD+7< zc0*wWy0VocIpJX|(-eBy9kAadhDI9P2i0!|tODOIn~+vdz&H4qMRaU8h!?BdO&fOv z?g>=>zo>fes3iD5{2K&80mTV865N`5Mp91YwH;raCa{m%28=kHF(a~yBppX+^HuM4||3Se$)z`>KK4*f5%Kr~N8GY=O|ljoCtr=8V?&OOrZ@;K7x(St zw%bZtaJsLu7S%*{U9H*sEC_~&pax?y@^uj~cK7-RTXsDmtrvk$AS?2_A?7j7}cJbrtg z7}8tQdcrd8-?fbJ51B4WDM~x9b?93E$}da@#yRfXD{``%M~353pkSOS)?ZIO1l!e9 zPPQ2PgsnQBazA#2s4vjabONPRNttGn_gi`SBMS0E+b4Eq{;T#uS7X>YO5ie_K6I@U zEyF4G{i#YY%$s~)s)4iZ@=PwC=a&1QBPfsVw`uh86x!^5`q)Ho?RqI z10Pl?iqoD)E>JasbmGKa3UhSymZUo7q;PtP?b!2jYS_^``Y5NpmyVlWl>Qn|&3cjS zCY#4`DZ2ri_G7oyg0@>;I!JEj_DxFUuytRXa z54>JWv_FAJ-9DI2Mz$ydb8f_-7r|dZr2mp<6bNj%S4Gu-JL83Xj zB=d%nqph_za@*OC-1$Hn~+#eB2MdVsmTKyZ#qdBB+ ztgbzst4bf${(J9qB{TmE?Y2wKN$8lK{&;#7ep8N;MQkx)Wy-=XvpXy+ix%hAwzKul zi@%2%f$mY8-G4(Pl7Y&ZF$Yxq{UI-r#Sm|@kd13_2tid4e;R zJng2kSV3@Dc)Q}xx)6rW1fU90#)Z%-gsiMn@k(h@*_9!N&imc`Bk?@NdIEMF08dkZ zPg*oVD%Z-0b(uJIZ?)O=V}0t0_pthT+=W`zpEE(sBV6#?83e`nle#%#;(s!$zkJ=* zU31RC7b1ge0OGm=`$c<>_gD%JQm!PBXq=J(JSwgH?OEr)&YeLRRxCpN8(w0XbMQ}$ z^NViDkKA<}=B;=5Xw(WZj6`l%CdXauIz?4`!^D)wexqZa-?X`YWBgALC&kchI%w>2 zXX2-y7?xn2Y^LY!cqkedC#!WOdF%nuE)Iu4tS?K)|1#o9?aCmx zme9`$P5H1Vc0zu5NDbE`v;i6b5%U)lv%Y*Cns|M5ppqMJNED zm-r(P5iQ|q+&^t-F*;h1qK!yO4eWYQULj!!j-va<=&;6hytUz%CVId&30qOAdMl~8 zlf1KIk4IbSKKZHhI%vHqj*AyWq}l=z*p2ZI?S-Fso*KsxZXm6t`ES0N`M%*MFCOy5 zbfyUR?Q`bpV0yD2ZTTGVCbr-RwnK+a6j9&mYhw4YQ0oP)V*MiBxks_dgtxM=FqWR8 zA4E23crR4mZ5QuAoBYNB>u}qYCfJ3ysCOq67aV(b-KmIh-|r?foUnVd&uuoO@KuuN zU+;1l`L8+Se*#3o-(`5$xpi#*A-6q)QPNvBw}HCRyyz6hYH-D=&#nnORNDcA!X1W;2LiEr6s{-?`T9BumF?q^#5a@K@@ii_?4EbU2;B=CF8$9f zOfshN!G*b1=mR+?sY9skA6?#eCA0L-2BY5z_=gF7l;Zr{6F=I(8jcfb$H77lin)PK zI1cp3?a`MrlIr4|*aDtgSf}aJCF0}2Fwxs`S@tU8U}yV+O*gpY_{ul3nSzjwY1^`p z-08G<8sUOC@tvf-J#>SL#D^#myNqFSBEs>vc^F!$gGBl*_6pFpBtsPYe)WMQcGli? z7NV^$#HkXg0P0Il%#lKZm9pE#g*cYLZ&o&4?ZnwfT)ORQv8k$tZtVYU;OjD`s;;6(BE*lIp&y=EvPKto=(|&M=tRSdy*F za^00zs#8kS7o>*EPi9!_oTNPnYDsPjsOc63--VsB=4IWEp5A*!`r7$&sLx# zN3%$~QKmBRrKFAQMyB`$D#_vpqjPMXwf-z#bsTjdza#%r&0dj$fb_&2q{hS47qo+s zXb>64p4E?=4)!ZKTaX39-}gl9yJ9a|nOAY~D21)6w<0q2ZqsikifqG&64x&`bAm~F z?Y+DW%f;)im6?8i!&$xALX*p?=rUVu{+YQEWYtcBLIk45Ksilc#%a}M7v#}NMn9Pp z3##!tW)BQ^r=(ROGH&e=n_u6kF3E)sg{2WFgir4rfgUL$eeaKnvDkb~s;5fo7A0}tML}`uR)f#3LSoyi_THC*Tf^s?!G)*O3Ed)Ks_fz z8K;)VQf|Y=8np=4JZi2)@}0-$gO#jQ)D6x#24Td^z7C!5Y~Lk$DiM7x*d*nqm-K(I z;rn#bnV<`#lXUWogChcwM8Vs^)=go-XEVD*EiaqA{8 zoi5r$!q&O%#{9C0Z#c|E(FaCre~20$X#e2nc%Ts4#FDC9e6#6_84HC->@ke9Kyddr z|Ba0pEyE5eff28R3aDQLG?6Wnc}8sKb42@OWNFh&Ow(CKjTZyml24WEAK+sgzIpPx zOPF0TKPj>8pB`e8g^#FjP1QU8N6<*#>}DemEs94YB7$dqXd{TOj7}^x#xfodO zjGDs*`5#j$x?BX_amqdAhtZZJG(Og^=}1UK2gLr_x-gliODDzd$hkiDE$Qr^pu?<@S!UuB_srT@YcZzAYE~26N}qkkzi> zir8AWCQ&(C(NmDGkm9Az5AOB7Vp}Wj5xeso>u$OIS?vfWUN`<$Req-xz>o{P5nfVc zjiX)FB{uidQgrv#rq!tK>oqg)wK2~@H`LZgt)3b4Qa8zk9Ic(oAI{rW?6IK)c%hu& z9kb5KgAvNF55FeIR_Zm7i$etDv zkE35!8{FFupv=4f%ENo7@a0<&-fm6NE_H7e3ciGq>{2Jh^=@7%oWa&ds#V_Vi)0*A z544ot>RrqvjIN?~K0F|6QJNl1f}+2>>#+3FlGz?v?c)|8O5)huE^#Jg{v&oG?zV6( z)0)d^?{qs*38r-U4d6+QD9p>&UwGBb4j@Drrk?wz^`gH~X!6Kh54PMkILdmvoqOrW z;k5f+8LPv>%F^>c=?H@_>4yj<|xv8>+fP_b)4@ZB4#p%fp4a^rh|DrS+#`*_n30<*a}q;+=49)S}ZyrWyuOO(i3X$ z7X66GjiZgPm1gZ*lI%TtfV3&p)yLm%b+p^e!T)kDk|Le6%_UGhDTPAu9~3+@}l-$Wp=~y}_=8&5+yP}J*)(=@igrhu5Xk<9pn zJdK1Tl?sq=vAUU3cQ0&UBz#ye?GsaqQ{S+iy{4AT8|^{$RE=&Pvo3yg*>0+h?mcwJ z2n7#n&efD*{(9r%(0u9&2!_9@F-06(-n+Q>CwKc9m6HW!Wrc()Tu^s5 zr6-{;J*869?1VJQO)hSW@smi0ApI=BoS&C(Beo`njs5ucV#boWg%J^)1{i$bC2buC zmpQ>e>|mt^B?}N9{F()bbG)^}SPSeJV(30gbN(lHR-aPH>WbkVX9(4=Kgw%!1?;|ih;ESYIQ6j*N}wT!p}`z3(__Ac27^rFJxDanGb;6@G7a%0h;mYl zTdvO;YRh_}s25XPDrICFIS2kU7G>iP{mdV&{G|rafy3cwFC{pxA^G)kTZ)DAc7`D$ zZCg-9nw5eMG;8k~EgezLgZzWtBC60Z=cBTnT8r9TBrAB^BTo3h7S2rk0l|<>qdw{R z2yOK*7Z{t0<32>P8M`M**PC-RXKIapRkk(~_dbNu@PmGxiWVeou3glJhtF>9p&!Lf zwKuvNjhaT*IgXemv)+pe1-aJ|6jjMai|b0$@E#v_dM)e0KUD4abj)PRE7qt_O4v!O9tNtH{Id*+B=sFeEZF6Vy; z?1Lv$aG+M@=$#}`%@vw9`R?qWKr`Sw>RDSMeqqmU1&M0rvp=J);gCaHFwvzIY04c7 z_Wq)H&C4h4$85LmeeA2%kS(yv zS&5#vLaQ|bL9^T|h z5A=e;x*~IlynP1O-OVo^yMiq)tsU-ln{B-Ge-~+atGPJSJ^wKO`TxWUjU>l2i2whT z&Ko>#{aW*ux2Eo2okGC!dsjv$dgWEb-p;(1|Gd`13oZOR(cfc&4%Ee+?r^0_?}JZJfV=DS0SoA*W-RMS#6UZqA&l8eN-+XjvXsK_{!~Eg59L& znqvhu+{>##vf_Ysh`aGbFvE>PLgr+T2DOepJk4l0B8hg^iU|!(tUm70jn#KQ!7^B zYT(6`Rjm4MsDyTtKUT;WZFaz#z8*+16-Vv`FUf-zNcZ79E(TSH>c z$?ugN03~-i<+q5@zmDk8fLsw(RhRfv z3kor1w~M7_CLCN4?dQ^0z44k&>hs5T4exJCrfFYLT@$qBp0(;=6m}&yV7frf6yQ25 zR6@LPusUi-VcMPU+FL&}m*mJAPZ>ZcZW#9X@O7fC)mQT7pOov)aASPAn$cK?yt%L& zW9Iec@)hc#nyi*e>2UM)ZSAA>jvhFu0Xz}g{KZ#lIwv&XJ+uS2wY}%>2=OJb;=hq$ zKgUcm?s>AN@&8IUk(f}`{4#9itM0d=&IE8Z#2skZI&aBp%Fxhd6ys|fr6XXVJ+aB> zyrV<`!qCMru0s|K#Q+@S7fsY~=CU01(C`LdVtKYnd`((ehvHnLceda^=fJd=0~en~ zNLf=}SO1ikA9Kn_6pLO3?Wj*-_rp4iPLUziE?r=o`ly>^e3%C(=IjOpH}2MK=+Q9i zjE%0>!0~)`hPcjPXGZum{QV~AudXUY9h=o89rX0R3B5|Bphbe3UG*pAWhX<~-#ri3 zi_%|K*@Z%evWYEs0$23d;*I5U(J~~CM?`Et#M&Dxqh2!?(_klTJN{dNvhDW~8tl(U zqEjCf>vb3c;8gdlb;c{SFUnlnsJ2HU=iZlQi3T;@Jb@wk7(3!OHeKh3jK;oSY)v-# zc)ok_)9TnG8euZl>zUQ1HMSS>x=CW9u1?Bc#mht4n|!Nv zp@dFsfXLU!W8+5DD}SNP)@QM9+oR9a7-!9?^2Hjz;{h@ByS1Ukfs9dLI`w8fh)i}! zw`LtTq#nIeB;UR!88C+Rk3{`zDHMb=uAWR5vRtNx$yokpUG`%E&PD?L(^j z=FH?gzwmy)63{*7VQtW ziv13OxqW@UQcYl^Hwh%|jE;%PZHuU}6-okiN{wnbrPe0I)I;*P(M#mlXlU@Mu0JY& zBPHri=G4oF#iYzLa;j9-WeC}WjyDM5giFAV>?uL3VZ0O2Js_ci`D^sK1&a*f3AX4e zImwtG77|9A*b5^*99UgagymLf)@Xo9y}D`0+sA%6X4=~f-G|M;yXBbnXn}lrN8i(m z_{@UAV#n(Umwz>PneHmT{wp3`E|@Hnj0y&Gct2|EBk6(Ew$GgC*&sta zU%9o-%w>3MyoHSC4+m_dy+@z?LK^Nf-9y-ck7A|MK}w#3hGtt!NPX_Z!>c;gwdSP2 zHE60Q2>5P;hZI|)62P`MnH|AY3AT@`+X@VwB2)w&k5Kyu>7s#byJoy5ELpO2>krbx zA%^AIw10%s8GK|9^-627jZ&SCl#Gn=mgIt}QPJJ@419mt@$^Pmh_*URZ}>H{+qT5I zwd|T=tSX5^>TI_!`Cv?bWI~Ne)mjyrnx<;QsM>-QKHP5=S#Tt59T_MBF;hysY%~}W zju`8+TdarG*fXtGFC8|{}DQdd=i>qT8jOCX+bnp!>QOa_&mE|Ad>JML2Jq;D_G?lBKt`ySt+ zPYvo^LDz|;l{iOZydF;?iXe$mN|WdO1JK`Ut_gpkXSM|Zt{lq=Vt{0p=(w;-f4UY2 z73@lxMUE_NYJb06JeHWc@4y_7cH3iFH2#=^;fks)4v6F$%QHXF2vNUJ?-3n+Uqc)Z z<}oHcN)mM9VAelR2!Sm+E$|2?_IV{?q&rtwHmk$rXMhaHzZrI{% znn6t?3hxK&yhl0iPEKvg!XLA*YYhclBr^4T5NYE2xb|w5e7MsgWp^C`ZJskj%Y_0! z1C`L1iGV+O%MU#KEN&5YMepSPf701yj1%vF-TRZ(b3Kv!mJ3SnQuo`LOv~MsuEM>7 z1VT|KI!H#7j+WTCC8HCnq$hf*!QT%aFEdR0cy0#Q!*DBU+_@6ezA0j}#Vark`M@T! zMZ^%qukGw)@NycfmdHXArA3yszKs8jng;+;5bbC4DerJGh zigAtObB9(|?((X&A4tE7CW{(QO@^lG8^X72HSCk{x9acVi8fGpO1!PXQV0b&>T@gm z_??7jA3(g+m73_)Er5c`69& zQR*?z^cL&;&z=qfEhcbXA$-l5lmtJ9mr5BtO0;Lp*kmQhfFVyhNVI~LG_(u2I@nf_gp!^ljR*~tkFhxrZKM!oHR88tudito;zb}yebr=bLN{GgP z3pS?~3c?WcIYB#c0&rTqlO&5M#mAc z&Ri0AEf=hm@(YeE?uB-(TI*K5q!dL5CGlNMGBZ;z>!0x}F*z&^5`tQe5C4oNIehMh z+Fo`^xp7hdX_*lQ{;b1chsy1EDtdhEl+((KWT$2Uwt*&jArRF>!9GOVxaUuH3nP3a zJMuCN{)Hdfd@0uGze)~$AqV8bnGRtD9np(ox(kJ4LmI3iG}Q;2TF-Y?6QpQO(G`6u z=%q0qVY`-fFjeeU8gR9HymGt=ezV1z`KzPJ9Ei@F$E~#I!AA*=byA6O(wr!^`vob{ z3CH$nGK_CSV=3fKYFx;o(~x%n`B_{ow|Nupw@b4xGp0*z@Bs%c8l_3nctFV7e`W$T zacpKFBKOB2Pya~>OFDi@ash5?qMB5G@+6^7VBAN;N}Wq??;Q)>^NQ=nu% zbq@~wn=R)TRJ>ob;ox7K{Rx#1HBy&CjbdQ6hn9NX^8RD<+1--jx+UwUxuO6-3VD4I zW`J_Czr}lHH-VGbo?>_){aPka6pEcqK1oJvM|hLm7{tPtphl@+sC+6lIj1*b4ZBX1x^gg;0Z#az8}e zka6K!4d{e| zPE6{1EpWaWS3;{xT|Dk_PPqUd9ry}OY?MJvQ~%)D<&7srPa`uv|2;L%qtv$h4lzDO z%~(XvagTH!J$}jsCG|K0s;8ZC4mG`bq`K`?g2WJdfk@V_?1x#aGNpAT<{}*|-BV`9 z|BwkSn^a#Ou|Kw^Xt-h6+wuW>(C@*{_PvU3KjB>LXqh%%n0otW-nm1@u#OcnbAL)} z%AhbP>+MI%NhKUk3jso&Krs(ivIC3)*|b&YxWC1L@Qfg?UbZ_2VP9 zBE6nvD*JN6c6g|jt`l!4I;{j>uT)L2p?!NxJxwPKdL#~ z`F?<1e6=Lxe&ZMzobn_J)n zVhC9jK}tuc64e(8WU+n@4;nLM^iYVXASWhvkRaggFeu=EJB;AzCR0AMir`d#5PpR_ z0l)NT#K^8V9?v4u9&yV!;#es5$&dM=w=~5#P2L7JtLw&SGG%5TwE~!5jW_>xGZe#K zNI#a6k_!YhBQ=^v+iS`T{zrzfjZvpGLI*X|>M*{rp zDzSkL?!>pHeJxEz(2m@Y_0s&?3_Sc1D%Z?7d&U^--=QTpqOMRKrtzs~Kj3F3qsn(F z?6&NL%U&)57P!2O+|vr~l1E(r?ZRaL4WPJ#17qyN7a=H+|F+(;DgHF4;8nua_>HUs z**@cAi^QA-4%_Dj{ibe z>C*j@j51*Dh`6NnB`khl$mMdzMwD;2!?7Gv%nqW*0!@-_dKcwSaO-nV>I{VD4S4=V z{Wp<#$VCE9JV~-{X2<_F>P+GFm{8cSkYX`<0cv5wAQZA^Jd7qF@|oszra%>ErB5=hL_ z68C?C^rMNjaIvT4_^8mSquMOzb4=$1p{lm{Ch|XBr-1Bbe4>F#43#vzha1ZlDv(@D z_^$pOSS(3>GVMV!rjMJR%1%$?%I+7))?QWo*qumwsg9Jo)CoPvM;5w-%N9ixRKs5s z#Y&HJD2o!ufF}J}Uc}H#V`Y8x$Dc?e2d}Q$F{zK>6%pBXL!0jhZ>Vuj(reavECgz_`LsV04nD;GIq&LZgD)QU~e;4<4pIr%D=c}2TM@C27 z?ms?b?XoWBJJVlRX}$Pfb;J!FmL%-7zxKCvrFge|C@Gi2{pA$ci)r;I{3|xuYDpv= zmG$3e92r&1GGxKmmq2?ghVcX5h=o^JBLRF-u+- z!0Uhv_4M^Fbg~=&Em5V{^m+p36Y!{}PWrKxoFjQK5uCqRAh6ek%tk`JpiugXyYO)Jofhh!yZj=6_7PDXK?q;lU&Q)fFJRl}uGOvu5d0&vq*}@Rp{ZliA0wKlAz|K=<#e(J*eJp+#Qf zYuXty#rpsA<&^=7)gioaQ%|F*#sKaVhXMT$)#OS+nr8JqHy_$gST)0s=ev4ep^vF&TvVx=SjzYP+Ntnl0{g?_*Lqgus` z@^sypf`bZ>Mv9>@!$RTaEVAJOfAgac;*_CEMyl%*djBTo;mTy#egY*M8>3mnWa;>R z-dL#~kG!LjqEv4?iy+PdNXNyUIEbqF%DG_%8pisQSuTd^2G;D zZ=A4f@7dW926k3Z+l!enuFLi!E; zw)68T7t~#71?#gvjzoSISxi(7tqcHsCP}u6rdmWGw4OHWf_`SB4FxeVPXvlat zZ)=kK;p+UmO2-g94ywOx=AcXA9bgy9PH_U(X%k?b9&F9Sq*nB)9lnJ7{EgOXEJ;aC ziMP$(bg=tTyGZ`Cq&Z|4 z-PtvntN(n=vPA#5xA|++(!Eo0GPf)Upi=FaYyi4Tz}GzeNK+e$?D~~nP&0*1CXIUp ztm2kmCjz(L>%7UQRIy{}dL->p^+npy?j{nfHp;Q-j6!#xY#z^LdlV2&u(+49)i(+{ zCwG!g)m+c$l5Bdn2LuLhYj;SR0=($-e#D#e3Gw`tw|iV<-WoaC1>mW_@+y8{K~=3| z6yiEjtWheTShK@B!u|`%v7}$bW*j>im!$8r+&;-$lemi=<*w;Xx+gL}n=2mC{=P^) zfhN@6I_9=3=lt9p@<7<6Atuz>#y~30K)EVCrLS+*Ocdl^Ph9#+iu|nKH%M-kE{K_E zJA}DI$rULOHNn9d8U+&yFVgz=3O4c^j6l`lxrY*c%w*=Z=on&q-zv<`5meBo+${EG z%QC!tOdRfRD%9%3(+qg92ca3a1q;MI`xt|c9*e0XlDFV#`tLSgLfl)j!0gLE@`XU^OC3Gwx7LrBUD6NlZ9%}n8h+Kw%w8h!~jqK zZfe+}VC8!!7?au7`=xF;QgcOG)o#sq^ixMhLKpY0Q{tG3u||a*@vP9CiDtb!j)Fw=nb`@B^)qb35AhV96 zS#mDSY?i_DdGw(Oq#ic%@})hTdxvY$Cfge}vUsKetTOEFCK~PVSNhX?6=mO3_$k47 zFS`@3)i}2}^Ty;mtLXo3hVrwoTvbpo#z#|^C?57t-hIyw)FX(f%P>S11ns;F5N4#HR)Q3EuS=ky% zmw?H)eXwQ9{!6*H-ZrsMJ|UQB?qQ!u4-CGjH>dV2TTGM3LEe{#8S1w`1xS$RL>9V+ zCLX|4S{dstdS7|30&GwrQ8!g0YE=p~r|v-zVX6hrN=TF8PPxw=K{Q?+{z~DTVpe_pejGicKNCRHP@Nw=k>3s+EBtm*O*7 zAAEheldNN9gVkgf)F>@U-C4C*LhRmY$2Tvop3Z9OZAbb2?CoLrU)_YMTv*)rLzYWs zSMfy+mN(GNC_?x<*NE+=RJ_D|bclr_<(^>NKj6pVD%8{2?paTQHRGDXo5r*F0>qQ%Yos{(z6<=tE92UcPfc_*d5)I< zy6x;Wb4&F=AfFse=JQ`fZoY7i{E{$-if%UyZ6m68c=Ftv^Duwt_e9&Kr;Dvt)e8x{GVpJE&9md`u-O$XMrElLVO4hV?hU%m;f%mFhCy-G zZrkGZD+QA}Ar<}=g%L7C`da;@8Q!nFSD$r$bgkdfgqofvn{K*X zkwv;Um071o`@HTB0_9w8eJgUE=vY(J;pQ0kAi0B#QOLjRbgd8RF26ICcFu0U^f8fP zQ8Zp(_GAiMT)^>LwFE&$?@+ZM*shVI7aL>=Cg_cb=d1bj&RCbqq_!KeIz1ckpTQLs z-V5zxRVH%G%`>eo!I?p{U?x{cLU_4kbkzT2zHYDj{8W(6HbE?BwW{XZmy6paW zF@Hh8DBeqC zy{%!scr+EePONHh43yJ>99mrvD6OUT4C4@mK)qhmpn%+L%v0g&Lgqsh{E0F1vUq`i ziJyYI#q8qV`r}Szb4Rz{Nh|SnHO2J-&v|B(7dFByqFpIAz9^fX4n4yzl72vFpJu&X zV>eQAf0Hl>Zl_I__&c;&p|p7^(mxIP1}zWIp-avMI|bfH77K*L#$jwT=mynjb zCDP|6h;EWcy+@Nt8-J2rI8LHWiQ8~`BQoY3l%pgp82pM#Ow66*F4Z`AjylK-J^Y(Q zIv_FgqXuJ_E1xo}eml23xmr@(o*Nft$dLvp$T@&EO`1>v9CxSq%_;M=y4?CZlfq$m7;wJlvsv=8l1iQ{XCc zk1E7qlGx&6_gWq#>(8U#?g*0ZI`q=e4svhptlJF_Hu{}Vy_jCYa)xuX|Jww34ffEycsl;mbWXe0vz7 zJ}Vpfgp0jSqTQg{kNbup5AH(x`yv}pt-!8C?{X>5hbDjo$Knp=jW%tf$c45Zh_#C3 zTF=4ByLj*epQKT+vXTcrp*@0g<%7*RTk>x^;=Fs@9jfGAEwLXN zxf1@ggz?|9WA|(HF=VEPBm!JyCD;thAjh|98WAQWu5^u~YMWB3Sj;!J01iOQs@ew} zHzn*p=NCYm2!F^mC-ro7k%4I|zczeo2zb0D%q{h9hJDB8hGpBu;CMe#b594%;FI7` z=4J0ttC$$%@IJS|)VzeI3&I?#uiMS>&(D2$qIqEc0%Q;kazB1qxo!#zf|8k!YAA11 z!PD&AAYUlNpKCVO@T{$^GfR1+cS6yDSMhOPs{in#uX2zRqT|B(+dJ0aCG2`yyLQ_}^QRl@7c49CxP>itUcj&PHO3pah zh!;wsHP7syKgHD62zlGj?Ui1XTrH3<9KJ9+HpY$|V?!gjhj*IgX}F@*htvxH?~3mI z(qI3s@f#agssC3A57WE6nf2c4+(y3Dh8IA7IGtOU$UGF$Ui>`EBk8Z=64G*y6qxmH zhp%e?Tm1e)B0%kZM_vz;S8O15x%q#OLVdpEW9u~E?`naNPO8}5rmrtIRF=$IXki^c zp1i4c@|6I8+tGp3Jb|~+O86s?+*vL7!KcMikiU6=i;gIPLdr^7yN}NQ=mQp!=Am$4PxNmia}~(Eg%& zE^BcsZ2AFet|WhGk4xPGQr)||AkR2NLoLrMU^j@={O{6PBJ<~r`DG^!Nr&)9?1_w< z<1UMPVbm*SHx|Tu+Z}-TI9Pc+%X;(ATkM3=E=Is`e)#!IUkAw!Nt8f2PFoM$$1tT! z#kXQSM;4S1Kh!xJZ<2x+OB9G+OPnNeIZgnI5zQGLt+bHdf%e5?9Mpx2vVG1DTBck* z*Kw7OU00-}EBh(0h>K^Q3DkE;Cyv7`uSwT&u+iHTC%2MahL@TtcS=|<==gbRxRU~H z8gIU~DkLvf$T6+i@)mt;ac`|D_w*X^eLPi!6%OiFEeGGi@zFd>!$`3UGm>{7n9OztNQ9Z8ZT~ zc1@PEeX6}Y363jfI-aW9b|u7M?G4rE3c!cPRDRM`7+dS(`$C zt?}=T{H*nF-v;oQ9JlwLse`mL>TdicWG6%0i;%+4R8hfrK^v?_F251d1#N|~3e5f} z1mKGp9-z*=|L;rQw|J^kLzLm&yEq|x{Ua8ltk$iZBi$klv@F6Qwz4t&D;G30yXa(7R-Ii-;qVKUsFF~ z-YiJJY~L~Xw>4}cexkjN5H<3-?a|Y=@2#TXu$fy=^78YCe04JN;_=rng4WBaeQcp` zJ0hl>xQlQ3#s!l$BE-avaQAu%9Us~x{u1qYSzY<^D|r8yrdl56AAvmHUs9%IR#M`1 z#?0+f?#0W{dcSsuy&07cN$i~s{Sf!eVWeiT&ld*nK$!+{kpi`m|LA^!)6>AkHS1=f zjJL;cLLZPpUqo;r$U>?GS?3*(0x3?4)JCtR@-(h-N-Fe6ucz2HPE!0luC~F+#aAq0 zw+5`wfN_)QeEi`{=FScw((c5-dBI;_e!x5X30jn>& z#r+nM{-KioVyl8pCB*RlRv`9~liG0dW~OdC^^CV)SciQ2{`k={%_`wL$qLn)C_1zW z4EBp~fBwo3qfl>ss|(OyP>EfseTj>chCFi$m8Yeoa>^dTY@D?mNd4T=t1V)IR-Xpk zD!%A-GVTi z3W5)=m^2WZc96%Gu<^AjHAQGpVjsUgO6GZ|u#1HDP*0JtR6`Up@YgFbxg+pVXdef1 z0M_*7hIG7vvAU8OOg&N^RXNIEz}H|g+nv|{oMyEQkQD?uuxj>Q zY>hx>TNn-g?%EC8e3KeJe_+f{D0=785yBo?{135nE?tol?p_LcikI@_MD^77tEFT1 z67FAC%(BcncEFTol3nob{*6ll_`xo>AB9B-LC0|oyG_@dhY0_2q9;f^y!y7CI!wQq z`L|Q$WSNES*XA4wE%=~eKmjxi)M}LD`I> zq`V7iLgm2$4OsTS(P9-wF}8o(ZY$R0hAvC>6TSeXr%T;PO5~w>4!+)ZF;jC__JXy_ ze&2s0)5x#9UWACLk0(+RADWo5fqUk9rO6`Z(aq}}!{nqlKXUL;wW=+brC;3SCe2@2 z{XEA3OQQE0wAVd#`%h-KW8nn6vIJj&CGc8>-njM9m#UJ;(zZGst}m*Vi5d5IdgHvi zlQkRjT1JrEw{3t>lu9zl%X%vyq31|i!pxfk$Wo1zn^P~@kk?-GhHiIXOQA-^nkb4(zGoItM8u=b^f}BBM$C zyz!$U;ER|yU)aR$t*$g)roc60>fsqJI=t7-u1?MnL$aAn*+xHdmoWN_^cO#HDv(NA zmbHyK8@ZE;KhSn_<)?UziP&Hphq^HP17B0O!A*Z;Os3mJnwqx9Ul21zeoij0nY~nY zh23L4S+l;ZP|KFldew!tF2rh%Fs(@8UX?~U=imMJA#dn{@yXJfNi>&XDV@}go}`7- z++8Z;9OOwi#NVFzp|C6)=)}rxrzIsz1h6v)RKP>1q-)hf9)4|M9TxQsdLo#pvx{~i zrFSKW?K#zfUyD|28k^SO>ZVMc%A8xH=QgS|Q+EqFXvph+{20|P{a43(BBny5;UH64 z(@?C3DjaudPRti86}sV?T%T7dJR$Myt{lJl-{T7Jn{kUHdmnmS$d>A!m^D z_miIZGtVjFEL@pj@|rqc**6ziW5RcS-Xiy;CR@D4n0bvpGWMnDeWd#3P^VhO{Afjz zmuSQsu8B{*6v-mB96w(m0pjCMwU}^8e@)0iDGsJ7Q02XDVrKvrQ~b2vFozj$_M;{xLgof2|wRXi{2mZA-i}58pm#VJ?e? z!8&*Y(wG>LRNWsYTxsJyU52Kh8KA2|q229qWLJocx`Fz|_zvAT#3zUgz}ZavR3F(N zFK;T@sGKpbR(I3Njh{Y=={e-2P5v7`H}PaD7-<~ss4g))nj5lnY7#8avS5Ke1>7VS z|C_bXL?V;aj?9e$uVBa3HEJ$DvO87s!1yFh^SOQ4;lpT!<8&& zTy(OHXqn3Ao2P5%a6?M>*^*|)8^w-kcO+KgCSqic+Fwu2J}a+s+4moAd*)zM#{1yV z>lZ_{?zCXYFSyz!hs&n!34<5jpPAA%;rRS4+*=^+4-tF*A`hD1k!`)1&lRDBv}*10?+C~85Ix=rrrZ7$JE3N#ul+P4^k68WF4=OF2dE^7IT|VvC%kj@gF%t z)@zh^YK06ZG}PgGBJvfEbpvMq0gKZSN+aPZ14yUuLe~<>5K~oyVaEgL14}~kr)Hth zjD1DE{k=2;uPD-$?C2RvH$Xvxs5%T#1!z+y_MzF5*v!6Rt`WR)vap~G^sqEJvjY>g zK}Nm~eg^k5&HmWUiA&R9u#AZ9gU#?zQ418H%7qq5`p)!Mvmy zRu)0veBM}Se_>s6`xfLuNY>9trsCq30C2NZooap-LC-MCqDHGRn0txTpQp)Xxz$X) zIQ=pNKyvyxPz>B`)oZ>!i+k&Vh)Jg9N`>jFV#Y0rwMN%dfk5-qbyYmY?JmtW78|ZL z&#;rPpFKzY{<}4jcuJ;E#b>xM0B%ru?^;^7WYfpyafdA3nQQkIj^PkV4NoC79qJ z3HTTNzRyRh;ot%n8#~^Q)1B@t{wHReL9rL(4C!R%VM}0>Gn&7jkSugCuZ8062@iId zGDRrw1?_|CK|=KZL)Du{L*2&z|FfCFj9oKh$&4kGofd={YqVG^Ym8l`LMjPktRrI3 zqOuIROLyJ2Bub1eOVpGKQPzr5#y%J`->c8(_dDP7{ioA8ooc4ex!%|N^?E)Z59t@1 z)8>x%C>ryndi?hLP%zc0g@t+1bP}fmH2#RnPTOWw?-Bp|r7mVJOjvBK{y5j2G1O#? z-73}Yg+G^BuLD_)Zpvn&rGSrCGpF*vT;lcBgqH@c2y_%w&n3k6jGyX=&?TG(?rXj7 zRfUL-_lhO`%+YM8gQ$_Cr zbyLWPhkMOh4&PC(ISpAoKE60V=oDrF`*%ys2QS?FmPC7S6ZWfV zPy&xHuWO(^*jfPdlH!eZLR=dW-v0D734i!#3vF{G+;A_3T2dlZg6Q7(ZPZR+dfzS> z#`7Wl8*8_6TU%CTzU7)V$%yWbvrEx9Sv-L{uW9JozovG_W>2Pr5#97tfI({RryhC? zTJxf4dE|i~R~fy0)i6cX?SJpdn&6)NmAD|2XQX*a>LstkKBB(JRJXL2S}lKIC>xrI zE7MUzBrp#iodD_X1#*7475v#fyu<6JBc&q?r!?Mvk!};v|2=PiVmUoQNWamYm*=Kz zb=J*#Cdgm;OyDBLYdO7%oc})cR!7>7(qDHYLB{ZhEScS}%*93ooHx?aI_Z8)5O_0y zTxl=zT^6_!7iFy^j(@=?9j#4{amr=~Cj)vxMcS7$n zPqH7XY2Jo4;3ZY_Sp&#v8_Q}QH4GV=axkd~YSEqpjkK0ek#K1hHh(%z>Yy^)ev*Q~ z(|>eBLd?Lf+dru~A3mIz|Ae?jF(PLogX6+Ub0Wf}x`&}f@7Fjz=&~XXG@(;lCHRR{ zBUyaJiUf*0H73Hp9B9VaSF|URdCH3iqwsdpFElwn^iuq&aHmgG%9CD)7+Yh_{<=fp z8Pn0om6$%r4B^aXWOdB9(bnDN>m{#A)#CrOp6ED9Z=qU#Nj|Cx8iEJBWksWsnEE7m zEM5ggwExq8WhQBN#pO|^P_g};>RD8gba&^QjMxxi4#LJG!AeihaFl^DC8sD$l~i<`)r>&apL8d{I^ zY0utQ$MA8z#V;*D35XonA15nys5)z?Wp)Io2oeMJd-#>n!}3XV)vTH-Yd;w7V1%NQImer7b4PPJbQ~Xrfyle^CCD zct+ef0WJNE`6$4j{{vQ>fO?MP;@(eM6^teiGGwx4Z47YNlHa472Y!$>_@&zQ)}j&I zo-1tID-GBY8n&(#`;=C<1i{s}zLu^lhc3zV9f6q*If>g^WJpe1geam>e(_e?eYO_~ zwO1_eo!CSJaFdie`I1UzjlMqtGW8>+ZiMnDVO8mg*aCm#9A&@AgszKXrYwniK>H3f zRW4Q?c(dw~nz(r~hw%7^_dfk6QEcgWej1|Ww6(34pKCe!0@8kdH3!3Vt0%^vwh@6J z%n&31UZd5e_zWU{UES4 z)D@7X;~a|T`SH{)7H?aD6X^_elS|@Eo7*XGPZP{n>L-R>^!2zS=&F8lk^ql5X5jJV zodyAa^S{j=$)BAF6Cp{j8iOrv7pH{KKrBWZ>n@_=*7V@j&XAw*Q}AmFJk*I~iIbO% zY9au?56bIm?O?U_wR6@48r?~jju+AdW9Q(nYXyuW7qf`J6*1a|tr%+JhTM*Ct>0b? zs`lgYCBT~81vl$I_92A^^|<-Q@kKYo^p{R>&Az`!dN_S$8rX3Y_al&juKwj-DY^f5 z4cQ6SkoV(EH>A#PQ!RR87`ZC-d)MDJ9n znmYVJ7e^k8!ezFar8I|O;@=T!y9AJZh0uL2n-TY~ZjWgzh#B;EaqubgCk_L< z0QrAFP#up`opanYt|GSecb$^G{Js5udzT=rX-idmrPq8tO~cH=v839$?NRRGXEL++ zEYHd+l0L4YRBt?ARxR!tc5a#EvlAMm{tp^mb4P5^_;Z7r0l0-nX#fRonDY1-NjO=g z2uXi!1`0cmT|2ZfHhw&m;Y{a&jvEQpZr|1D4cSt6Rl(X1@i18jqqci=6E*vDqJ&g4 zAL}0)*yd);3MU_V`Gf8u+nrJ`tzf>Dd?Y00%cxMktu}%uAQ(2T6B>TzNL6x4F}Z}8 z=dw*~iAf8|b;5IY&MaZMjxh5O!B|PmVs|DpG7{{VUMY=aRXMo@^)G?9=8Z52B6uuy zA9<`@pdn9ljBL&OOvDIu0F!F0*%BK{7aq4T7p=2G)mPxxV^0*^YKU=}lIyh4 zJYXqTYYaDeHrAXV5zLYD&Pe}rz*jp{X=2q<&hH&ohgNCxDr9f>mgZU8=e`8(?29`L z>mznQskX})-j`FEf5K<$z(7VgAx?^@53$Xt7+~PUlCZyM*x#*LUBMEI4oR?4Zk2)E z-W+Jo3lSk?J&>MMt)!knWxdvxnVC(l{&oCW$@A2K&xh80%erX*bjMwU{~{WPTN1VV zMI)xZQX*tx#8$h`(Nq5m`L|%Ot8LOvQYSnTV5>mL&IB7o(zNIhitG}J1ch6CHuJ;| z?VR9J#qOd-X%$WcY*;WY7No2^lxZ(Qm$}%WkcXf9&?3NixW1xx_|hf(Tt)^#R$FlI zWbIKIYi&tHZ&Ab6)d__Ns6lvXK8BOhuEEa75QrbQ5%<>HCZ@bs-3Zw4^V2``w}&V3 zBrN*<_PtO27}$E+bdAp0OZWwnp8iGu&!kusqW9%u5w%YONFtkS zBs*k4qO9u%LI=squ^l+Cws!EUsG+2&(K09Lc1A5x7W^L9jl5en(?CczrcXJPO*DvT zMo9MosCj)t>H4+~p~=B>#mP@kSIk-hxQi|aE&|Ya*ptd*)HHBr)7F`tG~#7TsFduZ z#>RElB6wBxqg9EA1VMDTfpA^Z6uGUHUpS=FS?8CS;V`(@VeYn=UE>0QAmge;bqikE zR^jY+`YH+j5%S^iD}maXIF-?}_w&3BvXs^1rzDmpqBaN*9YBdu3`DQxDM2&#t&h)x z^3jH26eK;f83x1wl~*>9W*?VGL8%LZoDw;YpnsIn5Sqe{$8s(D+VI#bEA>?NHBd-x zwiB>4Ackg_U$Inn^l%8qZG-(C6xCdJAg`pKQVy=!LX zK=m<@1$;tQi(1;@`(t3>T*q)~=~ZnFaTrzEgl1YJC5J^&~pLgyq^)H2W~ z)sAJAKPA!K9ZwZne~_6yf2P5 z@4Lg%@E&s=j!^c%5Te1e=PK~P()6FnTuIe`o=T#Yink^AO|d*=g`Wsr`q$1+mb)g= z;d5Rn7#V&(wOhT_3C)v`+CrJieWT65U4G6gJi2euX>dgDa!Py#%P5vhs zJ6^_e8v9zx6&c&p-Yt60JgqPh1xz4Hnx|@|W7cw%l?-5)_>E8zjemIRu6`gyB%b`_5ZAh0H4F4GoxbzEW&gPFCyxl#$>+Qk& z0QJ~IDaNk6g+wv2m6#5VDDIpZ-bc`PdN&nh-Rn(;H*d8SSAA`=G6(LTBl=h4?G>lr zA3o+L@<)XsR}DydD`hV>jc(fJFl}iO7Z7Hm`AEPMc%pdgrhxT#DMu9(Q*aqS){e*u zjah=Ohz76&%zXw00oTNLqxtu=U?7IIW{~&k@T&^}geW}GTj)joO;DCAP&$76LlkfL zbl)=d8+1V`nQ1LU+*PbJ zHoKq@wSk{I7+^kgqj~7PM5z$1+BjxiDYw4wXeZwB%d7ZBD4;uFE9roQ{l4+c>bI#QQyMer!kClvJ8* zZ@@7}WcZ)h?D`lNd&trUyJb#5d+py8o@DfI!@jdv^(@zXOIJ({p3|j)O>=6h00l~a z&uQ)wE{OK;^M7^W<*$WyI)9*n`>(dM0+;uX3=6Kq^4k(s~6xOU~)@;MvNoO)k^w=Tc}Im2ipte1bg1hd7-J-stIIsa3SHR(VADy@u`8 zSsQ2{`&qGxJ?X_gFzY~V zuu2~V!_~|02!IXe{8Y>?Oc1}3ST)> zEG+-aDj!_SQcEKlWUADpXhiC^-xGZ#n|d}>t#CC%!lmM1+3xX6`+8x(^d~6Ye^>qi z@N=rIEVocSj$fDnh`5VJyCXm)`H+5Tg5X+%Zl28RFKZpX@V>5WQ@E%?FOMg4p;~Tw zcR-p+WD%CTtaJGqxXBoxUOJqR6+XYeasX!HY47bOYA8{s$w(D3+GCV_O{K8cAFLRq z;ul*_WO4WAyZe)iuO;6W_7$KCGa#EH_K8kE;f^G-_-1m4WY|uE_AE_Z(=tDAeBdB? zKvtlfzeb5f&ZH1jyVdQ|TG+?Zn9=BgoN#REB*cBg`BrXzhU)!w)HG88iU4*)YQps@?fIrScUG1O<}Cn@Y|-CIWX0dr_EY!t{&_Z{%l zL`loEMqbeGGiU5TU@)%TXk{u*UHCGdU3D0FA))4mJ1DX2fOmlE%LG2W52GCmHtH$?Is7(cCXWZX0qjS4Hx2ZM6QFs|syoo# zP84IR+?2X-7`Gn88f2%=JF(}GC-=aL3s8-Y(*8@^hhT1M^AvAh`WdN`7Y|KA+;yg- z<$%Yi*pn$`=Rfez7bH%xcnc-a=qMf6Gf=SuPUrVDEEU6W>SZM``rJkKPU<9#?pAcp zsy($p(^3S^L{7U&>wQTtH0zcyZ*{dyL4`6zq>bZUd?0y_mLSd{*7}Snxqg*0nhAe5 zutgn5u%HAz(q{GZpXX~VH{x)jhE`;$pH8MM;=PrXCe|W8{ffcHzObdmwGslR`cYI( zBR2lscI_<6DSrd2zS%^gIj9d!Wd327NyRIx>aMkpBJbtm_^qQT>CLnc_kXlSn%5}4 zx3cva)Na}2q(U#gG)TM4OyI7d-<=I@j|`X~ly}Ar0b9xFn>D$}U1O)Q9k7cL7AWbq z!dQx4(&v`yPHN%!uR_aIUDfs+0$nR}j2hR)61oo88PAu@hyDr-ouY6TWFl2eWug;B^Sz~9c!r2)CSsoiw)yvC-&`-*bla_r@k1F^B6yM$=W<4%H=UB6FDv!Fw+yV{n@?5xiM6c!#2I?9Fgy$~4J zl>B+yjR1|ZK2a9`;>RHSuVD_{eu(Msd5MU3`;8)$&1Rna?Hw0M#Qovu<9D?LQV^#$ zS4w1>IP)6SV&b2p*98OaX#!T%ciz*tm_lu;Tmp5ygX1n7_Lamw$!BS$)9$|G!}~Y8 z{%MQ&J#!gpL@~Oy{!y87FSlr7v&zz&G!EpKdYWp?qyIpErMaZw1eQ!<=Cs zChyh$H96Yhbk@-)sUUL~U~n?cxvRwIIBNTT8^Wx!bMu3M>FAfg2dz-ws(Rd#iyMO{pw*_ z-$XSzxQnm-nu0?lCj{2Dja<+>@5(LLmfze0lcPm-H>*{b=bW5tS;;ZgjkAM#9fc(H zYgS35&1@Mdh?F2$NTvyy@@;&QP`Gh~@xo0Qv;&nG*o z8}?PF7(|+iRH#Tc2aV9&RcXdubO*I|e1^`}U$`nb%4-h(e@8iN!M0F?-B!XJu)naM zy-iJLBT((#u-YpfIrmNJ`9SSm3#ZgOe>*4RAC`PaJ-#?Sl~O29J5Brgj6f3Ez>Z}Y zcObXPsQ!#F1sCZ8IcBiTOy(xtfPnRDVx`hZY{%y0qSym(D9v^H-^;F{s#**gaLQjv zj00i#Th9`?687y;Pte zx3iq+eM5$juH+FGWVIri*K?C=pBa@=Tp#-0BZIQk%P0$iV` z#ixH=8A~YREnA-|r^(IKig>nkKUYOr}$#hANLB^$xNo zq03tN^P|+Z#6vo@t7{&PA|2pSao2O)4VwFt5{{lFUyLl>ZnPp6tFxQ?)1R4;2jvB>dKO^kE^Pcyl6h?k}{7m>EpIqBMOQq#^0 z3w@W5KAT_*dtDD@Y9rmROejsO?X%vIf{(HZ@YdE;?L&KdbkaH4+6%yO=wABZkCZ7? z@(*6ky4sYGIqo)dlKQ@kTgCgHeDhnism$1(HW01tre&N1{+cg3buxw*WIL2U8;rj0 zPK=u*z@g0Si?CT8GmXfy66U2@^q-5}$@>@?7l%Y>8*CYvoF)VuiGDDrvW};03Ghze zZOSl>HlQ0hdk;%q7{cj_E|y(wN!ZMV`s5IU4@de}$dBtn#K$kB4ZX(^IMKVOi7{K^ zQLZChRV|5V)a?lkL{x2Fg6oPFrGWLhr^2mt=q^bsJ(Ux^0Yn zsXD+DI2SSWxP!{|wpoY!SXw5z;scwTs3B9K6=ZH6sbZebTMtC;+-VYVSped3oHlbI z&tnmrtKWWwVwic{&PNY49|$F3*JyxE%tK|q*7H-&Od-R26%|J@eu)=UyW<$9O5;|S zg-ddwajr!8bkJ|7k};#iYBRP4LrB1oMgon6O!bzSH*ZZM)^NO~r2#eE+JB`fSgg5N z41ODO+;i)}q!rn#LFUkX)lXdl2Qhg&>D^#OC{&?Lu3`rw&ZY$+Pk0Kx8N%Ta{=caa z=Fm(Dijt5Xe-m*gYb$hoTq=aFc^P(M^fknBo~e>1b!Xr0zpKv&2gzPJRJl{Qnj|Ly zeEoqTpgW+^dJ#1Qcueb9NeiQSH+pIxGQsy^n!6w&$w`d2GNsi%Jfe*$WRoE-EhfWq zc;h`F0aCStFY#Da0A1k=5N10io7{4)(N282GeI)qO#cSb?Se7#-W|LNEX-HxF}kU~ zAlLumPfz5|Z+@7s+x*g;TvhkxVut7T%$XY}p3KeN{X*{Hx1+!;kp1+34s5o}Ib+*5 ziKj!#&zq{eu_!w#b<{?$C3jY%ws4;?FJ&6hd%{{mpl`^C^APT7OhWQm`gzsc;aGx= z_u%@R@U1g0`?TQrF=ks=Cj8sUBy6u%Pa>zOzA!O zrwSSL4DYGsy8c=wozmO5cR)3JE*k1MGCgf@)Euu)*^_5@g?@gQ&_(cfN8HvDS!J3O z#uUXIl@|7!oMV-VR@tSf^?aB4hlW{_bLcr?b4SAcRX6!;sJyktaezH6iTRQ1Z*dge zvyiF9bjBn_Xzo>T@&E_(Zm>_1GW=PZ33i|0mdl@2r5c{_S0?Gs7q*qG*Xz05s z{)j~HBQro?RsD3+iB#h!XWiGvA_?>lc;*7_o}Q`fc!=ujDbcb~j}`M6+pldbFqL+4 zwDFS_K6vN@p7iP>=+KbK7QZFRkdWLblnk&`j8MMi8BH~B76t1fiX zg*eS5u|e()h(cxHT(wpKb7>1-8qRnqn8<{*es9G=rOhR}A+P^s>LYbTuS-t`6LBm@ zVKt3rc9kF)Pe}xB@o8Cqi;korP#g4<%9!8qJ9R~*o+~yIU~>I*$U7bW3i?>eHSQuL z9=P_HFIYlR9UEc*=?2e3?mX%LZ`WSU!>nPnS6BQ2Urp3guz5U4)cjBS->e#)$@cmN zsk<5soKV7gTN_aw>Dedr1h-{Mael3IlNwQUl|Il<7MUK9wB&Dym^tJWiS0QMuz$OY zrKk8kw@5;RCg-hQN89#r{uR(D+o7Y4>Fivu(Y@L6J;ViS?+Jg8ej$!Oi*knZKGQ5!P*)s7BOD zO1jJ2`m#_1mG_9PiG`~R!MY&fPH36*n~D3@dI&i!g9+~7GO{#U>W?Su3dgNLqhR^|B!KSNqWM2U?)%1E6p6K*8ACx2@d$sij^tzlf!`h z(7<6A{{-X(x$cb12XseKS~2U`NviWNGVPG0Hu9}f7QG%4B`>|rs_?_=#K4t?vYfF5 ze~*8OS3Oebzf37ZZ6qJit617Y7b68{J5QjGX2t#10TT+Mkw5w?<>KFwMRT_pz!i=> zywu@~!<-*0p)zE2OPW)QDfF8qt!P-ORPvv_9&xQ$&{7l@UK&{|vDdhIuSi_@{JuVM z_MR@TqfW|=g$Ar9-_9$m`|4CQc+!%GJ};l65+6j+v|tfj+yKXL`AM`aq)1kHv8DdLvd5iF^mSc1x$MFrlsMMkUxd@f ze0I(+$w@k8uJ7;EczP3RwvdyWdSgN_V&Q8j=VU>aCR)^TP$U_%lwD{xE369W>yDGCwFdZ*{Dv(LRA`F`A$M6KtdR{5^T;l0=PD1s=5L>^t&; z7J=O^LgKni%rP$Y_(h~RvRgf0z{)p~i)nC9Rtm!yRTH7-3gLF>m|We81$a{#E_xe> z#8l#ZH3b5lPbPhs!+ng^)N~mfJghIp%_5PO>vpK=6UP8b!4&1G80NqF(PKs*F~*9rrldeASq&m!R!XRTj^gKQyD zJ@E;G^|#gk6rsWhxQ4>TUGXM{c~VD~{!oP5{O2uqAq_KvbyS}|R{shrg&BW$c@K`6 zu1kfBsTLV2{Xe_Bn_!n$g6}zPL~#mR=15F|AamJyliLfHMVQy*%cqDG*s(l?1Z&MF zuz&BW4<{l2*nuE(+69rbPeeXnb#Em`7-cvTfsfY2UEr!}m7rNm;2Jg%u|kOFIx)q|0$P1~&swH!ETkDbNUZMXkj7_ubB z^{m2k{SVcy+ngjCWC5a{c0GMJp)$*CNyJ7BzOEBZ@9Ef|W3x7}e9CY4Gnp(Cv$I_? zEVT!R3ifkOsr|kF(#2!#CO?0qEJY|BT#9UfKfdeqpY0-uhhP)wXbl`iJaeHf%tD*S%+S)+wtqI!Va!jA&V=bjk_2^v3pFza}^EV zC7)SPjfxrf7G7E1wtUs9{Q032!Ud>yQ~~kD0Z#|yy{M-1^CFHK$&P(+hvp>R0&7iP zHAwl4hIFfRlSIUyaj z%Zpr{H2DkL>^E57LKw#32IKkejLyU3wwdG%f$`^UPGbq`CTnfLGPb)7yD9bD&;xPO zfY7&v(*4?1?d=VfPABfE%5}8dT;7s^6Es|9gpW5^Z6OzxfXsMK)SJ=Dv`sY?tr)DH z65Y=jChn(*Z{$oH27rM2l{7-k5#3k@mGwlE)APs)L%dv|#12sPdHvQefn3)}23z%r zXH^umfP$W4J3(zOKKWY~`~Wn3(p%FeD)Mibr&IhASTE_)>&xVDG{QfC5s|``j#rlN zo8ODPsyWNy2x+g&6cG8mU_d6~5CV@#n!Vv7T>92m6l#STVllsGWoC9>?-pf%kE17U za~$q193v2-<)0TAQMB=CjW};4N~a#)W28^UjZ8G^;xAh=%PWX*T~>Cmi^AfzHf97& zr`y^>S#m3yJpC*3pVU-5>%kOs5PDDVU`pe}Z`23dNBBR!j3EGf463ekox*~BVbo~4GVD83>(e!nFW)Cx!%6t?;M)N@K*^@RaA0-OnWG~hj z{fbO2n&oj2T;)!7nj=LbFWa~#1(yj59-?z(j~e)I!vsO?YOyeW*J<2;qrK#KmVHvL zpr@wzJ60d#&dz-#x-4J5oh5u`-iVhjK26+V@M?^td|Cb|4%%snhRT_E;8hII8IjSl zS+VdPsr=1k21-W~ajg^rw5IP5vpN&^ufFsj5;yCtdhS_Fn;kYos?XXWLmE|(Y3EMM z@y(uhjjIT5PmuO$wg01mVKgC{dii5NeqjU&eE8kXxnYeossK3H;VuJU5;aa0A6FqM zZ%1N1kw~o4iL{a&al`IMf*=ZC+)V0NZyN3P5uv%%|4#gpD`-ieaKd;!`l3u_a`>kW z(oyU1p(~OHI`s3f{#hTc`hoRb_Kp9!`Fj16FBt!%|K4EAW%yjoHHA37Riu>X8wEsy zRTS(SSl&_b>0keXJFJW!BegB)_4pR6J1KWVc!ep2QZ zlDdf=Pejv*Cf_8n`@>w%>WlwpOT}P3J|96$!d0bf5Ncnm|6#?Il@;480bPMaXHofm zcY5q(zPZqMnGe18u`Z^vm8+dUbrdJEjSy^%vP!=U;g0hSaALQ9$?`BVJ5ERny^NAaGYW6Kft^b2DCVzCD6HmhX?o)6O)(g-0s-8#kpRnZckz2& zADrrbCHu>y&&?eUdP+kyxF|?g3#B=Yq(K_r^T@)wmbrfc@AW<$et*$C3)UBfGY{@0$B`Ie@ ztr9Rc@aA6*iCAk~D3yNuHU5>CSm0~D?#vIu>)8cne+|qc(F2Fdf7y1XavdDc56!8r zZTJC76l44OZ7~}J?fQ4^!eg^kZl%Ch!ac|$JW}!DgXvN|ADQnOzk|A-RT}2F*mGYmCwXX#e7IMc)ku+@u6$4>nHj*q=>(u{!hLri zyJb0>!b3VLwXD-$Hq&MgSgg!{ZpUG~7NujRFy%Qps0+$V8g*JH{X<9zaEC+VLb2== z6|Jo65;Rf&&V9Aih!a{_T3)$0eA%<52pw45vizMlH2J?r?=#eT2g!#9A4tA@N*)ET zLnS3*gkxHKGZ+N^Rz?q?ds~G*hQ@4X^I9S$q{)SHxV4eMXt5EM%LwT zkJMRKJ-!`~n$zFXZ8@-}Atw(zUkqKZDO~J2Ua6(^>!%d$JIOOhv4%*P)3wcs6%+WWDh>S9bLlyr-c{wco z`EnX5Eleq-k*L&UCn#bT6l4$|(aZt3Wt{GKfF)z-^{pH^ zkOw&vsvctF4UZqzR&7#-_8QnXw|&$MA|G{Va5GTq$6SXn8#(=1&~`G+;LRAOX-;vRuc;aHhe~YH%3qidnS`By?-C4|$g$7@=6{_6 zR_gOC)?P(AaxEs;(Ol@;6}CgXpj1d9W?f%ZEr~xx*YLZtiorpHa5> zf+1skL6B_g?VGm;3oL&KVkui);<~pIk{ktaT_WPY9f&W+ypoB1?SA7{f#0iGwr@)6 zL4-LCK2t%q8=oYlRqey$*O&45W*w}RBCA_O_d&KZf0CbWdlWWD1sqMOI{{K6s0IfXLUFrF9xc{l4)P5kR zoV}W_uzl3&i8gJ7Qv2BEosHH3H_5MvBAeH>>GW##_KjyH#`u)=1bz0eI`Dq>(*7l~ z;Cd%@W)PAC;un4~)b)*2+HJW_lf&Jae9be{F6ZA7w6y-cB9c=yQPEcOUD?$LYh_+& zn_rtO^+&|+)L>VbxP}EnxT1scO8R)rR#InN({Wddg-fyeJD$|j842mVVGbfrbB2bD z(e+TZgz4mEyZv`I9gf`6U-5WpTRMz*Z?>Q;a?GI)`Ll2_UG6%aL)<`+*-558gDcW^ z83mD#-IG&M6)L4az*#qXq_2(ac>KM%bH_zPV(E@c9={WjLr&urYipze8CJIjGGM=p z`vR4 zyChYsHm7D0WZ-j3#8w=Pw%Gy31My2FwY65zC5O&vNRs*03{{4LSFV-76F zL}=q%L(D;>Ycb<;_u$(}u-qTkj^0Cj!tvdc^<9z;aC!Mc^M4Js_VHZ$M9dDn|L)%I_;Xoyt&FuC_AZZEsVddqaGq1X0oxT z5g_@AhpK-ES+|Je%f+YD&y|qM8Zz(V&O=pR1sF2zY(2Y^Oq@02H`j|Mdh(xnY@sAH zh*RIcXkf<0m0a1op#81boBMQ2+D*5u$~DZ0M+cik&5?U8kujwx)7jan!AqKdphXcV z8CD1ZyieC6uRv{+7E%F>4|`uzK5~a_xr&0HSKE(}pey{qNS&~nl0waFAr@II2UM9s zyiIxv8~vzy*0QDdcp|EXD0#xXUIqxxUfI@5T(s4%#c!063)a7WKc(r|2{wCm!VH={ zG5goQp}V)be+JpEXdyul>_Pw2gy9xO*ykW(XY>o92JHuP=3!9aM50)zDV) zQ$|N&G(PXC?Oy*mMzv8m>S&WV@$RmKO)C451lPNmnR>cAbC7|1r~F__qQs@Y_34oK zw5ExJ0diWObpbZ^$f*Kt-pQ^0Aps~p#3lc@pfy^X=!iqi5X`~%AV#~dZMkIPPyV1s zyVRF6GntCHduXFj(<08G-W;0Ll2kcmD@qE_bhuG&J7JgPXqa-sAM=-=7`O1<{Hk{_ zZ6YhKeEOG@F?LBshYbHnxcQycsn3$$dewgj!?ZP1WZ4>3`I1n#hMD;g60GVTe_;vr z-irKz7`uV_pq}P4rlqZotWx+2IvkHvqC=G*-YQ8?w{)|W3D0SIY}j7A=e!(CLjYB{ z&g@JW?@R<}HFd3fy&P`O_N3W6Qo$_L%|i@VI99o!G^U(+Q1}srD5r1rt6hNk@B)jU z7LKh?kVB#XRa8#U6KUA5!*noKxpK?}VhBk-qf9w3`u^dhfQc3=eY66Yc^#})#P%j= zF}sU}e*A*3d~+-b3ro9YVXK4VTYvM{;`5WAn8H<^1*Gu;sBx8{q2ajVy1yO9+ZSW#Qxw(RRLM08cSPQFr;N2&gsp(FMgX=)o6-sU{q)8o5 zhXFn(1jnTT!^HXCXOI43I5NozLAQj?IzrCip}m5*=LOK{M+TV<2spY*+_>cIZ{s!= zM)ABqZ!NR+<-)%IWE9)!kdBZ?0&9ca$kVr5?Y$_5uBvkmMk!HRH3cmD*Sl?+CS>;~ zOC9eT&~kGAdwmWp546(=$EAtZ79P+eO;n>C3ZibYd-Sq`I>a1yruXt$r$&h@@OQoh z%9@*^Emw@`<;!%q$)t@;*craB&gwj~*V21o7anm|eORPG-rkdUpg*7QQE+?qc$N5l zfa!kbJXP1C=hy6}173Fc5ps6@z$0LccQ^Ilaq>U7%9p@t$m7fO!lr8>sNhs|HZ!1n zq>RLX)6qh(e>n)_;qOx)=^B+aX}j|LZA|DkOFcfIs*RJg_k^JqEINYB-X+N%%u);S z-2Fu4l*YR_JH@kIvjv9E|7#Y=z2Y@KqDMDQ)ls@W{X^~bnW0MV zj!+lk{ci#}51Nc*ORo4~)`ckOM#FL^t|F68-iY22BzG3>q)H**Nk4X7Hpyv&7Vy1a zqYkNVFZr6eZ|*2LXs56Ehtvw=x&W~$?;K|*<8~k#b)KdGxX|f$%H3byj`@>%G8A7d zG+w(N!3q&?cH8!GPu&9Y^{uxB?wV6TcbIVE&zc{78M6ONPC;s7ced4DxSF_^r2S*L z-k;MtjO5{*C|6?LjFe1ge3X*r35r%}iV!iA^cC2qqX;|df!g-Pgod(}SjyekcHFPQ zmv@*{FSY(j^nIE28$n*C1K})hOJ?P>J?B^t^K!iQ3Mm|_{G4i=m=M22zZT?~ zkonh2Qp$A=ki)-Et@iSf65G9?$}#l@a)&Cbew)=NFD)iIshILaLCUtNNYhW8#G*H- z7x!_4C*wIXf@%|Jzw1yEE64s@X0ghje5rT8dGsH>l%b@*R4glgYSDMp`PCaJy-1`= zxXXC@CZnzb9&NOD$r6~c21k=HBk_NrE;Yi>r9FHkFYSkI*^rlol9&U3$bX>gA|^#= zS|hC{IHQQe$k=4YQGF(dL*FO^;5vVBk zmGZzPL}P>>mG=AJ6VYq5zRjz37n2pf7*`;J<$y(~fS+D97ASVtJuLHAb&=wmw7TKx zUxZQg0mhVE{5y@lDE78j#MP>?7CAN;*MBfW7T0xSUg~;?&dS<_+bSN;y8TUW+2%Ad zrm;%1sy6~2yG_449GakvJh`)b+lwE%#fg_l#8IT!hRXC9A)Z7{ZmcUA&dJcTa0m+WY4AWxe|6+k-IL z#;vd6G)1yIiB7V#l8ZJZs=}Y7?14|^yuf4$5{%{`#TXz;e>MJ03B`8jjlPv0O6ST!GxwI~d=3O4+<_I%F9G(#rph9tkqe z4>!N?1??4W+p7YSYE3SI6Ju)x65iOvnDfac+@`Ne^55x-$d`J1u!Ocz6KU+$#38~_ z?`4#zbJk-^M_^8G5mXvHj#7R+XF0eCl1zbX1pht zZK6Jwk-%j6=OsJo5x(R~mdBFpbC<00H7$Fuzr2lzVEeNgGlpg%Qz8c@eNt?<`CiMy zbfl{t-Qgl{FDzkKrlPp>s7Qg>`TNZn0ToCD8%=~uKCe#UCOTtNu#f~E{}!c|i}cCR zQ|?W6-(D(|2vaQ3STm0mTr2Nu>$Tx-oN!3sT~iNthviQSTV*0ZR4(GSh?guq4n~Bh zj`OuXv_|X=;rXZhS|%451qn5FUwoH-uElv-#ZL(1WlT57+8|v116Ro`L-tw@qJCJ* z9sVm9z>3!{O?vPUAG=;(3tWIX^N073W+st8=Q@d|T$Znk5mQS)qpTFg8jV|qh2kIe zOteJF1kw~;@sm$*B~-Q42)}f+w=p2R`2kZ)gP97g6WF-g%6$Zx;mx-m>~H_F=~V62 zW7T$6Zm0|#Hi_NHDbpT_I+nzijd_8E&-V#eiTCN?E7Zu%uMb?pAEcJ*q`|dVuF8uX zO3QH>&z<2=;`1HM)T|*a^kC_rm~(rxz~%(yb!Vnv*XdV&E!D`@Cxd?a9n`=jJ?CwY zm&BKHc1J^%K-I20;Rd$dx2jZcI>iKHZr?a06)apky05&mTr-wotp7dp7QvtleOVIb zDOg*3JK?{81zyRS>lV?M95SV;XN*ZVqa@d-Nd?0fS)lE_+LZR3mP?+DPx`jY(^IN1 z>c@ij+&A6l>qE42a>^YJDO2Q-RSTX_QRiUyM1 zMk+9cnmuSr!Xhl<021FYb0+F>XL*)4M8}#nHmv z`pAKvu8iS}wwG`~4pS+!N)Blq5cxn^9^fEiYMxzT;6`g|na{t0upFlXRwPb8GeL;* zNpkeI@r_s)J0n(XOeiZ7Ie7bVpCD4H8~K9Io!xKW+&a6LX<1hNXe&2wb925WcT~Iv zhfNro+Wjyo4bnKG@p1vm&XJjOI2Z4sKb*^YKj($+{tli@)_WonBs9OM})zINRf- zN|}%#WnvfEBJqCx#-#R1<3vA24hf*{+Tm_BteJ zTrxk90`q-{*e}9atGWb&N`9jgLF|iZbwYdr$mw02bF$gKxU_%ygO7(Xv??gz8`htz z$L!*8$0NsKtP)Ik?JA~4i4Z`cOj5X;d~^6+rX;`;kI#?!;rX!S+23v#(>mnN%@h#$ zIp56>T2nkw6I2^Jl^unEhx8cmkW7#NZF=AIOfd#@4%iUH&h-0*U0n*kQ#0T63@5K@ zKM;cnh$ghCL3S$%G(zazBSEj=?>=+1$}gLi4Z*yg6He_tQVYBB7rL;d~Nz~~xd@}|1J&}6V+HDXp zi^Hg`Et5>jJ43oNJO8xs4_=Jl;!R0BjuipF^2uswmS$6grMEkWyCd>nXga%KE?B-D z8)H~@<4W|~X@5cd=LvzH*B$!62@0;RPxySxtW|yptva^~Z`VDkv<=zATTg$OC*&mu zpbe_KlxXXc^&aAn`VpeolQWZhqhB`pFfuOq*9~m*M_(YHZGXniVT{xiXQQIE!UB*@ z1yXOvO(ovLM)gR1Mqvv_XSF>9uPOYlDEZt3p+?*lY!{t3K%F~}2j9Pw)4t!v*xo_4 za!MuonqG5iayfEtWRP*X-riGKbEi&<9CA$`*F)17e)oP6H?vcPnxM=Re|{A&>)!F< zL3nsY&DE8oWW}`B%8#jfcdSQR(~c;FDQ}-S6&U^OWn5|tRLJPp&d=MLd|3I*lqhCu zW&=;`5M2L?KYD|cDpRY7Q_vWqF;6GDEE6Lshkfg8k1)%AfAQ|v)}eplFQ7^U(padx zmk-``^q*J`+9cHp)|2a;Wp+8}YzC()gQh$Vc#HK!%}xLitlh{JcfEdRm>znY~%hG2o$FI!nOy5`BWGz>aSdvEnC*ty={Dlcg(9K~8 z{1<231uA-r*5bkpPJ^uTo&A& z=-C84=wC4e^RB~}1f|(r?sn-G{Vnb&djGfiwR7E*dkZ!Ns;F)%GB2^If_QZ!lx=JW zD2c9#2|M&i8mmY4Rk-U?0~2*%DLVXQllgs|l;$z}BhrN$3zklwHiiBVUGE;w^#8~I z?_e7?Hm4mzn-OxHLn363(E%MDl5?VzLx>Wa^Qnv!Dj9i4?|KWVBr&H<5lT@hb4Wyt z$Q<{3_W6B(*Y~gAKd$LgU3R_pJlr4m`|W-tJ66N^^@kUn2iq(&=ez^Xhx&Q(uEg%8 zs$;4Va>4WDM(;cvGl`_W4w5uy&$liz9gm(uRbKTyvTo%1MgN(Rf(KtOuEI^`+1RCk)JX#2gMCIPhp@uL!2T&R zU9L>Lo>(b4F%F8(wcCD-jw2tSivD!8r;A?ua)DkRVOfcgla__wYHx1t=8vrr_*8n; z7&}P*d%aihXcJ+Xm?r;<@lRkGtBopx7X7~m@Dk4zr*|JXg2zPdAuy9;Su=9lcmk)> z{2Xtn^LE`@Eq`Ps8x(7ae2?iBW3X*&_w$ZM?gtuAEryrO*pE3(pjVosPP~_&Yln4B zd+;LEE7z}$48K2xiGN-|GL8`;#%(hCPj-2+GpAS$P?O`hQAd^u&lZ5|7KPT=4DBZ@ z!rwA~86)>Herl^u-fNBrR*w?5B4{+6=Fe2Jmw2cQl@NC}fz;eRtzo}popQA;9wU6t zoE?`<@RC|zo^VWgbLpF&{eumNuIM-capQPza;t@fa^=MzJbZwl=k+T-IqJyBvs=7y z@!H93rW*;^#wSB58<{>Pe4Az`?|j-D_@e{DH(dVQyveQ~h(pp}gnh9Y+9D~DIQ?Aw zkF0)sY8lB&PP6)ex&Awi=Q1HQTgSg{Jio?mZ*@wKj2yMmwa6JE*W5M|9Tn{q%X^U` zxk&=RQkzCqgRN;FQ@oT;-e-t@m35=*uUHYa}bvZ>-#a?Hr5z2zgOh z11aD4b^q(_j6r>^wwF#Q$b~O&X`+gFS(qt-ERc^anPgg(uYQXGR$XDm?xz zeF277&&)MF;`GpyZ>2cdK-FCoF$x}tl-{+0J!Rbbnnb)ZQQ|c0{96JD-h-vKK-xak ziXUET0(q8D6RFrG&6_H(BkNoZH&?FIi!OY6|BU!=FF}5Emz-po)R*n??Bs;MaHgk! zbB8L(rbGEj%HOI_L}ENAMfajbe%4{3Z!l@S5z%+WW;vyf7_e!VeLmPz_-6$^^ypbh@X?cLUeyShE(||mcY$Mt zRdAe5wG6j8%8CNoyB=O%UXq{i^>FUHhm4S^xpeMZd)&hJk$uY}o0d=IpK?g%b9dFk zt;&VX{mO*xT3W&UiK&i|Iilb>B~x*J+Y?Y0AoF|7I9)n`3=X_$*yEVA?$`q2Wc^WJ zJhY|qBmyAgu;|!KSTlOH7r)eu@742$a?wc3;KN7tkRFg25axdC6(@Mb&@|J9KiaT$ zl;5SIE!y@qC820x8B#ykhe^F9G~l7Q3*_EP3soS6=zvn$&1CR1k=tlp3X2H$w%c_8 zAMVah`6Wv)cn%nwpeoz(@x;WqZ}bLfZR#W2mO;DBmig`(-(q$}8Xw0-Fyk$#_^5pu zqNAATaobFGdmuNqAg0Rj_lN;ig11Wo=bs}RVL6Fn%j}L5GT+Z$Amh%7oY2bxQ3ED4 zN}4jG>Jz{Visz!$`y}kVJkq;;^UlNzAL~<6mBUxp=H*6=Jb){s4c$u(FYHODx(&6m=?DriEq!3jp348wM*OzQe z8I&~@_z$Y9)m2;$tl?)!Bn1Tpx{j}LC=UXUgeW_pp<*wj#x?8=%K@Sv0hfhksSNJ3 zGE5J*suU()C+&B>#Bn2hcG*}K>iYht@4RUd+N>CU)wNEpAHUvB`!A(vWaU6q%5YP> zJ~xm?i$zWBnFxs|c@ro$PcENg6ue0@l7Z9|NyTdG3i=%-j;JzA$YST8o>6 z&1lFl^ui3oQC3ct=f~sm;JOQIShE9p%v7|;M-Xnob_v!9trlPb6ou(*`dw_yU>?xP zWzN6HR}J;-EazM-%M(hD2HV_CGRhT~^i2${kSovXPqP`7D9MN%R8=7c6%wb$E$qr* zS9M}CUvIXYQBW@0iyob^JZO94J#x^({^Q|U>0N@8zzZTZRh$(~aYy?k=luiQ|CPOo zYtXd`lWq-x9367J7EC{R;VyB{gV=q{TVlJ?H_zSE;#SOkD~?By>`f4?{)}s%L30}f%3`naISww&46AV^0w%oI!?f8K|8+uUOy@)W|i!0!>h z0;mC3(hJ8L&uDLIQu`hWZ9itlt&-t4i*+nGmltFkA4Jb< zUxmAsP!lgk^7oZ>y2WNP0530gbJoCZ1@e{LcD3i)3kYtY#cc7~I?GAi1{lM$_E-*J z{Ei2UzRNrVy7R;UT5i(kF#$02ZmHa`WpXo7eNQ+}_$0hJ7&yW-Eq6n4#lt!Kv;aKY z`-y!5wY2w|Okd{H;@-of?9rBnOu_j$>WMF&#uHvEGw>iUZVEQ)#~R*AuB(Fw8YyG&O2{3tTUR57NDPX z@Q`!%D{IAtBlBlk2I46BiB{`on6}%Ssb}>l3z5$zJ(>T_%Y7fSa+sTRd7V%>dwCVV zbTM%Jfq&naRBZt+3P#y~wf95A;5*VnQ1qmWd}2Rv#8{al#l6O-6NH;>mrH5fD_kGA zz7ynZD=x5^ypXUfHdEVj)lv;IT5pAqxX621{)m(YR@^ z$$$GUTRXDnh-}Ss#JGgY43zj>#Er5uq!a3u;eFfO=-sRn!N7#h3NOVLbY1@lLmIM1avje`Fh%e3J>%*mOs`Ob> zMhznUi{G*1dCsgH?p;UDKj83eIg8X04}g&X5p^(|ZX0v%Hs;X3Ko!0YBNCbD6(SS4 z**MV3S>4dBiyb+fpL}~A^;rQ{yEx#)6N@hv>NiApc2cxA5}9rWMbKIS79S=wi6#*d zPe|Sa3c`yG#mp(w(4mpx5M;KhmV8jkiDLqbo6omPFqs%DyVEx0`4s2&UG+Nacdrfq z&)sJsb&7ECU%p0ZeleGib#s*W7E;`tp6{FFwpU@LfGf>xJ!1Zx~fG*co!g8${l*K%X@60KiASYcM z%`gdHP*aXgM~BrrRKXw0W|H|6vakt1`@_xu$2DS!IA{}5akb4hUId=nAAxoF-8N0N z+U6maKA(OjK<>fyvVtq^5ZKi1aXw`)T8#qp&& zM3pEg#b{@Z{)kf=7d@5cP(7Im`^0jD*pRK0wKrQ&>VQwf0u|T|7+jE6FF=3y9$dm6 zg`GEBwt(y20g}m1-{TNb>D0pH5GZAJ6a+F87srl6qE~iro>8+57~4|(>Y1@5Fmct~ zI%n}J-dv{r+COSDMWM_k0-y&2TXkxOe*)ey|wsD*-#?Z@ngB4h48u2LZQn>-EFaM4w=S7&Ky zNm6h2LtLk16|6!5&^X()kZl1w-y(`Rhb_d8c3e2e%MS5adZEF$v57G0ZLx{{1!XC$ zkJIgDnv)a+v~860)!M2J5D!S&x#9LpY5Lz~7W2%5(U350*u6h6dO-|#w(W@kJ8_}F z{a`J^i)|a7U9I&hMHeDMf_%t2+q|`;mZHko7#|%Vr<(@3Zm9z})~n!9R5JdLfpH~i z0gGI(1{q zDJwvuehC+s>AlaG9GxuZR+kjnbih1R>;m=V>o4^YN-ww87-gf+W+NA1^u-9Vzf28Z z3Ku(Bj!eMweO`Pf9NhQw*w3koR{b(A^yLvYs3p zbX-xcHI|ydj{kWp&)a@=m{I;U!BL{a1H$FFPwXJWP-vSvG^;4$>j}k{`>Ni|o zMm7XuOJ&~`#zH|+S1kl*IC}44h2*i{3elg*K#C3w>wPxo)r>yJ*+nFAW_E^nGN;OW zuR%;q>Nx9jO>v0?smm*?*GD$i^1b!=VvHkRkTmTw)*ZqwQ7t?#%g16;`ZalAD+CN9hUb1Y;LM4LK zhx}B)Iwtlff&d{bX#0BSIeJ5i4FxB)TZdDZiJQM^iLDv(uH#HcxQO-yTv1#g*p5z2 zXo*MSNkK^Dmy_}nM9X%7o_z0 zovnQM-R}_Fu)WmbW}w?E@13`5c%^qQ!g}2*UbSV_?sm$%X z`xknYhB-WHMfi{JOR3DId=AbnC6*QlRID>bM4u4rtH7A?Qx>NGtfs!SluoF8dc;l- z()BK|U$>=FZ|ZH-1hAP29xJCooRm1C(OV(O$t2TCuH={uqNqh zbtg~pwW(80EY%9s`>FUke0f-v)P)Ugu&xE?Kp(>gsOE#Cu<#hf6LrdyyvWq69j@oMwJX3%UrmJm?fbZTZ zJB*hqAgPe2h%mN{m>wRI&;|S8V2uBvS7lil)&A68G9)rXMa&bIc5Zh+R)9Z~@cCff zXl4$V#!K>CJK+AIhZ8FQrj+h);QFceSQmYp&j8MEFjWQO*HXEPn73u9t&fB&+bgWJ zSr-h1cs0VX2>+J=hVLWppQK07@i`9RqRf~Qw@fR|+dK^S&xkRqrWrmC5;ihm?sHf( z<7D%|^A`n~_YUGARy+K_hf^wgL#sJCATS7BtBwoC=cJ2*vZqzBO8Em6CO7rSxv|Gq zjMPL+4@M@G3;~rVz~3nMJL6-v>#=xdrSHeXvK>KM^|wH5B1{{SM6&7ElFV9Nh_)C!5dIl}^$U`1!N)kNR?4MMQ7%P&Xr|#K(`g zvCO!7LuLs)#O~}nLvYV+U2so!YmY9>- zNKsp0IxZ((ml&Fv!Kj~svIw|RZE5u%6Px&1wO@SVJaL?)8$^V}6_ojHN_t^TkK=ft;soQq0Cf6sesn&EMFZiOd-He?p|-V z@k`5lx6;MKsoeo>GI-a+X3+BohwS!#=J@E`l+wb$MFw4S9NBAEg?aKIZ+$mqC%(Sr5Nlo>H9)F-xcjz?IE}SEm(2ZSgkli&vX#5 zwK_LG>TP$hnZG=CO_T?r)$+K&UlywaUFOuSoWtVynW#b|L%( zf}w7@EkqO58Lp9YHA$Na*EUMjHg3HnO~DJdKhX3^YpHy@&B(aoC5UDdf;Tx&Dz2hy zdnXC+(*3J!vj<^h2TYrd$p`Gu5mQ0sdqhxzozBztM2!r6kwghYm-N~E5Y7k97FYwu z{?*uyA8V)jKY1)_GOL4-h5w10w&Q-Lei@i68BF)FIKum`nRJ=*-(TtAX5UhRAmm%T z-IR8^I0Zk$92Z+5sAiu9=59#KN!5D6wVlNzLA0}z!0>Q~RJ;gg+c?($ne*^LgEjFRD1NgZ^JklE#I%6}S(xKbKX(KN)j5Z^)Cz4B{g@fp zw^vl0W-lt95czBOGNj$(vKd-pINtVbym+{uml+m>Gx6C!^#^x8V>rTXcDv1f{V|7G z7pWv3%fs7-&0U7MbnK2#tUKiDXq5#e3;xJQ(vwg<-ynktR)gtL-n*4cgOY~govqIQ zwpJKWh+k`^;~~$Pa#Jc+p%)pd;)7zzRftOHCf0u6)VKQla6d-|PZIiKD^ATh|K7F`#G;j# z=q|Kfd_5M@=4;(sx^*z&W_;RZLmtz>4{m_$Eo~xmY_)IS#tE6D8)IrLQ_6Naolbm+ zZv$_5qSmUPH_v~MN+m(pQf*ZqMwkoJ7Zp$ApuX2VuVVsy)91-7)}mM=j94KaAwa3gSU(D~g1(_IG;o#-ElBPVXZ1J3QK3V~0|%Zp$D$+*`Qo~x zvHQ_3G-nA~Zs5E4loAnoWwO_K^e#)uT1b8&DK=S)`-5U)3+;tH7GjnySU-09JOvCV z#AOWc$>}WKqG)|fKJ;wv*4ngesd~0V+a|yPb)?xh(bO2ZBxU6x*TL@_VqX~Jz)m(kgTIux0tUdc1Wshf9+v~iq8UJ z5>|0%7W}orw!ssI2P|y1TwVL@HH38T{+hM;AIjmWq%Hiv1x>_A)__CV^MN#|GR(ZL$37{gRbSb7+B2VU5Bv5y??4H|gUp-)9aBl?DUTQ5^iHj}&5 z9zLvfl}zA@dE=Y2EFImr_P5?|@*I6ssvXy5(t-*F0x}mmcYv6<1BX<>;CCURe(nT$Dhq{bez}p`0 zmM~&;=pE|DdwAIC)Oz?AF~*PryFEq#0w0SO$U5!I3QV^x%<9C^FJl=FRr z|M{W2zk>71;P~!X>zC3}Uw6lr>um11^-*Rl`F1ee2yW@Uf78L^U`=bKPyOz&nT!#`Tk9T&)h5mkUv8sU6fwG|M@QE&gX^$knaU68Egl@@2G&10PLQM+ zp7!UXPn?+OWS{S(`aW`#<TMg3ka5w6O6`@nx?zQjaTR%?J$+?b4Z70SuL%{ItD(le=IbL)8 zYt4&wV;(rJ=#(=9U)Q_@AyHm{Z9WG+sT2xMm!D!ei%Q&X%ZP*UcS2~it)VhhalL`n zUc6wRxk+1B5fw|^^Qh195M0A%_mkP5iKo<`D(Q;GI#J?!2_mJs zrj14Pwx$~BPK{7%@r~4N6qZvd+#wOq^m(C5G#9l55`kk@VtUhR(sPm(3;jepD=q^( zEEBy>Pg>SD-!8yOCuoSe_jS80lP#h zz3rMtiTb+HrwIK_4WMR8(Y%oQ^{1S2(~(MV#%{-G_%%Qdecs$A+9|Ah53x)b3Qp@jPYGfvR@En@7m9h36Drxh{x-KC zqD*XYdG>T@8y8}F7I%-}|JKFXV2cXm%CSJ_gg0`|b$Tr=kblL3r4QL6e(QD}3l(my zNXNQr8yx|0`^zg`9Bxks#NAAE_xAZdb1uyO93BbP3*+5qY5|e>BqKJ7_!1xG&Y>{9!tF)yq@h;JTldH4dY-itdEhS#V(j1`oyJ)+oPd&rPmD(Z40a} zXt94_d^d5JcMJr$NB%#FHx)>{Xt%eeF6+F%0TliG-exk;21LhC>W?x4wFPpAwyufn zXLEr8P7xU3axMOkQzFMM5(ZXr7tNU2rSK!k0-33gI#NuVX~wTzHHa_|UYyGv_sO`7u&n^0%Nvip(mhVvhJrFe8e2E;(HV}m(L$XAHT z++_pe@3MpMXb7yRWDAcn*riu|a4fbAWrIBDF_nZt-Q8i?@kom*T5NvfrwTdFyv9V#6{*QylVe`q&shUh44r7Js%tv zld~ZNe@m$hMf%&+xh7)Vdh^RV*)QIL2R&(;lAj8c-ixl^ei(fhy1jt&^Nvzc8S3}i zVXg9MDY<8XOtq|t4c(`qC+TlKB_Y>yoV4am-aUOZ&D89^=VMFy>FW2p!lbwx*SM@|iL z!Xce!%XIx2wCLEQIXM*rX8H(0q0cmie`j@h0&du?^r`hqd(U9YM7L(YgC)p(u;QCv zHIrEWkTDGnzgJ6e9>^#jwF`7_MmEH*xoje2;mNp=0Da^Y3i5GQSEgixxNF!Rk7?#FAR zW=Q?!cvptf6iOE`0iC{Gie?5JPHfN;cZUgS&sq)33!wZhs z5*2wa13coxRC;VUcjVGfBY)al>nUz2pnrr|SQ~9!-?NW49KUJ#=~Xh=dh8#meBM!| z`*$GVbcn0=iiwv951pquqZwZ%3};%GhcUSv8P&c7lBY;#W~rp??ls0GDXrj~(c)oN z)b%{t>;fXDPZ20L$TBmSyX-O=jF%TdT4jV8yNie7Ib50B?MueRZcG`#(VD(F4=7jv ze9I3>L*xfP9Q=|*Zlbp&5CUKQnB$f&SRRrIR-(MCGpUob8fK%#FR@;@y5VMFkAAIZ z*W)qxfJfirp?4}?w{ye{CxL^Sb6|xfQ``Ks1xaFyt$w{^|5fCtZ)w&D2a!{stjzq$dFG zN7u#W%^iugWoE9zYXp|rYxodlegrRtuHOD%@fs?Z|F`(7B!3AwT`w_VZWkD{ zP<$FtH5@R{g_uM+)~L*90nA@xJk|m^X+=*m7Ya+xVVK1X)Devyl=xxpj)v?eT8=D- z)qb91hH~#h9j{v!TEP8Fw!&MzaPmJftWKUM&A5U{+O+(j2POR2NCX+~!?aTd)PHqZ zI5S&eYBcs(0E6&l;}jzw#ZJI9K%`CfvTESbP;!4h8!k?2M(QPeT_?wW-}x@6Hn0%m zPmqb|g3Mf~I<6#XYodq4XE-}0I!Pw2J}CL6bmWhs^?@!6q>;}-q$=;p7zIn)XG&{$ z*>q>5UD1)BK-bpv9q=&n5vSUJY9macdz=+$Kq*na{6$RVcxov#$L_n@x%2a%?R!n~ zo)5I|Mb_y}n8M`^G+R4#SthSRO}bvgMRfgh*!$qu2^pXm-e2ORQEs{XfR*_nr%TE| zB84iF%!2Z^16KXg`5!Hrw!Rn3Kb2Y-UXZzE*ZW~a)ME5<`aS7KcKSp6^Q_Yh z^K<$I%HBE|Ux*GBs?`OVhfTvKd>_7LfT{V6>iEcsG-FV55_Y%9@i+2~LwrB+bjK4K z?h~pG0F4L>lbIjs=r8IfBa;4v%H+^C9n3hVM)c6ZJoyJZD_+uAV5RcD*c!QmRt*~c z9PnQCl-k~GrVYfsPOU9rSM|b-;)4HquVc*_F z9cFYu{I~ZyoR~!apl5zd>&~P-R!Kfccq=;Q&dY2+0Sr3H0zCq%34TZYmA$VARd+Q} z8`<^@$71e<#Qsve3bEO}adq(8Z#wYiIkrA!Wak0aLw|0)I$vpV+|Jc`WS2Jf3v4HA zD@*WfE-ksRWxc^Bb=T^SddihHkAKjQ!3BEBzX`bFq|ffulB8@QHY;MIj=@es4V&X^ zO{cPNacxRY#(jyX$gwlP3oWP|vX%UuM!7&EjQ{t2Ix684Y-s!}3!=LTFq4t*m3dD($rj2+ zh)IpTG;hs4mgR$&IpGV6Tt&VBY2b_w9Z$YAsRpI4%~RifXoU5ix!niAi4O*>UzFw- zAec#&qwV>hd;o?XvLX0ER)){ySqzr8$UCJSH@l*HpV>mUcHA_JYAdW0vg?zixtVv6llZS) zr-Q-ocd@wfGRpCBl?--U*vu|FtW#7ldX}9Mx5ji0O$S7L3;%;+_V+0kzSZO9a~7eh zCCm1|%yksb3{@9(rEcAA5wC<#3#UJNC0xda%l#N`V!ep@Jo>%b#&GhnG#ZftqfU+-pp zqMKT}3@5C2i$=-7qf5wet+TB!7sw46*rdfg9V{Va#Wk4}F}_9{~Y8(BK_w%O5^&N+SBeYnzn5??kDE zHk)Dz0u{PlZ{%EY6GKr@EHydX)I?0tBx=Om5%ASM?h&TC1FvU||y;1$vnhMg@(q6~(N?Y4YC$kq`aU8|V>))Y_iBaoS>;8@f*K}%a#7ezxA z79{jajHu^gH2^I7v3-Ewsa&6(=ax55A+KIpzwD4#$Zq$n0<}E&ais^zq^tX|Mo%c_ zgZ)kM!gNb#RyO-m{6@mn6V-Z$WnI8E0oRP$GG`^Ze^JoT{w`*i_h@R}Tvqb52&9;TjRj?P^0+ReNxXp>SY=PWh4+sdY7! zBSR>==SS7Oj5>-GJ?@h^D|+J1KCT{3ChX{rs`o;EVe8e14;USgw-~9?F0gJy7O+6m z;>Wvybhnp)1T~9B@d+&}&_XqE|3>?tY%ycf6N(d=3XH8+E!Z7J47`B(4spNr!Q=oU zaVRM+fuc7n@=0^M$cZfIc&y-$Oy#dHJx%I%Rn@ed?-y9YG6vf1PDxQI>i6=GM*^qF zJlw0elT&Ekhq^laX!F9Br&Yj%n^d&8hkLkg^hZy~jEo}I(_81BchVNBZu&+oxwn*~ zxqL8t&yNvrC6k66Cxl4Q$78tGAf(ZS7Fqe5?gp`fq%A^NtbLI@Ra*P$gHVT;j?2H! zbUi3bvQ18xB!I1DO>Wch9R06(xp3m04ktpXLC}$XGNl_+kLvW49 zZJ8du*HziJtidk$CBn~Bi-$oCfMq6ZeiyuA*&t$mFl2J+9Aznivw+lAKbY05nmTQG z*#AjYay*rd;5cJnLbWxlbk|F6){g5v`nh2^0d7Uxde&2WnNQZVoq)aPEAd!Z zP+BGPhqY$Kwmn@py4BxCB|?wqG6^fNMmdgMp$_`)D^M(E;Rk$8|6N$vAgE7FZQsk= zL5?}dQ}ZTvCOXRcw|Ul;=uWQjmr$OM$(#Jp|Koj)Gpxy!0&M`ftYh|nW? zl)SL$T-`1UNO>u(FmJC$02!I?wV| zEL`>RaFbL}F}eG)pmb?%ZkQvp;@Uj*mpkUB9n6>`yc7GtHd3>fn2F$6#8du+`?}36 zPjz5Znk)`F5#U9Qh}Un^9_&!kTL6qzBs9*_<|0Zwu@atgVjgWkE?ZrBP>x~uiL*=; zX3~=10M~aGza?9$(SAaEvDP9;%#F9ym_6bGYXxAV!j;8#KRzVw`g5?IYV@h~+)3~g zi#RaZL-qoeKqvt9A&nst&pl;gq@=Y@j7Xko(MaowHSTKh+^^p|aF*r;Ig3!7-e*|| zHeZf?>8Jihq^_xHG*q6u-?pr>enHNH# zl*>xOOwu6Kje_#b5|G=cFhVg^UpsF4C;HhTg_#Pd7{IR~l_zalnmBT?y|%Gg00hW< zpk(O@PnHU-R&kYZ#`x>n$cN@^ja?rh!)HEv5B_?U<@{sQk8WCs)85aCOU5fuUQ&Ww z1qlig?|QnD>Pm@6)Sl_UJAqePtRcOm@>4$4@FV2siUENBx~Yqq&0`NS;A0}jBTM8u z!Q79XyrVxk4n0Cn{d7;r!YeUi3JF|og=FbX)qh0fAMU1p!)6^xm(jXMd#6#8Zcsp- zZU$hd0{8oqY7KUv!^K~ataVC)?ZtX{Z%EGY4@%kR_xAHpxv!wNYJCEm_9gvk1mvsZ zK~8V;*CS4U{?9(~5nk8*>Wt<}uB-szJGH0mmTVn!Y}~BDjB{mzbs#Q`nS#mOd0VYd z(mh!>_xWI5_yC;-j!}7KH~K%bNgB?^YY~-W8S(ahq=w4# z0XxRwUCrZf?L9sJPDdTp#3t^V6!`wG-U5+Q`4Zf)MJiXN&?(PXx;sEcX@~@5`F7)X z-LHC?A4KhH-cel%mj9{Tl#sB<9hEAc9zj|X+g>13_nM9Dxp9jmW_m~EJlH_|T^ZN) za#=>mxhIW-=Fmvpn}mbM`n~ULrUuLUX zTq<$ioHz+3dHFx-B7pz2Xd7WnX!i*#Qu!Qt8xw4W0cPtK=anDJ(vHH2piE6{zhSq=a8tO3f?OAi$)D4CcbUpj)>EM7M2tgbSDtFz=j$NX0RREAF zSdFkd4(`U@%e5E;|3m6hJimbk4<8)U_}Tlb`aBJBW-LYL;itymxMSI^j+k7Tb`L?+ zioq;mJfDq*oxsR7Pkf_>9uTzdtUyQ27mcbx%no42dz{SD!bjmZfOxWws`1zlc{h=e z+`Z2XoZ~^QI1CP=HM;zaFBTPN9+P^VD&a*{sSO2Jl1bW@J`P?Nitp+;AIX>Ujb7Rs zwu?4-+S^h~Z70<$KI`cz$Tpq6M^){vxU{mHfK)S?F7nj=>T%JUwE4bF7uWYvfzVHn zFI1d0-mWwR^u-}1M*opb1~6=!i#921?}ksolTEG$cR@^)aMcAf-`)=pXOpK8Md84C z1PT?C1z}zx`$H`${m24SA2hOWiJ4bT+c-s;khNyHv(`2@t;V62TIWQx+x%cr0sb~3 z#5)Zuj8PZKNrx0};-$$=a2}5Tyz2V&A<9)v9Y(9`7UYDr>yqP+gGZkTOCBr> z6A3MPdX!?1)LHT%^>~%Bvr?cQML<6^c-kb;oB6#NjU-W4kWbwugN^N_M1^~9!$jXf zqLjx)4!NrOCV_g#L6jl7fj(Z%%vnBPAnY6qM~qr`}#) zE{6V$s4^Ea5-lm$_xD06{895>nyBE2bzLioz7rx`!v@7O%Pc(+Z}bx!wUa(0=8f9U zIvYJSN979BEM>Ub4JEuFF`NfFOA&@N`(ILn(*?4Gi z`iEN8r!22HP)l@v1KXWx^SwxjQC4&|e}s)@NE(r)=C;~pv`YTHU1Z>Ptz_opt?$3@ zmHu1iudmy;?68i~|0@UCVw-qXaEF2%=I$`3r`q61&lgcFtlkr2=g-#qitFvRe_`k# zcj3Lt^r%r@&1mwm@0h~bZIcS_b%Ym%KhDMZ@T**W1)>V?;b)Jniz}eU6SAvi#w2$o zYxi%tIbi~GlN{d87(ekzyqX14?m)44F`0c^IsoK)sQp#CtF6K3edWn*_&;^;adN9S zjSVDCOfsZ~rU2GNY{H;4Me%4?2Tg=ZfBGqU2UW#EzgWFp<>rA`r52+NcBd~kOMP>_ zqSPK-%coRax4D4Lu#Jx%%2G;JzFm!9aP4Xjk|Rw>%k`@i?CY-08Z~!f<7_zA* zd>bHt;yz&jwz@R+3GC{bB+%Z78?SukMH|Bol+uBTandJY#&I09I7W_pqA*}4U}~O( zn2L~FY-f<0q#En@q~$A~uaPomgxMHrnJSlG0xsg%Ay&ICceLs-G~IBE{w1g(d~bD#qi+ zF@i-zimttztmrN&X9oHAU_`%W(82#WQ3+dv4=TKdSsS%cccyp=-al=~RYlZs zpB;OK^@=3>(~NzP)D5wq<}F-LJN-9h!oWDoFy)&=gu$hJ*O`TgXYkB~FaP#JYtPCr zGuo^Exx`A+`Mf=TvK&G^epmI%^Fj15m^2(-r%$lKp+BF%Q)<8w@d~5t>nD35@hhA1 z-&lJ*aiaCF@=5hhsT}r*^s|zNwFpq~AZl+9A zY=>fqYpcRf%HqRED%u&NMF1Ohm+vzGZ(2*McfB)+V9rFh;8jv}XM7}cZ0bJ>dc1Uy zi=m14FJ+J0_4;yjIUjbhZ8dm}gkE7w11tLC8c90JBF@?|P~^njRtfV1IK#ozv#dV= zP$-5tjuD_Q9{N>Y%sRA(rC5rrt@^G;^Q(HSZx9N7l)1SsQEfl}qlb*qe^-NHyZ@Ma ztj25KS?|7z0YzXa-HiJ4LOlQGw_^UTy3%}L~$a6ZAzK-nk*>{Z7a$I)D$6=!~8I*wC@A~w;>%xD* zhWLG8qSo9YDnSU;UM%);g(pNB*+Xd!AV(`CyFde#|ugH@ZN`%iEd^iEFpMW0) zTU{-Yj}3Jm?HLwg6f&Tk!w_bsSK)P1-0)m-l3uMh{DeN*bErckOfg)RrVk}ZSY66t zU0Y$eyw#^Gik12Vte;}s{#VQh_7jRUJ7d~>gC4w^t^eQOSg8FnA%=!%x9pu&K7wiB zN!(7_Omu>Y6jNU(iJr`RS;fH!H_;Cz1w9mz2SUqCB-0(ldKOB4&8(x`Ut;t80&Jp@ zM|SJ$S!T#p9iX4L%v1-=Zy&{Tf~k1tayovE2^VXO#?74Vbx3q>;&iMNrTXBShV14n z*9MHNU=3USn5V1!vvPRI$iB$%zWCJmk--dWe#^TijL_IY(c4c&DP;2$amrhejIZ8J zRhv!6YTISV;PEoVpzH4c_eSuw;{VeC1rHOgmSiI(dfc&YvrYQnaSSKw5q&RJ~gg+e>fp4K7Z z-fg@7SgAdux>+|~$uc~P;sGvI?%ILC&}*=P5%5|*espBQCwh5Px!s2jfZXivN9^O& zlyEQ6fl>jD60*|tOiQUOdsEJ9+-cH%AEOi{9JHqU z)&Hu?zZ0dqw<=|B@=C1y8)&#&_lO5O8s^XVsaW1@Swz){J&2So*k?1CljoJTzo$*@ zlAZLwVrJ#*B}D6+g|3N;PG-1UZ+UjO2uUmGx(Hozyj{sSczr&TpP+uo2_(nGC$vr< zJ=kLQ5HqO;$^C54iD^;PUCG2+Y^-1TK&k`N-}A7MwMTx~cY9OEef&;xPNG2b z=fkTh+dNsVLYZ5U)lQ=n`Q|rQTSe^J0n&H^%|s}IVy7E{Tg}MMrP8V9`Q(A zrrH%(hIGNbToV*o?iCHM{{Rk;<<2>mR>_Ui@xwlD6{7Aq(eS_d${tU@JH4s86$kMM zn1sLI4pTKPnMF$Q-?vlk^UK&r=+Rs#>XzHfdg1O6>{VnEQ6QZOVyX>ZXF?6tI&c+O&pR zLrtA|E#~&A`32Fd7<0KiLbSQ@{jfKXCBs!J-Bp2uhv&Y;;r5N-w@$wOf5>_lf2RLG z{(A>Iu(8c?bK00=PD43obEZ!@bd=19L53Tk*c>J5yB&RJNA5hms(MFq5(`+%6V*vT zZEt7dR>m)^%`BYD}$=9iRgMC}yUv$i;y+;0c8gin>3 zsDGzl^s=jcnie~}t2>DXm*yAIu>%Zu$VQd}alyW;!`t0gY#Lhk3lY(_4HFSajN6-L zASOn@97OqISLW6+vA1*6Q*JU9;@$&_DLX|M@SFs4z=4Ov7r`Fo@Za<=4hoQ{ppzl= zjkU{6Ol*c`hsS6M6@ISrO>#DslH32*q>APf7}=eI=izowX>0fR_fIf6U3?TWQ11)vwERt895b!~+95+b!@om zhbC35A7|(XZ!9a^6B9GB`vNh%c`P7^p??cnG}!@~zL4}msU*wc&h;W!rbIuq5A^}M zsJLCz!2v0qMGJRLqcv}eJy%x=L-eTExWi}b$MfYolU7Cim76}~9)A1lS3;RsiBamA zgYcLTTlhgU!GR`!_A3{WTi2OP4V|qwly^-+2?OU_j@n=E1{pK659(%Fuym_cAKc7# zKb)4a)pS~R=Y~V7ziZ3~PzRs_bm1?tAmH)iF( zXtJ0D(h=inm2axbN!1%#hWm^EWA8rI^@y`FD{ zNz{aCTRjlJneojvqqhy07krzukL;NAzZ*_zU1saoy^cZ|ib7j>rbaMUA0=LOO1pP= z?Js<~I}I;!7!OwitsM0whl%xs5^3r3uj1KE&MSK7c>5`nh{x$t7;o%&B;wHmv`xynRZYFqxk>(Y z@pHsL7x3VB%cKSX4OPE$-apVJR~_FPoov%{;X3wxY@nKabCZFcm|_Z7LaKF zeCvQ>$F=WMTN5dUB}uT}6Qf<1->JVqPyHz5KPrQ5OEwS#$`+am`-L!dPpJWQT3+DP z$9V#xkCiw_aaFFV#ng;qX3e)d1o(1ofN-l2Vi!=~dc3TR7;Hz1vig*I!fW(CX2e)N zI_Rh@@a`K_-cmhj_A6>b7Eo`18v)Q z1^Bc=B#kq{Rk&Mhgl)YZ>Uz{shXp)8gH-_|Otdu(1-Utd3%8Efo@4&+)qZr}tCqGl z1}fr?K`VLE|L_##d6qwkBTr38^PTT*Ze|9yt)DGd@@`!bKD%glCgte;S1swEdOLv* zhw+T7Do;M6I5Cqz(O5^|b3^>M&>+Cf>A%hiuhP^JZEm3=VWCV-wh^E8(g1B8iJO!X z++$DuWYl45*vXQEW}8A-m3J;`Fby=M-pWDVANZwqeBs34fkr`!*#=+cDWH-EazKIK zk^pQLq2B6&D^-2dkiZhhcJ?VaehW( z_^2q`xBOvvlW?*td}Z2q_io3+2e3Wc?*JYeB*=MoA+xq-v%_${C{O^+lL_>LW({n* z)T{p?o)Y1JNa>Uw)}RBi@P!UIQv~UW;!PW9V&mosP{B44B2U{6HJ?{#7)X0Ga*<&! z#~6@<^vzNu$a10Zh!n-pY=R6~1G9lxBryINp;1dL(u? zPU5ss-EMSzC$~U^L*eW`(#qC0T@H66!;doNHZYCfHh)XgXL*lLe9-!QCN zVf6>``2|hKA^Q0vP3~|p3AQi_>Y)~#>`O&kCgWxmL!766cVwb<0s$a2mkIvxI&DyL zQDLurO6n_m9s~~0y__IiL3FeF8B$C!Ic;9;3gYNj0K{RoYtzO$lD)CLj9{(k zUab~-Ky}v{@RKS+(^jFcQM>S0$JuuaP_lTp=xWgRUUUflN`OX+Jo$h+wioCt`&VLI zQtOj=#O2KBT_0PA9CEkiXTY=kJ$>!3Kb{&>P>vyq@B1d9xE|2M#Ltjd_jtx zs)iVm0@(BB0p8W~5V>Z>UNu+W1&364V8$Jr)S;#IMkG{kLaC&g^`Q)ubD>%}rc9Ki zYGv0mB(q|Zb+&256DSCqJR8s1(qN)a_&3IJa5nufJ}Rv4cl)UCd^{OL!`^t#?qP*~ zH9OGLP7zb14aVzl6P{A<3oEga@N&%G>n!~$2=Z6O%^0%iX*(qbJEH~MV;&_PRU`$h7OdrJ-E4=A0B9e-mEPzouNJ{1F5pQOsj1gc8c;LdEI%) zQaMvW0!nilO%$RHW)x~*o}Xc_JX*B?DA!yOPI}ProRNb0BVYw)oq( zb%1lutwyK;+ri_Ruf-!lTct>QT;o9O3Rt0=`Hn!wfy)8HmFuz@a2WP`DI9Wzrq_I5q=>nYK)qkHwRXeIAX?n<6Oxn5g4_m$9zvVS(|3iyr=!@DcoUs}P0HjPt za<88SWXUVg`=S&qbhY4i7Lja|{cv%?VW%cG!HyIc+qlL!r5$fa@>E+JcLk~`NofIp zo$Z+7(@EJoqa-uFy(+`ZVhV#H7#a0xgEYsodght=|tP4>*c19 ziiH$Enb+)^!PIPU10GZQeLbrJ4b-C9S<0a`wxB-O6Ig|=;tk&vbmr&Q55c`~k(GqX zHYe=42A099h&UdqHTt`p2fIQt--P@&U}kuGzm-1<(c9D;FdXmI6IQ`PTQ@uIDPDKm z0s>N%KtL+C*=%25c<$O2+;ebdZBHAn&@)goaZ2}`=N!h?M1bZieBN}~^QMyglZ5Ia z{RCe`C+x(>`2(cp_kJEoF=t?M3{t?UJCxid!h+&YUbpfpMI5 zJfAZb!1)jWz|wqIh;avubv*fYsrjB+;W*~ z*;-Gl0p)_FJ=lNLHL|zToNe@{Xo1VWsC(<-spM*vy35?FSO0<5g*`lMjy8OFvlDxOuJV@QQUy#fS(`ONfn`I@9{5h^fT=xAQmRmaT^2s+t3f(pH6K zW(Nu(VJK1OVe}u)yZ4C#lHzO5R&a2sn>%vScMf%AFzwNe>jSQ2n|9Y5PIS^bUN?Ma z0G@#*y$Vx*6_L}U^`8&`V!7+y`xgg(?3GDw3se3Uv?D3{+}Jb=NVfvQ?%;6hU7!#m zMNds_OSt2Y@q(;?Eb&ByLsjiHi+_;0KIKYRBK1Nv z8Vs4K3cC?^>hT@)Q-&aoN$Dtgc#f%@1Hk-Et4OXe{dU|XKWt%KX3|l1a>zdBpcZ@= zNE0X?n-UA)pofO?%1@EQ0!fHM%EtUU(a)N`>C}mekcnIvr_Z7W1bqq!Q@|b_tqwl& z5$fNCzQ%BuWPH}uvj;LncNtK&KlG7Gb?&Q`4NmU(jaO&jkyOfzlK`6THesa`4#@}|i zp^hDZFIpFK<>7`gEoJZ#xmQ!DuMu_2bBNNJ`^DD-pG)IQi>^toyH)V??gV~ANsKlc zZt79Kh_5OcW;v<3PHFE|gv}2PZkhVpUQli0kmk$IQjdj$>Fw1*xla%pF0rTY@fS$N zmNV57bA!H8hg)kZ14HE0i$KUegg*$m2==r;yo)_1`LV=2?`7v7wNK!8Tlm-?yaz}l zXK!{;-NEJ8`#Rr8bk0Tl8^_c&{4KTW2k-Ja&j=>6N z)9T}AoLiqXWjY3%8QZx>YmfHBOn!Yuw2p7L|3;19Gx!nbk9&uvVB6&_; z_6s2a$Bq1Uo&d=K4P|rcJc-LnFx_@a=s$Pik;{$lD<#guPGb44c zg(?6m6<})w-}9pZ z(r|Irs-0?-BIW{2=cUccZlC_~g-psP4BT^VY$Ess=;r#eh(2{!m$XTIXD&7*Sud4` ztI?6lOV49$+hX>q1%pZI{mc!zXzX+=AN3he>McGC;5zaT64bPt<{^u?-I{q@Sv7;1 zxOVt8KM}CS46I{z*8QRm4vTmPqS2H~_$?r+WAe*dV4G(Pn2M zsatdbd1*_OV)&D_EhyMNm&cV^CdGG-w}?h7S#_eBtfGKJ%mJ&U4RHzWfI_hjAbC3} zaU5RhQe2#5aTfdSVC8fsS4P5a4CaSMoom!;TCuuMW_2XV`CNBAg@g?Azg_ zdG^QMDZRbS9!FbPc9x_xLTCXu7Bou+DUhMv8>-~tDl`v>g*o-n;mHLNi;N)ikuhRl z03JO`eW(mYw$j`)J`27V1v1=%T1w17XfN6Y zEk>>DP}NEe>(ii3X7G;Vk9bdr__Vo_MzHvW68*Lc_T8U%J0pDRlujAGziM^uGs^tR z!Hd$*>SDt+{Bx45P|yF>DbYa4+=c5wJNH0F8tu*gr2nI4mh{Ua;)d%o`6j2pEyzMZ z+PYUWnl-o&bh3_tTDCXsk2vOVOH}fq1gHyAJJ!_GlQ&V~Fjh*R_ztdH=A2VKbv1hr?w>Emf@y`P`9+rLJ)DT+nHt-*32rsFvRm(N zyR{noklgp#5r%QZMecIbU1vv_W<-|WzFZ8wj|0y4!THz&OiB*+HQKS3@F-d0+qk&- zxIJc%95aG!>x?Jh*?V`}xr_DW)&tn8fDh{mK(jv@{@?Y@YY(U^`68Hdvr|{w<=chuZ!ACIzI0zi>G&LBz~=n zX1MYP`kY>8kw++paXrLaFC3t#ttTcm%NR%x4t4p>o&~3VPpcTL_-N;ccipA9 zwu#xd<1fH#oEjgPYS3%zlkUY=>oBFqNk$s z+d>qskpemRAYlt`thCC2*(!hI`q=VS_9Qtk!6HUsOp8aa+5iMra78KlTT=ITk1yG| zpNX~?!G}bM>9w=IsPRg|mGDRD0+#3Crr2LX{el^RmshHLdU%u(#=?N zb))_5a&M=~7Mb$j0vA!$?<@DMCW@SMvmQJM8~jx0*}*~b3{PEx_zI9dB$kot-{=C6 z&;LwjeT@r}ZM2iDsjd!*MO~%_3hZBt(B)}8Btk~~Hd3d)P?zB<EZ!TQS(PlGvn1qi|9RQOyNr{?~oU(O9ZFONaDDxi|;Kr%ZE~vE`ui{Dnm5@1LtNk zzXPc8v4ZLD@~0>1*QOkO^~xy#EuN6A2xz#Kuyd7He>T{AgtZ*dag$IVn9fIgf0p_! zSv4R`%Dt0jX=qONS3tk(02(@H+!9HamZNft6}D>frCTc*2~E=-zsgaBz%o+Fb8vK= z`a*j4)EVd3DUDkJPyea27{n)%-hbky7})U5fJ6#+ML~WPs(|j<%}xZx8k0`_2?5Ow zrW!yd(+vMWR~3N6R}E4Kt+oNkm_Cy7y^bRrRGade4COj zZ4z9p2#r@Ggw~8w_nv@070eN#p70n0gC3haOTm(aiCBI^(}JfHDFc^-8Ewu)kH*gv z6O-5IQ&+Ypx9~ZO++UAU+R=j+SfyYsK>itd(awNMsst?=JS349PUmJe7sfO}0{_ zN@Z2Ho8|@9f_;)@$!*N!5MXhzFZh2KhpyEBBMJ;k$;xS1p9F0({?CALQP>RZtqV@I z_5unkN>0WVcSa1~x;Gy3pZ57}^}zS0&!n5gaK?Zobn;-%L(KmhZ<{vp@)vosT*TR_r%mZhvj6w}{J`49nOD(^T{dXV$JoM?-I}#2V z_K)YSkm_#Lx6|Lzl7=!%a}yks5x(N&bT`Gc+f|AV^|za>kf+FRdowMDce_t#1?`Xn z*3C1mt60vqe8sK^Jul$I78p*dns??u^d4u_I%c*3*M*{$-OR~@r|uqcR&SA;@^nrh zG>Fi$kRSyhzzd|%;g6gcB+DR`?q26%h}EQ<#S)1IVC@VsfUCo3kbM}xa#bLHLF9>G z!)m?VGIWC;A={tnV9OFi9pgo;1jv<~)5+O8SC-Ay+sCvi_Hv}6EtgXZUtLfxxzRA? zq3?UPEfoGC#LTwFDSq_na(|%*od-PaktbYjVwrV#DKn!EmjJafQ)O+?4-(+rS5^HbOjem)qJ~{* zdp3xQ{-N|JLP5SI@s!Hb_oz3;+U#QBnSKrf%pzZK#tYIF=5A1f`*p{cI%5t!>gSX> zuj~fY>FW#3&`*bX+Nab`>{Bgm!%e{>$Gn|@-go3)55NfLD!HQQS5rOq$$a+f9d<3n zPQ=KJi&(}%7pCc*xA-R^UA9X>=?JUQq>7_z63>4s{D*YhnUGRv@$JL4a~7Wg2l>-l z0?|HlCH+m|cN8c-`56MGMJq2GOMNb&dnc&=^2;2v``=KrNxWEldBB)MJl@w7zj)m@~;?csyrEx2&C|y(R@AS zW;Pgj)PFu(c|Rd=oHrBA^?)R&lZ%k-o~?|UN?f!ec|n}v-yjkz3V{Lj^qT``;US5d zaFsnfBRV#^B?b55G6DDkC=j(m(gvHD*w9yV!B2Z{Tve&Y?|1b~2G<}xJ!xXUyFCJw zZ7zWi4;mThc7P7U+dzK4<)kunU6kzL$pqn)VJuU&bD_hdh@p^dY+~mQnjHTIeU-4X zB6Six>JJylHSuO_y*xmUm?ly3RaB1j#(w}r2lKyg{H1dW(4$NpfS6$^U?# z4x2hGgzVrAQl}_5@&r9qB)AsLllh@aR|~(Bj|Faq0`ZHyDCy`V4GWtlXuLq?>(((t zb$CJIGSPPT?;@~q_vL5_mCmM7xhPT7N%?4XqKwe*h#)X}7PAq(AwrK{r8O0% zloi8HYp`F&qP7CA*wlG|AI-CPu?WeaKl;QQx zfB}?tD)8jGkpSZ9BX&4;vzM5P18?kDwU`q)Nuni=~UQo1in?X_wW z;O^w5`Tw7T5|=7?@Go#sS^^GA#Y5G06EWzt(F=snpZC0YKvp&53ek^bF3uN~v#~8Xmlg073A6GYxoxCt z6GiT*EpLLqjLJx>;g9Ag-rRRi^amP+L20v9M*fZHX)WugG7{N4HMZHuUO{{UqKcd? z0Tg)=Jj%}prTt=fL6V6tfzooV=3FSD6On7U z=cf6E9w9u&-zWecm0?MTXzfl}jJBD+=6QP6Ca)YI9-FMSZZCYH8z zzvF_iuMk|mS z9H#_HHpdiD8X}s!mD9r`iP_q3l7>6m$c(Z5fHsnS_Y|Qa!19_DV3mx16`)O4FG^-B zYgJZ)_LxY&|LGi~e8m-{>*aa9g`1EX@1v1pIpv(Vx*_*SAzHJHNBMESx1{r=?0*Eu zDm8;twY#%PL#QMC4cV@?T7a;s%e1Fh=+ zETyCjR&z;Ij4wX=zt4*o%2BVzfRE}w#!r`%G8Fry?5nLZfAA3uk!R#y4`i;K)61v$ zfh0b)QO(+c%9M|@lW7?#qT{(Opxb>7@eW6M=|D|&^zUuEN0y7YHNR1VKOvVVc%^6c z)AxJ%$ez(`Xk(C^iX!q~r0LlNa-`oXj5qbO+$URZoZS*RefD02#{STqtv`B3YPig& zF?Lb)ctJzHn8uzhmvcJp_U}Y!Zx8K_-`}aw2lv4y4!gMuPM>F%x%>1+5;j^v4IdOj zvq0wN7Li+a@ec8N{zFf}=`vZYc}oQ$i-atsfYt<~&0d0IMQc4ceKe!589?NVhN2EZWWNR-IDwG(fMtj`!9B+}&j*u*9DuP==N zWl}~ysr07y8;S=Qj&b2`FHcd{t?U;TfwgISll*r8B{5jk|MY^jI!+)BWV)1RHW*Y5 zuxSJiM7IzQfwXFJa3)Zy&U=tV$2kkGfVD5VT-dtVA%(~>g$@XwgE5%a~k9pt_HhEZKZO5Ule%_OGO#!`w_Mrj)F{}`z1Fv-w2n1#JOqBE=I+#^(>t? zqAgLH<-;cA9veX|+yMAjp6pxK18UfHlgT9H7uxOGo@^Hua1`V#mN?PtpBjk5y9tNr zd+nKkmXPVo(A-TpiBoJ<+V%8z03a!6>>8g{+a>4jv?N3kwn#&Vp;H)*`?}{~2Ag~f zfS-Q)ktVq({X^0bwLN{}PN{u^z56}J_eUFLc-3@rg6rif_Jtk@p-8_r&^WT^=8+4k z39SLgN!`L_qt^T^I%xuyWdA~N*$JT5Uop8|u6#GzN0_D>*eK$dV4owoODPFxbid6s zFw`#RIx!qBz9kmJ=(*bs=YeJVQS_8E^H`5>L7SAw@XOkot z56HDT7=y=*+RCeyG*l3u6U6)39&?IldGYdapGf#E)O*#nl*Ltm2BD}y-5BnHLHR~t z(gc$qZs5R%wQGL}=Z#ghjeeBq!__ymDw6ATW`Fix(y)YIjKuFITXG;>hn2-I=)40$ z2jZ8e4q;gU#NwN=o7d>Ls+TJIUYdtLk8SsTq%u_!xKo7&4kJp>+wC>s!lVG){FsDy zaAV6mq$_$qod0pGcGjg%UGdfODf{=h!N+#;LWED+Gj;48=Z2cUdiYIsaaP8`hgQblu?(dqSn|MA8`2u1P8znY z;pgB|^*_RnLNiNJamIC7y$=J936y^mIrf4iUCT(-m4JbX8~*r2d!V-J{SuH#6YHvq zq`j+uVS#}fnhQZ5W8==B&Vd@t^1z(+;-8xsn^nw>&m_&6fuD#Y3bM0EvsPyaD!Q|*FJU8NbGxsbTE7g@pT5@4 zXK2qecf;qNtt=wO5Vr2)9)r*VpR}3%H19Q#(SHt6P;Kk2KZO{Ou zggvSn4L%mMvW0r93Oo7?Ah50cMg&(OQNl?}E+IdxR-tES9N5xWHm1H*hxoCX&I6BB z&N_e!#9;N`HWn|mp8rbU+Bh}}D$HE@xp)DPf({BH%3gN+7r!KKwF}2)4&{!HrxdOs zeJqxg>UFr#+FI4gn3z(hKkR)_fG>&N+FHHAyquB_?%#5-Rm0YJrg3CqHO(ufFKsO0 z0K1V+sT62o1g!Uu@Cl!U3($fC&BxuZsELq1Ncp>UP+bl&8ZcsH|0<3b;8@he_!Fa( zqe(aD0G|)s^cCbuR6x8t|BhxS2$(s$)YnEJ;9ZBVvUi?t*;Od2U9|nXDWp?4Om9Y; zzD;}Io1^GxunoUY#OGAvy%f5Wg2d(b@n#AMZ+#bu^+I&+QgChYrddGa>hy)4_Bs-( z{Kbi2Molm6Zqndx^yt5#yaqEtgw_hbn;uKW)cir!6r$t58j^K>(R{@`IDp=O&HkXJ z?kjOna@@o|dLu1PLPKm3sBKjL@Wr-sCm_pII-SoHHC+T%=Sc-2rncKo0^#W;O!O=$ zOpXgWYAkgQ_aaeDLI|BP723P2Y7b~`(Zt>t?KhhyjiVH8xSR}S zC_qf?7xW!rdudI-9o&`0ob;T(z^7s3BH^7)QnqMXsdQuF`*^Amb^~Me?H6&ppO(DH z&^CdzB;Ca69t9UPb+RY-moGM7whcM7IxInfObi`EZF@7?{ z**Ujg;_|M_LHgwB>r820Ws>dymZ=}SiSUh&o!KP4RL@iW7eW@lzMI2K`nUpe{7GuHo z0zha!)4M;?^uSe%#1_}55|5bjtK6iBwi)HMI=MEj1?Y`azqS5S`e}Byq5j0dM*8A6 z6)1VA$^NUbbqr{-*0idjAq`qv46{C8==Tl%vxx}Wh%Wb?<`~om9FmrixmJ0(Ho0H= zxeyZ~Wp0jXIW*dpUioP!`$-z}C!^CBdN9@VpL|0bfTygp{Wg0cKiFKRpH_0)Z5vH3 z1gPxD04h7~!PDxzFZ1}m>f@|X7gK2@N|uGJB^d63na(E@BGuCFX3+AogSEUe($UaL zlb}8b*wiaCP($}~P00aSM68hN<2_aoIXTffd>|{)$;fy> zw0B~Oy2OX9LKB9wa{EL&_hjBG{9^W$03=V>MltH2uCFctIeD)CyM?<`PHPlI`rdV( zK32?G>?w>nIF7u%vr-27_G|2rx7#0Uq9>-_*41kDjc{`3&-+n!GO7=H22I~sm(Gj> zUS%zr)>t(?!^|Z$zzLxxj~7U5RgE!vA2-L2XLx!c{Ml*WKJ^_6o(N7f z(9h9$dQ}wgQ}jp1bS@#y5b5Y23@`_|$!?Oz&uiueB(AR+K-aqHB$$5el`!q|0J5}= z-l_d{?D;mr&TyXp6O>P*a7Kar*3ETyF41A`KG4dc+Is2Fq=7xP-$%}gP%`Io#fAIa z?q}L--ElMMUC^B3!Akh3c(~Yas9dwVshEMfnB}^yFxS<)d^6S0KV3S*)8XuA2mRft zT_}n9J7}8BZM5Bw!j~!e-YEwB^m#-aiMbT;>eH^!i;CZzqpjJNa$NA9zwEMM1J8>k z6S(sE9T9=@asT~}c+A3!?{Jl`&CAMGc@kECZU)yrN{w2f#*5dPfrr8dbs4Q1?~F#a zD0~I+@kIrS!K0BV*)x+?05*&ZLM_tajWq4p%2m?eX=HS?o=~xm53ENvq|VEiyj1>v zr0$~iEmT!^2GEZU2DY|G?;ND(>Vv|7Hcen(w1N55{!!>Mv`76AR6J_Cu!qtaza#^( z3tD+3nYudmhH4m_N2RYzomjbAPvTyad$O4V^n=(OwI{@SARVJ{oz$ts=JVBRu1dgV zZsA%Jo-wK=Nnz2`T+A|gc(kP9+eTQ-vv;f z#x@CH%U*9+PuX}y(3A$v8;q>~nJhQ`-^`n$FQ%RrN@=ozm3zmiuU|AXO2r!gKbitb zci5H(s0yL*R!cy^Zkhyj7{uDikr%GGb)J7Hgj?(ll=^vE?V{?JWr#_s1--a-nE;r` zni+I~(@|mH93y0t^&k#f<|JsQ3GA&atVdUcABHW%gO)ou7Gts(%-=>vf(A>;VZPbJc^QXA~(6j>@Jf@vx94n**_-s{VnkOIaQ zu;@LQha9m;w@sCra4=gcwnzd;$Lfa;sq1V6svHxJA6W5v1XxNSH-V9zH9M(B@+^_#&-=8ZfGCe*^5>Uo=zksqF;LL zwz#*uSAgK}+VQ1UQe$XaE!^j;oyq5J*I!Y$kr#4^wfi5Kda0<1efI5T)ZF_up|JP+ zj(f_>nS;G|dgLXd$tO2^K{hZhv-Up2tua;Mxe|co2lgnU1(2f0efFH|9JK~>hf`w1 z_>zr{iJNM=u3H-_%G#~0cPQ&_Ce-n6LZwNv&v^8hSBjcb@la;+tLU81yFH=lXF@do z&1aUk-Ge$MN&K}d?LOy*G;hAi&IVgWchGWu>@!Bskg*Lq-$sSlD-^O}e`UEkc1Yvq zKe<8b3T4@OXT)Qniq)AKxkcW?Zuy$Av!s|NVkc7lb2rlKpO_8u^Xs^4tTS3&F0I8z z5^)Px^^CFLZ>a@5EG}_RUoqkXpaOEbR;*?9DYq1N5O6 zKXxbID0oo|43Jnm(suQ~UU3wps!(htt=1VcTT0!loML3q$%!&08I7`Tt^-KQd)q8} zX;))^uWG0E(N0R+WGCH~*T2$6epmVWEnV>hc{?IN*3d#33GDMxgld2x2e_orf&%T< zG>aYZ5uoD0Lgvsgv)4Jt(QgI*Sm7y1Dxq1r==qn1Bz;E*zu=Cp7LVLRf8|>VSTg1P zu_KddZ#=nc)X=Y*X6NQ_f>APiM%;PxJ8VVUYz`aTDnmvAEudn1lKRl|x_B3?-8H^q7p-nGs@=NS!)Pll#<* zwGF<&4gWYqO7zny6)m;D-ag7qTo9_hoiQwB94Az(c#I^3P!2li^BkW__r|@uBj3v~ z=k*By(*W`&XKp{=oY*k&jCg8l!o0}1pP);Abl2&r@@ExZ-wJ==SJH0Au9Ev+URRIB z{)SW`f6E9JPsGHiqCM1RF0HGYkc6`xs0f>T+gvH5yIzy#Z~XGwBpJ58qJ{ZVOdZ@E zKGh}?2PGzJ{~!z{#KfIl)|($9x{R8DL~vL0vcDH1)AcZxU2US&WjuxY#dh=ki`I)% zZCqs@(t89u&vRmnvZI^xogX~s{+2$!i zz6AJ?XpD5`AirgmU-p$bD9ZDEzPt8AKfU8!Yl@2u7kmmM1gk8~18yF9=P7$_9;}m< z&TF#u{Ky0pt1hPdPY1vh6Quy4PFFk~%ALXln@6Z`AB~=9ev3=%F!J287Pi`Y1q!ac z$OOEnFPUYWvm=d61)=3oT~Zrq0A@<@zV(qdBkm06-r^j3(=sC|X#PtQ5;kv(HG`Q1 zYkb8Qf;=GcYa2LLX0DC%M`(et6aKsPjX#yYb~6u`-PwwqZt;DYc#~-ZI@e1d{+OLR zdT3AbVMl9e&S47x6`=>1lxXKc5*G*E5(8R9tT&Ua0XINh*kV3{!2d}yiiSPL4!ky@ zkVdRfhJM_4=AB^x)h~C0U0a0_2r@ zge99}_d2PltQ#QUL`snyp}Vau6h$Hzw{t)*0Z`+61AI#ZZyUb_Ie~&GK%0}UfrHcr z8+p~^BlI4b-+TZdGX{&qkaH#bP`i|S_|^c%wW=9!P-vGswLpG z^LaPFc5_`swRlPkVWl3W*>Epr3hqF&ImdwhZy6=KXObH!`tSpCD{p{z5H4XG33?4g z7XJq967IJMJv1do+sn+F%5)0{-D*Y62@?Sx8>8!$*mR#A8L`UL|BmJYo5a68u$pM< z-%TP@);%P4U*V9>;1NfDR7MUK*d^Qs_V4+!B1!%`51bWqS;47#er0H`br;5aTdLkI zGPjoW&1h;2F*0VZN-^2k5Wi{7`G0Z^^3OaiZ6Y%-dWN82^;M^im-<^{LS=TyZ@RHL zCd2d@|E0=}k12=w_0;g6aYMUL?4>r~Q8V zZgZJvq%JTHA{R};=67l@XD4sZXz_jE%spv{i?pj@5xO$1edYO|ogdW2+OX7|m`B8c zjlvjwzzLWHpCt}Dhgp#Vv@(ok^SWFqQQ{g#8W*Ia;bf@p$!n#t>fK7o3L)b_;T?d? zkGA$t*l-un`>i&A0k$;nxpBB3QB1<3#yIN1sVV>rt?MZ7Qn>K-xb~)))g;jW_c*ff zj7#be#UlY?NRb_Fj#hefpYaw71)_S~Tjl~-xblN?4)mf08;$UGBpqJa#GJHNMr!H| z@~!HvLPDfXlx~Gw#GOeMh3Y|z#w-l52{wbD+d(Z|K)JfTmh9^<%{IqTGkGT0E1`tU z_+2V%CmD_f5h=4)8rHFOmV`>{d?s^@8lxN3-rV(aYq@*#kk0jm084v>3)a|E$+b(* zm}iunG{ig)R#r_L^8q2Oao7=vNiaP@loXdhaV@GWr?~lb#3WEU8EMO^fjhoquD87d z5Y3IGhw(H&tc$xZ7({if*^^o0Sq}!;nuYP z-2;Q?8)>LOl=xZy#n=_!e1rcE@?cm81vj_O^^hTKq!KA=r*erQz85e4j8 ziLE2F+G!W5PhVU@Ml~xvt%Rn3P6S-lqrZx{afkd=y_^I378g{$l{ky5`IXpklr@wD z@~~!kv33C7l(YdlDyR?s?Vhig$~P$=7YsC zy!$LBn32;VfH?luB8;Zi@=nAyZ?4{6);W`V726VF+G8++Ma&rU-PhOupsMa%N5!7g z0e%+%+&Ss{<`%S05#MjNwzX~qrPge2D$UVo0PFN^OHxY8%`xirrL}d8!1s(L(FQKnaF zof<-9OD3U9h4I4oe7@Mirghk|Eg7m{an#r(9^u#9)z${}+YM8^U@R~Wid~ei=4?)L zw1xK*Ynu*TfLPzn93PF6h?b*tUf1RWH=SU9Yvv$(iFkyjR<|Ldp7Oma{&BQT}$+E&x50YHY6{=U@;1PhwKs^CNr+^G87KlnUXg3#^{f=^|skLSOM7f00X+ zM*j`8h)`TMv*}hI*Ch(_p;dL2;Z}B6G@M%(c6tZ0@;M~bBo-$mK3$R4 zwQL?n8foypi9}hROEX3b=bO+1r(3iF5rKd`cPSJ7t1+H=1nz@oD{rrawRCoYYrHZ2 zF^oFGzhbmo+rq&&Fe=VlsAgY;Q;w!Y zdf#Fl##pCI2Vc2GlJTCKTPEEAa1^lZQebE49&KH#&=3kv%K7o_?1O=>`Axw`FdsTy z%k*iQjiWnKRTI_15E&9V1+5kof^?Tpw=eD3vgx=v-LqEZJ~{O38I$rT#fpu!OKq|GCwo zjX$Hjb2@859Sw*V)h8eDw^q(hrTTd)3!>~uPA6dxZL|$9OaQw>%HOoZi(8}|jobft z0%frw!5V5fT%e&(Jobcz)HxvJ6}>F|UBmgEiOlw4RNt89hbu$mshVQ-9M68lR7@%cGgIm0x!wFa0s3z;gR~hDRcKxs@x}6N4 zcC4~sE$!81UOn=YJwX6bd|;UL)ld1gQ)9J!%q_X6DGUpRal1K?SFJq^XmPG@q{RU# zowsp6#!&CFRje}DZVAyBsPR`Wd8H<4{Dc9u*rGNCv%yCn>$SAqb{ zPvIc%E6EexQX#^fuGqiBcr#w97At*&nB5zL%7Zjd<-wS)62euHOf(<) z@?WuSzecrJi$6t^b1)!&^Pob3^SFYseFP#w=hft(~y@axKXS zI+bjTHq92BoJ{sif&vk_?*N?7yhkeUdK$*K;)y)2iGFJeHCnT}*;q0ON+FBT7)2=Xrs$K89jH#}F+u-dn_%ffLuZh)x*x@{DOWXZ#^}i!Y~v z#Jw%E*cw`i-_Od_C^bx3U2fV}bKjYpG)9=R3e@PR0#!Vdn`~_)By-oB+M(iu;>@rx z?4rdGw_e>fCaIsCW<9mPRv{FiJWfa^RFP1qA98)X?akep-Wys5t!=_3mEix2sB`gW zx{v?<4z`(%Z4TQUYIDdT=R;9wo3oNbsgQG$O63$Phix|Il+j5C8M)%RIvA-`Von(; zOS-7Y9Fn3MDd+9?z3$)RzVAN)58uz{^M1cx&nFF-Qi%aZg((#>JdBQkqEfZKkk01IZre33+Rp%<}3>(S(@OznSP}GLW zX0tSTg>U8qrR-AhLA1O=lG$__CGK?ii_D=9yJD(z=76rob*7Im%Y5K4tBW-6$&^(@ zSKLN-bf@sB(NWZo*Z-6=z>ngA(gvnxN9v+_zZ>j5bcZ@nw*Iul?(CAa@a~*ZC#G`m zZ1F!tlxmw>NijRV;eL26MLOyawH?)uQ(u(HfNa^glgCqOpMah`22rt5q~rgVw$~df zM}vpZasHr?HIninUYxI5R22O$H(?|dt|Q3I_5&VVN|_y zg}(wS*F8hu>ft!^fkX-b42+* z`|#5J@(t(nrPJ{rHqLJm0MeTZ1HV1@!P$Rr`qx}F#1iep~WKe@t) z*79_?)Iuw#XLTq?z!tuK|mg+*PqI~nibVbf*z}n07^M={4!}5 zRX_E7l9RTkb)?+o>t$C>R3Z+*WYV1U1*Jh`R#iau%h;jHb{|US#Fqcu;~sT7)87u7 zJiXb}>ClQ>2VOZR_`uU;&bBGpxwd z+rxc>v~PcN3ssfhD+8ql>3C59fK%xaj^(fScg)cpW{|Z%s6AVCpQ#LP>EU!%`3_PE zm$g^R@)b|htj!kxfe@V9G$?~U<5H z0^YM17xwDtmJTI>60OYlNY@G)sOs-;3|J%%Mapi2WA;?_yGI$<5M*6g$@bHU#!>=8kuGG6!=BGxNac3)h%7lpVp$|qvH7! zW{<@RfEw zfkKAc!<1jqtOReTn%jJw4}}X(kC<8ak3X_4Cts3_iO{HN>B9v3=4@;hp6qxG)UdZ% zST}=4veHI25zY?q0&mlkK5P^=b=CU$3^<3~TawyWt}lP-!@&JQhpSyPx)PVHht+-I zOaC0wE4pPO?}AEMxRW<$D!(@O9hG-de}6JuWaOX8Ky9P`YguPuDS_CY7pPiV*INnh zzg?H8)y2b`;t(|)HnRUD>*%slunXb?=9l8p3+Nbrq1xHJKaYRb40^~Qp})Jc8$h@Q zKBi#^a|Ty#*pIwX%gB!h*t-<*J01L~EZEF0)gDZW+s!dhIPhcPEs#2&3kg-pE!N3FVBg$qCHZzAV&PlqV z9Idogl5W~xs=~b5QSw;L{kuqfreu0!7PHAJ0CUSwxBbpwE%DRyOvPZ15Ek0-8~WAX z&9|v3?YF9yV_RDZy0_PaJL6}0dnDo}t#3Cv3Z&EP^k2xTaD?5SdhA1<2E9Np+WeZdG4__Yi@DNUg?@B@#tr(@=^qqmWqY;- z;V$Hd>q3;zXMq-(VN3u_O75QDV~KlsOUzZpxR^5g7nf+ zT4vCI=-1Sy|CyXGGM)O_oLM(62D?q>}ILT`lD(#$rMI+a8GP? z$w$kA)>CF9BVHGQ+^seErI7*}=w~Ru@ZbHxKgoC)=w~=ujpPm*K_|US?)_C~4;(Lp z`a|O_luUX$S=@95WF7^bJT8uYP0Vx@ZxLMaxZ?v~XHwkyugmET)>L)E@2iaPO;?zv z5WQ&HkS{>1)^Ki98(3(HTzolr%Kwye@l$$HB`ni$cY;fh-i^(3HG<7BoSxakTYt9! zqp(Eec9vXXcff)>>k5%b^f1zlYb5vtW3R*&_inQ44%X)4Xe%o&_mO;Q?zov7yyUH_7nBjF6KmEVqaS(%JLBdHJTToGwQ})p z9Zx_xn@!qmc7Op=_E8uv+E8r2j=8_OjLM(Gwoum9hnQhDLq_M6oZ^;Pr2E9?+`G1swu|TI#l5 zlcBfDkH+F0O%KB-jm-iXg9l5-Y24iwiFG$?T&IX@>tB9ylHv85)NA5uS;a2uZdF9t zM)suH(CM2(e47*Y{W70zZvhx1z~vE7vXyTuE&n&g`{YDWjSN15Zdm$vf`D%H26d#Y zls~_-i>9nc#X~ zKesdq^Ss}3j)c3+zaUrKE*C`vPMFwi1&OtF__J?>!8W_tX!?B-EMMkgvNSgS*;&S&h@tIKzbKq<8TScV1G zyhJY8KI&JBHP|x+Glj60Cx-7CsQ$J8VpC50TRt$(B0!ivzp|bp4+Lo2qd$Jl?AcRl z!2ERPkJ7C>tnUjgMWen14nRu#hkVt&01&@}BF5G~Yes1kQ(H;?*b%e@*g_=raAI5; zz1S<*Xu*;4e>C(8+g2_QnjH#jL|IR~H5gD~`rK?rEA5P}?rv=(8l3?V5Eb_qbfRfw z;f=&2=JdiWb}sX=qJzRA=VA5cwKb)p>+7rD6;;o!0AA8}9cdgR8SMy zd@Bnmm>-VVG<`10o|aFcRG2<>-U>?UA(0T@;=R%Y?B_pQ*5u604n;4aW_JN+671_L zd^qmchDHme1|s*W`WQY`X=`?i2&e{s3papCS^pNcR8&V+gc0yQa>vP)q*HegG+vbEOO6q(CE zcK}4vYG`AzH;GjqnXT#}qkM`8zj!eki&u^2Uht#8)S@J!d*P=4f=wZ5i({tH*oY!7 zXmTe>*hUprR$PBv3w?!Ue2WNAogcTfp;%iPLI|KXtH-4^c1guJm(jO`niC3OuwVA$ zQ(+cO=N3z7{{9-V8*4^h!R=ku|GJlV;}%fU^jR=xvK| z*m7c%xruuGF_kZCtswg{B`u&d=1u)9qYYL|*(O?0(+DDtk1 zV+VP_b&!%agOnlGSIN*F;s}5V`1zpW%#DbAd39R;yg);mwf_L)f^kf-X3Z#ahpN)q z6ceEh_d}-L{ae73=P%5eVzS4KdzH%hW!m+6V(|t=g{^LIeK*b>+$ZNf&_%2br??Gt z`7sp*rWr^qsXj$nWu=Jb{rF}J<@#x*WLGmFMa~BpaB|`}Cc1nr=iZA$^m{VIdl;~y zXew2iH1Q3lwPRJ?3dpbmu4@W0A6Ib)2XuBME3gn@?yNq`Ry$rwx@JNgtCQc2l2zz< zcuHP<@sTVTqJx@V3+bG5HQUHwNiNe%q=IH#cWk-7)P_AFs$gCtD9N!PUSx4^}u z0*u%h=Eaq)%LtKRk8MIvp3N({!kSEx%{=C*#Rk>=LUqK{5#I!mdb`~2<9xeSgrfZx zZGAZR`j50FpTFvhh=&Xx=0~WC0sE&i6LG*F@J4U|N^I;*E06)>?%*sUXqW8NL?1{| z9k6b14KjrsxT_fzGy4ai#KtUNERg8$L}j?z>>@>JdL3Ha;}|%xm8*BhSM{yV&*HD% zZpZdL>hRy?(pWsnt8fl*x_b+>3`&r*Kwvb9sKhUYb1-{dGvB|<0B;Pa5$_$PqnuIZMW~12llxB zWr^Nvh{H)Ys|$@F@@!^|U9qbBke4e;*KMc9rh*|;DqjCMSZr)kJUG=O#L%~#%71OMu}j~#|dNF$rW^;FIHuuT5NqIYI0UJu*tRrb*pu&qU;F)8>iN!#pr3 zi21W&PiY}g6nlT4;$ouorsN7QFH5wJq&&eI#fb=@$OlUl_50wEWmNx*_QIIFIsPHD z-kfJRVd^p@pc|`PXB^bC#c+06Hw8OIZD}wbwmVbxHGS zDbi7KeJS_Mf~I9YWblMz8|YayF{-@!87?j1Q)_ntcw6wwk=mSd>W_dGX#YkM0`a<( z9)ek0wXHN|&Rh#ma?X&^PPEYR)fG9U`Efs(ksmt6;YDJ)sfQ&%`6_kW;jPs4w?ew# z_+lR`SY!-Vk=V#0by9Sq{3=NXKEyjECS6l@U(mSuh*EdmD z073?iW?WO6lJ!QhT1yc>_+77D=Lv({Azm3*$3^c+18^pz%OiEh+`GwTt zyVi*s9)={C&2~7J29h-zgg;3i^#2NLkyV;(U-`X?fyRuXW~)w3s=#RJM*1SPcT|+z z6YP&=_;B?v#YVe1>kmwK@BJ)|(sTcPI}zpWe|D@xl!oV_MLBY1-#R;6vvKa?g#~wX;IBrRha$Q$#yEs{+pr|C8uVBSh z;@BYmDQHH4-&i4)s;!j2ewCr2Ag+Sn!i5>ZfmNxy;Zh&RP958{^o;^_z_gDjd1K`P zu=y9$D%Tbvd#mo`q>a!hOIFd55TuOFfai3{j;impJ*)K^J)` z*t9=VZbYgO$br{GrzjG&2HrasxV9x(`KNhRXavMmORiR*Wne4; z5KWzDC0nxiZR4ap+kxFw^D!dsEZXBYBBotuHYi54?;X~*o?g2du8x?$e$Aro)#Fdn zLp;-Py*EoT^ews@5Ev`sZhEa;Uj`ZU!1Q4sK|^5E9TddE1(`&n-A=rW>4fRoAE6Hy zMVTHp<5jF8y{42DQV!WcTJB8$h^{p0xW|e9@s}`MG(4i9IlN$i9p?PGg9303!y{;gDzcd8V$8NvY3`acy2*1Sv(p!s%H#gg z<3XG?bg03{-1o8%s9c>=PLfAX?MZw?%6s;|ub_5$ge8>G&d|_8!JV;eO2Sx5vbtjHJ*l-9;p1x){`NY&R!yA5#?z8j*n&rc;*nX+> zt;`9X)cP6}pPe(JN%tziM4iynXhhsLpbWjz4Q9Nu+9@4y>hr_)*%Yt#cB zCEp?^*+4NRE)qOc2|sI!-RS`Oed9)@GBmbsgCUwtH>j~v z_UPna_}N&2ifwixBucwVlBt6Vnd_`;M^*gw~!5FG7`HJ}V@XiumuC3RJ@*SIY zjC|Im;;$TY(M+by8jFc?_4P4MlaASkz7kfyUx!^r@%O^xkLvu!pAr4H3j1T>jd1yO z17y(8v?FV#x9U87mXYBa+`38>UcRK-{xxiYT?#1Yijyh<7{_toMYde8EN_1b>fqHj6+Dki~pW!!~JoUU@>jsPgzgECsm zbNc;Nwec^9=*tZ7Q#xrGnc~zrWv>l}0R=CyiQ_)O@C}wH5j? zTcO9WQEvzhx8Rg-ij$i;5Mi5vn?%EIVN7|+>A6hAJ}jdh|6CgP42!4mnlM3=FpVY1 z?+KYx-(F}>J3ihLvRW%{pB9|uZZGk*W#ZErcu)px%3Sg{8_oIs2QU;(3z|VH*u_>n zRwoS+zqzLO2veyozV3mwAZv`0^a(vs4kP*HsDDYF$ikh`)(|pe#ahUE&9f5^TILldB4uZ_VW6IIyd{1aa3Xj=GkK{Ao_-aqb0)w3V=+y+>1+Dqn<4V{Q;` zp+w}*0%7Mx#;^=C?%h%86}v-}tH)5)hQOdRFTE?LKh*o*8!MN;>nN=kT> zOqS0%#XTVtdA|VV5Okv+z*2XA$@HMgvTo}J+*b#>bX&^^NvfR=^6j3t|W z5_(637cO{|UtEQzeK!w16!RU^Hg&6p{2pMKWau3S^md9P6rkz&H&sXX#{X$LF4yg% z8n||6XaD%?Y{Ko5gGR-IHUp3L&H_&(w(TTR4V`Pk&_qvp3s7HkQ*S43K;mLEF}OufOVKZC&AT3#FYWymW92ahK96N-Var(MvdMXEJe*pK?J4ngTY;N zghyVacWKM|(p82ky~&V!aVEL=J2l02cJsl7kxbrO8UKkQ5Tt+PdY*Tj;W>xOUS%*8 zpW=z>IDMg)?=b&CrWU4 zFy`9t&oiW@NykSEQ2R~T$=dQ3qPjRIt-{D{s_nkgr}SwXJ3INZ9f&;(Gq&Gy;{boE z^bpcFs*aMGd%ULE&Hl~F5B($P%BEnn)i~ER#3$4V-UUQDBJ$lQVT?=)Ek#?UacgOz z+QTyNyn)?a>4ZH#o3-+Sby}VSGsW(e;nlYT8cG_~fqxCU~ zY!Li>mDBh~87NBGf2e5h6~oLk)iWU9<;pC6Pj@@ReZji=n_oy)6m`5uo6o%xbb~z~ z^o2S^a4&NsQdj1UpoX@Tbnvr{H;chfJQcUkVf4uQI!d9N5~cm>aq?S-xKIx6huso0W?IDo327+COu#;{h z!Eh@=voIfbrd6B?Uy3w$gTsYJ3^bY-jPxE2?{ltIft!A7tM66>e&QHcjka}PN736c zfG+V#AN|@ETf2t%a_JN$(`go#ZB5XOyrnrLl?g+lxK}ysB3=wl$$W^p4PYSB)6q6p ziouS1X-ysSCoVYQi)r{q+MyN7c$H(oux^g!?6(g;1tZB8_V2?FEB>cJIWAs9e$FDO zFyDulJMU4|jjYo#$)(|)oNO3A4y;`kJkux_N$a4QHMv|#NLP))KA;{pG`S1l_zD`N zrB^m2c$y2%xikIhV?UsP&6L!3sH43b0H?2Q(V>(Fg7N@e0Y z>8u7>clx3`T(Z*LBIsoFihy~!D}y%#zlupA2z}jRp1kC2Pim8I-lKW(zRc3l`TDg* zi)UBR!q#q!7?5tR*>azSLXA44gH6$WvcGMMRloKJ`H!@V#&Me~ACf$hDBZ8sd3OIB z91yJoo;>cnf%=$N;0wsd-5ImWqHd4)G4?x9-pEUj@`M{}kxcxu;^V8SCv?L~3aI*R zg_DTQYPuV`aYI-2KDY*^$)w=-lky*9m%)w8m(;ia!F|8e#ZUTmSYdt}>}2~tmx{NZ zx#r8Uwi0Ra%pvV5d0LOyfNFH;Z$o42;V0*=L>Ph+@U3G9C5U5rV+(n0yG4%H66Ics_K3yJnjN=^B63$x(?^$U})WRx|W z?F!LD2gx&?ukj92SNLTTL})PNqUxBliJ`!DpfHv~>OYzWG-y1wd5S*yZupVB5c6c6 zST9zJ!fcaD3$_M&_az{9DYqY6U+m+kt9XYxRR7XOfcOsVt3_%1%!Ck;XA%!~VtVZN zszDS3aX+pjxnv{2?qx5Zsau^RNZ-~-Or=@fxN~hAd%+Gds3GdfXXj+dH=g2m#=cFw z*U=R@TSD9ESLM?#X_NjLtuvMHIQ-hSYOl(ZA>Ojea)%K3sFSPDhxb0V;+Yd+?->~n zZ4ApF)JKHfk!?(#*Vk=3&2(C0HKA`VuK!Uyx(Vw~v0cGMdc2!M4UKQ%1q}gJMpqu} zRiii9C7C0C{=%+0Q{U`MCkkAu&^X+^d@>TPC|wjAov5VDkY9}QRkBlkV;U~siuTdW(!v8dG0 z`QNOcD1ILSiz_bwEbUt9GhkSLSXaY9+?iEjE1MLUviQ1&}ioiIAs=4n|#>y)R zz%_$|r`0+}Go{g>kgQcTfchI#r)AhnHCT$!q^>H)9@N3yWZp;M$6Z5$7p5HbOf#IV zuIF4R8#9(%-02;@VeThI$8imQa(?;O7Xs9v;hyxX{rI&AkOuG4#jdmQiPv~aN_ z+~I3Ps@>}uOmaQ0xSC<^b!yon~H*8+!R(IQav9flgWhV z!SxYPx^MhsQ&E6Tjt8Dx7bbq#ACn9F)+dwfU6)$%)L(&`<2P!|#qxh&3O~es73p&H zpmvyXFKE%g#c^kSdAH8`?;O(9`B%39^vH_)~$-1udgV4estXM~>- zN+0PyW6nq*Xcs-rd?O2(UBzgg1szlf5+V|{0BDQNt99Bzn;xN@=P9ysy%>wTlF9f% z8+Jp7+(4o=xzD6+-kMSL+s-v*GOo8;luOX?KPCb}+#>W3HBzt6W~tAj6l8Rt6l`{c z$Q%=T+`s(#)kX>;R5KoY z{RT|OG(n4dRM#4}?A3ZyFkq(i_vC)nLp9$$tVTG4Kxe(?0RK9Yu<89yjc2&-)V#Nw zwm7LwbJD9rEs2JS^xe>hO?rQA66;$lJHA(X>qJ|Mc(;?B;i&}G8F6P>361FH$fuwN zk9+_Cocnw`KH8{)9lc0$s62Ml`EgO{@tnCQ#UJveHBZDpUlN2jNLv>te%aph*{&6` z&?TVyo9UmmRBN-jF;%j!f@%{{>glvC=jxd^y&am^s*9ZkV(KPu1bAOeglq9tyS6+N zfZx)F^9k7HU860xfm(Gn{BVKG3#d7b>^Fsdoq}=Ze6GAgfE3%Hqi~m6#FiL*=(VSx0D+b-SX@5)y1gw;( ztTcTHu*OS?%!xJv{^NaTVmR3Mt+xd}ddc5|^?`Hm61gS~dLw{h>VZ9$!@>Hhq zEL5E~jGBrId5KPh#(XCa1<8RgTMg`E7&11M$r{TPOSBJ{2KpdZjSTsn)?zl@1FmB} z?o5eCO**6{>)t__j*oqwie6g#ZT#jdY$Pofbw&~bOH=9dOeee3?`LFfgHIJvT8zvI z{4?0WubJeBqZyTEO3s03&WTpSWx6|_XAnFA=RiMr`{%x}OzjW0)77SJHsirW&ZZ0U654swu}Jreq*E0KW)j94y$Q_#K6uQh zAxWV=s~G(AXr@I~uT4GbLe zJ?G?cEy4g?S$=G1FK|uoTr6*C=N#B1-tzg>4%)m{w*4FbU3omSB8YLB#ang2@IfYGzn2+80({s*-CpphE2$N=|BYmUkhnMD|%Helq@eQ5~TGUZ-C{ksr?`*0&Ny7# zMw7zcBZD@w=KiEF!xQckp-CdRjv4y-%HqhX zZTMn(){AxkjX3mA&$sYS3~BU;FW32Ekr>F%ys+Tp=2Xf5jMpYN!E z%hwNrHs;L6&WbG{@2&y#ndopA&6rhLxnyeNqyzhmqeY!5fF}asqG^}Vz=b2YIXsH2 zxORj`p!zE1_{>FP6WKAKT3 zPyhU(d~0)aAzCvP<+dT~B}KTe3*Ow#E>XJf_OUeW0CX&|w*tG^_F9+qC9o!1q~lb& z%@BBfYX5+$|NdpJLvB4*(UG~}pTk!+`GqmEtI)>a-3Ji|#qyR)TlxivKj3zSCKGJZ zN62)NXL#f?E6LRYV+?ip#Qn|yD3Gs}R5N8%RIQBmam~V=s)Cswa1pibhX<&`cihIL zYLJsQX-~Qxi>tDx573v$y1bVzW4|Fws!lvPp$WHz`|?zk+DESO1MM7;71_WYz8M7c zZ~i-P1ftX1zB?5+S^&v@aNO>KBo8^(cXE%Ko!XlZ7`>3Og9_K*E6;y4ka}#YM zZmD;3%!6;Y0mOOhc$QkcU;gbpTuYXE?!78b{SD6EQNfgj6<6)&^fliC?N45AO;ZBB z?l@hVDX_V@mz0a&(eeJgv)W~p`+j^0jrB{zc z^T?P2>FTEG=N8ZtcaPQ7SxC$m^1>F5ZAkuXzM~77P&al_A6RKx#^;@=(3)pbCt(?^ z`^s*QF@evShJW_12~g08+-n`UNrRs_lqdK5Wk%@pE@~m}DEFhJG|Oat;ro%E2e=Z( zDP-`Q-GZaUlR%2cg)p$UBfXQX3q3*K(4U({)(i(WTZa#&F5?&1T~ljimo9`0)JHv3 zzMv;>uvRWe+FT;XoxITXJmk6yGB$rr!d`o9P7?H|RM>c#KI%NZ)JqE$Ar3ZreA^-z z8pvEde-#r~<^>pKAKfYN1iVvL&;|>x;`aev?vqAuQx|~8-fwOK3hAYZt6Xl3Avfz1 zi}7G)zq+PoD_X8UJ7Evm=IzLn49q_BfwWk78y=?f|}pBdW-jqZ^TGtV3lynmmP5clI1$L4e~eI{Xq6^%@`cH zes|D3cOGVwf=PIK{muqx_KxthygudTzrv#1%O+%y5TeTyhtSzqfe8VG;$ z@6dsc;N^AD537i1=}SRR!L=*25wPzv=$XbvOe27VkHO(@*M3TmURqMG56sGiRbEk< zG;er>nmzjx*rh}~pcOrW1Ion^Q{=8H@?5#Vb&rY2HJ8uM5FVC&T;wv&M$m9@(N1md zYU2~!_vFbRpWEFr#yyQDG{S1qp(rO!XX&?YE!j1rxCKucXXk4?F5{|<3e1?-Q9%}qq`MKQjYsu z557#;9t}Q7l;3(8S&2Kll?>%b8UAVYS>N1aK(zaw(X6BN_wvE$7jku4c&hL5)-g!f z2KaBnlFJhrx<#t}5tW<5vX!-e+$I`=Jj=)ZL(shhl#7s3)>F;N;Gr$8*y=U+ncM5` zRuJWzLLD)zr~vC+TnUSS@8L5QnQll_!*Eo%i;K0P5&au8lOG4_FDU3m^N*jW&6m>< zXPxs&8}Xbl-*K%5Iu3uuOa6hn>{fOMMH0D(L*sANRk8Ul%ew0#r}O zbf3o$c=e%x7vbUb>Mi==fl7(1nK4>UYpdlEWMHUuS*gIdZd=0i(;IPIl`pn#2`XrS z=CYwg^U@mQEiq`7@qZs8Pe|QC^C48{$3QRhoNuFgJ1$H3$_0i!>1u-tbIVgOxpB=X z*?ivxt4nQaC()+!>Q_&8%%~oFrt<8JVWnQ6=R}-~)y?SToQt#2WVtbmHP~>#>lZy8 zl9@${_#TS;QS_;4RUj$aeU;{Uo-sC2{aEnzN;x|EMKrql^-XS;!)ejn2h&BB+1uQl{yR4^{{OiF=%zfoi(N{Qw&$Gy^OX4vzstJhV6J>- z-n15 zE0a}LA@-XXXG)F6Yz8SwinZArnY&A9AAd@V|-E9R!L#x)*bAa?5vASZ-q4H@H%p{fK}F%^TRCGAhorZ5#s1|kCqnM zhJ8fGMSUT}R;w!?lK)U?B6{L9T@7Nc36b_2&dXtxuRkMJ{9vgoZdX$px%SNVNAV45 zT}bV&-b(7EYeFNwx47N{`!SNjeNt7bZKN19ly&y-Wc#_sqDuF$HH3mgY`%P5S+9o| zwPjg8aKNywXmw!oke896S?f{oiB`BBI@O|9!oGvpCfDQl#=k8NpXNtC&&m#dnNA+B zqL#u=#g|=kk5XWj`R9#ec%i=PjEn@sV8y4AHqXcxZq_jS7zUuqb7iEj3Q6#orHF%^ z6TE__BK0W8gsaHJ*Y9$;#(l-#-;}rq9|7l0$UI6Ko4|=JdDpb^45&e;Ml)FbmJwgX zt@2-wnEMi(c6myy$(t}1tKV~4h$|gz?AKqP&ke8}`JUiEXS>1~x-X9Aq%}#B0LgXfYBSIDlTOl> zUn$}qC6SX`X@=-)GC6ViNdN;CYeBG+9%d#vOPvU;@Zse1s;NR0B#@qO^+d7|&Nsci zwuq^d{Iuu$w70jS9gq?dG**m$U&u2)9gz=mmGgbMkW$`anZ~*)?CL-ViiDlnPdS)q z{TP8-15rZgXPhQ)$do$wtIYE@O#2HcnOp}n+GVJ%xJ5=i;O;cpK|e#>w)^?|LgCnI z?I>EttG>aQOa-=OXsPShW%{gBC|X$XSBP|Z1|vqYZxFMd{FfK7gOy1ap{a$I!j0;l z+u%c|n|;El$;T2CsNS#laoq>}!k<$CJPfHn9A-IemQz#1Sx8 z$%UTEYZ53lkY^~VbE>+~s0#9QfP?;$-*M~&6%Xm#<-Bv0zks-qV`>dG}_JfK>dN#4%8Y+)rJxHBPY z%@)`xIc#Br5ElXO4Taa#Vx>+;y##ETGu|7ruYIizau+4ddT~+^0WZ|936ZrPhWkRE zZq~S|FSsegU_5K~r-rv**jSQCJ|MBO;)OZF7h5yojb~&Lhdgp~I&-v4(OH@nCE}*m&-W_C3FE^;kCVy_)tyNm;j9o3 zUsx!tz~&D$_lH3@u)R;#JKmiFZ0~mr0n(D++kZ%SCRH8-yDuiJ<;7gqCmLpuBO+#N1D0v?j?7toQY2Ncy^9^Zf%9yGZ*Zn$P?39Co7kP zCW^`3l&!dI^Dy$Et7~a(02JbsN22!rBjF1D4#S*!dhuPWDf3%)&|k7EQC(Vp=SzLN zs-(&dges|Ve;Qy`IxEZ{7QG{zuQ)&EUc4Yr%jkTJJ!xUOqT5+s6M;}a-tpOIVd?gt zHfpr@KD}z^ew+AZ)NZxV-BG2xL^ydE>r%;{NNk*Oo?pkc{C2OqAG(u_abrHg7400W zj;t_@ZgGE92jyvZ!4QmtGPT)fw*@!jT?2Lr^zLx7;BQmCy~$U?BhnaWBo?dI`_PbAPbzM>>9o>eVjJ)s3E8F|}}IJQnf_>{E^dFvpXVtw|8FWwi{qQ(IPX zfKg{Lw&T5|kJ6K^N<%@_(0ShGZ2_JJd}7MU zWfBA3g6&7WfbvRu)l4RBKd+18L3!~tXh?NjVlb-_5p|Ti;mXhFZ6qs?WN!F|VXxS; zk`UP)C5OK;%NHr}5gkm!v}&27yTUnc8LyMhx47tZ9%X}g|LmECxc4~FPMfZ7WjG)J zq*$n&M`SiEL@oa$>0bce%7sDr4TT%e_h{@4m?#`z1H64mAn!o>M3Wi8XD97XyX|yH z*^>9~_Gr~dapc2(Jcl^Vv5$kL&qU2>`WbbSoFcB$&pTn};=fcXBum*1+vR};)D*?H zse%PHoL5&5KMwX|f>j4cTf%R~bt8jS<=?^mirQ#IMzbL{YVm{#$~8Xbh~PiKO;Yf; zy3Ps+>Y$K z6#okuKEM}#=qSDq8);gXKZad%H@RHGFdaYSV#0K$1S%a^dY+bb_8NHwnbf#Y5w@5= zBe!Fc7ahScdEvC9Q)%?lBa7z%Hlo0{%fT(dI;KLsw=m|-&V-rIwjYq0ckgoV840VQ zb(Lkoz?7czgOmoCh(oZP=9mkYE@d&wFQ^?U;{eEe)vZI`AG6r+a?CjiRQmNxW9245KWrR*nuoGbZbqnRCQ*UMXEkxOvLqrZNJah^1ZjI$!LPPIsN;CouuSAd#t z!=PN0?zCKs`6yO%ZwCFtMh~P?L#x81K9?YMdIkA@8)1Z-at_X1(?|u_0ULC$!}{A5 zL$E^n#nP)4j8)RE()9Fr2E)A{WCr~(vc7K6kzQX?k1i^wz^gNTmp2)2>f(`W<;^T! zhdL;l+ci5AikdT^8cor1VKS7pWaOO4^F{&Miu#;)hu(^M#vKOF>FPqK6;^7)c39Hk z3?Me&Avm98O1b?YVjG~y(gq#KtzhFkjUy5zADvm}csqed5trd15K_03t$V5a!NvlP&td#t&q7lnD!NOX{rT$H6nYg61=Ic>!}=)r zK>e+5N0Q~-4is7*6~AQ3WI16utDn1kQUm*7!{i0ht9%}SzvME1e4_1xJW|xU$bp^V za@p5AIb!GGKcr@=;#7(x6_WRvd%UPMx%GuHH6xO4f|BcdOe6F%?km9WK!IqQpmv?j zwgs%TXEP@ZVrf=(9C9-xX9owFY&~GY|5ZGkburHOgPrh44!l1TF06ER6F+>$-MdSB zZte>y4s5ME;3vc7`Sk&aQyXZ~oSsgj_HUxD?y>M&b^v%W8m2c~p(HDEX;%Z)GNb8w zmt-Qqop~xFTd^I~e!Zxy7!0E~L5*d!uj)2G76?aO?YMpN3p11$qRz}Z;%*kz8(cPp z2#o6i1==CeMVSKEF~F-rYa+@qO({P@57#>VD0o9mcs?w4G0+uW6qZisA>C<;j` zvCaM3$fqbW(ueLNl@N2QDV1&?tCVYU4=Hooe(%1&-|uhdIA=RM@8|pVdOe?yr%gfC z|GW2B-B^z+Ezt6Ao3l)?CZ{|=4!#OdWqjG2aLQ!YB`J!~za%)4@aV5j#p@0dg2v6v z2Z7_v@=5Y)hjWZ|bs6$|@d>oTSEQ9>%b6NM{7+(dw5z{=4!ALNV&Hxy1_)P#508)2 zlUA2Bx_%C|6NIZ7#DncA5C`~ze8d6B?Tk{ECDyvykYnG+kMSM}TFyEar+&{Zj1(6g zLEn8Lrb?~tSPa12Pg}hzW#g`Gq~E)+yn3>g+R@7-_^od$pTfnNnyjUrk#v|{$WVU7 zAnCN-95D5$IoA0Jv=e?%3g|~+W-34{|i=$2>a;sZ<%Yl)2^xX zB0-a8XGN^G{FNMXc{W=A|EiX|pPsqwnWL~G^y6%wO4wlbsI|Lh9^CMFx6HS0Vs^ON zL0wbX&}cLB;?vdS2B}E8OZlA59y;pch$DpV(zwpmOTTl}*)c;psxy!If^k8v;ppc3 z(}Q-BZ6cvt{oTo0anUi-z1=g}Aq3Rtf`VgB#(uu&+YcUvx&*hQ@=W|QHvo7(%TTzg zY{ob2ctcGTq<9?j>%c&E&W$!l2(4w%da0V~d93kmiT?M>-O;4}9Hx4ksI!#ker*AO ztB7H+Hqk~JF_D9EekX*@oefQJjAjnGIiu$}RvOBw5_QP#=MS^}f>0|r4{_f==DIoZ z`+P&|O$s4KocC!)+g;-^`8hva^Y=5}%zvLs4o9n)P zZa&?H0WPN%jU71fxZu`oIJ;Y@-fD__WpVn1tfLX`kq|3y%bAIWcwOn z(7bZ(X;(^xt+#5D2I<3jt{kig=$(3^a)4V^X~Rbcb5>T-f8r%=TOH4D7LKIk%Yo`) zL;#6nU@(2EkJF*&Jf-4Ma_Hk9g?;-#U9dJBuBj9rjj+4*Rd2%iR|6X~9lv^nmxdx1 z$&1_%*usm~)~2Aj2a*^73R4E#5-%MntCC0oJ0ABL{3f~(07$&$^K8`dFkcB*N2YXy z3=q8m&KsXZoNJ`46LIQ&(SlLi0J+RG)s^}hlGH#4UVO4q^U@jM+>n_?gw$gMT2fEf4?=^4%aAfDHfR+qm2JQtUWPAXnMP(X1&n-?Y`6BqAv(Q40aAo$V%L6Vp!kpo@$06SG z9Jf@`>vil;PTqZzvaIFD#wxGeqLINH?=kLY|HW{R|13DLzayUHSU1<*+X0{FzTDmm z^_5A^-FiQH^N&O;E*GBgPScdPXaWjne37DW93jDIaj4J>xz%vvmlPtYQ>CuB;|Y!} zKV%_$gCO7c69}}O+IT|(g`|tsAL(Nov#|+^R;{{7bHyeeI>3FyW%?_#rEK^t&YO4t z1AO2lrt~Jr!EGbUSSjs_^nai~U~=)nB=VROz<{q&n3cCSu4#ZCwQFLfmu5uUhS61` z&D7=O$je6qOWjOYT;||*@*f`#!_Vc{MM?aNY15l`x>G2+FuGdFyB$Se`$R+PXd2~1 zTUMRI%~b9bfXs)TJ|FdvKf;`IK1nwGQ?$=Y^!!P=N|oY-yt|gT9%OwK@VDyN@HDzn zE2QoZVz$BwanXTBLQy`B5fUdIuS15)_VO9=J1y#Hkbi)#0tS7$|8XA6_Z!r!6VXM~ zKm+kquoFbl=p|~&jCV(fJ;;~ze!@$T3SAJZk4~rZEMH;Xp+j1c+jhxDJMp7w+rT#- zr*h$GB(wfe7w&Zt@LK_!lU7xe-wgwqAPO~l zCD9j>DvP=qSx?Gs&gYN28;~{C-&!5UC2CL=k`zqe^{;9*SA^G^n)f@*7TwVrN>pmT zD%1W6Iv;^SVl-D|6>ORm-Wo;|^|#dgzd@^W4`z4Mt`Dydg*VIGx0oDrmp|ayQ2cD( z#r&H6)w)SX_rc$`HyIV?;k1c8P`j(K`zX7a`=MljrB*_f z(wqdPLprw;y*w|%1|_X?B_jZsbHK@>K`$Fn_KFjkd}i^&acJ&Uz2L^4?60w-&XPM7 ze0FLz7x7JXeTd|u#kA)Iks~|HnE`!W)AFNVk#9PZ9-0=HsP*O^DW57@iz*6VkwGa} zzal$ppr5hq@O^TNO}3 zjm!E+FMoK)yCMWeFt1a#Ktm(D%EYny;JJ15*&F#la zh=!LtcgobtZnzdwT-10Wxb4FGpOs8Bv_520B1iy@NA@`h?zlO9M2AZ>oIO}0_c+#Q zw&S~L@JJstm(jfI=eP*^z1kktdVjDJ;^Ow`~#hUYzwfV9e`zzFhc|IFRvR# zfTvcmd$Q(J_R^YD{!F8Di-y{g8Q$d4B~vIAs;18kY|dpLOBk8%w`|?a7ViNFUBmhb zRT}YS;4Lnx;#D9dFFEVManSoUYGdI5^r_cPZ$2$o1v-+J7@F{S_A{%MF&2Oitgmd8nn4o+;!Tu#myOX zP8sz{rBtc(i~tWaH#OxLo}#Q=Mwv`IpI-(-Mw_ASRR>Q==0fww^R*UKV=`3k0UI*l z4|X*47;V7#dW)QGA!QXZ#kEH)c%3V+Iia(<3P3sS3@p-6PS#x)tcovmB3GTBrGtlUG))Z93b)_t(b} z6>6xv;i2S^0;6thU^jRh7)C_^XC=2&zidcEYY}XJAg~`8nuq4k{Vh{8JntRllqmZRR)8=S-6|g zO7LS`g&sTtGy|uG7G3$J>0CFk<76CbN#gGSMPpy3)?ym!ovjip>`!9KqaDw$b<<+# z&v~GOf1dMW0jKq_bgECROK zv<^zato|w82kcaD;MGTB3)Ot0-dFIQ0}ZDli%h8 zO6gSfM`Oo6*m8DpT62P)S08u*dRnNUbd&48k;->Ai&dki|3~cKyUK+h$Qjb0*6Okq(m&A0hM|mp@0-koXN13{f6iIBzbg zA88i9;Vo1$K|*ZnTv-k{@vEuUElRRq9dr|$Z-I}%dp-d-idQO~{Ky&+;;ip9t;ZdP zuE!P4)9@o^B_`#Q;c1~-a4sqk46J&t9qUd2ku@c-k3RGR~toUZ(LldB+z<& zfIb<<3E@_>KKa*Fq9NRsEIoeW$S}6+GF6hDmW`*eL>UEyGnZH>jsZSPv z33hdT;??e9oP%B01@$3bt?2yvpE73N#mgg`$bP9kZ2bH6(By_b--Ff-J+VM#TY zyKg1?D!hB!jhvoius%1mZs$E-738*Q8TxVTHi*Xtt-vn~nvJq%-94<;kkkRFG+ECS z>k%LqDl#+2{m|C@%J&?BION~i)_~stf;DTGYxXKO;a5k1lPCHFAU13{*{wi%NnY|@ z$xC}AgH%x8LNO`{BNH^4fVaV-?mX%>5*9aVNO2dB0d$uD%Rm1?qi5){K7`bg1vx~#KL5)%xW^$tW!{jZ zT-nAnoM0*(nv9E~44(}J3LWs^>d>!wcrBFmXhV6Q=Lbq#rfe@p@bOw@DoN)Uz_d2m z-tP;vzYEA2KeSxJPjIq2ew@h8*k&J@*PHYtwlY%Ns5V{cawPo}GRa@*(eTA$ypHW2 zYAvs-7A=!<5K+FE69J73mTM(I&lXHtH)a%ehD9FNq?tZ)W0DNiznya}9s)dY4PZqp zZhaBnelmqQr2~AfSPh9s23hqLZCNARCRMJ~U}n3GyL&@83l#7As%h727ofe#Nm&6v zLsMgk=WX= zm{K})I}4!wnbCG(4Q8@GLW5u^iwTiMja#^%2Me!xy=7(1r7xu9$`ae)bjKl|{`lop z<-VSKoZTUB@1rj%JUhR(rCA-TV)LAla{hM9ZK^7COi{6K;*{$RTN}W^ShZhLj)A_Z`RiZ zKR%{Whdf_IO4>D%YFH6pSKF@$V;O>sB)c!4preiHQE~&L?xlyE&U;{%n4=P_H4X{b z&F;8cLTsa34Dd!ViT*;H04B9+!{cf9*lP&8C~UK2cACQJ?Fb_ka7CZgu^*dovpjuC4c%R;*WX&GtbhsDsKXy5C9#R>7&{ylN0dq9tH_cddx(Ov15=o!ER{2eR$jg zi{~3kNQaa1(A2z>lpV>GDexmd+$DGFe(1>uF4lKJMrYC9M}T8gs+hD7EJ2E?1AUTc zK#yNa?SJJ*a*V9fo?LceS5&rLH&*j#Ph6AZI`p8MuM;M-b%%G0akiNkp<7QR1N~{O zu~`z2Xy~SCV17qrw|w2v84g`Cj%-tmi&3pR2P`L5&Oet7Hr&Kcjg5!1Ol;Ri^k$JRA9Ie1K78#{Urn18NLiy zkA|jzP|8f(Ee25RJoioHCnk_!;H8%$o7D*4(>g>M&y?P&`2sVT%86fsb#c|y`n}LiWWgoj8#pbHQ_73mid5$f+SAX$}2W;A^ z|FdZqeeqD-q`tQxj_gR$fqd~w$sc{|wadKYZkhd|s^+>Y2{$L*n|9^zF@DcaAp68X zhaHRWgx63j7~wjJIueQgZ_m@NbFX?_Gio~JkhD=w4K7s%QkUbOfTb}@adYvP1a#^$ zhI5SJ=32uWS%5c5sHVHQ9wyk>kgiG*`6i#T-`yk`bSx~69g7{9=(^kv8->2F+#_Wo zSxs2|d|*3XOg}J~b*w{OkIVh!R^XO8DZ^|No-j2Lj?uF6i#CO;70gQvL6Xjo5+`1Z*y;NH1^ksz)qd5dh;r!Hi=vB;-v4>Vm+fZz>fN&T@)GL+H=^4$(<+m$Jh) zkWrB$dbrNZo>Z}OrqtJuALFKn625PH($T>~l=rRwfj%_DDA$co&>}c6Hn3B}rzE*= zr|Kd)YiudHSZ9x^_AXs7jRs(ssIkF}0)WkSd)A!Nn$op0FH>K4e%DHl=bAGF%ut{X zD#|d=yZ=5R(+<}gpFALDefSl3^12W`aEdp1&7(b6_!9f!;sGJ$+2{hPimPE2v+Jdb z{}{AJ^zoRX?nus(T*9{It3#a7BD9nR9n7!RTz(G&PV4o7%YQx|z|e)&6xj&k_&?*O zeHy2B4c`wf&G>fzFSQLlLhu9$@QC8GK_sB4b4{VS+&*Ab67L@A;~|YL{ZOGS^bK-Z z8C9H|^5whB0Zq^FC@w5FTu(2AcdtO_gESBuFK&uJM{208u|oPaLj*UI)4joP{rEtQ zf+O`ROU_5e<7b|c`7DR=j7~u@j&Cf#Lb`D#+!k}nuZxEkaS*1(Z1=dbtXHW1ht-q4 z(Ld(NgzXN4(ZgZu%2+LZcq;lL^P* z+!>oEu>fZLb51rO9;qUllM!)qJ3SZ;5j)>EE&=^_qMdzj{X8=GLuM-pml$I_ncy@| zHSQm^5&)Meas7{X>g~+Y{5!m3Ng8>B={BV4Hi)7m>)r_b%$nW8hoe5j)!Sr-o%5}^ z2Jy_e4zPpj6=c%%>SgtI0xs0Yut>xYNfx-3=O9uPXdN;eev+ zNy@Ql5}pTP%{<(mHZj=PZxbHO?&#`ewmN2jSC@^3cQOCE_(+x6p!dW+X~FL{b;iK; zw0n}7ZhGnqmM-HN4AObh3U81v9n*PT!2Di%&tw0J>4K+{dGb1wz=u^lTluXFthA-2 z)r4V{sXRw{thI>%YZB^kWOxE{Ef(eQb@40G?@PK&D@bzG%XRQ;YLa5GBh&S7byLcr z2)f&oLb-4&lS-0iG6Q`2`)6&$5~y!p413tMH!M=)8)oAYjxN2Ymm7paVb(%9ZA87> z&c}2YGy{a4TAqWZ=BCg$uItYiWFB=O2|pK-m(+hJSnzjp*&p|CdO`p~KO24kmBA$- z;riK92PY8H+Y2^+VKvX!KcHBOJ^bG+ zsB0j?nD@7eu-ixZN2DN%;>|2W2y|7VMmm8pm)gC08iSccZ_xg8c7TO?qPAzpI#J}A zo9pUkR?>kOes)zQh>ZVT2R;j>Q)CVEMXj(U+Q`Si7CVG390 zT>{HTLl zgrW-X*kd&|ul%=8`S(`D9wJ2fU7}md-QPLBqj)3*GEcVktW(YOoS+{m9zL?ASt?qd z7?=0{Va*e%#$5*j1F@}wpNnG$Fq|)Y9aC8O60xzdX347?;OL7r@{!PAshL0C{4`rw zLYbE;DOr@;re2z+M}$T47k=r68_vk}tK$BoBIKZGAVvIo#AttSo`PXB-*nOhDAgKH z&6b+w=ZW<6F&?o|*?N&V?w0DBl)+>&1^Ibh6#)+~M(M;!>y#TJqpK7O<+F72QCad=B+G%+ zhld|DJ6ChMa>;|Ynl!VeFT3_F%ZUX?7EN813B$$RTKsF$i`bC7fNAQ> zD6Vodj-4(tyil2ekFA?(TR3-8wb;1!T2rE}y~;h6$MeoShL7_ts;H*IBaIx8R0ll_0o8rO`1en;exW8?oqK-sui%2TznM5x47>gPO@;Hos z>9IvAJ0VTw8DAF^hW0H@VK4IO;2Azzl5Xq`n_0c^=`wXiQBgU^;WDP>gHta_0gPd z!YFf&+=e6grMG*qOgEp$c%x$fdD!2&|K4cNWjy;k?fB>V85DPpIqe*ZJtm*U9Q+Fz z2to;e%Z2YUw^n!3QY*4&&Z_^FuN4L!#OiLUH{5GmN%qC7^AAXlrRo#Dv%;4X%YO{)c&ufy(OzsH1Y27b}&1n?CdU z%>2pMF57(oP(e=40RfBWB*x_->MP!%EYN4DBt`2#8JS$SB$9)3f6qlz-S!OQ7to6N ztX6ITvY9ItfnCaBkm@S~fDre}m=ko#N4HwI8K*&RJcU*Y-^^*G z$jYA@VoXy;x+I^TC43MwLVlu`>?RxAPlsy6bYMMy8_t$c*+kMhjgE1Y!3iwEcXvZ7 zQiWp!p@@in7Jiu}!$*c}8ssOaE);ype&v>&?2G|&M2B&*xUi(vHF(l>qoktg0TT?{ zpqof^Oisrvr0wT|lufxAEYj`cLr*(6|K4GKzK29?L&wStTi3vQITyhMB6Z-9=n&|+ zUE5b&x7N|5n3YP-(Ev7YpuF=T?=V3R>RJljYaWb;be_im4nIe|jSgIZo58{?$z2zQ#3N(RR1Dc}(fnS;YSp8QsqRS!DF??uc8k*U2Bn9n zKEf<{$}l6n41UrSxNqITOpk~oby2JmQI;IWkYmtWb#(YJ{vE_VySHvaN&;#JG4>^aH!bdXeu#9)pZ^;1b8E)ndrWX} zFDCJAyExrv8=auVka@3~-&Foby`?)flMW|%El9Nk8_>G`a z$-|g=Xou-gj5%{H}cAN#V{A#EXaHmU%MK1yTXzyphxRM*NV=xbFN+)l77_LOkIa-Y$2?@`P6YeRojWSL zW7+LM8N)Rze$OjpTVZM5#VlrC-sO?+JNoB5P!>0pE`%#*-YN@mmi1-k{S#u_EQ0+keo`m> z3DL-Fp8}R;-x_*lY4xCMxc$C*~H%lZ$fom%nsS$v4AD( zd=+S`A|k$FxJ_1WBx#o1)^sm26X=J^_g&EBiTPipXMsTqDgT$r!^|>xL>c9T_>nHB zZ2XaSGf-DNZ0B{Ha=)qZ?cQ{tl?+SX!n~Xa|&%u6Fh2eU;+WfiuL) zlQ;9Ymf({XOQ-q-c(2ao>*sJK&u9_#AjOPi@IAO}+BHLot8&`fvDE$EU3lp-Qk$?4f54 zhC8Z4$6hkDaoi^vigUM4rfAvGrVlIpLzo{rm;Lbz*Dc)CYkBu~(U`=YS9XQw8}7|k zTlsImGtNEt`wcqVQ!Sd{S7JRe!tM3Y%9*Kr}mWQ95)GB?K|X%qY%IjpUu85dxFx*9cZ zh=P@+6b(@|(zpGLpWC3$&BGjiNV0P*N|<~>%&?I)z+cS}OX#WCtBgbFn&kQ_bsP5Q0lyJb6vM<MoJNB+b|G@CKM0_UlxrKAOa)4qTsD6g_^WtKZX=P?32d$K247S1hWe(NK*XT%n! zJp2c$&%2EalQyg}y&ub9MJ_dXanpMIN+|nkhc49Fz8iEGmg+PD>A;QhpE5)QG9jA5NV=xs81wsW89%jjV!C z!zPx5Oe;elzT(6z$?RP7|1L7rnFI;(hm+6h84LAIgIt%DE@kH-`*JF=fzp(BX ztf@djc3HDj+bxoiFOeL@rCF*JD-Ld;_r&L5(IDlmF_ zFyhQQD44`Y4c7fy98*RJgzz=@ot@+WKe5Z#jyFz(BpjyXH{Kykf)f1+aFE%V zFO5zFs!Rt}++~*(fqPUw>Ag4L`qO)EUW~gY#JI*`Gx8qCrpt`5op&>LLvvDeBF%~> ziW+^8zJ%(Gt#LWBuk0c8v>|UTvA>zBx$I?H-0kXpO5MdGe!TKEQ=QNDz>syaQ=JU0 zpGt4|zTzry23CH+VtwBIS>l|jT7y-|qF zNh*STlA3p_CL@VR+keKKZ8}+yvT4#l<{GP{9}YB3@~_L7_dL^r`elpa#Oj3L%iE@bZT0>lA4T~^M1&I*37x-U}rEZWv6i; z#@`oRQiAW~N)C82Q&Ywqdx5hX#UGfyRG0u_sBf3R2bSJjWumzu9par47sM$w-F}Jb z^MfuG7QG+k)U<+f49sb}j_oldAvc?+oOpq>C?Z|Hg@RU%11`WQT;Sq^flva_wsa&Z zIR#wi(&v>*I>j+Zl%FnIdjH^YB@tz0?EXl7)%D$*&|SXUdLC6v)hH&a+NxVeB+v|6 z!qe+b?7=&yHCw)q?eDCWPy28z(!k7~R}aE{1<*pwJ9p~#f9k}`%e=ThW2MUT8yz_= zeXpr4#pT6*ipSGrCgB6b4GBz(4HLCIc;dUry!qHq7h-_A4mXA%cULs9;0uY$JN_7h ze+&SDgw0{VVAfw48ve^Q=?MyM1pTXN87x6O#>$M{E*517)duvL{54MpZ5%N5@-0|e z2bD3~%A_U`Dj!vauoottx?Bl>QRgj{OCC3iecadsA z&P$qg_ZL@8inUDHBFI;?ELbX0bKpC`gn@hy^s5YID6dWj?aMqJ+Ge&Pgafcx?AdB{ z#Y;efrVtTg(%021o!H)ltMNX&I&aZ+Vsh`+6IGUzu1?Dru~g^-5++f(zi9Y&7SqE? zVxbz(s$|sGKFxZxpN`h2qA^7lu)cxNHgPy8rh1flJlN0Q4`Bce5u-Z?2eaQ7e)=RJ zrij*hNf3K&TqEfFT+3t33&|}D@RvYA1%oC|!^ePq5gQAOs!;XFI0v?P_2rS_Q%>!TQ;(+96_ga_>t^*9i5tRkmGr5H7IeXdGxwN_Z)6N zr5tea4*&e9%fHFsjH7||BLgf-!*{wMSp@3U5HZW7C<0V)f@xJILSCDY47AM7o=WYX zaUhg&42VQ`b3mugxChghfPqU)m(8T5TD%ijbeH-1Dfs+t&!#`vwTC@k0!E$IGU$C= zv2Q-&FL;OIE|9$ef2?_>2HGHXqss2)rRbaE?f?|1qLzC#YXHBb?RCc~8|75YN_$2} zZoQU#pl;leYZl&Z@LHhpJ|y5FUGm!*VLCO?=L-107O>F<)D~{3hH91#2nr&8OWpj9 zZqQ#=7fv4aM3>R3J4dAhy<{@2Ph4X?6bTm<21(+j-(+ayqQ+!*`y1Y|ENbloef=rM zN8VbL`x*lC!}uWYkTyAI4rl;+Rh_scf&=C~jKw_yNdaUY{|a+~@9H6r1}WmL`Xj(0 zp({1xmYQEPj>`@z-!?2Of5j_2F#G-j>9xLA)5Rjj&`6;MP3KA%s)Zp_XdWL(!PpMPCyIy(jIik4>Ble@I?bDSz z^o_LhoczCbGdHR(h0*~d`r>s3uS4ucngEw2*Idvsm*Mo^}@~Lkt3NV-{iwN zi!U+*`W9v-=65f!zoLRRkmkxdnaM`8>XT+u>G-GgUlxjm>xR97gzV%X68|pgftQ1k z-$BH=&+Pzx&MOcyP)!LI^&~<_o|wN1fxS5bY5B9F7^$Iad6!!+(hb6bbj zuxj~Pwia+~=vQ<|^I3LzGbZR8g9=W>#=U_FmdW)pxBHX77(sd|u^d+)gq~ z?)Oc0eI)lUcC&;Me@_api0__J4Nv9C$DgF)-8+{o|5`M!U?b7AGd7DRHS*&>=t7A> zzeR~A)X(27Sd8;VD~9WK)YNX3iJovw$uMN60XD4+sIa7EDEq4=Kkr+=bs+C^FfcCW z8)pA8v9K_(nRD^^euxh0P2N~5U}ixZ`sde8x^I3IGxNv+Hl@G?P)u`Y+(V~`W#V30 z{&l~#^xt1}d;Ng(9{I$E1XvDrVVWM@cEg=+{STkTnsJUiVd&ySkY=bQ8@Xf`Iil*R zmY`H^VD0A*^dx#Y_V9AuGC>>N@crqr{o#43mj0m z3(sUyQ{~|B>vQZDV8b^Kq~oZ0mST(8*rgGGGY6cnENuysui8hI|~so z;!D(l6{PJGYz;hNZOAuZK(P)Uq-svWkDD=kE1_5aU?Y_4q>#2-A^!Cw!z>e68d}4j z)aT33lkEr-%NS?g&NOmA1d!SK5jU$-HI24q8U!f zII#N_f_>vWMzCZ?7UsKhRXL{M+pu#AglTcr8lwo&GEXd0r_IH?3!3c^Lbf_ti==^; zHG_^gLBo300<`aJb9Qym8l{L>(lflyRi^|E&6+v51gPmTWkS`mdu!jB@18Y2)<$bX~yW90-L``_ZO9>_Ggw!H#+=*GB#%N_$O=G1@TJiB-T{m&rMDs%gk zbopm~g5tiIQlR+oJow-f^iji;ko%wEMjIC)z>zBY_2wH;+nVBMld!`X`LFc09JLs1 zIbGI4*?)PY^KkcEIJ2#4Sd?8{jd1x{f>$|{C6oNnM0eq6X#cYg6JAdW=ih;q6O}|8 zn{GiD2R?BUI&%7FPKyG1h~VVO+2{#R8Se;gnPzjXhrQ@fCd>l79nDBce(jDg|DfO6@-I zTYcUOmnPv6B=)!gw%#Y`x4Lw3C1s?X>v4+g*uJX)0F4LV(Zx6`!a9SYzaWpe8o$qu z`vJV6Z`D1WJS?W2s3k;&PUR?lM}0dY2sa730*X5$;NH*pIFMO>7UBRM1SJ%I(`|G+%8`46vi&o5 zny<+nYL}S;B|J5%n#nElZGnEG0#LnW0}gd9)<`lv191CN`l~y2O%_9QHkJV7rl()) zVqEO7l%)Urza&*V|0{?dnZ8&2#Vs0|JWw-2IQIAiW`pOJIm8@DjE5)=*HiX?V*0#l zS;5qE0#Rpk)z|b-bKudYX5qFAomOfeF3tn)k~Zl5mxz$AyyU~Cb_PhOgv^Ff|l1~3}(&!B)dbcfFp zA6j{G2r(ySjgI&O?(dQgcZysjbykU)wF)9S%_V5KU{=EKv~1(#&yUCW`pLf6oU(SD zged-$SdcJJ7A`ZX>`+`Q?R(GdAH#bCRaD9`Y&S=?wo@o0ZGm&!5iTSRIH$s{HJ||) z-m=rYzjA^S?~C;tLQ)dEBkyzoXG+?(qH5Az&2Ynadkkax&^Wi_@|ocn>pRlU$3L0* zfl#H;fBu~_s?67FRzD{Yv#xDmE@wQK87;9+ig5j7MfR6S!>jNkHlJs+#k?LqsWwfE zKonGE2|Dhdg-dkdXEr^e#~FsB&hqGCIGvQon?i??Ba22-Yb+6Xw;vWfpL7>v4Y36c zt;*iVUgW+9Q&)jzK%Cng;Ih-vaNTecK*G0*i!Sp;M|h2SMNIHjC~rTX6;C85Ftz+l zlAZ`s0|psBHxEJXNu(QVu49Q`ASN_~-LO-aiLm!u?0^~Lk4g?kPvqLAmAbH9N%<{Rv zFJn$Pl6^Yx;A``eJ0=#A(m%rwc&sTBCcVXFye~V58by3i^R`mvta%Y#9;XV)FWo|n zixU0a%@we&%IIU?8oCoDuJn24f3;CCduM7?Je*iuK|KQO<~-V7m)x?IG!0x?2t5no~P6M#<$__6NZy0_`fJd)1XF?cyu1)n=|` zeFta77>u3KO}M^=+{FPk;j22fm2egg9~vXQxXbBbwWo-ybK3#uxO0Q8%53=_^zQyJ zr+6us&<$OE4OZBPENrEpuutVyWZrgMPFk!v^=~Z7wOGqS0&wDayZg)9gDpnfWsd1c z|Kc9i?ecC7@?5Yc7ty`yzGvYb(?b|8@WKU+*B+6#VvmM}lm54!qpJy2M#qR3-WM&I znN3hXaO%2m6<{8Zd~~ik^T9JU@*3ITF2h;DqX}n)-3j-R`rv&!Vf#r!3KhjZ4>yfm z%Jy^f==)OLbw_Ir{hphc%Sx;PF=S_Wk6F?B#w(9%mgLp1mHqce(yzd_RqRlj+Oo4X z#pNO_L~i@MCM8%+Lnk_?K-t*X)2z1#k&_z#3NdxjHIyKfi!V@1u2O_vvT`W&0tuXL z!=w7m;rdbZOeW;7jty$`UDyn-dhDrdpwXfT?EJ2(0V}-Z-;yP-cfD`6FGG(4C9gvC zl+uxL_*rq$C=PHkj5`HvgH&7-sykdWgOM~Ki6)K1h+RV|&M(@J_zuY`^l)cx(sSv$ zsQ5)m+=tYex9I9w(%C}EEcLiRR?1$}dp*w=j`bB`il4>bHEFy3k{$%445doC{me(M zVuw1C!;Z!sv)i5d^~)a_jP-a%GB;!Y9eFSS z``U*I(GriUPKWu@9S^e3Qjb$ZO_A?hXQxsp^A=-)in)^#lie0TBv;6EHgTl2KU-b- zsjjz;x*sXt%xH2C40dI6)E8H=w#NNeYXFFZsnbY{6(R8!}Q(=t5YAu(y0P zoH_+cR9#4=Js+`NfEfwaK02l1MCmsa*-!b>$O>~kgq;TN3Xf8IAVpND^ac<$Q)}LG z+92}t20Y%tFoxx$lHQwkPt*NiHy>_4x44|~o)%>r)j#zxdkvP^sILYKH2 zJmWHybjtK~swZHIi*r`9Ng)!4(N&auvFBlwK(=2$mUM_vC0S)fHhGZtWa7EHt6nUZ zG@Gd{!v+#QhaZVGmc&))50q!XUC30yHjw!XLWWMHNaZ(XeRva|eozAQ2r=3z=E62B z!S-NyyorH@L1{txk)p5Qz@NxP#c&x7%?%P2UiO0JfwDx=+Ojgt$d(u)Q3foXsPMrE zLmNq5=s%qPL>(VPfdk(Okwb@V8K5P04#Lf$;r8SYmBVgX`JBij>E$o@LiJ>SvW=95 zGvbA4Gb@0HDmda9;L?efANI~?XT)Rp`{&Jp(Q%H>&@ynZ1G(ywTkj%w$mB0{KLdr5 zBo5M0A$wl&K~IJh@i#beYWx6fw`+hB=(&pJ9K(p7euL*}AQR0CLsh;)I(HX?33HI}e>ghtWVBvPt_^F6VkB3$^W@GLtw4`1u8a8=%x|N2U~_i6ga zOnuMXsX-NXJ*HoXi=>z4<~lZ=TL1IvWRjimi#5L#0K$(t%IrEd40&3K5i?G*t^RWy zP62tUd^n4!NZJ$+nE*imL7`FKo$$%ZZylUldT42h{@-n!i-`7AaUaR#J{S+Z39kV0 zA+t`*S@7GwasWE{s;Z&k*6{zK>D(Wg{{OJQ*$Eq)(>BM=DTfS0$Z>O4LMJ4L5t3B+ zNGjT94ihoyppcQGPX|jrg~TwKN~u&jkI4+!Ws za@dkRUgM;m)SSI!+{xVlHK{mnHbiVU;l!Kr2OthpkpZ;seR#D~Q_9udS@7$OGyKfx?z)JA4oAr! zx)QNz%Q(BTZnhgbwG8tNJqz3b@P@vJBJ=&*j` zwligg&D`#GYmB(!70&GbCLoz<@kR&ITTul0;S{G@_c|;T)^~>&oTHg4evv)RWXjWW zn0cGcfM8Wcf@(2jKlty)Yb@w9&nkzq@isCEbUT9%C!xG{r?d2;TIJN%k^t6q`^i|x z2Xnym(J@-|_{7k!E|eE2>qI|i1@^Jqi~ELEH-n3PqjooM-x1oIFRE;4`o4v}7z_T> z%N3@x4Wr#T@b}j;<0AEo<7)wL1(SF`b-?WU`WV5xkClJ$VPS<$4=G5}TcFT@ArF+4 zbL42FbKh~{7g%<)`2wi65>PllMss#mF?!n9Tlzo+OiJlo^Qb>E?tO`u1b+V?zjgK3 zk9mZ;SwzFWy6@-JNB6d_;r}7#0$0S2CCtCLNXRip3>n=*V*_p=mULaJ{MW`h#i#X>6}o+=hrExiTgC5`6wx z%#g;t+%b)h^yC{AH#aXFQ_MJE-Tbx{3+ox?{iFZLZY0O~oUCis2@Tl!5^o#U?q|In z8iS>uvUapu?LROWMAK9_jnz=4Wv(pQ_MWey<42f%KhPo%=OF`?ApJ9?q1gCnKn=WUIOg}YqkHB7p72dgRL*_=S6m}3f z3deM9Oo0TxT+G&j$EWBNq(1ZQ^h)WB#JlCt=Lbw*N8siQNo1l;fozS8>8Td3&kXzx zQF=F@GS4^{2nK+4@Ynr)3cEN8fQ`J}UcF^8C@MrDlk{viJh+4TWO)Vm;;2VpI6%LF z0`8rSj3VTpx;+s;+-|%%X~R)WxmXf|`Tyn#C%H-M*f)cVHE}`PulQO#1Q*iTF~t5g z-+eQTd|%P#dRkEnV-xYHdJ7RXrY|(G5yw(E(KLtOHU`*N%(;mmNtVKkjhVzdcuaL# zm~6>eaxpbCTB{MB@yk*TQhyqRz@?K7wxxp6UJJKeGMTUFg3)96?o$>ZWjGs@`BBTF zel&@r?#U{?pzt~>&qBO1k8>g~%(!oJ>F$yHmoR;VQ(l{)Zw#)lMZ+ay_He%zM$Rt+ z#3+QXkB(#`b`|^~{Hu5@N!Kv>_9)%U9x??phg-qp7_CY>Ladohb9ojgSezjyIi<=r z#}I2IXCAHc#fWkqtP36M#jfk|fZx!*+ghU1-l+V|$t#?7tU@LAqTUl2O>?C6Azd)G zW#k=z%)Ja_J_0V6+G5CkbVU`$f#eyu0$G|NWI~J$7Z%*vpEXB;B=FVa^{A7A+&l|| zllajF0DFTqQtAct+2O7=xq;n1E)k|jPiorJAW9ba^Rw=Tg?W5>{#NS>4^Zf+Tkt`n zs!RXRjIP&v$o`~-|5H53VUN`|Ka_KLYh_u?kmYi(#8P33SR zf-TW>p0%lvZQB9AbP4h8zHAYkbX~d^NNG23tSKrg9W_bcbHBOSt@r-lur5r0-tEZG z$QVxf&KQu@>IynaPADO?DyRdY{`#D(4a$ z=YE^n*9rSRo5?)p@Hc=8+2V?Q;zr<%65b8mEu+}V^)ukBQ?YRc&gPz_IY zOo&gif+ycaeUGV~ny2%HNkEs(-EZIn7pJI$uM~S}!nWFBkWCc(%WWzR<^Cyzty?{x z$XO`9MCJcsJCwGL`_uuW+wo#dkjh?Ly`3r7p2O&pfJba&cagB$(NoD-=noXUlR!G+ zmollS^$o6B^27b=$YqSG+Tha zAubpKtQl@kq4P z#J%7#cpG(BF?SQ!VEnp4*{jRZ+vOiOFFrAP6bSDTt-G}S0R;(31>X1!)6SaEr%AFyYL=GE2w!=+5 zJJTX~>zQuJqP8fu9es!#lwvggG_;BQi+6k0n$y0hG)_zda>&P_z!>>R;aD&%Ia%g^ zG8wQX{4XD@3D^;_yH}SBkDbJth06C@oKerS5PMEJ1N50EZLo+q_Du^p zGcSifw#yn7es7p#KlAs(r&ybNRLlx<+82#xeteBn2J?I`g- zVd&GGh54AaPP}V>_n6B2I=)F5wkKvD1qhW`tTH?>WUOON?Z?HP$w(kQ1zP+A*liL< zM5aMfLu?`i3o{5*fVR!ee*Xj2U6Fpl!AGvKiGAFcaD{!#uwUA9u};aBUN{y>aaGRM z^;ChHO@#u0mi!o~C)#;Cno-m%wKkAjHA!JXaR}*0ZSfm8>xuE15W0S!hJ@qNk@}>k zxOEac+4Y&MS3@f%S9DLODcM z_un2m1UAAARi%UVdi$Rtchz47-(bns5F{RTaF%QH$2DcN24kfS&@PN3CU!3H3%@O` zZ5Ej>!CD|07xmSKlcPjaIl_a`oB9Znqlcw)UhM=<_|Rd-9Z0a`AFHbY4IQ}ggzf#E z$6E#J8O=CLMDjrzz6a>k9nM<(T?tN)pZZMqi&2UgQFsCA`7k|VJJs|iR1-QL&@Em5 zz2*$TnOJvm52&hYVE1IM{nmgu9+Go~I&Jv=@@o)^3!@Yd^|^BArg6Me(6KoPV#=MK zH@!-ijgnYg1_mM)c@9w=#ZKxA<^MWv1gbhrK++Z2`O)RU@6dS@ivaQ*E_rMMzyQyI z17DJhbFT}AJUTQNKl;~gEH+wRcK_6Nyehx8z|x6uW$+}BbZ$jlXZ33eoy24IMz>{{ znAY92<*h$*C89K089?%!>kAT$W}rlU3|Y+A|GL%nH+9}!Nm{O!yeO= zpgL=}k%V=^LM9ii&$%EhIug_Hqx-yT-F@98!lPxYM*0Qrk|ucw+M;yqqMlGn=f6q^ z3Vx-%kSdjSFNyoRlfJy~c-k9@4TS_f3lqT(i=HR@zy&&{f)IgmD`q~p2W$$BZd5n} zx(@?#^mukQ4N|K#CXy@C+i(S1#q70`-nZL zlCkXqg%WNH%<@|W(Jf}Nl!u$##op?7ko8byL^l}Cn%?8_R;ci@kKwmjCS$&Fu(2`7 z(QCnA#^641Ni3!DvuH`di3Qba+A1pWaY=bH)xFoFl8g5TOoBe$5;VAHD(COKhTn(J zS{(E#Gk&X?p5bu%@c8=xq=RjVImse?~L^X4#nCrvK_sek7hg zRj{9%p=Z#W?O09Od#@}`SLtJZoZZp8!OssA@7Q!ml(psReO?l9jAevn!!Ah>?^^z7 zXTDl5&UNG9fGF=C3jp;8tywgY>&O9~?b*-gn+SMHc6Q23jS-9#*-;J2da;qSHuISv zsdHWDlOT$iIwa|#4*gI7Y&vq^mlmdUS*@)Wi^pPuuP@@n4?$ciFiTVMaqG~fAQt~k z7wSngGa)@C1EG-zj*D>vz%MS9tKW-T5rlZsmU&kFZ`SK~Z zDrMqxmmEEPgC=X$v)e{Tefd);LFt)o?rSPvHGIZ4Mfms_9JkDT!rHu*hBf>R-7Wbecgg~z2lj@tTkr%Kng_L7?lnZT$1{p+#ZbUr24eSgub&O zZ|mRQ3MfwS9jT-e!-okKD=F2V{`_&D_}RY~E|AJhHDJxBgrRjY|0t+k(qPDhD16wN zylyN)>Kh5j3+|19q@%;IRALw31J@!C z$yOoyX*X+4_vv{pyz9l;4b-+`KLjUTuoe#+H-3#dkxQ~~&ys0GeNo6$upH!VSB^Ph z@K9%@$DZ@9=`;CdpM&W3956+^RsG)S(8P;=Yi_|uUJLURewOPQdb!G3kcZ&#pB|*5 zb#z9GdnN)$#vH~|jP`CNUfTzK511S@TLu2)=qP{XI-LXLb#ogY3xLeL$0GXO(~Tno z$47dU-UbBgu;pp)SHvq;t0tji;j8@$4|23BPoz}I07YbG`z(=^&uaVn^nnTV0ew~R z_scERC51N%bwmgLqvR;dz|3&Lu3rZGDQPMeYjy8g5pLZrIauS%mFOspsQ`J1H_C(W z#nT#PrIU`0dG!~Owi5$LuM3FXKvCx7&FQKp>1QqPmP2Fm_gp^$pgP9P-6;t|Ze-r( zX`q_w(@Y}bMcI8KCJu{4PI?$8Pfhn*4X0JHl>S`8jjw}@)D*MrWvqtWCO>Iz#xHYW zwZK9#w@+zWF*4$fwqZXqS)XV!>@0qzfk@f)>63+1AO|#jaHC@1P2KtQe<711hul6x^D1~HJMd|j$!_s6~E0jj+Ymu{{vJV|iZ*G2-Ry6#z0MKoln z$0JzFv&4U7Am=j!Xz6*OXfC)D%>nAAS7hndqcEkj@R)6brnCT#{JbieqXB+^t)72X~1~ zBu0Kie!Zb$jn^F=Z0~7q_j9@kR*kvmay0+b&%8Djx>JJJ`p(e^pZc7tY1^Ode;~rZ z)=emqppxm{yX~=#-EM&5j*z96o?nGtZIa2Js}pgZyv(IPHQ`O8~&+V9h zIJ)w&o-ZIS`wcFf@-xF6PLaxFehoMDKPW${q&a{zdII6ArB@CWS|e0xhiR@BKm?~0UX*` zLW}bN0!&PB>h4~8qM`1umQA@`nt1MhL;Z$w#z#fh|1f&{iiZxD$jEcXX(vE6it>l+ zF%Gz~DBy6{-{9KL8GeYBoViek~EW^MF5<-b^@=aU=N^bKv$zw`(=a{FM)9Pc0 z9Pz=^RUZFu>t>f`d#Ugv`0)DtiN#3IOS=I>d@%AL%uXQ)upHiXuASUUy0C2^8^{-5 ziwGf~jw&BJEVtpKFCUOCy?aysuWTv4tI{Dt8|y<@>gj!!egPra=C>+Mut`tj@jm1gP31Xl1nMLQzR6gyLbC|tAE0Rh*ABJ%4*Wi|JaXvZ@ z%0J)mQiQhF((FxVcKhuj3K@G`#vOE<^ra>7E*dqyh%Y(r700O!ggPr}?<8)zNQyB} zJs%hrmtvmphq0UjsOl=;r&fii26}~!=?pfhUv(X829@nA)tXWsq~;!Y zSS#mQk!vT1JnW+48^H$h_?WU!?9HbIBkbPNu%4Wh7>@ua*0}nax52Sk85N7Nu@P-d zKSeFBSuM}yxFWR9to!2w#HD6OrPR%8h#5`EH(uy9KFbt)3Toj_99=tZwItYoXn}w3xVL{ zNy}@W3Z}O{;YE*DMNbek@O_T=Xn#{H4#XS|ZpJ(tz`y8T4w{%v2axY78Y9F~>c?Dx z;JOA-PHq2d@s`Xx$}zW-4g94mN2gxiL%n#>llddRPve+%C$;k_)?A_elSWG-GV;f6 zk%yee3D`C25&2u|QvmM9m7;{!X85E=o3LSYbWW{(jhlC9M6LjF%v=?s0IH1s6x*hX zPcWK>x~8w^12#SE)6_Xp+iU!RS%T1IXv1T1(bp6}VtrgBezTr6oC-do-t&s33bx~x zRhT~P#?ArOt#Ebr4eSj<62c;|i`o>-7~B_oM|<7Xy4+*U;}icpD}48(7Va{k76(7J zlv~v=d0X^rVXNXJvx<;(=h22T1AqBF`^qEQ3)&XLq7~Ad2+bD`4K-=?tMrH5y^88r zu8C(z2F`(rTV^(Vvijw`EWT7z=Qy2;0ilZ zeNpo<2yJD8*m?z7>&+p0@-|!mK(X}NYHRk79bP;`sbPLMCH16UAXg2fuo2s0DzSQD z;1zpIX&rD=uB@)|BOM(XqHP3sGR6S9=#z`3{OvzabSpb7 zBX=Es1b)zoU(2OLDUV#sEkmf!4#3VAn&0_HZ5W0sO#7&7%`G<5G*_F}iE7Vg+}UcXfSEq8wM`R{m!Eb& z1RC73c8t;UyZFjI4+=Qcqr3L)g2(+sDFH`%J{lwmC0Ivm<#4DF=2WXX@-_31lmsz# zl`TQuZbUolataD?E(^U%?d@9PdpN5aTSi8)p%o~%&tWlKM3+h8HpK3>XS=y>It|@l zu=Cw`h@bF^(g|D9t-cidSt&pIXYgYkVBRxSz9}oSPhIoX+Y{qe4UJ)J^1z*8;?`47 zQQx{_?aQGt6cvHaTBkfX| zZ>10OEK-&_*hEvZTP(y-esJR%vf3CnUK`w&QwYwEF<5MIZA6|}%dd_-sdErzY9e7; z6j)^KiDT59M*M;pZX4;*T_ULN<;-DJRk>}Xp@HL^R|#BRd>kX7k@;j5eb~^BQ>zw@ z(KE~{(=ptky?8NPtdJ{$n~#t<-K1cljfXDEd4t3q0y(`T>rRF4PE^!Z1wNkIXvGa& zdd6`2gm60xd1sywmmmmBL8M`mpFmX;8si_+D~wEU;q?#3Fm}mZrfPMUz}vO|g{wam z7VU|NL1KNOE-q```G+Y$vWxV~+9s!WoRpj_C&YnEBKgBT%Sa-+XDqC2hS0kfv>1d; z;5q@6L4gc)nej=V;#dL*m)8J_#-;B6D_nB#RF>T^{G6cGrul4fj?u2so2L3g?z!1% zFM{e79l&3oYw|XK+xzO^`Nnerx3#^RXH%4lcUUwC<()fTzx;H-)SmNq=7Vpz=%U>y zw$zCyMt;nT(adjxM*8*Zcfz>BlgWWqYF+SW~1OilXdFqzmGoPh4Su(h0&{?q6 zGUR|GV5Y_|B3|IY8$riTI<;E;Lffp9`+l?50uKGJhWZ;63DmjP-?!4Y$tyE;UJpIN4-GhU5H1iT|H8^Ls{kCBKmmc z#i$}_3Td(T$QS_#L8qpsZu@Vo@JIU>t7y8lBxO&@AvJ(QKW%-r3#}<7KlaSy#o1SB zY8y};KdbGoFbFV6TxSS4O*ZpSr2wiW+SA!kA+@xn6%Mcsfl?SjxS@w_I)H;8$@sg# zQyQ2Y9i|XVM#>GdL`ICqagK(7a2NB)EZhvDOG_z?x= z-A%QYsMS;ReqJs4)}{j(@+Z`8byLG9k16XV<3IMo$NLIevAQ|UO3PX5o!{x*Kl{D} zWl^8U9-a?@%F;VA<&X55my^kBHx@_Rk@mtQgjk})M8ME<~QhGaq z47{>Gf^ACA^wGHC5n<|oVtp3(WhP$A{ynbylh-pk1tg---FD^oO)>8cDBFT$E6N=< zxIJXuLf@x`fzDo$0qp%MMt6a(*9l0(qNVC?&DJ619m$yO+YMGA=gvu@AgB%a1UH;> z65^a%`z=^D)2#itWsS2^hI6~4mBaY4{AbZ!v6&Y*H9U>8L~`=-^r_+74W6+O<$tvs z(o_ej87Q}#HJv9+!d?@jYmrU|Q1zp04OS>YPN~>;61+k6c#@t_*`o+P+Xnea=l135 zOg9dCC(oibeFqREor{uc(?j${wx*lhs*BfD9;pgq25*DB2SQ+PkiB!pW(`mSXJ|`B zX=#Dlr!s@z?`RxNVUfG{BKwdP|CZy!yCBs#%eiZGZr*k}ovU|Wez&~*InPc@TxO4+ zT8c`K`?_JrhyMXHB+gXYMSX)DGyg(iUAgf@-j)i$s`D*D{pY%Jk8Z^OboZ?~hfMm; zwUURvRZ?YDtIFFT1bg=|TRfNAIJnohZ8{K9+N+Ru@jM|Ntb`*f8>FOVnTvz~I-pQC1DhDzpv^slwG2l`Y(JdD)S z8{ws}zvyk^rrz?QL!!gQ{kL4bjLbwmpB)HpWO;+g*%fUqUlA-T_;+YxRSs6}q@?x| zdr|uRQ2rtQ*-dn*!B{o2m4nV8S-aepb3NH1L1&m7TFej|{(cSEA&YEdDm0_urmSrk zt4p(L<4y^|6-@ZP3l$a2v1HU|dRD=$!vK|FF9i04zL;YWrRN3*YyuX1JFwOh8Pat$ zh#IJHV-o#M=_#rnJicR*&=gX!3AK|aos`K?;}F28f>#L5tF3Ze%l%kD3f(ql1^*Y! zS!O#d;WJM<6bt;pXzQOw7UF&8{6JQjS*9@?h#LDQyLBSccN1sDF2 zp3<+7WCZz;2_NdfCdhQ&X8lzJ=`nAhEP$zW%-qBe{mP2`H%Q`EcQ5! z6w-@_=H}f6rvS!Uu)TOWTD&m_g+g(zB+=+(NUtu7SFYZP#QW!&Drv8*MzTiE z(uOdIE#uU{b*ufLiygUyN8R$b6`udeZzD9zqw96`fc+oecMGRi*?f_JwGVdI->2BD zucq20)5LFm0Z_$d1yxUl?8%_8Nf=Old|)glH(c&2B^9K_&RJ*Zqnfr%&u4;)jl!L* zZ^hx~7%7fwJDA(ShDx4@uD7PmMjKgA5BfBhWC3J=1fLI+%8k3p7AE>6Otpdkg8tS= z*K{vIEsWQnP8|37*LbUW8~U%wQaNK@@-Aol>8A$`2b_}Hl?E+L&;Rf6^RXFI-Mi#* z^}cn>^S4`|Rk~s|MLjF<;LFJNtSazphq3Xoco0dtqSVoj1NOjve#N6}_d`W`0G*i& zT)q=(aaMXczx)a}Gxr6**Z!~$Vc$-z+(1pX-Gj*gxboV=13U7hJXXZ~^Mx|FEBNt@ zyZ9Sz(aeN@bP)KtPWb~2=P!;tH)L`r=0#=hf`fjf30q!l)Hyxuk$>&Z%2oi`*|-xj zNTs}lCn^KFc9-0b<7AHvKkCm)(67+4$ph5+OEQ@(uhf%zM3)N0;Q!RT57I1=ee~(e zP)oR9p@o#vDnm7y+Rwry5nEO#kg*--HTP9Qna;3CNf2y{>bG0<{b#2t zBwj>mACm`1k3uO$`wu){gM_dCMn4`gLaNOceZ$LQ4!Q6=nl?ayg7Q-Px7|X&WPJf2 zuw|}Xvj(hwvgd)472lq)^>_2iXyiuCVo3@Gub2>X8{idPB{s9qV;9n0f{iFj%z;Dg zIbk~DeK%PbrYYU9omtXP>*3*G;0*GNLYXQ>WG(_WP2Ni*??wGJL~Hcyef$YU)zj`} zhb3}BN{c90Z$_>-o}V#?O`cTz3{du8$~Yexz5Bd;^RBKN-{G4)$ z_9ZvWDu9kuxzS~3ndM6J;qCz4gA20|-t-F*$2tMAkCAQ$@3spTJ6wH398*};e_zZWw9WV+^T|$t4ad=So_NAxCNw$Z7-?sY@)4ACv&{Vxa$wl z>{mgSQV0+LH1Z~X`TC52`WsP@G3^?kf!l5HK)^EHhA70S#BAklAOPYjT5E1z!Dh8D zb)@EEvtsYf`$yOoWie(Lx}elMki>4twnfSL3*HG^3ZrGWEBlo_x~=O7_+i znOb;8&#jJp*oMTd8j!@;T$L3Ns$)j+@C$n5Mqy<5NUqWiBcJNw7=H4K!Ev;@mv#SY zfe$=F@3`HPm!#W}4qQHNaWJ32hs zUws;;Lx$g9R{{REA(*ZmtDE$WF-v*#)`qesrySJksc%_e^?MJ+=`cFZ{)tM;FaGur zX8iih>3o%+)RahtU3^5i2)@e#u`5(4zgzl{Q58kWDVE7RO*HYfY6?Lzp&cybZ?|RgIxOCSIz-Bs(r4wglXu;9M zSa2|j>4-^KYpB$gZ{nv}8%ksuoL5O88XDay>pw`O7V{KFk2LO*_<0%S%TkU9&*SVK z>uXtgO=kM2ZqApXAmIG`^_p-cJ|PO~sn#UtqqTIJ*OsDT+YwV$xc6v%a0#9&~TxWZBtRE&v(Xuh*^Sspe)HgAA(B?--${d(Nm7=HVaFc%$guJ zI75->H}?HaDT03(fcbQucUdG=K3XsW)a%n_ZNB};FBKJhxA&BCLe9T zj%l+K{3Q~0DA?&~mV6npYD=xTytz@gi%)EJ5I>-Gqd<$@=W-)_z#9Em zAiZ2!Rsq}2b~*KuR?pK^HGm=srj0Gsb)gGGm5srIu&g3y$J5El!jQ17NH7^vRbvftDs@Q}70fnuFy!g|m4Z3xv z4_}GAt1D(-<&%_GpMl?I{Hf+AYsc#)WgnGT;|` z8fJ*d*O_Hau2)+KRBp$yl__VIHNoVyDKO#}J+`XpQo(f!@?inG*BU;@+@I8#)I4bE zcf05ktSei_vJIr9@ra)2<$FzKSUsw7USF=lI@{zJK5HUrfAR^FxW$4a1WgJ)vbwnr z6?ii&$OcN<2Ff@#)T`D~p%jh((hL;4)|O+RH{nAi27P zk`vq@)%l7pwp9U-T?y%AyXDDO?>>zWk2q3(# zInl!6hz$og$D^|Z#cFOYnvko64pWW_xj`zL+MlB^Jpp)Hlj4j7)&dSr#x$b7LL_q4 z?W_^nRghCwn~?w5x@04r2j;C(m>O|y*hD5|`4yk|4?lEB%DmCDT+;Hb7@gUymweM9 zdDhI&)dVs5AC@TVLRcn`PfW%w&d!@aOq`t|W)$e-o~3(0V=8z5WopqFEg=;g+QS?} zq^#;3jjx?wa=*wCUT z1{D?%o0gF2%kD$}o{@3-ws8BhxoT1h;M>&cg+-#46i3dj0H!)8j1LkiA@lTqILPJo z91-aDS&bHC@~ zHS3My@KGJd;Ce2IxARNiP2gdg0&s^tz6HZ6-^~Dr%5uTGFT)P?^t?*)c$FJ*q%ME` z4!Ff)4bz2^uWj9e*$amZf($j+eNnbr*m8_`mhF9vuK)N7ci#o@KoUl6_65_0t#m9vlm{#tm%K8Ea(Xnzq6BScITniq zttQbm51+(khN2WviQF<@+&J3}f@M`zN!m8A6VsGjNUQy~3YaGuWnOorwkRlG>sI|i zA?CL&Rl^ae2{TpoPq+1d`hVrnXMh}vdzR_6WWTNZCf-M6Uw-hXQKCxqN58xMxA)hZ z>RdbLa!oxSSo~>K*F{1HBUbuf9qj0k&_yHnAp=)YormVGE&2P8-?ff-uvP&c9)sQMXP)YFr`(r$;^wHYXVwb- zlu5gtc8fYOkk;GC?_c-{(C#&Pco-o^r50YVBg~%vrOPt9gU@rMGbGymhz^bEym~b3l*x089IBt7&eA6_Ccqjtma2WynOz#%^Ulw%hz$T!D&s6}?BSdGaOKo1 z@{DhiRW*ZB;vF|&rY!5~7>r$B4P?J?L6Y&PAV64-@9u?R2QiY51R<%+eye3EC}NJal%qPr-CHL4>Y zxe;hzv@&%y{l1|Wmi1yQ`7$W6{1SJVvE`Yz*aO6I0dDANndN|a-?&ZGjBgY#_u^0; zVc0~K@((oR2HG{9kB9KD$5Ig^ZjBvw3+;Q7WAc72xU0^=6IFR>G2xe?zyfpSc!jEo`d|6XwtD2ayDz_8wqmv zB|>uuOTnB>;C!bv5Mp;%A)H7UfabL*H~%yHNp%wUrJSZ8l$)0&M!xj}vI(1A{X?xG zA5S$~V=i|8{6v(t@C$;XXun*i)jcYV>Wun!NU@KvogTqHCw}iZKA{+L{0jG|RtsM_ zB+74F=FO!$M;aTV>Q*LT>H0*|FY+m#fdeax8pm8gB|X{+aKiLEd!2pqS9Efc+T~sQ z&Z_vM8!aGbXAD-^dHuo(*MKQsvB93W2j9$XBrt~9WP%yk;2E6=2cFH)(>NSIVlm)R z9sf_*t>;(Lw-O;`ppP@e1A+)$)V6{jaqh`QYrKsUKTMu%-}xMekA2w>?`+o4hn(C# zzFiLJ_B~C2)b^F8Y?m3HyUe(iCtWF3=`#~IP-6f2swNuq8!v}E$CbpsglKVD)d78w z`)WFk5@ZVLOSA~|&9~+IgBX(ueZac9j|I$7P#4`2jeTf@iF5tUg*C)C{}LeT(6zSO z$A`Jp{zRvMp~#fmAKuKkGa*N&QFR`2DA9HhQ`;bS@hIRHfXWc}f0#hfCe9G6p|MZ` zu?QRUTYf%GA7R$(%RTN!?|1P&4Y`}5v{}Fm1g+)`7so@Q2jo;hq+xKik9_+hZ0-c? zDE?FSs(@(3N8frzH6gMBBj9-pm!LF~s3K=uu$i5XBAX zUX^SjV3c~InG=fuOH#9yF|pA9jDWAdGLEMd1yF(PsT?{zoY+W$hKI?Y+%hCbsW=|C z>#e4=t|mqKv0JOny1P#pHrDykh9O_NbAm6(jCK`|YmMnD|LvT%cxH=2(F8nfx`A<4 zw{{LVX3e)68AHp>w@v%36E{v5PbKgY8NSE>SHU}(u<+ujdw8gvt&YBVa6vTZvew4e zWd%mWF`6%#TeSmm7rK@nL{rO#mqBvgg<#{c);=*NvQX z&kx{#31x#hJ~&9+X$+PUASw@V%UXk%m~l+qaSo0il;nz1%2Tg;>&63sgi4DiI!}uu zxXyIeqwR@dIXiL&W1zcP-wV;>sI-FbefDx zf}Q%WR-AiyQ!2inp|rY}YX@+@Ym*;UWk`_y}GT ze;T}V@-aU@@jq-ojd1qELq8vvv2BB=s&BpP%O$ zIYs3_o7tC!dy>x6Kt`~)DVme26DFH_b-f=|#g`5q88Tz=GnbH&!zPB86{pUFw7Wld zb;X0K`ASJ>*1HxuqcTLZ);ExWq}hmH#i%CR#1TCvIa8g%7xr{w1=zbXZ4t_RQ!zWn{cQqG@wsRO& zK-3Ky;1}g#0>Vzup^R^+gtqI~V@GmlHbtl55OsvQerRPfjV6e7?l;3ud*VT`6Pr*&(BkP_&*cI)xftS?-i50nSD~vTgLeVUp61*UOyxA z+_2`G=GYjc>>RIBOL%1zEH5*`B#sP=0HeZVru%)B_I%v9`pAY3(^SxS;=pD`o>Wb9 zK=^a=YrchJw*(n1n%eF1=2hL<&*F^ed`qCs^38VDJ*~N4wc^dj`+O2hjumC7sx{lq zP0_6zx~H+e?Z?zMvMJx9+yp0XRu!LwN0^cKf$Q=0Kd02DLzy|Z=-$y0@XABoxC2~o zX4eUF-7~Zeqv=WCRh61Ox6`fpF|Y{y;^eE{AD;4KuXdc)k+@_HKQ+AzJCS?ZXu6)V zpaw~;ZY_B15`p|9jKnXlJ@#$gDQ*CdEvVUbo9(Av!uma`qi~j*qOt`%0JF&{V>&W^ z{JW16WobF~Z}xcBqRurP1_^HTyJZV!f6N4SPAwki6vZ1rJ^dD;W` zHb}b@K2imtJ=(FZr@yF9>AeC&Jeh-4GKkhjo&HLBWM%z}xBoDV(eNjG5k3ovBNMeD zwhKG%|A{769_QeoHnvnOlR0c~(`pZcqzon1uSn+|Aae|&pYm`C&|b~f@%hX&0oSd3 zalZrwIo(7jp#5|aFRmRS-eavU5Hg+ggu28%ot`uA*1%U}RNSr9RF90)y@4`FwfEm8 zXgEp;FYb8uxeJ0bue-EO*x&z5vi!qYSQt6vUC9MUdv1x(zZ0r|0DfaaE^SFJt~YQE zIL03yj@+=mtYLe2<4NXwIfqMGpn^}nqF)cVx?g$RRfJBQy68)Ow6|iKvgtu7bq%Eb z0ajS3Pvw}eaJ|8;bY0~A4rMFEs>AA zo5^OeDo2r-R0m!!^236mDN)FO`V<_3XvZ#ozX$A&m8e7qr{{`k@L2GZVp-+}(GHk4 zTPsrDFP+^xuV5$a-rOeYmH|sXy&gxN`Z z1Jb9yFV4YqjVhGX)`s#?L@-2>4}_flqBQx7u2=W5DE-8Xd+v~CIC;_P0_X$f+b<2-H@Tmb)= z;bUcTKM*q-tB4D6kOHJ(T@a`Qb;f@HaTiEIDOzYwg@=f9f;mB> zdoZ+n9*_bR)j`eztVpNvKE8HewTjAb9?j>sb6P;}oR$^B+4>Pt3c8QHTXsgJ>?b9G zOtvL+pm_i7CC|&^xt27e-qyduD%?gS|9(p_ED%;~rx>96A>gzckg!+^d*Y*N@OQpE zuX3;L{~dtT14nFLa62wv)*euf)oLpZ z#rVjm>CFF~EEQioarM#+xODvP%%?}9*qJ91bbAVV2mc%3o&V5wgf;rI-vMQDBbh(Q z$`V}_5kvrUy!8>F&5I_iO-#^>>6D>-4@kE5Vx7C>Y!BB>SAuut=!|Ef#gl~K&r0cO zPL0ocpoM}fF;=P7qyFLD$R$OjN+tNnLk!;GlL3;NZ zi0zX2Lr<9HwOz+tc|k+$MUglngI(2L#M#z&fo~)0wA4FgnwSHbUOS;q>acpaeIOz{ zPX6@TudgP(*LD`+Zv+I;bdkKPU-}7ZJ4;8MCeW1$3oyF%1|Xt<*ea_5FTGag;5Rfa z>n1m>>K7OS9i!G8qB}W940WV8kY|l6y7U$0*Bjo28qoAU;1vgZhXVhOl-8=B_2TMN zRItKzEx_3aD5;J;d2s*{h9R$d087pD%GEZ^n}QlAlN}w$@I~&kxd>@)P8>F>2{RRB z-mqaTxvx%fvyH=>TLO)$qqm3qMkpdsDUoV@v|QhuR1^1Wo8)=*S~(bQlV)bq-OMKJr^U_CKvmV zZlQGnAN<33IsxS=mGwJCt$4&>&OmxC9q0i9=_ddzLKH3MH6o=%P^ z!n(^Adx@v+G7y6UDPQY~zU*G@XFM(^rs|{?Hm&wf`oaym%bgwYyvVmESGmP+pb?{> zcB#hFx6q0sg1$vf=@LHik8_G=9VyJLf>qS6d7VlJ$N~67^6P%Hc5$Dm_hV z>kO<%Ls#pn?ff2XXtUl6j7qjOXSOd>lAZ^Js84?F(=HHC_F^Hi6^19j{5v5-;rG`8 ziT9ot3SuMg*q27hTZ!7v=nrxkcV&Vk#Q7`HU2EX;YUoRbkDOrseoMcVTNY2Lbfxn8 z7{Ug*9xP<+z7!W{J|{OR;ZXe+5rU^r*df@B2?Ot5_ zCxTyo`UL1m1}hLej<9rsM?z3QPinhr1tinhT6|3OjDL5a;LvA0w6#^l;_|$UTy!c@ zA&)KTWq~jjNj*1m7ZP{|)oF(q$akI8AcfrLIjfwu0J_$7$oY^%WSes*hfbt0Ye}U-l7yX{iJ^mvj1--xBuUIE zDrHHfQjH{vnnTQK`@Y_v@9+BkuHV01U01HI+2eXX9{2n0mam=o(5XKD875C-%^J_( zr!dR+GKpebl7TwP?tMH|YXIJen&$gvUZ$} z4dwF_QS%pO{|nXnER{EdY2Ai?A3QLB<)T!KXKDIHcr-W*dASBu8|eSYCu9t{XStIV zqZ#R+gZ=slVw&l-A=s=triRe{@~aF`cRH3(tIrtR4FiylPx5g(PI)4);Fw&z@P{FT zY5|QIT4ylH+MSmt?mPr>Jpe(EZxc(68jd6cCDQzblSX`n33S#36Z{EbaT9SPvs6i8+SqVbgOXJq zG1LK?H!wo9-hgUt6j-kmFr2%SeM8uL3wxAZ(=|sPFy%CqIzham&U083>0L6JFl!Sde&WTaem&|NlD{bBxr!Y$>uE8;dl$)&1xk;?Mq$BcrTF z_4c?!Pl`RiVXu|uA2l+IiyCpexq9;iqLAUb*9JH(8rlwKyjARv*9M;~)J)u=;9`_p zYqwFr-89tc>#g(udl6RTns61L`0UyQ(^(6U#HA~X|B8o}tQ-0m(Xxuj(3V$lps6*{X(9sP&Tt+~UivJ^gUtns-}2F^4!^Nfw;} zk(ure&$vfbcs4eS#P~(?{#4(~x=o_L1&@#?odXpScQ<$Eu92a5`pNEXU)#WcvM4=LoYt(#05;|?x&C#4v5|BGzY}n+t z2z3U1hL8^d@V1YnwQJfW|6T^=EHC|@x4QXWJq@?aHeUiYeN0PF&o(&CWIlN=d~q$G zfw2Fk*7IEzo^}qqM+s{Uq@B`7BchDkT>)g8bwMGUEjR>OD{4zOpNUCRd>#p;RojNW zIp^IqRP!O;2Gel82LW|!{CJ~Qpid1C{TRb)$=vV;du0@k<2RpMq zv(vtG`fkbCN23wNmIAMiYgV^!3euq1!mN;8st2rh?IRGf6p`NaQW(Z`?G;cr#YPes z6e(5K9%t}%X$EVJh2FXZ0>IR9Az()Jx`!z*2A^|`t+RIPD4=xr?yGCKOMLdz$}@4F z%_?&kRt`U!)vmRO7H!w6r1>{Nv*hO<7Lw2>}Dy3@mQg+tzNEy+be;y$#2$g zXy{X>eW4azD$tL>P}$!DZwtHEHkqNtbry7Fg8ElC6Z5O-1&^*o&7AH zTk$#aS+?>r>&?LaNCP+Hmo#Uaf&ni!-z@T5^0OXIgQh0WCFKtsvO6NV%av9@O)Efo zXq%YxJfOITwo$pGS-VvgY;``rYi&yoUe3kA2L|VmFHPBFdXyH~g#p%&?<2y1McD^U zbgfm3%vynOv6wXf!6k0Xw0y&PF|VH1;-D6 zJ5UABYV!5La)xymj9f;*FPXw5jfBcas`0h@J%8qfW+_zs261Ad696*&>cs!2H2v@a z@hMX#f2OsQ=q!4kknEZq{G@!oyqRNV$pA0{#$H>u>q$lvB62QW-#tO!*4*?*QlSy8U!ce;1$qr#GC;Zim!~3UnK4kk@euNdSC@ zSYx*|KI0>yYl_;)U~mNSGU4c&#A-K**1iB&RziWtU0kGlkxzo#Z4JuWEpj^^h&TKF zP5Rz5d^|>bLGE94Ey|&AG((Pmk^Q#U8bm2kw(-TNkfNL_Za?PuS_{vIvXi;NZpb1A zLt0>$jJ@2E3Y`IKqvD4MBKw%fl5%h~kS&Irc&}t`@w0J9nfjVncC9{(xqF2@t{QKk zYuK?>bRt-sq}`-}&2uJZ)ylKPP^@94|kfUMat{{-f1^?)I zXtXaFbfw>2X?>Q3ptD$2(c8PYlRG>hUqlqT7`fPx#)&2cYK$|2HzXP#F!1w{Tmi zm(sC@rz{B3pYmq^wXRr+c0LVfSLbp4CZV;vg9q?VGQhmCZU7GN#Ji<>=4Emh|H#>0 z3G$^S^?}zJ(IsiGZY(3NES{9hRv``^T$RyV{>{#5011A#%pI8euAU4gx*&&HP~R4) zji14qHNBGIA1Mftt4WP~M)T7#(EOlAGMX z!W;JJEgPl$u>_mDmQbPV792h@`3L~mmo5YQ02@62qntQn-LTYEGtOF7SGX#9(N#7} zePPN>!_5bt24cBCwxCCTl(K_oeeUEa#^oY9?5UP?)b6bHoQh80=tQ;u#w2_+;@$ra zm#V-$vvA1AWP?FED&lf%jZk&X+arl>7or|vcldU=+o<*F`2FU!ooh(W=nQpgJ1005 z@IaCQH!OTz>Av33^bET+z4HiAUi{yZReg8bD>{RC9pJvLZNYwz(^*q^ZcWX@lCvf8 z>4q}Vc5TBy*9u{pAP(S`9;J0%WKoMF`(0NGR=FDGIwxfwCJ`Fjvz%8j-`X5{;IY<^ ztc!MJs)sdXesgk1jmVb0$f2NjWn0c3u?D%Qd>E!g4sH?v{Qs`aOHBTSf_RVytdbpu|YyJUy989X_U4Q z*po7ayRV>DwfsG3I=>o0kdB-EdadI&<_>m`FjrPKEkY;5E6SICS z&H$4_^;+4vbncMh`FE$50g50OOuJ=FSy23ZqGiAj)G?YF6zr$Y_&H1(3&okEo@E1} zo+A|t#~`_i)F6|q;a8LAJNIO?2-)u*m8aUUa5fxVix4r@oGMq`YyIpsagFemM5zI~ z>PNpD!dF|dE(&vMNG}Sc4ph-?b;hbZ`vsBvL7_ku4Xjw-fY$Kko1J93Yi8QnTCM<0FfjW#=31|&ZbX%?=qkI?(YmIa(EhLmQOrR#zH=>x0N;vuW=fAR-B zOt%<5je7X&DjI%d9&U(>+fo@mgUWFU9CHsTX%719X7?Y{CdCQJtj0-eNs|GHTIRA> z=_(VF<#SrqG00@9ovn^*s>Vc+L@`y^dI+#8@jzBFfg}F~6pT9ex4I0-!6$Ds;bG98 z=kVP+GqQGVfs=8}2f3!W3KBJC9F_fY33HDim3m1=9fQlVwVHj`nNGKr%h8^YkxNqY z_?#goa>e-5Hv7|pr9AM3wdfxm;|K5{3A~|3Go=VJ==N>6s^(429q%c5Qj8^t8Xdjj9bD&*ql1x=B8OL`*ZLhpCN)07 z1nL*`W<6fS6}i~!u=t<>QQbZ;J^6?RkP+BIW<-OMCRd4~B~6;Mvl~<|EAAMzb>EV) z)q&lkJ_@(omeIKKFB5~7RIH8Rv$p_1QG0OTlKwAE$;ew~_j(r*4{9Awx{ouVQK8DJ z^V}xI@Bl=@2WCSr=`bwfp!%k(u@O_sb5`nxi9@_?xV5x+Pq>liFx4CF!tMPVkyL86gtlBzo^L_69x~*@>J004O*aniB)1RYWI-`3C>*1n+NOjBvaNuFPXoMuk5Bg`2t5KyJs!x|7zat{R8di(9n*1&VQu**dC-+7u| z2gg|04yNryu^SB6!_|lMDoeLCo%V#0_Gt_c#{tb>!?8ND$lVfHc9e*#9mR)3Pcf}_52&lwumCBi|#%GVmx&Lfs8N)t(UI0Gzi5zO^tMZ`_ z{y^oP$3<#9<-?N%pFt(;%PJ&obve|r%H1KB9dZT`8>+ak^H?m+dcQtRj!FETMubNB zsoqB3Z&Zy_ACNO8D?UI66DB{vx(wd6j2uX$)1{eTJ%Odh@730PG@RurXWzwToT;EV zth1p^GC*^+4Fk>u*-E;Fj^~##=rp1s1@o@}cF&~!fY_UvkMt*`zRYrW&{|n~MY){d zG6dVyGwdeK*thol07jooS5?z6_~d!WV%c!?Ecwu`Er1I>pr`ZlH&PKS7go8H1nc4M z>F}-kP+O9@)68bH;$r%Cl;PByHs6lnb!xz?b;g?d8BiVhlvo!X!djWJLqFFw3cvj?0hPPc+y&6fza^s++P`Be3MPNT=QRoV|D6WzjIUy3=#9 zps$n!!_PRP1s2sy6qG93Bd$s!QW~MJ*QOrR= zFW%o`Z0$$+mI2LpUfh{UGDO|3;niZV5VGOcMF2CJ28b+2Vs)E*Cf>F2t5_*n8U{-D zzgs~KnrMf1%RICy8rq6Vr0!w(tUnno@_>xaS}mX1ai+Xb1;V(YR>i3ur#Q9x`RvsJ)Siy{$EPEzh^0$475>3t_vSj|IJd_7Yu}NC}WFZJiP#0&_|1nqa5cE zV5@r+bP;u_yYojOnQ5aWI+d9&@_e;uVJXHF=VxK5daN(-LPEklrQ{F4t7{1XNn>h2B_@U2ZUAGnbdS5k^RtLw2~JfrveI zQrs(jCUd1#Yl+-aVNo(-coe(_V97-vZGV5;Cmfi`B-2Kqh zV9F&POQS&=FGCw*FeBcxUtWsMja-d{v~f(t&2l(i0nVR0B^`TdzpKt^?h6Z&~HaEM3eS? zs_mQ^Q19)(a{esuK;q1(Gc=kiUcww>pN0&yLi_g$)9d(eJ1Ll1~{d4w&dw)~9Ms}JOHTbw|?4_8S9Oc`6 zr%6Qnt;6A8sWk}^d`02JH(i17lLU& zb1i`~`EZAHrTSiMW+S|caXb)W9NeM|}LeRzPrzSb7n4~mDpHS(6s z19vuCNkMq5C*>dbO)4xM&alA;d|`T5DO%8^;17%JJn+4P(0?<1zZPDG-UlOOmEfVLHL5sR!#kwRRd#lU15rHuuxhhB%fSxV!+P^fC4vRaduZbx zRQ!I;Xsij)Ef`UI0Y&uVN$N7sA)bwk_VnfDpIM(A9}RXb@`G%DB0Z zfMt)t-n2k_;Rq#!y3a1{?%hZ}3ds7Lm!Ex{^ZGqD&fKDm`ym>5p4#V}Xd5+HeNb&s z=-a*{r!%@nb)mjb_%yHKm5%jEdT`#i)gzCKJwx+GetO@0QeY0fq1ziUgTHYuU7+n* zG!@gCx1;9+qXAX@FFs!L6xb&{#^ZiTrIGtJ0lmt-k&~(P|7CqDatmkUa(Ot*1W{re z695T60T8;3fbDjXiSvKpb>)adj{rofYz0tEidWUe#c9#B;?;wdC}N|cc(|2Jt}tF)frkD4jSidbl3do^B##i&n_f%G;7iHfEo5?_>+|j&6#yn( z298&jEMa=tmmSjaV&f(DB2nb+TyqZ;rlT-x9i5M{ze4O@tq_)_&<8y<#Qk|%&RyIp zN*!X388pj9Uw<*jhRFdT+_^Ghij(hY^{*|^lL4wIB+2+F7fukTtVMJruQAa}bS8d3 zAUJPkINOi&7Q0hawNv|+$Tix068IuHk}ic0PAp;Km54PM*dTvl^x0N~;u@O_O?g;g z=?9>!fw{b&KTF9m9V2N?ZZ2r&}@y=EFbkZ!m|VF|VszDrq^ zTKS4@w6{xDC3W~asGzt)h4j|E4e?!KvMmu<{K|xo-_`FqWZq83rSzeK)&_Bbf+MxP zIA(*#9XK;;RJ;Y#Q56W##$O*WdUhDy(W#g4Kw=4kmC1a%;o&XI!W*!9Yu@EdF8e&_ z+q!zWYsU+iiT7;M1i`MHGMB_|@C$F)Qn}F!FSl(3X zyIc2{?}=00rh7%r%JuKgHKDj`7o_s}gclut{(H zY3`$jtwd1VU{Yv3+r39i6Q-X59Ut}iQFxkv zd>TM^n??NUY1hd~-e6g4j7aT@z2o4Ff<{z-s0e?%BzcZ1x{sM)bcT}yHUEj9*lL!; zyK@(PL(Qctc8oy7`)*j92#yTgX=Tpz-RR*`)S_B_wzX}<(Z1HUXuFWOhf}2=ba8Eu zPnh#F${K0@ejEJzWnW=(H1IEQH{nBS)1C*3O@pkyHFpK9WhG4OH9OIu=eKs0;xc>9 z1abKRG1F7D0^`}k@zl|#Wy-RtpuD-b#e`P`g=atBr5QA!a5eN8dJ`E_{&Y==L3y)K zhf(}2ZpF5dI`&V=WGl_ZS#`r5zSSkbwf;LNiC4zIbtWQ+a2)#EM06t>@VV?~Sv)H) zRz+N?nFo-gx_^S|68AwYBZr2>G)l82eiS1TiXW9{c^wekI@y{#4oeKgH8PPmp%#ec zY=%{j&TMqroh{((#}MGyyz{GPQt(yS-#&{>d@AJwnKR2mupUS@_SHRh6AnYh^2nmj8UxBBv64O^!Y!j*XsZ|h%4(V} zY+=f5C6Idy@Nu9z47+B0)~vh&VGI5OsH>2et^%Ri1*Uu%>_!U6x==jyQ{VFv+jRZ? zeJb2DK1wA^`nc~z6zj zf&RB_LVEipa>Oaby4yU@S~DW=L-yOW?W^eTRH3I>_Dj@+W#gLk!Yz-0cqUA8JO&U+ zsoe3Wshf+g?Uk$!l~Z>^lKXY~Z^}jSh$@-kN6emv&a4J4siXA@8&|{Wp(AoV9%v3& z@>=ECAL=D28;m`x?O7Y-N)3A}j_r?xZ8rS)yc-lY0hl=9BXW7cw$Z6L1BVUnz!jox zk-V)~FKH3l4zRg>7{^F(YeU1i+bq`#SiwdjbRO^kMF$xFDHQoZ)mM| ziMjwNP=lEi4BIi9vjIVP#4`6=DyVHx?fi=tbtci~ZQYOTr)>1eqT2Bd0z#-NCxc6E zZQYIkQi}K+oxDArsBiVn;iQ~aIl45u2QBD4CGKb22CnFzz#0wcMAfvuwdG;Zd$Js| zbUMreT8QUN6{h4Ou$OmCBgdi-xz)%Whii+&8zvvy;FQ8X<2gb?#FTCyT2w$JLA`AO z=T@`fc(g7l({`KIpp!DKD$sM-QPb3Zd}gq-o7I#?Nir_D^UNfbNjZg*@iS6zXRI#WqQ)sjGLFH+TP`V42Y61$)r>8hK-npTJ-_H zA7XK&RD!j2K!hyMgX6c6%T=Mi0Nofpi;B7}Cy!M<`6h-l%UK`5x!Ie*_ZD`ho6kYl z>&Fl4L!%*ZU+&TMsyM_PxkPo}8o8Y6=ptM4vA)Ru^l19ob@Y61DFbBn1zI28dbvz^ zL@GyfN+}Oo#}R!O7G^L``g52!I7BUFt3)p6Bd=1lr?b*iL^ALez1#C-=pw>O;6Uqw zFKCcQT6NcqHCbX@H0iAd@qQZh5=^9VDP~5-^r9)aV zc18^|?Lr~ig_ubZtN`CmR;y7m3hFH-cg_S5Jsu_X`d)o+`cQKvyEa8Q-uIWR`hB!J zS3fr0_!nfO_wbAT-gI}R3IsFIC%Wc)jCMwXZBP5Hbl(|#HrfT@3XDS&d(`F<)j9Yj zrBbb|-3G9CJ-!Y3q}ypyX~%a)jYqdV>Xw7rt2Thu^8mk5;dC^$fUbNovhZ9zC7;@t zWn8I{2{Xj*TZAnm9;KDURR83Vhx@<-UU^lIzFEh!xJ3=t!h_m7T)MYvlmiz~xcElJ zGgk60^%;2!{(8}Ay6$vR-8W_cav6Wn{`CTIc7{Lm^xDi@X-kXu0vZJJfHkDxlG@Yg z^U*QNr)B9|wU&K$vX8M>LqlxNyo_ep;pG)q?$2DnzEpJU$a~fH4zN>ODW$0_a+j6d znzcW5%P?gzRKH-=WAsM~xAkw90Q2&Lo;!}n_WQwIby-fRf&Otj-31D1LhkAI$+^+} zK~236qiBUlEdMcTIGB4=+E9V=mKr~Ns(H-h@2P3U-!SbaS9c*XhLvD`I)h3Kn>G(Blr(|n8QJ31aB zKJz=MHVN73T9dOU>IVqpI90vK$xDq0SooDwUtOuR*J?86tji)ntqr^@%0Lb=?= zUt5NDfvcGET?Z%eyY75tzuR5Tq*-Qt{~;EdXi63oR~l)&kZ5Ct`?YbJ!@DBRCSKPo|=Zt=vn$>IS(^GGIE^1fh55SAYstwiti`nV{A)|}z zpyqu~a`4U*6gSUs4TX>`8CT{AwJ@jq&43*PjEufW@MKqyKg|fUTLLF?^e~?wC#3Wy zInV8)Dw#2**{$0ndZPOc^094kTI=;%9=daR(2NgC)@YC~%x%S|7 za9O)kihSfVVj)`pZp_d$(%g<6bmER^F`kJ)-$L0N2{IRcBM@bP>J%ng@ zlckF16-_UfLbdpt-wuprbNO$dQ)DAQ)1=ye4v1Mc6EA23JKHAs^a9=E?Ko6S;8;01 zE3ri`(c@M&sX-_3Hll|vJ$y3(ld|QJ^+Rap^IIQ!TXQ31?k8_DL1hjI9gQK-6?3$f zr+j5e6FRno0!T}UZu;dQNgBBSEk&*#?NxbQAvla`v4Iz-s(cUW{kqy@&d}mh1QA7> zU*&LByq1tH7$ckJM;NvLsKK%N#LO{>SvMzk%=Eat!q|!x&AQ)OY%a%EPp$ZzH0yQ_ zuu+AFl^}84P1c-QTh4oXpr}bFmCt6lWkU&7Z1Y)qM8?CXK;{3gQY0em4(cs*H>|rG zw3`ONU;%{x#3hq}-Jlm3UMGuZ4K4GW2Pdwqb261@Zly#h`t^H4cYz46f!^h5*uf)4 zCL7tt_gG27=cwpa9d1&FTECKDjM?2sMKEll&bHBUj1AGnxcD%|y@9N*aEf}M`1eDW zyEt{7Q7JWdS{OT{uXRcQJ|2}ut%RvzR53Pfp`bU@`aeM=^BlQHSDJY9G%X10u_DtS zJsIQ9+A_BS__Q?lT9K5WRh~5k6k9-!gO5VBW>^bz6gvzydD52(B5~bGs)%=wva((I zj&j5092+EbV;wp?b(z8H_`yU-59a6b;xRL1CuK@$r;z2kQ8BKI*^y@Co5NM!yhnA% za~U^Zo$Y4~{PlOts8Z^7Wr>z;jXt4-kU<6>uDNnklp3%c7S%d^Y4^Qa({;=eaCrFf zubwWvZP2?*3uvRJ#jIW*Nw`t^KK8QDg&3n3Y7;p%f86eK&m;a^4T-Dbd=`5L*cI@` zESq+1e;EoJ^ekFuuViMlZ{s8OrlWKtn?I8C!N5(`1NCswBW+JsoaJ?cX?MMy9~>n| zg5|BbQcCXPe_Ci^yCEoS8QF*k4xnfxw#n@>!i7*cMSF!Z8OmE9KxUPlDIS`C6pjwl zi$(KN!2}5 z3LmK16Db!6glx36_8Ki&L%e}S>Nn*e z1%#%o4^=yQzGO$9hw`<9IoHRtX?HoJTOmUo6rqk0nP#W>6GGYKFX!%eiu02%z07i! z0^D$uj+5?s&}=dJlb_-)oM%*F0$ulLu6(6yFdyuKE(l4D*x&lJ2>ZG9G%>u$_H4G5 zxkwYKW_x)`e{{rVhS^c6+U*I2LZb(D-X~`I+tXp|`U2dFs%e#C@QIj0SX0dynSP;H zAK_Wj3SeR#wXSGop{)l_#E(V1H0jAbu2ekmRvzFd*~ix@sd;Hl`)6gy@Y5VU$r*=P zMDyoYIp77u;g)9(i|9S?*hzQ8wLmRNv{#xOeP+x>zT|NV5_&0f)&95EjN z=PkRAloibltNdyclI29V;=s3=LEwR5rOwm7r3d^~gDCd}q?=$py`xQ|5h(QD+|MSV z_^e6BhFO5*KVsmnz6{6< z?-dQ#d@~x^ECN=w)z=D>(j~nuXaC}fk%2_>=-M(gvgm4j?YC;HlIq2&!T`&uSem8k z;w-npi|sEcEj8}$^@xvi50@ZA`h8v)P#C!a3x$rFCu}W|ChY6!DK>jSKlWc+?#Y@D z$J_mW7>-12!nJd7A~vp%Jt2j-u2!!zVROrLlPmQ{*6z)kT;6*dtzVJ*zHp`~3-oJM z?cZh!j*;Toc!+y3dsT8DwvkK$mIZ23?HiA~UT{(Z!BJQME>6({2y472Ey*ij`^&nA zRfm8=E$&p{*93edOA}rh+KB?>k@%6c44CNld^p(-sK@rL8PgD+EGG>~WG{^oBt19D zdUT5N{tQPZF$w>TW_cUooUMDLaP5ET?<>XFVTN=@GxpB(%7J@$k#;_DMu>u3#OAs- zuSk`Ho+*W%Gsy>DufdoY_Lz^DwnVN{z+%(PWiVyEF<9AKGu(_tqW`;C5(o{V0@x6b~%d_idMVjU_2 zTS8!=|4_g9amT0Jm(jPf1P+wK?Ph;)Yme@qqS|lfU<;e^c;EXP zhty+Jk*1MG&o<|cJmv&fqiRW^z0f#SlWwYg3|0;3Vsw0zB!z>^vmsi&Uo1$TT-$Hi{mU#-3dk~6yYZdH zw>a$kl3Uwa6Rg{I<${6gGRJ?Jm9#|ElP>P&Ws6J@fe_awv^6tXI!zcp8C60t&y2Ai zR%WbHmBT}o;kpFwMQAQPz`FHkA)Yj(=%{55-av&k-aIo!Hvd{t&#sbF{oiv}Z;onW z0m?;NXgLGC16f7gXDct%EM~8~RB#?r(UQrrxYjOs>l@5wzKDL^W}+rc<)a zJIx-`Ivt&Pv>Bow{4sLkprmSbx4Gw9dRln{`^c2B>oT5}jbfs}m?8}mL>y%7Y!5Tw829K=TH5vBa>lvMXhV>7(NLFsBolSx zJ@)XbUB?LrHJE9y(r*!;E5^rL7401PxC#2mcG&SaWiUI!^k|T%GX-W*adoMC+WO3( z&$*GTFRDd(8D^1H^p74HPhvv+_nfRK@vGZuAE#baTlJZ;+R>&6dop;t%EdpeB5$90 z)gO#4UOTeQ>^)MU_r9FF@PQ5rom`q24@E?Z$H&UusLyHv{cv;YQU{S#Aq4$;#9agd zTVc9%c|n&8LB;gw4y3C`;DAqa2;|{LIi%}(F#GZinCBhB*Ov8=u;uxGGeL;Rv0xrP z-otvSCFK^CXy*+%O^d~b705G!TH02on%aTHsqwE3jXS%Y}| zWmdECTXOI>T*KJ(ygq0D+UVOVpDW4Rlo%z>X|u`8v)Nz=G3Rigb~K69=oYR@bN194~`i=O&2% z|K*zgAL1{(REZXrH}Vp?lLF#x*m0$G}T>O}1`NGlVfsA{3!**eu*hXxSBh z1Z9_&uv@+391@xeAp+lA?%4FEtUs9d`zi>nF4a?^cXCq~^+_(ZWl6|AO>>vo>wS>) z8C3LBVzXBY+6a^!!Ren%yPP#}#=Ug46o<66vnd+hks;@oxyb`F%Uiu!h#Q4@kcU_0 zbizc3>S963Al-dWVs{(MXRrKl(~Ji>IsYb_k9Y_9eQbam)7avmfId& z*{+;IQr=<+Z-0&Mu1<|OuAhM~yuz}WE>s)sl;{JOLI%7|U{+Ld#l8NIZ04j>yHdPb z*V5k>c9-yhE#C#Z|BZtAkqAY52V94z%YA!O6i@hJkNY~N=bmKfo*s`E@2&|tnZyF} z;}h6UIlmK5yp^_pr+Aq7xAi0&n{~^|SNFy@kveo^=mg?H$t4t2(Q*xApW)hG-{HrW z7tXdR0r${_Zy|5?CB>#@c9%S6hYK zSUu&@nT}O&3DEle{H|x3UVUfU*eAietNgc<%@wPI)`+q_nON@8hGG5qbykhK-MNt1 zPQ!Zp-u$1l9)V(m=9A&X{0>K9SMMvOCM7BG1T$)23cVBrVDFL^YS5C>6a{w;p!NF_ z!&yO{sq*yTFY}s>M78)6*7s9d3jI*a%6lmE5$3(B~=MAx7vuvnJ21Sax#})iBwjGC?iu>5M{qP#v7jm!=@iUDEj|QVU1Z*d1q- zDxF=GtR(&>Zy`{&Zc13=kg-&t$H@&pQZ=kUl36Zv&9=y={6NJuE}~sm1@biQo|^fR zUaSK49vfNwS7up#>4j8<2Ge0}^8hx2i?eH6Mn3RSXcXvoAUmf{^T}VEk}=wUC1 zvW}n5DsT4iD_&8IW}v8-$pl*blg?i zc-CoO%>hS%CUQ*(arPNI^G1SS`!2Ro11_;yq}#N%lPSAFc4%Xxkya?JX7%Jv)EyFo3@xElTVOKTHrHPwxX zR1}2z1{BJL7ht`;8QOdlk^0(4g~@nHT`#9jq-jHRc1U{_Hmp~jIN>cF_Ao(ZW2V&w z7@0oytLXchZ5cf$P9ddm&-T$OK2j+i5gP713K- zWCw(JV}e17-A;CWs~(C}GdqaeTn*NpZHP8Fka=|63)yMP#A5u3czE>4zVERc(f16eP@1WGI-EO7yoaK^gbgdd_{ zT@=;FoIVn1~A`vB`Z;7k2(pulqT!dk%_sd8@UZ9SgoDD#L&JzpvLQMcpr5 zzF(Go8)E}>cWllXP&Rm;*g*GQd)~#U5mo&zK3@IJt~cFVeV-K_1tP&60E=~Kiw&a@ z>7jkydF0}jG|Ni#^^DVkU{B#u(J=WxO>%;(l_V!zLU*H;BkX^+w!i8XwwrZ>0C73S z31k2p+}wkRR!7;QIG-irYw>(HjCvKkx1;BoM2=zT{Q9z|I}z$=6}26B%)5yv)yYiC zrx7`O-=GP}jJd2kaF6@1koHo8`o`?ln%9!q51Tpr&7E`Qf^kv;mbf_Vu-6z#-y_Lg*(U8P4)?D0Th z+8p);vJG8*9Z`$y3@k?# zs#nLoiip_f73wsFO4MqnT#DmTHqc(|<;@YI6|vY{RBcRB&iIIm)l_sdRp zo{$}TXkp0eyaIUZTd@kcUm?wYklO5%)gCN#_D$sKIm}@$mp^m5qP-eav4(P^I*&Q! zJzxEoiFZrsa;*>X#>=n6dW$ z(%C9O`EA6nF8VA znbb;r&2e*(YoOwS7EQxNvE)qZ3Df9UrMquAf(7;KIL5orT_*+4K>9I1^`P6F?yJ@Y zWQSCXTXoW!gl9^(Lu!)%4%}V?O=w#WJDijkDfzPGkM{-lUUB!^$%ya@U0%KBnSYTp z-x{2bO>!EV{LQviHf+-p4Y!21-~%W2A27VbXyueLv%joCe(Q|dW5wygfL(mz_;kTS}}5jewA zmzY3hW0%qKq%ES(D*!g8jCcc7C;t77>3w^5L1yt8@WNWL6`2?TezIPwZx52Pa$oQ? zm1LmnCsY!8JQddOM==Uj^{v`}12o037J0YurLrPQzy0<1bEsO6q^I6u3f#O?^z4(p}#!&1OCUKE4v8X*Ul@B-ux9_F}rJsF9D5U=+ zLkn4IPuRPJZQsdnaFvg9ot6kSX#7Td%voFsTh~#vF+p&6Uxcx?wJbCG<`Q!KHC+uA zN_*?V73_WKZ?kwV=mlb(5t6ldu1D;(jq)!~WJasF2x3^7Fe(mD;)RXG;l%qUfS^9eI+v=UKrn^ZJo?+Ze2>ieYgToJ3S&4d?av<~|ob z@THiJ@el@{l;Q)bhbgI$t+%P~!#U^k*bqGpqN-L?JrArC1@v4xi_yG;4m=l1q+Kf= zJo;LWMho7q;KhDiYyLC2&$gVgsn+wIHU`6}2@P-QI1|m=nN7*Tt~XV*$tp($jKv>H}lqNRCCs-m|*htcvF{7cAv@+;RD_3FXzdWIRZa10N(++Ds0$op1 znzpku*=lRuJ+rbuQL6a#ink&-Bao7-3a}mmwtY`8^bXAYwpU|!Q7HvAKWtr$4TKfy z`P#=A8!AR@s^gl*8)qa8juswJ&u&y$TV1@=t+H!E%T&qbrjgg$2Gmj5x*0_FpSHv6 z9u9g5w;JvCFm$w0iTQ}A*MEDgYUzBB1bF-^KeDFmiGwMHbNsGX?D0k4HFG>_TVv8~ zoeVt#Fj^jyo0$<(W!F4XSVra+c86r0o%;@(E z5WP!mhcnb?H)XagOjbnNm09J9!>pxK{H^}PAHv5W0jH%_@izMEb?OR#idZA9D_cAI zoX56N5CC3+pF5O9Agz!@4Hr~38C$-SKSA7hNb0o2d82QXHSrj56jo3e|7+{MR45mX zZmQUtcvih7Vsf!X zoE!z-k@hF^fAOLZHY~KZ5=v&Gw2PA~Cq|sHTWVjOWlD@G@$$Tw^QFLd6q`UCqS1}w zhSc1Od2QU7EbHMJT#*jpPn)`)=aXE%JLC`K_W>h=QwE)ejfXTQJ1%+!1N8abh+kyy zN&`TP6Xm2@f3A>4ARe@RYl6GFF-(&F_EernOsjtEK~U!bV9c6O*{>puZs)LR+pY@o zI8WF~;|lxMsO&9Ft^Tv=6haA9Zx;XDM#X-LwfWn(mb5*a2kzeOjMTf^d8EVq=90X? zsr=2MSYl5>!?FZv|7O1YK9v@rg(#zO-f7TWX;+%EuB*LRDR_{Ma#kEBS2e+JLCWf+ znBX2#`C=D^M2y7h0{2kHE!rvk7dbID-X_{uz0KdKO1Og9L>GVm{AP0B{?3#fEr)p< z{;3JmE9vQdQPtT)O30|Xp}#E@U1+7kMW`(%C?`dRi%TLlHl5|Ez7};J(Dzjb@Pdtz zB6_P;@LfB2nTn^0BdL7OXVcm5Irsdn^l0n66~;R#JPx@n%vX4T;( zlRh17W)XpXeq-BrrR^;~6OAy5j#{|MAFsI(+)K3TZcos)b~{c(K?*f{Q!*nl z*f7h=QeqEkw{?E>eD3^T-yBr5F)9c2$}3DELuW-G@y2~`yN~~+z3pQf)<;eVSg+7w zDF9sQb|j9UhG&bPrUoEH1v0-=L>uGP9NbjIlNV)|iyIo+6FObT>Q%!0MB}GwazPQ; z7qGGpIk&!rmEIjK*F7|$KSo&#SjfKCO(PQ*iKzaVf#*s8DKiDzflbsB$n~+xiMNm_ zwB|5IY?{!k8q}7nFwOCYrCBs^EM`5zSny58-P5j7xd~KbWb=aL;*k3JTh2}ciTLiY z-RL@ey#VvH5aj+0@vX|NqZo7G{{S zjj_&HvSb@ewq#~(p|Vt`5Sc+GNl21pRy!F|M~e(OrAGqrq!H0~9`bXW1XhrI+!PJ=&la9{&7*xhSu_7Thy!w=&*AZi1Q%8bLa!Y4 ziZ_VdYY&C~sB8z0tCEc&=@^A6KQ8FY@WX@EAs@36R=1K`Df2^zXiUcf@NF?yAyvPu z32`71{>1e%izTaZ9*sR>!}JS@9er7sBloGKDUM5iyU&035-;+x$C2qc8nd^^` zcACK;PH7kNv`!>_l)>$9o0f1KbR1p$2VXMa&F5T%o!SO9ZMoa&cceD_p-p-IC_xMJ zItY2NPxi%u0nx-)_ND%TII-vps$z=S{eht+s~L;19ppBSl*ckFwLL|D4Pjqqy>Y|d zWZBP&2oE^(9C5UYuv30nH@7>5(y74 z7t3l&P^xfL#oZw5VzP1?I7V=vOaQE@0i1ql2e z-BSABdKHk4wHEfVt#4nS&OT*6629|;_i4=KaZY)@Ml79Jt?fS0W1D~qqNd-L1-=J| zx}~eX^*K{y-?5(|*U&p#@omHJ*za@s%6G^2Pg_&$n?WB+)spTVB8iajBq!n|JkRU? zs^3^`vO7n+UOc~&J3KZdQ=z(7we3#ZEjW7>BP~Ay?C|90kFImhM=(E%FwH{D`+iUz z_1LW7nVbI}Tu7#?9h;^0(aJUWft0_o-H>)nYB{sy3{O4{>kMa_mvc^BiHu}gw68rE zym-~mOmlL$M?f4Xehvz|hkRjBb6&nu8~qvG&2>VG2`jbo1%F{2SR8`DOxWmJr(4V zZLMkgxGTHQww2*EBlQo2J6oL-c!VlDu?&fb~f z(C7NvH!mn~J<~`_v{m7oVe?z1aYN52M<0@bs08+R1+7gjW5M7Ga7wygaXXsA&d`S{ zj(a)uW@p*MZ5fJoDw!`b0-Rh?&={+NS`e>fPjebbEs*rE{2*s-S?$}mEwMTZ>;OLi zu2d6>5oQ2H)lNgd=tFYvkF&mSJ`l4Xd|^*egvA}V&Q~Yuj<{KcvX8|RANc}l;cW`N zvuGKJ?9|!f!>Yx<5VNZWQ?i;N!?M!ngLWNQwj2>hmmDG9^j;RrOD-(d?26StdtkTB zsq(&G_F3uHBfUl?c;WFAF5zKZ)B%;O6S~A7cS7MxlVkRxB|qLXpi|L?qmZoq3CzCE zhB)jcm!;y)ngeosML4`?vqN>xIy-T@eoF8fXXq$M{k(Lve2LBo9v2RQ^WxZ3Y43UU_d$%%3M0mEWeZLeHEF+%QpNOU= z&D=g&bKw`yuLt_5O+s^wD=G0{m9^@_n`pCPOhVBgGUdTV>4I{7queQyY&}x+J2T9f zTJTeavdM%FANcpdiO-C~Ao^0{1j0hj?GMUJr`Uo5JvU?YkTtZi`m2B{b3X*gBFW6I zp+jQYP|a|7lC^FWNOA8?)^ivOElW?!`1=IeIu7awYEFdK(n9@0!CgT!vqh-csr^%T zxvw{X$`Yda%ez;%0TSn!z(b4y_k9v8H3vLdk&* zsKvQzW46v>I$@6xX=6`%H9xi1u=e^NyCh$dl?GN;1KOK?oChxFpcasgoQW_OgU8GV zQE-jEwpZOu=O|S0R((Cea{(pt=Yw*yf=GlYXaA;M8C#cQNdnvpfnPgBZXIM1y}B~F zHQ6ec&qsD-V)!YS74QA|>gWITZ(!llv{p7wK0k=qCp%$&Eo(P7VwY~w!HGQTjy)

    Vo6cQ$pA*5yBkR)IqT$Bo6pR^7jM&CfXg;hkb%K`KF^CRt`@nz; z*~Xq?@JTH}Hc%fs$)F71bVaZP-5^;JHEw_epg17A5GDD<|!J&@?<1vIa%t~rCxqaWjwV?Qyq^TZ%2+(+U2XTPVwEK zq_r^aCp7ky7gbInxYN8hs~-7KAqK7wo%^SWlk> z2j5ZA*@LdpAhRoHBYdRz@uq$3E10RB5qgEK6?qlUol^ZD7I*M|X z^HM$5>n*!+#U_qpX=c8dkl=dQp`5-!NYXPf`_XpV+J+=tSclxQ;ysvS82+=6JMIc! zA0u}dTcAOVO8zaWnY**D_>xnnRuZm z4zq8B{h6*cbd zAdjg_4<;gPcGvg=bgAj@uVD;>=VZMZUVTxaVQsW-o0i_9(!o|MYZA#CdxYS7lK;NP z4)HQ2yiYemL-Xmc*8nAT086x7jd1<7MBZFL(8Iy4>0;#QUjptk%t=5&ZyI9`C@Z2>A-9=`t;b{QM--+pBc}i<2(rted=JP& z#v$O^uW4wwRXLJ;M@wko8U$}3VuLK3uIDZv4A}Nu`M|aCldZ;tKW|DY$`d16K06(n z;l4LJmh?Vk{~RLwK%n&{%n?)5*FW2m0A(>9+;B`SJAU%k-z7%y#T--Kmu*V`Ea?z_ z_h7rh)y(Eb%!&cv=N7Cq6-U?tO4Dg1oCB6Y;y(GxZF# zzDn`jg1%6((oD`h44ZXr?)A@`kpSf*L|svMO3v?dvyr2As+b!XDL_AarIGYr=gApt zlC@R?EWGndcJs)*z3lKGcHgb3VrL#e;l>-oN2)arx79i*gy1CGO9!4$A32;farNp9 zozhz&EEr`(h|7dqSm@TQyt`$sQtO(BuJ7Gln?IuanMOb2K@ak}8cI~{j5Assp$#U` zGXY~|t-SO!-kw3x_Q}iwUcFR3S=DUSHF*kb8!+bD{PzhLQZr&skZ~Kp(8{bqod)1f zrd4N`OlBUngt2np4fuVL34J5K89{+w6LMJm3!*V2DCCVy%xfY5;+z7gQ{|ioq-T8P zKa_EqrkqRa`09y)m&(H5KR8B~{t%hre}9rZxYcqQx7T3K7cpBZgVgtascb`Sd}gc* z1(;@wWklS`PIBe<-7e=O8FhkyAThZkcmF-KnUoQcUylJ+%l`fAE1+!qqX8pZtg+_A zqa%QJbk8>WFoNTYc2_`PuVRulMl(;4@h(t5{i$@rxd(xR&+s+c+951YS1Frk)uU?Dr4!%Y^$KFlv2>Xu`**)dHw?Q`Z_{+eRV~Z!!@2T__F^5nFJh! za}nIw4;K;F9oA=hwu#>3bafTQ8fp>HV;Lva3g}#2lqm5VLt1n1x<_@MWU|-N-6UM_ zmOwT67hh;5_KQ)>{j@jnQ{Z1LSh=+{y8)Zofmatoi{GPaRrlJlSF;#x+KE}0`H3)K zXIPC}Lv4M8w#6?KPO-G0SColHm#mokYunhc<|d~jKXUbxckfi(3q1SM zN>Jk#uoqVCMvwVHs8pX(Mu~KMpX&tS-WM`-;!kJ|$wAQ8h7Q9c76CCuhg9kno6)Vk z6N%fwca{&MAr}$CodZsfr8NoiA2PNI+udvA_)b&0NdE!X_FVACG6Z6ae*Lljtomfd zzKqfmMA!skSZ3ipBQ69u@ssIVeFVONOv}HZ6=QEWd?1{{drHY2cS&=rw`?1il!4Ra zvW#bzj_@=~h;GMgU|it}I^jKGqTb7MOcqZ(Nlk;?3YxhXDb+QlsnfPAws=&nQ3@pLk>^v=Z6Fr5R3zoK3t4vO_k8BBa0)Icmy)0l}S5>dV z;Co1mz&Xg@jvOn{R0*oMQCR4y@I2h22z#dCzjM%lYxKJOzjLsD(yk!!s@D+J-*L+) zxE#$HSEPDxWJ_V`pQ=mi#))bnTlH0cS!Bole*;(d18z6s*cv;o&+d&=*8k(|*3=W( z2>U-8Qe(QY+tDdpU4{H#$`<-VBf3}fDfdnM$v+9=lo0GZIZ?S6xD*}z$@_!5*AH{t zP#9cvFGa}Qfm%#NL{2jse55wbXVrzJ6!o{zabC46=EA9N4<1gaA&QRh04|N*Em}2XIkC5L>VKaD0WeG`2$}@Q?W_Q?K;N8jC2Gv|SEjqO>C~yl+_Uyf*nT0ITs-9kZ z4iFT2K56*BQET?}*k0dTwq03Xft~NNJXABV*|S=Hcx;lg>Y$Q7OQHm2kzC^qtje=+ zE`fk8M&aN;GJUMo(yF-bzc8etqKujmuCDvRRl4qUCpnV5PMoOMQLwXP|66wTjvO?~ z9=bY*-2H8rq1kvl*JxkWGY2f-bg2ZOLGlN~PdjMV*NV$zAI5X$H`A8lB0C>;&-ar@ zKn^!G18>_-tzn-3?yfq9QG`Cp@`m&Lh!fJ++hD4oF4LWJWLHNh{3_VHh-J%c#$zj$ zfrk~Q(HJpo!nElA=Kc;Y7th-o#;E-C=mUUhs0G+MPsYt6fnZ7Z4b9lI=i&G?Yt~4>sU}wxzQC@WsSNOLJPfY>G@-l z$bQh9Jo0f>H6j4gsr@k|1U+D$>*Lk6IKa3RgFot zdtpG#=4eIO3o~SMj@rf&8R$as5;o>fIFP4Urv^Y~xvj62p|25rP3sS$_yKw}EyAK3qAe#u?T~_|$OG9- zehroEfvq<#L?q`}HaHCo0^g1!>Bk%k)>CY1iqyul|Ms1Nx?YKW)7Y_lqSSvGZ(R%ZX}T2d}0BzU$wZ!8>~g zT>mW-B(}9F%({~%9qJZeei$|$&(^vX-VQ;BwNgKtY&Po!HF*b8_g!XP;N*hqp*ps4 z^1(!8H1{(8JxC3Fycu_x?DX0|T+_|db4PbA}fF#|s;DV=x#pAX(ySQaQfpQM4 zfB9|s6XmHnDesIyi5e|8kAfqCx3b65y`)n8-yiV0x710*-Ae23PBWXW1`IG!R#sK` zjGaT2U?bX5eh}~XU)Ylp8;Vg1E%y!pUK}UxxIu{(O9^yLWcd(Kma*L%e{V+(#itx7 zP5?Oi!*q~&bjE`+&MMgXi;Mz_dl@ZKJ;CF{GqrYVL{0mRwMTf4d~>OBQzzaX^ACsj z0Ieqy(_88`p|6g@91)Fx^gF$T7kBfL+4ukDc1|(iBNJ9UDRG(tFO_smplwUxyVnV| zfd$}i2WwKQoV;?v-R~JjxC6ETW>x~=tj{AcILfGjb5cAXMNlVBGY#b=(oBn(NO!Z4 zNahFl-w|R=Ev8QV%d$w$)BQa#wF^&+)e(ok^c!tq8iA;DO2CXFGfHMN+ZWHS{%{DS z{RXV@1GF7XN~H{gp({0<--6ddnf!DH-}Dt9wZ;#CC%t1-tx-`ZX@@Hz-kKO4#e&F8 zhk3%?t*I{FSi9Ffpk>rV;*P8|f2DQt&#h3iFCvZ~Jd$ata!BS#r4%jf;jxgSGL{ar z5WQn&(mF#IBg!-f=CZE^UL0OqxFK+k+U@>OnwM;}==C^XZmxp_d3@RSG=YkmnX;>6 zUxdfr@LBALMS6R7sP3^L)2^fsCtfQWN>FCS>Aly`NLL&RT-`lM+hmUno-Ffm5 znHXG*NdSS}6$TF@ZY9#5>I~h?Bn&L8ol?4>c%7h&E;%lJedSUOi4&%b4w({T&RAp#I-6${IDZ4Z4=&9e9s3>{=Q3{323) z!BeitLMzs_wyZF#()UxM$Hm&WfYxqf62YbF|Sd-#P}p~vmVcI_S$*>kd7?- z_{m)t^4wJoWgv)er|Tw4!H>lHhF>GJiIj)e3{Hw1u0+BmE2B>aNWL)n5+5v zQ$gxQQlCZmCm*2cGU`yR!hN^AVKg02=XV8kTI_UHxVzl16V5fC>D1jKzYCrq_`5&M zs=nM(ZmPXj54BH=lp^aL+Se{7uZPzZHD9+GIHDsv5xy6*0gTkQx4JgKgD@hK95nb2)=Q zn-B9=ip}JTRg~J}Ca(I8BAwRkhg!>OLhhOh`#Jl`A`n4*QL`rfY)vx}-h4@`p=$1v zTGm$HgTxI)$lk8>L$7sX0DrDpUYF zP-zU{4MdP+IihmhKYjbh^tQ#08EOweRQKV$)Ic82SZNNoyfkNoz7aYJY0&h-q>&K zwTPNW-#C-MPn-s|Sey($a%c>CaQnIl)@i>}V235Eb(YoyLd>!2a@+nbyr@3-AUxtw zICjD_=GV$vfqd#A5xEj}o$YnYgoA5tU-fz1f1Hjjwm&j9!HlUA!<*l#b!T*4ZbnD$ zVK$aHbV&5q#shj@trk$#lXsD-x}>uoEaRZ1xfiaE&%VhNDK{YhCJXPo82l>?nju^4 ziJS4*b3RnH$T+?mduTJ%>L4DtbOF+dp#*d)TPLal`tj2dt_2N1UG;;u1}Xvrk|qaC z0;H1>*8~c^ER*9Y^t6oPx|)bs2sE0vXGLJ1K+6f|?sTW(?pd*qc=Hf!iM}O|Q>RWp zFD^*U(C9puwT}3$EcAj8abZdGWT6T+Mh_X%z&3i0R~Hy{upimz;aY&2s(~x#4;dOc zuJJJn2@RJqd*gPAu@Dz$MF~X4yUT!g>;rbai>EsM%a|8Q?H|Dt8%HQx^RYwohiOdn zo7|-ry5re1U!|Fr#cPOA>pz6UIA}5WB)T(PWvjp<{F1s4ZJjQqe$%6L13=fGtIULjy^kqC^NVSP6}&0dO}E zKuSnywK0$G4_Y7Z$hy{=on)ym5Aa`i8t5*@R5ol?ANP=L01-dgZEnPLAwN#P-n5Pk zW`~0R{p5LxWgDldzokw#eJEE=wLBW;FnB+x5pAX=q!VgR$&15#3f}g241%E4|r27(i<1Z_0lCm zb3AN_1`8$h37A6!rY{5)kFplvrrL0mR<3HQdhfdil-GC|B%&J54P~K^5u_bfr~9~x zO|ntfHIs^nKZ;$&|F)v@L=9V%?~TGwM6*{n3l8Ge4ITVP&x3Dr{*TNwPr&{>>!10P zyjz;jT0OomWOzONz|wPJ=SxAaTu`Lk;+OeRvU=LaDm5TTHh3xXB`Cm3F=P0_XTFzw zH;hr4tOF3u!HN-;cAKnV2zU7mpLR&#wcNuv-|yLG1Nitx`7Ohf7`w*5I?eLi#x2a~ z)Dc9~=9*|?8w1c&Ex4K&M`xFaJ0|R%=@ern_1e9;=*miHV_Nh-Q0tfFw&vsL6unPw zw-UMkZV6oXt?F~LI)bevgu7lY@!dv0S(ALp^C;r#0k2??`1f@-rWt#7l~8+; zI0rk)|I{;dKugH}Izx%JQ0Q#nE86*E938Q5X>OH}7+|$0M^4R!O2-ZqW_HmAF1`?7 zDa^~OGPyLsrbL>ST(13+lyzKm<1w`q;|cdtlQD+LT1Ki-M@nMX3m&cHIBXK=f8I~!s9hAS)$xLq@h)bmu#8E2f*cU;NYfd}!C z5xP>X9cg21`81tAWoQ|veUV%tC%8)Hr={OM^Jh-GBg_mn-^tovE@`i&75KY)gyE47 zQAz(0Z_94Rld)&4 zh-%r-n}PVBo~5nK*^;aaafMKLeWT(bD_vW;tY@Bh+}G3d+uD#P!1T1DB2cv{vrrxk zAo|Uhdc!^8bxdQz>@DZ;t@4=SgJI2#?RA>hTil;DY1Q+v=fGO4x6h22wIwwX>YT!> z!5QY=9xd(rT$%Nz_iJxIe{76B2V7uY^5fjeM}4)D*?MN@6mz0u4&ndFg}m<2`ruvF zCx9KD2yFkpN%r^WwSqAJd+m>i02^gyZGQ{2z;05;qFZUA&H1)!y|GAhkZol+<9bR* zLFj5em7V~|YuH-c)JLS5deec`dj(`&E6Bl2L?SjykxwK2;i}aCJbNsH~%`f6rSlKTE;jT%LXHb{araqu~H_ghhhXv%Y1u8%10?Z zsV!~Fy0IuDd*jxYk%wh>#3N-5Hd8rSkt;f_My363ABSRqmPT~z z1~u$jhd{LQ-5zc+cJUcMX%j}o?d}iL)y$#oij$q`&Q&`>hWa_IgC8j=*?;`ehZgOD zuoT1_Y87gp92L&$3D<#L=HxV2+?6`kpb1G&qFC!KSC7O-zWVz_7^!{ab+@cp(zlP^ zaQ_#xgBO3HQ=B}}5J9L`hebRPcOctrrLaqUA_?xi5c=B~_CG4q{SBiR} znc%2elP1zh;jtP`QBoH50uNUru_u*1C5Y`7RRnl2KmB7_1b4MW(IkrY%%SskD#d%| z=vm^IvGfCD^&QAEJe}F&CJ#wh`e94qJ>$KBs|)0lN7xjRikg080!-`9fJgMep%jX~ zZmuv+;Ty>nP(7!<>_yL>q;LUf!-sMIWu{+p`V;vp53m8Ngxe7d1g!+xRcd=)RV_02 zT-M8~1QG1w*dAA1jqwXf#0NIk#QWda-wwG~akyaUMCCTV(!ex7tX205BqpA?SWDnH zGS!r&g}s*DQseY@40sgdI@rWkYC|LJSu5DQK~hx-`#Ahb~iaU>*9dC+o+y ztTIa5O9kiOT2nYLNAyV}{oeOpLdaiLU}7t~M5?=kqCR$>bsfqsj#bBI%T?roO|hSnu66gC?;QLuZTXisB@rgum5Go}kq!`!^)dZTxy(we^dB zJ>Q<;S4MfP!1QhA+#iIROE@|@kOt-O2PFGQedCEMpISv8r)ykLsV84brJ^QHTnm=$ zW~b0*FKLHB?f?`Xr)cn^P1NTS*`!pWJ``H{NFksPIf!yX!&4q=rdsI^0Uh1ejw|z| z)66_*XaM>^h!8!5$?+3A>-%%+nJPZw&l?gZZ7T=Ro)XU_ZW+O?XXo6uPDSKzkX+YJ zQLdDQ$$XRtYkPth`#;$Cdq*ox1dB3bk;ZvZwPOXv-x=Az@eP`LX(@o06ly7knlO(f zhbOq$-q+nK_dnQ?P$|2R4GShoNqP`&&Hcc=r0^Y7v`mUH>PlSj&RglhV??5jIiIV) zPvQJj-n6~kpo+fFmF~mZifJ4TSD*n}Q`VQ5y~(_AN=M_CesfE>fy-R&l@6~OCN+1Y z?NXYtSuU@=;GS*P&20QIzj(KU*`^o;edu3)p!Kx^Cr)V0&d$pnV$AT-6hSxc%~+sT zR_ZDN3TA%yq5H>?6ay5jv9f{w^Pdh;&fCRBDCIhmzGr8vFTq%SUI7csmI})J_L0c( zaDVuehOwvn1L(VF;(Wy2)E6`JZuVqL8oS`Ta*p$B{h^sdrrc+{u*Osxd!Xp~_U=7nx4Iy}iPkDGvbSpg{jjz$ zFnFxVqHH9cMf}cu%Xy$E$xaM68S);%t+KRG|7J|gAN$&G<1Z&!Z#x;i*=|R6jc8Ks z#|rF2#R1oD`qn23=U4<68`>=-Z~>4p&xink^_#_UUkD`*Rw!_xx$8lI1NFC0^oRfl z)B75lnyUf4%-58FLvqz5w^^&|R*lt!tgeq5tf-EO{iF^6jHHsu@MOvP#;yur6izjo z&xZO9LN6DzP%uf01WVD-qyAC<(~az*x>}H5uv@SS($xDi)K3n`Q(d%*Dc72bq(^S0 z4bQjZAa#27010=OL;`NmVWA$mK>Prajs?WMrCoJpGi|^m{Q=YHWt%TB<}sb>$}1c2 z4TF`2AQ$ylPjwSdZ@AsrL!E;HgnZy%Y&F3ie*Uze4BwLW{No17sdgE)6dgWto7>wv zh<@Ng@qMT~sV3OA8H)Bg>TLplTaa~fod%Fh{^(gspxLF*lAxQijZKO0o#eFD9#GSq znr)-3PrtL^jlyUe(=6d|#3a|!=YonNJsBP1jMh+*$~ISDMx@AHKYvB5BinSjZTiGD(F6_F7u%ic#vGH$Qha2JsK9`;#Q;b4g z6C{5>DEV)FBh`hhkvndm%({Dy${86xaqut}rv!aIf8lFCb9m1$D;E=>%DZpq3*Gluo|na{U-%lAl|N9A;mdCsv?sRV0$dG0 z@paavgl|xvq!Dn$=?xt^9w zCd$`0&6ABSsC1THJ-q)kCEidd3v`}|RQd~au4C2s*ix@dsPYP70wLB5;Gb!wpr*@X z;g+eeyR51sk)7xr@VF-TPR%I;DqO7R3Qz8)lz?%o{h)p|{vWM%TudNQ@Wa)I40w9; zDuW>VBxSbSq=*~a@iUW~xx)(x+Z?mk@$FtWcwONZd;fQ~!c!k+R(|k=Etdl>Zs#kR zz|6O5*3S7-;g1FSswI2t8nua?`3n< z_W%C@>!lF5xe3|>+$C7>O`@AFUZZlUY+L>MP~^^1M&a~dL(j(7r+U<+7%1E-GJr7L|5(=6j+GF_K26pZJ;rdELjITh1eoJ zb4di`x;XRNEF~98PaVKRW_m+{+#)hEzxs02-fd(iwg7fSu{zfLlj zhf>RoqWQP+TTi4Oo$4`sZf1TimA4}c{FdV}T6MRtToAYX99ql$~^QMa*uU8ht@(959FVE1npH#B~s*1| zmG+{pGo$6q{&+21xQDd#+&dnsf~=E?2Cx2Z9huPbc7$#L`JC|!pJD;iMP--t|6T}F z`w}Nto;U_f=KC`zO+I?dt0n%PNd++S&LLUd%YUC36)Gf|P`v`F?O?^&f-pDSGV9s) zitUtK|B`oBxzR2P3K?w>N-n7I6J(KGQ}A50VLxk;nxb}!1&>)ME@`&Tp)=B?x>4d! zYgunZfq{y2W5W!GC)p!+nGEWKgklvBGx*uH1)EtNnLp9g{fd)LEFO3p@%1kmQkDbPdQ(}+8);37Ms$zS*k7%wAytRqw}++SPp@1V zGEJc7{_JEL4bxAWR-3ZoJ*NHYmG4vjJ2QW?s=Q~DHM5Qt0%9lfTewOf%F47c*7}&MJA7>{`EB^{obdi!_us4Zv4y!m*R~( z3*KK^QD~mPH5%r#F!+L3({S3axAQLTBIpa(1cfoarjRiMJwM8z;Z}*KQ49LMpE>4{ z?gz1A^`nZ!y6p$SYRhfaKhv{0Kxs-f=>6s@0NJp@T^zI6tL_TWR*+$=hL|x#<1ecaWVpvNWz5;I00SOsf1%e_? zI?t|i0?&sQgEL9d!EBS&ekKNJl^Xb5v+~-9{o(+>*4=*CL^65W9;)4DPjiy_$9n(` zj^Y7)jRd$|1Zes{27JthY6rt`fNjQ)9#MUOCYtb^guN*4`YJVnQuIYDEvgBGICB|16+C|7Mc;#m2b5qu0^@iaQ~WwabZR zSVAn95@Lu#R385>of=*;5EScWx}Gn$8uqLgM$qo`wys;AUBDF&tKne{jC zf@~sPtqu$ATSM27pg?MmX)cEN?QJU(GT>fP{H4SE9KoQ!o4V9ZZG!!A30OR*TBEO= za2y$F%V2f_w-LwP~lTP-&Cg_<#0v)tavBURE!&l)j^R>7{u* zGB*19K4sbo9wdXqM5Bv>zLkDb6-fVRHLFwo zXiC(4gr_yTSZn|IV}!+y`jhyh#VY^n&j5DR_&D>`4v|i*bkG?X7E^XT95S!h-H3Pv zyMqqDbgSlNoaj7Qv$|5^x6!b%3NpAcMck+Y+}YnZ%Oq%-*iM}V(-;Di&6 zn^-28ZVwL5`hK?XLzkezF0n%883SqcACPbfjP#trYuETen~KDi^E{yglU7f@d&i?0Oz2g)zm=disY=>P6=N=nd&e<=xMUzX zzgQ(oOJRfo*3lA8uI-Q8I=hAuetdsq%v>{OV24|p;?v%OETzlxBZM`N3Hj5|+A+-4 z{oJmXy6vL%9Wh`Cka@ZyT*ST6_PUL{_1nEES26b~$;^O;+YM}NFBY+sYK%t2gpk$xg@LQyH#e$v*XmD_UddhS_Kk< zTK95P=kb(hYDW}DD|%WZ&*!+p=M=Bdw+FdBRm_3|9|Qw=TVhR6rf!CZqVjd7%s&o3 z@YD2MhzB$GOPbWPbneKZL;82_xhCo8<67CccZJ_y4HH`RdmYVm0OZ_r?~o9&n)K7z zjFcj!x;1h6ElBt&8~rotxjeg(?9(-GR0cW<75y~WPmsX8cV;AEB-~&(j#$1H1iUwH zWzLh&?Ak|5U1cR*QL;U_!XGx9@G%t*LvGw{dxV!A?m0Yzk`8QZ@9Cv%5q$&h3=e5W z4vXH#yqM>A_h)@N67wU=V@Kun#mxAhmX}-7E#dC-Xbx_Dy|Yz*uJigv+yVN2+p7*v z<&9IbH_nbNsyIq%2i7xRtaO?|;NM~YP>FB=JJFD<7JQy)DH9pdeo$}H>8JdETDelL z@BPkcBVd$0nr3*;>g)D;)oO+$^{^mGNw+1EHJ3J$^1VQ2Uw=iWvRNwcWk=E>dyB`y zESlvF9hZ)SF7&M?q7I|JJp!*F6|a~-to?Lpz}v{MX}AW7Ho?24{$+CL^JS-a{O~ z!z)&j{U3B?n8Q;s&Qwg&aZ+D--_CpJ)^P;g#;S%SjYwXbwSkh=ruPL7w7d9wBb;EO zE=^(f8NM=<8cj8V*HIoAz*SXV;ozbgWa1+*pndijvj3n^y4_4p#zH~HoH#l8&^&3>6#`zLW?*gbMWFXL?h8ZYy9O_ zuWgIUBhwsnnZ0|8A{$R(Ds)uHq}+pyRk_C()Kff+$!eO=#oIY%0_`vSuCv7Sn(rA@ z`fvIB)lx`EVAreOPEgYov09w2bHY=2y@*Gc?R4P<)$Gxrj-#63cz4cj^{851hh30g zT~{%{U;yOzU>&lpP02t3fHLa%^Skc0mOuAMOG&-L@_VatEO4`_EA9se2X0sS_>A#4 zH3)2=5MRsVlR7?}eo$y_<$g`Iu?l%|555{F-<~oRM>NPeyGeVeQ9{rH;Ydo`2_q;} z>=axQ`>~sUx!}{@NDqh5=UF%M*8J-9@y37yqK{C$2yzkb#?_ z>I;M>u|n~_vHkKkBwGDH6g}y<#Tv%9KMy@Xzaqs3iDng~in5^8-zq;w{_=#6G;M=h z%p9#C{!{a3OEUW#8M;KY_k<^Z#XH{7J*{O!;benT>&ZhdhGSeMU|Z1XhelVyDIaB; z+H(|#3^|)uF{kXkw#=xU@|h>tM4m3gLu{m26&Lq z^J>J9Qkg}9(v_WK-dhdF48DeCT^;~3TLT_!sZ^4AOEWHuvp*Bk@555haGrzNl_~z% zX@?V%KAjNVX7XV**ac}#kEb}=&C3Z2Gg1Dy^GAeHo>w}-K5Bu`H!4*Z9GT%f;;f?* zX2@Rc(CqThi)~(q7er_j>G=#ds!E zENKBQcoTS1_M8MO2P?p;11Z^eG<&)DR$~+?Z{UO)=8TLJ^doJk+g`rkRp^un6Jwa{jBIFc9czV>4T!uXb6*-?3hYoPR=!L)wtmQ=W@{8AZB$o9oz$ z_KDJzG9;_;6WsWOY*NUFXD}@>Bm^?1qZVVKZu>{3h?4k(|MLX@xpaLkcj!Gl7S1{E z;pV%{iCu?8!^57eVFEsNRDa$;wN|Jp9TqtTCU4cyxHQlR4xL5Ke$aaaXZ4WTKU5!e-?F?a-ADu+yviOSQ^ z8dbTJAiTPRy8o+W>aTFxdNSg{ZJT+o@J(t}8Rw{Jgd?Zp3=R^ma9d@%- zY`7w1hIdX_pbsnneOK26wO80Sy27P6;*S(t)xa&hF~eq@5?w)Ge`OX_sqC@U>Tr3N zrjB&-G+y8A>12Q>_iRWUXN_C`xRtq*;4;t*rA{x@;*32wR>y358w0PMdIDQa8Tqx} zn%nTM{0mA8<_hbXLuZ($w~gIae4n^cP;v+K1Y@NLd3T93Q%4f0vWJMr--FMh8m`X1 zW2|p4YV%#Z(3a3kQ0ytB%Jd&S^MIUsgoqHVBexzZV1c*nq@<>q?HB1i{UTp;A-(8z zp+gxT0BEVo^cK0IM}BZtfJ7;=PFfR+%6n-!L$5$SQa%v)Y$a%rXME0Mx^eH-Rss2(GN^DPqZ!2WhqwaBD;5&uG>ZvRj|q@%a`2MhsqiT< z@zLMD*E^2dl*7WBQ?ry?Ek38Q|J8~y0?C12Y+2GkCaKytIoxxm#$FJG2YL0e_xW`g zKJ|V!r@H^W!SANf7^6Y@fdROjZODFzbmbTHSc%e8W1hbb9wp-tatAOCDD)N zi|T9u@mO9=fbwJ^rRAzw_^zMc#vC+g>FW6yBL2=96QSBD+@Q*wg|SV zS^$4>PLbfW^lIv`NpdjQy$`;!QM&)4k~M?nkgFxYR5@8#Im>Dj_*YKhbx^~Ab7Das{dXJ8ZcpvROlo| z>(&uyxu1A`JGrx*5bX|RGyD>#?bQ(ItWWzOT9RM%nPc`W+CU;X?={15?L8Y~|SLIz(mGBgl^nkMkh#;A{v{_jWbh^D~{7ca_M zgXCiz!k$9S53v5Q2jM>=eMV-_h6wgZXhzbuQXtfdlVN|9Q*u+VpSl30-jb_>sHHP; zAU6Cu6$PR~-|&?|4A91^#5BB34D_k~RFmQYOw4{zQQov%(D>7-^7Eho;jO3^P$?F5 zQCWF{J_dS^0*3KWtw^|eBJ9au?*zHyzdsD4Yc7DkRDR)2C@9f^RSF-*B=%(b>2Mw( zR#(0ok(?dd#^DKT!zaqrOPIOAL97di|9<7JI_tMg)b^G91CIv=I~j0S&{H|*Rmp`T zde8t1H|uLPZ@mAQdO>@-fkl+$!eOUHRRLc`0DksHqpm6soT?;KRR(XWQ%!8gi>Lk{ zPv;)a^#A|=oi{eNIqZO#Lk>9~a?UoV=-|*%&Xc54IVH+rC(NOYP6`=$r+Q10N)nqx zrc{d#(rFGAQ7skAX}{O|bA7MhKmK-IF0beF`FPy#x0}0Qm7p$Ej@f|t1Pn@N z`AX&p*;Jfh=83ZVH;utN+~3-x>Y+jp zB=SL;{$S23qd0_0TULO;YfVvf);>uOPJBpmHC>S8&Wivfseak4T<1-0hJ#GKa+Os} z-kTojBljL;mjAVWRn?OuR+>}@9(=T`=^t2Eo~e32iiojHO-9n|2gR#mSFhT(xlUUo z77G3Ly+qs6PEJ`v>u$imSuZd4F(;2N@0FLlBeLiExfw8h^a5$6JMb6c@F4WI3*B7A zY-tPw4YL$AyX~a9NcFhmKc%BjFv-bZqi-h&Pn;F>Mpt{V4*4%U0|+9qDPIpuGgZZ_ zwrnZH%r?&^mZT&rao&EX+{#%=$0ns}L_+4LlE^4D$L7g}hcf?O`VOsiPI2=49iivq8~*7@xMz97Gm$ttt{pB1!I_r#~V zY_MHg|4L-|iHY5iz<9hDguqNpgER z(irH?dc9iT520PNSn&DI=^;220|H^qjp+lNjlp}L zt2FR?en1^|xsTGEjd)5-(d~Hj?(-Tu0`1gFsaJ0&77euK-{T|p@vfxzHR-Jr^JGLr z{R+g+5rz>U!3&tm!{3|hIk!#e+&b=Vr6O{1Y|mPJ(dvR^G>h`^0AfodnOEwrW1CBw zH8`EgNA_j!-iKG@f4`Rh4MxAq2k@KW{slkvmab?be*5H27JcH~TOpoX*Obdr1QA*( znLwvlcOcwzr7kv!0s!X7J7Xc;vw9BSr5;`}OMNjbIf&TcZMvIWV!J+3yY&QHhHYOq z8QVdXr2X16_4Ls&lBs9U_IvV55H%M&89f2d5>S@pnny;pEkYFIwz#aDI)2#jbp)vF zd_gU7|Ca|}eh5x!_8=`BQ%IAjj?DFKABb9{1ff69vnWo|jmQdCo(v5L88)zPf>vqy zl~tEouq}tZqQd2**W0U{E!axk1dZkc#NF9F=b zmtX3M*ro-4za4O^fJeY~{PLF@c$3P~HlSdo*HVssd!}3b8hol^6>pd1&tLW0@U3cJ z_A(<>7E#9xNFCET^r>8Y(Kx@Cs$XrSe45q?QK|lz_|NJs#97e{Eih0%Ai5*Q#GY(v zCG9Zj{9Bx{*|`yz89^i4bMhIg=)@YenKh9y<2o+IO@H%G58+C0z>SaCQtk{vlBzU# zPYw?gb` zt+nWcwrQvKT1|3=KZFPNGKxS{Fwu5a-!c^zVY~QgF%Y2}AU2={OSeD#!7Q@-0KQ>M zghm_~5Yrq{^LM-^a}g_#4(5|Scr8B`vxiT2E2UZ|*p66F8k2sn&6xa&JgOBmMjZ6# zCJg9cNJ%Q1a`;-EUF)zHb1$7mgkly0qgadMhKaUXdM2?oCz^|my1Vz@5Ej{WD3(OR zeuR=2I9nG`zWbcYVYwA4Ru+3fZG-BmwFY7ee=DshGWzw`u6W4@BK=UyZ^X8x1pu{P zo*#{NgELLcS7@%}vzjAUR`NgpEQw;hc89*T^Q5IPkVT>ZN+#SrOQtt=#SbyupKWs# zIQb)C$`0zT9)Ld;=zYQV5t$8a%g?Oa?ev}NQko5yKyLSDo)4|Z@O+q*s$z`EGo8Jl zwFDn7{VK zbs6WTHpd9KeZ+q-34kUw8X8t`RN{>8XM(1@cje_ePWHk^!jY9ha&+5Qa%L~y=uY&h zErNT97e2cv>iW6Jgy%Ze+VPRR(ouALKGiT5HKCWd)^Yq}PSc;G7~E0X18~*wLP;c( zvRQ-m4%6}T40zvnmG$=#e;qKs4;2{G&un54z>}Z;W9O+7%e9iRxt89~a*Q66MwQ4K zgm&R<5&kh#e>h68TZ;xq$J=4|>&0=Gk>{)%1TtT{FF!h|d=`M7ANxWz`sg{k4*H0d z(e!C3+C>15&gpi4j3S5T?O)Gz3bLhQttVVVDT~YJ0x{A9mxQlywtmW5(SPUlIy_5( zu+=Z>M7*k>3rfX)(u|2wP>KMT4yp8=Ob@T4&_`28S!kfa>&{o+G2G@fJfSNl>i{|< zAGo1mcTO>^hiP*bpA@;;&^=(K+r;KPe@GKL*yQd|!@kj)XAO=81*Um68w?tx`A$r9 zp|(SB6U&mMhqx1(;*s@Mjy*CU{HP~>qac&`gYZo{u_o%jzuM-3!4s#~DaZ&F%JaX) zk}H(n<(>sXuNeUED@D)?{x4hI?DlihQ~n|K+(X@xlfY)X?Sx=7HJP|eR1l&5X4L1* zgl|oSbmZ!pIsa7b|BcCk#F)UhtSZ~oY`f@e%*ZC<-RKZclcTubIw#)IlLcG)R~2iR z;54Ao57({q4N!Vz6<|9g>f3YZYK4ecPY+f1boazaho+g=H^_`FgS5}!Q{gtX%b5Mi zoX_EOSF41m$I((U=G}YfzAyu~oG;(cNT!*h6WNJTdM|3>Rde%yf4LzdBgHC4KR(b2 zc}hx!_Cl?t|4ct=b04XEcqGLmoim;@%vUmm+Hd&+8w`XLidM1W^;wP=ZM~-FIsuC9 zfUrY-sYxxmg6wcqu6GT)OGl?1aOx%Kz#jZ98Q2?x$kptj_)@eTom7f65-YSGv8tMp zM?d9E`s&Kfeimbz;Mo|-6K|W8=qDQKfra?NowT$f<$6eW)sNvX-Y;6ukoY$|;$Znp zRK$e#R@$#AasC|}gDQ8`HdL48@7{n*}^Bn2}&ip|;f_ z+q}b3QKOrsA8VYVn0;{G0ANvI0^bAc;A`|>Jv~;Cx?XnYkItY#@K{$_Sa2bz;S<<4 z7v`YC9_YJTDelU{_ghrfY!X`da=lP*3;%mBlhNWt?&{~?MgQ`7HZieA1}DaBk&RW( zDNQi)g=M31FYd>m$5gcx#avCsPS(WHuEvM8kd4v&Sk-{u?t>z|3pq^-73F-ublaZ6 zV!9NQ9`7Kdj8wPnTT@T&vOO`O=NoRd$EXn_{I{67k(5MSu*j@z4Sc-#yQ+1=X_TIg z6lk)>K%TO;sTG<{s9&|c!S~#Vb^gv>{pAtkcfa$*&|*_W6lWUn)1k>f-|a+)wdQ|o z8_U_I^$Yff_1NNC_$f@Pi8-`gNoCG)V2ZNf)Hn!vA&&K&`GDNFgf)qtLV0omcSqBB z4`PP8={l}7fTpT0xyq>SC_AcVAf{z9Fy@8@Pa!mwrd~Z+uY=!(o0cg3SZdq*$=7GQ z8cltpULZqhyckE_qS&PHmjx*d%9faDMt8^OMU_Mb>5lq?9v>K44E~s?)6)OMzirr+P_ys5MJ%CT(!WSr=!+vde60+;^MGTV8PGjQshTCa?1Rs@Oa z$SSF+K0VE$LpO;5)t-`flqt`e9bNxmEHo80_!zqBag^W>ac1G&#~hotno&7RvC=%N zmhsQgP-}<=!8;;$8PN*RPQ=sWuWyi^j{Rqv?+5Es z8*XImkR0M;6cz=(v6i4th?asPFDbdfac_brO;%Whmp5ywAiVDdiPmnIoa-NsoE{~f zJ#|AABRuu7oP`ed05tTng(v8y$Y8wRuEKue#fF=f0nyIi1{WFvEQ8{GV9=IFY zt^0K~PkG*Yi<~_ypeNaSSe?!-yFoP|NLH4iQ(t~2)6br%%_kRQUCFqXa?R9Z`pG0O zK#7G2m-7UMx?so>)B7OmVA(!ub=L`lD~O3 zz40t0>b-IVMGTA3Kzw|PaL`IVVrei(OXmCViZQa63B?kB>xlqYKdpC8d95%9`ma?j z&g6pva@uN3zn9d>83I}c^BL~C@ln|O5O-Ix7Zh<&RSE9r>@|kkNBK_Ov>G~0$K6(l zd|9c?mkQ2xv)!@GaK%yyosZl`^j!Ki^_G~YaCS`Y>Y)RKq;RDdH8 zaW^~%;Q98cJCtXvS_;teL7FdOGG;RmWoVI5)32RXshd_inscQy8f{0{2V?boUx+q{ zhY5x~-qBj?KiCvzUehylxDFV8Nu>Z4XiQgUOwwC|Qzzpyz(zvUOZd~hI8BPNx_Z}c z>9I1r*52YKCd^h~QUH3w%w3%seiE;7BOP&>gwO^$Pjm&c#KbSv!*ENsa9XMM$)394 z5W)GPp4HEM*W5paznf9_*1P7dO$(O)7Ilmh@ZG@0d7sp(@RW8M)X$F4SYEmzLt{v% z-FWb~b*reeqr#Mk0`R|xcU8C}jzN4A` z(mQQLVA@~yIWI@L^#?%JTv=4;wfRp_Ih4D&I&)BhGX0@Iuxy6#i^9AJK}4Yk#2~5? z5N%MHj-!i(TNNt`ui_%$*z)H+wr@}Wi>ov^l4?Pw)puvDa7n+8uPk|l1Z;kSOR$`nh83*|v2+ zI4A!I?DFc*az^@do;!l|ovufJQ{*&hvg6G`4D`5g86~~^I7brCSirXJC$%0?8tKbD z*hsgywwrC;#rgAGxS#)UboAFlh5o^x3P1J!|AMR)E%03`2cFy6*4%l&-C1+=AE^B6 zZiM%uZu(#Q5Y=C}RWBS6H?dlcv{e+R_LYURqkSbeFald0{X_l;@#m{Kn2${D{q%%A zt5=Epe+WTsndB6Jb@g2Do~E|pnf>0!Eacs(YYZ$#lS#S;uk!uSUWxnl2Q7TN9!HR5 z*JZ3QPHzs0B^1*_c$k!?V`oSyv_?iOB@V3qK@!Wo;AN9FhB~0pO)l{J#3dXqjYkB0 z@-Bz|aWlkc_g#ZEmJX!y7`6cU#;45EWq^l=WwMyGGJHfs-He8aZW+YKXMgu?s=AT;9!-F%e6kH)^8c}t6Z zG)-aN7p_@MBguFI72CP8!Xd+pVGnohk|J!>zI~*=P}UKgIBfxeRn?)YAA|4fj$|+q z-BkJZ#{eAor7ctYcTTCvDw5z}rr!@x_8E0R&zG5@-=HTncz9xM!^H=(gAdQhT6t4rjNkakVvl%Lwv3=di7AI$rPOAlL}w0mi-Y zHM%WEgUBROkZZoYQDsM0$|qS^%XAJvtoi&W4Aa>?kqb*t%tJq&_GMl8S%rd!T0p`E z@)MjprZ?Wanm?6mSq_b`%$>0YOWCIsnA0p|puYMKN{WOC>KZWq;~Gd-vaLLMY#Y*Ar)~b} zKO3FTj47LEqVMqoS%$9fSWu-dNwey@!0d-xPBOv-OS76ronx+yl3^Kb-rlU}lk5#R z)NlP)1J{K5Nfu!)dxdq+1_z9`NjdBQf_JAUX=nI&SUaM*h+oa?KU`;p@ebS_7}a6m zdfaaJu8GHwS;v+wuE4q1-}Uae%p@ooL2IibBb6RO=&;OFrNsacBV0Uowc9!T*%&TNR39|FL?9Ki4Id-g;r3A$MHWba0~9o zuP@dZ9pS0p<$`(wyX&H6J4r_EHkTS~mqBP!p}C2hNxGj-%kiae`B*8O34C)Hpr7|# zTu9NcL7mwppI)pF@YBkR_=etK-&u422crl^KNPcC0eQC1l3m}Z5LX$tQiwzZKKx?_^YLN_Z4oN%}C8w))gZo|GA-4m^E zMj%4Le zMtcEtLv?#z8zL8GJm~FXbvFYvuQh(b?l8T{2 zKr~vKzDpndx})}bJ#zD`t$}4Ev_69WGx0756U$aDTFxKo6N3T|V4C>(ZA$y>aBH_- zYSXM$!5@e|&H{HoLD(V*snJuus^V~2>-E3a^3MWXk9UmAEzCqvZvYdk03`0jB!X|>Q@oWiCTM}W7F zpR(w_^2w@D%``N9%cOB@+WvoztG(w80WGZjRO=z3rJrxvA=fEaS`m1(NI_y~TJPUd zo9|}xg=Bm1p8_|OR^c_~nnTe>^=+5fZX~m-as9Sky>kpN%*Z; z#Exjl_1;Nf^V^vxHiUF4P3)IETpjY5)EuH}w-fpG#`*Mo);dHK2o-@!|2?6L7{1*x zJFA5OB4AM+o{fv}Kfg-7y!?WS=^@_A7O+s~%XL>opaUhGC-C{_OzqRzS@6TcwwxuS za5sauHU?{dC~TRFZjxgwdM$utnHzuHE30TOr~J}|eaMoJN^QA<`m3i7HC?cy?8^%}CgKI@ z{Pgi%iK79{bc!Rs5Y#o5OFAb+@6&mO--9q@+#TC4^79^MHyc3Hs6%^obv7 ztbAt=i-6jal%*{@t@cjzw0KeCjfep)c&^{!z89z7v4M1*#p?sh3EzTKk|+rPdClRj zuo3F3nLit3hLFuZP?TQ;Z&nv|{h&HzEUkY88dI8_u+R{yc7-;7n4yM%9=7R~1ArRTvx*h|7^dD~vIYL?( zqq;w|k^Xc94*nIFoxTR2K4!_;FSR6Hw8}WClFqPyu;AZprGG3D2B6t}86=Z0^uUVR zSbYK8VJxNDupm%>OL4i+2H}SI; zb^r7jGw3|MCg1=pp-IJotprZ#eH;GZfh0yYARW7OcGo2O6)i1O;T2kZDM}v`)?{wH zX+)`Nxbd^`ks8CvZCiimo^5T!Jv{r6mQ<8IJNoQ!6i*eGfL^1>Ug%6W_=O zupETN(XdvPl;OZh&1-_Kvo!g*lbE7Dc}Hp30GLa|H#Q9L-Bm+*x$P)EylqlB_1l`s zg>A7|4q^Oevz;wU6u|Vl7V_T+fMRKo8!`O|aWH>{9f?H`b+KR3;8hUuL-0N?CZV#% z+CXFM%N`~WY&#Erd~I^)H#K#7lwfCOW~Kt%7#_Msx&Br3UV9A}{&HY7wfn%!GZj}} zmz$bN9rY&8-Js?$%JUBg3!G&aMoOvyK;-gr1&f>>VH?lTMRotqL|6?@NVyi*pxoVKr9#Yxe_yqpXb!$m#e-FF!8MiXBCpRdt9#*9zUx1Dj3=7pEF1t!yseXIf z+-0Y!eC^)eo>7LSwI$MOp)?RW!M4Kf@%}2`;4fyr_IMy{E`Y|77QP=jjq+&>lm12g zOYwDOUR@}8No#qvDy`Sg^=hmM{kY@-{eP$G>HWG|ef%I;KjkL#l%cdAA-JFrGKp)ts}n>3WP4@6*|Yk=S^B)wp!A7o4PF zx+WUBMXIgDRAomf;9EpuRR3#*Eh3mimbX$4x&@W98Udu1-YaVkceSBKCeD16gtI5% zdU^e}SE}i%`4`*3C%q87^OUcT;21HxOjmro zX)B&};XFTJc{j`~j;q}Z@^}tQ=bFpw)Dvr=n_KLtj3er!Ix9#Hpr zm_yZ=Jx;%4iA~O?hnL}tdW2_!X$j@iT89L(FL*zo?!!|Q$Xyh>LE*ZP0j_fCUhOmQ zonge~=kD)Nq09*I)c3AS9E-p$Zz42I*8Z=x3F3t6xm3B~F2X^(@d*K0d#) znj@f0P*~Pc6ccD6G*Ah4@7LpVC77s=%xFG;TWtEmZ`Jfs!G$v8;cOYZU4h%WtNaal z1r!K9?c}s4J@u=`@Hz?Slm7KxlS&yBCok1fmO~+#T>7?M!vFhB4AMSFTj!5$Ige`P ztG+;TK5riGa!Y)>NR3s0lhb1SK4;QdCqCFH(-ss$RfkTx?wOEBd%9}kMli^&P3m%K zJ7$shm)5ytmeV(F)6%&p$jy{)W(ZW)OR^oxv9SlPRM=N`rsHOIZXhh#3c!b? zObfHuAjN{$gSV>w5wiU6X$YN+vtV-zA;@|B`)y{F_S2;wCx%{T05ZM^+R6eC4yLK+*dl!>8&Ao8nxx( zcP1NYR0C^g*riHlm~cVqEoVDCwAI#z&yPWAipgjiHAQTUqkS3iXlqbc+4ARgsz zfugHQjCuN+k62x&|7=Nb1hl*BR-0PCjg9(0qUGvQV2xO4lTohbm^5jGfIbc99KB6$ zi{cf~%P%_lnYlfr1pA%1FPa& zxU>A_q{#`|Y=h|0l5#by#ONKob*1PG zu=bVbkjMt)5xs<)>H~%64u2Rw;$nYt`Y63f`DT@|_-XEH+&#QP1K%DV5$OI~ax(&w@` zR<8K*^$`Q|uj4xr`gOg}e|X@JE;|9KvXEn5RHYJ9XV(%ZyIK1x`XdnP57pou0P9%I zGu-}B%Nku{n|<7;=k`4=uzfb=m%{;?+*oLA;gdrNuXR&sH!N22GS8SL2BU0`TSk9U zxns^Pi0~_{bc}vUHer3U{ZA?Mqk{rCFRPN_0fspW;UZUD1cI|nwmneHa=>?RxC|eq znOMgcHp`Det_L^skiWJ)0C3dZHwKp%iAl@mCW#`g1mQ^~=gh?t@L=P@A87dx08Kcy z0WARDedZ@}pf6qCYSo%{r>RjkVcz;Pf$;zh@nAs??sd1#2DkgGrG2yBRN7*sE^~Nr z95ehiIs1@mp3@CH`VEyHh~@%{;F50R-&>*dqD9*NUC#-DY{Uur>v(oR8jQT!%AiL! zt1|I>5Gz!lk+(KsT(zco2vqLv+hZ>6cW|^8tLpOr^u%7tnJ$Wx zp|#@@@*A4#zh~J7D2gw2HL~98@0j8SFR1LbTp^-`+12GH1eaominH(R&%N{N;F4T%wV4)>o*1^#ByG81#9gB=wadN9aDMXO{&3 znvu*3tlA9=)X9S0Q1|_jN$b+kZH}I%A?!UDnrLqs>Q**KJ+nkYkfvOv0qZ<0czwWY zZ}5unE6Nvf`qrxz!(5mtP+osXfqE%KChs_Jq`3zbqJMz+*8nEIOI0HoP%|+DjZ$u1 zI!uB7MSS0om<*&u_d&RLTMS(5EAyi-s0Ep6huDH!&dakGt2g!ACzj~`J-yD?PtNY< z;|VutIh==%v_r_nTzvKj)i9NUbeQT@d9S0C49!f@Fx;;k=iOlio^cc`(!GF6S*1c$ z^mXOZ+zZ*sV`1~pZ)GknA`6F&G)i85_jn~SY?55!u-Xly)1Fj3veM+vN*2+Qm zG_}qa`!Q6vFb9ym2t#{A-#hSv?n{uKX!ZmwL@NgLQ*kNQGEc9Qb`Z{^TzSgD?quak zt>D##N^J;CX4~qZlRx!(-c$Z0w|A0tv*PxU;HSADL-Ga1Ru?gOA1?R*pVYj)nP*cg zOjETB)854aN45-TUL761$&3B(z~1H`2S7+h;#)m^*L>RezxVI{)_i7|AJ#~@8`bY= zdMY()3&|?_TXD$OBU>K$=DFFlNJOh(RsM!fHd_c6W9!krUvFc1cFI2Z%c|R@wVevd z9Hl)9?D_^fdjfyke8G^ax3bbT@Btc zZi$L+;_4;9&V{8f0W-Q`u{z2b`W;Knz(Gjet)F!Y!*rx|xJ)}e>Tyq)!iMXc&W*p~$f9&*_F$yQBq zSW}o8Ns!gmDbZaMb4YvanBV*ywXPZ+CPe+|tFS&yUipQxXTAr8qm;vB$nTGt3mia4 z^;7Tk!&ya?ez?F#-kxAsdx zA=K9r4v+pM7A_n0xcSP*HH2k&L3Y=HRrsm=vKG$g!%KG3xI@aeW^mp9*m`vY0^#e)@;%WE&nL(KMel4HT!PVJ z0u)de)jN~L1<{_1C6T{uaFB-dfG*0BB#Pq~dN@q~Iq{kPeU%qXgBdEK7CcUUcb~9g zA8fth7M2O3fyuDn#|Z~X1kPs;sF#EbIaQZ-;1b*gFb{CY+xj{8+p%CAN)YQAi3Y|NhhjP(Do2srK?)=9?v z6Y6ne_NPyu`k8nh3Y_A)54nVhX7Es-^`yaS3GGEm^_7D{wk_; z3J#pXsX)QXQ@p(iHEj!cfgPSeuM?NV%*jpura|AwyFVEPc~2&xRMe+?b~n8iF+NHLxHS*3vr z#i3k%u!K%e2pjV(@f5dsVeB3pZ=lPO4LWnQ}!8S+LS zUEl#$H*rG7xglGk@fY`G)4qBJd-OoIgvi@7=W|)-bCq=Smg0A+ag4HQfoHi@4*j6p z+AsEc{&?$=xq#B8J}P{acn3CEz-*e%>0D-7K=Lg~Wv8}-BClim)i(*VLH3EyvGz@h z*;TC}{8IeeMk|BR@DOc{p4)a!6(_p`*a0|wh0O7u`P3fZ4>-EG4EM|ug-}vfZRHI@_hUzhcRY92SNxk6^o>C535>YgH zx2p^F>fB<9LjfQ*vf2hPa$ktdZS=nCwWxZa>8D1b07|D(L!f%legQvJ3%?XV*Dhkr3*%FLt0rU zhd5@?XK>FQmUgty@bjW6B@3((t@mk;_`!2Y188%86Ah__jqDVIHpB`4`G>M`#cR-1 z>@N1)bOjWo+EP%4&q8T5AlsT$wLUlbu!HJtg~q$cif+O!$Y$1OCBI^?A!yHAjDkG+ zG&he5ozS5Ba$ybca;@3O4J^VG+gMf6U5R<25;~yzYEG}xRq#5Jpw%|Gcvy?*l%F&VY=aRY#uaR`_SVvqvO{ly;(93ydg9_>7(B81!w7J zZ$B^6yA8ROXXmj4h})Ftier=~Iq?;c=k0r#b3wu^a?s-J{NWywk;yrm7VA0I=(mb5 zLANoOckU9E?@}Kol~oTev`3*gvTyahb>jcj26W=qQB*rrQ=y$u)qqv0^9-~v!OO`L z2m>a)%<=2w;|HzcNOs21;3qvGx9iv!ALWlxF5pu9 ze$6XMDq-)CZw1gFs>}IrRBM6>!{9}G1sJ4t!>gqhHN%9-1Xbkz#FTyy=P6=(cG5oztKUFIzE$;5%?|Sn>Sx#nB>N zg*`0*i`>r*Ct|+du(1bZ7i;=K49N%876C&{wC{`>3HeGQg2Ug_xCk0{I`ll^R=U)J1Y zxh`YhLR{nO-cKn;O?sA1YH+=)jKoFI=R`m&m#A9qrz_o=f(%oDHLzt zR%zJp{22f+JA8Ee68uN1XqB#CgygP;m3VdDx-`)9EPe>8S& zdH<^CgMiovAcj@;l|D(ITQKA_*jRUu->t^qTJ86puSvJCq0b{5`2Yt46^23GQcpFY z47~TQ?&_mO&?J!p=*LWXK=VHf8)CetL}{z0OE=Dojvf51LFN;6)EsbHO*07%(y1Fe zqjKoC?LCcy_>H&KJ~6uY>%2bWu@)5Myx_j{H?J@H6&WNeo#6(ZcMd z!BKDWJ8bx8G!K@lkyZ07G2Yb8--hP(VpmI?sy%kUM7mbVs7l6NgeyN&Y8LQ!%2l%T z)f&~G@`;_Jp}*IkTu*(F&fKm&(?g3HSduM)gLfD%vIcvZHt4GvYKG!X8D_zlPWQ|? zt$!7XRgOwqm*(u}9K4@)(GrRv^f~@916@CCJV5AVJB5E9FA5=B6eT6)YPPvFHFc*Q zwDPmOiiR>ipQ>o2t*oc+!Y+e$Nebeqr9cmN237@Bzuv1Jp%p5nezH=!@Ar}N50NnG zA8X^3WwP6TO*~#YUBW*Q*9i*T|A`g3_9-Nlm=N4!Ej6$j_H@tiXXM?WQoep{R}9GD z*Jom5;`T_{RwG^jz;sP>j#prrSI47sr>f4dsA)O;E~~&nexw2*{xrXZG&y{V;h)^13T1 z=iAeDm1)eS;ttaw^0Sws$@)kRVakTSsH+Bap?}oWYjr@a?r46>$HbyR#N>_)g_2fw zvGnHNpz6`yuotub-Z)^$_e}Q1y6agJoG#n?m&ti3GiR};bLpcpwfLt$s{N8g;B^PF zS~Z!%AsjUmeESUrBFJTC3jZynzeX9>8}fIJdAif)ficyB%E*yU!H~jvm~wD6e_wTn zA|`roUOD<}pA8hraR#meiY0izP0ok#J<<5*hpf-82Kwt+R6I%l?l1fl@xH0AfpGAo;boRTa8|p(|Md#0EQ)}anKFRV zGqN~V3tT`36G9@_13`yrm};72-z&b-YTnu<;lKaTv)p8{J=DoJV{v!vXa+>-2Fl%5DU}G0!`=g>YrKzYN=emtg z2(F$|*_YC{(;`JF+KIlI8~BK(Zc@%x!ztVPz%SOs#Dc2VfJ4QIix?JMQ=*ciU^YfC zV=qb(4&~NfNU^=x-b&jO}Sp`k#Qo5qEV}3cmA!ax8dXrZIuxo7m%FQ*3 z)n6qBd=Smi-=iT`2;ZtJ?D%npSNPqz@;h7c#U zVtpkqm1!pwQuC>3U3i<82VMClT<446>(s}bL=+pth~Y+BBBENApXb|MDYPjA@3*al zoG7vp5y^IJbt_YG&DD$GGE+g(3I*H)GJg!T{7@(SLloqsHHJoV@`~4&7&2vLFH?1Y z7WkEUlgLL`Rn@QaJlIhOg2@W{06m${BEDuD2Z)sLc5h7jeyJx+cUwMA(Lp|e!+6Nmsi9lbft$!PUyjJ?jv2XEDMeg`?x{ZT!!fo?}I`MUUwiRLv z%MjP%YKuLCxlu@Y9W^=>qIVg5ppR2AEcD5iRvAfs&6`|K#_wf?2#l>~Cfxi^tr|R= z+k)2LPwywcC;{CAy*i03+07hsNyY02f!*>!(1epee&|Uu3Y*eIqU!JU>u6@7!gzXkek zzLIb0%eixeei5>u_v)@3tBxq-)R&VLH3LuW>}h=$X$OzVuKvblB!p zsSb6croMD7u%sRk!`OSqbrt9nI}wO`YKS2b7yb}*>Xdb zCzj4jo1MpMJ_nVh3058gTA^mY6=M<{!yT*Wao}`&c3lQMhyj(wux2Ae=<}bPMx2ki ze#({79jJeRCpH`Gxy@CyTUB#N$@VJjyI%7U3fg|CC*p$IIcwQJ>J8b9o{DIa&7S8D zzzW{g`1^E8we$ODD(+^S;UNXd57bH!E`uFkl_y=7?51FwYO20-4?WUrUkz_y^!l}Y zk`so4Q@X)diJ5sdHk}&f8W_MN ztH|p+>|rmkhQta}Rd?L?E^X|L<$lG})u5I=yNw1dQqhebnIb0EuRwMQN$&pT#0}Ks zR1Nmg8oLvnzdl+24y}B{@b7;Q%DCdZc38mS564*<+rI@)LX`N%vVz@yD$<=%*`g;g zux5r^X%E~b@i=k4GX>p=j65~}#p$zwa}Z$RH7mBhD1+NKs^5x6Cq^$nQ()xahhx<8 zWWlGV-iSndvQ4vA;b>=5We6&)L1@W67V+s6aiWT#)V6_CQDVg9lEmQ2QQi-4w=Dzf zBaOsezpG>GOOpXV<8$Jj+!T4^FP}7=74=lg2FgG<|HBVzaA1Vd+=TycVb^CT{sj|Q zK8VKd%&wZybIcGaB0WtL3&vKDbnf2 zrhoKfh;Hn$3FL^V3ZR4>tnSo*v{hoTHm+_f;3fV@ixKo6`_KHe)6i16=ML{Qd`fFe z3}HpT8kc|Q3{JL9SJ?*m-qz@_HFWIc@C!!Uuz*z0A{Dc085?z`1gviu$eP43}x z$+{jnA{jXS#69OGOL*H!V(KazqFZdxg1Ri$KE$1~pxe|0`Sv0E*OVa#r5DQ(TsrUA z{pUVkeYOLn?i&BxM7(a3WIF3F6D?Q~rUBdQzbfHN$goUgic>uJYO77Eq4JhG=16B0 zbJ=D%uW-J)rheL%_EmOQxD}oIH~5!*a=D$?jkg*TKG*Nk(GXzIc>o@@3iEqDF#4j} zm~X`7PxNG@1oV|CRXUBW_JFyO|7g%A=ClpFZ=JIy(N3v1G$dd;75t8k+V|GyqLdRX zkF|vKUBlnshjDJH{fyK}Q%h9_vL5q>k|fiAJ4py7TI<66;R*9S3a`KeOe>ECEZWEK z@jSG(Qh{ApC#6EITLvKiLM&miGz*N^q4R8DO683SWFa;Q>k(Z8`2o$$Z9>O$BE)v# z5D+?GGtNi%9zK&nu({LPaBV0=rHoB*&)0C!VB#zw`8QMb;3U9v~jd6Fl^lT(x5ksTwYMuM2ARG=9C(U4>Fz%u$e|i)Ls~7qC^CoMUGI zP&IPcB0k8@6PX-MSNfV`=gCn&r0P(>YIcqfHc0TqReFpjoj9#3(&hZ)e`QU`F{TR_ ztkqJ?*MNLfN2XajcnHkkFO0eS_k!l9SG>m0g3TT<%TQtqS-741Pg@*JLFR#qF?IiY zcI)ah2~K|DgS$_ZwyDPT9MpaPJ}+hzbgxKIf74vBKcqB)bmqNxlG-K7y2NiUHcT6} zA?t6yNW@+yn;I0iteL)fz9^Oqz{jvxamK~4E-nkf=<=hulX&Gr4{g}ICdw7qcJTHw zPOR4zDWb3petrtvc*6Pd%Qw4(*PXmyBS&-*cbr7uwnbM%GuvE3L{u5fQ5=gSHiMN% zI_22!WYPRjW}qK(%@VTOVF`O1IrxEnFl2Pk7uK_C<|0FaFpi%o1h>kuuR58QE6~+W z!(CK~Sq^0=x_*TX#(Z5fA`Q@%=iO3BJczPXm!SJ$ zBYxGR{r7%J?zkH|zcd_q8vW7pog6#D-OHUoC*Id>xPW)PiAATxSEzj^#!J~teXs}W zq&moilX2n|8;*Za`Ar-9THQ8enW7(XEkS8B#4 zg)9JCGI;NRWESD5t9;bu#T1}&_!i@vZUH_XFp!9(&#?Bz0Tj9q&WJK@wFmFr_57zf z-3yjYwb(d}lQyw?S`npRg^d3QNm@fOY~MCE3O{Iic?Ci{lokg(X#Dk}w94T*SKv0^ zFIyM}uSG!(4X27`_?vw)p!qRf_n1ji!V;tPJip|5 zrq_;8{nG(7V0L4A)fT7O*t&^f7fG7{?BMd44ye$K}^FARW*wfVYb*7q0k#UFZ4xf|n?C^t=}^}~c+ z%#qfv4hrsaUMVYty89RG%CgG7E4wf9x*o|&Sm~f-?DwX=yAu8}G*Yqqh?QYNqSlBK zeFqm{aU+0oMZ3yW9e|jyD@q(y(UMH%$TgS*1#5!g&=yL@4>nfAa@`$wcE`YW1^6i6 z9G+Txc1WIh9-e%u=%(xN)ye%vKJuhv#I!Y(LS2Xabyd@7oe32sQGMKlA zxh{WbF0 zqOD}X*?*I7zoewrPr`en~=2T8|2qD{?Qb}}_$fi{)2}vs1!D&S` zhe`(-mn*uit{SN*7sJv>R|`c_Mk=BjsT{Z8`}6yLzyG?K+iq`r@AY~=UysNAKA!(6 zDdzMByVsng=(QWW+86_I&a*kYxoXCY<7(Rxi^U5AN$rNV&4Iqc->SllH2($6@V!MVlb9fug&W363hx{I9m>w1U$4K zQjWToLI?Pm%2Iy5Fo&048~)67J3>(@b*57e816i;|8?t*wDDVq=@tDC)&2*K+paI@ zq<>jS_dNJm2z^weJw}*)lF?HXitR^Vzw>)R`_n#HLO=2kU>X)3AdD<|aiKmOzb1}> z=~w*xk)%8_Y*B77r*BOB43u|-KaS8fw4|ivy}W<2=5?@#(#F3XmBg{cSzopd#fg3S}no710z)<6FLGu~evkd9T*Ml*vWzNWWTH(|E4JB+yRe%!sR zeZf9uzx$o9Pt16_yBxhoot5@vQ=Dy~CWEUc@4o+IH`*z?o`RoW8PCDM#TW>CW=dLI zJlqzB2KeAZ&^OS7_cYKOZ5_PrPxxVA*p=T4j$>PQm~D({m=`Dr0XMlzop+-TvH1ti zyHEz2h^TB>rf$sdk~% zVKR*Ls8ELx#`3X-V~qRaUT|v%Z(&ZutTs@CCy`}ND4$n&_hxCf`(eKDc+ENqM~1rA zkcFV9|7mJ>gLwd&p+-WD+~Qx_K?e$BS=9@!f=`t^4_+JT(W9biy8C}5%7kuVH<1+H zahF*5^oY70f=Hw$V@DtP}s6E=OC4 zYuHP;Ta8ShpXS)j32ZRg8+}Ii7#?qpC0R^stveEOLhnXFp}vmSN}y(R%$32%uRfF5dcfLj$iLojYZ|7{>#slA zo8z=M%m*9=a%8*%)Qv;Zkf=BQwI=fQHU$Q+JqpGQazoOJ*mP?0Pek3yV`&};MPsi< z6EOIXB-6Vl2A%j&AY*<~1Kg3GXM$h*m4_4Khmo&e!w;7T5^h7BT(cZA0=|&>L!id6 z%Y{r)arp=t5X-rf8H2qV(w*<`y2T^o+NK(SbW0$<)>)qU2puwkK;p0f3t&+|SmeXF zz;^(Q^b}!g#2;dT4_sSb_?g8&cMf{;zJoqzi%#ER4L={l&hKLU)w<(t+uLf*NHQ7| z7k;Ebcd%n0DCYSy&}18b)T}~l%$#;Xw}-GcdkwYzInLd9@H_Zt9^*f@z#IhHZ7LkP z&EaHc_i{t3(Wz~o>1^wU*Lyi2$I(Tcdp;@6`#m?X1>->mHV1u-Qjq(Q#(z=2ApBp6 zpVjS1!O#7~3JjB}p8E|5lx;&bx>=VcE*m2?dK{A)XVk75RBf4VT?INGHLgR*expzT z?fO4o%#QZj=W6_iup$stTPpA`DFkO+bfwB1By#%ZPj^W|M0B?|HkRb1w^j4&nKNQ@ zD_I*z6>ZX(;tsi5{Re_g9~Q&V;xy{BTtKf7i6YP&o{?H|$bj&qeyNX!m6uiHrM_~O{+ z#I}lT`LGH)1#=xGjz#J9qR;xEY<-7DnCp!B3zw@Jm}%%}D(L{MeY0LSi$ifcO{3B9 zb{JGOu0YRcsPm%f}mtV+vN!F=)@bRG*xmLxLCS9-X z`|yCtanZY=z$!{Oexw#u?mh!ZhCN#Sm;bwWJW>mRxV>R85biZ{kog}lw5i*Z%lkoO z1?koqB?0Bz3`ghO#t=xulsj)XAc-^|p5O+4-V-ThuY=Ou{J?kZ1J5{7ko81JI$j4F zuXQfZ?Bq%9J_i*V;3U}{1qzzBiHuNKXN#H_IrLP{V{JH#qJ=|}9I>3wqpikAuz@x^ z5~`Q^1ZSlWTqN~gj~IKxmnWp$afhD>Fldk#k~03J*q*(6qbc)3?`64dT7`XE+C|s+ zWTOZA&}7Fpe;`EsEOyKRyQIb}{##k)fNj#uu6jSfUC{ec6{Hw-Od%w;I5pO_;zIOQU+q`MzS6qFsAFn~@T>Gq9!2gyXlm+CFX|9hlOEc`+)*$1a=TpmKno}cKib29=8N?Qo2h2Sa&&aa zFCF5g;fnl!HOx($p)vFJvKLQ5yHKd8gQ!@nTnZQ(V5Ee_xt}Ib;I-p{J_EP7VkYNk zfSJK0yZYOKzwG!=Vgv3rpZ;OolLn6Q!4xr$Sn@{=-u`S&an(z2U!V?dYn=l)V%UWl zv%(t#Vq0%L?-h#hEzqf4&m$K31agZ2yPgYm8XOxP<;D>M>+_WeMMJYOQ zF$TZQ8mMLH!B2=Y`530hwk22x8~`%t)=O{(EqGjjKMJsT%wLVgn^YmJo)y&ZT71_( ztXw(&JysT%=~Qn*Xn}0ny?4((|B1V8cU-`Zdf6ZCBbbRLG_H0u&?_$yn(ogqol06I zo;(DM-SaUcCe^%iY3$6t=T76xM02HKpLh$1iCB}dAY_I`=_G!-IC+^Am>qHVG_tIw zlh>?7?*Aek?g?@Vz^mI{vjXpd{tlkHX)!4~LI%LK38ql!$SZ-@R?2*#-6`TYg7F`? zTs24TspiivisJHg4;Q}T1`Z={YSoXETswb~hcZ7S9Jl7$z(vM7gy5tFk17ZJCL|U*)7o9}=jOTk#W;O>Fir$J8c$v&YKkI+wDE2S&G zfzq@6-Tjy3s0+F@%$Thr9SN1^X@Fk#l%7pZg+|TqbxIgn?eJAl1gCCRx%s<+yfTSE z?UVE}kH|cbTL{*@sHyOJHp74f$B7grIg2)usyr z*C;59n+|pcl^}v$yV^C_b}|cXRD-APys^J(w`hbUwtYv?8p^3Ke7Lhd>2g*U)GHKc z>dUiDm{8i(3Gk0?>e|kXRs~h;QVx=Cm2|i~Z$02Tp=b3-_rfmWFQ-*)@J{ShsO3@+ z{5Y)$@97m2Sm{G6>21}9m4*CoqQ0i&5%{n2DGu}Ia?;_dowvKXAYWT(v?XxaS?z<> z%bFLwCek=vWdjbGg!S};4tojiFR-ge_H_;x-eW3)U%{rAJK)gny_D?L=H@F0T{P|=4 zTjgte**~I8>uwL#sFxiwAAVvr(gMk~U?jS;)#a)!3px~fA(9whVM-QhovP9ZGm ze((bl>TJ()MgxP2X<6x8m$br_@R?^?z;?Gd3OvOhGY%Bl(MPrgN*xO#*YF71=|cj8 zwCrBQ)m^GNlZQLQ-B5E^#Jh-{1&2zMmBA-1USflzS7#UUE|btY9?E0rhzXcSRL-h- z2AqUmt34Bp*ckoPiD0704sqRsuf|Y3zB3kf!ffrVUv60%5@YUuOmc`nO=NDD2)egiYCHXE#mR(< zw>Y0=+?y2B-O@=v>>36i=pt8+k9-{IIEYyBE9U9Zi?ueYh1h~|{>i!bm_B$3<(PPK zmT}<22hYCAPWHZxdGt>FUz8PHDs00*f#D+?0>?_f$8eNo&zpy5bQuifm1;}&AMvBH zvR(QNX=4z2!7Jed#M^yLCfYU%+u>N@;5tOm@tb@*syVyLn&?&X!{) z<^OKq9=ufqe(PWR0w9x!04!O1GzSwUwX(4cxpbm$H&N(#UEa8!czM6#ZY%s2)Uj&p zGv|q7CSO=gO`b2mKAFVU5zo&0a4sml9aT^Az6U<_OyHZ$tV@?)J+qT2G&h$t@y&;; zb_Z!k8O-I&_5G$DZ_5nB8p2Am=QYkzCw_f#{3M7;sE!!LWX%2@Z?S_zYroGUfHT$S zBT;Z~hw1+TQG(-k832Z zPFr?eh=gfo=iM6adtKd%-H}+in|!;9lH(a$>5PJ{_{7=Y{`cp8=k5n~CMI8ONCN;| zj#(E6!P3=ru1y(PkL1Sn3WIl*N2HT!jpAv9_t)>w7dNr2#r7w6M&cda!p-+)IaNY` z?l1XhP5Ljo@hL@$*{M>0cIL2=@q7b0ol?ftP-ihI0bQTDn#k4zqh_i{BhJI&y({d( zfUx@`fzHyRYQi2m-sczoC{D@C#-&FZ$B%i|+YdH24v-oKA|7WR@%yln%y#LNOSNK> z@|!}8QXOZU$E7oOcU&eB8!jrDzfgw(z6xaZ;UtjJu=;6Hq~yUotBfTX<6b`iBAi7T z7K9v3o@{S!)9H0j&9D7iT5&;~EPIPgL59&?|4$|ktBjBdzpSTyr=MI8TH)^yC;)CL z=Ujn(jvbr#&KI=h`E&5fYRZje+)GIGST}ZOJA8M+uksO3RsA~2>H=(ttpR8wD-QY= z?BvMEn$U=CahBF0@;IMaB>=xz{X|Lcn);9H(1l+|NY(>}09e{@S4I}<#oZBjcEQ)(;3DjlH|3mYWgAo&cQv6Tc&gzZOeusCZ&NaFKCeX#>`$TK>cIMMT>n4_Gml zbdnvY@$GtBZ-5^t3c2j z?zj*2XH&lIxxz#Y{9Bvi>|2McjhJ{^#`G{a0RSt%4c+#eR&<5*vcB-E&Dml?4ja}V zcFsMla#vE+I+KT@Z`)QrhIV@Ogx(bRNJ@ORK3_Xfr<)5e_1OGQ8>U^=ryc3Qs=AG} zu*U-3?4s~hZbd^|DeqDY$61Co&*44G^?4|X0=G$+Y$ddFWaFbpvppazZ>teZ#>&6;euPRiTRh~ z=|&Ue%5roa)bvI8MoAoQteLBrgFl8&Bw^(#`XSc{iGVtG+B)Ir1K2}i`#WxV1;*6k zw0H3MtzRN@tXw-3J9w3V-Ep^EdgYJOiieHBGUye`3}C<$oUCFQo~17SC&iLXlW}9^ z+9NG)3P?D&l`Om1lKEl6mNpt4CKwCy{fLd!vb@mZ-e#F^5m>p}%h9T5Q@UAb_AcR< z>d_?3P-3uUk=|8OcV}>ZNW4eG32b#EDX8oh6C^xc%|XUU7OMdSuF8VYD-0-hjN-p zIjoq1F=Sz&FSwHthhCCv&q4gF7YiRU@C2t)ms#?&ar-GyfQ=2nXEXXNuLTdk1RwrW z6Og}>5a-bT!L-yzO>xwL?E+h~Uc0zeG|thXt=5ZpCnBqiDaX(z-#^A**gf-I7Iy%u4pMf z48K;2d<%PsYXf~vf^2-Br8O8EpC8LCp1ey}OBIOC&t9~KMugH&Ol!Fv0sU)Zf953I z;q|PreIK9+VOEn0QwGfz{B5E!*Mz`o?AUyQuMf1h-TzJBbQ1a9@cf}GaM7K$R@Rj@ zjWivAWnQ;Dv$>|)RyV39NdA@FvS+vc^L5NaN~0_NVINX#6Cx-J{@y8JQs^5C3+Wm5 ztMV4<-z~$%&61L$9RB!u&_`tWZssrBW{J%Dx7jm`;w4UryL7f6~#ZRtX+(L zoc4e0P27%YZ~O2qYroxup!^z8lxx865X|eu$SxeSpq&3j8ebT`Fih7CeLCEHdOz#q z2j-jYRTRfg)zVLs+;YmPimZ?p^-}I{>lTR7r)kIsVn&p?WMqY<6yxiHFWSej)x*rp z(0DTqypomedHWx>CbImSZyH67@O#X<=ecUJQyeU&ML0D_Zpn1}AI7{7lSCa2A&&og zNRIHtseZ&=I^80=^A2(UMUbMeNprS_%*wi>c|!r<6%Glo28lENSRFrl*UZeT4JBz^ z*B%O=Tok)6UIRz4_%?2=(>TQ#-0QA-tpn06mr?STw85z7)E>eXNhA;af}V#SZw%Z#y=gG7A!_ExV;ix)wvvL z5+dfU_R-aWOZ3!atG~EXj2TJF$6ble$^}!0Hi{3Jj#v7|XSB6z=xv#j77g=6;apb+0U~hFARlRA4{x!Tn}&z6_Cr@GTFv+J zVxSswrzt{cAj1^MtwB^@wS|6XfoeXOvrV#;?YarlqqXt!lERgIJ+_oljrL!Hx)z{M zWAoT5Q1IsKkPS{%-Ws}#F|iX>qH)&=aY*#nvwZiYpzo;j4YbdrN0@fksRzA%8{>1y z(#W~BNYBD4=E_HBMmhg)D$xA@rUDIxJRjnLZFksiMxCy9#r2At{zJf6z}YJ+H}E*i zt~v{_sq1b7Pgvv!Av<%!TeS_W(XLZ@hb)HUwy|2!TPL&L9xNzOee3<+BH9I(evK7P zD;|8LtM>WF?<(MfGyb&?>E$A1)7=_2W|l}!uXw?! z?yN;}eZ@z5&tD#jTRb4_VRAtev9Jw`6+QULtud8_5mbQVB$imO!f^l=5?xVAS6q}* z{1T?g<0n}@yXYm?e`&})EL)MbF}>l~A~vh2$S?in$UV$uB7S)#>lvxySVV~xP)JpMZ%nc}}gS*f!g2Z~Q)xXJg=8UZHBULjhB#)G(xDOS2er33(>;h*wi^i4O{f z+3hAhiGJ$5-O%c$Zd=!xR3!Dx38FPRf_hrSMqItNZhfr#29xYAT)1@Pg8pqATG6Hb z5#5yQ3Q4dZwf=^*%vG|O1y3C%1F&hm!l-IZ4v}(4caJOrrO|Afom4v#5cMm4uPN=x?r7K)G9L%M=7YK?sDYOm!Z&@ zEBT|q^8n`?bNpw^xDLz8Rgd+>FEc2{E9VFkpjJ)r3{O_R%=aX>Uaer}#o?QKH6p_} zOmN&;yyDh6v3L=1Mx^0D*6eI-p@D_Duh{e=%P}k<&9gR9eSZ0793pIGqCPJN+K550 z`$sD$ZGRiH6EMA!nCj3_qNOu7JBL1F*e&buyj8to^sHxst-YYz=9sQ^3bA#@`9ZNp z)Q$qO8U)?AXQw2S|JCL=k8@l+w)X|`$jy`)_nKFrC^<3;h1x~Q$rvP!v+A7VF_Vm6 zNp(P-3{f-iGHf=h5!@uvIS@fHQXT9iw@`llFVlCA;tEU9rNpzzGnN6#Y;bPB^zSU@ zYNM@W6=PF0vcI=GZ24I2UNyE)~Rf1_%{_yY;)01`nM9DDEHv;^}AEw0l!}OWK(og2k)sd zV&G>RWex3EWu-stp7Jie=HnWZo)rL=UlZBbfd2$`oS**anI#la+OHk|PKxB^uhoE& zmzZhP$NDAaJNfyvX7Jt9`;f0cl3Ua)R?bZeh4Ra$@y;w?X^vhwzu!6&dUMT~$HfO; z`t7R_tCET#ea;KhACT#k*~P`RtcSeU91Z-zpUi4l9mqt-LGh$a?4_Q^)KMx0toRvf#Gr;ly@1mq^+3u_e3$AU1M&$cGeEgus$9hALRailASMSlNx`Y<;5lwk>+ z8Il?8cn<8+H%iq%=Z!y!8nuOfa(|nxZ(lw|NmmvcFN>|t#aV{y^r;c$eOgC#8ul!a zZ}_oJT%9J*W_yUiqC+f_C~R!;g|rQ^E??|Kqfc^kUko=_7F_d>(LPQSz7V!$MWPSB z%UVXKLE7$0f>?M*$zHyO9gUcS5w2dLIW@H`;A*SzQ-}mG`V|awWR9a9xkQJ~Bp=bd zoH3B4ik+3_OBc4M1sDmK%SgXQ0l3gi(|+U-ki7aj$8cD{CA)8y1<06*uqT=qnownD zi1~I!WfvW*XmmkD-bMSa)4I_P*~o+Fzo(b35qa&;eo)4I2&F;n1B2t`u3)2a{x`xL z#_SYmV_Nb(P>}fJ@aJ;i=vWsUk{HKJ*KvTPSfx8*Qog{U?#ZqGD55L2Mt=_$<<^={ z)3{Q)JcE;BqyqO5%xj#3TG}7QbjWUmWg6Ru5M9ICg^^NpegOVli8)KZOFXwP`@&Yr z65^+^RVI5MXjumJjUZe)Pb!o#_jl2l(An?wK2s^r5Kx+|GEJp1VRpBAZXAbS7`MQjjH%1iD>aDi=aWLpk1YeD!u{l@&St&Yiy#k ztAAKy)q z#M;r)Uvw(8a@7)f!oVO{yq1N5SUiDIdn(-!@h#{&hCX0L@j0QZ7b{g;OOlt$b>n`u zw1|rJnbXiq$g^$%Mi@a8%=qCVZmO7;wS(aAi+=nc!QeBkKcE}YnKig5g5M}moG_RZ ztf`{;@18~KR?(2ieCy2sdIpw982vXgas7jYk}h+<7Ck+!%#M88KARD@M# znvTz&6vZTAr&!z*vnW&Oc)ptBWkqBqx64s%=4*XM52?lt74}y2s#Ln=?G++r8fU^| zLH>&whnO8d%Quy77-5?=Ovzf5xQhJwce``BZBAYVty|txf^5{A(fJO!_&{F#(WI4u z-AChom1%Bzh0%&30d)w~2yZDqlZ5O86@4I4YlH=44z6P7 zdO55F>>eC_izg~4CEtn7E)6Mj7rZhoNcX)kV%F7*9Dp^o0#Lclwx;&kgzO@NyELQ1 zYaa42BP=#xB$ZwwvAQmobU3f-fp?oJuY>~eaF=jhY#%V}HB$7~*IN9eXnm+Wr}y2> zHIDuOcRv|%_^=D>=2<0LuuVXcxOAHb5`UZm7v2{sV2F#Ik@xwS`Wr?oc|8h z+uOFLSRp*RjXB5p-5=YNzdDVd+`Zqyc6#J&+~!e@@ugmkaGm!!GiTIR3?9#9HpdZD zmz^J((L9Gwojy>P#1`^K z^VK%q#iGx)K(Ts-;tY=Qv@VNq8}vkJwywr?AB&{=(N9i~$sd}B?meLp4C3f4v#8*) z)vFQAu&H9Dd^*qGDVD1)aJw2Pk2FQO6%6iZZ6iSAc0~%0SXef@qaKA3gUpRb#%|om zn>3E|#{j{F@wT+}mW?}X+n3OfZxGg)va1{TcQn@b<(ehv;))YZrlwY;98;Z!HrNR^ z+2tTh2jrO6e)Gn4eQ0gWG)8Mv3IWmlq)>w@6Xw~oUM`3H=f8fyay`c)c6XCBXnaWeB-z1>umIF543s0R^hMp2W#{;5a{5cNqTK_Pe!x;Et}Mkw-E8kV zsaPc)=C%$Ra7m)OCq6RQzn~l)$)DuqH+k_ez#bbk3^n?No}m(6v3*|Q#x}W#ukIjQ zd~^nw?wN`5N;iciBXSLDC+9rr?Kq%a{}$W$6W?C_0^j0ROZfuRQEt0O=TgfksGkmY zp{syy@2G2TN7kAa@i~$PP3&=F)*&0wl*y}vaAyGXvQe*-1#aYzWu0j#XSnW z3F&lw4?AZTEDH*1eOwXSd;)&_v8V*m@LlUmNiw8YnRRV{#4_9+mUc{aq`ugJsl|le z7r)IL*&$_YvO?Tn!T6fmZ4Z=V-$RVxmbiu#=G_qWPvpz@>RS!C8s5EDDhnL@ax^Jd@M&dI+x&%B zIRzn=C_~yyO~dJ&ZPc`0k#_45a)@ZFf25PxYRv z)!D%Vkthc%sngmsSQIj&66P*!9RUGfwpjiF5XO}eBJ?4RjG*-QvUtvR(A7|D1&OHq z#y<%fyQ9J4xovIaRlsWIOxzQQ#vw|;t0j#Zi}Ue9>8xx!fEfSzP1zZs%Kl0ZdBh2Xq36Chi%n|^ zppFaxvhQS*BtX0Ydl%k7PXT2~FB#E7{{U8~ggPT&X7Azid1rK8 z_vAINHoA0{(wu$Wt{v%nVtJU`=K&k|mlaf?n&VX;M`Z8{`M!V`wFXp_f!Y>Y_Z@YR z(qkCX6>@=w=3lL%8T#7tIi*sxHQlsEELRwA7%ya*kf1SryV%(A|z_Hf3mMA0rVH5Zfbv3 zm6m0DW&!E&Ov!^zdcX zH!xL(6R*C?RcbRSmjebLNWSS(>!-C3U2TuU??V6~gfu%Uw7wiOFLSbo;8}veXvI$~UR-tT;&3L{Gu%wP6^WX(F zh>_o`2s^PBdPDr)b=hq<3i*6Sx~@)GTN-Oyt58>kg?%7Y@g(fXbNq`rb5qi5;Usi5 zwu#?~O7^W#w9%j&p(8!ebx@sWLRaYBfay|D|I-kPSFODGnvFcvs4ql+F79I0z0=L= zxlRU(Qm%eVlY>p-UtlLX)IHwcoqHH|xBn6PdT4e1P2BTm zB-~MmC)%-S1?<%iCOpEZxX&RsYgy_*>np$8LWT@6#a@oauD z(=s*Fn3rl$6!t0y>Da*A=G;^4Xn5lZl^aX3ziOvbF zgau2-1ly*O6t{#{62|S|dhYay&l}*Dy4#ksT2PcKcuo~ds2}SY8TlLkeB!d{G(5+4 zL9jV4EHNQVKRSTA(O#YqW1%|JV~p=?BwY;Jj^c^2FyGREA@@Phol=>7FetX zw;^LJmf#JFpTp$7zXgpveI>mD^Dm=4T%vytD98u#@@49{og(-TBYB3xQhHo*5;fli zG%?ikmmA`7fVFKK>Ur1S$IbRilRQatk}EI2wvxUukFQtNX*WJ12@mb`Ngx9 z4`XY-qQOpnw-Xt6#4OArYsakMY)qn#Q`3#D+eLAVSg&;LuM4bHsQH?p!!LLQ6p+{u zMvt}9MX>h`D3v7`nsiv!=BX}T82wFmfFuf_I$!x`C5 znXsO}TrE{mCiNg;mSNEyMnCjNlK&=s==l(gYjfP3l+wzoJObK{LiwTb4Hckz>4&a! zlPu@KNxAf2trd4kq+hW?(HF6g-y6S)6$h+nS>nln|G2*hEKbV1du%V``g-h2x9k%U zM!TAG%5Im`UyC3lp%wpjFf85r7q_Yb?7}=8QHoFh0>1;U(0^yHx&>1BIfm#oz1I4oZByzM zu6lPo-o(60sOzB%J*MQ!0=u|XL2OOoVpq*QYvs;W+xPW7_`FGRQK`}c)rrsPdg~&7 z+eZoVLbaFoGkzK!4CR$|3%yI>{a|fcLoMrxBt1JBu&1Kj#6ei-?JCeqpze3J(DQ)5 z%|r1g|BIB%zcm&4pVU+m*khc|DMH*KKVVJMWkIxLxy%X*UB5P8*Y#!gRCI}-pTc3g zN@h+?ulxF$EEhCuXc~qYw5J`l$~ey6y-yRc3@yt3Z>0<0_J*1|1TOmuodA{Tpi(gU z-Gz29Vb>`DRB`VTZX39Mj-2wAr&}+^$9bfiB5KGUSCG3)p2}b?Y1%GZP+MV--)NN} z!msD53{%#D)~{f3E!TSMUDNHnpe&9cTG)D7e$GrP1#5pqJotlAd{ErET2&bt95M+0 z>?Xb+7QpAnl&c`YClvaBVTrG zd1J;|>zVV7Wn~eTbQ7ZYj#qJgvnO6sF8&eEqIbR&{KcP*+*>97V$qw};IY1kQpmpW z>a0e&&pkvd<=PZCeR!T+?}GJ<&?)I)E*mRs?8co;C0;dmb+#fWo-IMmttg<4BcdmV zDLOUUS|+xF`gu+JCKYrdp!vMTMX2BA#3mIF*p~0oN2Va)dOVdxUl#ecMLDcIdg6Vr^p~EOEEymnUlfS9X!SY z+6eJbq;uaH%}51k;+u4V3`C5Uphe(3pYf`61Q0&`^Sd0BcsJ{FocJ_E6|FPgM^7K( z_3=X2UJpecC=VDlbWKBP9SIq0FOtR%q&qcCL7Wz|%$>j~9-O1bl`l|oy|JH58L@1Rp=FUqmHRl2H+h6a7ZH&fjmi zN;A-PCiU_91_Wi*Gu}Aeg-2*?dzKKKK1>|ifc)*I>)FO%Fjw~K00VrPscJLnHr)1XZOsJkl!$VGB{PiA9)i4*3!N3{Qt<0% zA(YoirTix^8npf0pnqSqYJhGk)eRLC1m@a%WC_D;BTa=Cfq+pU`A^F>c8AmpG?7(R z&wrpeUsTVO-o?&k3HV9h_FIX{Izx8F2N#VYOxZzp+h{Z(6jioT8r7+|P>}<3lZWUR zL_Q_FJbmt|cKC|TqgfHLx!>u4Th$l?Le9+6Q;+x)K$iKyi?HHz5z+mi54%99I?SKNlSw@M#W+h{&4Xj+?2c*A#a*-U7^7OHq| zUp&Szc z=Xu2NwI(N+25s@dN!MMr*o`p4(8I=-2b%7SWRp{_&a1 zbJ}%6leCSFp0<_Ir)EbTb9);LyKMLQ_UE;Q{mv@G3ls3SPo7!?pIVlkug}*95W3@A z>9gnUJyjg9q-3ns?)Gj-9n*G_FJty2+n4tLbyvoFpqI@I1-Y{F?=ABJAXZHW-&zz% zM%p3(W6df70e?0h?P>=$8Xf7nFm4N}t7UwF47_?Q&xbSBS&pFWD@boMeC%%9)D%jH zGmyL}C1r%zA}Y&uP+Rs?-D>4Ima+gf`WL@tP|SvQ9aB4XJ7{G91Nc$?djQ{)^&{zr ziv;w+r0+lV^rUV3238CxDq4o@j_t;FD{5CMdKAObpsZmcV`5!6?=oM%Aq3yo3=pau zq48h}U{iHUOG79aD=(Djw&RqQbf+*U)kGMbXYw~I{|d0pd36GBOKl4q+5>g!faa_K zU^o2T^C?pV00Sq|H1H=2-S_HNr`%{>L{Mu^tQP0Tl1R#|T3V2pIYU=$L`i(7zbx-C zaLbn3f-Jj?Go8{9+gU`H03(oVz+3Y!#Cz6h%JF}}H|CI|8H?b52gwZ}{8kU1jd>=Z z-`mID3&q7P&CO@=v$9N@sOG6>LBKl>zX2%&r9&tE!#790!m1uvK*79sTP>&B{>qm4 zg&L;2uG;;um}rizhevCMEidlJKjho|!*F1mo5v69B-armpKxW;!M|UW6IpQ@i*qUI ze!2ITnIG-#oCO5STJU0L3%_`k*u$-6jkb@AcGa)t{#a$Fv7$05(!|&o*c5^4)3x8f z&x2c3R%ov&1YOM}>awv{po_R^D)nHb8sZFS?w!WtI7(iuzRrF0z;WiCSPM)yb00Nq z>*59ble{zw9S#&pY;vA8X-GHosA!W4Q5(!ztD)cIymy^)(6#X_ggtbsN>??ex0%T6 zV|H0{p3*D}1ZXPcA~;1(mWeb%6o+9Z4TyyFbjf9?*dHCjgNF6j7hXu8YrPetnhbg9 zWLKXQu6A0TnOsPg*5#mYWy$2Aqn>SvA}*=oV5vB3N>jmxxk6>IJn-#$PT((^RkOnR zIB0Snd1k+iVG3-)l$%c}(B>f>0f-}fNG#XC$2R^b34jcn3boUWBpIgx{6E3X-;!Xy zULN2>&tz^|1&A1C0x8r513cBro1qIUkLC$mD+^3gQ(Pl;ZeHT^(JO8<5R4uqbZo00 zYkTHw&aAcrHtT;bc6j_1Q50CP-?XTZ<3sE`{=YWlA6KrSi~�tD%58=GHVE^-r`` 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 I>h@4(g1;TNW*C}|p^ zlxkw4izRGDny;{*;P%vl@C%faDoZoaJ&~?Su_fR}Fo1~yy-W?$75@ARJbZ~5QDQ&f zdhpkPbvp}bF`~#^Oa26NXh=Rn0KwmD$Bi;4(_le-*%(4Ras1`UGU~}8=pAJ6C-fey z^9O7tve^Xo)L$V2Ic7%^Ja7gwo9(m#Rx^PgcSN|2Rd4M!GLc21FLyE~U1LNppjUOF zX({BM1Fe**Cz7qZNc9c6!ZlcQ8oU-#`;U||{>xIFepqXA4UjbmRtjM|aDe}S?2PjX=AW6ykM|8HD}5m9arOykz!tQX2r)i>M^SsraeLdgm?uda@+n@Pd6e{ra(RT7jgZ`zxeL}oykf|iI_8fcht;8% zZV32Hnla&BE1{L*qj6*zdu(TeRpFI?uEV_TN(T(ry`Fx&cm?B3250|Gh^)+8#NM&a zt+}8afxqE3K!(KWWDH;)6K=W-G420(un1G>MDDZL`#-xM#a=8(A6TBl(jTxbEz&j4 zr=|WbYaLj~71vt}$Hzk}Y-GWndi)9c%*HnT9^|9}edT=W0%E5oK5bl(a?bY&gxdZ*r#qdx$#AE0hd)AnPPuOIU>7&b~jMLmjC zU%=WvHr-DWz6aYjLtlek06bS;(^Io?)wA5L)9?NHSz0}HKT;#Oo5`*JuKCY3l!Rob ztPpA^7_Csec^vI~EHcNNs#VXfbIa;P%(iR!BbQ8L-O|y=09y|VKRF%?e2V(j0u6rN zw3==lDz9{q-$N1pxy?mIuuF-=r80CgN} zAD^U{h7-|Jey!Va_Z>TW*&PeN?)?V1jY0{fjsm^|&wx%=s`!f--}>9Y0eQ6^lw9ax+-`!`h;pFkv`3M3io54{CIVY*frxs)sZ9=nN)%j{9_sloUp+{_FL(OaiI(IGp}*EBBorc@$)6 zerO4?bAtOs!9+0);T_N=00EW68{e82C*>Sm$mkMa{}alWSSGz03>Eyz1|U;FNz15` z9EWf{jBs!ST_1sm&=JMrD>zk_QL>?-(2WN)8f>N|@9Z(HU5*7&rcIBC@+?Wfu6{!r>v@cBgTGyfeOfmDRrK$uolEgb=?J4C)xA5p;NgI z%VGkrrbBU(GY+6iI_S}|{1B#ve`Gq2PCY$Pk*UgiNoe9=M-l}eTC)o;0|9ikG-63j z-YdkNtt1%^Q-Ri5$0*UZ>0!rh)Y`M%u(2ki0IdJWN_<}T(P3^3+3}G=gsVPu7bsd+ zv`EMs0Zw)DI+bJ2HHi?m zI||cX#|%`2a*AA2Cgp@PrML zyL|Y_iPxZl!x2m9kTn4yca+)Y#$5`BSfs4U#XNuV-&r>P#NQiDIpA+LP@g3!%|qK1 z&;_X;B%YD1V(;_-mjEpf`98eWe(|u>6rt!PLlatCXG^YxC-tpq*{+8)4bz_bcTOu1Ke78Llo#V?_HPtBl5arlf#9U88}x@`;dlTU)< zj9*#>hRVpN&>M<7imV}c9hR?ax`kmxdZ|3B*7XgZ5>M`!R=#Q-LJeY#65G<2(NC`x z(~iC(rYE%PpG}qf`lv4t*Uzs%1k2F3N|Q>{i}xX%t|-)KHz!?EvDF~5%>e%xrS19FFNWQ-`=auM?SrTkHUug*B)k629Mkv5Y1i6%a%v$@6$F7 zuSi!+`J(%Z>`%6G!)do6c9Ub^eGQD;_bKN-k%vH+pa-Ck~YF&ucPSq;ZA@N!ogc`CG3Z-q3l60cSK4a1vtoqg0+e>|R&18Ndo zP=C46Lip1Tr-cpyjLbscH_D1QXt#BgwNmApr@^LyN1fb^p9*L6);eUhmC1>uq&I|* zO?qxr@ALUX-)*Dqt7(RDBgg5K2gJt@AL^Pnr3cEN8hm#IyIYPDuN9@M5S{YJR(x!q z7-C9$3i}KWc!m5k+~G3~4aQ|)u_T9ESquH3yv?wR(%-aM!r5 z4HSrn9QR}PX8Ca&$lQSNiU$}=rqKdr^T9Ph*o?D&4GZi<#*aQcf>kqM+?*yK-RrFo zuZ*hPxzZo|>x+7}FMnqCBE?(bfzUT3q-2QHEKg&U6(KdUfRw12osx<|WYVg9V=R_; zREy_5Gw~aX5oa)5ARHSAPxt54y{*ROT^%{eJCw&pyoEh|u^A#yKF2eGJMoOJ8@%6w zkG#2e9ox)=UH&I!PqB*M%7n4k7MD#&tW>-?`kmLAzcy&jAAoZRZOck}eSDB+KWp}S zTR|Htlq}=4MPZMttrZ!k>b6sgXg0hFe|j5X(Ej>0+FrI&J;6$Q`_XGZEdJFC`GvOO7PXQFJaDEB~#xc428iu|pxUso1?+lL%X15F&;;|n&} zbZ-6Oox?QOFRa^g?-pr_UX$f+e=11&x^TqyI&e(tn+`tc6)PRL8ip>*9;{P8P|uvT zyen03F^E&y;Lt8};3nk1T;82zNApfsg(qjKEZeFjz7gR|{p2mN6F=dI-FH$Dl-+`$ zw_m3}0JzEW(x=O#=TryWl9$?D5eRotMeE$POKm^#j7F}*+c(cd30YfeRHu$uefwVa zf?r|L(H}d#>EHK{T4ub5ws%Uqo75CiAB1vpwe>wH{}}e4m5l@VPbk%+RIG@^uWZWPvmZ~ynM059`1 za8fq#oA;}nl*>;Gi#%DOX={d2a#6dX-iqZJjEc4F2UEYkVjcQ6Br-J~fX$L{KRUj_ zPZ^mEjYj7C$7W4kZZ=2Ko^2%#r8n0zl$&p9+qB6~%(vAh9?p=DZ^ME4y?aJxRX>*i zL%5SaT4)N2SGj>op6Q$Zoy879D0{TQ+fR1h=+2xzOE<`E2tJ5$rYL+)6@1#DUnW8N zL2EE&&(F&I<(!vAGcthaQcDjt@?NHu#QIh4; zo+~562*8#$r(^%dQ}B}Y42#)_aF$9D_re5efU7U`N=)305V~m$KqwxkO2N?|vn~qX zC9A9R(dSyy*rhrsm((HT7%Dj`L$b8I1EC&g9eZun5~xoK_5zw!usoNtna^;3%P-U- zS3#A|yKmE7d9;-lLy6IRyRs2gRMKmshatF9zC_kf&?)f(bWiL&P}A}YWX{?rg`=a1 zjpcHcWOOYp>j<-UVhI{u#P&&ndcHoR^X;(dn9996{yS3%^b?2O(j`iy=nky@!QYpwgP5ST8ce+@n{r`! zc@7C3t0awVzSC0c=pc8zdcqbsh}qb~M`H5H_*I)kwLf z6{S(M+D!zO?ll{VuLH7AnSqn0uFHH|=zAq=(LrWQ2U}8)h#*(xYJ_bYgnyXal`K_< zrGH459)Q!Hps~R+cK61mP8AW%AZmt)MJhwHu}<2mcFE}NvEPKs+bPh+c>Y8>#qS4z zWEpya4SFwsLk)4|aQ}}KP}vG(Pk-h<0^8^^vrv&+80rc>Gm?r-T%xS+6+YtEn|>y* zM+(y$YSOKeDwGps^{RJflxQreC0!8{M5x&_;y)Jr&01D_QVA6KW|&9(LkNdP=%8%> zV@zhq4Rl1qo)sv5NLxx#Y3f9%Lhpb-5oo|Bn8L8@f$v4TmaFuFgY^ZVXB#I;F1gHy z$b?f4P<`cnKc)1fR91{-)NV_E)ok+DYUKIp)_P@Mnvd7NVfw3B+R{a}Id~7NH$XV5 zV^|4M|Gc>52Kk@X@)?~j>EyR%sQK$PE?rdTfyzqc9$_TQ6PnOX42H`1qh;>BbFR-* z^4>*7kfacw(fU)fx}HR_u%y2zS4?92dcrprDt2033r6j(m82|Q4Yy?Cp%s1SbiYzA zz`0!vLGDtu>c6p=Q_dKVg-z{&>D`EOeEhh)Pd$6l#cH!>{;;8z1ga)w;f z@9G8Tw3qfs>F0kI6!bndIVFet?%}LZ&Z);4sKQhWqbzd%cHPr5+qNAu6l6rb6X#(jHyKQN0Z1un$T5xZVY7(_{i;yp|-|u6pSV5Lkp1*JMpvg(ED)j6oaF z&QY!@lv1^kxyPm29R3!3!|HHGNExc4txDdSg)0NsO|ByycOx1bAdSZ$?=!=pF$&;2 zVc;e>C3lj1b06P`4|*vtXoq>KM@o>d$Sx4Lm!j1_L zAsW*09~jE{7FIOBp~>@&QJ|eRl8n@IlbDpya`~rW9I0Rp*x9OV9{d!#(Z$aHw`o!* zp;lwl_ph$HR@LWno)_yu6`Oa$0Lp>$5OM?&3p3-yB5riSuL=LTWJFvQ-b>TE@$*JG{Pkrxz}*djz*QX}H(*lEdP2?a!+GX)5yxiX z)EI(;>DT^iJ!PqtSiu*PL~bt1tNSu|eD@kMrNws)zIJcRByosa%s}kz~>-whFW#RB$V5MY5^27Ho8y^CK!(SQG?R z-fZRSHyka(U^IC~rzU96x3Hge&V{ip(u=U;4SIG^k^AHF zO@$QHYifE&NHU>g zWL{Q!MXPr_NJvEV-#Xlz=7JKQ-0Df>zq?q(d)rH2X5vg3zF9Gd@I!0=pwrb^IlBP! zpaz1F&FtRf#n}g@f1|Xr1`>IYt!0i$Qf@oH!SXhVY__uraq^a-DAs~vpNgzug_vgM zn;Q&0t~hAk=wZnYFbXbp#;O;BKS6zTIO$AJO~b903}1QJ{o9OiMeIk`a!I5nulNh+ z0W9fibkqSdz&NY~uf*@*UFraAje@}6T`%m*CQ(bHlLt@<5Achr&)8JR0>#%OTnZ4d z%bunX6EfG{{C5kz`7Q#@wj}ayy6_I=RFd3qxHE-5H>;0M8-h(kAl^6K758izG@CYo z9ald~4_ZW?%v&9%js1w>AZTa5Y?bsTm1JyXs%0BO7o)sb05^)YiXm_79DgOFVGS*o zu+7GSBb|EsJ5nuRM;Kiz2^vARx~eMWOT@R#mY@rizgt{2h~~26u-kRj(rFIUzd~{h z$R7NcAIw#Hs!*$Bl!W!%(DXmrWc271DM$pp5(wSaOgH$vLHIqk2LS=Rxbie94*_Z; zsk}A%2#UF%st1jGjUNr7j=E%`Rn_4O9x%8nA^I|aYE{>#elK9!eV}MSfcj`~V?RfT zXe(9OJt4_2J_foZ4e{&AU+6rvM2d2j20E{{b}*+Q>_z8}%q(R6eo8)?^WqCyMJ$FRzpxeY8 z#3rX)I=i0oI3JwrMtH>=$pZfl?L45kdaN~}uJ&27*8|+=y*+w63SPReSSW9w`Zed0 zjXh(%^j1>f+rP)8u5o2yj0xl)Z|ap~Mg5u2frd?Tlv+0&xgEx>qh`9YmIz61MjeT7+Ih{LU;UQmj^MesVcZ1=6#%$;>p z4yLb@i+gF=?7!B)Xg=$IaASRYh+wi++m1VQl}(vBL8<@e+O7a=ds`uY@{(1vKLYRb zGAAzGQrzv*0te1as6~}OFr_i?Yzq(d-XSFiC?bJ-`^2utjU}TV^qlqobg>Q; zVP8oH`onK$a)4~8@ZUES)L?AOWA-_txJi6n80^<|MvqIjMCNz%BF#^O>8Z;)e?{S- zNT_N{#j0LhU)t2fL5~d5t_zW2Qe23d58cLvjM|$e$qhAn*(n<`3vc~}c~b@l`dYuJ zI%5}#(2ZeFLOF*m+Os@NT+%VE+L{8{AOof8@X>c234;k}?z7ZVC~!eAzw&H2h$+7T z+Zt{*cquxf{pOKmHdUVZxLBL}{Z{2ZuYN}FQ4ah>C@0s~FPt*A>#EH8^a~0G7Fpy& zG)(J5^~Yq)h|2~zvPiO4JA1e~#_)D#faMkTD(h`QMw{6w_C z$C7o4otsVAV1K^H>UZ{R$@qt7_*%N}NIxwS$_!%5I*^3JugTeoUt?k4(^1b5YW z(?%yhtqwm!p-pCI(U5T#C53g3%nW8XN#^p0IiJ~_dmK)n|8a{up^yqK zF8n$t{jb;>YMs<2!Y2{6YSG}Gn~y`4_5V;B!q#N2*YRPkn`{fP?KdH1^$zS00Xlw` zS%}I4P7i1|^r{9TS5x4Fh#nOn0qN+tGva;;6OSq!PiZ($VK4eZ_1?5s7ckvhwbF7HT0SOKKOWg)%fKl+ri?N6x^ zYSIqQSFo0?Kb~>{9#Y00g97=&I$Ak&3pyLB%%l5abMAmm#oahAX@Xd}gg8d9u7CFq zT@7|Q2BcPiQIY#WnyLGgZh*-=?I$`H!Sl`+!fCMU;E>w1pSm%9}|Cs+$s{LfuAv|38N7D9P>fsXKbc zLa{zaCN@fia=U!G+No|~xS%N*enNrRRYBEr&oLMUATD)Ly4BEl+|_b&z3tnb{M#tr zv>+SdwISQzM_4qk6T@t&W=DTU`KP{wK86Rg3+q%=(_7Lxg^nD9HE`f*ny&=>?WET; z>1JBVrc8`^oHcPehZKw0$1^$&*fD=4QYqlO-IOCl9s`mW!A^75NvEr)>wx^Vn#$xx z&ERH<(2CnbGIfV3>PGf7)Rkbix;Oa<)jt?D#q?EzW#E8ke9Gq62K+m^><2b30_ng; zIEF+!jvDu;j*6jqmIaJ47Xro2_1hO$gTS<(QD7tZUZ722V zlmy;QW!_Dtq&1LQ9s5ERC7wE`unVk(;EAxcTbI;E+7Wh9Vr!KUPwO_=jmzC#=%*nn zO0nj@HDhVx_0or~w5=2f9{NZvT5-m<5_HHY!_G`97`klTXu6`=5-Hsrv@kP2fo3&A zUtopJH}bLdmRxQvLs<_fBi8&NtJ(4wul^*(5ETVEq;S3nt0T-2cM$T|>FH-z@Jm-C z*kSD3e+iIR|r#l^&f+x7`dM5{Bt#yT_x+=?gf(<;H^!#6wHDFSA=bO2$IDL z7@oX4N!;a5-wRO3Vob{&^wD=nrxom{Gx_A=qOMV_F8OJeN?N=^Jv@FwF1k2- z8NSF5ch$72)2yszkK31CHYYsGF9oMwdS@_;w4$w%`EM0eiJC_KYk0v82_Nb!zEuWp zS5q6Qq+R~6h^wjVe-qTJY51JB4!s;rJHh7^&ZwwNoWtbSx4hDQ91#v4u{71!{vEu5#b}Rqkw%A{xB>Q!iW1H> zuD=^#rW$2wo~$r6Zva8#I^SdC6Y;PIwXtQ4MXWqZ{-sq%(N!se4Pj>E4F(Dk;nLf9v zDSS83aa5shoGKfQ;D-VXfjMbG;W~AZ6|g~$R%WX!5`gXdo4RwirK{&rJ7XIr+T0i9 z5*F}+v-?;*_w39$zbFF{&pijdkCTrMk;B*jEv-P)JJcQn8Il((+YLA#CPwPb6mQIm z61iI|G-yGBKNAyT(JudBzN)8KZ)YJ<}>dvvNy-U?I&wIcsg99Nc=l1l$8M zU5EaO1oWE)2STp{Q~}XZemuqPXI&lV7`fK1w6BNup9a*rHVFP*Gm@CmD9!m9iqNXw ztnf*@O^dfM<(l^GcR@rsQvg@vYjtIFDg@}hF)PSb;&-RgzaJU7L+U~ITII>qj^aFex9d8-_ z|6B3Bd$86T=T2=bnL#^P8c=nEnEGq#>5VG0?&Mv+eG${Wr?KHUT1Dy~(P_l=ZH+cG zXbc>YfY~FhestTDtJAlB>(ZR;vn1WWp`Iqh)PI=jE@< zA`kfp{gB^9%vAViUOj_+-8{7e+L7g^0e|@CN5meNCQsLzwS{E4bF!XRyKhw!Vos=} zC(Gx9*)!5#GFLpBe(pQDIsI=YEIi`OmfsRYWuB4Tclr z3jBWBgVy4!7t{ATTleqS{wP;_-jGZ~6Xuj(WuXs?RCO z%ij!{;ym_Z;R+!S!th12(z_cJ5I^7TxqL8P^37V9V?GiP-VXNr1yB7~{?Q+qNv)A| z&gQ1xprDSBi~V@hsA}LW%^B|Q1u2|@Zhcy!8IP+|l#0K}`4mBZb){i~jjA9NU-9c8 zTu`Xv!()Zvxb#U(jGSz|VoKu$CN$YmW7Y=2nmxt-EO2_A1qwX;z{1j!fA}gNaEL1Q zrCl;J+>uD~{5;LxT-bUC99G$ccGXJRYf%Ny6MPTQk!RvEtF8f)2(ndHWyJt-vbIOBNt*CtSoL;&9>KA(U~(#Vk4+;yH-Q5`O%jt=k%OEW zreu-SiQmb|G2E=(Pit#bbusJ(J=oYPlJW2q^~iF`U>Cj-fK$m>Sv4A%!uuQcdl_?( zb9mCzVOkqY`la~;uYtL8h1%mMyWOMz@`&^Gmp^%BlnrlivVd3N!S z1I0-k4gKgSLc;YSnhxucStp1BUr>a&61 z4xQb5n$w?H?P3>qQynnK8$!s6z5ILc=-+UP!V%-7H_QqXATiAOO?!d!lCoMsD}i?I zvmzs$JGZ}9kze^u%GAC<2WQYVq30bWL{FMmQn|FzL*iw|S0$tUjQUkqv%t>n(p8Ea zG}`ODJ$21OppMN&*}V>7LffmYx&S`br=_cxxl(X48DC&tPvw#^w9H2)z@y8=P`uIUA`SXuaA>)E_m-ZN z1k_xaWqp{$@BAiUzRu3R`8e2U>pMTP52hC*^4;zJRD6Z~vQ$BXl_6Zmq-(-LxY74+ z6?}$yj&}hm(MwqTjn6T(3P``yH4zARn=n_zhhC&Zf;>uFM8Xe$*pUd~Ih>URNWDf8ld^`A4=B zLTpXLDbdC*hH|7M{r68PFQvEuT~?m93lAaV?<76a4iD~^3Y$iLM02FtAHeqi{u zYlxD}s4Iw&5pe5Sh3P~yvv6Q_=gu0PpI{AnvU?5K?OOoe(6bZfmfZfk%x=N(d<0tf zHdSm*uKxyK-C0m_jk4?06#!o0wgc8=DOh+^j0QsKPK{el^?Iy}61lvCfcKlhkVBTZlU$zdm4av3w zIQ|V0kQ=}L<^9A!|3v8L`CX4t?NR+trCqWr70Yx+Y>V?D1zKvq4I`}#sna;Wh<_QR z3Qb|6MAPKyEa|oiW(+bZ9GkLLl1=TnF^NpbI#WvD>4uteE&Dvddr=UXwSMm4Y#Aq0 zb#^Sqv)WP`F-p{FY-ENhqm27_wlf@G`*jKYUza>$bX|uI^-*yF_nFz3`mz95=l)uR z)mQAB)J}=i$O_OG1-2aNb}|=b|9{L1-JEcY*c^cMi7sO8)kCv0Vc)xb2bk~lcs8i- zUH5^(`x+rq&&uAEc>>53b!L|#_@3#W)07+un&*R#S1Ev0oQLmb*2%8GJbCwz^TdiR z(M3wPv+1b6W$E-lSxB##`6Hg5g*+03T!AWG=B&fR>qOW+k3oIm)CzZ22W|O?r0)fP zS)wjH8Nl7d;otj2$&fd#lS~4n0|0|8uyHDyIaT$o8y{DW*e@l8V%PXt_W1w_Y86Y` zfVYUTjYUjAvp%Q#L+K+Y`B5oI{-q}tcJ!kd(B+NB+}sa08W8($X>0U=K2=NYZ7EJQ0{=4Udl$M(pykWHXhp0%p3qrWC(j2=<0q zLgEO`d{C)7T}_gc{JmGB;^I-Sz&iR0WU6rSG5|^FIPC~^;FIL9l0W9=S2zOK-NFAR zzaoWYvQFx#viBb>54I$!Cc_th{^{lC8WgpOkYQmy1B zw*e8>)4u+eMgz1i<;?owHCF>FLL5G@{ZJrR_7E)jS@^)mPc6%i9oK3LD(W;`96V{clCl>w@6uiK?J*Dy?RFNs~ZqiLsSCfD)`+` zL5+m?3>|}6l+GI+7t4?KNA`TJ81~wR_!@#Pu->7vkgwR@n{82{?c9T}Jv;A11(L#Q ztJ0$xqNNRM-#+=))hpF+C5^g6AMgw2H&(o;$BLVjelb{futB%9E+=hY2{TOck__em z@RpeB9FV~-{ea_Dgs0&df0wsH>t`Y&V;Q*PksV!^>1LqQmikTqvF|xY7QSqkM5@?; z(%xwfQkGggm1C5Z*H_{D@{R_jg<4tOJP<@hUiDuO(D5(*ikP@_1)yC7-G>4oh?kn| z+*Ed+>EZ(kH@;N8l@0eMJj(Hf!%Sg0nt%dG=XaA*vm8s>S>_9i3#C-71=AxjH@wKViVYG*;odSfZg3a6WM8{yDhniovGNj&f$ar+5%eOz8t<6cj zN)V`d#|J^5eZMl=o6j=S?}_z3MnstLj|utzXZ0Ue7K5Ht(tZ1;Cck;cCy9~9pbGSc z;%IqZIdtG#1nmO^xY*nT)SXRoK(AdnxA+v`*=(~%Z29aj*2`ZI_rg;olwa|4wXEI&=GFl%V+Gb?tG5LchH>PvhNi{ z0;Ipf3nKe|Qjk{KVx=5D{yEC26#G?)tgRh{wkI+VM-rd@gnmBVGMK$A^Y5qIQ95)C z2;H!gE^kt%iWV_e{$izCtWred3Yuq>#eVNH?MU@ZuTgz}1CG(Kc0;~d(Ubf3d$@sh zc4@|`XBs>{%$i2b&XY?_b05o zw5f^Xtz6LV;bDUw&`Z4BRj`AX3N>;7?EDSZoQ#`(gT+s{;-Wx0?)yB!9$UK%iqPjd zZ=1=-z-sBtcxw9UlsvP!S|bQMm~hda7XD)i9}$%k58K5y(-jPa@N_pD7Soh}fKAs> zCIMt-1bZS?>dWkAb_-Pm+pEIW6y@;kY<;e7m4hCd#;3_u_mq&Vh~H2 zQ{vLJbfC4xGK=5+Zcm^I&&bQ&s}=09WuT4>F>_vr_7n-h8N4$L!q!2Kw6WJo=JjN# zV?Q><$286#e-TGsrr~-S<0c5_N8g;1Ts4{xp`FWzK%4E#Rc^Fp4GWO~AW_#sFcR-C zqWc=I%U%y<=6~(z5dJnX@gc9URGrIZca*RjqjJ#h+6`%9tg*U8CraVdNoOt$q8-NE z>-Lw>Y-L6G_nR26(pUuN>>kM$p0Siv-I+D_*|tH-oWkp3%3-wn43B|4R)8t(H{_8q zJ!>6Y#|$d3+WwDrVYFyecIy9iOzY26-n@cj=uIgNUm+*YLfpAQyM9+4*# zPY#D{y26zQ?~`$;LVBp0n24jL4^}6+F5_HPnnc)GtyQCRLE)Mh(x8Bx-;*Ctc9G_J zZ7ZaQ3Ku&w>Ov+9IjjvYhMvWd7Mz5RbBR*RHw9ZvHEwz`)rkKhvP4nS4s1 z^dBj%g+GL9V5A*!rzrE1#bCnd-VQ+^h&e4G`muF>?2J3_oD5HPCH(ojEve?D{gjib zhIJ@_>YBVtdBUNeMSAjLq`a0$KB|B41G$$xB>l2%30ev2nY@!zRhnQ>b=bYoupb46ThT`TU8SymAAB=J(e00`-|BzCU``^!fFSf2(Hoz3Lm*~#`e&JI{7qejVv zL*&y={`;{bi7-$NCr+oAN$3&)vv?+ zLA9{qHmZYC<9n9=7)+;7ToSn=bdMQ=4-;Y$;byi%Pdnai1%3ZDc*`U_WrN5y;oVka zMNpQlx|De|-@Qzjm7;wcH6KfUqhucnYgQ4rKa=@_h8}*HDPE*c&M}#2_A@7PEZuJx z`~|4?Ib=7~>DVrx9DJth)P)I06>r&;%?@$9WVjt{hbWcgWa&!$MIrTB=X{j#I=;zdm>eTe!5>+ulJTLWq zglmDUU()^u(XByqq&WI}zY%bvXE=XUCgJ`U^V$vnIkru&HafILZ?o(fa6-)<`uHDI z|7XEoCFLYH73(($Jrlc<4avD?uX*fu_X!D>v*IzmvOO`*o-u{Jtu+#xp9j@(Iydu$ z)h+w6f_q4=M_iOSpuI<-nJxcV3izoo22}5{l`-0vEV0f+E>q|ME$mv5DVkoVmX~AM z>?e!Q1l>l7z^B;(ZIoB^+ktUE&Vt`hAm8%SG)9KlLhye^LLWEJo}VmsvQ#EWrnwYu z(g1vVF1apQX63I`%17CzTjEEfs@q;j^&5AvUL^66t?T(Erd^04cB?AErg2_e0(Pkf zFWYl3WK%XG^trbq{jb6!P=k%J-)ubJD^~6|oA}FpqA@G~q`kvW1a~uN2Uy z+rhuF{$rpJ(v`C;32O)sY4Uq{%JSd=m%s|jE;L6?8k^W3Qb${u?4mngl%q_hX|Lpjz+n#zOw8dWHA!s*T8dy3*bH; zxkl9K3=R<>&$=G)*jXpuy^Fqdh;*9K)1bn%={BCurIUxEZoWZVtgX-s?Onu#IX+68 zagiR*Uwoa59=rSiJ&{d*xrhC=rG<=aCQr#XQabJ13n&`j{-+gVxb_orfHo2BXydH8$KsL_kVf8*{4?BDJ4?Hc{W^URR&@ zE?3Q0O;j2m85P9XAF66TYIar{y&97 zkrVem6u|2oUGvaI_6qV33OA@ogG@kZXec(gd`wn04V-gaRsL7-nN;Y=gO1WE)z2IA zwuY8c@Npfd!xku36k_fa}N@k$d2 z8%RjOSUinfQBA{G6wAz%%xhV;wG4s7x{+56Xw7g=cL!g8E*mjunL(|UNSIdVFlkx^ zplwn%`^c#lSNnp=7xoUC$iV^H_kXcd%>Uc9q)+IubPRTkNe7pd?z4M1X&#{@b z!=Z7)lSaC)7Ug9hw+3=v4Z+P~{_NGy8wv$(uBQicf-*(;M%r_H=h8r&34X)9xAY0Kgc#F10?(jNOxt2crsPJYGyCx>Vm2Lt=oOXnz!<=vVjoy z&ERy!hrrytvQ6U|2E{^X1WMZ<^|C{~RjI_SWc-LgkxhGDSy1sc;`Q%lT z`dk_p(Or*3n9Ay=Y-SshVl2QDuH+=Gm1W@G@g`27rW#5_INcZOG!p%aF$WrZX&uJ~ zPh_nN=@g&cXYa~Oh3JY<+Z>Gbqz^fVbuc@QgPb->RPsNc5*4wn;!PEDOvjnQ1xLX6 z2Z73p_x?ebeqEmLAQV=%e0<6&-WBXEowQ9n^y~!HW$;TN2W~|8cgD4$9+9d|(G2uI zsFL!ZG1Np6`e*S9egZgihL3Ur^*0WJ!p_Lt?f6JPGyhV#x^p+bMLPXv{-)%q?ucrS zQ)~s`!<2vN3Sd^Gu#;6^BO~35qODx@WnG}kcdJh97_EBtmy#$!wbd7t!qcuu={Dor z$tIcIX%*&A&!}v~hnG39jdjxPx#r`#EF^-K*EL==GZ2;e8(Hz{1w9(08zWSFQ;MvV zsalNT!=J)b*VM8dP7E^vBq7=$gR+C2Mfdv*EzZS_)sR% zG~QENdwNKbSMOio6HXNTyhk<@oQ&9KJNS-Lry*rYIaW(j-PKp$k-gq6oO_E$n7QEc zwgtK{WECPoriAJ5%#jo9DxxoYJUj0B3rKT5CjBa*N_Mm5&=|lJJakchoH+eM8G+P^ zBSVrG@xp2Q=74qTR-k5mB9J%+>ePLjT<3YSR2J47U(6x;8l3D zHzaf)q`@3g5#Id*a^{LTiH4e@g(HFMuh#b}O;SQU6hOLhE9&Z4Gq1BjNLipP>nnjp z@(HS5vT1*9O=c+zOpQuOBxQhRb6a|65>>{r3*_B)Fo3OEf56*c<^r@^~#LWWDN2;+!UL=gPu4q6jWaf{a` z|FhB|864%mbYHs1gppLmdQ8rHkH!r5>IdeCp2$r_LP}DS|E&YDqaaxw`*r$DH0|dv z^K%tviu^k^wxv0ZI8S#1g!DCu1R(H3ZD6c!(8v42$6NM*7a=Y45#g3JUojJI9kqb( zi309ws|~3lOhqXD%;}Th;PGAqVjtO5sF{W_d2=#_x2a9=UB^6J=f&@A`+C^PSp!7Cf_3*F_Go~{o(LC$elRuR7#ylSl>79OyvN1| zEaz>R{ey`6`A3KZ#gtCd+HsiaD%lcU29nUmE_v;zJZ&Idn35zm}OS>@#M- zDw`gdWo0?l5``7$34cEG()9M!c5^G8)9>Dh_+_|IvVA7IDe5<=cVUR*RWDy1*JJ2$ zENFmBZaYn%ZV3uk*L6tYdi-Ll8Fp&T*fy2f{p-RzyPhs(OasS z2eARt0r?#LEMg$f^*xJIf9o5ck63ofwx;=3eU17N3o^|VLF?X9F7!z_N4Dd*-ZWkl zH03yiJC5hTvst-0JQ4J=1F(wXduWp%k+L%3kFA4MvaBUBv`1k8@8lAHr$48tvmf#E z(}raD1!n+#ce@y%-6I%d8vJA4Y&_9G()r>aUEPa@k?~huMW#TAji#{OYnmy!+AVXh zdO({GQ~ruius`$P!1i=PE!~Il{>(Gr_qV|xHrO7nYZT|55rhIT3W^ z6930H$kB`7r|P)aHzrq9Z;0P{yuy%4pih;YEN6gaf=$NPZY<7A%n{rd>Hst9=Q{tI zCG9J%)$vhP)y0bFJ4e}R?&W-4`b=3S$7{#;Xj+k) z1s~~EY{c`PX1%bi-XW2oPJT9xD*}&=u1V&QxLBj#p^^g}vnFsr(R0uzecRgP~@#+u$#b~_}PQ2 zDw)6VgIRLLMi0`_*1GJPMgbvzt2W+Ta~C2r58#j zC!X1%Yc(MSj!6+qGv);vvoKfxa)>SJY76-{ycc6qOfVnI$=~E}y42$$dc+epOV2)~ z)j!EQ;NS($t=&e6EI zB8$C^Xmm9N+0OZqSVaeq7_TQdX;W$4Lnl0v zOs`N3-CT%r`U7Y@348-o*gT5G&9YZ#iL(O{)w*X=7x1b>d;K43q+o=0zXQ;N^Ghn? zPQSG^?EUEfe^_nB`R}(|WE>ATSfEUk&8?V1hJ+&jDC6;@m^zfv3Q)i4Y`NLR%6$

    >K6%S87ueWi19k%K#*%v^}Qu}{K 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

    O$U!lp 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

    e*3XG-GAFS7D-z~VAz9ihG((5B}J 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%0DZYmWx_>p6vF0HtVzl<gheGTt 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�ou*+Otif|$Pk?+NMv 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�ro*6^3!dIx8&f6i`g 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%0D5+?Vep62sJ3 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

    +PhD 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%0AcK$_a{{ba{Zf)!o)vH8lDp z49DMbp9bS^Sgl&sEcm%NH^tkeEgIiLex%hhNGg4FTRa&(5}A1?Kga5H6vS3DYTqdM zXpr~9-opn4`x1|3Xx@^cZJ)u`oF&rF8U>F==C9lQ*4B9Q3&Hu)qGPIN7hT{DkJ{N* z^CafeachxxAfNwV@mjd;Lkv7Y$pB0U;LR;4o*Gff-#x-I7nvI=~=9}&@-jThs{}lxTBIeRT5!GtNmWuhgoFn25a)tvx22tlX zqtuk1{dZ5q`GZVwbWvRk^TYO!Dk-z9xH^ni*Bqr*e!gtek@%r zmQG{_=)h|(LJv5DPiI-wFVHXm0h{f9S##DMSr;a7!rK0{m1T{Vx(RE^0nm7pzNmQP zBkecsu%BqIo#GT5IiM!Kag?7-1oz}|r^N@ONgCwOq)0pil0z_m!}aw_T^>g>cl7y< zWtjU9RJJU@ZslCm+kWTK*g=PhN6d3W1d02vBOrHT>F!Yn#HTXKt#wDUhuXPXIFuq^ zCd4>tIjX!s-b$u}Jc#;e6lqosRFp|K$C!#V+797f52nXJ!aiByLLC*?CMqW>t+kXi zZ4k9@4JNYNaV^Y(a+R-mbyejk_N80}#XTZZO?UTnlqkbZG;)^*X|RdRs6=5Dbq1o| zM2Ma=lymYg(*HX9q-QkQJ%j)9LI8@iVM1jJ`Qjy75aH$xbB9#9tQ^|J*BUXED0~*A zqhjBzG7mTWSPau*!!Cd!TYMaxv*gI%aDv~J$_M3YQOLtYsC5GJkzO>CX-95YuW;EB z6}D%2+1VvZaM52*ThiifGXsbWGnoB7+ULB6c?)yBcFnYmw{AL;({a3S4I2i?3*7q6 z$VH7n_q&M@=SCSSe1{C(e|`nD=b}SHkXyMefEd65F~LE}doXEk z_Oj!J*)F^=t{^uPvDH)b59eLeHQkVku^i@vDf#TtFo&$0BP3n3KV&sTbpho2X@PwJ ziOKE;qZ&lm7B`e;?1`0`6T+z2-mJ8`T3CDkO854U9WN?aK+((9UJ8gmFVo-;eu;x7 zGOk6Ea-g4afUt}(m}_R@Bc1-j zjThh>hCmduAPp*t^AdZ(R5QD*Ln!=&M1)E(F<-aW$1V=v$ekx}`gXUp->SKIW@J~o z_`cNOyR3Rse-*2tu+6_sCEjVD%Sw(nz(P&Xu|?e$-H?xGN76xclTD`adqy6upSkfk zbeDcHdDk9(hD#_U5nzoNdg?wyVZmc+1n_Tu6F>6IyIcTg(3<)jbUxSUc?5ba7FxQ~ z=gck7H_Hp(yEl*zc(Joyg}HY#Y7XXpvmj>a?2Fr2U?9lfAN=XAdDmh6SVOFj0emOq zzxAEVuq(xGRcgPO(hO_fG|)NTR#Z(Q`cU9^wl&RC;P;_w^4v0=Z92@=b}(%(?Vq6ai1H-MXTN?@pi}ZxRKsdGt;O^^T_Vlc@aK&g<<5Xp0&FIvTf%^?*Ls&a_P_u(Q;~~6S z-*jR5qisPp%=iNWpQz*WdtJgba;K8<{7F(>**PUAGDifxr_)r2kJK>FBo=+NwI@fN z(f)YLo~F5j!pApuWT(mZZn7d9irQC6Jg9YUM)hr;3%CX$ERS0sumWfmUuVEW$Q31A z(yG)NK*26FOeo32Em;n4JDT+ZWz=Ade?haxY{-)jy_IPk{ETDE!I)Z`nwK zo}97m|FXEnR}r&2fULBv56#RJH7%FVA@3_$CdwBr^U@w*XqbW!9&79i2!+hyWrC? zJF(F-&)8Zy$NuY;b%ms+Yn+dx&^yo%%4*Tg3qLhF{1`d&&SN2V`~@o1tRo^#*2%ZA zX@`VJKnXbpbb2N!@^Rpq_T!WwWwh<)Loo0OnRUcd2sde+vX8Kxfek2{~HuBcX; zO~LLgoGUKftBlwtf~`z1&0$eIYL)vbA^*QyJ^Y)85u>eX3l&2n<;H?d?+bB!X~2%a zNVbMDd9FZW`HY-6OJJ(1k9m=UQ(oi3b#sDK(eAeuo3`V}K<&f$5wX#XWp4|P%85aY z1-AAbxz%=e_+J9FBQL^@;Zzs8Gy^!pok96eY!NY5RkKNqZyCcUgR9n)q71w!bB(Z< z|F7Z8sGu}jMq)A?3d!*LXhfm7JU&n7Qnm25A1r?+a|Eshq>{Rk)<&E+ti8w zg_V91IY*!%=qCZsx7Z)7P_w;5o96&Si!-zb>`ef$pwmT`wCk37pabI>_{$Wd8SmhpLer0c3izi z46wXDLGP6)q^`Ac=#U^pE!%d!Rv`g=H)+-5IOHdtcTP`ZgwvkSJaj6m?n=*TFw?BY zUW7^m&FT*0tqV&hT`A^|0koNg$is$bv0$)1x*^r7J3$O=$|l!h8gx6&cuuqZ`}0YM z0%as(pxoimy1SZhE!3}gJ{ql{rwrUkK7*H2`K_G#bNK3CVp9ht#*dsskXS} z8RHewb~qzjD?@4grQk~)IB-d+$zFZvE3pO~rDf|ei}j^}C_Xsla2XNP+}9{J@stA> zJ;a;;{LvP(!he?-InSwAMwJ7< zUY}|ZmEYV?EV#eTKMH;DH%%?`*cBXZy@&$swl1~4NrJ__^jLO_c$U78DHCgQtIx0Q zSm&*eO53qBp$e09RNB)Jwq_8wvKeJRsRkZW$yjEQwoZq^ zF7Y@=@QzLYi}z18tWRHoJLv@0gTlGBaTgU@Vz-qR62A5qmBPZiu~x_A@^?|p#KUGC zTH>B>heQWA8D1PAlEnGV>^OCh#Cr&)5PiM0RNd_x*;W&AcNIH7sx1f&|B_-$%U9+c zc6W_)%|7PW%DM9vX&vfNJi3o z^Iu*^5FcEABoH5tf`IGrkgXPRKZO$6Ksx9EZo!Say5gSfx*aX;o>lw$0J_26Qsl?) z+Qa{Ih90EHLN4tnt5R#`gH(??Ju@Rg7i4YLG(n;r?XLs!YFOffF|O?VRsj|umJ`YO z0Ijx%?pq4C{SJQ)dKfI4Z;2l`s=3^vAM*9}MfrzvoF^cDzqnyaxcHCI4tUag*IcEF zS@ivJ+K}R&0<_{f-oXDEt+bD!9-0dFY`+08hfTx&6{Hk{$2=Q){`7aq7es1m3u75z z`yJkgco4@~gg4VM$t$+ZNL|Nma%evk58XMnUsJ?>jmmo%_S%4x@>!qz3Uk#m(o0x_rc{6ia|9mCEd86cRS+Ak({MM#F* zsbI!61`=y$&! zgVG;Xa5V`T^`06$#$G9ZK9fFn-pVChu#y@}QrvQfpAMZUr6qihW?MN$L-e88(=&yG z^f_C});{Xsm6+8gX<#4hg=)eVnQcvh%CBF@3mUmQ;3P2jF!v0|=pSl$x5U8CrF)u9 zq|OFKO@u=NrD3m9 z*?!)ETxh7X=Ql!l{}MZ&?(+`~cZCFwQbZ70tzc`SIFAih|LH+!?zH7V9ngQQhNr#` zZda?@ep^;puAgA5v0PZIGgk$*{?zu)7H*HtPb0@|T_CGRAqXL-)OO0Ln;$~K;q3d} zz+J?8X$TXQ>2auU&p_0%%F(M##ZQ}nyBnPXrBpiwSiNS>?pP<8naCY&9iH?4DsEt6 zW3tZab7S)*yYTkPF!SdDpANYt8xxMnWZObo0jk^gynLOe5g~-YQf=D1b8~dU8`HoZ zJB^dCjLY#Ezr8zG-N%h6TPAMJ#O~7F|zf|HMS! zs!~~t$#eJMR;sGZu$x*?M0HfnXh2lQna9{A4~8{CSTe#I#y zabHkVxm(L8?U)3;h*+be*8imdZ+>fqg0KSKdyj3Aoe#W`)%ds1*>&&|b4_Cp{C4_q z5IShZ;5PPoZb+C%KfTZ6tgd&nGl{X@pm|pf#Vb*RcMN!=S4ztoqdO4u*YnTYI;snx znIr2OQgY`(Ot3nC41G=nj!s*o-b}XZuU2S-md3eaDhl7 zHuSnHc|E3{_^UY3CTo$Y|8fbIQe}BDZ6+bpQp9>gOx3m2mam9!oo(}%`4y)MC!=;= zy^e4_puJ})C+zP_w*C&E(?#zY_rZh){8>v@#Mz>W7S8MKBV8;U4#(6J_Ox}8&8}hA z;Oz!r5r>c;3W>2CrGB#JUOS2#GxcILOQ3xfDALWvSkC${7p^Un0@M$c$cqh8otRx- z_3-!kn3UeHn4<1;TU7LLfdtR~s|6__-gVcmHb?Gz@}o1*N4IATw2u^kw}SetKkQE{ zXwV1R{a?7Zcj&kh(C&Sx2y6el3o9Hq<26Y@r9Jd0nh8UkujU6RQ<(Gmk-v$8-zhb%_5$u%s47CM$^&)hQ!^Rv#Qk`Ccv6Xui3el^Vq=d#gg{1eUS1N4`^HS#C|Bs?` zk7w%t@lDpiq&0QCCSBbeK>84Uq*k*2_OjMN1l%l?sRY($JWOQ4l zsFaaJlp)M*=XZX8_;-&z_L!Z|=ly=Yp3ls;R^&3aOA)XT8&=I)71O)2;pG}z=7R}T z;>zrG6P%F7mkXp;o0&16T^KCnujOqm3Pl^O=1DwWy9)0>0q)(eDWk(0rZ`Xr0(02D z&-`|Q+_hZzW{*b|w=82aNqVi^>I3cXG0g0nRhuo{A)Zo6%(7!%iw%!=v#dvmaARTY zKXPEP%fNT z{tLITM{a(^GU=&U(14zBuh#aDW#tcc6}XBz(r~y-s@ZbmgQyRTxZ-IbVTYEvWV@1& z*vT*k64u3q>lsSo-EBrswU96DdC#$KKsWu~1wn5ny9=~%lPOeVQ7A$SJP*{!pTqwI zSLR7>tqRxnA~&aHBTTGn04>uPzbxA(SQ%38i%p_@%tgJJL9!@tdEy?f333v_%H0kG zscVGOkpUOi$W7b0EzMmSv=ZINlfFeNYvdyX=_%*{Ud!2)RY`lgdTYx0RV)5}LTfo# z%@%eDkuQ{B6I2Z-lCxUwdhU`PXCys{vSoHVuvU&wgN9scrx!^l^5tCCqqeIqFRW-? znxy8SSvlXSYNvT-Mk3^$dmG7uCw9LGDTfYOzj8lY%DR5N6rS{lz!OWCW~`F((J>=B z&{s14!gq#v$JtFm%j2E9q?eD1&3{tgA>zp~9;)`caTlGqeVyeD!r$j-JLv`{Z{lVa zbP9+6{ak^flXsZEz?S`DO?o)<{@a2CK?h%LP85=+aJ6#AbKn zXtbz(-Do@?zErwD$kpu$eP?+$<@vc@oF5O_vmb0KW(4&5AnVa zU|2!-ZP3eEuOlP~2CHLfvSq;KT@tT$*n@Ey%lLZ5DGNKD;mWmWbiebz@v2@N@6BSE zbjUsAH)t1x&iWYmV0~dD{@a;<(^kzvx9ZE8W5~0OrW1u*IDc|Q=MJevaJ5zQm1K5w z%i8p{QfdRf7N%R)!zGfgfcbwAcRXL4ZlzFf8>h-Jeo(HhRIUPym z!GOwbMd82sk!PrHtmuqvt-c4abQ4D{D<@8Cod_zQ1}CKgir>RnbMZ1T^X`7;d=B+O zO*vPM&&)~tzntrjmXFxSSaico^s#}9^5aTYX2)IG_bTmy31oQRjX=@I8msb_sG!2D zP?qx-9R@9nC&4cbYFiVLcS(qZVc2yG2S zAZIbOoKMsoUka>d4pCZ*bD2_#(j4t^4Q8mcYiX#U#(`T0m389(SWNt;bMk01=M{+> zVECVtH0p+i?cD>!Iav0n_c%vfB>ly5qohHq&2`(Yl6n?mvz z7%hBZaK$7e@(Ibt5BPeET;D*B>CY}7?7#H`$L(2~ag186Ns40)o}ufEX~k8L)J&CG z@)}T5G723tXlQ~l2fl_Gi%*FdMC#cT*w<)II)i790 z%(S$$oF=H)pH!^TZvL)z+qOVD@-r~)XdbjmU5i_& zC$8;}J0kaAB>jkW5V1Wg#MjoEdUMsa6|(cLl5%W+KdSr_Mtx`mR%(wj+Xb>MlUMM2 zjO65dK~VwZ6$+0fNAoxS1g+fxgB)P@0PBl$a8L(<3+w&Zf-{9}(Jo!zSllZ7g7Jnf z>;L}j?b~q<9E{vI(85UlkNs?d0_=qKdi&{B>SSu8FTqVyvg~nr@9`~qmk!&J{#$ih zkGn0!O=Z8BlX&5yo6@@)+(20CgDW6DEG9$lIC>2e`u&ninjOZli*O@mOz=)5HgsF< z&kF>O8a}o=quZ~ww43=V0%rW|SkoEP6RZ2&ae1ne1xAt${IVe2IE3IWqX;sgteCi$ zCG(Y6HO0K9;?@QC<22f|Zwo8tNLybFVTB+MZK&y8&f~ipUnkEw|)GM3xu#nG+{ns?S#JX`-3SW9wKk^AZ}+G zvQhPS=_)@bCc#W@%l7BF>K%&hw}R}lth2T2^*u5hZ`*KCa?e=HhnVtCa$T_z9*CuN ze6p(_*0*mRpZgE*o~-C}Q7QIl>jPvo^9ox6Sqc=0`aew!`!@2X%k$y!iq{krs}f7Nw**6wYh9?yLA#Z0KOdfJSaSzs?9~8D$IW!?N$Ga zatY_OO+SkG?i;&uj$){H%1`ksD8k9vDhS++PE8#41CGQf=!b0jCLF_7X&dFxVyV3p z>j-*KYo^AY$uJ<&f1SaCwTCDfDmUwG3}+hM&`;w_D;Y`sf#1bM1Q6Z~P}8 zD-^VIl@{~9P$S#pt=ki#PUQ->Y2>Qk@;KZJ4(S+a#1_S*~zcrrGyti-1&J6g3ox+63*P;yrZN5!~o0y&$DAxA<2Q>ccd6`PV`A3a%)eojf(n zKp$Rbed622CS~=AHF1mD@ewemRM4~6ll2O2sfq|7P|*$KW|+lJhcWn?+f3~ZpMs#168v~r?#c$el z&Fi9R<>KW&TX3aH3uldQZPT%EwxK`&tJQVnhJh`vCX52@6ji+*Nk6h{aNO~8muuAt zZcZBr4oP<+=rFzd8!@Ir$=tVX=-n3LkGsM+-860}++WG>2>R5kJgcIrnC54lO80LQ zS-s}82S+nD5$u>IH0Lx*gnt01;~4!Ht4+Sa^n!}^Tj<$9>HmSQqNTX&qkZ1_R_o() z&O`tj7T=qj!3!z{C2sd5@yH0~d*#t~6Oo64Xk8fjAp;E3is5SpGXu&1i)Pqnqtt*- ze(3<`UdPZJh2IrYBx#|5tz*TdIj9sww)zvrK3MQLCTWju5b{yAwmsQEuBmat9B_?` z(1|ZyWv+vf_7rE<1djqw<&>hefhLC{3 z#cWl36&(SDZFzF^mlAaHvyfxA=Lhl!(V;uK72H-vm*&fH4shsGQQ4Y@pY8sG6fks6H~naLFJFxG-@ode-5F z7EVPv102_0W{hsYC0z5?+d^}%Q~tbbl`fwyc*oHxE0EElAlkqs?M@BGpyURH{isvh$d^jr&iO; z8gZe3-3c0@CTPt&sm7fi>Vq8 zqic2*C6l#>js2=qp+jhGl}xsh?Z~BJk5au2?Q~q5bPcT52qhziQG!>!Z>vo(C#EEA zua~g6mlTHN>aEdR@LVfHiy_{-#lIbxDF z#nn8jqLWeC{PK*r%{?fIIfU9i$^JqHnLiY{_41?J!-EoJ?74h*cunR{*e8_ufxT>Y2dILC_+Q8r%{S|Nn2U68!8v0fQl!lT!z>_CU^w#j(>E6+Abx_F(Hmvb2& zk01|k*o6+ZO%s8G8>3s3Bp%lEq+_4!uC%`Ugy|1OhPu6k{f=aQabdKY1cQ-u;I=;; z4j13~LLqQoy2bS`XO_IjC~QkGK=_!(oS5r9Cqye6*VZE^kA*^scow%{m|Eq=9vUO{ zHG?>ZMLdC8HEzRl)Q2*?u&*)qUP0)BGnyGB>f^p(8C(m}{LzGH9q|~4fBNg>0QCuM zzLBNX$9nL61^fF9ctF~As&w$>uS2+`h{L#&8pvR-5e~gARC$^d-{hn`Y#ir;ocl;i zVb`YX=cLp2E1GUjg(jbi4$98P!nO#spBwudq>ObiSy`OQV__2zWIufMdif!?!wyz< zoP#(TvK7xjSO3`1aLoiTPq$&qWbc`t6m>NU(k&^Wz`~k+0(KoOR(pu7QVAxhnbu>>yh8<~4RH z=B%Q%$1KC8VY6Rq>0sA?px=*+U~BSLKzzYDuep5nOVlg=P5)b;6}izKN%~cI8-?~~ zOIO@Z(y-C;`+!ZNR#4?HpKv%G14Ii!6DwOnnvqH}(Nd{)vqsz#GL8Yt`#x8?@ALDZ&pB#zW z`Tr0)_W+tT2g5{DkDa3v9>LD^vA*1sq_=FJC5=saKb$q%>%ZC2cB|DtW+D*3B6~s_ zc$d8NsXmg@> zLC;#DiCjN#rtEk0V_0YL!BYz4+mXb~?E&Ch>s*+k8@r)K;i*B!iz!AWi&7ZlyDev% zuIWTRq)%wgpl)j08wGX=)-gY@1XPhy7n74KhbJ6{gU5acWh8OnyOuRyJZuT$;{xo5eY7qSxy zjg$>!%sxtBipd-01Y7U%YJS}hiFy7D&*@GO#0lB`*3Wq#V3X@pQac`s z!(-9Iap2Ur*2hEG!qGHW+(+%6XOi#}Z5vQkz`Ig83&y>@8uWSXFZkTGe1%Ve<_LRtH{zK*dW;!*6+Snld*E~^tww; zs@dL@lw{Ar$if5d3Fy1%@~uUyN_;*5BQoC}$I;&pGnAC_z|LZ2{gIrU?$jAdOlvoz zk89!gmQh)OhtC{Uq-O zM8pdQBHB)TK0de(rX%#goo!uKyxFRPJ%(pJ*oi1DM7^6Yhtuq=x!E*h5`nIdRQw8> zzJtE8r#8vAVgf^CnHd_}@uTh3YPmfoh46GMn48&83Q!EYov#vMv|PB}=to)Exfhbz zPAjy&dq75D7{s%T>-(*2Tlx}uBU}dz`9ie#`j;sb4Y^I z0_~e#+D-l5IRk0fU%ym4Tdy>gggr0zW#rYQAObftJH(huA0ds3 z%?~41{j6L)x@HY-5^j;Pb`&VfhHnQNe=A0H9uu!4apnEum!#4(BK3Fp5Vy;Ypp&n} z?0weun*-vCu19gdXI?I8VVVfo#tt;uiekw<_NzkLdjsJnxSnN(d0?pRs4&Zp8GumN zN?kks4B=LXkN;-nH?dCg3O{zO*JTP9$8j9JjD zide>xn7gE{4?bT)ms!dUg`uzA0ZRIl6`D>5YsOELMYG&P%%9#~+$uR4G$+;EudI>} z3w%Ef3!FQ*{Lek%hIZ}CZ9aQgG=&6&`0}A&#Ds=KrU^Wo$Z-Xs- zHD?^u@O4NvfwN9t;L5xEXbMv)XpxtNX(>&xru_rfjrCeOsUcbsK>I>HS0^;#fUOhWRtOS!j}Ok z$WRM%#ca{tdxh-Td7|Ibq8)M2kSk7jOIGkik6_OABB zE}&B3VYEt}h)&1x*Oi`#U9fE#=S+UtuwS?ishjxA%FP|q6w|F^9j2~IofAW(K0E%<4+h`Qv7Zcw?u+pWywRO%>Nz09D4z? zFi=*7*Zrs8i?{Qb={+O%ft<`f=;$lZ(tJ3Ku5(GH-)azMsf@IcEn(d1cW)oI0wmE9 z8S|tfrU}dz;n=~1Jgc3s6DV`u_#9+q5_kOsl~;E7h$8wy+#|mEHCk09dq~#v^N;w0 z(r#y_Ni+Zy4$P|cJCrd^^ zpQ0@Z@+w>?D2B&djD^vYSOMM9UVoqQyVsFlLkh4r5Ww*R>y{k{X1ZCyuFKX9JXH=q zkqz}mV_15o*0GZ94QXa9uzUXqb5?j}O|s)wY~vO?H_rJZ z<_5pKgOc0cWGA`;{mo!so7T0e!Q;$0-94uC%hVii+&ZV9;cGy_UTlJ35@akN1lBbL z85F>CdI{DiAkEfyLF6w+l$zw(1(qMB?VJ3(`CSU{YwEz?lULu`5XMrKI`seJL~v33 z9n<;~2KQ3Kh4A+f)^weQART#=zt>wBvg~(nU0MzN#Szt09_eSpH{Ra{8`K5j5+PQI zU0hRByV6>PmIPw~+^;KV4vd)xh@4ffl21@XrJ|5vo`Ex})v z`**=dZuTAvLv$8)5Pe)=N2ngpPnUktZ}ZatKs?>+-MBh+PeMLwy_o+Fu9apB?YLz( zHxpZLD&9keD@+?uIP5JqwEQiK&J$RI5>Dz)sd54FUG%-6>kfUIi>)q+JSw{Z_^n-i zQvWEmLH9Pg_K?~Q{NP#pW46rsVjF`^m{ZdH7w{aHLQTi9XrzBI(tc|E0zfZz2!mGY#&DP!p z8y*80iC%>^m6r5MBRkdjH;lI11$FfNtT^ev1;hHv%#XBthYz=-0C$kv^(`?j=N<&M z*5bIGzjmPYh<&wgE?zCRf0rnt zl-8`eWAG=~)2kXzgZ!*jfkOXFDiQa@fuUk~wSg^7ODyZ+z-sVOIEc>SN)|T%;;6kKS zF$~rz7rF`-GBF1fWe^Fi%1Q4=80dBbDsT5FdT0pj%(4nd*(s@O;WkMiIV(rU-VC+X zw4ILLiEnJ2wfc03sLxjCdSRQD6rFPBe&J=T=>fjlrG}?cB6U#Ej&#;g`)L$!q~*R4 zFZV`pcoMR+1{f^^O)v6*gjYI_j?h*+WQ*kBX}n$t24BX5JIa{oo!|W4cT;(Odw|OPU|M|QTZ6Qv5{$HT}!IkxKT_oXffqSHN|~O4t@Iy5T7Hpor=c#09&HxaWuL zdf+9@66&|tXaZBR6?A~M3{funhdFDo1_JGf>YjBWxV%@Vf^%xR8>D}&tZ}p| zkqtuY_hV*&H*yWK6mn;cVz$ocB&1pkC|;q^{4ojXvKkS;2N~mmv402*4YZuQPE$?j z){m)BfpV+W-xT)LE?|;&n8$6=gtCt@wu%l9(KkT&S3UB{goFghry!%s7J+?GTC_yL zQ{OqU=}?Qsr6dnCIhXD*<61g4y764Sf8B(d@bf5%Atj0ryXM; z)KxgQ-fZpR@IR~i{2{(}uR@N(d26QT50)T(fy7qkfD5iz;Kv!UaCKa@W?x9O6un8C zzfqge;KZz2NZya`L^nsO1i9&Fk54-7B{Wdpsd_?1$iW5 zNCRG$CD$*WnL_b4WBYsl`HnaOhxH8->d4mRsR1fLx}rHoO{yI#lBGj;QKWN2F>8ej zL3IaY2gGXWhcCe`x`74k=?(T!o$>>Qw;mh&;Sv0p|Kha9B`6cC42k*XSluR^MDh$R zIt3Fd|4Qk(DxsEe{jys8A6ozzEu=aq8AEX(Muek!>*1g+2$#}p@;zVKWw+(J4&_SR zNy1eeLd+I1iC&KF2}Muo@A3rUdHPI;CFT(95m`b3W*B}O@r4)M8LOKT@X7DKgP=5r zoHWgQgs`cfg3xVE=OyL$9$lEerWKJ|amArc29DkjZ%@DhwbouzwJpc2$r^+0Xtc?HTT5YKiBZJkb8H8R++W#D(4}{g1%*zD3g3s-bDi>}{ep zl?qI(n&z3C3Kbdhew2VjBmaBh*~9dIO{uS~z~ha&ueIV{$_!Pp09x&t-0gWn+zYpi zDUc|EM=T4O6Kg7yAowZuYtCr>a%x>?g=#9lduj#qO3h&E*+mwPI_|ERV!~2VUXXWh zN((8^A4%E%v2ZkfF-N=AH;veE8RxaE|JmPj{9v-8_2O7Zk=f(`|3BGCt5UA=_}OW=Vn>+&t4-r^;FRCJ91`vDE4(dF1pG|>k(%s z1m99Q{O1JaVc#s5EQf~ZhF_p3HVqWDvGU=W={V7CWj8;FVR*faZsYUsX>_%&-|If; zr?9ACMR|Yqg?&CfAK=8G>)~0|OZX4CI;_FX{|;u2n%EdDkt%cZ;qDEX5d(|GNUtZD z&q-OIB^^vKzbB%PwVI)iF*mf)%?6G3Z^eBKuC*Jo&Cj3v3Absc`RgE4Iq=mlrW!!X zSjtl1EircvvC%{)q!*O=?jD67r)0I)`=zts@Ae~=3=FMeDm`7umNDT0f?Wg|Md7O{)Yq_IL;AZdF5|+>=r|VPAI0tI_wy^3w^A!6{HbV+mYFVli{0^x1 zm4bLS4>FV_?N^jrkl9ZsDa~})J|L&*wEw0}=!B1E5#dA6AhN9B8mm2YgN-Sqe~?0)PlGHYQ`X|zW<_-m1hZ85HtfSw9QQ45+yg}9INn3okzYbS(N z2bVEnb{()&cvC%U4op9!=ZbxHLF-Yrlk(sux$*fh(Xfr-^7e4fk>#OPI9|c5yW7&m zx?osoz|;?u-)8k(wKY;^?|XxQO_6lIgNP5TwW9SVv5X;~^9pqkeocb0k|Ij^FEXyB z&`kcptwtiGiY24bNGn;y3u5N0dmKKp)U*>Hzekc=+=aJH>=H8ZX+=`jK4qJ;UN1$Xysn@jl-9EJQ z?$u}!6EWJOt4nYBg^^s76UqBPG%1`%>J8iggjo%3NqG_X2TFcPcl1rMK)k+>);zPG6Kj^9_X` zhr~l&Ab;3U*oq!uzq|u-&Nn)SG5;#3c{%wlf30ePS`S|lPpKxKU?xWx@KUsP0xbRY zKp2$MRNQ{sV`G$f2cN;rac#Xmz`V#T325iTcGD5lYTI>zEB0tjk6||_t($KZ{j1{C zf@-N)d875YraM_*mKpgs(S~_UO;=kwklTk0FJ{5>L6!%Eow^Xj^`=1_YoL50>rkrd z)~gY9OxAYE%FDfy9TVi_38*h)#qwbXEJSjhrGXWS;Q7&I&k5-wJmIXv#jnjyPT^Rk zcm3>+#4w0FanerHJL)X97P`+$2f}!2&%!mxmnw3D+X)$RbfZ;CMhnQ*6tHR=nLnX# zg1_NZEu;9%wWKuV2JFZ=ZKYGwZ^BYUc)$@xQw;mBgBUj6SJ1~nZcCEik zhT!))P7UpbH8JREUZp|=g-8B@3~j~i5krccNv5ZQ9}f}uA#r5{h@+K}1)Xm>C@CVT zA16i~%;h{eZwhg6O6;?0`X5{Ve^6y^wEQ@5I-$0&P65H%NhfI=BxCv6F3m zT(uP{lx>nigHifvX28Ny_NOcCQaPbQNIP<`6cb@sF6(T4(;-lt8{`|n(a;TNBhQbVzVxA#;LSfexpM6n}AtXG;icW6I<^6XMwBZ|n zl^LEY`QCi)C9E+3N_i*^n*|lI1Ek9f1?S6`94H^1Veoy=hbcoTs?6VbGc|wkHTs_85Kg;h(og4rb`1SpiIH~6Y1(|#g0C~N|{+S@tgp`sX z%V8Dd6~lWn(BGC*{*D==*UKM^D=Hp$vJGiCmj#b+Bsr~5egB){BQfCDOoGX|B)2GWad4KcNp~K=s>@W(f>;dLqkJgy0xB%#QU~b1lIR0H` zJ6(d;Hq1~a)+BHUynb5q8bYP!@B@b5b#Lm}idKw@x%CQ&w%CcPXM`sz4z$iN zJ(QDB{_P3#`kPICo+>=3I2N=@Q#6Aml%l!D>0t?39rz!;vBGU8>7o==Mmdv^gN*Vx*? zjq9-D+mH%0a2A$oNPd64POE3XB+$`@7^`yYh&cJ(A^U`@CIUDMI0>D)b&B+RH`?oD zA$V2aTCkj^z+D{g{!b0J9RnV}o~7=E6DmfhNg30nY~OL6j6=8*$}mwm`~@?DA~<7) z_IY@~>Ceb;csTzFOl217ktFLJ^otqHUwutT4_X#AiGcB#-=#>&)0bFX*2osp7=1cO2$C)m0Mvvnb5S z5ncz2yjmP;R9h-Ho$n;k7VqL8VurOOqufwIx#5*S5GA9&3U(ty!pPV{tx;wke&?%n z+y{w)D5x=TK$pQ9WyS?%M9DlqvP^w~U6DC14YpbS!YVm~>zUvC>0awEUW7;BVyEHw z`kS{*`=Ac_V{Z8CtoK14#{#J@4sSsy==t_#Z%pewZh`hX!i$)}0@w0Fn-aSD%z6*v zx1&C|UHW&J8NG~#&UX<6)2W|d4;0lw1OTkIw9T*K9T~kLf-cR|ZopN;K5xbW2-%NE z8vd#IoR@@yzy5(Z(BGkipo=VBCaL_9uHq{^2(md+>E!1paR@f!4f%xD;Z@iZ6wJ@d z=kiFN5VVGH;u{$lLAnE`?fF;s$vSUmgu~#bQ8obPTQMbN#kl*z#NiO+$MZP~s@rEq z43AfJ9Dn%8PP|DcNM7mm&P#%;!JvUo(&XSiIjz8m9r>4A$27N|9AO}|gDTHkukw^v zT5lchQ3VcSzT&0IA^0U1)o(^ZbW^l9p-@R?!(A&3=Qq7s z5h$u~wMA_PK}JyQCom#}@_gkyJmIPNZz@sv9OT_1zJg%yPPC~Ul+&OUGw7{J_r;3h ztE|kypDR`(McrJeyw&Cv3dxzluO@!I1;;_OW$aLtbWx@y@D-1R;`)n@rlWxAh!<9* zErF|%Pfot;XSI2E$1d)?M&B4P`MizGwc_)$dJblMRoa?2v5sR%M|&8KPz()&t#Z*H zKV$`^$MB==UnvD82>R}MaJHSHuEPkgP1YgFWRewb1I> zS6>eyL|uNu8I@$fv#fCwZm)0y6q(?Vo0{EFyu)d6WnD&wJTQ9qQD+|H z@mziQA>3X@J1D1aa>gBu;P2haUv0Cab^2BrjEB+Zzvd%Cf;-=Kz?+8t;05P1Ip$be z!I{YxkWR;xjY6uX2#JN{pH6`IjurQG+0#a4Am&B@#I}PgWhOPjg;y8 z@p)rhDof+6>Q_6-;?AsdDW1LTZwpd3H08O!YE%Kt<9`@06Z8hQom6yMzW3aYRglBo zwn9~qu>*sU&#(;={OQ-kSSolR*zWoDis*sO8A8|1I9FmSv3cLOmwa^7nm>P_R%KiN zCft*`dvyAo%>kH(6K~vH<=`BpvIz+I4x%2UpgL?uy;h0Hy_CLGyx8BF+ff3td~26| zT-Hy|UY+Ed7wRu8y?J>Cw`Rx#=UCQ~Zsf{+;)O~iK7a;fOG}b+xcwc44KJTCd+koT zjf9JPr9f!E{GRH?c}K}GiMx-%tZL%5Dfz5)%5822iS%BuBIJ1&vda}TyL({EIzi%S zMye4%qWU+nqM%t>+c-0LZLU+k^1CgGOcOT_2P}v?&0|vt?4_gT--klXjXfPuu|DKMOv?;I@kqyW>e)tQjCpG2E!3)Fm>d+}Qn<2iC5BsJB|1$|)wzeSG z>}>`YmBMgxYd{8TX&!9FHn=n3M;w?u#_}>eP>&=3XFy!xAxgFIdjd~TG>z9MRlCFe zJpwkdG90asPy;r?EG2Nultr2D_B`0-UG9E@A?UQ!G z?!4UcKm&brL^_8((edZ9juxTz<191hH^YXh3Bi_R!2T^FL?elxfH@TfZS%dRt&~YI zdev*`s2B1W=s}7K4g_kJR}@2P-wIy8mi%1W73Zp1cm)co!lOad(P+4Z+qtDF-6H%R zW@gegQnk(e;0Ir{4m!8MKBXzK3-*;cO=^T`B)!C1KS)_-7h&JeuMC`#96SyI zbfTyZR|mC>)_cD4x%UNa5sc8AXTV+ z3XeabQ~g@lDSt3Z5C8(D1{a#7lYpcifQuC|WSiinQM;uB=!>LRVznPm%s-KR=i{LD zw4Ud+CN58=6#5l-T_>a(?V?tlNY$KAhL=UG{QRmV@i!!&q+(am{+NoodLb?d*A3Y?qA_e4 zoWLB?jc+s&G9Y{-*E^kjZKD|9K$+5LFujzyWYy5JGy-4&d?yL5B<6juVQ~L@3Ic&> zv)Py~HnPwhNX_ZEla@UcPw~o@E;l&QZya9PQr?{Qboo5|em{mE~CzpfVWHI*j8U zN^DJvnNo7OrP1Sqym|?Qw2f9f_cLQyQ4H=X!++Nf*ueb`EPvAynpF;@P`g*}^A>vS z7MT_B+J5Q8(Tq*7e>eQ2T)C8+KSjCn2&=oAQ6cj)Q6H>^z?%V->;XqUtP%4L9ZzD(%zwfOF7>N|rH9o5m@m67unZ%qe; zpXgA18F=(o{|o4OiuzM#hckkLwYL`y*dm5vwIQcXcf`8i(I3!41DyzWuw#sM^pCUC zJY54%_Y-E?~|bGdWpQ<-n&4!C%BX_Au6AJ?mmdckxPWoCT^y)Nn)R4K-spgq(z z!0!$cGWVBguSeO^ZIDp;DymLs+4*w?5=reQ>{{&^eA%dRzzNUoLZK(!ZX$P{ji;zvu`!@ zU+kx>wxNPDnLtu*x}KAw^t9qt#-S}g8MS8>bN2G9stpgUZ~B|Qh~DrJ_VssPV3**J zT2wKG58tS%8Et#X?B|%u=dIJ5Jx7NzfA=g%7wkHA|80Nz7LGK#80#2EL^wyccFit%~GpllSWw=9?9S7o~#s(^`#Bxd{e8 z)%mT2{(p_=qA$=P6{7n8%^-Iwbw^Oq!J4#9u!`Qhxx6(T6+PcL%@B(;7NIGvn(lRR z2T!%yrKk=U`czfNw@6jfBSp04Wp2EJP*oi(3h&4PYsMOr{A`WSaVG^~?91>a6d z`pr_=VHSG;YeQq%e9ahBM(1+b3Zt>qK#=_C38)Q7fwO5VL9B8jIM~=G}(FkKjyvK2< zjt>U{g)?d~64YVSwy3z{Qy}HyvYdZ=(fC37Q;y1&O8rG55iQSj9;SS90}F&5jP?Yd z&})mXq&OpD9BX>sF>%*i9IwK11ZE*;bao3l0HZ?s*7slrH7>)OnJ|7l|DNBFHaokd zrH(m%G9t_kF{3nUq!*FQEb|lvf`VA3?P@xs-K(Pj*^gC|{6DLV)?42cf7a}punMD) zvn#=@039!j2+0VgwmBlawci_Kt91H3$!(Zu6Km0b^j4xX^C(=yqTM=MWgKDOH`~%) zN#ffw6gh%^*um9?dlzN} z$Ix(jA^FuWN6uLVdlss>Od(<2-`@EamReAsRt;M-jur6D^H?C1dNch1!fH;eNXE1P z{1e!fn9i~huwtK8?hz+Vd)A9?xbwSoloJf?atHZYcY<%OLM=E_6Sf{6n9b?~D^zlL zvlJjUNroxsvEoc)hq<+P`0uhf;0)=};OP5IP_zo>_VWi2wZ+^{E5Z}uce%oPc#WN? z-O5!`=;oklEYbMN-R4d;d7R`MJKnT1m&w8qmLcR$5@(SR;V$85LcDxKq3!8Wjk@w? zn&t-BvDs)?>1_d`ta9ZwOchluP~4~01#fakM15+$@PVnum-M`Wm99ZQ10CZk2C-rf z4|(V>X#HEX+rE5M&-5E*!7a6A(-za*{2g|VvaSwlPK9IXVN;#2%E%1XFMwBG@>xaF-9d{*UVW3QjxxwMF(tK7tb1yzt$@dA~pJZ>h>>JA=Pk&|@ zl>94)uT)-Qa8cp8IPvlv$zh|?>p~vtGRWLzjeW$3OqfTUwl#N_`JUE0ORx))lYO9p z4Al?HcLHwo;2S199kfanbA0!F-fW6v-kB#w9Uo%!4S7}<@DHlo)h+v8F(&&TMdu#R z)c?ovZD$v3%zc~N<`T;Nl1pTpTl6h-m&9Dtg^;AeZtj$!izG&hZZ4%#iMeG-weBiq zq*6(9zi#Juet+<%$9X*LvGe)7->=v6Nu9deRp1nT@s-OPknW6nR|)ca7dyw@9p;C~ zG4epa8vo#CQXPW#cOT@vW|ifK8TsfqpOznx-*x(&p3Dy7!Va(_WnJHfsY&oYri7!H zlzP}61(LU|+t&BqW>thiadGrF#xnz+3{T&l6 z@r@L1`y#WGvzAOHvM=^;GUsnpdtCuoSuVds$N7V(FaIfQB8W@E*lKC~EOK2N;;;{p zcLX4Sb~4c4y;+%%9on9X4!NkXf0qRQMb72t9$ZV+B$ewl;5LAuE$mMNRnm5et{vek z)(3<7*yC;1snH87C>u+N!v0i2_n0`6TfTsK4NN_?67SzNuzE*?hq?Mf*^FKE&&rKSC)Z?56{V$ zXF;e>5e@sANF+9TYm+72YXd&3CH)>^#7G%q^ZYj}wA$^^gcaD0UYDuT%2FLTjkshBF zX|r%}mp?>Em%hLyVdJZHQkKX*r%Ih9p8~}yFZgL^4hhoxDi8A^ z^k9qfKXMmdtkGF6P@7MO5en1c6?u^MNxtnjp`{Vu{1G{-$79m-ml-2E0=369NFBRt zhLd-aSDBKzTX3;5C4*L*CPm#DTEF;IfOoxxZ>Hfh==qxTzY&tVZL$UM`G9f8C~uR+Flr=Sb--!Z?R zvd#N>Z9o3C^D_6`?9W*@KOdU2Y*{hb!#_NsaCB8oxomFQ1u%K-JK30+F-%P?%X)YU zUiP}`*Blj1_Ts>grYo#1T-jjN1sR>5d4NUl$7rz}0zCfWa8~Ehu1l=QuS}y^h81n$ zJ{f`U6(q#J|2)sT4JjcWvZts9=eeZ~L)8}O4T+D-Ys_mrX$nfQBy84=!lzCsXrb>1 zb5<-Ax#LIU8ANOAp)|{`lKXg4yoIu7a^R@`u9b;yxe^fh?(!9wc>gWo#aNZ4FmqAo zk<=`X`&r%Q4%q6wl&x~^Km7-EP&-Xz`zYfYN#{MDd%w!@Py}uVZK8%R{G+NIU|4$J zCU+46SC%T_Hz;Ll{OgSir{MYb>9PMwpwfQR)9@#H?j+6ol-0ewp6fdA$5;nEzuDp_ z3%>oWM3Mh^3x1w|A@&(n4~bWf=LTZY z>DmJfo+hKw0ke>-Dyom;4H0eZ+!kuuLmR!WQoNwqK`qREyGJ)oN`M%pI7sbkqxmJk z@$S}nEk;HyUAjSZRX2-{li3v@4(VG5U@5yLtB9Vj!@En(v-U0nQ@CK=#P82@gdx_? zDf-C{O699z6_dm*XIGGVSfx<8CpnEpMYJH!E(ae4n^}HdNxp z+*NIfj)WA$p1F}eca+U%$hYLYS`^>8qB&yfJyouXW*-hv$XVUb<6KO+Z>t)xQ5f#M z4vlSEwXXPL{C;+>T4LMfQ@U9g`Y&X;8)?fMtw5bFTFz$i8(34&9QiH@w)KV3ItM1S z0ZCbFh)Es38QhAt)Xk~!;07E||KFzGXxK(`cjtCSKDsJ(r{>#r+j!(Am~zc%SGHA> zuL7Cc-W!V#O3X;e)ixK{&pFc?a=6O^N01V$dz&md#r!723 zUSkuvK`_-L9Mh;=)v{diTPE7_N^MGkXSZWcPs2>E(Vvc0Za#*FHHXrcX61mp?9;ai zLFJTQtLo2-Mc6lSqtMc90&z)(i2#|mV2}4Mt_J?>TATIA>R8t$tB&xO@!uyL)c?7* zEtk^wbYN5VLQ?nV$J*sxdwQYhI_x3*%3t7#pLBq1L?r!;*c-ZYy#Q`N$Lv+Ub zpF(bRfSta($Sap-qjwxSLIu>OFBde=$Y1keTbx*uPFszZMe$FFjy?lHnW6K?mF!Qb zkkouHM?>IuHMVg`guo>o{YxDif!LQO4{i9US9~>J+V4^sV4}ce`QcSF2XGc9>GXyx znP(a(yY#0hLf1KRFm7Y(OQw=AvN;OIwn@LB$626{4+T0^?AXcw@CH@`iz}; ztzh2G!}zWGaeeOGR@xn8RrKR!xcou7(H;8SL`$Jl(W?Ro#~Bl*H?F=;grL&Jqn0tR zbaJG_&yE#9q5mI%1rcc>`i7_|2Z9b^ws!X+?6EB=@aS`}cuhj2gHT7*=@EH{7R{Pz zY@+!2t<3y&0b6sSamQxdn1Zc$!9> z=kTCjrJw@2yM#mN*H;lO&QQ~frMdPiRIY_Tz9SvL2$JKDPVryjpm zHrcTsV3SP9fm*7og(j;z-$pb%BB9~XzFIry6lZ|eH_G@ny>`P zQ3z>nYn@872=|q+n0-$O{D>TouLigLiSOq4mM8MI2WVlv9-aN9ZRRI%Cw|5Q7nLBDo^F%-}%*J=wA`kL*=`gZAw6P}ryBP82k zB)Ka=!5^oob6%l`1lscHa6*Mj$qo9qC+$3kRRX`bj4QelL24YBL7LB9)?z1Im`4 z!Gd7upm=l;Yi7FFKZ`6tZ5(th$2D$iDP`xspw*7svi+q|h|e#Pnp|^b)RvBO=g1be#s!pb^TtS9PJjyG{b{=KU^xA+v!371tbepe zkgr=?bXL$V#&*eAgrUxQKN);94cc@NyA-*97PF75VsWLKX2ZhB)(R z0nbgj4w6KcFkn~KE4NAWP{B`9fqU3?Si>U9q8rFo6Q$iOr-3%WUsOe$bW$T;?F>xf z*++&dQm5H(xo5qLA7;Oe&ANEMueu+jZyYYg3N=X8?t$F8d{wE z&N@w|Kii>MOWzR*_>M=^HXI1vo?BA@dFGIRC zh5CQ8QI6Z^nWLSA9pj%1593T%nFnYkJ$B7fGLMaozofVw{DD6NcNo0OFl^^8SAdiE zoWIK2pHRB%dSDNs8^SR)^OKX;e`=oTF{`}eqUDj!e65SK={>&2G@PG#%ly#jy~2Q> zNEP(Ac^5ELoMrj-vy*h&iM5&Vq1CJf1gF%C1rQu2?P5)PT8rut4>F0hdoDM(micTtRVg!qc4-8_uM-_ibp|hS~mu zdU~J(x+|*WgS>a~iHX*!pbRkF4gvVz+AO@8VWy;rcVV^~n^FW4Sr;a_sE>wY&5qJP zz}mqXy>`uJ$;!0$gK^{Wkc>PK=Lzruh_ZX9$tHk6OMM}vZIYfQAudIZWl!#k~6EcSy?YRZf z=gT-gwpJjvG!0O0c2c(2!~SXS{Gmu&rvg0%G6XPxVJ%@5)%($`(u9xEL=f&IXC>`8 z8K9IIl6@j8^K9miFrUKA)VHp&%C8@F*~DaTB}q4!f8!#JPV7MW@+FaZ9o59Gr3adRdCLa{7JL75wW-!)DE!n%!KQv?Q%<&l?w4FW22TA@ zFrCNOtMw9_{vZ{L+5R{qTW!wi29w!tTBMrV!$oT_wV z8r8{1W6YctH>(bM7Q6;ULE0aO7|_*zk&rC?#~ds2EF}% zzjp4X>(&N^34%+gphI#ltK@gNvh6#^y#_#X)K|sSy;gcJ-DmV4={+|Ab8)N9e~Z4L z-5{tLxh-uT(Z%r8>e>`rVDHOXIF#Xx&+bY2!sU5}u4J#b&z;n9SX&xSWyhkF9Q<6v z@_!)?eHgK221LLt=8$K9_VW)y(C_SWWr=p8mloDeJCZ{nJ`Mfn>)~g=2;vjm6#}IG z@0W2npJfMHy)+~0u_e~!^qYeVeql~K^FE{3WCdC;R>&{c|2tfnu6F79me1{tnfv)1 zd}lO8jWs2>^ADr{Ft`6d2m$`zR!_B6D-XWg0LzZ?iHciGzxf@hJ^(6zUmx(XL_5dp zE_6I&NHr%-h4; z4XHq5~;smcYxax8p0)KW!Hb!HS!m+CBPr)2b=w-V%rh>XkzU;+I$oQBJ& zkC=5)ydwEGMk3!ro*Hb+-X7dz83gIRA#PK$YET}4$W03EOnAr^#qzfZi%ytE72_iR zBib`}I^IqWX5v-&^<*ETiqaFm;ug83{%o;*SJO#J!edS4dx0ze{DmBq=wzP_3;Fz z|4$z*`LK7l_p46f+0Y4iRpkr zFZr$ps&bkg?-A|jx*QphjJE?!tj$BymgL)Zl14*D-%0>t5x)c!Eb0m!?(B$idic}0 ztLTd(sawOj1Ir{2ws-L(_<$e&ra-cc)oO`G{_tlENv#@B;k3+w3(q<`k^jgZN-BV# zts&IGMFn*)lGj^=TkWS@r|c&|OXgpN9*}k#MKYt^!+cb-cPP(~`@lrI!>SR{tEZkg zAi#Dy3^Yf0? zkI_LjGayL4jzP7=AvM!MVgMmJH8uHs%p)17)_qM=XQQ}}pmokCOks_O%)=!T{@{o z2#vxX$d*X{??T&#o58*bMZaJ|TYgD8K==TkKgRO!kS$|ND_GbG+OB1YS>~QPFS7uI z_yREux;vSJ_|)6vn807tdqn%k1gJ9tulRAnjpNkz#pkfLdxYi|^_J2S|1*l}132jJ zGB?1&BI!N z`)HQbinbG(_ufxXfxd;W%)p}DIa233>4#(QC)AGf=8_{2H?sAbl5uG5;jtz`*O$Qp;aoe z*d#K9uD6a)-R|D>iwb;~Me-5+JQrElR%JJ8m~VT^8SWLHs%l+&B(5uqDEna2tD_B^uibS;T?=YUJlsh_bNLo0w8I%uH z!XJ!8#|^Q!R}JJC`UR{9>UR+96axsYD*G_uzzgQIvEyv8J7@pmN!XT_MCcaNr*Y7 zY7BJE4^fFR7$OO+yYSLlL5PD3L(*e_Y?YlM;=nAp{7+E0C?95Fc-!2lNKm5S{Rn;+ z&WY{N?QgDZXXIW`d9x$_NYyEmIt&lHCP$m6E08<9vXZ?_SUVGd{!OAweRXp6u6V%j z%0FEr3`fko%^fwUQ#TycjhTp~#npC<27KXM14anCN7HITi18G>ulDb7TF!Tnw8b3I z=Csk2!)=2WYy@5;G3;8Hl)T>yCA?K&baYeBA2)H1E_ypm$DF>W5%x$1cu|$Q(o0ev zud(5BtmhLNkJu<<(^poWz&g9@Fpn;@2*PMbtuMEt|)T>j1e`If;qp8|-iDA|+SN0L}U_TCw{$Z|`4+*cA zrOmCVOz^9{t)V&h!;Iy^bDs3UP^0k-)}L%U>m!tvPZp}Ga{W#k;%hWHM<{X04Jm=C z0v1ky)e?8<{3%q^XOcN){X@N*WQP{HVSx#Z677LwWLgDf3g1D*ia1lFBy&`@RSSw7wB)sYl0Jg`_P@`z9_EC&1HD^r}W& zv^HE_>3aBAak5R_W=hX~e01pJN4l;se3^L|pbKpYJeTkgIMDXoUhdWpOjrGvJ&-Zz z+Bqm=XWB0Jq=Zta0}NOc6eyR$nHOR9`!@&!eCfK4s_|stfaT40coliX5%JqsH1ZAt z$io}_QGS}xz=2b*23*Q|qU8EpG3h7~BT)((&4jU}`Xk>FD9LmuwqG(WtIzCHk2n-4@{~#T3pHf5=lk zaC%?&i=XqMw2>S$wrqu)fw>tXl`j{4*T@jwVSPB*#C@(xv-{IU@Hyd?12mWcWwR3J zNQ_fVm^gIIy#oZiC7=0{->Q3;iSdpQE>t(V<@}LRQV&zW4j(sgh zmsOn7=_U1JeJete4{3oAxa8)@9uT)a? z-p-c0GY8zq$MJu>2SrmQ@bv0|(5wzvO3xJ{?OCW>d&b*SRAzcOV_&v;4*cn_{q%a~ z`PbH736}LJwodr~!EDmkC*lNw=xIJa9*OK?auk0aD}=1lUZ*zbJ9m$oxGOrCtkiCq zQ9f*WbE4zyF&^QjjR%3uo>^I*E@6EJq0LLU2W9w5ZBGVey)Yl^YxPlZ znILIX2~V(Dm~jf21t`T0v352FZd_0MV1{uLPW%;(OUNK1GQ#NOh}b zwMWw#pD{^iWmaN@dE)|%?EkaI$DH)yKgskF`00}rl#T5*>&Z6 zX;0WsM6?9>?!X1I&ec$6dYCx!JK|0|TN7eG?P*H1&5_H66P`SdWc}jK?x!u$za8YC zI7e!J1tVJWQ3?EbxWy=9?=S4_pW2d{uz*2UeSvg#n$VJtxr6`|KqjbvkwK4zfRq9% z?YIbG@8BRZ2E?2-0j_|*czI6hvd~QB?XGl7i-J96E>0=7Qcmfnl%dDE&3S46Ajm8P z;96u6nC@@%Vv4jRSwU#g{&eV@Lr2FP!UO%)Rq}I)-=&qbMyu|x+yQ_)2i8Xg+UM0pcrb(-A_oIks zYtU&CCsS09PtMqI>*0}@!fW!8UN5reD~WMK54tFp=E8WD7WrRh7*RXTk^7{Ing;A! zgBFF5268`wpod=>F!TiPy6RuaTSs)$zd;-n2c+lkzHmW5{~OIj2SiqM&tY2xkbY~N zmc77P!L%vh16^75u_%kt<;iK2_(>f=vOQA#t3r?r_fa%GY>ObkI7=;JH3a)mKq+g6 z^XVV|4UwK8*LOo~#$}r{%24a%T9s8xLocL*;jAlgUeHyjhb=3W*)#%#fizI5->Z`L zK_E~WA^(+SDgY} zQ!y1XrM#eMk$jZERdJ&uL^{>{$(~wo*7y<#slmKm03eAae&*p;1_EsX%Wz;5-P#v> z1lZsJ`H8KZKD@Y^X3RJNTsb1*xQh(jcn@BuUdQ1>hr(fhy$}~bY)T@40n-u*U(zCW$bV+8VYG|}SV+uC0eI)u^ zbe;PAz6JHAV*TZG3+}_~8j>@D2;6@!U%+e065sct&D;1>zu^)ipAfwe#-OiFYU)%5 zeTz4-)pSRokK9d}uB2vjKpFf27h6hbgE<;pGrM7zDxFhowJy1M@#3(osRZX5dNu1>z`SI~AW4!zhx!iE&!L3GnR1^d^L85~lKj;PQhsRrkWsM!=pZ+`QMwyZ< z(;UlE<<7#z-h85Q(437J5jsST793Nc_$bw6v0($FOm4^F%V=P&;L%S(`Yof0C0uZ? zAqulm&aUJqBD`U-XWvrlWnEnEPghd~glB)47O-($xsG7l50>_*?As=-z}JMJG7n!f z(;xgRJB%KHxImzs4L`3nc#c7?S}y!xgtpHo=Il1kt!N1F$btv|VEd(c-zDXDfe}r5 z7p>$_D#0?S|9%U;zqh(fijg9>hksN0xe3?(`p)?mw!}XqJ03b-iDn%D@D8ps1a86N z2w{C9heI(ZUF9a@Om3=P=a?Gq*Nx^S(U;Z=Jg=Hucd0}IAcS@7BJuLfMQF5ewvDfj z>|2KJrc}W3Pa_;}hqzB=U+kcLGasU5GvJpfLWqcBX7L;X_HHYSG~W`oB@5yr+2K}6 zfR;uc_v{fy`ATJ&x`=`dc;UH%e`(JXp?9q*sM~>!@p3WvOdll{*=i4*GR=q64fqiw z363E}E>6UJc#)P|9R@27QkHYo1RY0yE6;SvS!?p?8sgx_S+Z*lO8$hmYd(BSo`Fvb z<^DG1j-2x1s^7d$yy}lS_|lwiB7KrPp*f?V@-cGz9+~0n*8l?G9{!Wsb#Y$KMckAZ zDK`b38THWU6st2Tk*)@p_%*~)8p|2*h35sK?V&b-BkgsLKdB!!lLDT$SIMicBz6%c zz*bF=y?Lonr*`4Fv8|7CmhvC+3=N8{l9UN}oI2bt!Z6EfNM%=r!4y^)sIy;LRVd=4 z_l2KXg>M*g_oqg7zw6E@HCydFxJ6*F(!Hbjuv@yx8uPX^X+O(+N%+dP z&iz+fn~8u0++5ej7N15rLebC7@Zy0-^BII; zS@w@r)`}mN$wghXDAMiqDOgm-XakkkaeSt2y$|Y;4f5SKz*V8K2lacleT!`!7E?sf ze(~_k>0kD(x#vsIDDEE`Xj<-guK8^jt!dxiKdaTz@(-MG*YTT%Z2@1M!nLNm)_ary z8;chUiw8**#S5U1eH2~L)0_8>RVkS3sBGuk=Z>a?jEr~28jsIt`FH^i7cSb)Gi8W} zw>6vOX6L>E%0Sf%*{sy6>(rH2RL2RE#krY> zqfj9iXMet-N;1|jC^(s)pqCWgbmj2BnGprGSi~OB^59lpDN3WWK;(ozF^!kltBa77 zx=M6e>DqH843-6=RXU=`&C9TM>V(+hWpKj3FX@X}bl*+H)OD1xnf4F=s0hN9CR|9z8@M}{F(nZjYlVstxjt+TL>HOMg`|!KAXZyfXy4Bap`Vs zkdE+0Uq7sx4kdvn)8-dVAbPq%09PeR+HkW428_NPY{$8Ba@;JilDt8DDAPtxFd@s- z^HtFNM)x~kfa6b&4~gipyyXX|6hQ*Y2H08&X#f@3HP9>m<&2? zLipIVT>1Xs@rA4o+D`S<+s`f$4wDMLcN1m62V;e&x4HgHfY)CW@ihypiga)DiItZE zmfKSyZas9Djz?&vaultt~hc3I_OK`9>_O|P|~XH^!hP&1GD3 zO^8P7Bo~Za08&u4b&nC2yGV4bYSUdcQb+BZ4g)#oGY^g{UlCV^mSQ96`7q{+dx3_2 zr3_<>N%~C|4uS!Q)G2b%M%J|lX`nHHx9W6@JSMp#&nsPP69maRKo5hMqG8-#L&;LQJ+7GiImh%gx{bQBMlifIe^xU-a~#j$lqF#zwb$FMo4^Ij*u@iq5tX`ULDDCGEASOY2p@xda3rLF{)B8$7}b zo*R{m-qg@fn$SXk9vvM3MT5l-Idgvw7c!Zj)(;) z^+=*EuLVJF&EraeR{`JKMA$~96>{q>PYr(QM$3Dvmc@o+pxL= z13~Wc6&*olmbt(zi$2+{P(%L!rXQcjl&24{e{g1^_u?Z;uRh4Dl1&9Sr^fWd4jg|O zJ@8y0NpIZn~`{m9}_t4_AG98VGSh22%OYOwCQvx`5u zhbIipI!312G@8cP=Geq^p32m2DpDm?M2UrM9N0UVY8T zH`JadM_p3Bhswc$ub#m8)1e@E`2sLfUFT&g_`Ly*Q?ypG#}=7)hP(Nk(`fF(*5gKw z1XQfNq)};(kNBEZpD@D-(g4On-y|#CpR0+q#mNbvuMSZp;y-ntR|TV;U`{ijAuSZ; z44K6I7VV|o>VY8a=4BDAC0HaFT9X+sl(7!=bS ztXipcJEie2>H&H|Exw{0n<7+80d%Z&8{t16(rYWYpP~Lm`rTKrE_K|#~f(Awszr8aytvFOS6)*D4xK!@dDSLujZ+L1`NG>m#hAgjcH$ zNDHqkYblu4f;P6*i;L7C3d1}%Qc$pizgB3rntd9ks63pA{o&<{6RG{68DI8BB+gJU zPA1xHuk9eo2LX~uLUe{7$kje&(aE?s(nwA^WiV(KxRP;GQJNQ>gs(c-tLZsV&OX{< za9Wa?jk++L`+VTT;YM@U&Vz3Dx;C_uDJFVsBB}IO0i+~Lh3)g%6u~+m^LXuQN^VQX zK2(5TS1>>+?cAQGybQs80&qDYEA!v&-u;l|>|WVW&`Zk)a&7a4_MN!LefZi$e)mu) zRes&6AX(R4C!+J;^o0df&wBSx-nOl@T5V;uEYn3XHQ}lJZc@3la-}BcZ!;a|0*#;# zW)b5DP%cvZqyH#n5@)p=Iy+z5ijXXShm7}^gwIujKm4w)v==^6_;^;yc~Lo0sv)eZ z+pP2U?WxDoE+Olc`H0|elxS_M@@%Pd?*$iPt@li3#+btS^}oDTI+MS<2t#;MxlCop z*7VuZ+fJM(F3~br?urRh>HMKx?D41?r!SK-TXe%Ib}7<+nrhg^ynZD*poQV<0)1(i zz+}BP@mb?A(Wt^hTi&t&YtL2<#wqaTmYE{K&|$Plo+5s4ox|J!GsoQi`T4#-PKPr@ z8VEa5E#d_*S@wy75xsYdq{q{N+09P+V_>E)~zb?`W0ZuOqFpp zIWdznJ1gK0`tlbFq8W_y8_Zw8NcoAM3<79A=hUuP!Gl)j{$M^m4e?RQma}_1ka0yT zZ~zKCA^ay7o=T*j31~M+3?$l5Y_x^hvzLG9&Xt(cO+svk18MSQGpNmOorqzz=~Za& zf(qsCy+iDa#tf7GgoH^Onr02(!Gf~OxbxF?umjf!(l${XRKG=}EK3RToJBRKUxUbs ziCP1FMC;di#V*X)rjO4F4eb0`h{~SGU+g|FAg$d3Pe;SWHEUv2=c(O+InHD^76J7Y z@q3G=S{US&jBc47(MYjXH%?w&G>flb&dLCw0VY9ekNFP%pBRlwHSY&IO4xk0K-w^D z9jZ|67t(fg8=DE=w;-NGZ10zY68{>v$6(Q#!c*pgr&CP+LCz~b+hwJ@+L1~z9lEza zQl#R{48B*cfPF$#P3Jv4EJo#uyfSb+SB0|D@T>~uPWfOb=+EHQV<`zd62FHX+L5mf zBK*H(n)|FM*=+j%Ymh#+7eLQaOws*Kyal*$XS{lnn_E=AKwL!joX zY##sE&r@;Jp}%{)#}IqHph!uOOJ_|Ybc)LoXqCeO<1vXGs6>rdG?6?_7qm{}Q?+y@Cw7Ue z*FYM_&8uA`HSO(!H?>sw=U%>7q|UgGbYKFR4Yg23R!>=etF@RN<|91-iJc-Q)8 zLd2mPGK9Z`3u(3{G*DjK7mb*lX<64Z1vnW=GT^s!Nw57P z_c0=)_wm$UV?uKaiW91|M+8zLFHP`6bzwVA)Tp4`{`iT2vdS3y3Ng5BEceh`v&E-j z;&rgW6v(W8CKqhs*(hJoO#&a&yD)9Rype3;Tr8tj3^x}_P`^JomVHPIdN+jUa|(GU>Bev z>djOAF!De6-k1F>dj{MNc>j<4K(40{wDHRIhvSUk<+bQyhJH+w+1T%cXj}O89RYfq zlzk2>wXoksrq+^1_RN?V;+(G(zsCZHQ$O|c;e)~Qg_~DVYdshnO z?t-P73?io8TfKrh`B4blKg8Gp6_%vy!WwOxXQnVxZ%Rrs-4uDPBRNqo?{46iP)dJG zbjS9hJ7UEIMeBrQ8*9~n>%EIT5Q8Urp~KY&7#Aomx*2c0lVEO96oGwlkj2ij;oLzO zdhJK9)vYSa1hp9Ba|ZcalNGIj7K=jD!;mooOZhN&`PYUK)ri~5jj<~e(vz-!6iYq7 za+ha}utiBpYY8{pA=^8XjZF+^xpl4T!0azW+BQE>`1ul;9}JkGsK3s+DH zEr1Y@Cs6B?AKlq`Ps>P}_#}#_H>-6x8~fj0n%z5*vg2EyPy@z?O9~ z@UUB}ccPVjDqp?RttKi>L?Rr*N{I}4l)6v+edy4+HXH7x5^J|k5v$trO41CK`~sZ4 zRnvUy?<80RtrULV-#9>dky+zZP*hOY6XxdR%$+7|g4<_z-8OUefT3u|Ro6Ou=ptS% zlS5z-c|Y9!jm7OdtBksd3}@__iG<_118+bd1(od$wm1?k<55^XNF*wM*YqBc)t)Z= zx4!j15oLcuSc}%kEw2`0(p{B)m|I+OT`gsb++J-NzA~wsWI+7nPO<-Q_p4-c7U7=3 zBIj%-s>^@V7!U^qL~oY);77J)Z9ctyR@o#hbP)AW%gO68m(i*M#T^Z<60a54X$HSE z>D1Z&hU|`O0hxZ$cu8z&ySO9 zr^6gN#;E_gNsN+MUapTZI=!dR^CYNU|0j8|-i|SPv$hN;xpAFTb<4dCOH7_zvFGGh zZOQ;KcejPz@)gTtItfh=OVoO=WeD>w42{|595Kjti5$_m$W|~&#@#f}dDA!GRN7=& zGdddObwF%az19etiI5CaP7~wMF;iOGt?bw)3)e~-+T4aQ_k2PAChwB6tMvSzv?@r@ z9a981pT1JD6c9aRC*It>|-;2$NmM*|p1Gfa^sB zm2fAigv2c>Hv-0xg5`#<))K&f9-d3;+lcV5Pkjb;7}I{v_8wzQ(?9&MP0bE|h3zZk zdtGn*lR{U}OP6K^U`{0jwt4NsKH5pB!P##?t;v?r8s^d#6t_~j^(VdkoG3@hEbLwo zVN!!SuCINz%>$Y@{*H*g3X09fY56O(i4oePJc&zE)2P+Vjab&mxL`@gHE?0x3J9de zU)8d|psH@&I|ig$ zciOs{27PL%TeB7*gw*6#r=jcGCq~ zN%j&K@)%+Rdu2uWgFaHlpcSBuhK!wwivGbecLG7|pm!KDWEIv{tr>=IW?@q|PJ=@@ z{${xXu#|luozsAnJwra&jY+y|6+_oFZRcoCar~T6r?Q)xxS!~U#7$FDP_~cWlZU zSmyWMmklHy6e<&*lqhTv{WEDsF%5veyWLiZ7?HAMF>}D`jin(`V(&)*f z#$sIAP*L96QRhrhk_db;A73q{CiJnUodajU?5MB|ohet?h=k z7^v7JPBwXv5y-NIiokNv{3*|dp?w)J>o)aP`K7V8(fTzu?;>M@BPZK1YhS!aWdd^+ zItu64h|_6rviqY@_cUnv>hcyrCHlP5#^20k<$CNrr}_>1ly;VEtgo@=;bfP4w2R@) zOg)>{^ckSGC>(d)>3h!O*QM-WNoC^`s+ID6vyQWd%LLnI0n2Q!jX3TLL-$Xov7DQJ z4r<;T&pSfPe%E63 z(h;on;lKGvS-;2U0^(vX=2}EV_VYB_rtD10xRw~&klN%ZyqWvq^82hqfxX#-bl71w zsqrA|n)t@6ZLlpsQ6?&i4L2C(8|kYnCGLVZ3Gs2}!4~eiEhSIn{se>@`#&&}XU_soe}s2hBRCvd^-vf(%>U3hdJ*xucpuR>Uj+V_}|p znx0nW^5sf$3OX%!8Z&gargEa_Pr7FL77HG6nd~mLFung#bmoCf{tq1AVH-9!x4AaA zat$Tr*ydKbN~IEWCdrkAu*(@`N+pqzqEe2pN~O#_rP8fZMiNryzGlzw`Teo~{IUJx zc|PyY`~7-#>>CJA2a3{ilrPgWHXK**W;rDEYnJ*NVe4Q~D>K|fXD~Wsvs?cFjVLWz zaT)q}SF$s={!U~0<;-cLQO}N1rGU~#q(q9f+&jd}k9t}5P$%FfZdZ$ZUi+e_z&FoomB~3o!Fab)bE_|-rz}|lWZVk3*^k>;?Q{IZ+cjee4*Ojhcm%m zS2VB>YBwmOB7^hq%tYpsx3Bs)>`<~#$ygWWLm#>;m@E@U(+vcZ1nvUrxpIM2h_X>D zMWK{l=1BqT_1gJDOn4Wba$tjHP!J2RFWo1v01F&h zKR=?dP~7^BhhXglKVU_h_+Mc9YW4*HbZ!}^2-i&64g(qk``U;nc?ZO>MSh;6vMQ_V zAFLj+A95X&jBPOzS_yYp$)te!-EBGv>vX>(Jh(+Pp=pQNeaXeA6TWFuw2E$(Uhefq z#t1GwHrbt9VxOYkOo1#*NGGfXhpkAN>jb5*b`fEA@rY(2s0**-d2LM&QGdu0&Th+< zuu`957@)0;;S`Qi=X+5KkIgxt(ROc9nJjq(VxWc|hEL)>-IyNT34|>a@{;_7rrQw7Q*M z?yO-)Ajsmw*zD4K_tFV@0g6zv@=bdCH7(3-;G0>%EIa{aKPo$RI(6+TQ<}j~V7zNa zY_1W%k9upWm!bXHMR)X|dmz61Bk<^lV|l;p+*+&vcHAG2Jd`G5eBn8LL$(~d@dl#y zD66;~Xg^`^t};#D`DJ+-8}<`kcQ3CMg8cx3qFZ5)&N0l^XMdvLyS18bV?J3^1~3Jr zj~GlnIW2+_s|cAwRR~Z~HOyYEN-=UxYD+fD<|9@|NJtn$Hp^~cZ(mdm9s&j)+Rd(J zmfqH=Kgf??m{);+dWX1!1WmqOD4T4`kIen0+&H$WiD>DUaVNcY$H1Vr%@4ro>mn{4 z2M61bnVTXzG@Fbtd+?5<940i;g%nviJlw|FsoBhz^}{m1R&j;Mn@mCl9l8yceiZTm z@6SCT`md>hrLqza`{qriG)Zt2HbYRBOB%1Wt#^DA13E9si}uJE}4LKga~?KH$<(!YoQRDk#3RP zPKYZqiHDG`W}-ro^mCwGW4BfQ zeS$TYTg8u&`N7MQ7Vg&(rdkmpD^gFaN}!E$uv=$Q$u86MY6V5w?lEihPBl^CRUJT~ z_7g9COZ2{e`nxHoVi~dfzm>wff3xe5DM`q_zyU`-9pJnS+zl{~tX9ayTh7rx{Ln|) zhQQW-{yuHA$~mXh_*N!yvwlB*CH6MOf(1Q1z}yGX2Qjy43Q}-6NHa(B-+mt)x7TX$ zje9VBlaEi&80`>IA6hLEdGlg&?fjI=9N%ZfY}0dWsJpsWsGU6}<98Bp+JKxKy>^=S zT%n;Jc3_b(Vz#9mr$SV;q}>YhBQwW*dp0xP)r$kQPnWQmevm^%$-@%4p5}(whmF~Q zL|wbNx4U)PP20{F!g9<4@|Cm|K8jHN^MP{npn4_5N>h~MYy^KODbdIDIu0xUni(UN zS_*%uuzBxW3^nr)y=AebQ>_YFZwD{k)?no7{nRLiXaE~gBVrVd#i6G)cPlQRswtUe zO(~jyfsUZ>WbHr5EX5Gds^8&ylH7kCSP^-JwSpCKdD7@f+a!-McrNGf>MZJ5v{aj+ zDvjFH4zah9a<|wMq-IK5>4pq0xzG*QXsJkOu=&bjH zA4LHFelT6cS41zFW* zyA5w6ERL{D9&_F4Lzf!jhGbUz)P05kIi64V>UvuG;7OJRthYF>o`gRU53y3GUa-|; zR+g>gTo~u%Ck;ilWvsJ4o-=YC!N>LP9xuSOq#mo|X|hx=YvXyjEs?6$k8;FYJ1VJ`P< z(IW1N_zKhH0Ch_|3uT#m*Pm0b-|ZeA>B>{Ck>5+A+z0eu%kYD#?kL@&oA2&Es`v35 z-KJ8eE|{V!*@egvb^HRKtun$4J~&StWAOi_ZpfzU$m~}kb*Kzgwn+5^XI@Gld~bed z7oHCbYNOP@qETKf#jW>QU3C0Q+tv3Z>Pi=+ecUT5bJOk0B{3MhI(on{&bMOpJSS>^ z;8VTycLB>4%v8azyEXnNp}TS4&1?w8QoxNR&35=TnnmvBK_X^OuqiA-+LFO9NII(> z*`VwI%|6OgN(m-foH;o?m~H{boRI6f{^l+(ic=3DE?KlpCpbQdI^COdQ_;=6Y00kz zPj;v>8|Zj|yTHt5WSuL!Xf`m{O9!Ruor-)h+~HUO6WRcsg6rKmWYM%g2z)P-Z45VOebZwurs@}#%^F@N`Q55H$u z{9(9?xtMY51YfVG7vLBN`+vC#CgaI1^y4JPywR5P#Q%5Ky?t06Yv#RHiU-)~ow+5d z<4CRPx%Fp6c*v|Kc*$kbyis`BL=Zsy+53CgX#8ws)l>@oV#P?Wl^k+KZwqN}!cLtB znv4ihhBg$`8xG3czS92rTDwM`@{dffL!u-?qAXM<8K5R061P*6{3LzZ=5=0KBA5&BIHW1hjhb6E?l zDrvh_*_~zstu^{){J6=|VHJBfd4r%VpKH1J>NJ1T zQY+8pcK}&QZ~}s~;BRW5ser1aG*Y)I!M}w7WU5#5l`WY8PU~|zSooD`+c><;&g@|= zG$Yn~wRcf%^V0tf^Rx0~w6N53aLRt-9D$pF8`I&lIslAF)QTaHSv^K#t6HPYq_`%q z#>XzcB-o>{=P0;fmFxHxP7z~i*D~|V(Pr4F&)WIVlGouww@}|}xx`AiZ0DQdHV`D> zE$b}3Cz2Mt>tF@*=WDwFJK^ieD>EQ3g(8*Rpm^zqz#$8JhzrYvEnnliP z+1lDhv|jMnz}?mGdlY$mibS$-`j;I6Gs}dRPoNLGBX(%2R*%2^>4s@~*MuQD7=2`_ z{A>4;kjUO1=_~l}_Z!tNm+p~HF|pCSf>|@j{7t_~Ol8W3iaYy+qrVgy2+ZGNOG*en z!P21mrmW{@!3(XX5=3+FFH~o&ATOEI4KyV2`Yv*^woTN0X&(XvKhVepLC(25?aK8# zjnybautfEqr4x~qj-IFOOP16j)Hi4Ly^QQfZ;Nzbue;>8^U=#72v6&us(y@x<`zYc znh(%uTJ3a(bIhAX zbZezlFtX!b?KmqrPOer*(IPIA;wRVwH<4M!M658K#i6c#lOO%EWBz_=sp2pPU=9PL z4k7oSci#i2lD7rxSK2UTc4Osd7w7(HBIT0wFZ|W}RDtn>=e9UYRRV*$^4bMz*IT;Y zDwtOKuM`$nsgf?@@6;E)BP|IiyI%U60B;ym-UBR~uD&234;|jp1o+R{-@CL6B3>smGTaJir`<`b%MA>hPfBVWCJ`x7r8#%gbjLLPl`prVel)2 zEXHO0Y`{KMgx>Z98|KgL4O@3&{E&&Z{|DN6@<360E-jq7uT`j*ec=<)f{}}IccuEm ze$(zCPTBEl5W(9tZniU0_nGpUl7|Q0Lv<7CmFpC%lv|B2Lti4w-I3hs=kTcw8T)-w zAuvDf0DC{hzRrS35BV=A`1w=Bjik(|K(nqc%`QpTf-dl110LkS=Bk)ius_niLO-58 z6>hM5>z>m9Ir7H>`N9Lq$5-mFSMJtv^3xv5K8EN|8*AtwcuA^gr{MqH2IqTk-=QM- zBvKmEOKc&4a9pA>&d`B>)G^IW!5G`k@cwygaE8<^P|za#hS-?c<;Lr5LTj{bthqM- zx013VbtmhVn%$I7I`36G+vg=eHyy9+BT|BgL5X)_XsmUt=W+o@&wO*{KiAx@YmbN< zT!|NwF{xDJbm1G?jJf}MY0@#GdhLjq-(Se|C`{stQ(}kxxFj6 zBcJ|T)p3dJWxpcA92(60?72mj#P1-xBD)+nyCQ=com=j$cxi^Qy{f7{$>iE(=jyKT z^D%hIYQ#b}-Q&>3_-u)_4r*8y@ubjHFD%&Qh!ExQS7lc?>T18!sgCt!bBpg1b7sj) z0y2Ce)f1FDxMKjN7R3HSyXw_H3diIM(sT&!hGJ&C-+zrqfc$Sse8x6CBg((t>!-gw zkF+2fc(j{^Kps68JAJ-H5`5Z~`VJZHGx`!YMqOB*X{=B~S^j-P=1XWL$bh2APYvB6 z_F?hzeyp7?8WW24J~kb5xGVj(1p=6Nn&bP;VU~GC&|6yR33>iUnaWGdPKlOLbkbry zLju)#WtrEV#!Hj|5ok~L;Kx)AOcdgB^GNQczke$rgW{J6X&nfgn-mdLdI;c9{TBLm z4oX?HF>LV%gAD^H=sr4c?;+k3UeP?^`X`D>2@ZwY*03SE4r1qt6K8`twpW=oHR)`x zT(+neFyhZ~_K&yOf1W6BB1;T_)(%rHJf&@h#aXK?Qq z-_xaj!Bze}TV0WA@f#!iKf@6So$G`)Z8U~48RV9Ujb8eLCA2?=CdmlX1$hi&TgQs! z|8t(bFsdQ+`Nl#K6_+eS(uGf`9TG?xx8cyPMfL9x-!WkC%VQavnr`MUo-ubX9ft*e z2Mv6w*e(s%Y=VFPs;pmrnFH_hQK*x0GXn>*;Ou+`St{~P8=)&wWx^0jZm!t;$bR!83;8=uvFS5aWxu{E|$2RzAiIb_2Wm3piA`s7qd*2 z*z1;M!_Uu+z)70V#UKg`*22GV34am?Zt9mc<7Nq{Z9->FGxvm(`vxKgA1qq3nU9rs zI;;WMjkQ3|GYYve&XPp!RQhlL^~+f3v2Q@pT(&?l2z9u0;vw)j5 z-k`5KG0wgAh6ID0Z|D?mPt}mSR?m5rGtq9Mf~VZ2=SdzPnic)t7G{U=t6{%*Lk2P| z8c2;6Mmt|vl+mB4M?bvYtk4o;e+t!c6l(TweI7k(aM0se!_a9#-t$=1>)aN^o+v9) zuA~&zI+R42mRC>?UU|WA|GZ~ZUeLY0u#Ni=1+As2&?9!if>=s&Q>2Y%hMzY}u&DKnB| z&v9u1Mn-9kbdtl^3$ZybD_=4lP}L%z;Wf~Kc;Uyx(>%mRuC*zDv+GKPI_}SSjhl}{ z^P=o=Ec^6pk|oJPNNUYkmDyn@^LG8GVRLkZ#4PnM$|nuTF>4NS4(J7$rhoLvAtRdA z(d&hQL5^^&me{BfeGrF?x~uIrOfT5Ci@((_VmJGz{B5jE&`Qp|V93cgQLv&Z%**9hqo*-GmLe6jql{=!ek_c5@;@BdSvKFhIM-ea6a{^ z#2PHW0*uo&+>&O#J*vlNW^%kN0qm13cziBwLNB@6Ka_Xfsz?)E0HF? z@e4~U0H?JIQ2;-b0)-TE(3n`9pdhPr`kc zH+px2y~-mY1E1ezspqNPs}-*m>b`Ezr*mT7YAdR>ywluIr_Rg9ke%$Zq7BzP&NM6( ze8&vkNAxk2rK$og)+$EGa&nAHk>k4yOr8Qr7% z;3u0OS3P*`gOnlb`B6Rnw1%frV4-KzB;;cte=Cpc@Rgq34vhzxkWV&Su+%DuE`{k3X@C2_lm zT-Oi=G2g#FtNsutUHDY2JLz`TbF62R?)e7DpUgjoVWG9-%`Mvtgf8g;b-8C@!7^V*P5pW;xPu-+Qt8i*Fq||*U-;)5 zAYQS*ZS=>Ar+jWh;pt9a&T~;J(y5Kah6Z5d_vexzo=Fx}o)0O?>C9#k>ggWaqsfbZBsza@XMw7r%fs`FF-8+ah0oiuQE_GciSqF>l?5;5f`^qkON{xgAGKMceT$h#H zaf0(39Tu!%WvsBW+15WbGvH>vzaIR_g)8{PXPON^;I~&%4wqnl6;1}=Sp4PwpmsrIEc~FK)NX}V zUe-C+CucF_3~?9@8d%ed2*~Wl20)gu$uJ$GK9FN#)o{|%YC_G3b+Nbo+2w$Hja zcFz$s%-kIVMYCAA#M}*|a z!>EaDkUSgQtPmV-7+I-hs~+}N%UHO;n&G`imu#mf{KtDG#Wk*DUhJ$0a`X!Qh4fam zvgF8$tp+q1_w;%Kj_j6_@^m%uNrB}R0>X=P+*x+KVhsQRe6zVZH?(@u0>)6&K)pNnAOCvFWAKb_PMb7ZLiW{jV-<^ln3%dByN=(}@I_e$d9MMC+347YjPPW!bo1)fqV^a5Drx$Ezq=JOPpKQ-tNNkZem==@dvtUbb_a5C z{(>kxLG0z1|p8dU$vmtwz zE1YSx^cc@*LO`WY(EXXyUzX(Y}PPXC+W*60~$4 z(9J^ZTw!eoeCI^;M7CV1N7O;m0F-gR`<`~3shRarQSWbSy}qkU=*ByuHL-=4Lhkmr zxFc4(y+8IL8x*H^rY4@M+mi`XlE2cjkyCu1;;P+k+CK)^bWuAR?jEFzn6H0v{WFV~ zn4TEfiE+z-nAQ2;>aJ}vd;ijr1Ez?``#l4w$Bs%>Q)DwV;M6k47-?X%2XcKQTr|#|0DXOhnidn(gJE*9d!}t=`otX>T?;n^a|V3UonShw;Itu{?O;l5z7mKjbRgB_@Kz+Uua(?@_>y zaf&@pyW3}?>@!F;lIk5i&H=9CW>l2lpcW#lyNA-2mX~TtfWxCynaL$G$~7B!exdzii2K zHKefPNOxz*RLgmCi1ub(_@OY7o4pK98}0dLz!j#Oji$17d`{EcS*3FBAPRgR|LpM) z72gY?HYP_bEiranVs7MEvZzvr_vT!%`NV?KSgTkJ9}jt2@BWlYje5L2#pi{4M1>R8;d^yZkyfIoFn#t!nvSSsxvTI(fWau59br3=&TM&j1cjJokzq zxW7uLQ!j#~`!EFYGt0`7I3z~h!wZ*HOzL%h9rWV&`EWNYHV6Ef4;^r}sScFzw9Y&3 zgj(k2iF>aMV>DV!-*3^zQ$K z?ttQ=Ee6i)?l0hU(}?ws&t7)Fk-mI+Br$}dDMDU;Sis3kcHaw|Ql4;@Q5cvZ)9FVU zp2{poRB;kTwOA_y`t3S5Z%>?B2;<>CN@``eE`JL@vyYx^D>;U1c+dR@--NJLxP!HO zi+(_`-Y#=!1?52j1Pbi}j|f+T$5XS za-GA&9Ffe_uo!7pg#tm}El^ZF*2knn0DEq2#C0PFWOZd%k1NX-50P_0)Ce zfQle`e72#k?y*zSD~el8{z6-}yC)19s1jEto}Lt}!Z*vjFSJRMJYzdXPHZ%AR&P?n zsgIK5ydguqD=4pFt`PP6sDKq|AYknk=G|&&#b7Q1iLrA&QQD8!ZvXP#*K&Me(nw3_Y;$qeVZTV}R8d#<%gR=qXIamw%LRla%?&U?JK@4jpwZ?N=*$ zNGQAlRSXyLve?{iP*`q_YfW z<;0G-;1b7NNNPFqM;fe2@gVHRD7#1Q5Yef)@*37xA{Nc49yzG|5#nCTaMk&s>RS8| z9<>Wvyp6g+%$4m=#BAFjkK4-%vN!NNH=Iy!$swb6{b z4$?C29$Bc6idiRDYbni1)$n813PWT&MvS63UlVr|A2}_GjuK@UFO-X2KpoCChS}K* zcZ(Ky_cy{R&Jb1~1e@%jHtE@UQtP@9 z-^~`K4Pgk3d`ROks$jo6NKz9ZI#!Cx>8h;7}01C`TCqn%OqnFJ++xK7RKvZ zAlN9g?mo*>25jCb_jFi)=;~qU%UKBcMHnDHYm9C(iFYz}mT|q)9cAQa8iU3UGSoNG z#mIBUA-tTYuyRo$>hZ4PS&R+qEcEyo3AbM?lPtYSC9w|C`55p` zM~uq}6|&FOzJj$h8wvGJd;oFtIZC%ZgZV3F7eXzDn4Q5G)gAFRm`53YGF^8G; zIAKF#cMJ4GgM19~R&Z_pM8jd%CknamsbbI)nf?&3Lll_Z zIC9ff-rqB>NO$#fa(f)w>!I1%2Gws?2_0--uC;x$=el?vC3s~8!&H~SR{q*Pzb22z zXTu@j97H10LM z`d+pqS;zpJBq@q14UqqcD}`aQCTTuw347bhEQS8m=1_caM0;l`s4{J4YgpngP1M+C zCX8=+!o2lPp8dE5N&fP?=@`)9_IY;0I1aolJAg9ZtIGFCD)5sc z`RxU@L@r8u->LvinGNskx4`X-n=_z)?D-NhU9I3PY>1kO;JZghd1J#(BNUtTl8&@S zcF9E#X8^9CBKZyGSr5GUMEijQtXHB!)kNkurcgDqDieA~Hf-?DdOB^fp9gjDf4zo% zpbnx)8vJZx3^Ygt0?seA{nxpDubvV(2v0|i4x3kl%co4?wVCZ#W!vRTnqt!A;;f2P zW-86ihUUYS2Gi0G0AR-o>?CzZ7;S$nvwc>4lxq+9GF!o9GUqOg{Q7R*QjXqvw}6|Z z*>xRoFL&b@INJk+JryKJR3sw+#9f2_bQ=SC)u8tK6PcO#4!6NhpMzh|Lm%?6VPtjT z2lEnj;UpsHRlkrh?<4Ckgl+{^q^~At-#>@Sk+RUn*glZZ&?O!Hd2B3hPX3Iwo>1pA zSU^0+%@P*~!V`82?z*Xt)IggcrxlzGwrekfnL%6ovC)@DJdj$ye&;45*5<$2GOS$j>QcVoEkM=5F<5JLeV%Es)cudiH#HcR64WDgBVcBrCNKn$bZSTgidJe_&K zlipWKN$q_gy zFIuov0zl(TJVVgg&)EH`>aJ7mFB+=+-8{C8KsoUwcGzb|0$5dedl_mv#4eAP>^oko zASq15+P;-8?H%~`!wBu}Zc@Tg(PR|>g~2Lao-NbPN^Y;-!{*Ec3w$ZNtsdv07jC^N zOT&aUTD3gxA~7uQK6z|u^M=*2xMa>%qlv7I&L7ktv-I2-9HZ z0OJSDdzytt)2?sit5&jK`NyNzC|j_+-w6g#3B$6Q~`6%-5}NBIc3 z$Ka2$#ZLVc6F*imCap@&M>a`XeWxZb*N+iWZCZQHr_1*}WO^#l|M>I_cJSC3DEiXk zUcR=;A}8P(UyAiZ+dJ=Cd^5d4{~7fvcVI*I=g*f1Fir}BV+z5$pyoh8Fb-}OMOif2 zlLokzO0Hs0gp9h&a+f4$%$2ge>rQi|-HG$y?|I>`=0~nASTD>-wK(sCQo1$~7z%s% zlA@%7iqlrFHGd&_uYwZNHeh|fy&yd2$gfNd)rK9KwUW&Ph3Ax-)b{u}Ge-Wp36N;P zF&qapCMPz^*2zd%NI0`LV6ucM~C5Em9} zQId!++m)p|qSA{8Rsd}NMedWUoNDg4ZUqvwi`V`mUsh5cbksP!z=)>Eo;HX~#^qWd z%OE+fCI?Z`61q{1Owwg%ln4}aVrYXXIg0GJb?+EUBlo-Qe^;@E3MMz!-H%;Ytfws^ zKS1^?Tdy>9)DQC?bwX4uHmKi49R+EZ{?d1+6!RS4Q~nwI!s|VnVa~5*q*YTT_SaTY?XFxKI@>cOt!LP7T26$WHbsKl|Mg*~Xg<;`)0w}Cj z8s9SzQZVfQ;!KNI-E7XN??f7;aXROa3XNfG3E>F)N(@LAf?(q&ixhYA7c1x;kijv)-4}^N|A{`U$ z192^xzW&ip@{ara7`=Nzfyt9nCNsCWFh->^0+A31z>Nt&=xM#A&m-<3EiaN3op2h| zjEwAMf`cUvOFAAEaB5qKGyG#>*kbh&IL2ZYCFDY6_sb$vAp>^UwXKU?gXkyUr4laa z!|&5*Jk6MuXkuNy-O0CqtIuyr%+qsyaf12`SrRM>2^mF!*FUwA>#{>}GCR5pvy}F1 z6C;1r&HY|JI?`n)q#=N2GXVxY<8r;E#RCHn}HXK<8QG`|3f}LmF zj+DYUw%Un<@Frc4PrC=-4riq6)=G{`IA~=c1IjTMI_1?KEPZ+?xn3z|-?Vbx!7}P8 zwQXk=2$|9S3+Pwh3I zzIeyrM&9r0Uu@f)&}8!h(m@qgbon@vH?Y;3-!W+sU@ndcnRfdGFOAdw^eT4vnd^%) zwOZjvM;KT`u8OU&o1WZ({4SG=u$08Bq62S15WJfG8#y16+Qg#j!)o8>q8ywq52aR7Oep1t7pIexwe%}`40cDIJ|83OH16&eE}ewI?;72~Buu3|WS-!=lhpwqGvn_o!U*z4yeocKGQ7&xmuGBk-Z17~J&FzD9hh)z zl|8i52ir#2aus7mxFA;L85-&s7*T_v*Nl*j!B*9{cqGyw@+`AVRq}d?W8Ue^9nKi1 z{#C5~5nQynk9^Vzjoq64GSR%frzi@Ln;Otgj8#GO!%O+og9Ifrys*$WAe zWeld_A|!arT!<4VgJZKBbL4y>HsQN&hioL@aYH5$QaENacr23yFy6^NS*I?gi|4M7 zs0gdw2Re{GO%k3qtaqD0NVB&8p&Z#r3!QglcbVt}`7*3((LB=Gexggq$5yTAGH!B$ z99e0i3+C+7TE{+}AWaJT}=Un%?H$4Y1PFUhoylJ}JoUBV<5i+=&Pr^Wq0*DA>^uz*r0u+)U=C~KB2bt-c zmA0d^-Gbh*Hl%H@P9SCuB0a3_sQFn1zmvHQNj8EW}s- z_4El+vOI{4$|vy*S}9EFt?(o zRn(CTUM1mb_ zcMry7U~H>isrH78yVEkdM?^Id_ye$GE8= zh!$rg)xYpueT%9!YKVs~pW1AV**2pQ%r#swUdd&yJ~OEjvksmwGhu{ys(i&yVKz^W zHv`UtUH$!;i7$rf4FsRX5o?e;?fe`rrX6ZMmY^x#P{tULlA)Kf70XLXBqcX&SfqMr!&rbM0P3HyzhWl?@G}OuZ&C z>_AZX4!eo4Q=l!$hf>Vk-tZm(OU)8;$E_PuI7K1LY_9@f?cCbuwhLfsWj13~w1JKb zmBe=XAh-(_ie8g9!dIGTGLT3$-fn3dd6X`^$18OqFV@eSRCUMA^0H>i1Ka(lX-`J} zY~xFr8d=84CIvCP<~r|5JSC?v4OeFygq6w4Rr04>L{Mc?TamJp<>)!j-07!S_k6Pf zN990~$Sncsqi%x1^;lWP!RxO$;)@|3j&4?g&t1zhU=|nU0w#j73bpqJ-YGnm>=I&A zWpV=pEgjDu$|Rk4$yoW|%h44p++Ic{LU1*yt_zBu!y<BR;Z`R6T8g%DyzRJTvTf ziexczwr>2(e2w!LEINV{SWI-=nNONs_vS`8Ua*XK%`{Wykv#3;d@dbH4}ubGKy3Vlz!UQWjU`MPcNy&rC0vbAZPNVN*F} z6ynONmqPrwiy7554{`d)Ow+M(A1B)d@~*D}gus8)L-IbWfV+Y{MTPNRdrKwz{-$g- z7@h`Tjf3R2=oRw%k?#O;`vx@O4}D@Woa;e#R|TP7_bZWE*l9h=fYM=ZTJ94b=Ao+0 zd@*^TgR&o-=7!mGyH9h=x;v0h-u(le_Y;#jGyukyu(nu5e|2D*wyw{@lgiCU#ZF@` zDHDc>kX^xcb})YhEtBW8{3U?`2n16r$(Pc0a*J&(h_~a@6s@(y=~i;MeM+pi#KF+62tNLCe9#cA#mn1 z*Zub}5r+DA%Kr%VAt6TA=rVA_CfBWJP;2k{WO$-DzFVXzX{%wDmaRqoEJ^tyh! zg&~vj7@hh^Q&-mtWG{?INS6Er_P%`qVBl!+UR9tvs-~-r_{?8nD||c`uj#1NI*8fR z19_y)_0K&dF+e^)lK;A0n{C{$nk~g6Ja740M?2zkkGK^m`ikO1;l}j#C{++QVYRse zJ=lUUg-IBPIGa8pF2bt+@g!FOjgFUUbdSd*2l?|T67iZcOU1M_UBcdkKYB!)Uq|yp8QlD z0eE5^NWz=Q0=kpbHmwzMmlKAwrY8T-gr_hIGH*M+$r0PYGtyt= z(>|FsOYV3>deA^(K3oHwWIFrH2ScE@&1VTC8Z7ibu?6u}S7nc7T`cNwOSYODZkO1C z_5|_iB>Q7)i&uPR4*t+681(BY6DYkOuHxUm+Z6p)zuEp=l|qEU1+B3F#^-aG7U(Fk z6Bty|ma?+shDjqcAN`M}a|>kp|Nr<7wqav)h|OtprotSOkZq1ra_S^0a|o$~q!P9{ z3z*_p{OLsa@s!s&+p=YvrBfd?fw3|UeD*_0f6Lxi6s|7 zNXzNOb8K`KtQk{4{+B$uLJMZPMeO2`{)b|^y?VtONP_S9C7bQcY_3y9%2M#uOgFTWzesJQIwc{)>n|NyhA*6?XnJ=%t-m}ZBSdNuFd>+vKb~xg+%QZW|>HX_(SNG%NK0GPdMcZXnZNbpG z+}}1!EWb~EQ_gSYbJJ6BaPPh2A3?U-D;x2`ni*V@?pp8Rv}0gu2YF0wVu!}}b+@-U z(p$KB2(E>q%K!khv}u-IB0c7K*&dr6Z5Hny z$$gY^wuaarzbZBC+}a~V#cv3$9SEFS2AJ)GHoCeE;qXt_THm~V!*A>CoLxajY*%Qv ziqPFq*3jb8fe9D}C$iMnf6M0eg{n2X{)tp+vc@&Sl;Ps7uz3e0R{2F!C|!HL&#?b85Z*vJB-HdIcfihe%?v0J5qCJ zwaj!s7R#8+DH!A$6}_7M#Vk0s)wN%lecY6|mC~Y8868eNEq8YluUa_cnML8FH!%yI zX8rzWW}*7ZT(SI8wogaL>m7CMcDp>8qp;u31|LO#ni>_iqXa!B)Z$vMOL}Ogxx706 zhr+e*ylbLNgNuXuuOUn7I@aVdgz>A<3zqWn)_VKJD0NxW0kRc!;Vm-&jiG+i)P=Vv zP1giS2^AZhu20>sf(%a*s z?-{+znLg|v0CZCIsAh9PFXL#RXtAPWB<=+erU#KI{eet;g53T+Sx!8Qq28nP#>x-> zZmO``7W4cYMLy3vsBj(qVPWc>HZl?(+|}|#CMD0+ZM8{ftSlsh2H{+&h&+DLTj(7nL;J%1?HZsRpM>r>!k5r)`6fvk=&n ze_*d8WuJUlM&Jlw!Go#VN>)~`j4m9cue3IIwD4u?*8XAX-(>yUk^Z>0j;_~`#xjgD zQlzwzHVQ5rpR)3xwkvZ)2iQgFBzm8kMi7Pz$*i=IM%Q4C5C`K>o@fjw{TvV!CdqVG zGKxGP*iW$}vzpPdFAx)p=A6%X5JSs2D$^jsPN@vSFcUIIXH#}@HFWLez|%f$3b7_T z%{X4Q!cM`*-Xz9mKn`7B0>eMCQSHnKH-*!W&=%+9FL+NNVnxR<4g-+%_sr?t9pr_< zA$C=Nun*i;K_Mho-fhO^v7*a{VDV>W&5NLTmI{QgOfvIKyY84Zy>-wXEW130^eMH= z_og^_zYPh8A3}l1Wj|3HBybURAWOzV<`E7Tx^=3OI)Nw~X-o=Z97(M^##~>Q{Rj%2 zh<|ox07O<59;T{k!G2GM*S(W=Z!{{J7a6UgmdpyDfzk)*69)m*A#KbiGA(otr;d^;sugmPSv&4Mgasn<3(fu2VXgwX zS=QQ)*@*UOO=e0k)@4fd2g}$S9+j*wbWZZEW=m;wM}_06Q_32>%>mvw*pJy3fyoZ= z&V>s*E!UU-5+43bpSWcHjqNF5>JTGsMMa#~k*JB59VN=m%s*ORQ)P8pk`tNvA21F` zV@%9qkxh^+ZwU3qsoIrf*5z_}Wm#;RamX=tM?^5+TxBY4`(3F7e~9U`kPH(Ft&T)B zRCQX^Zr%Dmg#&;9zX|_ySq|;~o9IK?!z#=FR8Jj*HWqCpfRVH`cum)O&a)<38p^vP zi8~~M{iM8eKs`GkO65dckJxB3Azr{P={0~uBaesM9Rv(+gm88mARv3+B#%&>rW?f? zu^YL!>j<;T>b=JC0D)?#A0ys}7?>P6_s4?QP!ztr0ASCy7r2iZ!_|9xnpi_Wz)$e@ zl~EuG$v(3K!&PoE_@~i`lT$Hz*!U$37vhcZDqdd(JGQQ{TlRmw<}nnOAv~pDd|tO> zHg(dl@+%ZMS@m#)e;f);CU>`Wzn)$Be3HC2*;79IR7*YDr!CVf5NxX3aUP0~1Rp`% z6Qj1b%IKj!-s|lU&svZo7T`wd{MTQSAzmW5KD2jGrG|nk1UJs= z@Z&W(2pfa>U#dD&Q&(}222rnQM3%Zpc;25+v&5O99w-#f95z79r17=Rf0 zw}5tHH^;%d5b*>~i%R*1ZqE+S?JerjKAd@7O8QO$?YCpQ-(=v_j~pJtgLJxmmG*)b z%Y7tepWWHcXO*a=7KiYB4iCb%o;@#J)+DJoV(j-^Djw|z7FOS;GkIgPlmwYo;(rlo zcNn4k;vD-vsrCa!$R>& zUZM{EwoJ*nUz8d9#d3U)1)1MzqRm3vJ8p;@+7~R|zb7h`f#Yx_%a=SF`L=aUC{Bfdm2^hbfhq4quaT8Go zukCyh<*SG}vCGi%hvQl(^%)y=hL9mm!d>P+%E|;iV4Yi?Z%9qP1lkvfRE3GuWM01; z_o+UJqZK|2?0v51oxMOT469HUdc!!oAx!fB5G7PBRAr(A`wK?VL-2NhgbVBbyu0dQ zHleMyzHXzGU~j1TLT0pVL&(MAmpoIGwfz2U=p_U{cjfnIRVxZxA5RWI8q4q_nd`Ku zX!GVJA(*wHmU5k~Xaz63yp!5T;ah)FtWP@rUdeyKQ#gSV9b{Bthn#Y=_^wl#n^@0B zDTPG*=*4hn8A9lJLPcsMZbL~t%Sxw>sAr9Tw;LPVS*$Q&;;MIsT9Qj2eGB=A*8RH7 zt`T4S4bGr{@IJBx+jIGOMbRu{+~K4kYq6J*%~@PWZ-a2c3QXW>1a3f&Gyu?sWI=W*VbdoS@tp%+08#uU_h zeWg5z4i7Hu>nTrDU7DYj9+yMOXm`1kHYGb5^v@!+K}E1FOdDf6Cw)Msy&;fEjmj{< zarl3*Mz?v79&u-zlHKl)*W1jVK?X%-5>jSRp(`gxnB?f#S>bOu_M)UsBQA)lz6}2$ zzqwuFR_L~EFTQ&oz@#bZ8^3va^qD&Ri6>NV>to!h1d?&sxPQA_{%%;%Ov~Qfh1l_z zk}IpNa$j3h=rZXD8y>b)c{x8KP#n%+gz7nLNotU@eIWRZN2}oqDT_>n_l?l~r@bBM@P650B?~eF*EeLNP!*Q)1ZV^4^eyuCF&rrP z<}#m?NeA-B;`FX_$S9Klsq1lwUG_~Zr7~W6A}Nonq)xN?SeLGs)v%0pD3!*XSstUf zI_F>qQs^nh1qwqOaz!g)S<;cm6cd-s_841kdVgd;sYe%!OI^Vj6=AvA0S4UdOo;?} zwWn=U7sPfKtS$>1_eiV#w@Aj{z#xOtyUBxAw1>MXvV;xZSkX4rF%jY-Um)$tc#eHx zdpT9p=BU)hlZ1lXRzNE9H0>zL2C zjK!eooy1v|N$4ZOggghIg*>F&)`cmp&)iH7fvw3Y&+y#C+taq`!Z)D}&!!OLE}69S zFbRyD_kOJXgEWJ38eEtg9kcA{9s&N@@$qq|`<+crzg#`1AjY}a-96dX(XvHA{!^pb z0kii=Iw;{H8RuQv@Tgk;OCyou{VOW;jAE>Mdmb-6nMX$4BKN{#_su?`apKV1vO!Wu z^;bl?{^ns?UZCGO=uPcp)RLG~B?GP+azi%l_clDB{jHN}KtIa5e<=6bq(tb64kaPM zoEu^tz@PxT6D$pVl6DRo z=Qzn^oP%t#<;OrSpn8pI{8-4jcM1>d_26KYP{>69Z=wm-+kvA~P8wmmkLzp0d%tOa zGvEH7;x%T$V;Q4&0?#w)PjVRFNIT9+-;>dP(E5G%qPc3Xj!S5hxp{5j)CT~=ZIu|6 zNrFt(9nGpr_=d-H>}59fQ8$=o$pwb4VC%q`u3=Ck`<+MijMRs0`U%&PHym?VC1)A? z;-u10KL6gHrY0wI^f}t^fu52a|GA}f$@s3rRCkV@;C>z;YE_M10<>e#!im1w<36yX zPSi3C$J(rA8@HFmqs~F1u;lf&fOYnCJnpJO!9{%SpsfFLTh|W%1a_NFY%yyP(5{e` zLB_drzExMqpH!y_m4c<(y*PC!TbU_4o+jGv681QZ{E#~?ILcY3 z@HU@a-(V$!Jt!q@=Yp$1{g9$@Z{cFv!_a51%UfaV_|jGdGCiujMvm3cV;N>QrLt2$ z-Ds~ufoIEmoc~4uD`yr_sXcGs@-WM4m8c-VWLcA|W%ylLwik0KhjjHX0=aYpLC96; zm`;7FNRp!83=H~iQQ7$}ojS1l<}vX`X&`m}7f>n)K1e$(X z;u53$^cw6_udsz$Y)88w`U~xD9y2w#R>0<6m3h<6lc;wkmk@#Ai{C?X5Xj>}7+;V@ zK0`aBsMkfBp_#4~4B7LqmO3ORqMt1c1h$-RoCbWnMu3Zn3vy*g+VzD@`|&-?6TREz zw-w-OZHQl(_(ZGo?-mA`5jR3fvZP7vYUE}|>Hm1{I@#iIzVwFPCwy+vDevp>SUsIn z)SYN#29s}bL*WFpms#2CJg=_P7E)UbJ%rV9kr?7kMaPn3j8YCg%Rip>OK~r+e4B)B z(VnvP8TEHYnS!xW_JFI5XAsg?fECHG0>6%`4>ay7E--6sYJD(c67+itExGGy&D!!x z97B83 zWXIbq2I=W;{z=+@@uok^F7IXs!|X=wuh(^I`L@pS(8m(pf~kVkzWWg>H=l#gUu96R z3W9FYq3R50b*4}G`z*H<_YNlJJ&R6Tlc|tB=x_KI!wb?gYVERG-ZFmqR=aOTfgCOf z_2MsaU<`Yd`b9){c3?Q~X|P}x3TVyo-= zA4CVX8~eba!m%XM9R7_`=vpjrswQOVULoMDEt|V&f!=Ld7H`nLi2WBVMsvO#;bv^m z4N!{hght8g_(_~zi)q(AI3lLr){4PSe%5uu(1IG3?of9IX&Tr_qx>0e?%vy8gBjebCPX&sVZ zOOfVKD&#=X0;2XC&5p8<5WxH}^z{|EX4h(dbuFXS&RK4vEHG^9=0*;F zSO=2NlUdLxBAMQlD3*RIUFmti{fZ#%%OwUC9U~%E zf0iW62;byFT$b^m(v6t7p*B_+Cy?#EeiN3zyE8&%@p zHx9>h#1bZl!P;ES^1!7cB{ah_wn`i8fdpaV2s6om?y7Fbr@kk29dFq{9=XAgznz>Q zR_Z(9!D+RnP-QZy$qJz#!G%alGe&XJI*2MmXYd*llhlM-D)C+J8r~)A-<@7P%~%4v zBC8*Bwl=+Gb%%@xBLm@>7q|Cc7{OfIjhCsMzlxRT-d)C?GVOW{_Gnan;a7SrQyx1D3}Y(D3EeR=}@WZCJ33 z-M3z@5KO2}O!fHa*x~721~=OWUm?~bp>ERv3S}OGDd%{h52V*&t_0j`=gx*%hJ87-5m3%VX^y1TKYz5Kcz#8#H z|2jo}Y3j{4%HMbK*Y3z(Nr+pMRA}bIFKil=(V0@}nhHx9U!qun+{ISt@d|^@za3Q; z1uARiP7ga#<;XUOt?{h7&6CuhZYopmJDZpSm4o29vuN%Bi@Gol{X5G#dPSi)nU=J_ z`pdOuf1XqqU)oL@U3Q5kIg-|0b`&5MlCz3Rf*U zM$}HKEJNpn`@Tnlfku+DFd7D+_?C4~i{ciTz={B}=_2(+fH#+H`G{I@!N(ZHBAcS^CK}{X}K-a9yOR;W21X zdkq=#DA&g)!?Yt()_STaj3)t!n=urkJL|KfV-0{O?T@gqXh7abd7~>;^B?U5j4@}h zd}zb)%o=|-8)~(JIGnfwpupZJ%I{AggMzJNOpQ-cFx)rF-d~!#-yi~(;X}OF?ThLS zer0(D1IwERRPfc*CmHWj>U=nw2|3W3?YcTf9kYwAyOF*1_(`TGFR6)D z1x<{Yws(Y$ZKv~-t4lEW;$JS^f?jCD`p8PCYMwzR|>F7j^ zYk)8au*oO@y_oNlvxSV|`)+LmVtrH1E%=|%+`j^|DFbCrlBo5%_jUjf?)mR_On>~g=%gOz zps~I5>8vD3mIIcql4Oo|J(vZ3*G9GKCVkf#XpFY5%V!NgUd?wZQn>XAE8yBLG#bY-MtcF=X+SO#w*6i5L|KRl7q%i71;zt-{xrI9mp)Gs-aoBuw- zT)FCVJ$GN5!f1T`bH5sw6Iks{%lR+C#Q4`i<&e53oLpyY_{3R3eHgwwI__1qsmr9e z4db9(07P^{vJ%KLOOwylI)G;$L=!gb>oT3LRhJ9t08~{egLrBP}7l)8K z5H$L@z4T9Hb)WW;ZOuenINS58t0KG2;T5nTTDUyg;x$g zuK6KG0%l_-rQ|`Djoqv>saNKH!|$n zMS-+*y#)^5dJ(8>onm4}pjZVFWBFpDjxkLa7>_45pGEpri`{mj>oq(A0K&_=_ntkl zh`4tYOr3G?T9`UyE(mhXU3P>z6&5s;Ln<9hLdpd6`z3nsNYOyEL4x^WTjWEu~hnhJz>QI*JpJG?S{SeE~bWV-r8vz`iWuoeFE4NV&;ng!P} zwNyirs4qFUBpz@(_R6w(m)pUq%xNvZui*^VJ&CM?7#j?Y9Y;p#zy4t+-9~y6L`p*N zloQ^&Sg%nA!-^RU=ctX01C`RTma#o*HCm&{TrT^bOFSxhYo~ka1Bj#YVY;A&)!&(F zqyAYWwPTSQ@}1J6>>4WUg<&#JY9owPDOL=L?&%g@B`KE@5e|%b>XidbFI48mlk6Uo1?~tcTRt3(tAlX`E1_2psWi&-fg0D<>q5ezF#mm?YAXZ~+Tmh}7`1cAEudXyey#$8NqMaHBAwU1obUh7oI7;ken0%@d*VYu-R8@f1Em=akb7ei^31VOGlFU^F1{|E@%;z z=e{Sp1S;GR{~m!}e4)kZ`#$|vG(A;wb0_3#b=Wf2YfhA{Feqcs&5~r=zm)mu z2C3D{NBEf;MKN+BXpyw!|WmE;dew z6l$U6qmrVc%<8k%)iX>{v0Mig1k3-F&cYmwfLVyDXTv$M#x=^N$`-=cq$4m>3FMH; zifW=i`fSBUvbIHPF66C>CESpKt9nAUP)VF4wp&d3Z*%PpwwVfsgc)RsnWI%dsET%a zw<<0T@i1(YP{2|IJ*&@7UVTHwi?*gh6E+$=+UBvDd&FRHadbf%4zF-eL_Xp(k)I&` zrRY4KWc^Xsuz1k5fHz!6||>^aJ{EG1M2NxZ=B5)*IL}PQTJfi30kqIk@wX>|Ybk z^5QpLIB{!e3`s~4T>?Bf_u>jtq35~?&)3tfFX0)#b?^YC<`r`OD}}Bub2wP+wk+G< z2)UD9n%(7g#OY@k$BzHABCL5)@#g4E2!plwE~tv))Q9ML7~ND+w?W%9bKp5+5`J!W z8GiLGAK9=6DM@#jMSz-fI@UwTDkidxDptuP5w@asZ{d%>m1w4r+uT2DWm5ti>Ds~mn6F6SF>vQ9F7fu_UQ*-}r7+tW% z&~D~fymrn}ZMDYK*Kf0GR05e|$qP%` z6Q`!YUMr9N<(*62>Gf>pOPKd=-yVOP3EA5$~b&%~%;XA~zD5=oY>u+;a&e{Z|JzmM4 z*jenH5+uJzq|VEooDfl~TmS4qHvB$}guPxj)cpd>p-)%Ej~X)x?$1!qRD3(nm3&!V zDgfhwx69j46JkuAALn~?w!cJ{_?8!_0dZL&XiptjljWcJtAXB_aLD zh~LUB_6E^>c-=k4o6zn7;GMJJJ&p$Ed~qr>hzq1I?NI=Hd!$xtC&LM+Qc+(0@2^mO zGdhh7`hC!zWHK2?R@I{NQ)W5`dg!C+d!&P%yP5U1r17~G_?U9d9qDQ7tS)99)TJN6 z&TTJ1Zk637S6E(vS|oM&^bzlDx-YTBq40!uRL$|0z*EhF*V#|D=X|(MdN{rS(LJX= zw)}iWA&T2FPN!vD+ar@+dHs?cJg!b@2I}lD^+;mbtO{*b+VqL9>-yqIS_uSgx(AFQ z@(>v5XSBVNw$t+pEt-to=FQSKRiCD+*|U4-BQ7iuf|@lO&b8xS`SP#aK7_h4lDAq^ z@{9TI;g}0(Dklg~{leDlwbc>8Dz|{h#O1kR&PzfjRFJulw0ktu=LJg@S1)|=4&5tl z9dAjyt#oRYct?~I zKLka9CVv2o&hQJ&tgYh1htw$TT1B^auy3Snfk$c|PYQNRkORS=FsGF)v z?O6`PKZ1Px2-({W+To~q*j}0FKL^Y#6Pd`N`Pm=8Pi9=fWcAfua$dyu>*or-E#JQ~ ziT4}g8jjC81Tn-F(vj|D)?3|g3TfBA{`tiOhQg7e2 zSk|L}qFpPGr=U)1S$+ zKEPa_KTpFuz)w1{`@3;hsZ~pJu!qWsY%#K2O?udS0e!Scwzpt2buDQ86iGb7He6ya zvOFN=572SrAFiqrCPI}7jNco3Wk5x=F8@2Mdu?gK&{;i^;H4qzBY9 z>Rs}Y^$Jlc&}S+AqyEL2pq_?&q}l$JmM|YP2pwm>|0Pwt$Wk7D`1KX!hV;g_tS#~8 z(}E~7XK>YYH;|A8<29gs*MI%+U6A%Yt7~Bb4|~7d19@49t-u7y zWSk~J^=K02PYkg%%EBAY0zWADO;|7YHh_E~wMcD$u9oj#y{%!`o*zG= zik!X($yVHpSBzG^OK7*37um=sI;7L@H9}M?=c8jSadOq82&6BBprTk)g{Mm`E?FHN zfb1SQ(GQ-@7SDpFZlALfJ%xzXM1Mq1PEdZq)nI;g4uD^2cQ4iP3 zZ83T;`5yEzmqVDW?*_do8r9akNI!||kGHh$Al77(UR8zRUXLeuSBsllzt5UTrB9lHS@ei!P9o*Y&=047M#}_ru^ctP7OF5NtCS1G(7^c z;?Ox>!CfxyITLAyDmxE1>CdbN`VF#bj-*}D%*{eDF(iYQkgYQmYGrgU9j2@Ej=HG3 zO=>d>*SfK1wjAoDF^!z}f~UO{QR>z@Y;06ug{Q=3n~ga|$?nf3st48dTcd&>0GDuM z!CVwIl<0~~fYx8PnV)&~$9YCt+lre#QPJe*MRH!4W7e%_UClX^!D*B9S)}=lV@Jle z#|EnnEH$O6$bhqQWb$=mcwQksA{PC)|K^DVq?Q-F;!wRWCMa;- zNU@N0tkx#mRH_W?A1ZCF*@3*u+LGiXMQNhh`Cyf|13@`&Ns%R`gaYJl?I_s(tFt>) z{oF>Y%lU_qkwL2lZ)fwNwP14lo5jt#-$9YJdu}VcY^X_aD;*9Er4HtOh;z36CUy8+ zX3Yekj^G~dKju^LQlUX-8Z+X+&DdmTIMLBlKEgt;odthGAP>*Mt9&BtprH=SEtp;% zQ=}hWsKTP@;xwu-7_QO?wTQ}9nr#G@yZ9~bn5S9}K2rN7<MqM1Gz+m6Bt2RhNAlIjncC{JMdftY($c~=C5y7TUIHfaWG+uB{ zVVD9Pg6;}w50VY|+CEFHm&R#m;G+=Fp^xh2YBp>Juu%qGUOGC37}C}lmccDR_+VN8 zgDaa`L<;7hvwjUo=Xyu(nuQ>swk#N1sSfgAB@81f~s)M%TsTZ z40;4mf+&5i3GP*oYLkKMHI$aniXP_9#%eufD8_@&mZSQiqXyH(F7ei)5B7XPh<5G5M}DXBap?&0LA-}Z!^UHWYbPdJL$_)BoQm6=8)NSr?9^?M{9{5u^q8y}yco^29}J8f5) zhl*86!*9VZVsp^d# zlcJI{p|4S9FH(M{wy1)ek^6s%2J%}bi5A3ZMMi)@Cn zKD@$Zg7i&*iHw9eMr97MBh?kL-GufN3899MEFN33JRhZ9&1@6bSMq~8v)aIPS0^G= zDYjk+Q_qZ>rTXn|R($UO`2 z3pD36P2IXf7u$aPk1oi||0JOWfRsV+;NLfaE&Q}T@WGJbJt_Tp3m@dcnV3hPK$xoF zOf12JDS)3^(kRZjW-Yh38RCBr9&BlWF`;(uhJeQu2Lp9IW%&{)kttO;f0U)SqgacR zQ0+Keipa$1KCnDBTavb0_NA0=;hOh$kGl!eNWm^aq{dy*zlVWynWie1_4NhuQjGTh zWO1A@s{9Gp0Cz%8CVo!;yw%d4-8qWG&YLTP^&C!G$O}_)jVSNlj0aMf`nGAm1%?ov zVyA2ES-xae%M2x{gH@=7ng{eM=*_i+1beiU1Dnh5Hx#MCh%oX!2acwmnx`}!) zR3L9(kg3p}J-BGD`?-^<&oYz{fLIGMr@(=C6vRJnr=gS{(`N@Bo?OS2$~B}%U;jk?3qk>nK5z0{|<*@)Bg(&2%s2gWEy-Lyjh z@s#ZPpTJ(3hq#qMCKnyY-Ln3NQjL~4BuTQy&dff^m~}@Y^@J5)jxVwy^f}}IF}asFL9+^E zi_^+};l8%)>!7ugD>+>*vW6vBz0>i8Mkf3E#@tXGXJvKL7#S>R%IDUnc-$8B$q($T z`P6#J+)Lo>u!1?DWJvrjWn%q=5=ajoL^QrFUeNYA47uLWoTajF^UeJ1zm%t&IO#{o zs)m$T&;!%h4)x}MPnd@ehr@833CQG!@(~G{2UWezR=LG)_Qsv{9nHb23QA=w5Bm;s zMwhPSFt&n*C4^ZV)HDMw_sQbsA8Xo9wOk6d%49v$6E6v0?p#&#)hD?;=V`RO!u^M5 z??(c(ZM*VQuORNCDt@%7_NQMByg~Im&Ni6|8FkwvG%qp-^-iQ`;6!BlTVZnQ_Th>I zW}@Sh-E@^lz38yTKJ{|J5$x36Pz7$eWPKgoxccu)-yclPvZ8u2I0r<^IXGD(bZ+AuOugz(bM;vrp(5{C@iDWomlO!KjE-8(_7 zyYN!@`-KI&iBAy@4%*RpU9$(NE}M_nY9u%_SEby|xJv7sZ;Y|2pS7jkR2a4C0={y? zl`m6cFYEq>u65&oTiIL2U%kxYX%7sen>e>ei=H)i#ZSH{_=$Fa1$tWM8o=|p0 z>dLrgh#!J>(wqhAfQuzewL-GChOW7MUDeN8;?iv?`o#hqk#j+Y>)Pd6aMchn9Vl~$ zB9K5W-aUk8q`~#TUC{Pr+n{PvgNg(whsGvtaa>~d9xdCfQT>UQu0@uyG!HsZ36C52 z^M}}5llr_Un_UF2Kn=@7O){k1Aaprh`zR38_H$G3&CkqUYgM}ObRCH?bA;ur^!>*+ z(lc>pO<{U9^oE3RG~<)21Oy{B%=`~a)ChOcwo^CrBW^M?gV*rHpkhEsnabwimT)KM zv*@XWPd`ge94=;2BlFEg5XwkX2)|#*Qd(c8l_hwjN-U$JWrL(2qh&2{zc`e@rjRKB zZMzrUsrNqrPuiL>Nw|Egm>Z_^DeD88WLO{uGK<3{LKRcpy^LIM>m3V(QF(w*rQB%}~ zExNjwCs5|-=Yeq3{hW2biL54~!0bM3>$A}Bn=+b!AW68?4N|Mj1c2y7FPuO=y#rW8 z&pEEoix&csGl85U@mEO$To!?(?Q8!LOWCFX<~?k+joVA4st+NIpRukg9iB^FBF{G* z;rM=oJp(cG%iWL{^SC{(N#fK`_7yKR4HIU4d8%r1Y8Sk;)36yC zg}N(SV);LiUVutUhl6)1m<1^+y_7dP&=bgr8N9>n5*?c$jiMi3WhEW(Q=j_N1Oj@v zn+%w6uM?0~epL@A*`?YGC%m4SPY~sd<4M20z022rUFl)OfNoolsc{`HSpK-DgeOSW z#e9gJ%&cm(@1!OV13&a!$~c*Ji(CUhFJu7pzd@lfXYD0!UdB}R$==!k&nVMsLiKmH z4x|!$?tk2<%BGw~2=3Zf)`h0jPtIU*asgWqhWGgt0rDw!z}{UBckbAii?R9O^clu$ z+!!mAsPasq3l-;JUz(yN%s2vFD>y}7LmWcg+yTGiJadxtNL_aaRk#Mw!-Nmm;{3bH zPqG}(pna3WGG0uYJ)MW#mEZPHcQ|{N=rfbzybZ3HUYf;l4UQqw%^kMt1gi&cjs)a_ z$+2LFQ89z@O#8fwv8+$9l5SMRVVatCjX z5PsGdPgmLN^9!h-Hkw|ki}nh9h0I5>s&4~~ zOSt`#%uWl^O@gnAc`c7Sg)&}-o>tei@6 za7CYO^2h+{yMq_lIED&13Bc6bkIVQG`c$WWT=729>gwY6qW}Dj8-mkJ+p?Q)usK@bu*%WI$h#>yZW)9CXqM?*iZ2a{GaifqM{e&#b5zrHCs_!l+PV3K~H3zZA0P38_hIF|Z zxOQHVMKE!9`jg#Fi4xf;v1B>#DW{ZOpl1G-EQ<`1UMD8k!n7*jE9eaE!!61|RF(gs zHv+N#*-OOtP=4@6xOEXfiuD8ZhTl@i7wYM4ul51We^ogZ3En2!zG7zRLGl+VRl(0; zpk92@B(63Mb)gm?&n?T}ucjjMK3{8l1v>OxdIKlOQsXzN4njKgn>qY@lip+P?~4Da zn6v{S^8nE1anG+E@^$iQfS*^^Hbj90;rg8v$wL$|hG^ZbdY#*aoaEujb){BVgCo={W(?e$qLI zq~){=@{}&S_}66V(IWq5oEa4C!(EM1D7v~x|JhWrpAJaoRQ0=c%yy(Kt2@Jf#SI#> zW=oxrXA3h?c2>XFGr?W&8u&fi1q0Rq)jKg4?tehnUb>V@c<%u9Y+)Z%?u|zp9T&V{ zB^rnvWm;sm00iDHSD`(s6E#)jz;netT4zSU)mj?>?`M+C6-2iK$S~HH--yPAf$J`3 zMtr;{GV3!CR1p-$?X38e-FbZYd+;Zafq$krT6n_1bgNi6iVb}xN&Pg3%{jD3F$8kx zXl~i=(HtgEHE-gBAs}vS`Q1tEcviOM4Io$IKCk(T; zm8fwJ?jOwiAF#DYi?_(kQsiCLo(6#0%J4$rl{yFX(|A<>ku0BGdf|e8OTKuPcmj%1 zB<@_3dY+Wp9L7H$PF{CYa@s9qx%4or@im%hQOHMH(pT9~l^OCsQa|-44>0;|R-I7y zl+bcm?=i1_Lu*vT`FyBK2iXn}uH~5#FE<>wh3^BJhuNXTVUG*|&w)moc_3ehQ+J#n zoREyi65-8x7dtmY#-(O=!Ga%i)O^;x2EV)Q5Yu`*n=p^#axy^h`yD!BbucHUCiPfB4>{xpJso%MptsV`uN_)al8i$(QUSZcM`zC=K;dHQXKc(@Cgva58+V$f zfaBEkvK&PueO23EV#%o0db8O#X_t65)V7!v;xg>aH7|ZR zt4E8Mw?@uGbcIw%+Wm>o6tZbJ-WReZ*EKfF=lhw}G>xc(oSjk=e^H*+2^+=vuM*Oq zoIJZi%Jh!rHOq%WpCkIV|8Eo;A&vP8HndM#j=qXloyJD!xa}A!NubIW6gjADC+T|! zIX|WKm`W!_6I>Tlqj|q*GY82!Lx^lyk7r`HQx-p+b#7}$7Xb7b_W3mW5`6~tgMav1 z&>Yb_s|aN^DqAExoo;G1YJM|8e%v+?vk3AmVj&y4}w6(R{)Qo!6j;l?}_b}q&VwQl(Sj!lt`wwRg+KBQ_JQ>js~s%aq0 z1AEHQV_mSj_oB_7bH(#gHEad_?$IK*JWK9(K>8Iv789*%!A(P#q;lZcufaoyFj!14 zm)O8x!EV_Qsnde5_bt07L0M`l)DMnlbL`|7{9~l=MA&n=fz<40-~(#%#sy zp|9Ji*8KJoqdTfOwJk&G$*aWL6@cRFPkWcz1Bp12>kamV@5Sl~06z@i6-Ek9lSaH_ zgKCjJptn`K3Q&kAgVd=EC}ftzS5=V`%4EV6h5ts}+M`T@-zz=s1ELYc|GnNp+}i5u z+7FvC8_-n@M*1&9jOmx=%5VC$o?j)Z6fu*WwpZ+Axu9GwRdS%o|EMrX1#(mq`MsRe zN2pa}RbEsm&9hhR$qL#GR(n-@j~bL@BffU%>S&6A%}~ma)J=^hgR!FTOyoZ678zG& zGT@}Cz%TQoq3@6kue0u*iV$wt^U2(@;(CCT+{ry5RQoLHYiS!Hfj`#%P!?CA5maCe zRn8T`OukFq+FqT2L%i@W`9F%zJ)Ft^|Kpp@4mM`aL$;Z6$YBmiPMfnNq!SV&$C8jr zg&i?bMifOxzNPZ1Rg_AMIjmAiDwS%aQmIBcv-@}d{@!)%kGb6M`~7-7pO1%fmYtRT z#JMg2&|_#?GxYV;0oKl&99?Av*UB4q4!3P??s;_i%UJQw$F}t61yCf30>fY?;pWn@ zO#-8^LnxP5$T$>6UhXlpyK-PFOAO_md@2@qJyyD-`Za2}D|I;ecrDE}twHrKRvwIN26)(#F^9DdYnh zbFr#(N+M2MJgp`9#8jW-1U2$r4aizyR<3yohW^!5yXBPv|6o8^v5s=a7?-U~4Rt|h zEE4bBnxetTkPIcKFZRaYR!1(PstWurh_((?2V6HGoo)rirUMyl^Tg++_l+W?bdMNA9jY9UnPCJM*OnVZpii zGdJC7{!<`6PHQ7V(SH+Y!w+!_T5dOd5Imb`-z$V zNp`1;Hj&J1!WPrLJWRtn9lgLoT~lo(t3@~D15s93COn2UgI~=9i6g!UN1elIIX%59 z$-$tINn5rR#VzfB3WFT*#g``2B zBA@-eb<;B_3sIvX?L};Ob>d`2$>_IW|G(eop4%{PGdVx@4TNC_fTolt!K{Wr6_2b! zUeSI#Ogh~MkUjPA&s3UfJu*6&iUi2_dF4!(EG$a8N4e%cRzulhUUgctQgs~iD<1I) z1#Uvxh3ZLmDRsv7_V!L{%v^4@8sh46K%rdI07nx;vbjT~H-DIbXVB^Voh#VNUyj{Z z*aA7{C<4r#*~^E51iL%H5BGCw_7?q4t~>@(CY4|kni+9TN!UNGbV=UsUd=w|BJj(J z2@qKsaqbnOpM)7Sot!4VYd}_^AM_I3Ik#BLiJ`sSe-0#UVP;fPsTD3eepSPY(rB;5wauLpMt~8UpJS)B2;<0N0 zL^FFMbx%ad9?cmVVkbi;x^*nt23-XBVeXEnb)&R(a~hX$+xqy;2&l;l*n%EP z0pF+emAo9`VIjwrip?U+pIO41&KF0G)_;#-t&L-dFC)u}WZ|mrM|m3M!@oT7@p1HB z`E1J~>0{|CBhR8Gagdi?KK^O&L=0l5N<6h|8IlMt1GFg|T=}A6#sC(YMrGhIl{$^# zR0?5Brsq?S$`bO)H4xi;rCYqa6kFo||4U5R`y-o|eZ~a3_!OT?1aTet>@F z>$+AR3Xl-mXn0Q*62(W}LcQj*^b5)!vNArk({YRagjGe38g5JNX8Q(EEax3-v8F_9jC-gnDqgRC?2XC@f)5Oy_r_*e=9s zX`yPM$)O35%z31r8J5~vo_{{?Lq^<|$P|PUnKe+5fHacWR_DDs+8PkHSl%Xm0}MJM zw@PU9M>vxGEIai#KhT3g*ENJO{V^=llD>qy-f#X<|jxLQU^!4Fs{kX+rYP|{Vj ztsGmGD5Thsl+2Z`FoB=WT=fTzlEi!i(Cfxx!fxF0X}^#D`m>{>bj@S7V*bg$V(9Aa ztgeXyYFvF8IJ*^Le@)~HV+>t|dCoG3&(NM?hN^7irxIN2=f zcsT>F?np0uE%SY7Jpb1#H=l-^Csc-$ilp@YIpodV+rN<%N1E5NN*Ac#R$$MLC=|*Y z(o3o;3P+zjh{g&xrVq^A7i!MZLAVg)VgJg`Rjyi)`}faQp)-4IOeX0?jk4d%ID$0< zv}3~8ZP%-lAf>y~2L{y~Y&nONbic5JCt*L7Hj5+)YJk_%JXK%uBsWmso=OUGiD3mM zKwfcg7$?N$zm5TYpu)o4{6!|C2LQM_-^e4~ki+W-9@5hjbQ0#rS0}x&^arI&e8aF+ zS>DQeJp-<)2GNK-x9Ko@JK_Vwy)mcUJ$Sc-_zP-a{I!M!B<(C6jc7$iEQ1j0x*jst z|3%?$t5{D$z1D|7-f{9`=?W~umERP#Rf2761bf3}__m~yQfOBKgI-;RKGPY3ypV!S zbn!)u_ngHRi@w@h27B5QsB&CXJFee;63d`bjsIZa&noT7@2o>s4fNmv76!^b3U6&i zw28H^>`|>s>}x6x7rg$xvY@)wUK9;r?gbe9eH`3S$snN=ltGxc6(!1QejhC*;>8N; zvpq;e2G3G8YS;)AqZ<3cet6{MWNylL$c~qG#Y$HTAR87Ar1?nRM4!Trq%3V&QX~bz zt!6*Nqw#?O@A@vC!AG98&((~be_l9r#xv*+K%PM)Y@DlQkAiP^h!($)HM{Aj65{9= z%*o>slN-46x3oU$DD8r`s5;J06JH`px?O%Gz+Tu~B={0CM5_8r4Bnz#275KtB)&6Y z)6kPEa9jn0@$z}(?rI=R7wCL{6d><+_TN>Ae}`Cl4%z3zKEJz|WKSOj=LgS_$Kl&< zuN2&QMc(f+beQ0cYfwq--c}&Fm}WmPXxg+NwogMGaUVpLgE-f0k}~BO`Akg7p)3rX z^0KR%?{?C|OV0wWqPk{c=EKDA1>EL4GR9I#vVOmEvH!1CaGLK4SVAhY{F}aiGbrWOmr2qPHFt=(zhS_uW`)dE2e{n~ z;<M+@$+Sh`~(yHqA`^Q|dieO86mN14Zxg)T(bb7wr85{Kuxq z>}dh}HG}bsnDohhKpV^aG&W0C&Nbb-7HR4N1H&qN?oRX+?Zj$`!7fID2CEF)K;xO6 z(Cg%2v5luSu`+k7*b538EcT0LY_Y+R8ni}f{>w{U@DNh+lmYU86ik1#te-Wwk(bQb1PiG1#m7nHDs8MnQBOG1Bh-J7|$AH^I#79$Sqa^*xR&hc-|m@_?f^s9_(7mAeQbFW235OADPuD(I~X zQ)=Fwn@kQ_td|-3Dwdp7of=1;%0Hvz@V0MbA?uvZkf^zAm*R?wlk8IbPO=KVuiSTg zi6GI$qFVig9zpOlA%0IH{YJTXnr3@)<*#O69IWpkwuiKHCD%qQmcqjgIeMgCqZ{29 zX6I&XP1*s^;ARHvzJfOA6^Pt31zS{d5UjCwXDGfMKT!v~--G9W_xG@Dnt^WpaQTy7 zY^#n1N9P-RTCz(P>mHN3S=8Qvog)mlhRIZST>$oi>%iT4+mgkRJ^lSs`RLpsgoop1 zL>pw+YPeP8i@nAo+lhln#{bf0u#Gc15qOndzN(x56Qqq9A9&$-t5*D#tw}PeF}6|c zAwgx%-{CJ&|2P^$W4`<8bS}K90)6-xAyD1NB`ctkJw?k{f`?jjHm1FYhJR*C8Om`_ zjfS%w)ubGA+f*-vqwLDz=#CtvK|}HBY|`a_Ac=z%6d1>=01*}Pg0#9XI7(bPA?}49 zMebcgOv^d&(H++JAHNY>nUMG`meC!rLrxbd7h_9|b|*q!DG!D|#x`(>G<5@|sCM4? zp7iviB3nblNbEl)>X8tMY6lZo^XM%tH(U7{b3r4+uDrF?a0nRj2A|5`dH!*#K>B7w zJJOHcYbH3ML+8e6=-++U&lFZ^mk@v}>i<~Z%S^z?-W6;sJhnJ;SK{*m0gPcqvrXG$Jp ziNGi1`JPTmms~aT94W-=fp{N65gmaQ>U83MKf!)tpPmEAn{kMNUe$p$8VNcK1J-w& z)>U$3);jm3DGgoI#@*s>NExyPr&#VORvXNKnze~4FiB(nIU7YTF|Uo2m;^ zzW)Ah$j`UzFfl!b5%Y~@{Ub4MUO93Iw%6j}aa=gh+|oqF^}B!zeXSTA96&ypp$)Ru z4_hRyz+$-N%LO+|7jUoG14`O#ka^gqQBXBQ)Hw_up==)7c z)2r%_dFvPY-mtf=FUNn)KuntFL*uc;k1ys+Tpmc8cr&|S_!^{zbJqk7?{1BR+$L(Z zOV3|tr1~8ph6Z{TcfWon9*rK~I-7QurT$cyy+AB_t4`+Wrzn*2zH~784$2lUL;P66 z`)NIxXY-3Cb`A2{5Mk`5)f2g%YJ31lzhv`o*1BCEe*S^{UvZT| z4H@c>mz77%P>%p$^gAl`Ig@uF+{5MIKr;aQv7&6`$9)G9gDgBuGVVi@msD*=z;5HW z1)u|nHQ{_Rd$6efR$ls0P)YSKZh%>!WmdLYq^~G+i`5GT3Z7t z0u#Cs%%$*+vEWIgfm+?PnC1c}|E*Pfr2pT;fQFOsL#1(+M^nX_7SMxo|BC@zp16^8 zLlbm-?iUUQZtm!c<>@4Zp3#;+;H&*sj*lCH~Cf7Od}fUb}ie{<_YF zw->)duXvcniLW5fEy%RCktrvR58T%6w$^%2c;SWEiu0x6Zy5Q`%T)T~d>v?YN33NM z5GuLY?0+~LSk&J1k9<$_s4Z#aI^b{1qZSX0x%+2n+%Ss8c)L+TtEs|y!b>YN555Lj zx|f_U!=;Y@c2e}PgyCDYu7PKtMEfcv#bVpJQYb}fst+jI{^;-$1?08AFv_AdC`_XO1z(a2Gsuc8iO-6Dzolf)5TD8ZCNu{dw=Jrl0To& zh(Vj-2_4H(l2r%{T~|9$@bN-i-m^SO^X*$gHOHIvzkCzCGARDIwQF%F3`*bVE-!%U zLfktJY#hoMj)nhY#|rLQ4(ux$fU$;@v1W?^B^IPlbu*PpVOyU_C}OIL6bJRKo>8WJ z;LOY+p|aoU35aorg8lUzeYM5sD`h_viz-pe$X~I>R+g8CjLVnh04;9x6?5CxoBiKd z+N|ylJDBbz&o?o~+r!gf3e8darCQ?wG$GB4B9 zb|TJjK5&7F7|PK7A6)5tUWkfS7$bo3MJfNJcdsqw%u9fE`2;v)a?ooF`%Ike84YY| zGqYy3+-KUeboN|4gKu5aJ^Ed*xQM>{+bi+dy7g37zc%0R zNAtgOUfBBU!^H8htC!GB1PKL3_vsC}S3NXA5@D1Nq68+ug0a|Q>&Lv#rbM|V5 z*HfxSIwP3{-4e?VHQ z!K~2h0!Ccc-&y5hM|=$0yYlA2kXOnP`uTEK4Jak5W=hhrsMWTsbzHr}_@JjrC?>1+JCSi5b z5Bc7u67x;v>yp$~PizfaQva=NNzhNQZB54RBkr*$BwnnBhFW{5ax7rmm8l1eZ*TF^ ztgXUMTn8;~A3-?kb4ajDMmQE+eB=iJs#qvc9B|j)ypB2kp8u=mG zC7*WpoC~8n!{1iuDU59x-Wy@9x;-C0sjS-7dz#)*?X4$gAN=#jqhWu{)sXf7UDux6 zLxNjdXDRLI>hdMMngU__y_cq+8;~8Yg}C)n0Q8Nm@)`(gaDL@yblYNwePp5xxO}4F zE3MwM@26d*N%zAJ=EWxGcyWT1sl-09ViIC`Kh1PQqbk7uENAMW-XgaYH=GdOYs~eX zQHxG&%Pagn-t+pRm;1Dobb=+ z0-M9og0rPTGq9t&5f!lD|1IQ|;;5(5dr{z~(9+$jS&0!(_WZ;YJ`^t_pAd_~1~+6> zQ$2MY8Qm|L{9wj|Lrg_i`WS{Xv(;SsBbxU8d>TJ|*iTy*>NdCd%TLMI*3KUlLwhR- z(G^tWRb(eBE+4Aga|SWowCvw?^HrR<*Hxw{T4U{hMT4##)mgV5{vXRzFAUEy;_J9EI{s zVGF>mJ;_zG9TRd&cs`AjuI-15azhJ+8#+mG*_oU0G827P`rRZJNi1Q=t zz$i{odYt!nvx_`xL>jl%lcRw}JhCe z+;b*Xbj#L$8F3*3?R=;-?v~}Iex-A4bCd^Z6si^X}9S+eOB`C>>7T%!Na~s5T*9G!OkI=-lGuf6jSM@)gGGp zA*+QwaY8EM9@<+HbQp5eeLynYlUhN0r{nk zkr?#NL~!W+%WLniL=*?>Q>SPR{YL$AXd(t_a{U3xMP~Un4%2fVcTV| zT|9_w4gR}DjNoW7z(|#78&P+X&%P9K;3kM`MAUab)eZg|dg%zr5AUeqZvUl4*m;W2 z_|RxqZM1vhJm$l%X!cqn z^a*1W318QhW76FC)B3CFqRPSxcL^ZFrc+TWxK7oC1l)t!p&NNs$}OLIrKl=#o)x4! zm7GzjQTn=5!JS`qvCUg0B4LMMm#AX1^g85iL3j}TaU$Q)e&X>VVNFw@p#4iNvx5-j zwhWC%foRId@>+4T92Y`>R7;d=)KDPx?_iIO?5njr0n=P(mg=sPZ$kvc?@MGi{TnWk z>v{2zQ%9G1XTGC4SdqBYVD4_@jA`gQRx9DP$~^8uxCbuB`*=04LFs-43lFUE8+Tb{@Jvpln3qU+h)5g?DZ*Kv5=nA~vd4NG9LS z9NdOZAMOee#E5z-Ks1EXCiU7%pV|gz{|k?cyi0%i&FZG$*J?UM#1w^lL>_L#*n zR$pbS`*a^QxT;cNtj-7v^i^>jNG@Y&n?3f=P<2oP=dkH|?rTEVJ`)&w(vG>DQ_dNs z3>Ck*5p9oBL2*{5iJQW?R=)?_o^?Iu81wFG{Vx{(gsw_2JKp#u%ecR@4!*V0f4yp0 z>**xhEsr0`u~sX=11Xa#{v8Otgy z$dMik;i9bugeuIH-uAUhsh^n*UkaQgtBU^fUu5K%cE`E)PcDWD9)mn_38VG@=>K8{$Nfev zm!8N^e|HQE@_T!FbWySj+az8a!-V!QSLUC{*(=W6{8pr7=FfXVZVrHP1#4DZ5mvX} z78#gLYN1{hPh;L6@sZCok&5V3as~3=v3=v+ibIO&I zs$)HJ6*0_l-=QP5;Q#qVHVr+P;dx!^ z6CH?p;H;Pa4%2Ni(DIn1bAPeJe{Lsv%>*fzwK=3~NJJ05!rA@)NhdTN7UyBoZL~x7 zeK+Y4$#xtaByjRqz7?TPJRCt<94B?9N)ehofL){~G{t!8xZSGr)^$>2oBjX^wv1K7 z$exJ~rpRfr#EoFfYWCE1?_5ffCbQYz@>=)|Kxl+1yfoayPa@;i3m<%=!4|B%!}LNW z1w$&P2z}__hl2f6#F#$(K3v)TPNPh0Gu*55?@+%fPm=NVSv24T!Z0fyy6$PfU?;6PL*)%^5nB4 z{wtVfNb?nFfhKPSp! zTWn-^lqSZHs>wVJGOJ+W%B3e((|_VH9LG zDQ4z~Kc1QeWZc3YA-c!TFaBCL{9!Vs37hS@%$WUu^WQI|W5dQb2ck)sSo&`T#>HG$ z8iTlCJpb*FUly>u@G}wX8tH1bUp>SHskP=4Q^BC8K2N)Kki7s(9^xTZ)7%y$$RReR zch2CN)XFsk?~`ckUtYdRUV7dD^umcpsQqmm-DIT?b40x$S+3DQTP=O5GX_1v?*u&= ztPsqtVtgkugURhz8f4a8j>t$$8{6F60SHr_zkJh-o1dR@3&ZtC({eo{UQ%1SQ&_w! zc@MaJ&8d(PrKj$qsqlf=b;%P-w}><{<^kE154yGvPL0h{n)w{PKEBtg4PW#!RzYGY zeN*6e`*wt%Yo#=foQoO3Ap?8h6K-kPZo=%xc&;N+*`5q7wl_1u=!%+6O z0G%6GNKm^QQ5~$;&$;8+kZ8@aA<|;tOpC}xS*ro?`1~Fq$6yX>G*UaOc66@R)%lxN zC@I${D`=D?SYe)k;is^mrvwu6CRu zU7dX&47{O!_$9M=-sBk(wcX?>2U^<9Kb3|UQWt-AcMTmsqr)8dnopI0 zcG4M^^2jOiC0(XQk3&&~_KaMm`p$|U&jD5nIUkW%B5yLQ9lDOIp^-7Yw)2vqvKQJ<$}Up(`L7SWD8lB#!88&RxRCnpx6_Ih!; zmDwS%QOuIw6w)>0VlDocmRF=RaB(}fxb=@+0$o*^cfeK$&(W&Cr(Lffjw>@BXL$`4 zG$F~@_&TIxKK0$J)!49qw)H_9gi-f<{o^eB4z6~6rYFxF0WR`ZPg{qL|Kr@#Q(wm@ zeQ7b$!a(e0)%V&C+HEl$RlB9U+R8QrziirN>5DkW1-#$Uk(bre&~c)3`1lrx*$2;T zG3vjD10R`U7Jm`I`maUnk)}X|V3~seG+%cq{oW~nWNtC9EFAL`q6RC(W(ks^m4Xv? z#u-`xPW6xW@NBm!Xq3lg3B0umudSxmNAuaRNpDbxN4SpVs)(-xJ-^K?##Ian>L!5` zi_wAW>+U1pJloy0qaMv^oj7C+vwT?p4dzh5nA6a~hz|EEymYkLPnUx;Bh)o3*b}TT zXeU*33Vo(fBr<^opgc_f;A4x;4rzb&RpLuGEpW9iZ#k5!-IlQIWPECSR6qb>68Q_* zku`%!M}4k1d-}HI0MO^>^kr^2vXd2o_3{$n?ZOM{@mEq7rxcbu>|X>&z|3Q_FDn_s zp*8T?+R>MnkI2fqo~)J1xyr|GsYwGGTWG&yk6dlF`>I_vJgM~a>%;sQz8M!ER$PiN z_58TvR#K;yQ)d(iU5s@TINi1UdWZ^KNT%d{VH58az2-Dehqbdg}43E#-`zi%Pl^Y~7peclJV`kYa2g9lZP{1A-uTuSoJd z(fO@ffNscbVZ1@MlhR%zfAS9=rF$#M*8kBA(Jomv(@;~czkQ&~en-$@#F~j$*M&k) z_Z*zo13_MlV3@P{ItbQ{#Zh2cQ~DH2cIYmpEbZ^i#w9vNO5Y1`Ooe28XO~hq3c6vH zfX(K@O8vl+)LXAYT*$d)9NM(I%VkKjOM=Jbc?up$`}{*8GAvsBcA zD|0(7{1IuDvQ8fs3ual@48+F|>CxYGp$_Hsh zltC;Q-D!R~BU31!kWBhcJz@Ia=YCl&A0Z8p)*O}@W0HK~k5>Gg;G2RxdFc8~ZUd5! ze-O<2Ow+1mQ*<*tT2DYev=3Tp&gp9tG~T6<6Ft>609 zh7T)T$JIY6jd0T~s-)54TE<>C&JH+ed4`(Dtt&!CSbR z2x%o-n$`TfZ8LAJ`gg(|s+yUK##H7aopR5`iDkY*dG;o>mzeKRK3gNdLQ}F zOQyWu7m?&7$$(bpZ=yV*FI8d%_ceyjaNmGGW+NsP?CCRv3e916!`}r`TjM+(vt@b^ zx0x{d8*vWl97Fh~VKR2^i%oaz`cHl1z)Y=BKCd(~uJnG0-k8Oy30cwo{_cR<;h_3W>;5U9mTpmt zYA}P|Q&~WUDm-3$J^qF70E~Bdt}Jm|)lSzm{>;O(G50OB&m#fK7w=)EC$$5od4Oik zCc^&@y19Sxw*PrmelYv4XSEqH6(i5H6A0#qH8rbEhOcV-SjA$iKVwpg+)N?cS7$n7+;r*%Tz3+{1>ij*${qw7?*5pkw#PdwzS zdk;(GRrk&Rt=u?{%?=zyt+yM%v4ZBfAW4)eV)@LklGNVin4Ow0@i)fS66LmX3t2lN zjLtbZDk+LCKdR)nGE2O6Mefb_nWbH#$?sv`UYySyyIlq~7YX_yEpNcUG57sR_*3sU zCv@}y0`-LDz&dH;8$BSA1eaM*30OE+?dy@Q*W#0lC3(vB`J!D@Vcr}Ay$}Rlu)oLL zgKFqeG@bV0RyQ3_`m`B4gow+3&st!ydb;mn3M{T>oyhX?zkA9RsaRM!E8XT5nGdt+ z?GD|6PegZ}T7Tf99ZLRJvi=r#T0dn!bRzDsyc{Q(SAEFFIU?cpZ|h8Dr01Jh|86PW zQ1gpKE`t`k;(T$4Dzw<@qHG+y`DHORnoXEM*OWqYd^RMINJldHyRo1%NRJMwlJeW{ zAoqn`%!~joZVs^@J7pA?qkh2HytfYLg_~}~bU)J5@$|%bdKQBMJHsY_@G@9BLn55= zAzoF7D$_59yb1Ii^1A-a$B9>pj~?^|DL`7a_?sm4S83z3u9T5$!!VS!O1yY;m(wcs zb$4Vx6c-mT`-VTyx_o4?_eyd^M;wDt+7Mdb8i zA>uL67uLjUP_YP3o`1Qt7(I}hBe0=LD()of?R46R(gbbxSJACEqzs`sYxU;J)uOGe z5UZZwyVm?$Tf{DvgZbbSaq$C(GJsL9eRB3AKn`_9AP^3-%%r%k0<}6N>eL?)FD6Fl zdjv$cA5%GUwUVz@scJ{eR{a71*x`QeII~-5>aFT+HCu?`YYTgrW}}_~2_9RY^m@$S zPt4h(+LmsU`4RLI1xk*{TDA!4p)rNlTvZtCAHw-xUbYl7mrJr5d@wa_32PDKT#Eqe zFJaSA=RFe6aLMey_4&m9IsUBiogU_RKF(~ntzFsI;FKaj{;ni6A29uRMH;}KG$=Xj z^)J?5$t1t@Ox@)>jNABdH;pBLIq0cT)Z(AYlXkrVg@q~s%j^sO({sd3NO{F{x!V2N z**~;_IQ?cT54occ|FXyBF;)sNwSa>qeK17gFoWmZ z=DBLZ*SGr$Q;5KO|6!)NL8rBo@WeoD)G44KFo~OkTMtq?Q%cEBSUu94kL(eIGZgvu z%Idz?}9BX@;usl$8YH_&r{DKxFJ_quUM=?b7wwWGi_mu4`BZo-;U^9nD%X%VgE z#H32nU_%E)TTuYLq?z>=c@;@NHaZLV?w&y1C0Yb+Ug}gJUwgGqCV1~1>8j@!qHi{h z)7X>zsubD18tB1y(A{tl=abC7CXN-VLR?_4tiU@>=Z{3f}T>DfqH&1ZN^$LQG5+rWyw;* z&=S32_A@{cQawte#g#g|-^r*|HA96;7B`+@s}2v%cPhVig6~@|g1q+<-mfmKQjWaL z9q!7G#6~kA?}NpM2X52~*Yc`J8G(Xx`Kwy_JbYU^A0M{EQ^$2>WvK%Cu$E`&ZDzx6-@Ons^E1`(@%n{L{&%uYdoz7iFB29tH#H${9>jYI}Pxsd}ec}&k> z1Ng}jZnjDU9C1EV>4mUoAL%apeaygN=VgZvfb`c|;X|2Ex>ydqlS~f?XN_W1gtg++ zns4ih-YCSnMIP8a1yT0J$4+BFJU3MTPF{-0Ctc)hsB?pA&zNQ`u}>A$bR(ycE{n#_ zjb!<(-n%lGXzk57+P_@4W9PLRaNDtEb_&4M+D5X?7J37fXLXgb!)9m=0?Ue9e;6d@BF9?q=l^x&vJWXBZ=SZYq{fy+pPalHx^EKWb_C{h`D48wH-Rx)Jp*nj0Rn z7p+7d+tliH>|>AV?^?`Tw|ik;nc(gbd=viN+lY(Ib38^<0+crUf~c~LF!sMGVRaC= zwOnUGN{8c@N;Gg%t34v@iC#cHWf!s`FWcGa>aNavdCP?{2-YA6-9F$4c6X$k>5o;PF;AP}3ZF#>BjE@HnY?iKB>3h8i zVNO2;FzaF3AS8XvjsFtSiU(d828lNV1pc(yj;-p)N(0GVHhNQ>RA(c5QN_mQ;3wS` zjpO%W&GUuwbE=i!n-5{SaN9)4Yxw!6J!>!#s3(sfcTpRl59?2Yf)Uqi6Qgv?!z>lr z@K)1uR7=}&EkxE)DA{&>#TQQ`a(9TeHO9i3C#>qLREyHdob z-~Rd3k)IOkS4-5x8pRMe@kmVlBX$+z#oFT{l~y}xx$3)67uPA)N2u{(57J%<(S2hl zpZ2(PZJP8PwGrXEC@{b>;!Q57@lpB?n?UyeEbCzx|Lx))Z>vU<>-cGfUW_LyFD!3h zmviNbkcTIR#y!hOuIo>Iy$$&9gVgP)Plz=94JP}JWOx|u;c3E$V6Qw>5|h%X^_THO z39Bfu*O1=ZY4}~)R2dvdms0IQpv$Hb?A5U1Yo|HijY9vkx3}}KhleIm>y5m6SRb7V zwmrqF7j){fj8ptd6IrVR_^x}Yih^UO@YM*}qU^d-PzbQBx|vvBJBzf_u`l$D^nRAi zqA_zQ7QZx3XCxh6u}NsP3sG%5wuCpo!^fzF=`*}sjBBdU8GG@rC#fsmm8#myD=U~2 z@9#O422mtsem7CJqMM#G^wm{aq|_DP0Qt*O5JgEvl!S)-_)QmL8=8jMJmZFK-@a%w<~!vVQr+X0ux*aWh0I|9Ao%Zw`#0@*J1ju5 z2!vcHDBkf88%Nw%=*H>Z=?RhUoKrwv!{(w5^IeK6PNS>S|EJtfXwP1OwCm_qKc_>V zqg0M~Z{q*Fp%0rhIdvo2-42B=a|6CT#6(?d2jfTbA#T2lt=wQD1E!U%6eD zZ$Ncx%UM>%TNWohgp-JO#A=uLnpqD)&eRgax~b;TR1_fkJFtSu+CF_y3fD6*{n~;Ml9py>Y+$-HO)mWIhHf``>Gp9u)DQi%Ds*H6 z@-WKZ$h-wsMH3!!G(*ra|LEKo!k4sR76#)ns(PM;42Pd{g%xZ_t22>ihP*V4d-sV3 z=v9VQlK*=PP)$9iHHUo#ODv3>aarN9hT~D%g{n>QtETs%I(DcvGq7>ANiDoQ)=h3q z5BVq2`DaUI-KbSwEU6;g@}FM94Vbuh1HzsJQcj2LvVuK=EQML6a*H29B*?5+mT^i( z8S$1$Ta+@|yBxP*G`%hZox#t!`7_LI`iEPb?qnAwulcdPd*Zh^j@&}8aL$te7v zrefg6hTfin^SHZ2{Zsy?Xyfy$D#ydBxnm2oO!gWIr70S>;gQBDy>eIGcYX6cG3T4O z<7=A@(VNa=fx@+RfaVpoRQ(Yp1j4muyRX(v!<*-fU!-dT59e^U!r2*vCRK#n|FkkI z>?F~$*z+9&uE_N6TA&d_-!ObrmF~5?+T@Cup8W?Ct^OIkvz}8ul+}6erQAvVd3NRx~BgM4Mg%nDi1OAL(#S*i;%QmkHwJxeuhxc zndgkUt#=4$3QCas{PJcN`QZ{G>ma0Qf>Q~9Ki&5PLU_zj0)thifUTXd#a2OiOdWWX z1CU=iz%t~^$`?=wH4nz$Z=mqfcpWGM8F*wXyrmasim|tc9lO_$E#}gMFXP2eF9BF4 z&^4{x-{J4>qedbvA=98l5WXdVto*M(PT3*5h zVM6Q&-Wka5*bRq-?WGT+&u4Rb42HoL8_5c+1%SOc5EH=Cwc?EN2w`_w??z>D%fzi# zDV2Y9(`?CW?bm{NDB?8wpg_#dQ!V%X3+n>k)LI`fpvv1p=8H=12a6D+oEJK;d-wxM z-ql$Je48*m#Ui(HPs|TSk%q@JwpA3Ywj8TEq`ZS>Qo0 zx{_amFqIwM^nL(@sKb71s+LYWM9lhbu+rERQqNN_BYKPhFF3djx%8slTXZ*!;r8{1 zBE#J%Y3wh@%PaG3vcO;ZKjmfOe^)(Bv{0BBYhyP>-~C2a`yf%p$zpHsRSivJ(5Tyr zFHew&$*=VVxHHG#J`|&)yt4#7#h!eZF!;JycF_~2Z5n0&pwEpz1Cmp0Z<3{Dul(!N zwXXM33umPat_3Xm_>-ReHx+k6e`I~BeI|=#*(@Uv;%l`>s6+O*J;#V|v^(PW?uL5> za5RCZlphw3*wVFb1W_;4!DvI)@6RpYmUNdd2jnESK4M%NVHwl^wopV28!i zBTQa~u1kjcidV;NJKi|EH3gFV5!!NB4}Z{5IEf2i14;0}OacNBB1Y98{21?TWWY*> zA9+mvqF#x%Cq`bUs#SD9f%>LWQs470_WAVlusfjJ zdsS#>P*?0Fe8(3B>)|0T)b61BUHg}C=kM<^aazKr+YOBZwx*Pu8#H}zu#^;a^FYz~ zUm!_Uhp*u~gutA0pFE~Vay0fsm$}EeHTK%ZI-U}##MsW$u1h^{{i4BOp^ciTBhBi| zCEFku!=LkYQq`@`O)yQiv}#?Vg34SFelplGT0Iil!4{d_TrN=a)4LUMUhe zf!(&oWlpdYu?YTlT1PIgNHVhrO>sAZBCr<)K6>f#AfFYHoq@$VeRU)doQ4GmoV?rM zHp%6cMg@vynw(H~57V3T7k^meIrGHG?3bSgoW<3=c-tY-SlDvGQ|j=%*5rL!lTO(W z)kbhAJ_OTCz*7y^oUF$d7_~;E{O+yu(>k_DyoJLDyl^0=lly^IF5#MFibtWqc0(tJ zOvh)w%3cCVlPUo^8nIEp6Z$q*)bS3MNiNhwhEywqZ;*>@!-j80 zmh~P{y%z8KXWgi>mB~HG4UhQNygHpXE#e84qq+LFtbOa}yUGEE`&W*`WG?V`iOAJ^ zU>>HS<$6NnH5NSimH*OQ{iC1e2d?$eF_s?F!bg5#@02bhM0nB| zEe`*c*?1`Ai1DI3T_^L-+@Avz>$>SJLUhiWgyD@`fWSCCDAQa3|M>%r?Zs!cm;KJQ zCbBM90iwdxG#-^zAu+uQc#SM9V5ZHD2L`;($rb_PPCjSSJMtiM+Bk(xF>8Mj{EquS z=y2h2p-;B(bR>PO2_XNfss+eJK`}c=x+Z;TdAP$$xapP$%(^#CE`$2n6DbI2*#=B(sUDoM;SNkS4O8yn_OCMro8c}HhS zr4n-}OVlbAos1|_8X?Es-~03X{lCAq``&%Op3m!gJnn(9b6TfT8RoTo~~_2jaSnh$1!z@9&qaP3 z6^&p`#|aun?!1c+^iTkz^3`ALXRsV*+5=Ir691BY(;w2mL4a)I zr8Ve-dr|-dzb>t+rT1GI9L&Czi8wja)YwG#mqA>*gw<8)r$2pPqO}%(%pGFp>|T_r6%-&;nu7b_}BN)FJpr4Uepf&YSEo@H7eGl z_;}{349OU>w1l2eVKA&2=w9|f&LU%z0FT@&kBkJRMp{a3fNoaaKt0dnELaDNfV{iO z-wutqnj=4fl0^yX%D*pXT)!f7r=gT!wOW(>g9Sc~|9No#C%90|?#rlz}xNs+iV1q*8P751;y}9$a z<>?dt)znB{PFO$IXBe@Lkq5Y|{aU=PU8hpA{^nYbP!)@}@2p}qLL(6^V_pZUT?be` zsc6ORN1^X1QZH+zaJbG-vxIv#@2>fnEy>&9q+YW1KtndF)J@GTnat^W{-TdHr9!I< zcv`I;H|WA3!@c)qMzv7SBR{Ec#=fOtz%n}IMY7pq*8?Hw&&8el+t$YHgLEGL92;RW zLU1pB!XCiS*8VZ_s&$1P$fW;;zijE&zim(txubT;UK({29W14W*+*V?<84^=O02ME z5f-`?w?290FZE?WEDLSG1*uK` zvPF&fhs1R0GO|!{5vK7R;R}Xch%!@8Z*kR!G|!P5FypA**_|L(_QReQLsN|W$K3IN zLc@?pXReH}zS`-Un(BovjJ!1lqg?!)eAV{o_W>nSyn9nEoeK|;NTGPe+pMQ z4bj00eu`p{OP8k{aU>CPM!7i7Lhl+Yf{47V3&B7|4jnWLSakM|=HiL{q|24D2AT)N zy;_yBg5JQhJ4SA2md0mtcXlpxT+mEfUvo?*&SN^Ql<7nkZe0A$ep~{*TDGFopBxuD zhQhiQDo$}ALS%!7!el*s-SevyT4s)+h{yR~IaYG>e&;&eyPQ$nT#$g3D71Ao;6*P(EIPko;`Lwk z)pg-PTgcEgomyOf29_J>1?%yEFt>E+jFkj={S>x4c&$(8%NiII4 zuyiC}>QVR>@mKd?UJ14Wv#sNT7Ei&_tzD`%6q)&9E@y6J&)C0-*Sf7)4$?!$r=1s) zp!o_ptn0x1%0}nn0@()U?Qs$VzL%_S+p(&%2LVTB5C=eu*X=1-Sm6RXW&S<$){o$u z85#dD@O#j=$GtCbq5pyKCe;Hpb~Zm1<)oYA^ONv8wsugV(m`+oLZlS|VpL?Zg>d6- z<|WU2%5@6ID~wC~68I!zpsm65Y=TKrjkY9yqxdS9 zzg_hbGyF?Fpc!SKntSg zWaD{z$)vdsCQ;{;X)Zt41(3S>ZOJi5a2#Q2{Z<;7F_l1~P8ylus~I6>CVfPN?~vbs zh&AF!UqSZZWp=_9)_M1${cS)dALcuZsB`oR0O;&6cZQH&_X(7m!1>hz6C@BkQXnXZ zukJDM{b|ihG=x87owT`#3HyTWrjIqlxFYoCZ=x|`l~!1;ul4=wH+_g!@2a!9Q)4@-RO_8 zR<0|(C?9QMIf$(o`t{2h`#DEXtT+DQP{k5Y$V{0;u}e?M6<%bvF=H0zV1GGrF0!V@ zNfAGO^r*1+>T*@~@!uxzb_nnf9QmGWLA>nxxfZknnNNdE`JU4P@&|V}Usto8F%ZjX zPWdNhK_g1#?rRh-_M8@dJ-sEB?>i-PfDL_P3(b%Ti>H6wfDIVdy|QKJf&u{?wL_`dnpb z%`*SHz|NDUMz*H;X>rDlD~QXru7j?&;N^9go(TFpJ>>6~{bLmMGmQP*e$f}uV8kQP zZ~&TQzs8#LD2>t{@%OwDV{zkV&U&ASZc@lq#M^&5&sji&W}`yDC%LR+I@^W-9kj;% z6!hD@GK!xQ^+8CbhVE|6A>)4-g%d zly1l%lazrdMK_Cd!JEMWzCBW$$?5)AEjqaeAn|5^1xCY%U z^LG@%crqGqP&FfDSItzXW{7-hhD&cncp1cVb`Ng#n0E-f5O@asInrZ$6!TiP=A7{Y zX0EUS(S1D^54>_C@?2d5VzXw)@6JY*9gy67H{~me4SMa;Rr(RzuUOxb&s*d3E)Q&F zzxEIAWMTJ3zJ*brm&Jd57Ku0SM@_xJcTeo#Obn^a0(g z&uj~!|5)06`-xXrh6CmINIhAmAa2Hkp}udU6mWj-3NomJ6;zX z;gnWNqOtl5$U>ouXBY>HD+L1BM4nnKJv5u=T4ZQop+D&A}MG3rP z0~{L=@gc01acXKVIo1jKaYe^YcuIS_D2Xi#^fXpP1V9Xq>iPk0X(SNf@ldRm0 z-_!(O$mQlS#t+T_6VO$b#g79dvhptc37#^RDEQu0g*dweVoUkDv%8(11jC~iR@61K zIS-TUHeXS>b(S5jP=jm9*3OvuQn*i;Mo$^@pE~UB^=wx^#w32rXjo)@$x z-DVpj-YF=es+Nh~kOmNC8>hhcVMEU*Qhsd4?^igjB()JJDaF_LZ*O2gEMOP?h_aC1)nsIlj}xEa8mmY-DUIjI!7>0J@@VejfIN$w1& z)}BaniuGQOMZSEOiQ3!K2Mt80JOxTlgIKC2n(@bMBUqNT%hSe_=XQ{ujxjS!hykBe zd5_e?Zd>K}-CbfgHS7)eF8eu|d}LV1$A;2cwr?>nb=>J(-$s?k8B7h>IFEPwCUbS)M>xFd||Y$gs7Q-`^}jlsrIT5kQryd~5Al zrC$hZKK%3ifdMdk{JgMF+P<>sPKX3$`D;w8YH`G+FC*dpLA`6ztLOVI9%rMxbLC)CQ_%U=6>0Yz6JSgiW2*1n1%sS({=? zPmPE-wG3kU2^VODx$MvKyAl6%!ltu8!QLAP`Z&B&N+XeC&1~%$WyRd*&j4;g0*Hkz zdoMn{MvdzLD@y2fYinvvJnk8iwS)XO8yW^t;Q)s>XF*+#_!pE2rk-k7UmofQ1cl2-P2R@JQU>qR5%h9uZWr; zHsV~m=Rz$)J|wcw-7jA znT^|*C?})HSbU}M&8bM}xDkbiU@TaRNVWuTS`uGSTbd$sht9;@*VTnlFY zrL3;al#QrmO21RPaN?^$u1a!PKJo+ei3 zsGXa+dhSMzDzOh!jI~8K&T6XkNsQzge?P^xDlO_ru1Sva-(JbCpOCe=X4MF@cgtK} zJ)gaOS_}SRpK4zI@GaWs9+`N1dPUVXLBG7Ef#Ar73%@k-)c&y|Fj%TKeP_}aj9f47 zK}Ls9_O2P_x?!}+>asU$eBJY_*E1t8#ug1U84qh0qAHcd@hu% zP~#3iV~QtLsJdl=Ac!Q(`x8&G)kLK{jCMkgm%$X&A9f|2$T@A^TaZoLB8_TR4(OVv zI$x&~Cl1=Dx>$X9UE2(%@s1q^0`stpB zX*d~1g%l{MI4VXZBGzWLt|sYLQ2F;+-%vL%!<#W5T)lWUv?cY-i?(Js$bRmzAgWsx zMA5BkRA%IIB~D(^;5Tm$@xq`HpYu?e-gU0SHFuC@Ke4)e(&ZX#3#&rvuGn$j&uTt< zFQ?U8XSXcDZlZ2*SoC&~B>IL@dWfxf4hD?2Jva?D%mq_`8mlWs+AjFx4y0~Un~k0w z$%YcZkR3R}FI&vY)NOtJ?GKuvMP?1RQN5=LjM9CJk{`Mtkc$5nQs9WhSAVkV?F3Bj zykaTZo9sqZT$}A$5 zT?+9w)TrkuJVTEBqO2a5&6cMoJ=XYoi#8B;Xjs2Go_)EKEeBSu#1xI~IvQ_O^KIJ1C(@*_mi8sfwM!pff_ zsVxPQc;9UkN5On6$9MHE4GoZHYFE+}r0rPSuz8kkA-k+Pw(l_3>=A~O8_PRpHl zLCKvbY8e{MRBAe-Xw&fgsEH^tp?nRTofTJ#q@J#@`&986|xWvE$2R${c@FTbKK z>}O%&@_72mE<=hxP=9^P`SVHDUu6%=?zj!)E>Ba{w+i3>p?0FI6${w1&wrC&w*!3R zI;cEzM*Ya0m!FQ_)-{z-4Q?iwa1&@;Ul#0R9Efg`2D`T!;}1UW8JZ}7kkA8E~3rEv!}>X zmb^koFCB$)cY^!HuU-DyM7{9=7?tzo>x1Y`U%$?BN+40fbukp?3kqDs8yN24-KT;m ztB~r}ybAO=CEIAo-kIgqDW66R^MAFtsZTn2AF7N=-7UqWu&hlO!nrZ{UY*rydifX5 z$UDFWo8$Wk3os#Sd)IP(&*u0sR-PtZgjV*G0!E3W(T$q#Tf9#1V_l1Me?ev#CLICp z?8w7DLYnxh2^Hw*!lb4Ug;>$OZwU#%#8ce!0%H|v46Bc71I7bK{T2=%HVGWOKQs|D2h{*Rso1CUaCIL{jTOFh7o@})@Ryjuh)hwMWErq7V zXbH`WiyP`yA{I%eE{r3JPV(Df%D}AZ-*u65$V0$u)IOQ#HvAU&krAz=hlZQ4EiL`n z2#;2hQ@UO4(jG&WTa6{luCAVZa$7+ue}2;CM26StF8~5dlCtMmHt1~;@XeIC^J7%c z4#=!sfP~uQf>MWZ*u0C+5Wek$G2VyeV$ZWG{gW@`?J;&yTlE?V%|q687Z0 zYn_k$v65M z_DSg&5lGGCNNBV z^&;OE`VdC^wGI^+0Y!~Xoha~ud=^|UXwO_z*tM*qR4fTIbC3bpCpsazBqHyf;A0FH zh-kuc`>_Fc8J8d+_DkIhZ-qi}T^c~25ZM8!iGbJ9H6Vie9X2%Ae^lE5hOIZT{6F%3 z*&%tL<~@*~_>yHtT*YnG;7#2kQVJQtpUxH_o0hWYsbk*9#P`)2GpNjtk0d;sQSZk# zh&V>8{}0pze(3M)L)-%xK4qkMm$tI6yl;wixB)`0StC5(q>~wtOKI=WE3NP-Am0=g zy$bl4lLS|^SSmUAM$1Rbm#Wd=0y0jzPGW`M3`}Cz@;yOTr8l@!fQgGbSd)389FGcs z*a#Urka_3gEtwGzIHxOhno-t8P89A+;@~zfe@*vyBNI% z9SiyO`aG?|8>j;Lx$*38^~7K1{Q;SVhDN=TUxv#^Y68@1%YCrvkZZ1@&Wd3sSECww zH7X`HukvKS>*^^Q=M588oUo)b1jI!kcD!5&B&DB}?zL^F|5Aw-!HYl`ybtIC)YtTR z#f$?K^qMy$Q42Fbl{OAKt5MF!8htjgzberDCbsx^^PMErFpJY;Oq8F3-;G2h zX=ZUKswHIfi$~EM{O~iug{^HEu1GehlS`e%dvoy{llH<_F~{U7i$PML;X(?Df5M83 z#RnSkv(a#UGZS*6>p66hE21OMs#6HMlHA5gBiU$s6-5*%#YMz->y>;a0;pC$ znbBPhhWtXfAxHPVe!U|XoK79FKTU?Gm}H}j#drQzcVCq^^U2A^GrB(|y1wog(!yDz zTFzNrlNKrk0HZ|ewQ)vyoe-k^9&r`zMb_Ue0P?+-m~j{7E0a9itmO<8?iDNE4B6+J zx;j!8kCjpG*e|F4iX51}tw%Dzj60mIxYd5!wYuf~ERo78SSsWg20MWXmeg34E><{D zWS$}QI*I#bO4OVQ^8d^i>CZ2NzH~C1_qnQ}2tkj{K85QMqP$@@ZkQp~B;R_DrswsX z{ZE?X_oJiqLq$bKfE)(gX)Kzf(vI8onPR`}&Jd*w)!mAnk?}w)fwQK7_LmJXpOZd=29w z`;%IS$E&EoagA)XhhQ$(7JktT>HMy^lyvxx$jmU|;L(q~Lb0h$263~H_i6BPC9$baiHi8A zps1Ere>rKL^E1j{03)Ag-~P(F6=m@mt~!?q-0L{-B|^2o=#X*g9K`=QK6W21@vo1h zLeKn`+n9(tXcRfA8ez}Z*yg?r&OiabOoE?x(uXf@HU?K5S4ca}rePUBKIMm-d@#M+=sF9Z zFrcMb#EPF&0Ad?>yJX2wC^Ui#Ic?glQ|0He;3(+FOQ@%^={Xgkjb67%s{3Ir+b?K! zMXiba2iJHiyNdTr2&vJXL~0HLx>hSXnXby+m)eB^rsL0n8kU+<|Yg0s}= z^$%%HREfdhaEpCy$L&^+BAXV60mTGC$Hs103xG|BlBSB7P_^X|8&$i>oHvj4#aPt3 zY(SXIjWo(aXXb+N&S#d&>$}=PZDC-^EnImVBbggIM!wn=qdLKHGcY#;lcsLGr{z57 zyw5Rk^G*+3B~zfk`StOak3jL9JoW+DC;qWMk& z)x=;ky=TXX@zU+@p7u$ma5dkprI7-wN9;&T=bHk;tB8Uik*RI5xA7ysnRDLz^~J#J zm*bo>aQ;`Frd?v2_lrYb!4(=@5O@i>^1DA=c>c7Gv8G?MwWfat$Xy zi!Ld+32LuJfpw9B6Ha9OLpwj4$sN&VtLTjN4jn2%kiu+2q4q9MAMPNwB|Arp$8tm8 z0@FkO;DsREFwB2DmX6phIOvj?C9@`WSkJCS#@+1+&)bCq6%nw5(GaKK)SmUIv(>!& ze;=&yrXIIjZHg2}l|w)ME&1aJZ|H|_-u9;&h-UoAk^{&5f-*VXc{`JJtgEwNuVDzi z2`TwwDc;X4=54k8U+MtkzI%5CkztI;@q=*O$3Wo%cJSLAwL2X($a*y#PVFdy`1n9- zYdf((O+6xOMT%-6ewT+&G^0@sBYcmP#@yq>%oFGzdlkexR;XDgqFDE~4$^o1VRvFG z@6s`!7~qS7V;T2+|nU46a-yoPy3#8Yx^4R#W$dIv!*AiZx(G%>I}O4V3+6L)~R(`ZX{*WAX#VKh>=3p~fZP>)aaoZq}f8`-nu>B=ZO=QKm`BB={ zgpPlB^73rYLowQCjj3YS`DUMGHO0G7|6(fVhQhe{lUI=@b0J_d_6VV9*6nBz=Y7huP)ALJ>5lilyvTl%b{^}%yJnxJZAy~5vFEO z+ku_1Vh8%0leMeV8^TDIA-3-=PS72|C-AFHwC?q$RT~WVa zs3#Q!X(T+C*i#POrCct-(FYi(;dQ$fb4q9>emLh zX~!yy#hqfR?d0WPL{oJs)Fm7yryOtrXLSp`1M&_rLf?u^X{>xsY3T@PL#4M=!Mul6 za!ks0XGuA!jRlsr0h>v!(|J|WeBo&NM;9zV3QtNpl8~HABT-T;LJUi`JzDLlRrisp z|AO`2tyLzg)Imy%TL5}gLx7pePS&)4bbYPm0=r^PM;kBE>Jd43B~LL?-KOc}lf_t~ zeB2z8EnFUXK0(!^(<|^hCT5cW*IG_`*N@D>f?R1Vjpqh@a%zp{H4VBJ zYEW(!;Bk7nw_uf*Kul?wqG>)2N&>ldH%pPr{?Y2S-} z^bw7!PKky$-=+?!m{49>}hI=$}VDrShFa{$)CAKrZ=UMWQ-Yi;&?cCh5%KY!4z zO&~xSq;4NkLp$^9_5`gv9{{in3w>%KO5BBl{RIhAWf>tPTdiyp$*B+nmq+=s7G#5( z8+fsztA;OUFz>drTN3P%vvWWbf_fj zjDe{xD|yY5)N%BeWn7?k=M(V(=Z^3E{a3OU+w`jXZU+ZrAWG?++9k@Di@{E>%{CCy-@BP672t)Y*gZLpc8Ke@iuF z_>HlB?g(g*YMp}H%`$RpJ5!=U0i!$MGzmF=mwoG<=f%4W0T#xUnXujKS>>a4`F;%T zstvybb18`xX8Z!{yn7l555D*U5-W3fe>N%Utw4Vp-my_J;IKeDXJ;z4Z8btH&aJ~X zx_F}8$7OfCk~zm}kxScQ?ORcH?#zfjM$+sCD!3`kpcvL9d*wnYbow^))d1fZ3I-r& zw}eJR&cEn=)+hOku5;dpvH)GWQ`D{>_U**r!HR&+1!^%m^;?NfxGn+k3TRwJkLNS7 z0%Vd{mSH4$m%=}gO;;Xa@@J$vrdsUFE7aO2a_8evNZDZ3Z6T4gF&rbfDTQK1M%4f| z0;2}{hvhZs))YM?Y_k)@NhQr%X3UAfRc&f~<83wvQ5RDY)piG-g) zV*j*rn{%&fj~Z9(DR}Y3VY>r-`DzxYuj|4eA{U$oi;Pv7C%l}F$i!hM*3nVw+0;1Y zO6qGPE7_0oVX~k*aD*C95+Iz-3q=MS9-T|dr9P952sr8MD>TlpdA8nW_IX)Sk(521 z7|USLF3}(steDQwmzYYm=!kESDNeW}b^zV`6xf}#b)A)x>K5Qm!!oY5scZyjI^*fT;}5z9Nr0oWLn%#(~F9Sr+mAofdd!;%{@8 zHe{1cgt$be)f#%QF7|WP%#?E13ws?wj7D6x_KmfNu~Q*=jN9b&!E6H5_2U-7^_O(a z8GxB*HsF?Gxlv<%>l*vu*dODh4(*BF2p*x)Zfx$a&d0P!)+5!i?||sNwzrnA_6Qi{ z1fdT^o=am#t+SL&UmbR zUgyhg(S0NMHf=X~^g!y8j_D<$6!02IGWlLR{sWlUudze>-3csq0<*xtsL=gZk$dYF zVJ%!geA+j~(@VnS?AF0zRm+xrzndwgXJy+y0W(9Sc!V5}i$W{Ikqu)J1>yLVSR;bae(^c>(CU zzz0g_=vzWQ_iyLh*`*C$l&y$>wcq+jy|0q1_zfHz-$!XNXuA>IF|x>%H8C9(;nsY( zZ?mezDV)0H?8s_q;CDKTCyL)%fS;!LZ1aP=zu%Ry@uX8A zv^Y}aDgZ=5d5I=!#@(-gJ4Q$jxhl8jlb!Gv7e=+CGPDbX{wGiRaU0V7r!?Nl{&+;sXTb{9; zrAQY;{NMuQ%fu_jXLv8NxL{YSUUenEl;OC3x89&86p7-A#dv5GbaQv{oa

    #PR(syZl1X@r46j3>wG%#6({PP6a%vQ5!Rv@ua_*=5LgmeD z7(|&s&IYs6+4XiH7mTdc=@93H*jC{I?f%h1$YAwCw-FYtM3~hc($*w3{N2SrUqR?J z9GMh*53o&A%sXGaXs-KCp7_(pisg(`KD=gmM_1MfT#L`hdh1M-yY{Vi3LC{)HiN;u z&{j|&HhZuAwu_$MQ5%NmulJkgkE4TMwZB^ITB{uh2{P6{*tGSyjk3jqze{>~etG2d zq59ezxU<`ruk`R1qKy0wRRfQ!BRZ~UqWX||y!|$bBG>3fWl{mg$#Y%ZJD}k=b=DX0 zpRN$1*z6v)*fpbaI}iq|72N{G%&~WRR5ILy^Dx(?fJuzSSgPyl2N-)Z*yUOPM2CYr zBCw&ps4yNYB$;CK%|&a@c;aKY!3&zQ(yOoZTMKJz=oQxlDX=WgZV4X-tXmP6G)?pw zPa)U)>e9_fUsoNU3IwS6bt2P0*_h8n-bF+-+pm?4M(O+7zqy((peQnSxjD|u{fdf< zWfOaZf~755r(dxMEJBx6(I$@iGp=n7JXzc1Wkmlq04qEQtJqJbcNUyMg8A7xjW@A* z4d|_>tX+*qBj8Z{25iy`V09J!NAXUIwGF>75VB(p7Ip_4q9W6_jWj_Mxw`PGX}dn< z7){gbAF<*@u0CMKz*o=+xgaw|wW7VTcc6)%8k&3)yxCMN{|L5X88pO93e_V#*InMp z%<3eZawU+mJ$C}D*;NLMm_ZcW+yr9z({0)q!iK-kigk~*A3ka`)8AmhK(FoRvW|CT@RPv&}=`7Gtop zZi2(cB*t@H5*ZhpXunPVo^6CG>Zj==rz#KhzlxS7R7Ut|nR3XtZ7!u@LqA2N)8MQyaUc%h3z4LOQMe zp?=d5yEZb#cU(jT8G6>gu+%mw^8UqWUCa;*IqU!a92TsScvxrQqZXy0cL%x%8$f35CIaKCvwO}rE+x*(%npRAW90%uf;E&6bn8lJ` zStc50s5zsQy||4r8X3P9aC3G08vpU-DLfpbNI;ujluT}duTM&lGw6RN7dk0>$vL;% zq&t&a{rZzC5Rv7E+t?63^7HjaEXBfC`X%2Un*;0QEm#(Y^fl)B=v#jGa{Pk-NeDjH zeUCU}zfDzP4^PHsW$k#waaL?iqB@Iss?DTS%PAsXM#0?^y&|SoUM5OZ5qQUdoDRh@4y-i@&^1CBtd{C~vCxPF1LHB#1h2)t=SclxC!Wigp|v^$3V#Y>ZJfIQ98i ztmh|(?9YchTmrS120VDA#`~JT1~#Y9u9oyiiBey(gfVV^5HIr8^GxC2~f;7{ID`9b&0XVzpNJ>)X87y^I4u@Qv6 zc0I$=qHOtK+6oRY$UytgS&KJ*QK&1aQl2JqAxzcqZkEA+@%FAL)yCW1 zjv-0RVVog$YXi;zwFl3&I5mAM?cHvyiY1J54C5N{?;Eo!%*%VVr;m%p6368R&?et& z&S(Gf0j-?!8Wbj-fC7xGY->){+R8?m{c^LxKUDg(ipL4~awPkI&J2D_AEeu}yR{o7hw z1#8hc{^vCurJ5mg;oJqawm5uqhJ0%h58CuvtGn&k3aap7@NH-;v6W#`4HHr#q54l< zdNxfh>ICh$ytC*J*uG8G2;4zVcZKOWXyymNqwd_P4cndfcn9ad4$kGgo?SKi8?oE9 zf)HC_Z{G!Mrwpw1Odo2YWP9plLZEMnbEnqpKZ~UDwd>AW=zqKw#Z{KFKQSbA>}XV| zb{sbHpoV@Xf#9J%=G+JwF!)~qa#rTQxS}t-G)*^8P2Jf)F12AZd2J2wUA_Cd@4Z#` zfw#g7e`WEUPpx(%pSUV1#!|ZQ>Wmw=hq+XblOjFG=pT)4{!N1B^QixH^x-F<4*k}h zI5IsLxA{6gIl&L+p_6{cxFS0M8p6rvuIH{pl`n!=h7BlG!xwA-xN7`K{tSrR`(@s< z)}i|$K;SqfVFmZXckmV}@B6OC7<|Tn!@elN^fBID5~0q zV<-_vpO(kE$y{8#e`Z~p71lve_Ry#AUrTw^#x-2~1Ks_yjt9xrQZHX#$6O8}k7eX0 zGFB4xL(E&3i&D>++ngLlwsvWT@Rf90`I(68J~Wcdn+T4|5m6?ZIz3NKs+|XuE=*@$ z)Z)|Q7e+ozwPTrCbfdgBtEw2Dl67A7!n(d|uO#QkTCHnvBEW8DfA_SWiDj5Ajftz)Wo&rT|~*;US;(T3hJ}1tXHM;MJ>cw&R}ti z5-~N2i0O^=*vUWNm}V&aGCUj=&O$k<@(N_rL2Wh@8@hT!@O-9Sd_4nzmgMG|QDADP zu+GjfEDyPrZ;e;lC1xOu;s?*PN!sL1YS=lbkoP$Q9cqJCG_~T+cNB`?zAw9P39gli zyoqGM!a$MGDq=6ZuM=hZVC4I1e)&_fi?@8dMy29pGlQt1__#40`GeX>aW*0`>hs7C z?!CSp;&~ra{RCv;_~ozQ(x#ZF4_h9q7QVFOjViGU&X-2;JG$x{G}I@4=(%gMj84(( zGfxu;gL@075VV0sw|g2Fp75Vq)0-(L(7pcKYhCf-T|MQ{fLG$ z%Bh9c0n=Rv6Hy*h!(yYZdrz3Ow<_59G+(g?lV1mtBjOC*eun>=R6b`JaR*}Yhe#wB z5jxn40f3uYB5O~(=q+T3reRJmdH@<;O2MD4S^PgZ(;xrtF}VOs4a`EsWVPr(TEszQ z@HD77%(E22s}*Dtx9cjsXdiB8X>4m3d~MQl)M81wf?{F>&0Pcl-u=$OCa!Udu`&GkxDAlk=yBFhourm*4}kp}X5QEN?ouS@ z(yijpgf4s3@`~lc!rwpb)KVoPX9?+W_PM;~ihF+=m%^@xC;SI82Z`sw@E?~yIYu?` zl}2q}(TQ;4B8zYojW2PY6>^+2)NBliQ8Z7xkj$`_C@UpbaSPfU6zl%jZv#$4vm*60 z;C7IrjIlChKx6U<@U$EfiAkQ(hHBYM}COg8i}JJVRpiaZJDEXn&A z%{SO5=Y@#~raX54!yzTRHE`td=s7%5LA32X&~WfdIF@@d`BnI)2-?LG*LmY*Pi5Xi zVRGK-5fZWBb{WuBsL46OOUk~&4CY9^x@F_&0H^gg1pc~18ym4m9t0kFK}E#j~q+-AmP zG29Vrqj^OWz6hmx2+#tO$bgvwSxt+wphq5L&J*IXfUan2O}rGxo%F#Ye> zt$8)DycZh;gZ|Lyy8X8N;%4$uzoenU$~Lag!QfOzT-RQosDmao6JEDE@3bsax8>z+ zj(Vj2c+Fv}r!}OL!{c+f{Rals<%PRIJP5`SO3(l%K7% z0J)`7{hLZ`Z@?==Q}!KX3nWMgW+=LQnM#Go(-&u}`>fH=^(F?j>Fo0H@tS!4%rkBq zewx~>T=GRtB1VFqsY!P5V5J%TPUo};llaNJnM^IOO770zrpOE*mOc6DNYM+aX8y3YlZWWQM^n0 z1>^Hk5^9hS3L%_vx8?bm`%IV9`)IcuX=OW@i-&9|jQ*W`3abLL1;c+UB|l>e0j&S< zMf##fG|It&d<($si3Uq=FSy|F-P@-)M^oJdbX9w<<%Z#k8!HsI%G;{y4I%eQ_tA=P zQuI_-Gp<06s@>2k9*J)5mfzN+cNjNa-0pvd6hK(N`77krxNbAp1@&^pGf}y*M&Bd5Y2Q+7GG<|G~U@PP%DZC0F_UbVx2V zPETpT68Z_{w~xnj(>8F|p}2o{o3%=O3*S1XDtC%AL*18 zB4d`Ou6@>9K`|=5Q-Yl|3Q-WB@g?t16e~n4pEzuLcz85*^3SWrlW`T&AL7y2#hKsh z@opcB$oKS`t|i^g%3N`Em*J_u#ik^7zRQ5w$YN6Kh zWX}X9^R?PMzxV^>iG1P%-G1-O*U>{u)ruJ%Xu}y!)my8SO&4>teoBGHlc(??pXe{) zhA*VxZdO_3;tF8dl^{RVrB^jXtIif{^q2p`4{-{;CGjoaW!;aJeRpA4mKj;0`ftI#x2m=t%ya zopuA?_wwI4ng&~{$-7DrA*SdfNmeXvT-=TD;JZ(~k~9uL%?C3NH$mS6StauQpuF=6 z;qFQHAuByE6)%M(S#n))82GBhVzEYN6R>zFa&ZA}Dj^+(nqPNnZeU;ATAT*L{6Z(_ zc1l_DZ!_Bc zLmxbG+t(*-&%SxT!k*OrJOqh^hAe90$ji{jws^mJjMMkR3ujxD-o0lJ(K_m(Pjx;9 znRZ0lJA;u(MO}C>dTVQ#;IFZR=@s2%LWR)<>(|2y@mDv@EiS#R`A-Hsv?SgOb~iDs7YZpeX(>~2Qpo~lahHtkZ4luFl~f6Jk6 zL@*5kq616@3xF!k!(cXy&Wo7V>%;60N}7_NzUyApF+d|*b&isR!MT0 z-;1EZcAvGvc3}f+Ou8!nnaKJ`#k#}wWGz~DrwqDY!yDHy%+FAT24^Bn zgDgNz<*t>)M2P)M3FJzx{6Ue`0G7Nw`9A+EHb7Ak+rm+QazXvZ7x#sU)8O5zWRYIT z((h1cA@zFs=o@a5bwwu2k}0Wkdh-w1laZsWbZ4(?nC;8cKh=;SIw9_xWH&&910a~L zmTyePVXT`3_{e z66U^`J8$D$Ygkos{B&mG*M-{+7D!qGNpvC%+7$-X@3RWjUH(Vy9QxgmtK^ZgnQecb z_Eh)uo~qqX0l%tVWwlNI`5BUx7eWZmt>ZkG3%x!=%|ty6(fDF8y!2#DcZaD$7GhnV zcf29_9Wc)K-12bXRgCgi8@=Z?))7VARMn~E;02%}hK$LDzF9{*(U9T)n*NvUzb;8_ z6P&WLg7snnIp)4ySk-|se1uTDuC%C#J&_V6PzVcG6~^HM#w5$!Ab;+LK9&Lg=-TaC zt@;-h8BZFT8t{vCWGXJZv@q0P&3;WR)n4}rZ(YnitK^LdDCK@>WHK{~v@rpdO}q*j z(0=Ufh5<=k0?Ts2Ll+FuFBNRyr~xY+&8BkkMxi zO+WH9K2*^wA2`jqDC{N(x|8`oZ?p6Y_-D(&;;8nwSEvcD-xS1mfo+gX^Ie(OPO9yr zA_sbL4TqX(Luj`%8eNEi4p)($9RDL&UJpx!3aHhqSY`lL<_$%BC5lv0X4e>@cLm4`gp#$H8 z1=gTgCYG%{^DLr-BBlSl1OQS((F^HWzN&5vlbOA=n~+MEgFVQ~9FJOCIb{TdRm)mq zo#x8j)z+#jaI~n%t@~;wcrDqrYlU_f0aB8Rog7^0b&#sH=DV|S3n$M71xgYW6a5CU zWw%^2a{nv*6}-4`|2)#w(Hz*WSS6Zo_Y#r=@A4Pq_oi{W!X`uuUcYj7FOkaEfFf1x z_6@Y|ftmfT{ncTYq&DGZJ7^q%lXlW9*p^h?0D_@{76-B&m;O*iLGP*`0_s)8587u1 zhW8&^qPNmN91k76V=W0^M$E=xz#`}x`;r_$j>|~T*LG1AJ_9a}+t+Q&`m!#5cUB-F z%rucxoAW@fYLPOBNO@{8p!|#%O|`7Ni*j(p?=o2vFUwpz1v6KwXkUY*q`#?tIZC8m z?s*yd*;4q_4RGt^jRVZGh~P5LoD%Fw#z~wVTuZ?p#q9$Hm$*QxK91A2NUB7yfA2N} zIjQFO2qF_UYu+#c@WF75zlJiDd_>}j$BzBQ_st5@FjmT`9pJH>m7gUTGH`pEPE^Mm zUeP@@ZrL%+XK~z>D6iBBYg=~lJ%TroD)z+R?^GqbcEI0gHGC{-G|gCf$vP7W4h5B8UI{YcaUv# zPmEFX?hx8n%c0Hde+=CwIVhoG*6AqA0J$w<8{Lmz5wy5JI#crn2&+HGfke|}hxW!3MO9=(+E zlHY>Nw}}t;8Kn(iGO+rv0X-VS%F^k&y=zI(;J6Gs_)v4Ooc}HVkG~zltCX9vdcVZzov?pg{(F~QS^PlGxMGO7*S5m zP;HA?cb%gxrRX&Qevh2utBGK7LkGDUYo~gN(0E zT%G{^IfY(`8*tT|(P(Ie_&H3V)n*8?D&2!{aDPh;C+vER50$0IQg&{-@kQ~RH?iiB zafj`Pmh!w>PHM3Q}PAo zcVo_URY39^GE0=<9x6F*8>8DvDX&O*&dJ>X02t~8gZ1m=SbCt_5`K{chi4d)8CC@x zxv)K)8-J;txhc7>5JyUBqCn72kl43t4VS$LFNAgi~rRs9(4!*8e;ON9EKel?G@B-?DdfxAO|AJ zQ#YbE*goi($<8rL+O8R>5ocv|oTh;4IHSO-#cO+e=x@RsxRYwP%{8|}@_qd)-L{d8 z;>5UV`YF%jBzPMg@(&Xe06)a~){%sb(jmE9DgP-+tX_VogoRBTWb^1BIf zlcq&U4w^}+`w>fj|nuw!c|7^yJREqMNT!I&L{_VHaRPH?T zxzcg})WrAArCHj40o*Q-X6SIVJHDcH2b zO1~uYYj2KJu0gl78V%`;5A=5Dq}xj@26~OY$)5(D(9)dikU5o3%MG*xHk55EOyuQa z-g!FxaIm=2MxgHe?m&d+Sdm{q8V55WXMg=W_>4yh(Ci{N}12k;s^zp@lTS%_qP}#usRh zSvVth@c-d1Xj7KJfHX+CsV9ZBG$Lbku837pmieeAe&s>axAaoh^M zPj=_yaFasyR}1S}Lp*{u;*8nr3pJqMZn@f3bx#kM72GAQlD@ZY)SnC=a^~J~4tSh% zG5^)i{T$Ql+!jogY|X?dQ*_X>}uE#;|vDGJAr%|B&BnK8yCj$yX4#?h=(C1 zT%{)UFFpS(Y@dG`fpHxAv;Wd1{@ z`eQT=F=X9uYej7u{+w5q#>hcLpU_bLJh#}UM1jrgJSS8M!zk4ZFr)LcF*TUt@39Dv5oO( zCqHgA&mR3pzVuqG;$oeavaD8jVH@irn_G?>iAtGA+9soL5Z*0OBzO+H1*)BqWoidI zIK>1F&Oib<;WsKX^wTh7R5*j6J17S5J)B!>xI>q%SewYkdM_aL7lhKVOw%uskfXwh zhBjQ~G(&m&pq^b2YldxF;CxhyhD-F_<5TD#TCoKKMVA2n8>R4B=cfQb2wx?=Udg_Z z6-)=p*#w)$2zmRd?jUB-?I4*{$&laRw(OSresE$Qs~)L1M0@sZxR0~KXG6C-Wp{zT zrzMD{$c>Vp$=oz`BG+P+S~OieI&ia$zC^8s)?fgt>YJkc?Zu!*rMspz{>4>+ zM&=t*OKGs6In(6Sm@zjjA5+9tUC!LJ)4BThn#bNT%nrHlITeni{#T-WrEuf%A!+5g z4d3E=3g8kwUNkKqRhRXFiCm0cEi{09(OX6hmP-nYj}r_mBl>NObm6-=+sp_nxn8sA z9bPuLN{t;a0Vs$uk`?Z~#$u?M*`(|o&{e}-f%N(Y zT12D}V>N>oLGqvLQNk7B)A8h)W2mUKFx*EVXxnB&Rtl@ZspJR{nTpvBUN>$)wuhvH z?8(A(0{L_z{=htMJzLL}(YP|(bKK{p#BgTs;{Qr8hVbtYvuy@IoC;D(Ggyg@%G7)QYD_U&wW-su=%niyekIT zp$@d0g{BO`lEmYH!Lb#k!qafB6$kb_sH4AXgG%Y}(| zAsr`y`5sL;yyApsv4VMCA!eNkQj1l@j+iS?q!5dRLqLa~sv-&;QPn2sii1qsf6|<4 zL(_Sr{TS6l#MvxRIB+16t#71%r}4dfzE%lS_ZdAd%6&IvMQJ&29}lh`)>AF`u^;mB zd3Wcj2^V)K4r1oMMJSQ4X!+L`wvFL%6}&UJQisWyQfGUd1*qT|9nIW`VM;T|9Znv| zMe|J_Dc1fZ2?(=1sqNi%x#0~k_e1=W7Nn7*QP;hHzbC?{yw6t~v8KpXy z{FGU;gTJZ{&|fX%Oc(y3qV2SwQYYcuxMD&8A-{bvpk#s2*bqqK80PUC!p`~gMo zI$VvEIq>FAn1|qg==`~o0)a_NIP@v{psRJ|LE3RrlWpyuDfuA0TX;-kX)nva6CKPd zNc%CuG%XS#TCb}`lf|WOeCML-i&t|f4k)s<3Op@Sz8)X3u_QlfgJlqDfa2qCmD1w2 z2^He-T!`MZ5BC-YNF%S*pp4ZTd{0NtJKt-|H*b@jo}!ggZj0HfV2=P20(Ndq{6yS(mxy`5LO;9|5t5isDQ$J!0n-UcsD})ZV=UWVHOkV88A{-)i3Eh{|dXkxEuj&MIF?Ep^4yuMeaEf8i~Ty?QIf<9{B8hRsu{;FzI$_mT66W(w>e%?h1y=9DxxiE^fu3E->i+Trpghx(txu^n+SIZSMd_zCv=;^Ck>z zZw|aMa!w&ud^*V2rP&#ZHSD_#5J|_w|3GKlH!U7Yd$s)SphCKpZp?@M3}Ht4A0{%0 zFX&O1Q!<%r_7kaY;B6$-%Y27k%n9;YC4IPmfF=v^Qqri%FJgmb5cn}jmua9<H zzL`cXcl#k9#JoAVxZ@MW^s}^o>&kFZQ+|1gL^#8ds}~6bAMREyW5Im%Gqh!c1_5F!5n2PpeS;TikY7$72PbCICYZy zV>lG&um|6$*PVA(0K@&uxIOOTOVItg6xBkuDn_~@|2_I~+Y18Qx< zDrWkxW~SgTKBlcKsCyG$mniNmC#$m}sP0x%3~J!1I@52FSAksP03ism#@a;fY)gQj zm4H`)^{hRWAZx!)k)zmp>*lw#g(L=O!Iwei zOsGZN@y>cE^5=oBqL+g1OJ~|(ook*r{3MJ#ElA<~a5GOP@3X2wdr>FnoMq;yokm0j zU9!pgPFB(r-M`UmxUF+7e=vc_%23xp*+b!SMVp%@sWnzv54;fFDh_6zHu9goI|LYc z5DNa&&fcmk?Mxy%yEkZZ*UKuhj~V11l^cv{j%O*`)~r)|>dOU0FF^LGHkZ??UZM8N zA}5;WgSDz$!Tr)6{uRKtt<}W8kQ6p2=Mqjjto1l+&lxTTWyBBD?$V8#16HV}x#P(; z&ft81nFUZDVE6x$)j>Bj3(jF&fP zNiQg|vuSkoQ;T5G_6FzpKj#&7ZSSYs?er)qhyLtf=8$VMN!70tdiXGLH{BiO8+9+N7|ROBvVjrZ|m332p--v0ps`-}#^3>2NXxOafT0ZsM30ZXg7_4qyd z62-W`g$D##=lnkb;b$3GEGdptZ{zNu6{x>(^HF>Jo9d4dSU%LpBjp<8^%7U+sNxyu z^OY}0f_zn!&vyp*%}v+q2V92tx&i9B*kK@(vq0^6!-$GtKeSc9{VJ!34-mDQS2!D;Ga*H&3MEIn^L^t>e2hc z7$QBghNesK73uZd4%Jl}FpYS*eFF73UMa?qmx|hQ((4$>aCBWJiak+=t=aXEt4hd# zU1=5><~a%${`7<*lg;}M!O?nKUHcea6EBX8xM5&bq!hdt$U)#!N6%x<78N?W?W{tFg!x%&F3zL-emv8$cw7s!UqW6$Cob zerC_u6Dr@N0w9J&OlO(GGVhK*W~TSd;ZiSK_$cgq^Yub;w)|Y`!tYQF;x}`F3&P08 zPyldMfoMasL2mIoYLt@sT5$auDLl%}*OT(>+OVuo&8Rj>JK3z-Ifot%NA+ zlI%prb0 zb~ha4|HN#6Q?4~9t2?!V+jOks6Li0&ja6rWP2Ou-xlw~BO|F&ir|P*gv+TTOS7VTb zv@Q0}-~HGw4v?vA%_+;T%`0NtveKG#;in)gdYgG0fc5v}yAcjKMeKKDYdQC^bw>7u z{Ah|Om-(t^M=mc`ps1>+#uHr1E=5TvPs0|Y+s`(Z2!}9{ad>ur1?yv~(JQt^9N$d( zl6BAwgw6%EqOM@_(<({+5)eL6Ga1bcwZGx)-})j)h9Em${&(BQ#fDrC8%_fCD=+S4>&qG2wt|pzNceu;6oT3L zOt|98(oeOWcfy~IU%DDL%TPWlJ^MX@=Tg`D3XxFTbzMD&4SuR(rUgL5gzWuMDa9~C zk26NCe8nMz6kc(O;-5X=ZbZqoJP&O&`bFKM1MAuNEkkaUJ>3|5V`+?>uqI9-bNJfIh&1hrO~hbpjBOF z1=wa(%Sg`0Pl3370rH4iz}M)B<(S{kvH0#wW4Qx`rEeSERWMOwR{7k^T@Q99>Y={` zR_UW+?tDs5DWvbFV}ixxBj2JjH+&2G0l0aJ!7A>b<^N~z@Nm$9AjqS7XcYYjVe$s) z)iYViTYXnmZ*2uLBhb6ca!NUE;;_49yWw9;jqspPbEN(w{%@?bv-fFxDd#-gerxq5 zYeGjWuBaF?I|KEOxGk1a-pgn@AoA(E8g-L&FGP4*^^41)H#LyRDh1;OS1KPxaKc{> zn##(Ej^TG8>dzALHITe(M3<~=dFQAw8Dn@<3Hf0TG{!3{Y>VTQ5;&|QXE9l^bpX+)pz z_n*ceBr;5$V&b7!7$mF9Jma^>0*|oxZl4Z?zF0OQa&!3^J%<m9K9S1gkfKkYo2<5uU;BC-*=0M; zjGol!-7eC}k?)WkU@4Hv>u5o1*bOi{fk1@YQ{02S?122SD#gFZHvI*cQIBmW+1bJ2 zX#}$W#&4xYULv;-0YPf>Ry5UJ;pU5QP1cZf?~^W~2wGloOvTG00>*-VCM>Vw2)MpJ zUM4_tL>CPTOuum*(XUvMVGQ>Y-7Z7yacg@ui_~2u&_gRM*$Jl^g(ReYo=fx@;TdZp zt@_cp@r2M@=7;wH4B56>cQAfxn-@?7NB`J5+_f&2uN`X;sI70ICu98T4HHzPLUWj} z;ksKJq5+iSHYFWQd^Ot|R8!_TP~5TSAM4&DzjjOw3X{|9YtH}SI{e>ggSFh-a(?#@ zfwl5XAHW-q$~?b&toz*9Lu$AVn~~zqa|?2ql<#E&jb$NTF`ri#{>q4pX(0)ihIb^P zj1`k9iGa-K?nUq{ZjmL0@oHzDs3Y+b&uzD{T&!TRP3rbEpQwJ39SNo){uTtr&oXPp z#G}FTZ-cwOR}3Vr;dF7|QSfcFJ!z-XJ{XDE4arzZYg#sQ_|vH?*zmLfj_hu;o#{Zu zEG1|hSJA#JMQOKhhuSGtK?H0cTERwc&>)giigP^n8+by+HfSMUql}M!mOktx_g;N5 z_Y2UD-!a=W^kgpL-&#%~mWd$QGI~>WTSQka~*mk^{8j!!>`|^)wIgzosNBMz2d(6aj)1 zzhX;RgiFWC9Dr4Q)JnJiVtcVQ)Se3DoLHm=_^I_C8EgGc(oFM}b8G{o-6M#F)t8|y zZv0QHq`)ZJCa#{sl9J{|O?ZZoM|mtDAkDIdU2a%PCLVQKDnojXtGCzylywdsuheW4 zT%JtqLJn*YDr=rTzepGXu!3&(+?$D_NbE0a)dI3t3;*ZqQC(zm?{R%6Tm-r=MSS-m zV0CJ_@aA>bqbT^hv}^`$@EahGaY@;8AdDR7)?{g8!}5z*EByG=@?)-XGQY0NR#6Yu z`eotIuBkUW!mo5_#2YEN)rkGb^$j%$S@wsZhW=b4Qj(LUx&_kVrnP%h>#X3OVRDY* z?+N?gAvQeptCXWAl*jt*A{rwaj+`@9oQGDOK6bDp`BxPZn$FC_cf zX1-1XUZhvmxIcdRIj^}7VhWVI%x`L|0~J7v7^rG|Yx~6%sZAO(WR(`HvR=V?4R>vv z+ZoK)5WlL4-_Wwdvc@fwsSo{>3VVZiPTNCMvvTZwVz z%{SAC+m(=+a&7l!?4!RT3UaEl3A<+V_is{GxJwQnsAXn)qq9VGNQhA8LIffdc*+_N z@fcaJX`I!q<~92Zh|d9*!TPhlc9YRy-|^q0mSjgznGC(ZQQEon_^`A7;O2NUFJo5U z@qsL}0#R-;!K@(cakjz_8+@|k_jN+1Uh~+TUB)e-*Wy%sv5=8j>|;US zC}x$=b5g0owg9Y|=jsmQ02RQNj7WnKqpeERgpVHSD+^e?6_Go#+xqbcRf= z0Jg_oFq^~Hy=(eM8t{c?#W417-dFqrvC)?lL+Ehv>J$2kDeo?b2h*P>q*H@%MXI#o zaEJ5I(GrSjUsx(|RTk9P0$Hbn!k*}5N!S0H`ZtUHQg$WC47rcwQ;;9E;65-iZk2e> zVRme+hiN9d>X{S&W0P1ZsUOu`55Ezi|H8yRG`8|gdH5~QpqOR9GYTcE~xI6_)Lv5S+!5L!cL*iC8s9 zEAEjUkuMmT!eMU;(qA9Ne6edc8)4ER1^NIunS z>ZKLY`RXeF@lb~Sz;n(r% zHQnlc!K>$SPs(dE7q3bJiv7fr2D?njd|+3n<2W_$*QyT znJhDO=8}52;nO>f^kheFeWT>B_8IE(^7h-aS*DAbQwQVd0riXB(}scN9jZ{NM5d9H ze9O{HWuqnzz6@TgH?suEuChkWr0U7s4QhU+@ax(h22q*v4S9s5R*isG*GK0y&ulGW zt?>8Fky29!0A_>IS8`KBhD>yVw(|wopP7Kju!0lJzFOW-LqS3oQK2>R39HN?Kuxq6 zV~F%$4+-F^-V5TE7O@u)AoxG@0eipy8O(5q)ThmYK;6tDYX+~~`ZNsXq@86bn^kJn=s(h)Y`0HKk?U)W_{SPhC)x}+I215kNacKr_N=!8!(`8s_0 zw%{~u!wSN^(^9k)@6yQx>)*=9Xvd{Fo@TBf9G8cDd%K{Zz$h+ro_=-_?dZ`}rP$n$ zJPR+p%2AVt&4w{D@9&d#cIGZ9=f%P7?))Bkh}rp9BEy(0(x20J^*=K{HP(>?IUUP2 zvG?Bc3_qOA1q35y}Z_?##fU_Fz0O7DlaaL3`^6;m-rR;CMO2O-Dbz3?RcR%^< zc62}WM!vB;1l@M-yWtPc#x_IPnG$ofrzU26p}e?+BbIw(!Eb?IZonSZ9G1x}o4>%G z@R4m)Pf^)8$1vSF25TE_P+AjAQ{bs5a7~0jkMO(dn=EP9;hUhJh;W;&TY`(nzdzrF z?dpdA4MyHLOh^PSvc6A~X0lNpZOb|5veZ+~43lb>3c98@czBJhdDaGje^QzH!+82) zIs5Wum4nU;)Uy7LIaKdMVEh>VuO<2QHf%9hZB%z{Iwn`EF8i*vPdmOmB|*_!b+7j! zORbZsT=qLivpSoLOT4OZ`mhGJFSN_w+SFNwt?qSD-sBHeJ%n|gm~<;T4Xu{H+*KP1 zf>SFr%a2whI?V2;ZL9y*&eg$N-sHu(2!;!z)C=AMuC`#Sba|%oB(l2_Y5;Y~Ku#^7Y^UaBN{pA?-p0ixZ_+DR?MLV zo#+s;MiAjN>_wWa>9BKNTY+t7r=g!Zh?ha*HDQZRGJKi4OPt*akq1A6rpbD+`Q;;5 zKs|j$=lTu)zI{W>v`eTZ`-0+DYSA(jsmNmk@9iRm~c4`jhvV~n}fWQ6>kRIcPo+2 zX@`L@sy5zn%XpmYAAsq>*h^2gv?iZWCG;VDZ8FO;G9BVnqL38$y}1Kjis>zW77QU| zAbzbd-hxv4=2h%|+QlUIfC7iRn3EkewY5U!ngVR5kcpf)hp$kLA--d@(;Oie6%^IG^nR3zrRW24C*xi`=M)vTCR` zc?4(d5N~eKrL;5%8u>2mFYp@gqS>;t)Mr*kaU_Bq86mbZv;(A1(*q3q>i&_KlQ)i7 zUPgvWa==9D0Z{UQNuxV$&kZ_-H}N;q>)sR8gplbf{O#o_c9W;;gvmU>=u6aEf2svO zWYw?Zygh2#$M1eX-tdGy^p*f}ZtmSoef7VZ;3$1Mt|dTWyK44XEDvgvj+Ad1@jjPf z`El%%Zd<#CxCVY(vapIjx*%^*S>qPcl5?aeq#$h_{1)`_gV4d^XI>ksS%zLh!>f?p z1Bc#8*H%57mIX<0i$;L*LnVHrT9a!T-RG-Z^3nEbim83r!Hx7|^SKc^n_uQmmPQV5 z5Q$V1F{3>Z)Gr%)1zFLt!F;#Y-7f2GBpweskTyA$ev1{MvvN&~zmL=aVRX0+a_V?= z7dLq?01{xGR&eEl%-`)fGL|JCnRba(n4YYDQ70+dk&2ocB)G3cFvJVE)CrR9daFBD zR^VFa9HT9+j z1!aTL_qVOmQvYz-q1f*$q0M8{Y6lKLvOX1BFo_O=R{$xsmhkOE^Z-Z4U`j?S+DfA4 z&<@`-ET}>kcz)YZCh!i=1^D}B$+sVYX#5W!SO}zPnM?X+mwigDGng9p?XFr*1db>t z>;RC{d^mg-QnHH(P?ijc+i#l1Kg=s4xR5(UkVF66j&Tid(ywru*XSWRN5phllZcgk z5qMf$lO4Fb*V3*@otFWo1ZO7j_U&BFveOrd@#n%tCo<0}1$=#yj@t|AfjFzk7u9D- zT{AbLG*`MDVqo<3n2NIUC;onw`hj~mQ}q1hunhLH+LtK4bJxzQ2FQM!Z+YH~CxnNB zvDt?gu)`3M4uj-6qR{)s(q8Z~ZLDw=gfyCUs9TCs$+2~sELuPT&ysyj-7ZcS8N`IX zO(x>rl0i3xUn z#uzx5-lr9drPA^d>^-~LhTV4-_)QKt&$O`ueIJbIZ3iAm17H^i+)cd@p0eu-b_M_4z;*CM2JL1A-LFc~tR=DFfsi95ZjZ5|I^^mtiUg0?7UIhEB zk_8j$_kAh?d4GQf#P8FpadIJByTxJdXJiO6Iee@)nY5XF&S5b%jK5oJq;G5~R}d!t zP>(@VQc_pf?uJlLE1e%4|5cdSt9m~gWqU%WDp8#Yb26^gaEP5V+ zkUjKAn)6V8W_Oh{tbPaUFYERu)a8YL0QDIRB&ID8?v>!CFjHCSq8V@svTlIbPqMp) zcRLUt15)I^=a?H0Xzw__BhUv*X?t{SeZ!_LV)EF*fZSGhLF0ir?@iG+WXrVJh_=IU zOgz%7#0v894FB)b96$b!)%QWVr?w8?owana%3b<;L?pfovDouI`|fA97#VWF?PIpl zF?myq@LpptM_lhgy!^{6RCJ=5ITKv%}LmjXGZYwPxpcL=(37n-(UyQYG@9&=(g zCqisqtK9$g1+na5Baxn(EZt&yzNyLe_kZW<$$aoi_)aq3GG&1m9 z!yD+06C7Qamz};D-L=Rcwi8^$r@~=LL5#+h)^IXTP$J^-5`#{=*{LMAbTgX+PX*z{ zB+t~GQsmO>Bh4o4`?I4xW8c5=&fC-T8mEF=@U>dCma6ITZyKMoKjOU%t0r8ILd)NG zb+;FmKLKs=mOcJbh`k%@d6Iu_zTroVcN3U-kt$s&qJy5?Sm__R9g*CF7WAC)JtL?$ z!z&T8aJ15;XA4Vzhz6T(a!hVB9Sa5TwzL!5Vy;-W88{W$mzh1?J;458sO9YA(7*Eh z&l&czP1PrMX%D|c)kH}bt#N^~ADL;yS=uTakR18^fMt4Y9dCYrLuA5r%wSqh8xNHv ztD-4a>S$T+*54Ua15*JCM+1;0wswFn%DnZ?a>@yHmvpI*rFr8?weEy50q5o_K)QXg zq-ppqH%=Q8`u;gf83te+{!vpC-QGf+*5jA=_+uyWSHKV2rtETGAETtA5t*HN{)LCE zNYND}xC~3I$X{qW!Wff9mmD3O9eutrf=qfPFdru@WdBMQo`v^}Yl^-wnGUOM#i zy`JarSz2cVe)xh+_3zPvzmS0nLB!m|-RD^3o>Xl4lXU2jjfhVL=pP>wn~qwOk4PtE zKGlnO&F@#KoehxAE=}xJ2mxk_O=(p#szz1hXxtlwsC4drRQZh^p8?3s4zv%T@5>MQ zZpb{!$L{ZNu9w;S4|8t-7mL)f=c)nir+U7dhzR|nah^?eSb}`%9+l1VeMaF7TAZEk z(p9pepd*){N-hu)vSLZ@u;*eMc*+2FT}I=!46at5rPhOeBHsRUy0!fUL09FPTs0IS zXcd3e#5PtI|809J5}dxCKztKCmU;S*V)j5T3Z7D82zj16M%L%x{sAP!FRz3kvZJ)HM!fk>5O#+ov1aR|gt zoIs%ZT+h2H(vGRy4v&48f38R8E7mwSRznk^h6>xukaln{%Z@}VN+8gtD{q7|Kwg&IFTzJ4Fu`S<9urN^iu*(j-gSj`IV)q$ z!u)FlFLFD&Jec*2z1~RE4hoe!MfDm=V);Jgl#QXz?mxhKi=q`VUBv`!&%x85V2SJpF|G@w^6EkzdUIe&F*I+w*7^wrFRL*?ZT zs>sB!UriCqy8S}Pt#sX=fYhd~6}H=`y`y0Gf%MWW0S?#v(n0$|3W#1pi~bzptWa462+Fv@=>xJQn(#gMwGGOWL}34b0px89?piR-6Q4s|F+gM6S?Z^ zc+`DI-!gz1yM{qsO z-P+5-WFx40^Alz<+f1=xjZXk_IB)y2tEx?HZNXv3$VX&hw-wmS|HfA%=i<}RDu^8o zbD6nTv|G?$s0jBRsDPCpA2-IgaHeVf+N#Kw2k};X^$sj{Zktj8c24GeL8ZR}KeY!^ z#)@LNi|C&cOUL1z`42%z>NVa$Me3=i+pGBMDS*1LiaWHI{YKs$w^4I0 zP~WF3(SHeCE1`kBA1hF&d&= zHr7&3ee5sy+5Q37|2zg@TMUo}i`YCx3oin<8A3RERKZ`#HX-uf5D?k?YCJ~xl>4G5 zBJ<&I>N9DwO6&CzbtUM(-m zIusbWDu%iDqwqSX7xN}E_H=EWbNav(_Rax5{HzdK56cg-hPy~cX~%(v=_((H+Uo*9 zIMm*m4texK^<6b*8P<{0s+f=g(Q?pASJ*bI61jT{+okMnYdGzVtc^O`2RjQOqhnCBlhn0kL`WIR7;p@7B+`~v zEy6DSqYloz40W-hJp;ha`ORV4L5)nNG}AP7b>X{B)dpmf8joI`&VI9LP}_2;#um=7 z8fT*A^W=EP23loA;ZXCPh|3x|&h6YVn+hKZ>xawEvG3BcH~T82E6_(jN>o~h31`#* z?#)_Y%n7cj(NLtCk`B?FUjxcpMzV?rsrW_=7@Wc#+L$ITXo>nij?Vp&$@l-`JFsD6 z<}e$w4LO9&S&_|Iy~`<;bTEe`DTgFVcEp_8L?sn-sB~VXQYmvjq*_vRbO;GK%X#5NiQ6!7lv$P&XC#^NqJJf|KFv+g;)v{Ntf3D{Zqa=uVYK zBK@W*NQ#*yixkp$W#wU1`n4dr7uUfF+eLDcse4;*ZLNqu+sCt%z+A6x^z4KOMZ<;% zGEd+2r_~*Mxkqm=%Qx-5&Z$Q(JLTu?BI8UZ+?hG(0!a9e%ClCTJDTi*=TKvR(t)_+ zINfd^BQj4<3HX&w5B!qZ&jhAYm>bf<+Zc$NF#gmkufPJ#EHpq&7{}mP~3auqcm4xFuBV2v_Z)!jGSj|M>uSb_QOrQ^F)iLh` zoLL>W;N%pT!abB|Zv+6gxPHJOQpa^CeD73-vfDvr-VON2?FEjRK_sU4i6$dmiRA~M zt0!P$coYqV1yqSu{E{spf(z_xlI)k?`(%GQE-ab!%ccpRLmD%yfQQTL$h?9qx#vsN z)20KTnS|8VceG3E@%xnDMrO)1pPd?na@gnyK<#7*={7Y)%PO|HlQF0qN~e?7KUmAy zq>-es;oWmPkIoJmt*z&DLOaRlpX&#abxrH1hRp^Iz-CVuoO`vdP3gNS*ZSx7%(pVH za&|%Q4Y1Wpl>Z=V+DCq4csmyV!mq*PzD6S3Vt8*Sg{dSxxM{G3aB!XPyY#Cvi;744 zSXsw?pUY3^u@ytZA!Y%oYyWKEHmpiY=dQv3@p>s}=;^DlR`!zyu9*u@DRGFDrCx z)q&v38?26u%?ifa((>o3^-X0;m22;bjp1ay(}Ci*;aqb>3IMeYdC#-D2Szdd!%z5i zqV(FCbuan8k4q6GbA2wpj)yC6Y*dGTf<{Scc)p5mkIJS;c)jU&%Y08`BN_Y$ZzSwi zOQI&p=$OTTNW+@O+SK0)QH=4bD1Bq~_z^i27itWT(quPlm^!h(*G9f%`(1@6d>?zp zJJ3++eaP){U*jCYMQ881bv60e+Jg~OyF!!?R8Baz2csir@8rmB3g5!W(^#;e41iv- zi)NzML*aNANZZ56Ox2~iTEJ~l&iyUJpTn%Ct@xw~hK8`=w1bW2rbdXjT4*6Q2_ey? zR&N3P9PUxZrj-I<>T650$hX&f4xHyI9?AJu~&I*X+v`k`wa&^I1EcyIZxDmeeB@s@eHZdU_{$Dh-0eF{VkVOBToBO zK?_w}TU|E9T?YtGt2MGUyRYOq3skG{V^lbXv!TH}{R~>T6Y_8)1acaEPoa52CKf^w zFSnwnrsy=#Or##9BtHL!A#ri&N-G*cF<)E$bnkjaIYV!DSrRrerh=62mAS@}v+{D7 zFEw7?6dJfF(u{qWvOk}J&#nW&T3YMs(k!utH{&o>wWsk`*2r}UBRzN=Bf#}pP-<2h z@^bz% zOR>6d^1XS5z1z$TBXX5<;9Mu*Y{b6q;4yfaJl;&+K`VW-SMrzZZgh8c2GiygitsLN zw+T=rNW&a9@%xE2Ct8~oHepq&gcq^Fh(m5CtcrppFqi1%+SIiDZ(3oF7Z9HhEkh4< zpo06~wL%gN^{j)z5$;|(|5(VD&s$FphAZ6r6?XwSWvX~Q!Ac;{#MN&;A+cwhf976S z9YkztuHRO*y-n_#L327MDBtAv#E#(-ywZ}8!J9z{(v%KeA&uzDUJo*)JSt5#WZ)LwI|(}hH1LE!=keV(6P1kQ(UP34{1x$ z-Bh^U`;)%rG(y+D%XwktR3?7xVoA%f3#QKqdz(qNI$=zNC z?aG|sQ`uOfv$SA_&Fdg|+ z(N_bi+W~!I=e6}b{yxC}c4z7dG!iHL*3yylDpzSAev!DzUVbw!;hLR81D{Bpc857O zQgU3ev`e70mpkwEaGH3^k}k#w-snhHH`RgHiUQC?D_A!kt}S*x^Q?6F@8o2y{Q%~_ zaatP9@YGHfm%gLSA@xja*u7z<9a*k>Q;#X_6{0Y~ik6*g{1Sm5+_3$OpIhscW^$=> zoXcU-uqHk97<9dPtO^(id>XP$g(E5EYmk!L;IZ)nvH0bUhSwjQ(fj7QDY*S9>ALE+ z>}(F|JA%D1%^I#7-b1^7?rx4+!!N`4_)1xUhT6dE(5suDg7u;;kThb0k?@Qh%|jq+ zoa&ye_Sss0FxN%V*$Q=3eH+O=q=;VueQ6`UbNUP3cP^v{iiPz4RaA;#pA&xw1lK>N ztiNB8cfmZvme%?W!XIN4XykQ{b}F4Lg4B3~F3uy*y5PSgdWiP*-zMaJ)VOUz@G}U+ z<9!cDlr9Tiy#tB*6UMFj4w2^-UZb&l<@HQQNNnZb!X!06v94ow6%BO*hxLj)s+Z@; zi!}|cnWjEf_cOZe?dq;|%j!)lvqtkOwCK3`>xUp@51f$Cjy4!~;jep8ML8~A{W z=`6Kh!o8r1n6%UkIFpW zg;$ZF0_;MA>tz=7=m^XeeNoB6R3^jVv%41QaplQnB77ILQ5DFvn58xdp+u^)!TM@@ zvMPmg^PzK?VzWk{tHX~W>cDcz;rFFCZz#`b6gj?_srAZUrNsjwf6%y~o{o&H(wxJq zo+VQubjUS*Iie%?4_OW6H7X4?rRke1IClg7noEtvBG0TX=^f{c+OwraeO*eghZl$T zUY+@!I_a7h)@1R4_HjF82Tkx9sqah&LA{r>VvD62I~w-1viBg|>g0CI#={n~Qlr)7 z&u`jJr5S2Cw>$d&$T&*ge7!&I*u%jqEx~@d>M5Z9Z7djZ(62QjC%9Ki5dnUoH1jg- zC#>#Hw#GeYD>JWR>=AdpUxypd{poE*)zz_N;_4s7jC9MogknPMqM*$E|4~A@7M-vY zzH?Tgclxmx%QtGeMG?uDSJqf+x_6nlcwX!6t_UMNzC4K9vPYWy@8&wu2Fsm$7=cH>f>^J=~_ydz+}aU3Gh0a!Ps_T3Zq z9t2mcmGu7&Yh)V_;$Ko+00QxL%|;~CS2>q<-V@Wkr4`MvX1>+>4qmWSnhQjXIgPk%_jD_nE4%` zB`JhxxS>B%1vO9yLMC+msnYo)c<=`EmQ&yTe`Lh|fNuGr`jriP*GApmq! z+}TEXh4<#Mma*}%mX2rU(fe@&tn?9cXy}p zT;Ft>2iMY~yh$aho5^th1@)vus=Q&y*ErzA0g;aLLGskCY|06;UqdTI>%FX*0p!zu zp_z-YDOqTZywfXX`Us>Lr>&a$&FC%bQSr;fs#K1_Bp~r}y>HczvL+BHUm=u}Bi8X{ zYhdI3XD93|tM63gnS8<@YxAUiu!{!5Wcl^S$cD|p)Q}^(N7Jm^wA3 z^Y*sWkt3U`znGeCM*~3EGljkQf~UZ$`-@Thh9!-&aG9dLqUz~|ta{NP)rkmOHg z3m9svIsBvfSTq*nr!|>>7?tFl>L+y-k~2?ox_CDFRFbzH$U86;n6Zq~kJg1V)yokm zc1B7eGW?g3{=7^3IiPU~@nZ3^?t_NAhnQBe_>2wwK9EEzqG|kE^Bg_n{3T^v@XuKP zen^P?TrWd%00I!`^ZM0|uz1EA2*gkg-4&9wu%gu9E9>r&hCX|Eg&_SXhQqe?;+?*` zcKrY{AEo(f@BCI8n4**!AJAQ9%!#YZJ`&g?vRBx2E##C{d=iN2&#Wv0FNgBgVW@(4 z02B9;eL-3EPGuDD6XF!ONB}p7q4>6Q0RCqvNgtMvyr#sHNQo~hC#mK5hkVWEWW=#g5?9I0?GcG-Bq@7J}T-AioTY{gJNYwpH1F|g9dat5tj8A>kdQTPy)n^&70=F@nbl4Ua>N; z(zK846gJ1HXfOSV_HCk{>I9?UHsPbsfbMxC8wIC%QJZy&u-cu9Rd<- zUaCIaHIQ`P`ujJrDz!&2A-lrIZZURjACA~Y`7I&`c2!DRm1LE|l~yJm^KYa!xEZpR4O; z3IjP&hL)3du@Cz$nREGlh)qRlxoNC|bt<5v^Ds#UPw;||Y*M_GYP>ZLG1rwjYfTfm z1ad9PMpr4J22)rq6m$y=b@t&C8^5?Vk{xz+XCy1hxBiT%#9GBhu8qoiCw&eBs2Mg3~ zH&*!r>3}HQLwu+N{D-R2N1Jb}#-9}vE1bswv`AGJ`|>(D=rZl*2xQi1hGa-Bq4zt$Yn*pVV@z94CL4UA8}%W*Xm2lnK7hqH*Up%#CrRcmwe@}@tW zw=Gg@Q!QdO>7Q>k7UwKV4MOv9t;d9-2#qEAcN)OYZB`U{XYZTLB_x;>)TRreal!!~ zYD{@Lv2wdJ$gyP@msbs>p3N{7g{+|VMZ!@?x1SlAObun1w+)5b85=^^&Q;^!=XXoS z{5{h7wa4pzWZG=8&^1qA!raehh<bRR3X%nbkt7$YkuP+{R;0wL6Ja34-G z@E?!O@XEIV05UE?SUfdDymQ6Rosf5xDX6=z+ExwN_n;$npc`C^1uf0#`&UpO7Kmqe zWAj$UICgc<_hzM^YH;mEMDZx{BW#nqdQy~1?6i&5ToA3Ne&1kEWJ$BW68 zQ?2U5`-QThz74M#D+)0mA33j7^|@ncNKU6ry^e1d+-!igBohwlI9&M$eR*LL2u7?z zzFrKc9T-7$&H}_nr@5UB8cINV0iNcH@y4pEsu#Tg3|}M38#1I3=~(Y0-w@%bSH{l> zErUc+Bv513D#4x4gQi*FAJFWmpPo!Orxf?$dnR3IzgGoHXaM1^O*e?p{MKz_?UCqAgO$&`o zWa9S2-)t^Njj8xv(GbHZt-4OUw@z2kY<9@7Tkax_ZKWo_ipAOl!vMr;BG{Ku+ z$kbX31~L4e0d`%8rEfCjP!=_-@%;XeB^WdV&zuOCV*cJaQuhP8cdl71{>RVl*N8Pm zpWL3y>PLyB&>a`WZ~W)x(AM()#I=m7TEUwmfys*JVNcAY9D>CC1mK4QSRIf9muF>P z^kAw+FjbYx`buTa`8LA%;DbSV{nGrGXi@%d!1b-nCvW;G%4&vrYkH0rYq>(~o@11a zARTw_!U)7^(_m5L5NBYT82iCAoJF#N&zx)#=xI9tT*L6qd)SVRCr^Vts%|BfD@P@7 z;DI&l?@T9exub{c=Sbf&<23utJ3h+gWpwp0ZyH;Yu5amBO>g}#_K?>Xb$?i>LBL#W z1oH+VDT($ZWyPDW0=ClST)Yo87O3{Aa|Z_jz;D@G`9fqmIr$$|$<}YWh3BJwV=(_F zpSJ^t?#;X!e&!!6zNqxcb5*#$Hy&^QWz$10wCIzlk~8Mg`dB0iJ7sA7O)uv7bUZ4A z6b>rlR3N?hGcE@PWVHO!01sqhM6j@99E0*`SO*f@V(KBnw; z)1U>~-`6a!K>|i04tC%BG!B1*3^orH>vS(}>6RwTyRMHxA9QccmP$qBuZuCYs>de* zVynpAI0lawAETNo=@yjxZ9Ao{P57Ok{h&g%X~-kq&;u2*g*<6sJ{u^8rkXcbY^zSB4u?( zK1wfy0l2)hnZT5CHpC9w@MOZB$x3H3b3h_M-20Ui@$r^uJKA;;DHx8{$>27_Q(9$O zGt7qb&lk{>q%iA$irII8zPHg-iIO+XR2nApERJ^UFjz3@a*`EKLOvO{ z|AO()ZMe7ll0KEGMawC9T+g{T(7dl+PydVH!G5}U=Z{}c;5$_Ab+$|t0O&z$ow~Y= z5K?@P7>3_$1G^N;^%-VzmEjt`dzhd4gV1u8v(#-3*h8DN^mP5d?8O@LmmPWTdKAPL7JtqB1`Dt2%OVEeZxr9Zm`5LWJr_E)_Xy1lWci5_t%+oe z40I^Cmi70lN0vjRHq+FzWKfF9gf-#`GaW{7y&$W3YClv%6Wsl7rD*N*`qhOwPx}a& zF&^)tc3E@A<+kV2vHIC0@Mtit=WUrF|D%MO&Tu?X`Ur7)*{Ej^I(*IZ6Xvnb-Cxvz z^#Kl9+D5i{9Ud1rFPPkqkh(vp<8t-Z)%!9p!qeLs(I^H9u?q0d`bijrCndHyIMzoS4OvugK`HzOME`~uBY$FZ`r1~BCFEpG z!Kt(gEQe-3krDw4!)48wGT+cujqcwecafhx5Eq^`Zci**T%*<#0SgrzJifK8HFW>5 zoR!*tny@2on>u7BAl%&6?pL}c%gC3*+7q6_kZ8%rdwKVkGZS8!&U_jXnSA^5g?7`i z&ikTU*D>DF46GCEi|jdFuq<)Ng*Yk~-Tf)_no-6RhrApqA4ksdI*SREW8Gt6y+%v7 z%Im3EXsn}ccL6KOe@_S!1Is)Wc10S5hP%AV%Ff8X0KJGPMRzgT#06eZ`eV^U-RG*< zh1$!)0sBs+ifHi#Um%RHA05%38Q>8i)S_jo*=DxO`JwrHv_I1yYgQHjJoW?wB)Y;Q@ ze&Aqemw$In$t0D|Jzt;+UO!u2#h|x$2$nI=J%LH0{*DHXzpSXuBV~ToD6GReKU=!g zbMrmqD0{X9ulD7Da?ot@Dg zm4L4-T^FBkh!WivuF)m&5QO4Z&HT{@FtDiPGjCFS>*Y_DT16>KWp9*g*2W?bR6!DH zYroc2t6b=AcV^a-Lknp40rNVkD;MiJ_hdQeJ8MM$yj9*^dJ;6vJ%EH;F95+|$Owy{#Kn@h!nR zhO81_M9u(=#WJd(T zAWNE8iT6^|pQzDJhZv$ogg{IKy$#&jPK(@R+m53J)t>q% zk_s*Q%=h8ryj)i^2TVl$M2TUnWHiZEyZdjQx2X()of<_(A~mF|OT>#VBIEMA<8J&j zT*XKoPSA-tnZafV$bP8y_l}-8+&H;D;mDCA$!JB87~6`?`b6{S8#umS^$*u2{etY1 zV|bkcp5;@Sj{x#?nVKIt*Ym@Tzi;|e#Q_K`E4$oik$($g%6+3Im;oe~+P4u`UJ8%> zzik2OQ*0%E!v(yqH!ucM6*>e!Uwp}h3xtz4WDj)zk#Y7Xm(v8w>787iBI!$nlz} zzlSkukQ;v^J=}CY5gZZAZ``mZ9WsYMJ<5#x^5w)cSakP;ZW#KzQ1$SKXx!R^c3*lS z-|mDMx7hFBXeK-TUg=g_?E0_ocs2EF+b*({TVH={r|c>%3bAL})R_><_|N<2+K;AV z&}9-^)WxeZndTz{+L9+lJ+q|xMPTG)JHxRQ#PGzLNC6@vn!c@kX_(sI!!@egzQAX8 z|9G>ljcx&nG73OZiPVM+A7b1cPCK*N{Bo&bV%g>~s?;%Kr{>Gw5*Ns)1A$fIHNHtD zWlq>+8>rLZiS{X`h6wTs$jZ>lp>=Op)%Yss z8H&F8i2Z5>K7Si8$2dE!@vVxsf;*R54(%zkJYzIHK4I!$p3oB*d@L~^@_zTN_kzb!g*v~F7`Yvn&M1k2i`l*e>K=o#+Q9J8pbm`4^ ztDfzBJ*x<<*t!YFN+SUbqtZVGe{?0VP!bc=+@&u+9?sGDY7u&%gxhpE2i@na?y=oC zfNX@>vF?T~cXQ#G^3HU*1@hwo;5O$OYN7m4!@9H=c%@LojuN@< z(rns2=CM1hZRHs@dY=c;{?|+I<_b73#;D(Yt4dD^Wva37d1kLkiMpCg;N<7pPjoA4 z&9`Q)q=(m%0MhR}A$s6SBT^y=gonV3bI_Ggq@o3)=Ll2d{*Q2)!s*KC#a}wZ2nkK& z#Zv615hmy)uKp9Kiwl`$MBY26$s;B6q;>dkSN;#on1->e38aR zeltyey=lDMGg6v@wNKc)3?_m}+AM0fkR)!~=BpeRst;Eo9fFb`IYCpq#@-eNiWKn{ z%23~5|65&C;q%Z<5mHY#v%>YJM(KkTeO1i8Br$ zAIZy2gTH<3tLkfv=(u*iaY^omf{R{$VMvEp{AG`#bW+=PL=a@^$t#c&((?M4$760@ z|L>TQOnD<`=-V;MC;G;yz`9)!LeKpNhiF^RL}s$Q9t_xMyv;dvigvAp5%@WQ{C&si zWyryAay3O9tXZ`3o=+C_V@J1gh-#jsYIs(Hjd`oM*WCFKG3X#Pe(!4z;w<@Cg%5R- z{WtyAa!2eX)+Kj>CeD6_;Dvv?v9LC<=_l#*J+#+$kq%<25$ciYS{;$;s#US z-_qGL>9yjWFAA9`{%c^ZUaaJ32CI^jA2v%=vMr!AB=kcQ{UuP)n_I5jjtOOYW2tIi|QM)|p3cc!Hl zLVG1_ffrW(%5C_y%((@CF))j>y$*c1f1g{FzL}u#fmb8I?1r+#DTdx4XtR;tFJ?w; zd{hifeOQlJY}ATcq}5-NJp_l)x#b1;4t>9dbX2rj;OO>gk|dtgDVj$TT?xHqi%rScBR!5#-TQ(s+H~YQ~T5z^jlMxhaKM`ex~S-ncRSHSD6v$Pu{&7lR}(!7uQ;_={-Nh8;yAV5sA)FbkhT!{SC^$hA)ZLR2$K~KIX;cl?@S2@Ey?8 z!y)+1kaCvntrMc$w;^K|^-aPhXz+uXNn+@?eIo0B#8dVIUg>?Wl0+|*E43{3nO?KX zIIf%7fB>=l;SHguny_Enf0*5l*bVB4I1hw7jw!dLU*{7>LHxd%6>>Lq6?r^b{LEf? zm+EZ}E$;F0Af>GH42CGCIRx^+lRHw9Ak%pXVkWZ+01o!wTn7kNYr2=t1S#>F@}BXb zc6%Wo(SuP35Q|%rNb{5}pyi;ub?tB;qBshr@_T3?tgnASwzzRB2O2;WcX8&yw@i<4 zis7ebNCEgzk!*+j-lF4li$4RY`$ z`e2`YP!+6EXmZLqrRNW$))|$|8u+g5_&<#?dXn`l|2rcg!`XTFW!9xD;Ed%GAKmB9 z7iYTo?vqJ8WL}oa)ZbnGN>YWwJOC)kkp-}&-q+5}-$NowtK!7%k`9@yy5$woN4dSF zH;HV+AIz{3Aa5>YM?p^Eu@#_aSgvovvk>MTk|RR5K(_AlWlT>`S*2t=O%t@}_jMxx zWbSm>@piVEQ)9k>=&fO2!2GPZ#^K-G^c7~Uw!nw0ER$n#m(_(UM+sV~Wwl(~qU zbCPgj!gO@h{?cNal=yA`8%FeXv~Ki=hPAf*jKIx|$RkXa8{~=iZbZDwn)%3nOh*B6 zvhzHm(ux5N6L|D~4s$ZP_o*~Rv>#~PQjKWQn0D8J+X!$>IW=)n!m zt!}LIJ-R8GY&cWjjHN3$XTu4xG8$ecrHqeek<%<(6RJPcJcUT_ zxF)N%sXgq;mWFc@j{cQ8Gu{j4^zb#k0C{ba6-M`S41T?g$6mZo_w*+QIdgM7&ke1F>bcAkEv zHfNnCv{wFf9hVL$_CTw z=JhVoyC|QFG_MCmgt@+yBHU5j*;$RjtW6SZBMIBJVTS5~{DWD37ah&fh$N@I>FwAq z+IKNiUX{16Zv$akk;4ukzg*`RNd6`hye)&GHXh$$lj18&S5R@8T6Zm{^`T6tUNqg! zAG2F_SGJB0J;W4+^!u*xd)4!DpWE&R=3NAst-MMHs}=C6cHJ%$GUP}k)6sF#Fwwo zX#1-TG+S}R2ZrMf@~unfX{Ii)p~Sg6jF8ft(}%R-_BnpPHI$ujxWNYX0pGLsVO;2y zHDx>Id7}RD4|^_%k4Z6yLIxG}Uqynvnh4i|@*+i)6W5QF>@gzV+<1nvDIzvGLjnyu z3(Uw`X$xSAM~xsuRE8As{%DUY$ZF$XLf!e&I{Jk*v7DWvi#sP{yiu3t)(O7fWs{a? z)cu-Oe#A6~X?`AKJgfwK$~>oUfz`z`pyunQkpbrv(b=ZqXi%i(>XOz1_p8s{{9|7C z#lJ~~+TRZ%3SQt6g1#{BhRhH>i#_pk<#1y!EkVY?bLy>pU~H{;wjEWkvE-i}}U zC`of;25KgxI+~ao8RD*J$MykM_>Q9N#vAU<>7Rv#H!raLKWL4OSuF^N_6)B_dbRp=ze1%igQNZ>z60?+eJsPJC<8k@MC?TJOv6Rr$37c zrjYDxNHe~>dhW8aEEwGFPh;asb$l{X2TCd`U>tppZqH?*J^fJH)nbKgK3Iqe+xm<| z_DJuJ5xlXOlaqOJ2j4%;c3hcEQ)w{o3%wa5b~lO^@9ZfoB*h`(e|0}70f}%>=bP25 zuwp!X^IsMrNk!v(HbA~9rWpiDIfjMgd~@DMy=vJ!A9eWGML+aUw?4SpSJvjdD_Tjq z>$^C;uVG^mq!m;`KXGQj(rpE%@=&zK0eMA(Q*m(?HNdKDrvYSLtjvGN$lUdF2~u1o zQYT7i!T|JQ?mItHEeIx%hfKU=jb5!umt7TO@t0j$t$3RFVR$Jw;Tm$4OWi%fMuU=q z@W=FVbI>QYkG&tGImg}6*f1_5yQ$-#4lb2@stcO^W&vUz zX7u3alPk0J$lbQC{yHWmGtF|}S^Rt5N*m4*$X_&qq+(T*t^=aYgn(3OMm6$kDm|I- zLjw(t<)=Z1tfFmx{<_30qMm=O@WpH|SnL@Rt3;~9YJ4&RX6nafuicO_)+hIKiZ#I| zfdv~UW*g*%oP`IzYFy-lR19V2S>(o}ctJgKfdA6`r|ZSg*Q;W2o!)lRhX!<-M3ld% zTm<@qni!&gL~0}Jvje*3htLq5kiq8YD4Yhi*k)QOOf-S4Xt7eTcB zY9H0qzu$Y!r?Vaw{Rg!deP+1iwEqZ6g+ zikZ1z8NgKVmv^n`BZnWIAjK4fxt%+mZi%Tdk=-KT5dJIFYwNyWsJI6`%4dT$IqwH> z?^sUf?^Au5V?DU4bz9B~>gszCDJRX1NVF*F8mA&3076c-GSYp-wmL@1%+dAdKv<YKsw0)EJYO8jJF@Y zT8W2g3_S9I~Dsn|er$p40Of8+qtuVYC2vtnw3Z2AurIb3Y2J=D-WzA8Y zz-u|36YNj!MqyuacuygZ?5hgXo@P?|K~?F8+yg$wtoQ@F&Av5}veXPYZThjaRu$m3c?5 zK$?62tU+lN(r-20w^70I6Bc)0_z=~JgO&|H#*`S>MkzE&f!5L);?Wgc8SLvpS5zY) z3dp=}&oo)%N5gJI0YWT9lw6r!pX|E>j8c-8Z-*6{iA?w*DMz;MjZBsjy*b{;1N?mt zF$=b!>C3&f)L18!m1=r1AZc7B22txeZAUiSd%ZhMXBJ@TVR-StO$9?yD}u+uk+(6%Q?s^WQTkY}*s8d==@ZkS=QTn)GyMxOk(!uClYCTKGtAVjpq2Y&+!$XwQS5OteG2ZvO?_L+L(K&mvufsb`&1PuAK??xYivdDk? z%U%WQhR@c|QZ8~V$iBM=T75=mEGwcw39Z*2r0<)t?$aOuf`zpyWu_!{GU}u=Nnby& zdx+Il*Ch_sJd{V&i@Hi)ft#j*pYWP$Ze{wd6?pG4^hxCT4|28t+iQwXubIbx4Ru>o zIoj@`MDZALF-u5`wejtBee1T@0~Ro=V149V*#Z^5?OvPfQMVFIA@vfxWo-7 zeYf^N+yxmw-h6s%ABD{_VjjW5PupoVrG(FuY|raQi{WQW^>8L)_&WN%9G(D{p;Pg+ z>0~)ENm=$wN<`IIKwoNvTkryB&{sP?2Vmy!@q$lP_A7jtTX^rO#_?lAMiYGtfYo`e zFUIIfZEjmmtt4@z9H9V@09TE zM&fp;T4V!1Q&znxgrCn(T!5aTlexQw2F0K>%^CvO8`-I4G;p~x{Sy(Z8HLue#=tcE zq;O$=pE6P9S+r^3=b5l4@B>rSAbTv{+V!K-uT-}8*RpL5Nj>g)W{6u%9|Ooo96Q&M zq=5PdpdH0cwnp8vmK1-(GFEeVR6_mRqSW%Mx8)-*dTsWeooZuQ=RI2F3(9X{gM#h( zVb6xCqaxYJPVAoi?1Hp-?k6^4ob2SP_C{DBi-kY$fA2Gpxb#?LWg$`sJ7^_cu<@75 zbidC*zc;5}M4m?!I?oR1YQV=`6b0F|{H@;~#Sp3wS^S0mYFA%k zY*%}UT`5f+u<74+9(_m7h*!mR5Mxzo?3VDwd8s+)t_XX+Ty&F3jd8;Vez^a1U`W;F z@)YoI4Mj+XsbF}Z+vpBvGPrKc$ZaBBgeOqmY>hx$L}(TegtxFTbWLgex%AR?K0zrOz&M`?oKw!d0f2cdYAyO|B9vJqzC_3 zHbOmD15?i^QIh$kHzSxj+*+0_Li3nGaN8+xvR|JnkkiF5lL72GQRM?3qVSCAlhS7X%GbN7Srab+<)S{Oc^K6*S2Sk~oFS z8o2Fr%|Bl^Rtze9ZA~+ygcv4~TCg)ua$8Yxz6M7^GzCBS>&xn{91{)z@|CjB(xp}) z2z)@o5lN|VT@1}k-)v z^_;xR^6xUP?-ht^siXxOZYA{X-Bzdq=qqX4hxU!JP?n*jQJ%RR@huW-hWO6YlX+!8 z;DAI)>eLLz%7Z-LV7xMH^<_=Krc-?405eC{oq#NznIcI z%*KE`RhS-h@BKVnC#`k4?g|?=2oFE5?}iDR=2-~3N-CM!wB{MVE}{cw7*%?+NE)`p5pj1h`@5e#>l<(M0d!K*m@Dn=Ss`N5T>CN8?<0B>-+0f%(^cwImI+L zS~tSVMI+f|0NLgJzhYhryh+g{*3T$1?w8Lt&YQ(=pD%9WaPBYV8mHi<>#-rkYEI>}Hko8A|w=`be14F05u`+zG zip>gF9!vEukcF8szNY2D2hjer8e{X3%BRHN&V!*_k&U>&ADT!^JA`_~5X38P$E%$) z_3HjqZ!k+n;mBH-C!A`Ug!&H@KEG|zg9Hl@@rE;@+j!HWWyqHw6`y2<^1J+To634n zvwG*}&ktCl-yd{htrT;vq1L~ko^{S~Ej8cYc=8c>yuc-)B%~3icf8hhSjP7xJ^L@v z`q#j;xfHc^Yb(X^ENg1=<8MBJ7HSj$e_L}3z@_-<#J@-nhyw`9*-Jv>e^h^Oq}D%T zSRTo=*7_$J4aX&1Y8n09|RgEOOq+tT~`Y-nFUHrN1bdSiTct0PoZ^rW08A@g18%s;aCx>5F{ip&2>nDMa)Pk-*UOu{J;u|++M8<{1^)uYs zAp6F>yfE)XO~)P2m&k9R5iZqf1XhQR&0pz8m+6*;A3B%_;tf_4r7eV)WcHkRzD4f&rcOOGrQNNZDZq_M{L zRrR#&>d4CUqMNh(=QZku=E2i8+eGW_c=&f*-h>A_O-7x0Hs`iNW=2Ek)%z~b&Otw# z?mvw+{OcTr_qc03NgeG$mW8wLcqGE~mc=GjVY#J<3ayQD4+&?TNm(y}hV)$FeYbei z7eK6;Hunza%Nrgp30=9f)+ifV_xe!d#NlcSif6r<82th8IR27aM0c2M#tZ+t&~2EUo?Z2iRA$Olni&$-DPJeI_I*ais?oBhrDU|{6GD{5`4~X&B|ZWXBu)DU zzjT-mwxAwKFk7ibe7|F>d^!8@mE`1Vaqbl$$G&KzFhL1}4=l>K?LI9BKL*({PK(>5 zmrj*D0AF1zm~_p%s5wD^1@ys}{yr|civ4O1^CX`Kx-!cy;lX=aW=>v8{$PMaZU;c1-JBuM)SZmYkph4EnFw-;6-G;3BwZpK3(2h2U(@AK+vpNkI=T7z0kk;{6`&8&XuKu~-jD%wV?9EQ^TplEE={%DTyXnSLsntO zb&XRB!joncUI_d~HQ-2d)c1{gN;c`959o#)V2Tg}^Ti7l!cctpFazNR60SX~o;gdC z)~2-Jrx#=c+3sIrae_$B?sWvHI&cgMhLU=4XsuMWn8(6-(PT=pd) zg_W%M*lW>q#64MQ_oGr~adCeQ<4x`Z>eXdHDOn<@b~n zNW|hVqpzYfm$98e&be`wmw`NY!ov{&W3JwJA7c4=!b$#Is;zfw8GDn2@DM&kW$gs; zu`gg?`BG1{3zTQkpIpgIQ+Hhjf*ZGTws&;s8!84S*9r}lT+Q|VkEC<)XYzml_+|&g z*ygx7Z4No)v>}I*%^^`jXO)<cV z>BbYyVpD!2_~LmYZ>O_l4sM@GzLBcaUSWhpB6H4ur$&*DI=J43U*J1HHT8ij@=qx` zr&JAKCvZdLm%*u-fa zVoe%vOe}-O{3sjbC1loRV4VBtaVbNNl}LrROSsXIrtDl3W7?1g-v>=Ey z_fnlE91d$Z8e;I~#+^-Bma_uL)`qLl-n63T%s7%mh)_$@&}VuEWlKN8Ji%btvL1{? zv5e!;7C`t3cug6e5YTKxAII6-+qnJy3e+Nd>Hp}@u){7@uWUj#Mzg+qd+%7z3$#RC zVl{U&?X^3V1&Q3IH&mnnviL~o+m(NlriOz+G~`h|upov!(`x#fQDk6D60uzK+?-qq zLuc{%qKmjTW3QB3!vRpO<~4b``KWbQsYUqLC%!a}BWFVZe>_zGB*T2=){PHr&*$*rascqj&HETTNX}5qroWeu9f3qT z_kSWJ3pEuD_i;XZ*%QpPcB`whY8~PY??pB}`US60ahIjVl7z>pHJd}_u@uV4q0O=u zwMzPPz%$i3-e+1Zu@Jt<4&&Q!Sl)CG}2`Q>WnGG%!L@cnG3IR}i@`CEGBd-b#J~ zeu!QX9(_~Ppe^QFD-0=8RLYPA%HjAx+Us-qzhnFKt>?~j8EdYIw2Hjk_844fV-E!A z9-ZL1$}TbYS z_8;)WWRPN*-n2I1^dr^-0CBHz#5%$}#zVytZk;2rdEs_dmcH6Y#HpB51>)0yhjSoG#a`O_ai_`%@IY6{kJd%CF*mcm#$j zc8^Qku%4>oqHtDVZs~D;9e{ccv>xZ46yozu-VMD@T|`ukP!A`&7f%swhq>xg-mWRd zvjDY^#C?O$H&Qr?7ki>#kxqIq0pZFaRc5NG1xQ*b<{Bc@bE~fI(c;@wkU_s6-U_M4 z-g}9!f(XuK@EZb6tz|}!*?!gwsgV?-^lH$qM?m=g)J>q+ZjTm4HNo_jD_8%2AYX6Y z(UhZk9 zDbie5G3A)Ox)j?0xlYWzPNJDsnfQ$!~e8SnRCzbTpp+`${I(s zM3AY-93Wt#lj2J_OW$n605J|s+H<;77 zUz3tf$fbYBrPM0iQaQcg5%kumHO;nde$t!@dn7y{^(345BAj>OU1iU+3w)dw0?D@D zF3*FBJ;c~j$fz1XD~xQ-o}k5-xf=K-N#w61TbnWiW8~H=OFuh`f9Q+vyzT!l3D95E zKIMhf*YAhe8FvTQBd>{BRuBW6@`GmnyO7tkw>u-m>u?JG8A4T^F|R!mcaV_)*fLJc zz_b<&9IRNH1osEt>9_VuDyZFI7Q6*5i2|GXTBxa)VyT(>u#tChcgi`{$BDli?(M|7 z7R=;3o@E&~yr!-Fh!0I6Y2W?ZqBYtS=dCF77|_ZKc@@gTX+U3&G%za>;4_8^F?_J| z$H))v(|dS=KCEdUJsd|f8k+nJs-c@$0WSfMJ#*|`WU}EwPzQa@Hs#DDby}=uuO8s{ zP?o0)nCS}O?P7xh``r7DLLry8IIp!Vq983L0F^t`;T@HKR9{zH#yaG4zI zinUxsbsmvQ7cm$10x2p`iKtq6qe~6^4!H0vjZ_f8W5%zOb?doa~src8g(=G4*)Kmpy zxGLh;C@B@!R)k-NMn|mMPw)mu;8h?V-2G}L``CnH4MFV*8uII?IjcWpMb$p-7F zL^-%~9{t&GqTp(%`;~s~!8I#?F>#a0@tO*Tx)=5jCM`>IL!E<V;|m-4ZgVEhcg_HJbbbT*YNU>siH6iD%0H=S+(q}e zNs|Tk2@v-ZdU}>ZyO9okoea5BR&HW6xW}7(o;546iOS5e+@b8Yv&;KzDPR1Fe+pi8 zY^kiG5;gFJz3jPVB1-MoVRU5e9Ik*+dxX_jWO_}EzKh@6R;hCB zBKoPp&OKgPLtkI!G4jr@{<~=DU$LQZ;5NiICxI5hb|?Zz8Haw!Ov^u^*RNvM%Zq7M z=fTs{DrvwMPW@jex&EvxDA!_qoQV=H}@e zudpZGZLi_py`Vk(+_Rec!a=1%`|Bt1RTWgv3{l?)`K#;K(w%irtJJ0U)`edMGUk~Wx1YL)_a@crELVOiOeWo$+PHYXbiMwvhtx+(0c7c zk08OoECUo4vMw6P*MT}V7vH4B?h0n$+IN8WYp-Bz1NZfgNh%xbWvjDy1|B7McYDTD2j8F_zWTo_ zHq73L&F?JvIDDarjnZHOyc!`PJ-SCJanE;z*5q|07dV)J)R|f`Z?J zAzOz3Qnw9X&+lGi{NOhfZjKuRXARWE=pfF(B7zG%@CkV$Cqs-l1Ut0G%(A%8!>nqVHeL zm{l0yvud~K-6HOAWod1u!wG-Lo+r#<_q%0zSLN9QA17QDFz^luO${3F@zsjbyLK#r zRw+n*(i{4Ig=w!NTlM%_w>r0aMD?AycpGn1da*1z!r;%{u>_;;mRu^LNH$t3fex@o7=4QCHHzJ6T5;nU8B! z|Li2gdIwv5bk5_3Y{q;nuIloXqgz+^7jGPN%if45V2>HqhReX>Ro^9&exD3L&7oUm z>AyDl%?D5_cPTq+{&2Nc5vMs7GkFh9Wt_gZDF>rFkh(f)d28%eTB<^2H<0Ll4LZ>v zv$2omps%T8N;tDmfwb*g4{~XnnxdlwPM72MD1(Z!cUa5@+&A7>(F1neIcKJp=M%rg{$*tGjL zZy^5vp+O?&SHD^pPr19=VE|M27tK461s<&DokTp`))?AF_nY0jNehXy!+EyIS%s6W zwZ?~y%YPm{5Fal4rHZ3?Cr4BcS$r1@^v zQDAt(CrrXdO3m_s!qI{2F)n##r&$lbMGA9_Yf)+HcZL3m^$M5D$p1w~vyYA=?m%pu zR=R{VvwieJ`S(h^)T#cH9`9@mR)ML7Y}y$8(GWEaQJg0Er&WqB%HFy$X1iYVuV(y* zAq9EC{#{#XrU((nPV`5&R++yJ3HIR_Cjo_9rn@wN@_gUqGwEIK)4ol&vb_t*McaEr z9xE8BSgWKF2b0OzAad>+{$JPH7QW@fR+=^KIA^$h0+_0d)~u8%xa;NGqtw%i!m%*i zM@V?w#$zek{$!khcleJ%BPo6YnYIpGJp>@rLtq`OF=q}8w*Q|9v~y<~v=~)=ZIZ7u z7y;$+XnrBY06Z(u+R@#Hgwgk0TIg}>aa}pN_?E5^D!~joc87QE!Zom$I*6q=JiCIt z{S2@puK@o1cPl^{^c7>-UvPaj@55PlN9a%m(|fNk>E#Ud@bL&59<@#>TPGm3Tb=%W zSc)njpM}Za@PM7LAAl&lW$&(Pp{XCm$s19!g?KQ_kr`x(Tx%CM>5v|XnIbuyG|OJW z$KBNRO03rmQ|)s}taV%GZtlqd>kdXnhv7yx+;DNmxvC9(B-`BhnOiYHh^QPL`UO7@ zf_DQr+A1I!fsnfgjumHJ%NiD_`n9f8G2a$W!n7OO>V@sC0H$atoS6%~fCXhp9UXA^Z1COHpKc zNNf5pbf4Q4t7MpLi0=(pcO7Zti&V zO}YiC5RtRXNj(jhUPu5Rn7@BW>+N#tVjGTOOrm%tMIrvEVEdMg{UNM_N^5vO&oa-i zz7f8uLe49i{kKYg>GAlZY(-r6r(m!8BRlb|O1$Ei4WL+onxCTb_;RqDo6=EYQja09 z&v+Rq)a`J0S49(nSE{|Ic>v3huB|=U~8kXpp>^^ zx(vFw$uEr$4wEO-=`vTQoY-ut4Vovb1e8;*^t2UKzV zEV*+b+|)JT)wd;iIV;KV3v;2=fTtU#MK0t1$Y-t0|uZoq6jq#mX#W|CmSr_fH|->_mLn^=XGODDAYkw#iB*P{U$*^cb~ zakII1R^xK=&q1MX`oJ-df6%9Gdy7~!rFEVUgx9IU=S1y0I=75%161fr8w4eAm#$wn z5uxDft$u2Mlh|F-hYHhGMAtIA@1>T|J`NNloisG=kgcw6-X#cnF~x#DH)NaGc}G;h z!2(p#KUk@*$TldhnH7O4(Ds~$>P+bj+>RFiUIC;l=_R@RC?LI!433)#a{ezonq=j^ z<9uhxhh}#lVX@od3}$rg+0k$4vG%Pdl8A1mbX^IVYMXMAOre>O2>I>f0F!AaT;E7~ z&z~b7{W6Ts3r-o>!Fz0MitHh+k!C}ao939is0F36dZtVyozaqRncB;1ItIS9m`Q;9 z#U!{A2Ha%u*oHNC(Wpnbskfr0%$C;xnAZ$_YU-vmODe_wNJ_C9_SmvxWryNeyP5Pe zGmVXaPo&S~f$uT;u|duQ=V(vAksR2#-Y7ysci15hdjdv=AscWiC$HiH^*JBjuF4u9 zM|Otlq;vIV6@wEIa}+0ap|WyNsG_1LPuDmH?*^MAnI!D}O_li6@V;bJ5;Y(5<8^kO zT4{-L5czsa8v6`-z2ji7uFHO(^Ij&@e8Zi*s_=Lp`wFIOtptz`r$UDw1Mm^zPDCk+ z_wulOr4{FDsm#y{5;ZcKim~7fw|w4mk^ibH`=6k4r=^mlA=0d%4c=18KD@7=*RD@b zsuqx*U6}fb;VxEb^!*@|;APAHPE~}InrJtX!X}DHdGK{%tus3Crckq+{Z(;m8M^9x zj3B(>40QZx)qzl@gY>&@QNkcjvb)iAqRo~N-Mv`Z=1jAg_wuR{-1YJmkUhC>n+)R7 z-rse01U8h=koU{-z6{EjG2~BThF=`i#c|a2u_xRJsB+B%8#Lb=j~2dRl!c{5?t#}a za+K>(SUYKQxm5sSn``41IdNuQ)sk#P_c!$Ja$ci0)Lw1W zpUA1w4<{iYbGEW*Qgi&4qi(rJy#GSXu`DF8qVVhG>dKskHW)^h+?}DGs;>hU^v%a{ zSu*BuBsO3v#|}a}ADLlX&_KJzhcDIQ3QB0ojPo&npmD$}EoAzjW11FvR*v~;kn<3F zT=1~*@XckS1$ye5Wy{!)*DH^F&=X(8M-v)z=mOM-#LXJ;Dbnp-tK8d!AbsvHxJ{oM z1=+Bec|uLoQ@PkU3}c{USM@5TF(g2KdRl7B(k$b@)ap$~d-sA#8Pp|1}SZd!)3jqeMF_ajFk;fX7wIL`eX%M0%|My@d&yE_B|SSj5w zvaPBh75|X+KH!EX=|jtCKjOcxR>fWJ|AsE5UyD$Dr1==di!r6Q6^{KdxPsW8yTPB; z{4U_imeCf%iaJf#E5L3Yzclr0M7KGsrr;f#XPbr#a!477Z2bt~Xf|?|TtP1KVBI;` zaZ@2E3XcpAUAT}yN7ZhHcIsReULXyE1g85bq66L;#P8~~G&e=Fg8|<6pQSCiHM@FVB~afiyAXsd3!&Z(t!M6&^%(9)@>~O0u(plz2Qj} zBu#m~HoKF?J=2{CXK;dM4Ha+~?#5lEPWlEwJNa+FSa;RXg&5Kaj23th^ypOpJ& zU2~kb)vfTx*vo799wW650JA-Jz%A8clV4{JeI4n}!@<{Nl07F7AV|Td(JYkpQ^hOe zW?-12{_!00>GJ*X$;}>LmW?2ta!uX# zIl~p0Qi54$MyO8TTcG=`oY5AEEIoaWS@m-JwzL_cB5*^D-q5`JCF&7nMDKlY!WnCY z;KaU$@7?$ufW-NZ4fV?Ll*@AV3Q`!MnuU-HYAi3ZcS(u z96>jU*VBF4#4O?(RH-d`NOZ-hlry;?Sv5rPh_f5U|_W6fkXH|7xKsTctDvmpc;m_QD-4~Rb+Tohv)_$^z@0_; z_Nm3sr)xW+tGlG&@k%P8_8pL57cj?6gcVrxIGT#-QeI3W%a{8MW-ugg5!-Nb9n5H4 z+{{D)f2~Z!hR~{HKgpqslHZwlQnLkRD{J|5MrNcJQXOM7SDoQ=tko1^5R%#nkEM`p zS3DG#ftc(^4su#RXqgo7-@ga31j?xJ1?K?WK4nmnwd=;3#+js9ZZ@aqs}vEk4avUZV*$eFO=8h{=1AxADq;`%}mZ)$-*XTjhF*A$(Q!imj z8XH{y8lE<;#y4?|F?WqZCmEg(CDhrX5YPQf05R^a>6cc3`wqXONLW<95FIf z!mN@*bqb~OXAj14)19+)NdNfO0#lQpD>CRObVGAfHYzY-5Lf)l^TB4^oU+{xief?= zv*RDEBQQ|s2j)^CVb5Gkc`edbb^*JT{(20D$5y|;w|$l-g5tCX!A-q#ScppoZ!;d& zWS=U8Buac&s0#4 zG>@kJg2bPvc5LD4&mwk6Dq+WttUyW|-ijJn3angqB#9vlrOhBk)%{ur*p9swxojYscKk}%0TW*SrdZe7aKg%!Q<9R!AbWI?DeDIG78{XyG zz58s{`S{V^JNXY+S2^GN4hJTcKl?B4c^-5amv|3z>2|0eXI_i9lIs0mpyD1R^6E%1 z)`%3>ocnw9Y*l{il!9uQ*C3yB>3XO+8#lzr_=xB2)ZV3fYo5Aa3*{pZt9%AOY1=Ui zp!-F*HmAyfr91(_%KyCVA3=2sW7z=h>6+HBa>}`zaR&5hpL2^7tx@^a1-3ozB0hr% z{B!D*syl$e?AOhw6`HXyKVb&Q|4n=(UE5@xX}+cIe2)5p>euDLddNc!FXuR(Q*Xl| zTtPYbUtJC-!MquYc398?8W?^c#5c6+5^bZo)>AXV+_d`DX5lPrmZQ%8!rc~kbB`me zd?!TVrN+8m;TfRkWEhG}y0;1t>$mY!&r55xo~?00FLu#NF9G;F)71R@v#(IRxS}&X6mmPHe%{LI6udH!!EjlwbMUhTTyJ>}SMBpCc z))>`jN$)Ir7mS~pFls#j3MZ1FuQY8{o?s&ybbbK_ZQ8d>fs9eh)mxRViS0OL$CjtNv8uV28t`7beCJ$)@Ymj7Jm@U5%& zRco(!GxCX#Cs+YF#nvh3ep18SVISXJ0ledoHr@E@CDrGTvW^YGj8F29Z2IT&uZhK1 zF%x-tA~$E;DF>vlZVv3EDT4C{(B%A+tP+ETtNyGC zg=w_>KzB=EMu*4cpKBS)MMBM2_8z1RZ(OIOE>G=wP#qQ_)+pvR?Cz@$&nZqDrRhe| z6^)W$H5whT&FxHvVRUqOxX||;4L8=lX(B$L5O2_=*Wni>l@Q$JT`Y&(K?*li1iR%Z zaNosDhF+7kWQ3O!?Z4qcjwE^Y!Xd4vznPhFJr4)_$Kl4;fVe9nWN>ARx9`JZ=;K7l zdowRpd1MAUM13p0dP{C_#&zOgXm%j>xgMy1WhQ>wc6E{dk@j`Ij63Qc)1VK#*6AKR zvAJ^>u(}+L3}C!zzZ<&l-`tVblLqzWdXI?0UL!gMyjj^MCwwf;oH!kMlAR*t39EMR0nxEg|qI>a>>4;j|&%XvQg(drn z@%>IE1m5rdvcUkY304hp3^b;od4^-1I;|JenKJ(Mh_u(FJa(=`C&3QUdVxPWrxSVE z-dBB?G|EqJU5RFO?V(u=4|ez3(oDH2nzpQW(CN8d6T&0cWCm79xe|r_3o}0*N4Zwr z=4>i68J2DlA%|Y~j?49wv}NS8X+633HTIWyaQSmCFVblyoV!W_!;C?pm5X2#zc?yF z81s%(vkjXAc+R%;54;!w_*?ge0 zQaALgE{K19?&2wv`6OVTxa@8a@$g0j;r=2RY_7E2;momhMN(tek0t>GI4b{wg1@x${=jKgTE(4xFdJdW%7y7rS z%nkAmF_zPCrDMF9s6Eya@MbDo%u81O#q0yA04`54rMoEc$Ola)&AvehEg5gZ0rRyN zlUFxc{^3*}iwSnG#+1yIK`B^NwT`vY5BD=t6-dFdq-OzB$IyPKved=0#i{JzY`+Wv zg)$g!V@Fs7ZPL^uMe_GyEbm@g{=e?(M^j{SwVR1XGHk}wqFwGa;Q7QYAGYu{do#*< zR;Z@p7v?8z(#eDmV~1lqdVzpmLYjf6sdD=}Y>xu=09!u9tR>^7O_#UVK-#U_Kt{ZB zWP`$EbI6~I6oX}*Fs(!=m^6Q_JVNc8E@EZl8$L#J)F=g8j>`C9#l22Tym&poL8Bdx z?(5tszM4bbARWcE+~BPclBGsUzr45+X2S^4Q%eXcz$FG5=r|fqBtLS$yEso}-yWmX zrCENGx9Uqbhw9`Rk!3etAU_!qLktd@qSj@X=v52x&j0$KCr;gh)b966SjMWboYeMb z$$-2XDW+1Xny=KsvDW4aE+5+fb$NbK?_1q6ESQnngyv6sM<2X;h^O$l2S3IeyKELFz zt$NB-gSA0)Pj{oZXB9r~7Ly*;%NDXudJ^Jl^g9q(yU^wvAJ38Q1&FYqz&g*~S~<4Y zT^DIs@1b>~g6pc9PIz;u4alEvXO1PpzZ~}hjZOOZKpYZ^Hj^K_hV?70M81aTe26AC zxWsZ4cuaD>euF9coItL%sNUhxxygUq4xYP_vON?`%*mfWAb^PKl@0?y|os;)EB{UorG;}T@VE9X(w zW%WHRHrPYTmE(UJ51_ZiXB2K-Ok4odcdTRWsa1$nirF`kk5b!SK;gF4=;KUR0^&n% zDALfXMovpiYSttTGrj})GdQtc)glWTEhJ5(mZW(fBjX~aS2bEQz_Yp{`-)5cjG2AU z>Sk?uPXS;jcyvOz{1n)?9TgxL~8$H<6pjubIe*~ z-*b-}m@gAk_PDD=ho*jal9(8`r_ZC()HW%p0wa#HjWf!~hI(x@uc)1M1H(Oxiq|(Z z4=u-YevyL=GgiEEj$wBu%PkL0bb!pg>ffII8RPax+5d?COJS^^+r3w_4qEN$0Twzp zJy#@lBKVyMaygKJ7k|z}+<{rCuUt5BAKA7ME~kGkL1yaegEg}yna+edVx9{0!r;!4 z7}zJ))2G{`);oO7IKuMLAEvW{VD~+}0?VIsjbq)^IS#=B`YQ@NJ2a3>J6nD1n{b@4 zf79BYA3J)XwVh!e&TV=(FZxzxc;*ApFI9-~18!;mz)I&sDDtbB7;;W% zdnn-hd`f_^RZI0Jr~`nS8Cm9G=UiZWf4{UCRhaS)$Up7Kxeys4{NYsFnIjNo;J}To zU1)C#yw7kM=~~8)tdf7Ortnn5jWk?}JD;n%jxICGZ4alZ=oRf0V{>T-;hf>!vw}!? zi9J#cPa(g><~l{< z`$+&rjM2xaK^w66I7_c^R*_G?pCR-);hkBu=e7;qkJ*8_spc3>s2W~D;cD{Gp)0uE z`j@CN#oG8u>p<{pk<0E2f#Gi8 zsc(_g2i^^c;d1X+nX(m=J1q!X%#%jW;HHavW)zU{by~8a8uU|;G7~#-BNX&>)H8y* z8pK>+XIx}qW$)euYFYMu=hpoHSmtQkeEDhZq_6KOstQ9l6&;IG!U?52D zPO(?#$UJKFYn;grU=Q;?1*sbToprTJ`N$E>>@YPcTe&BEZ*VXNTJRSe`Rh^ie1jYG zh~e~1gWubTh{U-iN}!+bu1iBU@8F>O(x^MriloE(xK&PzkkU@>hTrG2@CoHz%mtdM zsq`*A0Pj96X9OEl-%@bk(I1Z99>G%f8_&Gq zXCJb#1YMKm%=1%{oKe`N6a=1qZ^8B$pi|uE1+#CLT$pTmnHYW?*JlKOFX0O~X7Z((eVHDI2X2gSQjmws zKL=V`Gb~jULb}_W1!{3JgKL6EXS8PrLJIB$jy>3Fe4YtlUmGGG(_kN>JSR_7Xqqy6 zO#P~#W7eB_ZXW`#*FFQdDP-_gNUlz+c_Ao8eea!9oQr5eowAX*zQLxAG`Wp5k(DeVLt_V_1zAT5;pT)!ZickNBavF}z+M1wDwk{pkJ z7~|REV(eZA_9T$ksTS~Z`>^JyibP~-|I+Ov`gfdevyQ63BGF9=y07{=n6(%+M!jgi zTmsu6U-4Ha+uXC;W8uqm8GAiz{}0{|?FA)2wm9(#&Ku#Y@`*88#Hk6uwm|~-q1Jv2%~r?S zx4!9~`VIg?*()+mOEf7Bj96ccMqc+!KZ29ge7!6TMcvyX_{@pj| z_4htNaPvD45(SAB!z>~qgs#;YQrL>Iz2F>fs1uT_xiYUVyn(;-N;-py8pJnsdY?0W zO(88kpRg1pq>m#78~ATi9WRrbNP$H#r%dGUK?9o~9wmjW^^i09&~k;HqYT)!jOEo0 zm6*(<);Y?hN4bkSr8~+O)z_#&jI`Tgfu4e|OmA0KX7c8je+Y}>^`oiBLHS|v;^gPO zNWaP{^IgBObpX0p#VvyrmYcViH8gU29-YG|GkAxLp?tY*lhL#j$VX-hM?~I}>m7nj z=iIKzbj(*-54$}TP23L=R5b+!YU`5ROt%=8om$lCcWsHj&f}w`Tb??ar3u3@nh|E9 zmnqi^^x*c%iwo-=mo~XXU2eKQO*Az0D)IvP#YfJYD!y0%x zD;=2?ea(EYg6w-radE}H;1%LLwVfv$JyedXym-l6S!sa0XhK!)2;QMT^a$`?3)~n; zM;$=c!rXrF)68Lww{2QS4&}sLXD8&loduI-4JkQ=@*k1bp8T+)reZHUEGDD3&h_Xz z*wam{u|r1D{**@b%fZMkv{!L99wVQ^vN|BwrsX#b<*9P|pG!lgmVe>GEU)|j(b;oP zVy=3`%S}W4P_xXR*Vzzil67iycH2=@`FKOwUw|{CYvYJ%y!|i)s|h9*b|lcI)xDK` z2bn9O=)%>!`{~fmpD61wW6DG}SVQFJc>s`W_BkIHQ9dR)7a-o+`Na~%GVLcRR^VAJ z=P2Lg57Is%Z`xSLl?|9SJohx zlp-nICf(y3;8S!khU5`<%XUH)s2*qESp~zxn{@7WGm*%Nc78CoN(Ot~4(TLY1{GO= z=0>G8TvD2S5Jbc)-0fwqgXbOO){wAUBWH*`7d(6yz)zF!Bs0Ph3^;7t$S++c>e~pL zwWrs~0R}rQ$o2FOg#dwW;h*n;alVi5(Y`BX>x`j|zO2b9HlcN}OOU%+5ev-661Ms; zfsm_ml7ENo_=??5<5=RW-!2f>5JX5{@~Xl*{F)%#t`SjE^cEpDL3_gv}XZF`7p)SR+6I?6p!wM3doCjEwv$md%6ny9Ze*G zzJq`%AGS|6Ph7dTJoFJz#YK=#7-(#KoRe~Z+n$aJKfT8KS$Kw#f~1dQ%^uY+KD{<0 zaAot+!#GvdaESj`iu*eU-$AW0$vPu_&cOV#s)nfkz6~WnE;#l($WL&)q5V*sl8iti z&5;ApqtLms#NST&eweesAB`X*hqC(DqDIJo?!0`h(@#tSTcvt&X4%yH+fY$*>aY`U zXT7Ux6GKo{W#8!d)&f6FKEYcfI5Yq8gn~eIHua=ve;HXT0H+fia55+;3G|1Z4`W^F z%=)7($=ptKQqYcqn{fQ7!I*LZEh=L+kKyFG>FDUjj|(70Gmc#i!2nKu^WekDej3 zn~&x$M9xSE7ToS)Ic&Ta&5qBZczia1Jt~1y2np7 zPYMc>s6hJ@&7dcAYV#2LN8L$~V%~siYo}s=#afm+o%3@99eljZLuS$5t)p#fBR8p(8f( zf3K-NBmTPMTIkQID`Z6R;H3M4k&(58r6s~I}VL{99(HtrBKcF$N;IAyk_ZyjJ7mv0Sw+rjxm zNV@KEIXnVS7J8c`JKm}|N2c4U&~67(S(Vav?f3SM$bNQuYDm4N~HBX7=5ve*-X{>Kyef5nr)rlW^jITRfy+@YVE>+dCX+Q^=m7 zH6U_N&mzuYWg(K?&HRXk-}8H04Qa;nMsoVkSLDY%j?YqrTi{&neq(E=r~K_{b&xEm zz5wU}EfHU2O}4TIxs9*zn^f*9+soSDvOnzPG(#Wkf}MtD$-(8t?jcSYtBS#%y5|?B zRjzknZ>zW;1NU!6DaY6fY7EnO+UjOSFtWsf)i^6Hz8DVi&VFC(#8(Pnooety!mV zTde$MUAthq1bQiit|T{vP;I>fNULWDK&LvAx~Kc#^h>uO}X`1V@>lqqXM)*887V8Kd|(PinYa@amR}P4y#kutD^ntMAnu-<1FXK>ls2(w zaSlE6XqS4@%n7iGt?bejQcowroz4`4^bqr|7QHUHF% zTp7#Xsm;ZD227)OT8HlgEfu(3e}JXsLa5azHG!P|XSC;;QL5&Z>P&-AOG}eF$ZmJd zV(i^z*+>F04XvNIYPud8s<64P6j0Mh9t%ysuT)LP9_Tm7*&I@|P$u?;9#X@WXY$=$ z6f>T31sli?zSw*Q<-w~E!tPWUEcG1r#LiPQFFFP} zr@3+=3+hN?PW1sOuIV_nKqWz`dI5U#d+K{zF6nr5_+ihFSvny{3j(7j4? zl&}YEcKnl8SC5W^6jg5cCjHLTV0Xt?=edmR-q%qpysy$3aO=oIVN&dw^@;w*KGe5&Px}DwxVWK@AlF; zW;wNY17f0cSuWG?24;+?;q(9z=A;tPsP==Uvzt1%3pzv5v@_hQ@d;Od}EoG`VV|lDE?F5m@c|(eImk z+HW$Z5RUr|8kFW_TYG2dGNrT`^oz1}acK%;>m`GmBc{?mb(Q4_+K(JA#c6y1!^siN ziVL$;iJWy(kKzm2Wj!at^y17pffb*P?cS{<{O(3~oo-9a`Ku8SBx-8ns2(4CyTb6m zT5^+)HB$XrX%=dw!~TIP((uq0TXXc5Mo;6N(qU?@MZf$90RrXYQ|8^|BzL{c=gQEA zcZUdkDRSE}#&or)apvPQD%xe3D4fiRwP81Hlzw>XUq*_9TPHWn?Bt<4mky>4VH#tR z&eDrs8QMdR9}2JFt1C^yn($SM*hNkC>s7}koHAKDA(bDmIO@o=?z07@>)%}{;}x_N zI>r)Y9zRuwj@bn~4poSMYBMj~QypjMm%B2pT+P^&wom;VK2gp^S^8!}%%Dn)rjmtP zkV=9`viSG3V*W?YN{by!aa!*|@BMt`dBMAg{^W`E-B!{Q9MVtuawlknwkIT^qVFNK z0}XaT5DDZ+!4c)q<8s*mAb;B6Eh5#|H*j@{n1nF@#}IZ*qGQUH6bAsb7?$uv((Un1 zr2xn~q!0xEx{3D~p#%&H@6EVH+E?1i=ZA;U<^0QQ;^p4t0ld`zc$ZWvW2b+AK7dRl zs_pNNlPbDR8%xgyNPR-Rt3K+46xPpe-xd2G}Hed$9J)fZOmL|bK8bo%4IHz$mUKLw{Dcn zhNMzaDwXWwe#?|frHoX*x=pF1V(v>sQBkUqB$PXI+voTBowNUU&d#>a`~7-7pN|Iu zq*nx8m8w>EW!}*FapIbEQ0Zm=J=EvSShU~7+4z0H`vz14!fYvmg5mT3$*+mj`)hR0 znJSh5Ws6ELVhr!z$TRv+6mNR(RBbPHr1g`bL}foTf(zw6@e= zYRu_+1>fVCG2+e8Y0NPG%;eT*?7E{z0O}hsdu*ArEbg7gwxeZEQvhfz{>#}@T$fl+ z(Z`T>^H2(1_v=LWQUiOdNr9Y;3T)0_^C1cE21FiI@3_caKGOA5ZcR?Uy)v8E@E4%B zD@Nvsrsb;qCVQ=$y!&&uZsl99t(qp4eR7d|{GYHCga4NN6g6|N2dS#Iq7YZ6H9NL@%%0H_|WGWQuOits#GyA0Lzb%w3 zFRxLzUaa?ZobHc(${LsCFv$c}Jqv@Bd#kuTvsqu#Q_T$Bj%?63@_Q9QBl;`i8S_d* zL$~Q-AI=l!W7RIoeRY)e;y9(fZt_74@J>nR68>;C{He`kxM{8>W!ll$mNDh1G~~+nVZ1aoZ!&jNFNJh%1P6m^@oOg8 z2|93JKR+FD31&v?8o54r2iwI4@ci$E?ABGORv@mD_N2j8E%D0$JJ25cRKvv4S#N?~ zuen9OPIP!NFGH(o&=-kJlI#?VmFm6j0{Ovd_}^Yp4K7-vVOV-YGGhHEkhcY@m17w= z)xym~eAmGAgDP+zh`$k44;nXR6qh!Uc#4>T(C#;NGg+P6%n@wN_zI}rJwHH)ui<3= zR&A{7OvDPB&xnWp&eV{%vX`F*@ZRaiqbY6cm!iLe*MEkK{EAWB6#1ZR#e32aYPxte zBQWJ`rr!>kXQ#SfBXIFDQueb_Iq|Pu>~XnWs`b3yzYTw2YR_45bmzN2C#@ZWOQxfT zm49tEaPRGj*pQrGrUq7h?9YfhJ~s8GhN&k7`F%~jnp!=rw93&QGBcFklF>J}3`-*R zODF&6!<+V%r5X)tGPj;f*%t2RCimvOSj<`0Wb!Mck>QrbWrsMV=<89$Xsq~cP`Q@B zSDc=QwMxMg?i-~S7%}1%LAv~C!uYo02v}hOigRzMCwP4!C!B^Hypptn-RQ_IX3c_d zPk&m53nx|WId~zp5){-Xtld0xkwNr(tWc55)E8csR^NlZx@5OQ<>yjZ;nVUtRO64j za(I;T-$Gl)Ln9BX6sRX$)qP!sec)}Pzk@qS&cGkybLUhmDauE1JIq?%G0LZMqVqeI zen7<;AM&G`^1YIHr*Kw-TU`QM+mlou-MoRYdY^gV9lJ*jp%W;BgfMv8?{WgWb@d}@ z_%HI!wcA(djy!4?Lc#z}X70JwESEO+P% zRg)_IYOj3vfwfh<#;D~=v-nWq{D8w6^ot`=^#ONSTO_?p2)3oq2;v3&n;F2x>=l|O zCO3a$uaL6vHO9$)&z60gAoP)04-2isX*>5W-1;WPY%D=*zL9K|yWh&aYiA`}-a>ig zYAqME26nkgVF7N(vZOIq&;KBJU5Dp~Di05SNUyOQp?`6+)Q2DY;`%p()1RuQDtTtM zb-i2BRZ>+op#pjNis<`do_}Z~Pci?Q@}fi`*15QfLR;a+P39?7647Oz=)iUWYLUhP zJ2Sq_S2q$KqN`jl4bX*!T|XV21MYJ`v8N5kM?S?A7Ri+CyTnYGk=ymj`Gf5`i^^QX zo-Wi?Fp*pFoCpq-9=_LEQ0V>bsuBTR9U46W$O`!;5AGe{jvd z<+>}rvEY6U|BDPa2y1K^l=skTYNyxLLYKe)AQtxZ5evE5P*!ReP+W}PXALjYfo%*? zf5GR4s4DKow#mJAQ6CEQV7^$@h~G$h)y^<$e6NAv`F>u-gh&*(qq{M|MF~Uyp&hY- zU5_SHLLMk>-TO&&FTI3%UL}fXKSlolQ%y*uhQq$gI0v^XoNCoViFeNpZqG=3t!0jq z0hm2a=k?!lr_g(Z3f;@gtvFt0w?~-D*k9G&(b1n*ime1k>{34+l2mGCT(5<0xX-2YA!0g$it^1mGZSX+%dEui*QmgL{GkN?@ij&{IZOmjn+9+6oGzfJ;S=FthX z@QF6&Ftuzl*(zT{u|WenC^ix|27r_;?AJyq|l)oO7A0Q3mVq3}t$bEQRwjRdx+K-nn%x?JqKbc<$*#Gdf_Z-ib0$JZ}Ufq||c``VMN%nJ(m- z+3k?}lAO0pk8liWB`))L&P5JQ1 zzytoiO~Kghl3~M+gF)Cls|(ulpXdIl4uR{9pp*i%Ast&Sq9+Tig z(Tcsf>M+?t?Yg6?d>y~B1$`7u?D1+&SJfa33${a0r!+xKW}pj46YP}ata$~QqzC+j zJ(zCUYS()~rGi+LzWyW2H;d+PIP!3(TLNQWSCw-$;9oFcMWUV$L6qL*u-2woQ()!8 z%tEvpA9m9*z279tEst3ZNyE+$I|Y&|_6*%xrM6gy<7_>!K}clPJJtHs7~_AQy~#zv z$`{2WRG#am-mTGv$tD>aO+)uF{%*4tB*^#K8eI1a&goZxoGS0)=|r~pcI7_;=NJAC ztAaqP@_FS`v<6fXEu8SC1jq~>S|lH^q=@5k0>Qs#&Zc%^1`HsHp~@i=P($vVinmpE z=CAcIFiKt=`LvoY#h-Mc=-Zwa^s+sILs%maBi++IjARcpy9#ElCvG=#gko{>bXOU@ z4XdyJB~jl-14y2TZ1Lkf*_)^00hBnF&-gXsG$*5vO*XT!5=I2)!8XSHKxbH2K0LhP zCcYK6Ew*dL6TL@Xt4ew?A8)=!A))1Js19uuqQH~mii zZBeYU13PVKgrYwaiIkUp!);f5#o2y{>JE3E9SO@a#eO%unX2Hx$)!$-Tz~;_Cek%o5O3j zFEg?MoAu70Ggj}4!+T9KPrr>PF|JdY*&i989>H`k}KqzB4 z`q)>_6;wXTNp`xP#)q8zYmx?v^Kv?utB33o@~?fNxd*CY7{0*Ip`j?L++L&QZOV2B z+F|xr6-R_&KPd3Kw7)s8Cj1N!1=jMAn@FUj<4z^U#?HHc>wT{HQG3fgz{4pO7l~g| zukF0~-L*0-KxHn)YiKOl8I8}D@t@XjMj^eLb9SAg+|>txgyB2=&i-3o=)^iY!X&X! zGlE>mpSKMSNL#ogRLO>5vp75R83*;h5w91-b|Ag4@|8S|4Coz@5cswxhZ)ZGS#Y)L3XYwxwKJVMXNRg z2g*sVKlK__zUu^EMINIF*{HQwh^&WDE6o6PVGDHH)S)~~{)-^>C<_u3N5P=}y>1!# z{Bt0+g3ee7%b;y)EVL zc3Vv*92X)&*h#0 zAuWGJ?D0PZECJ-sS;pN8OF>A;`M+hhY;!G9DjVfoM6v@##@Oe4Y2@b(TW@L3vu+Fs`)i#xJMuA{N@n`;nkEM!b z`-k^2iY}vdj3754OStz@5lgM@lfQrOZVFTu<}hJLYWK-dxy1mRB>F6}wxWrAauLOm z&GOm4d<(#GWf5`U<#Eh^f~Id16N0e-{Jy~-VPTa`W;=9u7(lKh9h1^;BOA50Pg7w9q0unWXSws6lnYgF0nR+*4WpJda`{ItN#C2^&ZL{}H{Y(Q2j?_{bQk zmFvKx6=jvG?Iakuw`C>+m7l%}HtOt(V%$9ww3qynEN--3HNFX{=2%Tt#I)+ry4i@mi`x$UgH<9okQ4~2ikAqw1#@7BJ7re_xE zQqD_V>zE*bi3boH_o3H2`u&`AXvbCa>8T5|SL z7X;@$?VU9|%Q-F>d-9;tE1=Mahg@&uFe*iTB1-fAm~^$+_m$4MqMUQ54UFcaz(_`2>|Lc%{6hGG=o0wurg8-!0|qe@_Le z-1D65i`fHOTw8^I%;X|iM)!;A3tAVDvmI&_6TWTxwl?`~;(yeCnoLbkNA;hWRZZsR zU?p@bSroU!s}K1aN$ky&dtlAjc8{OI3xQ(~)LH4F)djOhyLb%Aow}p+T5HiToKaKF z{WW~**zgZxng#JSvamKT`vqhYVBbHCgE~2z4hF7uFnwx8pc;gQU*qcWN=R!tcR7)) zwBRw$>$M&l&828>d4i^$?>@+X`%=nb+Ze2;GxYn>VCn$twI#7@j;6Ov`aZ^?(Rvzk zWqAQ@$qwiou}k2I2CZvgTW?ajugNPJ7#J1ZVR$~_JIu&$63$e#)Ea#cLVjTk-ui9xR3dxKJ`F2Bpfl<=b)eFp2v58^rPNqA-Cra>e^Tf-lf$PLDixqspoQfHDH`ix7 zvaKo460Om%km;Mq77cl1QFa3UlG;#}ryF%;dBHc03+n})Ou@-&<#r7kYEhK`!bILv z#iEcK!f?f79aHSG`7t)QTV!+{;7PX27#K1`byAccZ?EcihPSOK&MNU0yym*bW9i7u zh81e^xT#{02GZ|##w#iA7!Mau?Z%~y`aWW_Hd!KXKS7)?1-$+q_YkrfNr~^|?G^l| z>u8NeWn-KdO(mz3@y8>Y@+{bX*EnHo>KIZ+1n_;iQ`Fpv-avL7StWmv8~8mO&i^zO z#rZf3MoK2#zfYdDvODeEt=4tKFOl-x-Z`;w-(-?f6{|_$`7Vs^?|O_7d2&*km&b2jWTEmCgu~}|a zk7z~})N6d-%PuF8kz8HlZ&b4^*Mkm{;QQPYI@B&5fH{>#r~@h&3Gtg%hqr3jg|Ny! zKjH=~twgGJ`Z3OG4WV9N+=r7tEYquMFxOx5n;DxnN}gWxi(oXPRrPIt(l|Lh({6aG zgQ|Wh4!QwqoR+xWc%8!rI6UAy%FF{1ay%>JBEWY<6F5Sa^&ZLzfxFk;&dYUGf=g1-kfc+F5zb!cXVVWO~)3$ENCbQX|k2ovX9>)4*U~m`! zW>7C3lo4y-k=p1|+>X06E9P}*S`gZrT%r4?$Egbzf#f}Dr5%^u+ICqMA<}kZHpPST zR)xP{+eeBrNEUp8KW-JhU0uk!v5s9=)l*>4-%nY^VZ#f zcK%zQxx&4qdJHlD;|JfCH2tS4C#S3VO{|5r)e79a4a(ww14P*`1lfZnpG0lD`S$m< z`D3uYYKpV$_wT(0!u_n@X)|p2SC_3Z{n2soy;bsfXFY=EYgwmtOR$lxc_0BiSa4e#j=6kjq)UVF_;@VyOKK}V za66)()!W^k-kIR@B=sQF?3L>&d5wT?xJnrNS_()w&xF&`^P%T;F@Ju1b4{y&NtE3Rag_pjjxtTF%Y`#Q$XUvfQk2NYAn$^@-H*c~GJM z-6t}EnPzH#U<&Q(b=879ap`~ALq5c=5`lXZNECGQt}`A$w^0FqR~Q}-fH|dA&uvoi zz!Z7gdFX=>s8i4kz2Q=wvr+P@X9bEI<7bbsLRR^4Rgf z=*q0n$P$Mu;9g<#2ExaqUIQsAQN|Ut50;Kqk~WGtFgvHZ!z`t9QR_k-wT+_W9Oc@+ z*g3hVb$O}?DA!fL9KN4Xkcmxz>ccCFSy`&@60A&VeeW1(j+va?A3W>@G<28iE!2>Y zpf`Q@&=1Gtf4W@?T){;cYcOUn2)QhZ)?ZN8 zT6d;4-Rr`ICNPBL9*H)j^Jynk4iT=N_N9vh%SU?-ac(#LA1Vam zFjgxc>v#H6{~)aa>qPi`#|zHiBP4J0w3m6pb~9kVKwkMcnv%MUmc!#>pa)H_rOg(~ zA|6!uC#HEBS7X!)vE${(kwyPuw!_@z-Z^hi@9~#rKaN;i%NuGWm3w>X>e@a^(XsH6NH zuD4~4$>0o!Xl=!`B>bvzj9dh~@)5Bp_iInV zjU&+nYFu0@Dsq5i{JOqD$*i47_2*f`_GW>mx%miXqZjreN{#4sQvW~C z-b}9rpacrLu$?2y}t02Uz?*xSNAp_2o@;W9t{%e7Pyz0<;Ak6A4^ z%JJ$W*h&!gPx0&ZDsNkN4f>kMSn71NTU0A*CLEerk;!g65rq(q9%E zM!gG#$KZ=L8IQ31MDd*OC2pSk4Q@7Oy`)YULfyDkczZii&q@`yqUJK5WnW^XKRKme zjBb?=eKn``pDEBdiEn;j_rTCL8UAr~A9UMf8*OFTxJg8vf)<4Y*;B6v6Jvjw394z? z=6kBCn-BNy?8L^y^h(QjR|<+{M)$cRUOcGs($pu<($W%kod#Xz7hq3 zwkY#dmy0I+RNyta6Ah<{56M!P`EMD-$eUpl-Y_jUl5&GB>b@u^=RB2F<5h6!5~?;L zk1K*PdWUi@^E4WNeckKtveOTJg0lR3gBy_It9Af_3Y7-YO@!YUk+k^8Z0)0`wi zNQj0~>mU!)&I z*E?}y4b2zuEGl{LSTqIA! z9R3IBvc&qOwq?YB(R!6GfAAu(&u-x(2YNEs7*2cf)x@b$-qmo|pzmt3sazyey7W&6 z{+v&P@8c9zxfkhz8h7Mo=wniG=pem>xahWd=$VblUAC2Se$D@R;jS9fmV;mt2e9_j zp}CAg{icVIH*L^9Uni^3kMr=2ZDjV%O<{o@Dp*~32pgp58kZ+xF z&@0^hVS3E7WYZD&PQJkXoFK7PZsQu#i4_?)I$7rFM4H}EcC?`-xoQd#t!u4CZ+wpHT{Z?}0v{P0$T(ABqpw=lzO6<+79|vfz!%4sPfb5Y+uW#ciz@m|aGjAi-ccCze*SOrARlquKQhX0QthD1`HX9| zE7V2}$(z-T1Q64*Zt%|O>eKZn3>@DHWQ(}mx;&9g|Ja!gU6#(K^7|+;vZvRt5S8sg zn|cnQk65pw)d2DhzsR_e8>@*nxKayExvLq62PkLCtZrGD%Uw^8m3#b65Zkn~iJ@Y1 zGAJe+reJ6;@DFa!=w6oHI(3HS6X|v|N)KhYxuvO4j}gjAqme_)>u<=nk$cY}@rdGK z`JIp#dKv=`f!YmjT|A9(xnNe-zdL~3Mj5{>OZ!xL$%^EC2=a8$8Z~F>(>jX3U{{l) ze3P~hq1Vo`#|W^DP>Ql}eC^V~L)b|powZlVvy=5Y$M}ni)pLw3_`B*Qy*c-sW z*2B`T`^!%VlpRKfJ^>;vO-ckB>-XqzMqu*iLt@O5(8SGY3Kx>}`ty2Z@zYVPkSS+2 z8bwhni|!+pC8p0rBJ*Cqz&1g;4scBG=U}TKx$|?_Rov8%53oHW3&W(@G?hRbSoe>0 zBlQ`A#3qY0U}%(H=Nw@MD4gMzH!r!#HGx6yKZ?&kfoZBJ#X^#?{WSegW%AYeI4#~2 z-TFgj=Pz6l?5!MIM)dD+iNJeiVSgN^(%=wnH(+&5v0bU>0jeo7B@T<7q#-x!A;#G`LeCNROUX;P@&%&=OUx%eFEXYDpk1Lc z4NPL!p`N~i;9Q-*rCgQc{xY#SMw^*u2U=$ieAgd*1e}|ihr@d|fQ^k3TL!}%kik#K zW<%jC`ziR9{Y**_&S{WY0>gLdXir zA$QE;OIjAWlc_38d4!YsUTSx~O6`qj*O)bN9IwnEYMvBh-sbifY4_VD%Qk%Zx8b04 zVfDv4$^GR8+^ETph6WYUQ!W0qVpz#c`s$iwyKE=#H;C0)x)|o@mAR^zaO2<6ks-_b zMVBuo4=EA>4dD~i77I$Y^OAkO;m%^Z=eL2D*7P&49}4Y`{MNHjlKbz>S@@Y*#VXF? zykb00M?d-DI@6G>aLaMJ-PVtXl`sDIq3iOH2{$833eIMhq$AFlX?y8b(QsEVPu0(f z4sV~m*wpp0v6~vebMv__RLy1{@Ve;?)9x5KR|R;fn-nV849z@0ihUJa6uS--dMW-_ z%sN<-RyvdlUQENuw~ruAcq~CC>_Zy%QP`&D7ZTj!4o$B!oNLHZ&T#vIc*Bim^PS&B zv4HyY`42$C9PGKC^APY8d-&B7J0hqD^f87N?Zq_ZP1?1`P*~SQN;;aZ$`Jvj!jnOaHEOWtv8NND4`7S8wmycc24 zY6%3bczoxoMjf6sMvv4ZMB)t|m3o*ba+UN)X7B%C&IG+ks)C3M~g^*CH(}h`B0S+^EGz}7e(+9o@K;g_jJKG{+gPM==%7DvQk{nSv7#K zk&HPs@eB-Y!!_`FD~xO3fVj24IXA;wa^lx~>|7vcSm}OsaURb`0oKaJPI3Q%r*R$5 zCRE9_Z8@6AYn+KXFxDhXHUr0C@N0&oe8QU5^qX?%+6NlrSwPp<3oOi=*cA1fX`k59 zGN#)@aKR_F)LXj4Pt4x4M48s>qE5a)ld;NA#0B7*ax$tg3Lze*1FiCAaAG~?0z*s2 zFnVqIgg3q3ZIjr^FDWuAwdZTQb_^C||KxOq6Uxw!y-AS-S}>7R@)z5r=U^Ch(rYgs z{B>tL@Y|rVn_#BhvK2;%G4T7h5mNl-XvSmo5LLLE!(Uk$L&fAf?m6Q^$1l^v=hcB; zD{=g6wYy40ij<@+^cq)p=&T#Hc3ABaHB151@Sb5d)O;VkHC0x zEH=DjT})B=Ae;O57u{_ehcTF=c+k8BW*yy}`-%!X@x)61d?f=pd7uOk7RhAAT>L%q z2bVJ86*$294@&)JKcQ#$?e((!D-#L5DwXG!yo2|&yLnmxl_#6jPr^KFpy_eirh&eeV@p?4UKs4X;Vu|bBJTD}Ip z;h|Yn%P~EwLC8kG9{@;79Cz|4SdrU~)HR88 z(}6Fi9lJz(ypCC-SXQ#ndP)5Z(aBYnp|oYT8{(WzqYU6GQE~1THhIvuo24ckM#&?3 zEsgWgF)fHH*Dp8!Z&Rrmd}dSBSInSMK^1)4q|h$?Y2Uz~U-Z%##0yLS!PSPV;p_re zv*9Z4S|s00ru_QKE~}Q}6ej?$O>n-=1>J%vXyF;;4r{*`K&7FEnt%B@GTn6)CoUAR zqra-$S*17T9i{Vg($YS#Qyeqa7(@P~-?Aulw*wi=r7qPl{1I^+ho<$?g6YAsRK0?% z>SFAgpZ|Rh$vWxvmGp5p)&?=zXuwe*Jg(0Ge=U8a#@}@YeV9FR8QU6v;P^#MR!+^x zTyM8lV8^4&VpjAyOT@k4x3^WIU*{A!flPVPyfL>?)oT)6@@)`$40enOxNbwz&M~)S zX1wg&x=AH5#l*QR7jI8<^Qzh?l-OE2UZpOtFE%}G6KoT4ZcsBpy)B1~=b&roIkV{54 zj6^1sJ0z_*n`Sf@!~9&+;5`$fn-EcpP-J^aauRv%gxk7E%E|ZC14euBkBik729&%H z7V>^zN2^tb;iX$$1LQWo&Qsh{hkBSI4|iV51Wztp7-y8|cQv;|IKdVcnPLJmj8-G8 z)ANe2KzG89s9ckTznN)V7zeu9W~ z#Yw^fbAQl>%yr#tFR3h(Jmi_wmg1E}*yJwaLEVOSe>TVA3eEQuyaL3US41(!ylIr* zLBfB4bT3>!$l!!s73X2TsBeUWKsN=X0djDK0lL});u0lDSFc^nDVe8#DW!Tu!YSI3 z&jm;NWu2T_WBD?z?HW7O-cW|d*!VMolYnOy!Xwa1^o$|DsX%ZZ$m`+kcO&0xc!)X+ z28{P6@B)>k13w**1vGc`hJs06#h_#`JOQI!&0FWHu)m$QpRr!28BF{^EU}GVHqexp zu|@I7-FZcu^DEFXx)F?R?~T#X8n}IwGaawLF_h^Vo)ew@)NYhNg$AZITb8F~AkJs($+&pd5@kH9Zwa zRLXEAoEUn zGvL*FndMb`Bf{WYwMcbj(FBT<7JZ}mUW|r*td`d0| zh)Fm#Fp%dk)V<7DJ76RocyHLmwR?Ie*+|aymv?qjjZvYNMQ6ZAA9J73*j&*&rK?4- z;x?2T)U2@KN|4tZu0Y|2MVM1S^S9tYp8;vZ8PIzqZeL!tKEJ)uOS~d2D7`6b6>&OP z_a~l`LSMUVTI24ga~$7rZ=F!V)dLw97ZfdBjYBYkyH<2i81mLi(Y>*JVUjldI)bMN;(Ir`Enj#D^}DF$YFCZalKP9j@%b&kq-LR zInB>LDZE%&nNvJ0)O|Amu)NXNpmm9jaTQoUa3}$Qk;Fnt(9b*~?XSrE2YggxCC8Xu zwrePQ zm-D&!)=YQfL9g>GxJ^3a8snQ;h1#b2yxb_af{(@|wZ&P-438k^rbx)7m2VndRP`?7 zaS^2Etj4t&kt2VBbJwuJ&|1Bj+PHRsgMkk0j<#}XLkWR8E~vBFsP;ev>02Bd(@JBD zplA8TZ0JWB{3ZwDeIBTnabj#!Qb^O8{s8A*d7$9)IT^x2o>$ge7rpysGC`+OIK%A- z|EUsQT`%dJB!~6``@150-6)%q$6LN{mM)BGB=b`o;j(Ty|Lr#9akQ>LsO&Io(B?2Z z=Fb@|wD0x*CN1W|CX2Zv9!R(u#MH4~Aro3q$$xYf`zoH02gNBL!sjD&Y}D^_VkhvDLcPwa$u4ZofPDF(#+zpmxTU)132 z2F7XaK40OzOMtbWPa*3U=dThs$DNxvJ@Zv7V}k$cZCm}@Nsa1BPz0MlFkvwgep0aV zBaEM_$~WzlH^*EJvJ=$?#4eE^?0+lf_&igQ?N0T2Vd(^;Gqk8CN zpw$`h%=C&j)*FNu3`;(%-b%I9I=_u3Hp22AYNZ`o_T8N3hISl^OkQ_0)6e?oU#BwJ zG}}&VyaLF$=4jn^gL^eq>!>X(UCT|sF|72_%Wx*Mex#e{lh*Xz(^(0ufjigE6Z;ea znTq`Wf&^w$STM)u!D{-L+nOC`+b(kMX8(MhMT*vt?%9`dV`jr^*z+-vYmXw`2FD;S z`W7R}A5Ty;t3<1b@9oh~r$Y#NU zq%~?)#x(*~_L_|MkH{@&bIsx_Dbp?+w(h57DrW?wsK%{pIx$Gmn!GktOlSTr0kGuS zSFM2?+ge~joOaITcl@_O*z5K0Gd9Iqy1hs6$Dw9r@Nd!F7!Vy$e(p|Kv{B(P=eL&C z#lWqPE6nGX6!i$ezgJmT@0?(PEL_0z-QKUj2YI&m$FL38xxM$hwhI936&UVI{UxCF zz6P7|$PV?Eq24h3U1BRsFPmG=BU>7aMJ*&smb2;topsnX@)Xsyd3z`&6$<|&`F6H< zt{2E}&=}mMtU#YbKhSlaUuQku(+%`KwrDtq?LEGs-tY%Iv9?t+6kCOgJ`elbacOw> ze(4HgA)#ZpVbg&hMlZ>`_7SbGJq=L7W2lib6Q zBcGyJhBfzKkGYD~{|)`dneL7stR&yY!uz(QYzNiG{$3BA0;5&B@&;}jcs{*` zMq6VOR5~KSGVMju}3(~%Gi`rfa3RWwGA6MWU*MQ30+A%b%(r4TfZ_RkLcSB{$|_ z`IG)Z8+_`I%ySD?+{PxuiwHaxMj!raMkx*ke~5`<6uz_)9VAVyF-#b;6ooWqm?gVh%@btYT)xhc9^RObVKPYkL{6izNAYz*Y-NqUTwj5@hG%*!{oOO>4 z)L1NWQ@?zBzcOY(b+DR%ZkUF@OXUd)-ik#W(@urgGL3@>IQ)Vc&2aRLW6EY^#s>d8 z$}D&_(?PVE^!@|M#!Kef;k*Ux==ET%mZ`D7@!w6Mmm?!311_856wd90-ywk;t6S%2 z>%(emQ`<_)*0#^Wwgmtss#XbLtyr@nN2st1Spj#s3re_McAh>FXiCjVO-1<)IeaLU z_p><;b5I#McdWqK(cldrQOlr#B^~&8XZ%oo;Qdw5Pv!(H&FN3Z+lbvRW@O00N4{+3 zqxtsqT6XFZm?0l3v-2oT{@Zb=i=kF?#!J)p<6*-#?b+reY$WHf@32)(L=)%hqx z_-#ni5}A;k@#2|Ah}OeYF6!ZK+ABmzi2}Bvm`;WNU<<(BKLKFHiP$RVP&wvZZ;lJR zxAeLpM+z8x6X79V+%@rX)}XLyIQV8*4VInyD55a;>!Cs``c?9+QPlZ+mOw$IRHjx* zQ;RpF>BCEA70qr{O4X`H&U^j=Njr|Hjpy=)`m0Y9UM2kbTIY!kPdtMS<6vmc7i)?@aydX$ zzDs@_XZcgn=GpTY?4diqOUkKhLY~Zohn`;ijhatQp~M*yc9rT+;bwQ>n+A1zVx8%$ z*}2)*ji1!LW_Jh^#z>QLal$&>O$0~WLUlpxmohIg)SI4Ca-DW(CHAJYyHlK@w&BJDAQ zuy=KT!?|xN4^!&G!+Lyn}tc^3B+aR;5=acGv z0#U=>em>w_-Ui<+zi}-t29;o`KiP}*3QZ4O2FNx7qH_rABr>5+ZS4xkyekVE24a-0 z1)Cx#T^!51uU_qyBtbHh+jn1x+{gUI+{c8O7eLIAa;XS|5N8`_!cG@cXyw&FX7(4( z21CxHPbs$@1!TtIXkh^V4Fjp466NL;05_gT)lA~F|1sw%PrY`-f%FmhjU_|?ycBT# z$kot?A}nZy)+;E(2jD6VxfSu~=hosndW6r$(lFG@qWVxdA-I|3=y+tcOZ#bWnbDdi92VT7-uESLyvV^S#dS2^;^FehlLSkP~X2&={Oo5 z2_-j$+!r+)31|qjHuy5cnZ{}J?Q#hdZWc({l6EJ%roup?B;xYO_ozq@Z?tG7w2ZjPU;6#q0vSH)%ReoM=f3j0L~50H(%-=wL1Y6ZZ^*5sPK1-~C)*~D zrr4gOsKk^O6F0{S%o8G;T9vE}CbIG+E&N~6w531|Sf zR}|fXKecY)xT?d&W|FU(GS{t8f59OTJiXFtqtbUM_975*Ck2R>LDxcyD;BjD2{}O5 zihQ@yi9hTeP7Sf~S4zHSw|V0HXV<~~hq!y{WQz@)gX`T8##@;K?QiwoPA+yvj1QdG zMhEgzuB3y9*?-n>f(h~%WF$*6_B_uT6sk8+^zVyB>kPODu}axaR^JdekDB@vUD|PM zJS=+uzfN)nSLd^T>vsFoh4p`mQq?P!C+TNa(LLxrqVu~PK$*oc7YVzGsOi@^Q4C0a zegjzeHw;}VK;HeO>9B5t&mdftrARu%{7UhuE`G;`^Wn?%gA2bW!o(7M zeGNdbK=+SUzNNV34^0JbrX8W8okgOEc7vD)_Ry-<_hX`rOuJF%2p!-O=6C*n5cZw-q^h5A%sIzE96{>8 zdXH1(<(BAQZ_hYll=U53voNTbCM9hh|~Opecs)aF~ae|Rti0|7ZWV*-6m>U)O(3`bn z$C?ffhMA(EZ^NjJ7HK90_E@V_VaEbIQq28&tz14(vVsIw!~-g5Gc-|I-#%xuNzoP^ zWz`dm6mEvSjr8m1So~rvPkFj$5tQI>(&{u|| zC$um)EmNJ5bMsD$xQ`hT?g|JTy!1bc&ODIm|BvH4*v5vRto_ z(Rlt=VWH_zt}dtG81K`p=HULedi0qzBBv@qrK)0j{IuIGdE=;@_Z20)!()YvOaPSys?WB@Le%!Y>+b$A516-}1ER~%*dwNy5=5VZK)LBZbnH`Bffhlo z=}rKRaYvx_WZ??bEEfbKux`nIFULEW3GqaxgRt?0=V_c0;bW$%JVWz7Y@#$Ne=9j%_Q30<_(|;78_#(oKoihofFydN0%e znD29G^X>c%kvh480%*UN)D_tf@EqHl&?}(@;uhE)!p#74Q8JcHx{(Q@6Zss>N}xdbHALm2C_eMp%3V@jv>vjM(@ax!C23T_(Wc8kyycSWRz0X5^I z4p@=yvE{L^o{ISJQPFDra*Er3xi>``S+mPXy^(Muo=hLR!yX{$#?2X%61WuA^}G|? zbk$sI(Ze84nvN)fO5X+4Qe}$na0w;2D-2FHgO=UHnsBe|5xx(#ZF11{YTHZ2T%FEe zLUI!W%_*NGyeOpZLo6SxM8!Yi6)R95KKmfr`mgm%$>ObEP}QiWq|(ov-B=@P1Jnz1 zMt-`Ef$XU8e`L6SR3>hR?MS6iaquefo-Tt+axqR#k##hw$bsJRMwp36`?^U1%<0f5 z?_`ZCLW@Uj(s^dLHI2|MwCBehF)&HCkp(}cYL^1;Cm#*AGBTkTb8_+t#smrCGoh2w zmrY|u8p;Zx+Q;Mw$KARkxnmUDbw;1gtY}F6;g-If5rJ}@_v*^hsrDq@C>nKWdkq;% z{Xwr%e1>`=uujolXSje}S<3OaxL=(Y>p=`6E?}vbt|+oW z9zFIiZ*G|2>6tmqgFjdPEz?0FvoVI)f-c&9~{c_DC(8z_ihV63t!4n7Vc$*>) z-JB>r^%^-h#nlp4i6EfUPkE>XD;IQxuwLyZ->@-DOr8=bg?vvHBtXo9i2D^#eScyh7=u zUEE$%)z&m9P7vj)YBaLR!Z5-GU_T#I2o}Hcu&aC9Hjm3InluA^dnaS;VQRrAuAi$j zdIBuZVAytv7~7dxA3VgLkdTnJ>ClX?o)M%Gha5wyxl&%@?by~H zQs^38@{@jPosRyv;Y$7~$r>@Xoof9vXy-q?Jz~#ALRS%y1JAKAG((P@LmFKYIy5f+ z*(yWqY6ooB7;A8l6DeDyg%eNGQL)zhGXRnL<%HOT3@Hn}SR?ehJc6x3DRwF`hxN(x zozI6ksb75w*z~*L?nQ1=)=f{uOez8qC4k4Z?v}Nbg}-T`gIo?pYsisGH3L|CY@ED4 zy>$-L_QQ^YGmd{ZWEZ{70E>d|E8B0wF-4a1Q+~D*>T!joU6fa$ zb$2&M$wk=&LX|U2<#ld8bRWh@R*9Xitro`+Hl1Qd>@Ip3`bR)cFoF)I=3wL&qt3K> zV|KBmSF}2f{Tswb?PTn+lp6I{luVAJ;B6_o!&GrPzfsIcSa+US zwC?@`ex)@^#S{Bk8e`)3FZlq;xiwtFahslU&aFW02<)^9DeXZ1Wpmri3+m>y*Wz+J zwEQ9&cWyHbVg)v7l5&|DvMi&<#)LS_`#`3n#Us&a)KSOL6{Xk}eO*N`@}&hY6K|2% z$9UdeA-+D`n-c_PgbtCZGduu;!EiU$zCM178IC?Fn>n%ON*r!O{$t4k+YXBcl?=W_ zwe+KsLTnI89u$;hGmA&iQKLgW*}G^u)a-yhX&m}54ZXNbzz+EEw{nhOAL7R$JG!R% zJEN?)m_ch>vFL!?KJVf+?dx8?v?_-CM07$9Y689XxBNh+{s}N1Oj^0k8(;TBSJ57% zaqy6_bJDZR+v$}LrBsI+XG^DB7l04b=U% zjcMRKCLCduYEiT8_*c^&Q3%?;+r@Q_GTvXB@~_eY=jk;EgJoIoFIMqL z?caW3Q|7gKZ9=*a1W?UuEt|~9PEYR^l+Pm(asS|{E@zTSAU>jL?OH>`xQV16voXH7| zH^SSOPE#!)CkiR=t$*fAyqBnero1D%eQfPkEsUnU2af}e6l?^IRMFeXGuDr?63W#v zwmxMUl^EpD=-CB%mbH!4R`V=WL2m-v$uAt_G7mISLYRF@J)cP@d!7`ow9&6h!Q9_n zV#T`=psOlT3nTQAqlxpY2$0-;T74plS^w9(>SK>+Q@GUESoM(PyT}uY)OM@pi-<5C zfx}6;CE^}Ol<_qWPf5B3O)gKDK^u3{CbdzkuSxy3I}!(Mq*{oeUwO3_jWK$iE0oeA zwb${AiUZ@xvg_>Q%jkZyZ5zJEE;lb~We6!djaJEVK35*;<|m|Qt@`MbaCLTWYHCFk z^3G56o?oWBobg5Z6R7D^ccQbH>9^8HHA8!M7!C314 z&qC*kY8I^buv=o9tg8YCB@f$}LBM3_Qrrz_4T{C29y^48Yze3-ib?w^RKO@mMHO(@(p5x^Xukq$_8vP-Xb7313E#c01kYwiBSvMA zU`6&~`i|DKfqw-$Nd%48&Vd|cpg?M%Byn-o3f>EmtV(Mil0Am$ObNS?VC+Q zgRTGcx?@auFt^_Q>{ARXr~w*5pO#!CH5Kfu-hHbc{Hapy^QYxJb1;AtH-0xPKzS?*;$tiYipwt(RvAO$pmD^1M)jm|+w~DM6G}bw|v{ zEyFYs9;RuMlneUn`6Ue^#k^e{OtLg4{V+uPP1%hv?rllWe189yqH$*5=Ck$yQb)H{ zvkt1?^>gM%9@Waboh85jBhk|VAl|1Awn3XyD{9))(KSx?%ZMF|s{0&YF?uIbPm8R!M{~5aWj-lO~za3MfxeE2v>`(h0$46b}JfcaC-ysu3_#Sy(efs3np?@?@B;# zs|>CUn@MgK7#bS-pQ!4hn8qQV2&tG^E2R)FVn}Pv%tvkVe6F@oIZ^uKpqi-KFKR2F z{3Z1QMr%~$=ps>GG_D7!&HN8uS&TbX$gW5gHdIT~+WUymt0XLrJ+e~RP+G*1ta9u~ zlqZ>+k9i$PahhPP=NX^N{Ctl_wNHD-26MHSawotP|GG6uROTor8jgcwVGwifk*>E+ z^RJPVWJMwVQ;fdXN?$$#*8^3U8-K~yv%niwD$VN32witH8N2myUa28!f_(N@*89YY z`w}Hat|t5qg@&h66`-n>?Cu^m;TX)><+(JvukNuIaCa(*11Cj`xX*8YmqqjopJ3I) z^P7!aL>SzKCA1Mwl3h~spoGl~{2`H6fZ2|+3LPbewhT9aY=4acld8_LJub_K`QnSV zjB9KIlI_df!2%4`517%M9us$K1ej^Nbhle89aHs$QaW%E3&h#0hP=zsZa_)_yyjCe zIxbb4dzyRa5YHN1#_dOA6$UzNfNG&pU)=`)Zg*XZ;a{@IL*eXi0}@S=r#Wo{4u<`U zsBvZIph>27x+nivlQdjcUv6~eT?hj7pZ%YePJ3X&sb2T|Ibs3xX-V`C7fHYsKv4Y)2131-&!^1|gts)5N}3 zDFl8h6U}a1mIymEOTKcC^s;S(a}G4Jp!GP};-%oGaY?v-J{=*XWyK884zc>f_@rVI z_10=CMKj=MHl|+~$j{lz`!NO7N3?4&vB`QvHt*s+#o&7Xww6WXADKx_%ltc2!glEg zv0F9cJ_W0+(bpe>?R80ul~lip=U{qxb~~DxK@AK@StKNP{(+HW$i=j-BmzY=Olt%=i~EVi4+ys^_c| zqh_V=BahHkT)D>2`9Tc5BSIzO>%_?ifYvy=UGq|uXp&qK{&dN(mBaDdaP2;Z$Ae^- zI~x-F`(_n~SXKu8g;!}IjmO%+Mv~>4!Mv%i_qG&%r2Rul33=i2*U}TH$2SCg`|yFX z2M+*XL?kEk=Dc-1o$j|G>{)DLvj|ntoc90N++6+g#LW!vP~;La;S+RT+68acn(dUB zz^nsJK%XKJkv_1Zu8dzPt{K}oatp{q*$tVKn5 z&TUKj=XG$K_Y;vUy&v1bT|C1W-wBlNFTpj|$<~A^)sAcdbhq82H}_6VCM^RaD?)Bk zp?xkV?a)m;(TF`mE(nAXj_dh_ZhGPN-v3b9!vYhQIChlbE`W)()rDe*+joVkVus78 zRZ3XbvGdb(`-nb^A<;uwlPhQH@tD?JMyJ}5xpxB}3GH?}+~3L95(xD&Zfk7^DbE$o z@x_j}&~GoKO{gNcGR=nh0EWGA18^KgcvWTgAgfi-CqdoG^#C`pT_q6LeB;w?LGMocIADkjyd5;`L5~)@$bRX ztk&_v|NM^vD{VwXB=m`Fm(j9qR*VZpe%ltGH8-{%5aKwYdRA57?>YY; zsNA-OY)e!8x6>}fFx}eF$G$KmKlx5wJ~wd;EwDvgv%AL|66?zC%S4eT<{(>xNLX+C^kK6e}+vr!PFdZh?Ty&L`=8I zf8qZL*@wUbdH4RT5-)5g?NwR-_vr*8awIc?+^ZoJ)gTh7jn9LmRylxsg2Ave6+U(t z(bicT<@R5blK~99Wms+^e|W?>y?Gqbu4*|p7rf-_38=7H6sn_=hMZ%bxW z$(TriTBF9h=;q5sd4+={I*)Cs@RfzJns*k zCyG()$?&RAKXRPvl3|NV;HP+IsO#y$&4?RWLttJd`7Bnc3IR7=mZJ`&E|DJ5D*`Nj z8Okap<8Pf^vgQj`caq_OiMaDn5?W{03um9!+{o&XB`Num$H~@or?Y#V>iIU7=l>Al z!MBZ>3N6^^V=hyl59ib`^{+{sk*iO^qK)&v*2lECq_+-mH+Gv;qYk zEExA}bZ~mb^lGPdJ+`PZXfRwn+E5i5VtWFzJV%c4SGen)Tq{DEZkeG71VJ=^`!|xv zTCT)Oxe_8O0K{iL;3NoApqF|PTDo?g!-o7c4P?xkU<=*2nkRDLMsX@S?vlx&o9S26 zQtO`*e*PpUsTE<(Xkzq=WqQ@~{C;E78i7zO#C5RQh%;Kr2~m3RZC7rhD=wrRAEcCWbsfd0C0`NiF>U> z&kE?Y+ewvUfsE@OBTJ${K#34_B6_48p%7YXsO|D_8R<%A z&a%k94e1qAD(#KX!C_joeTIpOrYLLx1%LJzst4J-qFi4+rWE>q-T+~)*-LZMR{EqeVvVI}JCc&?#v{>o38~%9*i%MC1oy;3nx; zKY6`SnI~FqiafzUJeO-k{Q~HSoJNK^z?~N588=865)FQzI=@%q>gs& zS~5sdFdA$ovtngK7mPy}`pHwBNXKntG}@vk-|VmnY{ncvD5A&d=t(aLH6$7Its^fO zM%~olC7k+d$udGu%z_-g5RJf;#~%-7bBg`}{|LQNhG-w~}Y`9P!ER&5s<&so~b{9gf%6 zC46Uvj86y+rBgCg9#ebs0)P5WS)V$A=Bj#l?h(H6o@4{qL?i$UdhiHg40i}bD~xD; z$NFuTFy$EL<4J$p&-al!TdB1bf$2V{Me&`}a=MWn1&Y{1j#+Gb#_VQh>``rhxIX^B z5o^?|IgVZ0ZJy2#@a`Y@63okP`z>H{LH*p_KLH%Bq?>T4AKYAGr}%4Cyt=q$t}6?4 z@9o<}jDxdspn5soXy!nSX6q2Nv_(DZdy7?a=w{xBv?AfBYKf37^lX)IXK45iTfbWk zxK)0NPndwHJx@ubAtx`?`?3Y`D~LU-kQZQwE(g+aWd!G!Ghvz50uwAW`L8<(zvZX9 z@bBC_FA@2zWZ0szI6d_{eHJfUoc;C{s_NZ+sVDpGJ@a=`3(x)(F0Q17jl8`9Hv9G? zf843si^}#=zvxy(OZqwSz6;p^B4ztvl!~J@1|xrOfu&Bq!^t?*jbua0KiEyilk~r@ zG4Mx76cYV `F}dRH)h1prDa>RawjOGNb~rxL0MQHPcAcjBJdUQ_h~9hLRV$+AZS zmb8mxY`;tFLf6S*PaGFLX6-#+cC~~336!zHgr$>zUT!;lY==z=jR2U{|pPLq-0BJqJGbh@tcPD$T98ZR)?+OAvW0 z&DbB{tS;{3E!^nQz)vczK(Bgf7NIvM=}{{WF6nUMeR>!Y-^`RzxtTU$Z-2Fr8cQtt zTj3JKnf9;kxWtt*9JCRZOLqgboOp>8oW!#@skOs5q*N6 zJ|v4$Vd*q`pQ zvjpQ#RY3ITgMd52i1nha$9i?`t%0u`3Is0AwLB0|b+_SnhBop{*a8ziWlxX`O#K!Vm!W<)Qe0WIrEUYYc0;FAFL~vVc zdDoz3ZkR*wI@2P-sb>zR0?hvK?TelypKQriyfXAHBQ=Da=-=#f1KBV*`{VTuOpmQ? zTlrOss+~MoGjVPh%Y$N0S#QgjN>N(GUoT#liOV8RZCdiLLtG#FrNq9bw508drl=JV z8n8(>aaO4H8QFz4zB5m%L$1&rJw8W__WsTPZGcnBDq6qE(EP_=hka$YbZEA6I&_?Q zIiD?E4LSH+jw=9e^5%6;Ap?LKJY5NGB0BSa<_2Bc)3~iyk zE~evcM}!kb#!tGnt$%cN+-qd4(hZurLI)vl=EujS(uT zeg=MHRFuY36<^o(Wv>pC9glC7q$()>q$eiY*ZvTw;IGYRo-#^^zbF%-8(Jzh1xW?y zMzY6~W%rUUO4ZR|br~{2Mo>4U&}!v!bw<71O0A09Ys8x5DQB{3E9A(Rw!7j*bhqa? zRh$vb)eW{K`~`qGFYiNJ6q@Y;H%Q?AT|?v zkKz%W^xQPc=tolsmPo;?P&Igoi5ENO=ZI&w-)8vBqAfKW->nn>1Zo8CW2GkdV5)?f zBZg@Rv5939RC@jbGSEnN@pBMG)9Cq!d%9sCGr*1(N~M)! z=fgX0#3BP!6O^Pa83*PIqhD*Zz5M7aCr&x@*TJWp%UQn;H9MSk zMV6^a`Kt2EFfUw7B;w1c8HjT^*MbsKphq(5Z% zQ%GzR>PCcemBlNPMjDZpFVGEf$OL2AFI9F+md3KT;wu`p)+7-2K8|lh ztWJuDLHpYVXtHbz$r=b4vVo^btF-}ug+^`ZzTLdmFF;jQYA*oTxVj7bd_;RK=SB!Q zMKKmp6+P)*IknM*m_2{!S95znqQ13FCCyHs#yowW$O1cZ>_q)qtB~=u+F{S#LM@4c z^hWHWfjY6Rdt$D{?O8W~K1HUq$(;QruQqRbl=g$s-!3$R)ZdwO@UnFyN}c*kHi3!f zVMiV^sy=<@jCMk5h=ZMeG{1E*=My=h(W1T;B00@>^QZ$MKuF<9w$Li_%Ry0#nvpYc z^=$pgq>~Q7+(&~ad#GrRn|k5#ksvJm@*QJ3U8ToASmR%~7Y`O4@fRI+F?q*U!P$HI zTyNgk=?R_x@?FKK;%Aq0^>ld!^HJCSd!ksOi4>&iqxcIVvHn`>%bpfddSwBDv~k-X zIc*=>vR{(67YH?!dGmEsyJa&iwPSB)c?)X6$IKLi?@q(@)7{Oq8ymz=UD||A1N@Nn6|`vxY&M(GT@SDp zh>lh%>WV2oEDwPRC`(EDe&I~%r8v)%+eB~vHuAxlDi=0HL93A+oW#HPG>ik;sXiJ{ zvbWw;z#g1m&~*C-eKq+l7hM6m(t4MPu3Z0;U(9yliJb=`viGYX1VU#R*6j+RH8Q^H zNk_&k?U4Um>}T~mdlUep&UMnN+Vb5(A&hf`rkHhr!~lh8(essOCepHE$PS0Uo+96u z3%#p{wkHTj1G%p+$n{?%1?g+XKn=BizT*5*+@;$@cNh*5DsUj?@$)35LCU?iM6_0o z;!Xtzi?Xc^GTd6|>o>sgKe>^h-8F|06Q*K;*&^9SjS1-Q4AhYg7a`?lXX}cA_cd_Y z9mzeL5@F8F+)cX)JqRWc!b`HaQVFDfgL)n5{2=z{_oC8-|9T*h%ao*Dx!)dj@sEvT zoSN8f_C!Fa;>eyq615N()1I__MQ13`4ZJG7PrgD>3#?U3pOUDy-zW#) z0gMM1k~=@TeTJBuZl~=qONnQpzz(^!=vXmO5za}X?DG8yGJSdWLBV+YoB|PGk)&xT~#8mmjV8y-THf9H{lgG%mg&WU>;2*3J+E#+`ECqFQY?jsSU=BPVIvQ-7 z<7d7~u5PVA9mG*h)m|nxzvPwg?**2>9!7*|hdsI zb>J;I1cncZ6d$AcY4#>sM?QEuO!@oBx0&9n(o?ksubuxV;XeMdHd=L~H2a}cqO}S$ zLj09KpG=i-mtW$72)plTBYVHYW;#*SBZX;M!_s^YCnW)0d$r#6l1>$~m8HM>C#@DPs zmO~!p;XcKtWIAeWJM_T=RSgtvu0a=AE8vCh&k@9v#B}+~bK#IeS*kFx@^G14wVkD! zwPua!*+QeT{rvT`erlA({SmoYt&!EO&8I-h+2#~3v4?+r^$kQ`m(-Ku&aiKEgcl^ys%M5yH8V2CTw)~VKI15vR6R&E;*)yM75V||3#WC1 zN&TgD)eNa7w(wDaT7YITPr8UJrvc?VAPBRC0ZfGL>)Y$gs+~bXK8k67uR6tf1#xCh zA|l{EPl&Z#CtG$0{m>>$8muba$6fs;loF|;A~Jt_{QFA-LLuW+;-G~JyuP{Vu1nJP z+tCZGb%XmJ7{%E|jACQYJk_o$o&>##qNUvEWfdTeWG7psNv@u%1}GuD_5W5DaYHiA z0K2%Mlnps?1TA7>U%e%#pBOJ7cmIR>AzYH8)lR4EX2bRmf4y!ueLhuXatg*VPUaI&NThvdd%ZlQF_Zg{fj;hvehqMJtXkY*}vZYT(TW zwKrwV6Qg)yKZZ$LG&CRpY$kpYiKG=Ht}Q-x@Z>1F&@Q))+}zyyX^mc6FbBdkzzz!R z>~4u7-u8;{pfbgW3&9LD_Y9N%8kZlg840EkZYMcme0_!kAvd8#>uI+k$g{HH-S8Lt zqn;GdIA!vRU{^Hl1xe~g)n^l)PYVFdi$UspD6Y3#I?0@%-}e>Ha{oih2~5(F>@p{57%B?{Het>HfF|&S^eU)6kQUTOB;fw#9ivsg zzbE9Ew2=Pg6kQq(^7{aOr0WK&%YZv}w0t?GpJR9Ysxany@)}9=VbWj3o&oojU2uOF zk?TI#haFtET<9flk)KT)d9Op;SgmFF*Q-F>y90q=iOuXp`|cP(kYs`F5mA&z+&iER z9aKf}tjUFYCmx+D30SX5RH1L)64_Z=}J{d8u>cc+4dS@7?%)A%i z25X-?iLjk?Xctir0$oZjrpXh+o>Nq4%n z$>9uP6di=i?{GZg&v>8|x`B3j#5z1r*{l{u9KpzGK2c=XDD{6x%GieboX5nHomxb$ zrtA09{3anc_OZLXS%274mVi;&DyRcMT|w%pBlKW=sJ9!&U+q8Cbq_!E7Uv@NU7SoE zg;Iy}7oT!E&chl#`oD|)gW>aNBaW*f;@9~!^1L!QwPe?|(7D!hTI0qP-60Iv_3MXNMW~G@mu~uKF(@|Ce3z?=3^V1ygkxsq$ck^2wyK1x6bJHkqDseA%#T z1`Xc_cN=}L>3PB*Tta7EVoPbz+rH~I_jVpMblIJD6Lr%2UDhchmFp3!$UU(OGczHe zj4g6+kfCZxTOUe0Tlb8WAS2A|vN85k0u_Ow{v=W9Ig)ulBF?)_EskL+MZ1wb=$l(#MfSNV`zAI0}U7syjF8WkI@ zu(GHN3{^?VHx-fVn3L?#ic<(>OUBF3fC)$TXxotZc@c|)-i>DwFPaf+R_bhudL7$N z?_vHCeh3Fm=}VbZtojVA$BUH(>!tjP0_*)#W%X#g9pdJ9b6Oyu`I~S(a~!U7o_Oay z2ShS3Z!NnaYt-&UY!DycVvko=h=)*O%xK{1mpfi>=vtbm-Ew;c?%71jNm-wg?JKhm ze93U_u#HtXThC4bR~d-7*7sO>zpC+-E`=(+*kQ+}5tB6#>EoR}pqk2wOv9v&^Fle~SYv^>4`bn@a*YtBX~Mwks@@2i=VK%+X(#U7ga$>cj%yk{3Hw9-DZNU3I@4;HeRwo9~<`#^!JLM;~7jXl2pWAtaf3(@z?ciY5J)r{T*r$WHGF zGh@vF*U8b*iFT>{7z4olr6-l~x(uCOQpwktw4;u+Fc zxOC4QZ4Bekw1>!Y@tvYKgv2`eEz15msB?t<2YY!`+q28KyU4yS#zojsWc-w|>P3ZO z)ln}H??0Wqp|Bg)yX-F!QVy|k(WSh3;`rLl{crno5;k1(zCy1p>y!{!)JU2JUB-TA z2~{^+8MkxTk!o^RLNDWPT!l(tn66uGl7Ff$tE<`TA)ns{LD~y57ji_7JMQI_Nq9ds zR{bTb_(#6Hc<>YC#gUkn`w82ZOnxrqR0e>TtNe5~dzuNRW;q_%@bvvAC-hZ?~a ztmoW)x=?cDhE#}JHWz(0$1x_Bf3(WHTM7JF9x_hwHF^rD%$TwCb(a zbGMixr(OOI=(rsb7GAVRBw1rAhy4N&h)5`g1EN0V~qmpSEeky zp;9L1d-DLn<%C9ZV6SxfUg6@!B>YjW!#$xv^U25o0_EZjrFxFogim2m#c`=ILtC#_ zr9XXXIT+WEZ3r?!#KFw#KCnr+5=(8Xp8H94NgurXUHY|7l{to|LOA=AWi*pjQ z=*Zo1!lUt?$9HEsF~BVho}TQ|w{>~E+&ZvruyobX2uD5vu?$Na$uwcJQ_^H~moG9N z^p&L>HvUcZsS~8OcM&7}gbWnj#%1aT#m7?=ZfojLtpk45-5rS${rN&X#)SKoT_>JH z|NB^_?N-1b{)j->Ly4=|!*o3cH*kX%o3&$x^m1xflW~cys-gM93UHHe59R5M)7`^# zT7eeNvMPT z@455Dv)6Fyj{qZ%3$*>>mCwHY!tH<@8~t96QpqgbDq%vy#)Tcnh*6_>g=C937bRnN zR5Z?ZN4NH2ib_vB9Dg~dVlv4_EKpg^rb0%_GqUX>6>;^lo>~&JSwsBGzkp!t)7eRV zI&P6|GL8vVH8vWdw6KMb&1bZN+q{Ym0f9rT5sVLrw66yY6BF$WVZOso zrXZkOYV=ZuM)@a%Ul3I4kP76ZFUIj#H{H?6526{K@(W-ge&xUG1}U`r;FkNP|Ha!Q zdYT65&PKcarYa<3RMaAvZ)ctjVZb?b5RLLO52x)-h++a5)GayOxRT*7N*J%qBuX3Q zO@lAu&{bl>Wz_7C6!Zoq2oVakT;Fq!wy}zgtI?fpOmu8uOrAhwNVNo0)kM9G;Zpc@ zQ+HhlvsS!-ia$whm1@$${y4BM4`_+N!^QbK4|89g1xK!a6d%(ig>QJ+uZtRZx8uSO z(WGqIe6@^xzfa7^h0q+y?Hr6s@qG*zy>)z0Md~LY81bo1|EWQ>>J>YYlY}4L7Nl-p zm!BvA1~0nJME2-hC|%iUIz&Um^4}~=JoQPtGqQ%1&I76+n48t+5^{RDCd*&}Wzc>H zD^DNMNl>sX6W;+cyk7u`z-dnJZ@~`m1>#|CCdO(mM+ERjnDVPcy9?&)(kE!j4rX(kmlPi`#!+;| zRvzuG?laOoxa!m70=QavIWaKfy7-na;Jf?sC@Pg zGT=bwJBX`tTEi?^{XJik($=Tm6UaJl%@NMxW(#Ox5*n+cpDbczFAyMXr=2A^yO83;Z^Mfvb(;n%v2zJp zoux;MxKh2S^FVd*!Hm6oNmcD&I>xZQ*iu%oU_}3WwIn z|7s7ZSa%)K*cD6Ly+S<2E(PfUZ4M**A0+T*KI9h=rqnqlpt`YeND+cCNO zUV8o<rBZucCW-bgt}l+74s4|HLAP>1lH% z`C~%ic(jh1{RUGJ@A$0+iW*DCOA6Arkom7Tx;V#6nURRWqfz^+>eoRg*TGrxY^@F3 z;!{X;zvEV(Wf#q9)GfzO?sYe?{^>W}+C_~`#0gQxf@hy@5=PtPWg-rk$fse5MNsG%s!E27I|r7aYu3nb{-)+)w%bWTQhj+ zWPm~T&;UiPS6QOjhKb)c7vEy|0-Ek)r_vjd?YH{Z$x3{1lKauI%<=F}- zJyW5Vf2St!UKiu4iecPE;sNNp?zEWm-{}*ZsVPO1WcY{6^8YA;kMkv=I&Ly!1L=47 zGmgr=gma7mk%8rr9~a!tvp3tXMTF`$%m)r?7X=XsW1bpgV@);z886dmdJG`ZqA>An2NM7r`lHh;7%?sS|cAFasHuY$$7()P|C89kHO+i0$CBkh606hyT%g zk|a+~ZEN;C_L5`utc#wkKn@_Y{;RD)|F{lRxVJDOl;OuZEH=aE1Cyr1d9Wj~<#&11 z8Zy;^b5|=l%I!yzbP`2lY|keEg&cWes1om&&238D5~?gvNyr#_@R3#3?sNU_FJlrY zV9EpOZp3Fl3x;1BGbAr}iy;x7_tRd(JP`@}47ugJkm9!#-}#cj8P;7y!VlvsI3hcd zsrO_8euuqI?E8|W7i{wadt)0E+ z-jKl@{gHP{dI#}XtXGt*vCl$GaCC2#ht9$vmo>`s^=U+uC{RVb|_5 zWg(&SU=x~7AZZFzEM>3gU_Yy>K5K&MC!}3dAN+)CSDbw)@<__r$p20!9R^aM4StKH zs8$SZY~IA#$V^T9vPj%Vnbo6F8|2|=?~Cx)_Oc*pyNSQCqUIhg@+wmN)9(aM=C0ca z$eqi(_d9d<@LFZLmV)I4ad+aHOFyC1m>_b&{Wp5z}NR_BPb z6Q(?fMNGQYH?65*GVAae5K!PTV!*^D!VT)$MxPIptM19zD?Y-Rsk(9n+o|z(n$xg* zfL3wZopqt6Sh+y-w=t(>DQvIh2kskvUYX>4nN-y&6=rs|oQ#~xkaaf(R6(ar__EI> zI47ELuJAtGs=)x!CogqmG+jmbBenE6)~H%m0DN}Rf=wFKEu5h9y5KA+t(${|qm}I_ z@2X9@=R4W?`viM8gP-=F`0$L74x`~7-7pGny9U17PGC|9NM-Ccz#1{-V=+mU+b%GsGpx=&9- zE@z0ga1_<=mxvdj#RUMf3hRC$vUZ2G;Fm_%h9E&+j$j-1b}c;}w~0!*{=SVF_?F@U zb~D30Ooj9!mjp$mWAYVflK|W5gW3P;FypBQb?=!A$dwcjxZ`b?&-C$5q7Yuvhmyyy z>JMJwH$MA!Q3if@<*PxDLwnK-L^uLhWaA~YG)b`i^Hdph>zcxLe4ORj=VjiZ0joQCf3AB6Vi%Q* zdMHP+aJ^B4S_Mk+?hLL&6R`UE>RZ;Y*yY9FCZ`&VDn^80M|db2^9c~yDwyZ8LSE3< zUt+@HGSnxEX<^pm!G7XVZ$>}^-|fp0(b#ju1RVZySK?#%7}E=^+AnqvL1r}u_cX!K z>HTBW8qWx0>h}_~w&o7tVIIdQBhcGwVOc z))e=DnOr(7yrV`rzH?`~AP-|a85){Kl&J8f(|Pu=f?QnjU2k!e7V ze|&V;c{ftvTic8S>x);WKvz`I;NUKY_FoK2w_`#U(yfyaEiG`uUx2M#vR{>-{g-B?(He;PUNgB>I?!&dtJ*+k1iWt&DNR+uwG<>04Zt{*&}J5fp^$w zS7TFJv8hh~8hKw$rgSln4gF+>ysucLHvH5Oe49_VobIOEnLu%9UYm#*1J|QrlTVFnV-X)N_pQd++Y_{`UYaJdB1)iBW)hh%!NDoBd%7_UqtO`tuu1T`5eiJXSDQmaS{}Sgz)+y2#fM0!_xNPSQJ$l_l}Z!*Y{=2Zzr!7+;114&lUKd`vq-fqMGX~n8a42l@&u~&h0g+-@Po?iBp6DJu1#OJ)r_PU z$IEZJ2Q{4b-KGl9khAP_ECEQEXXr!BK$CFVY>p-N?Sti)w2KoZ4qKJH5`Ud98&T$O zZ$~;o$zz8Zmoz}=QNTWO&Getn@k#Amyx^Ont(ax&q z6-9Za+!-H{`v;=vRTmp0*k?3=_wtCw)m&7JaG~74g`eW^{YBM8_E-l*w9#wjJ~Q8#V8z6H=&~soeV!E&UH|zR@*7FxV&6ie;I1Gv1I!&lW!XQlNwZa zjZ|_|tyo+Cx5N9+4${GHQYy775C1IN%JwkqcA}sB*pARXqXCLl>eM$mlt(GNBdB~w zzTfLee;M%>Ri57=nGNLw9hfEiUF+-KPHHU0Qq54Ro-aICv4s-taVDq4&XSU?G!pAo zr>Q%}Ra>KLz2FQDwwL!jB66Ykuk~Om1EL@WKftRbSNCQ6r52$7oIU$1E73qN=<`~s z64FQR2f%SbS8kD%p3WxGdJYKg1Lzgy4GG-2Q2-D|J`)I71F-ed1PFZKYXCj8i8iV^ znuU>(3Fa>U?s-Tg61l&kqmiS~aKH3a%1bt)oWQe&%V6 zds*@&<zBy_&U(vsCsW+ICnq1j*wBb2^~I%RB_JqN+u_Hlx}a_oXw=bY8bsFi^yx5&NC z7Y(;D2h1P7SD! zI?QqRB>wHW55Jvc?(WvHf&?P3_QDM{!6GpZ_iK1ROii6{!znIiXwhJ1z1c0|rBZ*f zYiH#!Z%3r%4ruR8i73y%Zmxb0*W?Vb{|T;MKkJ11o;$hWa?pYY4G5)y5FqgPa_NUZ zx$y||nHa(Nv~`CcKc_E27!q*JV%1$%ORO(pZfgTpp%;cw7V+SF^>WXPR|3RtOPR2G z=$vz0KW17zs_*E3d}K6VIhD3Q^=nt9xfEDCxyi!qz&^g_U>+}4>n+TY>mt<7b>eQs z$9h;PJQd+L;!>A}nVbNKtYvnH9BtK@u|q2H+U^cig?L)I?IHkG|F)~?LRT1z%)Xmm z5v0&h={nd%BJI^q9;IoRRTfU9s9#_gqv%GCx{tNT4&f^cFQ}S9bfTgBg>`_eoTx(@ zQ>m;JoO#r4k8ozv?CH9MOC)> zJgUhv*%{hG44AhZAk>j4rK}2OAEBeef5|Pyke8MJ%sjD7lhcjc9C;Q=eA>p$g58D| z=J?6wTt;B9kzBI~l2qazR)Q%F=2`cRI&&-OwU^lo+Ud81i7QxVc#U&6CZY-KSlGkI z2Q0z=#%#tn|KBY(s%G(k7XYqxMz{*pI@ta~?}RU~WxU*MZ--K04$HN|c+eJ9vH zCM;U|2z5c_J-`fHyAgV6qy(3yaVb$P=VjP9D32As-zQp*&Mnaryq9>J$dAls|A`)J z!n}v8!mfA;5xYZAU0;O!Rf)s~O6h97qjR~Izd}%vgLHvlM;JY61^p;)?UPYz4aThq zS+|cE2*V|qEY$cU-eQ^i=9~V3M{JSb_=O!mOEummrN7hi*Pr4gVeZ<3_MjWxaNNsg`T3b`_<2EbPk)e; zv5R7ey54kN?Frs6EejH#v#^&oGAnaP_NN>^ZsNS6QmpWU+uK#9%K7@QN#{o143mjl z&R#$&6=p47#8p77)0cm#EoPZIpF6OZ{_zE{F6;6ee{f#D@e?@W8TsU_E0``x6`R9} z4-#jVj&+T0iXE>WZ5#AEhS-I1y2Dld9ZV}%4)4FKiz?7>GGEDwu15X{rZJ8a(#wqJ zHg!|}3*{0h*#lKqp9xDi(WVEt68soMN$2JV(qBfST`~cmq#9}01UdH0YjR+SA^K-r zTHARxdxZLQkp!1YZF)1unx$`O5ZZ6}P4@`?%6Fp$+hj)ePe_4*-bGc!Ht**@>(aG1 zmuk8`ReR`Ol@3loa+|d3c2l6TsWJl=V&nlJ@^2S2e;7pZxGP+rX@_jQ#WLCpeFtei z#eNV?|Ct0^3+6Yo`?J?OxFEW>T9egH;^bfU;_#QKy=Q@{B&@CQ*^taMq2fZND>H_* zKxbsJC$rOJ6FUCxJ|EbDzJu6HD<)3QB8tt4C;vr9s)3S+q+67}l;!)~aT8~uqc$k< zma9O66SkI;FY$?2{;3l@MRCeSSmmbr@E0R+W;psx(>qn(*1!FJvw1H>-XX3Q6K%DcyxF5{T} zev4=ACD>#3gK=Xn==)gxg}-`Z!L-m_tMk|q{BmKjMVRD&pj%D_*1I(q7Lo=}<@isp_w1?bfjrl!PpJDT0ZF)T z?cJ@_TFbeL)!LH%QQT-SgN)ApRYl9-Nl;veOsax#XZAg!sC|wc6wVqFvPPL)Eg*2c zlv`koKtku$l1yhMm5J)KAXv0(`f54dYuCkF6RPULIJjKhclrG*sDY^t)0d9T4#cd? zHTs@_Do13BoTU%7f23qnA?=-NAO4Wv9vh-cKD7UHlCl1$jL}UZ&=?ZQhh%?iuZ9E% z2n?0k(q;LfJ+Hf;Jr~P4ctH+<)u%c1iyQ*VP2IMHF&qU_uHJ@A-w4{}x7`No2<(Ep zbi3nL)}WhJ1}gmfs{G4I*8*zAcjf5(!aP-5%auw8d!PVxtehF|0be|{h z1=oN+WR1vE_3;;p2S7r?E&n%iX>u!4-8^XVsNfy}x`_6f7#IzajG2vfM~MqvP<44F z!q>4etgzvnR^rU7FCl&0?6H^RzA2HkbN5G_hz0r4wnPrR=a;jg0shC%)7U##HF=UP z_nPMRHqPJM>%b#?Z`D7k1PsqW}$wxoyhs!73=ZR zo6D!gY~7abRh|f6#l)%A>2N+|F=%oTUQK5%OFQ3byWmLuFTMaiE4c0QV^1xH@n_oW z;uX}Z10;Cu$xTnhUVRQ9;eAL0Z*c< zy^zw_1Ot44@||6b+ovj*vvrfzt;t<2c%bTDLhz{A+9KfenaWgoa~_Lsg!?lKTQ(sbs5VZZi0QXJ7R2-TaEB zDgr6e*aH3)UCvd1LAyeVp`IQ*3o<7gEEhuuyOzs{&2Fp2I7A}C3`AQn^8t@tz9mk% z>H{FZ{i7J-ueFT4oC3MIjNLp^u$85D`>R;ots0(oS@&Lb_B-k%N?jk#KP`Lf>hXtF zSXuTV%SQLj5{1;wruhcImeP;MjjWC-9!aDe9c`$1-kWc{#65`E9=^Vuow2!&)r;ky zrsDAGwq~o?iO=C<$OocUcvI~-qD$aywx&4zfc4H!bOI>oPEG%KmBDFam8Gf)R8ELAkndB&&s?-~y ztLB{JchAebM^Hx}^pr`kz@O4|LUw95^2K?>R$^^vvnW7lY$q8k_UxcY? z=&0hRlq}sV>u%F-okt)0(LXy-mT0FDg8_XoOrMMkZ#`)w#|o}I6(NSvV*l;qIqMqI zcY(7+H>-KS+R-`UN7ZJ&7(6LjTjViK9@?cm90G~ z2H*)>Xu@|LYy+t5TD}`Wo_-g(7jphNPmI1lLC4N!F##EQV0c*PcbHJuu206N;^Urd zfBd>alJb6ac6p2Fc52yXWYI3Mu7_yupF!1=B|Hdd_a+n4`MXT`+p&n*vTP10bm5xzz z6(p6nwY5)Rn(85h-TWYErhz?oo_u+M^5j^b?t#87H9WmAsbp{VDI`6m19VB5DIuSs z#};-8(*zNs4Zf5k?X{Cu*?zuz(dMxH%Y&W0&q_x3j+y+}IjCs#b-kxyT()(v^ghOt8$9)m6EmeY~# z$r+TQY5>=F`vr+uF>9LY@d3W0AnEg_*LKETfW3CBXMAA$)W3Bjnl61|$w1-EhRz}6 zguPDCwPQu}tyIxoO3mk{Z*~Zgo)FvSqGq51JZ)m^NhCvc%=Uf#}$E02S z;@p>Q9{QQqNUo8wefBDQpms&!ugU1HXwH|WO$(wwa7XnU@`3x-_c8WHMzaovKFXMf z!T&^Rcx2@CK!O%ncDt)D!!SD*$c3}y0_pOvmuC){#s2eBaI#4NeDoh^VBHhEs|0iU z-4x0TughVB%EZpjcXhw5``(vPo5^R!vdj;~qM9b``B`y`IT!y{j!2Hw98hPU2L0OJ z2TtiN^Uf^N)akJl`!#y}#j{rwBgq31_{VrQW+R%U<7otMR?8zit=HVfN!I)sK#|iv z>}GWa8V}WN`onq-6daf9|B#yjO$oEH^XGbDqiQ%+oe2 zzTLfJ{Dx9I3EC6Tqq2TZ^dP6`!FMZJedMF=Vzwqr=@mx41i3TRA!RhXnIae^!$#J~ zwe1z^8|3ahoEf&lNK3EkEG{^3ohyMS(8VK4urpKT#SdkYC(9er3YH? zfsh6+o)79M>q+xYBt8jyK=c({jQq*%3)R_DEl3RSrW(N(c3 zXV-|kkizS{+i1LPZJW(vrT_?wsf|-%ArV=oaRF}-3VvanQJq=4T4?@Q? z*A_RyZ)J$07&Y`E@Qq5qMAd)i^wygir)Gna6W`)-I8%6oHN7UcSzW7vA#>iuvb)S5 zh^8n}>=}XXDw~j$+iPNIQgRVx{E-^pE3Vh=UB88kw;OY1PA0H}a{cDaFe7K8Wc=C? zZj6O}_#yf|LDEs(SXwX0PoUBfF<|0Wx74TlWD+RUpZR*{8>)bX2p zsaZ6FhoGxp&SKN0yvT^|)Cd);oqB^bqDE(@^S#2<;aBsVcff#Ll7$q0MT)j5&&yN2 zx6+dgPI0vd=@spQheYxWs`=zkxAePWY==R)8$g07xzom zUfoJ!+=!4_-c6h9cz_EzJmXfb#rTWE@jY{d;pq3j{VTsA&l?2=)xp~bKktrUe;jF~ z8L31T`;@&@>l&rHJ!Q3IFE5m67x=S3A`f3Wzt!O~5Pj7!`#>O3XgOe_5%_g!3cc7p zAUZR{zx)h#M031GX>2N^%qU&_H=XfYf6POheVyj-*gxo)G|lO0XlAV3fYUx&>#S-D+TXVc@?1>?T4$(i<()i! z%kukk?7|-w;(-_E1z`)7#H>cjCo3F70$}-@hLdct{wdD@L*w<&wE7;wYMD@ zk*u88*rKMb2w>TnLtZgFoalJl^i%uEbx-m`!}81iNTY8sIhg4bNO1aClT5Pt+(Z)3 zGr*MRxr1UB&_;=gJza>+_a~P^ zYD|jCOjk=CBe9N~XQ^p{q5vbD%Wkogo3CbK0(N(Ah zrY`UPiiDZtmrte`%Pcz`;Gtse{OWS5ZXzzC=^<4e+awZ_l_Pprc^BsO43E1nHy^5( zMwplCBe&#bL=@0#t+twXnvni5r1DuJq#{nTNdOHq_!P;Z#M=kLjkul9Ng zRd9H6Xym=C{Oh~9cc~E#m1Dgxpj&pstYeK)kBZ2VgK1jH2esy+Ovm!h85CYUq|XnBT__Z#beo^~rDE^B28AcJ5M%~yTRv9zu9l5OIE?x2{_@f?YF z1L3Izwz0(YrI0h>w*EU2wH#jxFpNIHPl~=rMlZ`Rn44DS^ddiXzF9p>zc6nIR}K)J zOmu+j$FXXoCCdUaxm=AFDX)S!JF>0MQ_A&R69lO>r;(bB3Bf3KC%HNFd?BfktNJs+ z7>q2%(9jG5v!b;zNuFuh`A zyy91|ii7+Lh?@)=%pOJOTs7sqjYXs2Gb&V22rn3FsxGxb*(EBz1SX@<>jnvo* z9>iS!DazBDuQ@ar|MBCW)-I*hP#AF&)`s_M%fNDWmqX}FCaM~;hg8nq18QI5pE1** zg>Nn%t_)N=1|7tAgl>0JN zAT$tS_b06uD>^E$2TMXbU{!0P{>{ee-oc3E?66 z7^Mc|-RN#VUaf_Q(-C6We*nks_0&TPUOZ0ef%r@q8zn)SC3+Vzxbf5V+>;%mr|+0G z0R@fS>`Pw-n-Aj2HA~c*VF^I(TDRae7*M`|lSIM{vre5GCict=*erUWWxNR}a9Ccw zvvoYMs0%2?D5LhgkVcbDbG^HnxRXL%K*~F0{3!YR#+(OEZ$mMr(@7T!rauEd-xYl( z)7kOzDF)gPN=m`@JDtn{u%Q-i^`6ZtXB1}bHQ*ZX{Sk;;=*dI5^V08eS9E&p!4siW zVf%rA6#xhv9mjrw4<#+1h5D~sGmuAI??(BIC`9uRB4-0J75*23Mx#45`nGU~(@2B4 z)bF;TUc{v+_rWb$5yRA2o{2ySA3?loCAM@sRH+nmes3BuZw1#-Q*QqH%xwPb$dvor zJ#UuHT`0Bumf z1ll(op|6@&NLitBc9Z0b5$vEgCgrO>WKM4Yf;$Fy%l=Ebv>V?LGfJ)D@1uQy+kt}N z*WE6G;x`sug)KFP#F%{o(_B+y{rCDl3dq~$E@}xymNlW_z1BH&{NETVTXA6CBN8y033|(5l|Nt%po*3 zq^uwe-unV|!5((fK8J9KUEY2d`V;X@fOIlNe<}e6QRc=zR{@e&dm;fH;B7Ou=CyN1=(Wf2M-_OTUe57C?V=~+=KJ*bgZwtN7YwMLbU;k*PePl-bnU@o zd?PG(sEl#_lwh|#WwBmOiIFh~1zlQh!)^Gd=bUPVG&jh2hK~M!B%LCWl=ic8d)`Ip zXpZb5ub4OM-hbb{iQpX2Ch{g}{RnjyvcTF@o0o4>J*QpaqU$=BbPUL51OsK{1nJDw19VpLE-*<0u-TgVPJ$DAVr zRISqIxXo-&)wkLw5-TJHNPD=km*|hQv?IsQ*G6|#!_kx!`CuKSg=`$scG3)Nt%>3qVQ1}^eZ=}ABCP<<0a3`@0w51(=++ zzCxS9E&~(vA9H0aJPx9|Ni(o`|Fk3YOQFedTc+W(g(;Hc>@2^exZ`TJ<{J62#;kb- z!Y>W*dUWpOAZF*oHCu-(*-xMk2tESB4%X*ew9NGj8^yLwzd%O^jxV#RWJ`u9J|dxS z%M{RMZU=Q#8hpAh=2=64+Q2^64YR%|_0Tn3<_Vnu`6fO#Q&-tmUUULI?xs5UJVLbN zqGg8);ThjfrCi~u))ARt!S+{ zx(aVIx{%Tw7Es)7G^_Ik83H-H7h;596sstjd#2j2Bbor7=SKWT7U8(9Qk*0 zzD%A2>?YzS{E8p?6tk|1lHLci;C>OLL(A$(wAjWY?tW(33-gqgJQvg0e9bv=-KobhpYcBke8ALYxnENpxm`$aNmGoI@9iP8;>Abxsmu&ri1 z*)W*xn&^+7PN86%F{kq2E5RE$H`+vbTR7d-fK?$bu zhwFx$*0=w_D=SMI3=#%)%FAXJWPEH%)YHHEg8Wvoo)-i z?%m^DqOh_}H3i)caYiKYBesjStZ<-!pwxqZC)K;Mr=+o2X6PqmKcKKPQ!Yp{<4Dav4b+F9GbH4+UHNKl$M=V)HTLR0*2a!tUHN4P4XM0q^b$6 z=T8;L!+O_udZFa&CF&d!{|qwlSq+K%EWWH)QhFO;8Ng_@$j1Mw7DG-|x(Znuyc_XH z|JjbR>l@u!cg51q*pzX}J#h4ls**211JY_dM}1qT&AmgpgScwKs<{NQGb}BpB5^iDQ?bt6b3&7 zqJVGLlYYM^IGx$X`ovp3U8rzWk%n44phXSf{tKNsDzhd z-Yn)ns1lkp04Y|kz!bS~;b0>1y!(~{psW$6A44g2NkWpPiR@3aGR@D4DI0a+`dci; z>p_g=j-u#kd~w+)?`YDET^6xC14x)6ZWn?Rg%)>M?LH_sxqGdWU$*b+<-L|=R?lwZ zv#wj5-Z)rI%dk*dUzm{rW2T-gD(Py@r^;bzEdI>*n6$s+&N(b%&`LLF7yundk%EU9 z@vFxVaW3O)MkLZW?A!47s5D>|-k%zI?GxE^e(I`|yG zw6S&?uj1QL@0KLWF?*C^^^=0{!^JLOVN8Jc>}wLXW<4n{=>ZkRFTw` zD1#=Zy)O`7pWs#bSI*#aH(846)%#_M({>~H?j6IrHGJcasu?QW3RQiJzRNDxiCA<< z#o={-7;+0H6r|K=)rIHc%T{Ua&oHxRUHI2<@%JsWy?gPgy7N^(I}FNJd{VP7R3wW% zH!$?d5*RVL3Mgw`Zv(x_F^t}4hpU0&dDTzn1fOmIh7H&@$YQ(iJ}-P!($%Wjw4jcwJdoH3*>kaQk^YMStQ?ochZ_T z4^Vy2Yg|5D_6oKyHbqjmf`|^;=mMp`k}7PzJi>M4`A}OU9EE(?NChi)&+4eRplwg4F4%Nt%j<+Gx?nf!?C% z)29>-8mjlReI?6z4qs8-Dr3$0kJ*Z5+1$4%JvfTyXM~T}e?z&MABvR8j5!LF4e%@$ z;hx&JT!IiRIr>2yJCEzUXK;>CM|!t3kasaDvgYvPuw3{NInGtw%c&$}6mJ^mbd zE8zy7i6%JbqvD<`dBVph*MYR(&klAnZ8zYTW@f0k^|)&&;mU$u98bNrY|sF2bi8Wy z?>nPGT?)rFcKN*<&|b_V@^m;rkw;VFz8DIL)xj=PIYIdad(T|UPv5STVTe2TI*Nx* zQ`j7T=28Lqm6Ok4)=Kt?T0=FX>Ry?$SI;Jbt+J5d1|I!zhUaOXjdlJZzoN2P&V76J z<>gC19CP@ZM)LP{RnnDHlr)xCw>EDWRD*nTIHq-bv#H=VldE=Mz323G=?)#;@UL)C z8Mf>@d>F^gd$Xrk;7J2?YOhnKS%#?3MSxH$7dabtD+XMd8)F!?zXHwP{!8O#6M{dtcsYf;;;0WKP{k zFY>9A+|uaF3p;O$1J;Y9#n6uvnf!Nw(radxtEEY13b)?SYHKa4Wn+-4kthWl%;=7sVF`6*xJ z9{tDogRYe3cY|6TN1#2#GV;$M?>0B$&b6Xf-jpGLm$6QUPiJ^J$dz1T^6X5+3t+Jx z-52F7j&Y1@ASXXAhT1MIltS%3q3l%5lt*`|V4QZ!yUXusv1Dlkads%`Ou!mK@tNjY z@E3nUL_|v&;ac|4szRpOhO0%g=E#G4+wZm_cA=fNm*hkgL0jZ7yFq!unwmJqdii-C z#lN#RyW3{KOng9(eL}Wx;yAba0EeDju^tgO4EvYdaRe5$xA^`y(tf#TH{=d4@Ev)!(^SKSvxN~iqu=P*iTp6iZ_L#0`1Do;kqh<-TZgdZ8! zmg_KoeD+7c-E3LGF9g?T!jX2KQLX>VZpGje2*I#{TDZkt`e7agRz6}RF1P0{aqmIU zSE>sxYVzV?>bk?!rwm5quUN>h=+H{#C%Ej-(5G%{b){EAVD%a?i*Md=Z;#PuUp+Gr zvc3_XIowyOoBtTnbf#If*@yE5f5M>R7q~N3UZ?0hgY2fE`ems(at#&eI@RFUZhpEk zhzPk=vO1dAeOu%rYg>$L{=PokRw^3Yn;rJgE6gh`k(f0o*OGlkvDJ9WemOYY3zayQ zt#+PGShcbd5WY#)@*bsWrtH^n_|{MOuOYemVLvgzE0qy10}h23RLedHYN^$AF$`Kb z1Mc+v5?tLI=K~o-l^~e`>C4qYluEfK?gF*Tj7r^Ha7kcRk9(-vMBC&6-WFTKxDT8k zEXsuHz3x8d^Bn~!p33!7bb}mJq{PiCg*qDV0{=~+19}*~?%UAsj|q=zH2%hH2Ee(S zJ-NZlaJsmfu^-5J8P}Uv^yf3zikDMbu5**{(k*5I$@0E>#Qn;ADYX0>;ATI~weHBBeci5X_hQ@y?)Z{1oGbn@30M9o7%nuFsPHW$hNS{cimb zjdb5yB!9knIN>tKb-;gY2d&JG07#@c(DY1ltoT*I3^6n`@E%qwS;HQ(m-eV@;1JMY zviZ!l+DiaG6$|h80?X627BQ}t(qY$@!boCfBzYU^Rso54!x(&D>am$rnAae@d0*3F z(>t7^YS70pdH{Gjhm|3-wo~Dq3Zm>|^708MqB#blU|38e%s!A;3Bxqvswb&YY!zSK zJmKl&MvBSX_;bXSTsHLZQ}koBw%y>I(tv-!O%N2U$Vtg1QO>ot>N-sRxUQ-Q!fTH9 zF^wyskCtbs&95L+{*r=6Yxd1=7RWC7a`Avp{l3V^SV)huk4aNz&inh7>`N_zM+|Ut z$~mz|&;&jN;l9Jj-hHe=V1CIW*O~P%`JhI`Q^`4G1k39T>C1f1^mq|TJ87H7a!H$G(Zjv8_xCdg zTF|z?aXyQZf=iHSNsoFDJ}~CJa5CWUy0<+j;s)_XzhOme!{Nvzj;3zCKrWQZt9@d_ zXjU+r4%k!7ugEF5FapAXiI4tc6+`IRp!s5HUvW1Ml?jPXA``lE32PDw3q%&cD*lMh zMeSW)owg4@X1TtPM+AACksuEC6=Tn2TCRAgl^tBe`fLeaAC3d(GmpXLmc^53cpEY0 zKP%M^NT=1<#lo?Wu^oU^+Wmc4p%vE)t1OgNNO=9|2=rmNxMQ>KwtolMO;&=R?lNgo zNonvQ_8`x_pM9DqCr7z%THmLR{^`)1fq};wb|m0d~mb9?qs+W9h( zv(L5FqvTqZohLEyFjM(@iT+7XEC8KC?NY*YSRcP{23{;>er8d#!^#KHgYDI3d; z<$PUMpWCUs>v^zz8(s?pw9RMu25vF$+N8@~JDoglk4J8hYvOZ*Be;JK1Z(j@Ih7=B zaFc-Yi~gt`An|IkY>CN6{SL8u^RmXLd4?)Yu3qHHViH}mP~YNE1HI2)KZ96M!9<&< z>Oa1qOye3uoCnd{eg(0sRQzk{aCR!6a=uMyv}ncHP|;whkE5I3l3v>f4L&xqjfdDD zJiRJa?%j+zkvmkB_=}mTs%lpt=n~DA95T^`3POdo!y~)KP|1pE5cv%f%KS*qk%06C zgRLU^=5d)c{C{};IzLui&S{#g?aqQfL0uJOH!b}d{QBWOw(-D5dz;{6c*o|KkOP>`uON~g`1FcJMkNQ6xHk+;Zcz>OE z-?*C&?jWPbeH+qImEcs8m{iwLBGf4?|BtK3#%yBj5RI_L)ZIo9M-|ezMNk9Eh%}$b z=IDF5O$zR)Rirj`X98s~mZG97jw52Qj6&;?#Pd@?iLo`Vu1fA~ zPTr;u?FOjw{ZpMrn$E-0Yab2?`+HbO3K|abS5yJ3TiY^!%3_PG5|b0HDaXt!UA%{= ztUjzv-pu&Np`rtJ(@O1okPo)RhZk?ZJ(hdRHmNY+A7LNB-W&idS0pq`YDO7yiCc7VS)l!nN%Tw_&LPCjhhsmGW~P zoT1QfWk+)+W%}-mM9M3D-Y?7Eep3_wZL7yISw@E>s8n?a#}+HYlyBcy+q|kO|9BhI zh)An@S1V7eU_UNSp;!O@3y`GW9gkvCbcg)MWpb!}e(&5(_vEXW{%gxmnir*-f3DUT zn;Oj0{WOn$S(wH@kO@SSa`U#oZiL-ib6-+Riy}8SLqEa_sG)b=3J#jDpeqI5TFZHV zHE6Yu1%^d|U-Q~VS!N|&_k{{$AqgJ|IsdNS`IN3?kQo`T(aJqXN`9|bM@^b8l(qDi zBE#RWC^QP;8NT=jp0UkpyI{N39sG{xPSH>8sL6sDBWOmpY`qeXzFd^<{VyXQwQbmMb#)ggQa3SO3M+697@x5aGK_t2 zH(+Cj#=0kk#iwb-?G-?kxi89WH5y&1DHKA&aTo;$;&-ZV<=n4*0VG_5VvLcnm)X{K z?eb6Di+6nFVNo+2t*f{2D6H2So^;f_8kJ-5G}i=u0ip2|-B^{5Nm<>P(Ek0f$SuXI zuiA)f>(J)5z*54Er&tKnprN3D{dN1Z=Px0clq^TJ-Os%30i zVAdd$DH>pkZ9%f46^ydUoeDLFPcx>>9{!vtYvKmYC9a87&z%Lh$z_=877HAVoi;=9hPN7UO#{&38k zH|;YYoM3Y`F*^eaGf$f@--?S%1YstR*0EtZShGqZ{fEoKzw(Sj5``xlWg0@Y?3^Im zyM1Kjwe90nyK6(ZXEG?A#1iAOS4Of%f;&DdRZ&m{)>3ThMY@{EGCR(dD@g-kxR0sj-%9lv~pgR0i;CS7SJE$yiLL> z{Fk$p_Bu_Be;dMF#{c(5{>^b8FOa`iWvUVbz4}OoRJ^P}K!-WvcE>F(N;FVD5$Y-x z3_{v}D6r>n`#qDR%~20PxWiCQBWqNbKY+UgRdwM4ZLhvwCYz$1mh^);u1mE-^`Y!I z=^&PI-HO*tns!BTTGD;)=yKoErQ^VaX> zs(+Mj?Z0)Sjpsi6++pOuqx&qwJ#H*Q^I1?Up9|gaUZ>FkE6980l~uU*^z4p`uq)l6kOel$COJ|PY5=+!=1 z)j^(9uktuHpOz`I)w&f?MTfn^e%itrGvw}zZ12E~Sn7J)>st~nyBRybQ=2iKrayD) z%Fl7#)sN-n+YFd;XG?q#LPSjk{Sqtc|2R7LK&JlxkMBOSxoa0>n<9 z>!^todl6zs1(&JL3dOhedtH|ZW1)WuB&qLb-%&z6kC!ZDb5ib}d@P_^z;CT)dZ&!V zMY%a{2JCsK*ty|)m!JuF%~+Lv?lMmC(J&oR^A4fYsr%tQ1h2Jaem~WOPg1poT$XW% znbnZ_8G_;FOET6@LdUbl$=S|VGS+ZvPqV$Ak;&Yg|0Ed}Jg-q1YZt0t6ASLD#DaX^ z|AvVU7r3l<1~{*G)b7%ZG+E`Vf-Nk|d}S3(5A8g!+Rmey`WD61ohe7fC!;0Jt?B|r zCFL-xK_FHLbIWr~Wzjr5Hb)LUIGC&SH@RD>IquOf2CNwHSt-gnz7PD7SuKI;LGJ~J z5&%L~mIvKAz-xACd+;-2n|@U$RW|lLepe5CkE0;vgWxQWqZm4jXGMe(Fw7d1%ln3z z9@)M&<{Nr}Xx;PiQlI@sO%MYzcxwOlq~bsPbLIF|M8e3R4fPCr@M0Fp^SJtCd3~Cf zOfwo6d=QRP9sk*$^qvp_-)^e@^WNzJ^qO%}fpauQccpfxovWTs&?)|npHcB+L#IYlZO1dDT*Hq`58^aJ=%Zu6aj38b;`4cz zeMo}J`11znc>pBOcf=6aT~8}GUNIk(U)*~%?*p0Lg9?m*=dJw1)W#Q;97dgzk7yQB zDt>7Yb?~(H-0ATqk({$z0OVE!-1-|bewU6gvi<^9M{1Bv)G}~@q!B0jOgX38T6Xm1 z-%Cn_+?s&CdW(H31CE7~x?NndRdk6zFcW6FFx8{PF8yUKYyBTc)9sevTR({v-oTTo zt!QuKVH>E*aZ1Ij+@`y(XJrKn*;P8L($@Q}g3HG=-BUA_>bzi&-Q?ozV7g_}JpBtV zjf>GFfgEQmNTnfA?xh&3Ex$8?-AI^DILfoHg3}}G4|&0?P}KgBx@c3fBj#H3m#u=y zOvHJbj+fEIeZNTQtzEqGPa&pVx0T^EnC!s>8$n=GVURuh95J{Qbf$4~O;+mT+3Os1 z2(8-EH6CCtjpkaWTC;S#wTxn+CHG}61$)>Zif;lIYBCZNV7V8g&>LCxUsSZ_N`a5* zGyVT^QQTiud56Dpt-z=Kl5?QsWKt(spQAql3DKfsr}$~t$P(g9=}j8>;j(D+W+rg z^LdRr)EK2f0k}u1ezlo4n)nhb-03R()g}>rodv$R>ZMkk$NZCil}JyKn2KN$oco

    L}+Kak3cLz}}qrYR6*5!9M7F#T~RTxzJ$cPdXWkcWFPV=nu3FnEm9Y`|$eN zMZ8(GNwD6jJV&WFe6v$4I$O)*P^#h2ltLv*S>=ot9J{RTK)1;-_!JV#dP?TNtVLqb z3#Hf;Si~sE4If!Xj362b+<6%4aptL`PJRtt0HXx1*fGnPhk2*=Hj0vrtC~|dq#{gHb4zra$P^4qiv`7 zlB#n;YJ>MJV%a`jnfn%kTB92}HQmR27|oujP4DRZtzc`#*9*{A^`m%Jsn$i(_+`c>JGuQA_V3)yn zm#6(LM0%4HA^K5^r(WufX4qMH@G!w8JeXgneGMq_l_z~!N9g}9@0fd+5BEN^Exkz* zbbOl{CoO?M5=-FEvZ&GEtkT>-d+H$MYKoH_&j51#=0--rQZ~6%>hvMY%p)Aoi$L>4 zaDb)Uq|wGvKn{a;Z#ZQo06=}7)?1)VFH8A+kXRN(>M%&SjgB>2DgS#x5+&sO!C`(_RJ59xLGMZOwb)n=#<@3)l&H zYNdGCZ`n0Fgqj7Y{a;)|#*gc^M}bwX_{VO7+3)7B-ph`IlRX;i>_SE1oTH*pub}vq z-}2yzZS-iu8maYSz43H$H!6~%jccSh6m{z^UK(D?$5Su1pqeDyr5)#+%KP%NhiY^0 zXpI}WY=dZ4jvY;(={=umiYN@i;$YBa&-CqoNy>Ox-eo(Z+F8Bx!F*{I@3p|MWH z&yF}b-v684&k1w5ZecTw_=I$X14_ycSY3TM{Sei}vOL7B1}2GD%|9wDBaz5fUF?7& zprpIg!O70~-u6suCFscKu3NqCDO$Ad6}7R&)F?$?)kBns zC|J@4q+3qL_4e47*bk5P5KAoTOR@BKt!$si)D9mB={Z|zNej^z3F@v64cx;DOXc4TcjL^=K_Q9-Aj^p9_%1(E^Ny=$KPwY zW0nPpZG2|I0W4YC=XeKOY=E94fm;YJSao;O9QPFM2udanJ5cBuXzbYxn*13GHh4^L z+rj(0fr*4`kUr5aaI6FE8LT4KixJ(=| z0xJPbPfoAbqnu0iUhbfs5n|Sd-;0QfDOza_Q3`Rp0*Bs_Rm};Qbf2hIynu(tIfNQB zd)IkTl)FCr!%N`@sY-HUsa}6NQ6%mt9pXSOIVa2|rt7P#g}~@>t-c%-_e3}`|Ck^P z)r{0DLtYgDyV^PcU9sJCH7(fyclHQ&!Y4-}iRu6g9_deW_Uh8Ij`$XN!#Py7pnf2! z^7L|xs>ToP^{EexqPfL2xD)Dxd8QUS;$`zF{I!m*4z0QUoqL#**)P6MJWz**E316L z+E=d61NtTVPRrD;;r#}hF+9MVBQEh56yKAe*WvbQ@_PAV$0i4j0#%kQEsMuDgg#f8 z&=gFv$P!Qw_=cRxPfE9@i(4QPEzf(ZuJz4?`9X!Puq#BGp+g%oSL z8GDe^91hB)2-7OL`HghsjUeRtBCnrjoYfg&dm14muLcAU+rFF`AF-i4>p*sK(_99= zvd6ZilujXH-_+CyKMc^KAy2_qX2p(=jkyPlxa}F!w!xzF!Qls_7XbL%wMf1Sq^y#Z zjDY}KHR4C~;`Ko{42x)$6|Ap${J8?k5RTvfD|rNE#**&?OJ^N__>9nN>z#sg6Iv5l z5ww1l6c2b?VUUEY|HZKg5~I+)XNW>cIS~ea`alth^4_zaQD_u2cj=G4m*$$>tCr1U z7K>?L*$@5@vlvkZ)9Ih({RZJLEU+3Uz24~mz?)1rwY+843YVqdOcVb5K1%k6l45Ii z1+j81V1tXK>`_kgnV__ln+kSb&*p+K^*)@;;g%glCjb!+DtxM{>n{A(CF6l%ujVVg zNe&w`+5CJRa!A@Yfqh76h`>HiOt#KK-21aO2aW|H$aa#9Y#e_?ydkg&do9hEb z!??EX5RVz|2q;)fkfr-umY0Ghw}SV@k^f6RT+Dk4LPkhq9zbW~)nE$D7LeF(WcHA7 z6UR-LwsdOLU@tcp)QGY;WlK1#Q(OdapGWHm#($x;J1DghJaG1VwmTb<(dyZUjSM9` zliDV9cJXeOy}5|>wqq&ShWQZnrasHQO-E$7rSZp#XkCCbX#a0ezv!PvX(-Q?P>%k)X0wY0O~VC9a2& z{zBzBY7aUe2ip#iZftC!ir3b7N4y8;A<>U&Gqa6f2dw?gzRB7xyAZp}_X^=WkdW}c zWmJpf6Cg5gZEBQ212*1t%+4*Tz>?6ohc>?N(BAxnb>8X*Md$BLhsK62hHmkxwMM}q z6)wRmo_C4+c386K94m`;EhB^FJa4@-yzxT1?$DSS zakNz6jBS`mzG~-l4kxDU?FfSFQYEG+S%Bs`xBPI`h`E^~-+vypbr%NhEX^1$k7T4E zCl3IN3z-*EQGMCRrtWHdx#Q^f{0#TZ+cgC|76OG}8zrD`<;^muUS0&(J!hT~Nq4Y^ z3xbry5=#9BREnYUK{G3;FaFoTaPU+KWxA1>hqrKnMqbt}Zr_wg6mC6NsEbTq&0o&9 z!NH8_q1a;pTbq<8QCb0t8sYT?qx#Ey<$gqZ>Hy_|LlecaJ`cqgJol3S>0 zydt=};kq-U$}bO2SDX}_DK6X#yI zwfyHG#eamd#m$i?;~I!?&7)|Y9HUdP{im^R^zKf!-WP_%xC z8{RoWx$y=&%tD^obme12n61=Dem`#nb>IrudWizQ4-Y) zFNjNA4QSQ{mkMu_u?Jsq-iaA)j#mNWU!Ki;r?&yYw(dk9u8XX@5~&WJ*X=03A#pp7 zHEziP9$#nlwJ8`pq<0Y)8L4~4w{2wYO1Sa3<1*~k+{(`zc=S=J#aD0FJo^_+@n8Vq z2VUDXis^x;jkLbX8AHRWE=E!QM+o4&kx%szg07yEmTRrlwz%_(dRjn-+5o1AGRRJ2 z4q_hZKBhDKWrwhZ&e=`INNDb$&smLL(!!wwr%M{bT>|~(E_MIQV>7)&7t4Ly4@ zyEiOpqx}0OMS-E@?{5{C29eE^8bQJ)@M`j_gLph00;$cCr>V`AC{|Tffi2Zl?FIeL zeAp+U=e|{V!&FWtLUNfXN7|FVU8lOGr{md#!sj#HO-$q!F{5MFDB=CZm5I$@BTVf< zE60(wrE9xU1ps+X^usL~m-7j&&wsObGUDPq${z*6|ENiFZ;M7mX{p8^ERA8yASx_k zbFv0O(wvMk(ds}MH5DI~Vq(FFTJaTr6ntWl;ugH#J3G3Dk-}J-dWG!_j&p*ErmlN8WhT<9OJXAu2|bYs6h&8;7^% z)(p4~G#`T*ylp>k}Myig#NsC>ZOyJNQ+$K}*NiqwUuvs&r4DV#8Z{TPu^;oN()^b&kh*q8l z84ry3!X5&Y%A^Y-;?+;mj56XVzul2r2Oq?xJkMqU--7&Pt7jyR%3C7K4Bdb#$Y79c z9a%BFm%#(N^V4`7=P0jh;CrQ|fyQLe!kg2gmT2D>fOfe7Bfd;f&~R$JngI4=ys3$B zRwAKLyg=aSBf4JL*ew^vzRr2;9 z-g!&G0$!6jfrMW#>xW9x1Bh$mm?`ZYNT0*Q_%E5syayH1_)sfVpZ|h<8F#NlPJg>7 zfN4S<^0C}O@7`DJN(2GH4|u0uNQwq7a4JXE73QQmyY`PGXgiL z{x4B6vKq6fP6h=>uRP!4f2o02lnMO2!Am>JR-{?Wq4O5`nk%^ndQC`2n#Fjf3)p64 z7Q^fMEPl7>_9BrcizVKZD^L`#Lrxt4-x+7fJWF0(;x5YF!*jE`X_aB1rCJ_PCmV|^ zJ1<4s#!le`^-V(PFTvlGu6q*Q{#TA?40S1{TDA&-6G(kOETVW&HpY6CF&3jSMI@vp z#u!d~3F`i!$l8k*uF9L-N%Nh!oVZHJ?paibdC|on^sr-h{ZSHWQGLl0*9Q~>?ds%F zZ&dB+xAeb9k{P&Lm*c86w({#t%_EzS}ZkY0d+t$|2m!^X2 z%cys}S@NhE{I~Y&k3KIGZ$>sU)*uI4JJKf(lK&IgzjN82o%BPcHk3^ZQzF=8M` zA7fq_fjq~lmJ*!-Hq9J;ZT@uWP|y=RI+@WpJmC8mul$}9?a5ZEpQh#Y?VRepUF#TiHwP$Q4Fv8@W?(-Ks} zY6+ypZJ{uyy;C!Ir}0aro=l*L)1`ftRQ>cXX~)4a2gJFW`{=;b-Ns`$MdJCt>pOX; zjFsHJNkbN~d$)S+n2@!qKfy}0+XGG?in#f}s;u&2a>RgEqePg^6fLmE0rnuwG;0JA z*J3hofnWE>DE`c6#&QeAYlniWn3K4HPwXN$Y^1AZ_-pvHwV^pp_@O+HAE8tPRYt)) zpG;R6k?4*FHw-qQN}CcL5MkZqFh09d;&wO1xRnnZm!WfJ3#nlkeL zJG|{EHEZ1qEiO}MwsnSEAh*ZZv|YjB+~65C-|4)MpXgkO@6Hn@8W$2uSZaWkP^vI9 zNjKcyI;-VLzZ{=;MXEusngUz49u(y$Cxql=)*i@o3 zzmd^;h8w#vj>)r!pU=eJ@v0#On!mmDNj|tu$+n4E$^K92{0rr`;qrbr93W~fbGg+F zqGF*UypBig=#Ypv6dFeIGg+fM#48ERe`0biI^Qm;ap0gImI&uIGF96EFeo0KoK z-1_bI*mK-dsv_fxOMZJ9Hq4mV4fZW@zPWt&(!D6h2$9Q;t!Gk)wGV^0IdRjJB4~tQ znNdosrReUKQx+BT*edjlIlqY@JsDChu?`-<^&WBr(8o`lQb=K}m%Y{4uArlEwV~JT zv2|N4ecc~QpIQ*-=F$&aJEbGegA}TuS%-!z9v?6os)h;aB6HlUzSFE!=7Lo2al#irmv`2 z1!dc=yq=^DPhPQtUsO1XC0mSWdhxu!Ky2kGUe zAPHt5`IAJ~g841OxGG~hGF=icU6rb8J)q4aFI|&_6kHTErs!CYH79aK8J^tNha%J* zEfk82g*~CEt8lwFS`R{;WKTrg3Q6rGfRmyBsr=mKQh@4WkEm;B(Cm_@Ok7}#&L<~o z0dJwyJw}1eaTw!rj0{~J_s$_t&W4rR8ST4BybfB}dgZz9!3d@uXnz~~N@|&L+SuOE zCvHDCT;=y$!DCfTFg`2EGUp3;j%ul{InG`OR-_Fw?m%WJWe{BiitnRA?2}p=kqVzC z^YaT`-*iqGGRL4^E2$4|%REIKmoQSF8T+q*>pAitGTiJPuRx5`SUUfRUssUvb#jr$ zD68DtFn#dDh6K66CsMuEVK*%Z1za=yQ#2MX8iV|%r?46DJzpH`7Vtew5}Yo8(34%X z>g=?|8ujo~kGCMRkC!e( zy0$kP)s#frdbECQh%A)lCub>06E^erk|yF((AeO7Mgq`mIrlL?S;n<=;A|la`evyq zUWYGyZ>IZOoCMt6%i)BMw`;hqBfgklF0}WxD#F%7KVzvcFJEuW3VwmzY3J6X^Y-v; zJA=@UeJ$q~F$<`PV@PGU(s^U9;5ebL zwH6pzB}tK`v;QPU8mC-yAfdOI^&sEgN(^VO6pHa-L!7>Gf9C-U!KtvmG_nL|mF6t9 zGBm||JU;w%P7yqPX|IL+#8ML#+&vRpIdW|VSfjcDw{8a}?!reIe-0FtBZRmK z?(6MBz1<@t%6#Y}&Vw^a7gO9d9IJmjqnPWhHdO#5ZmVqoupOuUovvfw>|q-MH4Jd< zUmhJ*p_^uB0!N*!iyU0KpIXMfF*a3>7|B7@W2Y#sr?Y?AHzTcP$L!+lonB?$xGPEd zYSNTMm)~XD;%NYRa#Xk)!CM6!qbbKrwiWcYz>1xqn^dT0*@?&xsn4%$@-ZtfFhgia^DZ#7-4i13PM^`xr7%dH@)iXTl$6Z^JRe2BK!^7sV&3V!ml^QhB~HKX?kCSl=! z%)O@)qo{d6;R#x0d<$lUXuWCQ&sNN`!-EzH9}yOH3poGzIT2~@Oo)9!kGr&ftf8B5jhzxM?`-kp?^{}-Uyh_b=6c0xoL5{{Gaq= zqZAdXK%ng;8(JtV=whqR&U(Q!X>nvyLXD!aw05sK3vv`qhVr0?y1DsI%|3ii*h&xJ zkQ*{qFN%niX56Lgmwu46oh=RUwUDAhfbqtvLZMV~oWxrPH`&}A#)G@Vg=eQF%zs~7 zJt5MXho@}pme^p-O2X-=c&eu*^k2WAs+ax;cr2|yP;@CzsUhkYe)h4$SpEj5|0vV5 zD5Rq?Dnq0dP>~FIrRnne5S3wSTK3V-O_utUp9tF5dk>QbYW>N#XN<)xR@pV>Zvx8lCcH9wD{RG;<11TOX=%L=W zwq|~te6-FO#MiBNg945<1H5HUbX+aY^IQ($1L;{=65|odJ+!iQ)e=nIV$hkOfz0n!PaWT*NC$?b zbe!?vRAn|Io0Icc*N<3?A8O>rsz}7CCDe8Sz{XlJ)Q7WUB$ea>`jN%e2sItmwCpvL^ zyxvgfo9qc_1Fbd5n+zS_R;6}#4Kx#7O)L$7|5GQ;E2_Gg-Uni{rm(zTY`HA(hJ9U@ zP?{gl&iCww4QNq$I0;U4MxHFbb7CA91#;LnW7irFdOJO|#lfQgw}>7^7&afJ`jUmd3kg(ZlKZC8PM}0S0V3q!Q)(Ekolp z_ZRDPv_BH1>`F0K4EG$po(TKH7(oqjkx5XfSIy;3O%+{$U9mi9Gk!z&Ft>xu<~P4l zk9q-ntT?-X(MLYy9dToA`BKk#t+F_|#`uT$X%`BW3}qU#yBdO*lkcd}K>;gk3Z3^D z%Nq0e+%bmMi0pyOgzY~H#p!1o5fwjwsn{pq^?B^Z;Y><0-I-ozyR}Z^#Eq`Cb@>5Ec&`T>Txbw8b?K>km;zFf1l zImP%-?G{_Lm-&!US|vahA)EXl#@8D4WgUJ~l94mV@_<1C!RzQVnsWQnYwKv}XHwX@ zTWYc!`?_LdMU^gCDh0XgTKE(2{flFcGc&L;Bru|f6}w&0T3pt-sR88(;3@i%nbYv% zvxdH){hz44#lWYRa+E$RM#!Rvl6T3zcE{|J0jORpsNMyQ0eAaUFwAiI(lhSOVjj1cxu zlmz_m7^t|M`+gSkbsZms(eL)Y3zrJfbEmX*6-MlZ<@RjbI7<^Lv65fl8ixUcrKpy{ zKd_eyuW6hIBF+X(Zf{kF;#T5yM5y15FUAB=s**7k^mnt9fz=-Bw_djQfD|H%0h^VU zugckGvbEb}OjWl?E7vx&*|QKtL*b};@U^~YH5}WlE7i@%iCROA!GZ3~GR>U|U^LT9 zf`5G^d-g4^PJxys;j|Vh={@3`Q=xfF!-qw16VQGGsctx4L=BdGeMa{W>;&sZ3tJ5& z_~X21M)7QR)d4{6ZWn1+)Lh|nPGC^Kqy=X44z#(V5EFj{nJ_*xe!ANO7ZIhh#gBR8 zs_H&&^c?=yDaq~5Z;ZZZLhMWNZHT_pKgMF6+-G;Q1?nNu21Z0MeIIVST-#0VU4ITQ_}EAa*2Fe zK_m0+>N4W19$13oBgNz?W0$D0@Z;y2?I16&{A+o%6ncK18)NA(Iq(ILZU3qlRNDSw}DE$vV z%u@HXZ#{AA1QoeK?I@FWp66=i27?bj?0nnW9ksH!1$Lmqd@on8Z>X1;|C6Kji{fDv za(JJN-fqPNF;}jOktBz!fXfkBD3@b5`EO)lu;^&(h{s)~wjox~x1R~e6vcDk1Anxp z^YZtG07^7wSIr~5<(xFUI|zMcrOTaZbsM@Ay(fJD5KdEs9_z5;hPEq-2{fGB1u7?$MaEw{)5A*jPzB^o-@v4?cqHdTYe~kQ+E;-&(K+ zMoQy?!CkAm^Mqfe-)!YDqe_M0d@rUp@A&w6(Wwimw}XcN!GFhoY|S;t`VO!vfizDy zNcD!aVfi8i_T(!ot3{j=w*%Cw{J2OaZo^g3r+a|tzZ)&2QjASF4^5)<5o*w7;U`bL#}! zIiJ*6rkdcuvX-f^LWdL_37AGt$ZW3br-czneWRlM*G0ri-)2mnvBQ0R-+CGvXKX^K z{t7kxzLsT8P*A4;3~a*M-v8ME`$sAqE&}hWU?geH+pazt6-*+woFoVPJ3-~2F?>yp z^=qhhYk2d0-t}%i+!J<6l|19*&T~{9gJh2Zh`}XL`<4h+KYpOxmi}UG1D-H~B6}Ls zFe)jqU9?GP1BV0r@1TrdeR|>^+sL4;5B-K;I8#+|~vAu8U-yNPG zzbP$;A>Qa67v-N52MuNBoMqwqqQ=^jBr=bblYd%{Ie#HYh(-+|Kd2=HmqrkF-(_N# zEqk1n^^m6T)nFW57nFUIS&TSbAieqV(TQ^AUSJjXE&7er^Bly!bnspk71A#GP&)sX zAN{OlWFFz+Mc{!Ae1WH!%tU)70S&d2pKRxN4mcZc>I!O8PUk*uVaLuBBZ>G(nilzt zv`MniY@wZ!-D*25KWre}|Be?cUfWTA`|sLXV4Ibe?use3Luq(&N+I^T0eP^9S;=8y zkjWmw5Q8Mx)y>>?HSU92)@l;)%`1jSHDJUfEF(vT(OF;j2 z-P@OgO7Ck_i?=zgci%fPyFDfvI?h-$0qBY5oPgo4Sryn2Tb0j01XI)zN%U2Rs_z@J z`lIw83YSnmdvB#U{tushUttf?u&ELHeSlg22tGyEO&f$ka=uD7viw4B-^grFmsH)h ziAdpz3@suOujK)E@Z;(TP6l`77uO-<;H&n)Q!ZBunNq#lDNxBE@bg3Yo-FDw386&T z*|LrgE9>%{(9-oH$~^Z54+r=MG4gOrG20lmTM|H#>cF`*rS&MT3&ze@X z-ibn%D(TwrL?VYYOv{!zVTC-7i20tdqWq;dZCh}g+8ssjQ<`pK_%{*IgD8vzHNFE+ zRF{ezH94ItL?C;_lCxF|86k=8rPuk?6+ONE@epd(N;-D?r7&gQSoN1KRVnPNmG(aR z2-&mu7Mr(7| z@IU>IUxue>hm!xi#W?v>6ke=ePzW zLC)nFUJR_hHm4-(`tbO(CKPuspt&%(*9%4YOkBCVu{omF?(d#L$mTWy^(;U(WhPKe zj+*Cwd!I~-(r#=*{MyXv z1rwS3N#Wd0faml5y$qB;-`Sog#>Yn>ZZ1ej&w|LC8USzag&2Y$_ga(g$ZWrrf4lbc z;+kdEH(+%|m7+$U3A{&76}#JayBBnn0joozi_6l(O>>fApI4ijf^OOem4_AV(ot%h3ABa7)Acr7)>QbaU#sW(Omvit}w*=})!$)irMk_&;6coKMG-_`-@ zs=~xhb3q)Ld6J2`e$nxUDod`71eY1Gc#MLLgK#7K50@GfX=cj89%_Vh{o22o(kM#H zxoxH`{%N5*NWnfJLs``|Sin*jJ8UFH=~t-CB|YkeBuTsGL0^Bs0YMLNQh$CSxYWxw zA%^0jcBQbu`9@Pl#bz?X(}l0%0$UlO!1lo%H&O)fsuZuPR{vCKLqAnv8#k_w_R@5? z4EjV?Z;>yj*pLWY1mdM5!D5oBbae%D7*#xM?|Q^3Q>IXY!rM1?_Wi@Z^Kg(gc>H0G zumUv9t;hfdoZ`Mr%NuUZ_@@hY%toaG_CZOPEL8VkvzoEwujjJ`LF_v%&T)E!d*T=A z`=yG2kHJNDgmyPg=a0xAEWOk~9B+jM%<|(nxR{;531dmub8L&`q<}poh9s{`GqF}0 z`LOBpcY*2u9hKRk{Y|)-I@C*e)0pI{AG4A>ZC)YrDm<7zt}-_3j4+XkaYC_qA-hrJ zUdDRzb1FosaA2Co4!ZAHkG0*JQBjhASSB$6pp0g%X;Wkq!at za8s4@b3=`m+r1vH!d~6T?4Kif=nSsQJV(1-YAzx=S=`jG{2qTEU1Lv_4=V2|x%i)2 zIT~xsaSmgXVYTrqgnW&M5BVj7<^QnQAzfp_wOjh4X0Qv4GcldimSOHRyHF_5C+q}SYNi? z6ODUbtdHIgQCg@bT;T0AAZa$%Owe*g60x%1MSyyU))ue7(R+MJPKgxARLRrlfB2_Z z3HqPFPcsP?upRPZ^`>0sQpffSt;45Ur7`nHx?JI~P#HSmWLKnkH>ocHy3zHG!hgMB zWK=r52j5iIKe>^Vi>=zUzc2mQ3i8#Byp$~b1M4A**4Bfy23qSY2(8|Z^rw8qDZNwP z2pD=|^3s6*GW75m`$reuYb7IT3H<`ci<8~{K2w%rPwKiGNFiR_`1p+L5@gPp@(K?fBfG2aQMHKMWo35a<-^$^M-a@K|6yl{j|PC7o8%ecsDT;A>%48 zB3Y{NVOC2A?=jE%cLrfz4c|7{9j^$s!PKa`3 zyZOJc+{zh#4JkCa-;=X0{}5l6r9jmwVqv~hKPG=Ql9Z(!r>{~f>LFdXjj*8S3PU5x zUR-f!UUF@TJS>0<`8d01-F_fs*-<3BPGRK1uNr?fHoxgK zJX#?YRd^V)^ecj$hH8?B_l}88JBZrZf+s>L`ZU6yi=$rIGY;;{5*XXulf!FCl#+CjE=R6}7S zHgxt&{=o%@EOQHar|Wa-=WDkXieX?NUjTVEg1Ikm{gap_AZUrUA1td)^L2;GMrd#L z`q%74n8dVz$Bl(nP|`y&@RF%X%fj10kru`GIPmjYF2WesCTME`bU6_6y{fNlz!66| z9}Zb5{UBHEN4(h~Ksp930V4DfiT5{~l_p~}jrm=2-GJ7oB84L#87^kMDQN9-gVhyy z&zie?ea&c_6>(;W;@~X+NV6GA%d4liy2Pue(0f7 zL;CUD?nMQw0l6tm7wX zg;PfuEN~aMy-tJxaUm*R>-gEOI!VNNY(-&Um!eje%;X7H^>O$QFh?V?6|!&|CUCGR zFV6)gUbS)4>(DyLe!#eRF{hnS<@zp^ek$B?2Mv?BY8p{%q@tZZV5QXgcYRg%_zqgE zRw*PaLC*4h@^P5gwapevJ?vo%be!9H*+Uxat#T)+Mbh%a)z0*nQvQOndTZ{v)5hKF z%No&b3QZNL)|VNaUrOGWA|g04UB^aH%l~pun?#NHx~CgGt>|+{xNOY@XyrD&QkVos z%Vg0%b}nny5;oRu9@IUav>x9}cyx@_Z?9r%fI2_+xAo4=UgHdW-r056kC(f{evUzI zeb2a9*4(df8dncV9p1ntUNjjHboA%;VmX-E=HJOCGC9Lc|5g08uR-B-Bb(lI8QV0I(DN2i{{@~@0Sy6SG zNMUOfMwC%U+CawC?kIJI-F?jcWxCG3pzt77bB+u+ue2#RkenQ;;k(A@uC`j%b{qRJ zEon{GC{usiqW?#6v_?q#B0an*le}j7jg~P_=|3wa*ad6C2PhPR`_7;)W)kCq(@j@} z7Hwe?+yFCVC$>^foUui|*q(W;b5X=dRo(HpR8Dyn@l6+QsrC?cHUJ#*6LKqBNXlXX zzt)qV_LSFq{0kvq_{phxtZkxSYn`YzeNgHlnBQPV&&Y)=30b$j&TH)Mi;MepS65aP zM-{St7c|_h?~gGOtCw?!GPw_)(6Rv5NjpsvkDixrxN`M6&POR(Wg_Z z4aM^Q`hw;+E!5-lTf>6zb3oVIRF^aS)6$s2Y_ZPcq4gA`6?(&?fCcsKmxxnrKRG(~59sGVX0#UwRM0MD8e7mwM|0t^dBVEtI2cl!p)CwWm&e zTGzQ9<=A*E<6#ltLP}w@=dI6GNMPAX8#;h!1abO10~h(DB41qr7(Ha5jy-bda^{8e zXb-0&rE7|V;N6!l0X>0`PRj*pu%)ObR?4s4_w^dnw>j=b z9snq*00Sg~&XhIPvYDaU(x1|7FRGr;NQdXnjQCH8r&mH?!GK^P&}S2KXZ$0ketOk5 z!g0=umql?)r|V(mBWO~DHk?>mER|w;kievW)V}2 z+=iKv`un8^KG&=g38WMW7nAXZ{DHl`j=Sm%YmxoY3# zH;0M12>;UvH$UDyxkdrMHCdvBJDG?SgQ*AB@OmEfxJI~qwkh{K?16e7YGnAQje-*&4|s?jD?5^&IwB!|WW8m^ZN>ipV;=kzsd zPQs3}=;w>4#46(hM>~$LO1+y}t9wIXWRf{%TdrV1kd@{eP)F$6 zIRU}DZJD?qctCHl-IndVnQ`k40OPk#r;hCwE=d~^)CAw=iz#U+gVV-{&Hl z9s4=?8ify_p?|kT)ElvW)}9%)&%6wd->(XOUm=CFH?d{8_!;j7rJ5pbaKyWt+{d7R zji%aS7}DnRME|v#_@xc0!|6+JuFSLf-L$x&Gf^Qk?B;3c)jI=&e30E8c*6vG>Pl%u zT#JWJ#}BW8*9Q}?RJ~mNT+jB8?qWCTC!Lj;EGO)aU32E@bao$lqOemok3-Fp9xO&T z#l28;`?!4oCL&9X_H8yHj1jZMQKL~FKIu?S{9Z(Kuvne(g}LjYyPU3=A%WjwIxo__cF)BXma46U}3Pn=yfcI>^v|BzmcR=`I;38G^_@d zzz~$zmz6?TIPJlp5wB}39RpsV>7v3L2cy_ph7ch?J3<{O-`*h+?UhnJGQ=HLJ2$C4 z<@@E~UI?yV-{kYN1s$s3O0UboVu zj_%5F6r)J-q$N++jK|3*g|gJ0QW5d1s`U-v>MxkUGpWyqD2gY2BePaG zn4s2bVn_eA6lc{4qVX=jw4F>0LkvIagO;}+OL>edD%h;>P~1&M+T)l+fM%M=mHWZoP5BQg{!LiJM5Z;zNR!$-@}(}&TMu24p_m& zs_BqEspw0}wz`h(-QPS#R7z=xUofMeO_E8`xO0NCMol4Zlodw)gkR$gphkV+YpQ8|@oOlC@0 zpl{A3(~`tKTlj~T&F>S`_Aky$<_SE%uPWuJnv*qrWEr5?X;5pL;bxp%3acFm5>$`41AZI90%){ ztQCGaAg87v^UR|77mG;9pT&l@`3MXcwV9WnxmGSt?x-NIqfc8e37D#N7bxYsro%TVvMN z$Q^2-R#L{}+>d|v)0~M4Qdm0z5S=Ob4~j7{OXM6GVY>{T?yRVQyNjJN;~yei68g-dW^h2 zBDH#}xU?$|H!=C2Y@H)!K3K&~Y!QaaTuHb)lS%oiQ`;opgwN!A1MD_{b=+%Zv0nhE z5HPh$3x#@UDG){%cf271f@YRf6K{W*4PoLXr<%9Sl&?)~bQU5&VlL9kC`-#GRJ~X1 zc5xK7d<%GnJUxB3R(as(*UbOks()E15byUl>((v$gPIenE|t0Ey%VV zg~HHn{${JaYb^HibCBPsMyDU4fDpr7o|`Sj_AEnmnzv56afDt=rW6522@D})r{K6k zI9t}B&3u1BzonI~PX(PG)0=ch1boA4sJCUQS0ls0UC+q%?#TG9{97ut7LTRCRpb;%Fuee-RG7O zUaMB8scA1Fz{0~*WHYHw7eeI|Z$jb`<6gU6E5Ys5FyL@Q5F&)a3Pags!@eo8vqhEr**~1d~15}46GM9E~ zkqo7i`5KlG%0hm82~3BXpOhV z8fde8Ja|uR9QP&l^^uWir>;Mtk&*7p_UWj-dWQdWkxcb+ZB|n@mLPfGJa_)vrMN~- z6|byv1NQ+=xiS8LH zCQ{<@a2Iz_%DUAxPrScQyEdYXs5Fzv;GNw;bsD}6UR?$7b@Ed!Yhp+pwHTAxBouce zG*4%lDX*ZG&0YJCEFMmmGDgK^&D2ggeHk!LUEldlp{IG~MAT`D)!5yx(aY9ikHd`o zu-$K&l`BWWsrG(9DMl}3*zNDKsX#sVy!7@RAk=hw075$2FUzmFKaed+RT-C~s}pER z(sGEVa>l5^#eUCf=jvs~(RVT&RvT3>=37%UOC`|ghl%O9tL(df3((1`#MU0e)%tQ} z7H%))4kMX0<6xF%fTi)`+}*Q*4_R)gFj>A3?B#h!7p7Zm8Gis_gH4D~9IlhiN(1Ju z$a}{cbu88ZUTpPtv?|&^ka`hlzhAmm@Qe=aBU=7ho(&N?rt{T4LT=m$LS!Ff5`1UU zWX}noJ{<$K26Ua6{P?3iFH3GW=p*9I)u`89{l7WC3@5w}C+A6pe_J1RM}&Q+vv!LY z78Grg`|DT(ef$9_-&k<=C^2d-Kze!h&7!n)Gqh}eV}L2jbo_BE3;^A11q6ZG?}?@jn7u&diY_^(Y_e>QP8 z!7c%31SN#`i*79&qKzIyXoC5mTk4F^?TE-094?l<-)(Y1JW#M_ei-|8*(0uX-X6fh z>788sd~|J{cgH&T#aqaq!vV}EaW1&dI36-RB?L2E#}?r~&2|?GkGTG-61#kE-pDIG94;qADE4A$^*Tzn&Bz6O z_RBHBX3^i$UAy>O`XI-(6%Us zv#SJaGb3A<)Rf*Z-Yrts77B3nF++c&No#M)9w8n)Sn&y?XTC?Kd#|@%N|XU|5+IvB z-z;iEG9OI&u=D&SJOXghuGx*1pSa$~EzRHNTWr^Z2t((uBT%|kg?`2bj% zQ+Hc0>ljV_j@`iuIXAFw)OSGFK6j|Q=9AB^7Kxl~h-V^s6>}-uP|ljYk%<>?pyUIg z!W}$bi5G2x^YE_QPEW*0do!;A+E6d1EUF(YRgc`))q*oH$o`M-mfCA7o4H<+22SUT zAW>+hv?Jk!!-eGBnV(G88xvVG39?P9<#*YXKKOUo*$aV}q+gRxwMWRPuoFk>)On-K z^4}W5w7L+ArO!ZGy2j$U1N1wfpBNr+1d>XPW;>Dnuhmo-|oQCfbDR@N-QU5}>C0K0LGTnO36e7L(A? z<)&}hr~m%_vb`?Y_n<_CNNoAqBo!UIEY@ay47Y%dRnpr~CnEDuZLs;+tKV0T9u%QvHi%@$G51vhhnK@+|s751CA)cQ6 z6D*4doX*vGhDBXEApHEHI(oK4H@lNowahkU!NAnqP|+U~iq(`Nh(e1&09j$WMDl zP5}JJ{5`+Rl(5@M;RBWj9tb&(RO=9?PT^z85qif@**ZlJ9B%eN@QccHQIkvSa8H%2 zw*zqNkSPyxmdSnm*tlCJap;i&>T7f-|NRCUtWVeJ@yirb-nS9hozgm-q!|(O^lFQ5 ziXN;tLXBN(EYmx+9WXYgvdDnDVRUr%&)lyCqZq~EAvSY=p_01KrUXo7$ zXXU;I&6{oZ^~VT%Jh={)bHDbtR9$j@8ppOjXGAW?=jJG-_0TVvQuZ4Pkf-@JCYv4HYp zdJhzLK$7-ZA`Dp58SFVBF-TD%4x)1K94D5nH&*GE9g@9_@ucWhB3opm0-b+|b(B{^ zke%8hWGhw#QJ1>OyGgR9aO#xX$RO;JjD^uoqZN0lx~>>T*@}-?Uoj6i`st0<7&)J8p_&-qwUkh{pLN?k<~~ zZz?I;4DWAg*?>Ml-K~P)(jt$$+d4QUJDaAq8!6F?=F5OP)O6X9I?vqldS4FUBZ>qm zeWr6=kgcAL@a&8%&%%Loqr1RH`9r@M)U(9FCO%s`00Z20`4qD^17*DLk>J|2V?pl=~=SgeKQnP%cJf$RG z@7t?|XGB<=4g!zd%~IegG)F*eXIZdElCZr{oSas7AB%ywmnpT=6cNwMxy;*oU5lii zvUFCC++t4AIhKBN2C`{$YQ-*uBumXib}x}7pSplKw*tv-x_p@pphvhJ-nB2%>Iz$( zg-!Uat(!V<=jP6IlNDrxP7y3w%PD-JRSh}~_Qy%t$6<%HGXHHzTK)qWjw3qpW`iQb z(I3b&3Bi-^q?27C2?GGr8iDZk*Bn;ir<;)nd)ji1UEq66WI|?5oV$q2H}N>w(~O@YJiV#~UZ0 zG1aTk>qd+;L|uwBy?!b~D-w0El!Lole(2S!*38ihg`QP`(lrp__{J*iT3-M5g4;oK z&aG{KN2hd6CFyqgggW1q*}^hAEVR&adV-vwG}s+9G&cB+Y31W4UeL16?gpust}kDo zY|HwJT3gQIe=VE+_FXG8Bx!OBcwEK0_m`I>td z&O}h3unHhTXGrWiAZ!k!GtW?bN>`OgnL>8_h>lX=3(fd=RZmo#*)9Q=LN%0QKMa){ z5TfNm2H^D-TuA&u`0>ZYX&u9CLRUBHw3(<)g)EyA$5rLBA<0aDarTst!Z-` z1py|usEgA9ax@Qyyf}k<51}22+{W!)3p%!HU@TU z41R;3VYZfL)*%KvjuvoG=k93@#g6EZCeyrq&!v|=TOwknd5{=sYH}p?54J_^CD5(t zQGa-7TWTnA$S!IXc1R^J86=D4P+sYn4}TcaDYJ#XfNE3{gS-I*o+acl;i|9UQ~D~R z0U$$L;Wg8xQX9*$$pLqZ58C04RDYkRh)qm2*yu z_pcUxLH&0W$H1k_ND=3Ln}TCl;|Mf%Y)==J;&lM5eGFs{hy>o;gq$NL&RN(69cccc zp!ewiXQLx>|D54Uud)m+IYUhLejuk8Y8C^Vqg6FH&wgxx!#&Lit6ah0Pq5%SSg(8apXqp3>gICZy( zCaAaX{s`o6QDhV$kae9Jso}pA^=^5ntVHv}@>U zK}Mfv4a1K%wLk-fpYNG!%B^_`vT=L+BUjesmvfeflUF)n)N{X887Ii49KVH)_XQeO zhk~SYm2$EU$zejNl(=2bZ}nSK6F68m|A*@-o|Ak8w(gLV<9~`D;PqazH?|GLwc+;I zUL5%MaUF4Amc;GTFeg4#!7`DHGG%=NJ;QCk*WY=Mz_`b+ln*~ez2(w)N39YWZWtA( zGu&+y<1qn1W+mZcPyrH3?K_Z}C8M4iBs_D2{(}liVUy-7wu>t2q{3~8JHVaRfaR>B zcIoXEE^xbmnm6mK228{48k@G+$a;>V#c@*q(R#?EDLEY9fbsFgkwRzpq0K#XMrEQ) zFsZ|nN0pPs3JS|JF*7isv$L?kU338A8bH>M*!4vgZ7WwCBPHQF!Xw;gZ@Yx2N??C) zO2huj(45Q%MSTL+zHO|Fap3j+lOJl*ih-dtlid4+I`;QhA?1d*!c?|M<6zb`DwF5v zGv6JldxLm$NGE8Fk~vgZK@l3WcqY4<8z6HD*xXgTF^f7n2P_!+_DGHp=t@4t?X4)y zD{N|9?V(1Vy~yB$JQLcrCcm*hELp$AIN!LKecN0r0Y8Q#PXD$Dmdfx9hp!c_k-KzV zzpC~~%6m5sExJOW51P8J4YF z9X@>pLin1J>{IMw)d0bfW)7HpCxBK7?-0Hc;0dnmQ6;i9I%pf_!e%=Zk)kdNEk5@F zz-a(^os|+YalEJ3$rEAMKkFOZkO0*FJgIr&Ji!pWaANJX)~((Dm)MqRuF%H7hfARM zfGV3uDn==-Fd>bepD!wCcN7%RUFOtB`u6}}XJf+Hs0uJvW2~0!e*9D)f~%8WMBB3$ zRVDiye>U44nzD@Q32h`&tWY5xM`oVSe#7It?jITb)Cg2t*pMZOEAV15q5d!aJ`WZNVzs@%CNk40*Um4}Y&pDb%krq-x+JCd*o>Utdy zpGmtmbhEWx!w3$<8K|ufZ!5pwVP<6&O-w8N$74y|^zvwoxKMf42n><&9SyXb_amKK z(Upqti)1=oD72Q1a+Y*_opZKZpBF3X{^P zC$ym_);ekANLqkZMTTBu+6cwpQE+x=3sPV!|1oMvugrAqX?p(TmWpefna$?jG0=Qq zwBCb5A`W$gBZadm&wnLr4{*n za={l)??3&s1qP6Y5wmDY3Z=nYY6r3{)ou3xNv2yYoU0|W7xG(Rb^$lGCjynFs}q5*fcVY z?|%6FvHiuHVC!apx~MkdZ&>2rIbhHM*jv>GRh?tLwX-XHm0s9?1uhpeMmvvrIsn?- z{jzJDmA+LtS*4CW3>HjeeGhrwa=WCc5<>wMbqW9n9)Ne90v#QK?zR(kyez(>4n8nK znX0EMt~I{&FufQW>1G;ldB)n=3Y|1Zyxw&_GvuV46;3+!U&XD|xGBBS0jcn&nNjvO zJb2sgSqiR+p|L1khaDJYW?D%9$lT7x&5FvthoG%SJeCnGN*57ZJk}YKX*la+BYIM8 zP5Svm>gnj`CyWkjYOWHKe@4e%1)3qA_3jE|1uFDBs*VFIZ_FD`dvCfB^=>|d*T;Z|6PFdOBAS^c}=Gk$ZRt1&Yw!hM@+ zPyj9KLFMXbH+bYyzGpNCGk`B8O6bw|rQ%gK4SlZo>!XmmvpUj^3!lnH$FbDM*~rdl zR#(ckGT}hkP@L)Ul(=P`W=n2>m0ZWa0PiycSN_P|a$dU5CVW>g8)=afMpFb5Ow_#c zX|MOq>pZO&QankqRANQ#bP*)GkL(EJ)vlscZt);qOqvAtJ68gE*esQ{I!;Z@5(i5N z^b6@f6h)QBrmgI?e11JPG52lLH|k#DeN*xpo^S`?^DT^oWqC(~j0r!9TT9fu&Hyn|x!`$PVSrA8Z79 zs)#t>{IKnNkwr2B)z-AX&6{<1HQS=b*!etHC_C99+n0l>9zM)Ru%%b_fd;}hO zbc=Z<)|WLw8@tAqk%y-ZMJhs~={L(ov4;}L2=_5? zqy}m#^>Dh9SeV35dZu40jNqiR9PCiWs3@bIdS`+Ne{5zecL1)ap`!Kg{F^2VWp;anUI?dd84evHX2xw~yYb zqJODcYMJ)gGTuktiB!<$Z{+=Q2qQy43l7l|Dz)(cB2r5{N_^j*W~UI9sNfv0-g`pY z9D&e#^Tg(qC8@K|2RfcG!-OWT2s-p=*UB?nk10n1Xz64nPze{F_Uww~z@kNE!LIyR zBm#jqT-kvA2P!8T4`Qa^`hn80rjJ>`&z35>b|LJW3KtDegOJY_p*x92PU6C7!rBVu zXf`QBTX$&&sO%nWx}wqJZaMU{mGmN2l5XD7TI_*t&Y-_Mw~$K?uFf~tXy9js9PZW3J+PfmDs$!34h`ri+8Ob*-U|Yu=1=70VE>@(rvKsCN?^gNx}37B8 z{@*uRUeTh1D8oBh`D%>3NK^l4t|UKr=xeGYrfpg!b_2MetDEuAP4WJ0nbbOV-WnTi znk{BYd9P@{H;4k{=!2G%cuA8g15lv2 zA#v$Y2ZPvDKRhGvs&xDgTPoP|ANkaY(yHG&*K?wQQReanxgi#FF|B-vkpR@dfF#?< zS!%I5teOCydz{mp5%V?i;Yn*hE!ygSEL^eR_5$=}w2A6{8X%Ov&N~OUE|YJ#cMW;^Gsx%y+2#z%fr?b|Ex{)sMQS2r*02$Bm*;&Mgu6oP ztq<#URWjsDG9diBLy^*l&5sa+G7Pvo0-st1sEC;f^V{FD-EV1@vQ)COG1XAw6lwr9 zxTkkn7Jac|S?XtQtZwANf9FRXWf^Mg9De+FVf_v5^2+0%?*0o#ul_cz*tY)gm1%8H zIiD>|Yv;l|1mtDn*Sj3E1aYB((ob+ZlV;c>345%j1KnHjHEyGDST*A=+f6IM$rJZ+ z*MsCtsnN~1(xDXu{5<-#`;zKVI5d4wzc9v^I&Cr$?h0?7MQ`DjKswE*0f4>{QAlIJrHVNcqtF!YLj zSeJgBjB?qvdj~l9W9W27uH_hB1SDM0TSl&)#<|-z3I5AB`sy4~yFlDV?dX#yIJyyS z8Lrn3ue^by0{Bx#@$~03F(OXk;Mo-l7-Z=@POXx%Ik<>sqVGqhEG6cF@OL(}^~+DY zwn^Wdb1l=ag^MxGN`4B_sg<-YppEl@{ZH)d!ddRkEtodu`jQ#=AD_sEEr%E9a(7%b2x!JfXXCF z!fb8;KjP%$WLuMbd%N9M&Uds^Th*4>0pLgPp-M)nYw)06PVF^S?JH99(Un!2;!ct= z);4YlY&Qq6!G;>fV&sLI?tHEM>LqJmm;fhYf_Lkcf6?=ui$J=-eBhaGJ+sTVv)ReO zLn~+JUL#fPlk+6>NY0>d4FDa?vZ=U`)p$NDa92isu)5!?mknt{d)Kfhuo*Y3Ou%p( zOKxfhdD7O2OqRdMXWbn1Fq)7gk4DfZnlj*zva`e!iVTpq%8mb>H^;K z{K}Y0+nJ$Wh+050pf5>Y?q`YI4 zm#m;uON6_J=Qd!CIRjF}m;$$Ze%U96Je*UElh}yld%#wszz2_JEJKGm$oOxH z6zbTJPbsLI>OZ^)66X~h80yEFwB}LiS}x6ZHsO>82i8*2R(FvOw89MJI_PL9&Rw7; z11xyvN(pgy`e*TqNZGxoqIzPc*{*bBDly;vipSO{sA$v3;*MoJ*D&8N2wLDQE7$$N z`1P>pI`YnDpgciF(T}Tyk-SqpoNTIAEuXQVpcVTC=VRFi53o1ot9EYhnhwe8hqSOWld*GtS|7X<&!xpl11R!>JR-^pGuP&+BA28@V@;x z^^}Bc=G(s4BJH7RBsEuemH@0ADgR8UYoNnxB` z@3pMdPbS3~ro#4AzFW{piFSE3`s3d0jGMfYv*;=89n_6if+|;Mq!bmsKP{1$ab#po zy*oItzV#XXA||^33v;~W_-Iuh17*>bMiExxb-`=K7bizE&3XxsO_w;I({+m_*!ow5 z=s1nn_YG(a$mT4<<&(6q-6Kwj>YEw58JuCc0GK_YBnOyWOnmSFV6TbaJ92D_5q6Pu z9#3xHG&4vMs`l~hSeMM`x{SLkl+(%>$8g2%5$JYJh_U-32M^j}Das3yn?AUjjgf&?`$$QF~Al<*Yo7njBc9_F8Dmw=((Vg21FC zyq$d_%dm6Kk_)~SMDh03F#Xh+>h|}3TDfA-?EORBJt|F2Nf`rNP$F?4J^_60lV@10$sNEqRXRS5^3iN+jAkPJ1TCPo8T2rOqZKB>~wWqu){eG zOt(KjA&LNulds{B3|tVtsfp` zi-EzenW68PD=bJ?0QWjQffJ-i$V$g6z0KrHD1Q<_y7PGWTZ72zm%NOaE^oop*paRC z2K%Au8iEJX(sCq@_9?lbC|jUS%_Wkg-3uNF>*8vS&-}w~2&XB`bks`AZoS)hykBRE zuk#3H$yNd9?&UD_DXuH}(oJM-&Mc*7c@+9Y@F+MPPX4BzUJh>Gjy^=&XlufM_&XYP zV66LelsiWYeDFBia*E=3kh-y}P9~@9+SvP`Inzx9yYN{9U4G%7e8^R{=AK92UWTDn zTb$lQ_GkTH5+?Gp;R2O{zY4hRAH98#%)c?JQ#W@X{?OU_aJAhMJ-s9y(kTu+`+euE zusP1RM%r0;5N4g?di*`)W`53Zg=0_!VALov3P_@b(NpQ+JcmT-m?4KJ7usr`g;?72 zk)*3;iXi?8ZTc6msvgGOYRCTYv&CC@`&rdcI|c9vh~r&&ES)2`1Wl|-R#CA)-Knb0 zHT<+Kea_zXN7{@Aau&6}E*2hzs)_UlPY%VDtoVfbN~%mJyWdIX`;I|njJoyNW#U*2 zZ58?{u;3r`#Lw@X%SxqjhpzmIu(!9>Hs@UAz;k+~@QXkXqJ9B#LVIIDvDBMDK6Qsz0wi#sd$e{QCr6_%zNRj$ zqF*Aizi<%Q?Htmjkx0XH>&iO;ehc*n>&*-*Ei0l^ke02MFw+pY`GkvEBTaFQp10O@ zfD3!2{tdqSH6{wb!TLj&L%uE1pzvw6W#5>Hdq$b6$Z-4I;@oRdFX0)nIAxBEXSOtI zbMW>&CGrUBNA~%)qgyU|T@(F3OtEEO0<^b8YAN#yObp3r_gOy0tu5LW(2q@0zjI@< zm6M2eP3i(K^$x5e>W`x}q5CH3TWU&#@0?dA8HHx%zI&DDx3=Aln&55b@jq=4|M*qj zzwT>e9z-k-k?P*$${Jq@5ld$$qxIp~ST)c+uWHU){5fu|vrLOP2i1C?^{Vv;FPM#T zuxhz?qPn&GQxnawc(jA_55elaWrgX=dSN3Tjfvqewsx_m>EnZW4I?OPbUJ(&|Dn{g zk+s9BqEn`ls@qapCcLa4Y7aygqa?R4I9cf|%J5p-H&FTx)IOKj*YopB;}opF_kI3g z)ULJVOczI=KfXHG<00#Ec_jvHbQ*2L=%AaDW%-D|MD1ln?5s82x>;v(LqW(g$UPCY zj{|im%8*DhcfA#~`A*Y#JT58fr;{trwWSAHnkj|bb2*mr8h1VrcwfN-nlnMZ5++nT z#(R=&gWi*vM2i=6+sW>=jSWAR%E zN(m<11;yGP{GTXyXn2w**F_I|$$Vd~IAe-^J8rbC%YQk&a0Pg_jWyiT%?W&$*9$!$`rQL-NR`M3nVMJg zK>J$%IpG$+Z$&(9ANaYDzB>)_-xT<64xT+WDE-lTtU_#m_OBn*_iAB;X~C$PXj}`orLA|P|A;ywf8=m2 zv$>rTH4kwV$UoRg|0^BVQH90>qey=&u5#%7_5{=8GjjiWgv`LUjn1J6c`$jiWKskM z@_rokuL~2Pw#MkudSKe?3fpX@D1ra>Ei2aVN2qRzU zXs`w!*B*E(^PfqU0_q-~f ze9%}3$L)*BY>Lvr7OCyBv3_hN7O&-wuK)bWAEC9G4Iw9u0n_HfsVn)VQ!LB@gh&6Y zuHF_As%P^<9wdCAM!qaO-{fWQtE|c0*AvTt{)GS^+wcr?OLm9;6&475y!?ID&+00N z=C=wmC^A=rCZAJ8@SorUc&TJHBW)GMdT-xEhz z{}_0V!W4E6b*GayM8{ItYgc(yc+T{{-#o9AsS~m=6DuU?-ips7?@{0@~XN4oXq!QTn zy}p?ByJ?e(&?017cQX!@hFc!phuZNklU4HI8^KcTi+ne&Wku`q{ZvLm>iU{;NUkg- zl9K<`oI%yLaDHocC$m0wZQ*?Sbvyey*%yWD@NIkA@tM^nR6}d5Fd{| z2$x}QuAIO1HGL6T`K}Mof0`0L*f;t$F@8Z0T;s6nX8HNspIa9aU#5t4!r7#F2en^g zPPJ)}z1v$9!Xt)o;Ff@vElZM>zgku6bTh=tisd;*`U7mxmQibka!k0v+6gc80{PiS zrukT;+rg`O(|@H=x73!D_qQ zW)&Uq^ke6}EoLrS>#$DjH7k<2iT~=V#(POis8%le?H!G_Gc~@35|5n^eV4_Zo?ELy z`B6xE;EMRjYGG0Jh~X7rgq=X+7V8W`_s@7ivcJy57+bF>@;dOpe-&mvvxgz4Frk>A z%zVc+q7PH+fR&dK{a3g(y+Q}0Z7koHqZdFO&@D}CpTu9S*=iN*W<&;q|DT9 z=_s!Uew>8w{vcbv8JR2=Z| z%VZ{JKUP|Vu(|z;BYox}5`VMs;MAr*((Bu=L|KBInEa47yo7@@DxTizn51>ZZ|JEY zz^3^3a+w89Bi--sscfd+D@Rdu#*pT&i>HK}LyxYl`xmo!Xub_G=fb-x z8;_;<9Rm;b;YuSns{FOZZv^e#&477WJ)1}wrJN~&4c&q~{XkWeuCVs+mV$9Jz2T9l zgpr}iHz9i3Di9=S(5($kQ_>8(GUWWb)ng{?tEOg`A(QR6RK|z`9(-{%d4Vh=kWr7F zpwA)(jQ|NlwEY{L5;V83Lx~UqlF?dzFKmsKxanE=290dnkV%xxx%!)QdPQq}hpu^O z?N!6p#L56O(^mOuG&PWEQ>tyz} zXsk(!Hyp7VvBiE-(sTNR0C(*lku}*y8mV!XHQoXLO8XnK?-JcCz~FkMk)kT?gH)%1 z6Nx)$gSr17oR&Q;tp-gRR1oBIXz5@<^5igHCU58EDm+mU95feuc!BAVt`}6ywg8oP z1T^MV7vO*jtY?ew_Sj{f#fr-_IhBX`q8bk7GLAq3D*1K859_rHSOx`^sO^BbA=xm} zy-fNypLCXY4M4RZCHfvT66|YI zN#9A#7s-knP6|-HSD@|sY)m^kFqxq$(`!eef8qO?y$#JQs0xiElKSnLW4iLm0k`## zuF0$f-|}hqD0axtbz&>tHJ;tWFoE@Jt`mDk^nK-zZ(U|WgGMNkS3!GC4U`VxVcwXL zk<2?ty(OXyHo)7lJsTZ6FSa=CuUh&aX@4JSQMAws{THpcLXBJhi828XE5#;)cY{x! zV6d{mUs_wiHv_`cOV6&pvf{t6x5JcRhljJXD1y{0g@N*u|rk2X~ z2+p0XDT}1WRMJhyLIqp?0e5T6)Vz@&D!jD`&*q4R&fc7B{{Dvoez-#~lLoTHVRe!Q z-nPoMUz$8hlL?L#Sm#nfXJZ#klw=32Dk$YgQ>WnX ze)*b}*{veief$`%EJoS0-bz60k27n+E@OVBe`jVsM?GrpOFvu&shKrtJr%X)e7IK^ zeiMDk*Glde=ceasN%{_kxlcVMQd?lUJ8J96jDd?x87>3d^JXIwqmAM#>iMMLDgzw{e*t>O#PPuyve z9~gTxt@S6fntw|5dpN~3fjzUzIijOl`2+PDX#aK|vLkOfHeFHCPz_8L!9qgN)8RNB z+!`h*A0DK(3X4Xt9{h@;-l8eGkAoHbJ{KaY_o6P}gCF`Wcj&a7RUW2jGoGxkdAhd% zX#YmElK^_u8{tyB6Hhu(baHl-dv3tq#29~Wn> zsnukotBHvlUuS2_1QV7|_$@nk4z)N9*~!nh$mrxHUsI(U0NE9y=wnk;_WfN~KPIvw zC`9mz9*z65t4b(1ktXM)qu{%B*|I`^i_lq?ho~g1dLe27royMszBPqXwjYaA4K4Qy z-Ku9!ReVncu8f+5ilN`@{i|VQ#xhFtIv*?Z&p8xrUnH)dww<1ei+XCAJO_;I;>YuD zIkVRlBIxI2*p3LZ+9vtUm*uy;0OZ+-(%h>x!)bU)yu5#_i!HU~0(*4X=Xl-@Ztp5; z)_{6YUg&m+eG!^hfgjEVwXom*rpXo&?HRJKJdUCYHIDg z=+Z~3NAoLGw)#j#xX5*Z0v#{e#86z%Mv}&{!AxDVnbtG&+Fe0IpLnyL`+FoEHAd)! z6bspb)G+J6l~ws|svl>**{KnA-fEj*mj(``N;$jc$6i>M?gyOGCDad@h<2PuuiLd- zzGE^W2OP6bjuN{D+GJk8yRFaUN7v83^{$h6(+4&_!>+&$3G`s#&3o1K@wC0a?_U>U z;e_DgQVJ%nv)lL;K;eqv2Os)o7kqs+Hoji>UUA{0*$TJ_s3xc5y(yfIcKyg(C>!1Q zzK+=TR=DTdKTr9e&aTQ=?8>;J<@v+N6T7Cfsg%ZxdoU~9?K!y_vlghmrH7Fx$87fA z*Zz242B!e)|3_>%ct6V&zg~DI2tVe4md`~FO$>aC`lSiaCxxa>3b9tz)3;$W0~vEr4;i&`+g-5ED2%Xn9?OK)SuOQ!b$u~OX=Oqm{Hqe~(PHX0Z!&Xm zkCKw-np=XJxK_`7NVPjZ@V6jnQo(Boo>z2}HR{gQb0ms8cQwYAONAKuYCy3+h9;9C zNZ3)#1*JpZRQ3=ZnLxrxmf?^hr;nCEuF;-3L4^ik3OvRrHDUj^t;gLzzb5Y=EWe`$ zY%!2oYZJVYl6wc3m@%={b3N;(;(AWN6f6uM`N@L8lVd%EUmj7>>CS$yi-i9b)GqzB zxYd4I7>gd~LXV`MExR@LH18^;sN$oY)rOg%^Nnc2Ec}LtTy0J<=AE5yBbD%X-N#R4 zDPH|sXav3`sqZGe{&$zJnbS|pv9|>tSVPghqsI+JjDa-k%=Amy zc;ARlSi=--+N;;(a(_zpbh)h32N#-V{X_PBE)65MWqs>AzT++jANtGym=&khYd2ugwz@J)v=oPVcsf&>OFt)jd~SE?kVw zxVs_w?%+q(>B^E;?rt%xN}DGVtP0&U?x3$m>aJ_{!8et{t+dVnl!qtSWy75S_3JYF zjAES?z#8=$?r8em1dOuS3YKL|SPXe>S5`m5MM-#Wj`*(+P&4=gfO%wu?q&*&Op?l< zv7Y)yF}PYQZ*FAWEt;AutH>)-huw<<#{rlgPObeoOu4Nw`(w|&#nwhphH zU(GXg{SW>&w#`<<926kJtPZLk2a9B}jH>G9+f}}OXoU>Uf3c`Zukj8OlXF$;lnG%6 z)0D;zRU6)w-V!3h61ctKoniAdVAc#%=IE)CQAIKjp*6#|l8(D4mSGt{YjDxOjhY(ks09_n_5eO1psHnL)U!?NjxQjnX+m-zpaz?YI z0O5=E)k2*$8IH<^tHt&YFrlUE1jaQ2snM;J-LNu7ITuJeBq7?9iUy2jxs`j85B$TU zvCD##HUO;aY9?kqyh3kflS}nKUBS@R9E`m;xma2hnNIKn7XgVYh5BG=*3bJ=ql4cX zT?Qkh<=xOjvdKgbG1*zkSrm&oOopR|=$uXXDaq~gAU(iS&Am!EZO>+8MA}0RZC_pk zN%Kpxd*o1#yRh%VR4`(a)QJz&VcD1$%;~Z zHG*2TA|D68UFtQ?B?n)L`mzw3*axuxx1fl7y*z1V9gcv731i zrsi<={S13vUPNO`s*jx(&7|NgDn=KE$#tS7bqP$=9+8Uex^8m;VrWq1^3PvqGYc)s z7>`ky9j3#wcZ{ErI;1I!sx;kZS3OW5d$%SgXmrZ+q*CmngJG;yOPNIoA<#D=uHxvr zVvu<5yV+Ygh2qB^v#Fq}<|h9A?T-g{^3T0*54cM1-j8XI^$vDYak8qKqTzq$LnTMJDG!+Xn`lJue`TN)Yz)o+2nE9?V11=(2V=b2QOIZ4l;RrX6XNhy9--f zprywoHkOb1EoN&Q*pPZiJ#d=~#cGeb{to5(dcuJ@qT_XH&Ouh53#Avi(p!2HcGpF@ zp6c*n?ox)Oy}Rca@RU?HL;X%L7d}5`w9CU83J#QXU-8 zN=VaiRnGe&k|@<^rfm>ESDdT1T{BJ-l}xiPH+yG*|IuAE$)&b$t6>rd>?!!^V(q~o zp^l3%ZO8aPfM1Y=s9Y;erR__x1o_+mhn!N}`B}(CbGLw=;4xbEnHDE!oozM`x(2?4 zj!RZEwj*t5YDb&rw?y@Fktxd8Fv~lvni^krsEX-vi-DshLdX?e-u=p=9;{4x-vN(O zhSyhP_7Sb0kUq%s_GqD_FA&ao=@@CIa@6Lm($vtc-U5gP8v67%TM^nEw!+g^erwF3 zFVlYDOZh&3IAhp!wToP4nz>cp`~F`V;Z6_FL9g4z-|SHcnn^oPChLNo0EdKyCz^@7 zh$be{ANZJqc)0cQLe_pnI-n7fPI@_ngS7Oz9^O^Wd3O)?b2-gN62?P|6ml`PzyvQI zA2e3$x`;)!51z@1m*1uJFr(19CSC0Yr=_d}_~lD!v|FiQ>cY?%+&+dj2RML+zsf)_ z_>E~FOeGv;eX5Rvkc@0?$tTudzW5(S=N`@U|Htvo?lx>_HrKg?Ld+$%vdz64D&LaA zTtX!wNs?{mvQQ>nBr?>OE?=#Zq+;%KDMXPj=9)@{T;{Uv_xb(1bL`AH+volHyk5`e z8QO22tToklT(TBNR^t2INIJ5K6gaz&6dKdHMPmHBb{AR7y z_fMvuM>D@b+OV!3^C~an;g5B^9@w=%hFNK@eS6=QvLN*%YRW1 z2?eD_GrEXHhABH6n=cLBgA$g>^5kTLr#u}A`UrBpsDI6m-6H$UxkJC)4njSU^`RvebLdQhG4yo64YI+XjL(&+nx?`PWHd})yGsh- zqk~4sY9retYP$q&h+|f-C6`{j5Xm9{g!PW5r5KRfTZ!PTJW2mMYiZtO^s!ZaZe?hM zOdJ%tOC4$!amRWepoP>F=knKWXR~4sZQ4}!Idxm$oI>>uwT)PdE`x^|`v@^S6^MNz z-F72RCyoDX8>K;Vlzud#>>R+uk8aWjikOG*yyQ zpKF_=qKlN>eiC3?f%K8_t2!K|VLNK~`{p5_5u9+%+-dpmyeKHjGivJwPz?oO$iLfs z__W~13F{ugj0#@4ZETOhAn2xd(6&%Q5y;n=s}n~m&JooZK8yiR%83d|h`+0bhV??L8tv1ZJCc&t@rBfGjb(prA0%kOhTn4=x|uu)%cm zd?EemC<^1zDpsp2zgdu^lFV@EZlx*&)nCYX3HXsdsjj7OP1iWO0eScKs@LrOO};^) zXvomD7Z%T%RqY$w0$S24p1j%&iOWQnexn>W*D__5uVyCHl72f+vkTJIrIg_OYo5j1 zT+ibGsYLmw6`e`GC0C!J8}Ka6-iM_v^PHkd($udTSA{bVWmp{{@YmEHf5PeIMs2QR z$jVGg@fC_f6o@1XF{cVv7XH4$lmIBbxS^aOQ;4C!9>n zlM58MryX@N1>_BKhLZL40BFt+D|fi~B15RM6N8z4p8vFc7BZzY$6k#FWD zJiN2(MuQ0=eH2zo96k6W)p@DwAcsOEVqY>wkAd+cRP`fL3rmvOSN82SsKX_Qfuf=< z=Of>(h_ps^{MT;?=ZK<5pIiKaT2Fh|Q}Vc^YH`grWKIVVc2IcRKl55?)2wc)2p4KMqbnG_5ysHWu@|rE>29uvMMj1`pRH zb^CO3YI6Y6`uks<{f_3d6V}{(LSARkPzYt8i@3A?8|Gn@CgxGJ>?n5s(QuxP;H=GT zmxtIpa$>{LP-;&^VbYM%S7Yy_$~l(ymY@=(1rSrM>ChA3W*rh~HTNhnh*aR_s7~sF zR&`IS(s`&vv`gu-vWVFh1}Gvl=D&Xn9f1hUXvED1gPm9*AM+&hFwS_PJc*W<^G>d>2Oe83m>LXF61e4f|#mS>5q^h+_y(2s82a?Zz(*ka<8>H=a; zmrml)qZ(IT09Ycbn#ie55aPLHwca%i$(NZgCNN@Gc3<&cn?) zy~#r4e?N&V^et+3O+f)IUz#)9W;3AbNoN*e9%PrUD91}oh3P8Fd1{}>oOIEjj$N8w zQ5f8mOgbfzLJk$Azw(>?WVFy>jV#H|o!t?DwIV;-m--QMrTv*jER8q@{a1YXK`*lL z`W!37GrN*1|M*^rT+sJyPjg;t!BACIx|tYawgkBeb9}FOT`w{18u2T|9x`QVnQ!?q ztD?7QG7>%mn!H1+d@P!PENIW)OOp|CH&v6bnJ+9DB)$e69zra%Gw$Ro0s#BHKVW_u zOjMot_XwkYsPHP;!edX2GIXW_o}(04T%^Q3-` z4}17h{SYn;HFLGTp#g`c6GqWu(j;0<7+~R2dJ>`NbWH3__4FmdHorT@COu6_b}kY~ z*4E5D1L5YwpkfdSlA)zV1wiD3jwpY6o$r9cFTK zISHB@jo#_qSV^mzZM|;!*v!(y77+`h9Q(Bezm=1;P^bI?04Qm!Jv&+LM-Wmsf)2+l zF9Bg?l^3{mV5jWT(_0@acrbS zcd`3r`!b<-l5?6=TMaSU7=MlY&_HnJq}6mh%||@;60RPGo04<(^m6}zu;YTYWitrKwD@%P1+QuPeaS~J;J*?;gk+~(h5Uz z2=8R2cMe{tef)&Q zGg)3zSB}MBT(FX@@@J0QqI~%4PQmQT&j@&6WCQX=gs>ySZ$Yttc~WU!FU9r3Mb*DU zZ2WIVb-mGU{c5i^3q&;R3TEGk&e7OTM%Ytalwr6~PGeS6$bid%4mC2OnlV6IKi+Y! zc9c>Ti&c#XwgnmZ$8F3j^@wotGD`JYK0jBy{%N-e?ov$B!}x1La}6?Vrw_84iaI?* zDrt)VG%U*eiRGAgOJY-g-m<=h>)a_Uwevu&)=CKr02AUtVVj#EJd^CalPg*AYiV5h z;b5o_g5|Zo=AF_1wL#oUGH!Ig>XmZ$5r$IYj8Bz_FUtJ;OUze@Ll1n$+F3 zr(=T~_KYG}v2O9ldYyfuz;c0_I|aITTELM+SmcOGWPMuR(odPEmsXKrPaD5~>}$Qz zkw8%$S#I!`s;TSk1`93Vp`W{3+XyP5eW-Ko?w)C*AKDngMG8ieo6pFuUd2bwNY#vf3j|(C`0Tiq8>^8w7u2=G@ZT5S;UHg zXNy;|nT@O88RE~Jurtl)-?h9n4B27}4ag`+QzA@~_`{IDFx& z=FmptHr}w(kMQQZjhO18HE*WUyk=IOr&KT&G}Qf@aU?FroR@)^{^8Z@tcmF_l>>Zs zy^$`qI{CR%<`XUO>vHLus~=(fJmkc^WYMB}2@ar*dRQXPlut5Z{>XonRGvKPt3ACM zRO?@PUbI<&sfICx$FAbe%ql!wrxd>NX(j~Efv&kL8MTc07PRvs?tpEijbvkmeH}<6 z0)ZcJ9{KnN?r!_VC|kW5LZ0CUqUbStPNiuN2|u6eD!giVMIY-wDk-J(YL#O=LE3G` z=d>pP)8WJS0w;Edrc{R9*s}AGRFPsC~Lmt zW~K9AH+WBE>N{*)AuIg`X;xjo*V)2-y3-4*5Gd&3_)TZlC30Ed8qTaq%qVHM4mxHj z9k;1Z@8`Lt87Ih8Sp*#ZaMC=fx;%5!K25g=S1qw}THAD??|qXGK@PC%Yjath^!BGP zzddOIM{_QyQLbd-ZURaTj}0dlt`Rv)pFf=tw!d)cHyikIgW|>2Qq~;f?U&Ovf;A~> zL5c~SE&=+bPNU@ClbII||6Us`Awu2GJywq$6}vt8Ebj$4&z^-GG0$m_ucB3et_esc0io9>#yYy&I!-HSOprz~Hr}NQ8>Jq=l@N3gg~n-HcP1 z5@LZ^3Ncb+s_dcc-Tw6M3l6=OiI?oSukP}GQ^-Fu*+|fjoD{utu%sq+$;4>n{jAk*4}vPn{-a&ozcxwEBZh&>-KfOX619Gdh<_ET}pCF8_4P2C7jhy$vX7o zo^^m@NVXbV4G@bQ60r)yzga&rZH`IVRa;@VKOmlLh+hRN(_Gkj-d3e)Rdb)esAP#@ zHBP~CBYZ$n)`Kielqp3+SOIU4hnPzDr>UI{jFdMP&pj`(l&Rfky2bPA#$TH8pGU3G zhRbUjKb~FTy<-1PNv?pU4y4YoZ+diYN)s-bKJ3jnJ^r#PxR~j(rHh&+lX?8t-0OXs zwzVXv6KUnogQp~BNZL?b>&QOMuwdQaeiFp%Vd6>{%}`HGF?D!>^h`Eqpg!TokufXO zq!RW8oa&uZ&|gaWL}X}c)fd<#WNS1IzQ7M_v6@8HM@zo^A2B)t^5%;|>8XJMum(Ls zm~kCKfZhs>W@+C4WKP(6d1|!^nUTwu&W~DQH6C_i+^+{RzJ@$go#A3D$2>(~4MSd7 z5|twv43{k_?8R~{TA4^7WrKAKN!jVTNrXcrjZK7`7AB~$N6fVz{u2@9^NR6f*#3sP zMkWg@I8f7EmEy7GMBn?o!$v&wEzrMxV?Wv}&broWoas}EdaMn(1gdxIzT>x|(KCeU z)|{9}Kl+&XA-u5)lu-iZY;-}JQ1K~x=0JpMqs8>*!v%){f1jv1D?SxjpD*JaQuU0C z)dY;VQ8-dY0JWjX>mA!{-9^zOo*aUQN~JlKH~2SERyw{xsE$om+g_w#P7UDdl8CBb zYiEL4(SGZYSE%%}#L{sJ2KbUkzFwN(FPU27SxnltBk-9$n| z!-9Vu^jQU&s{(enoEQ!CEcDnyem0>`MG5Hlmj`8iw1RGex~coOfB~6leFRo5-7u!o znj>dcCLr8OC$jN@`~jBfx=L*?a$J=f_EYA9SCbpkg{KZgTn0$li85;Ivnr2)7Socv`($yDU?u!?)qO zjpT^S>vM}rZ!M&ftX$SVGb&yb6^%*KneKlz z7&HIo2+G%fMU-6;TkEu%NNKvG#&u)7JNydhNyFY}Wtqr-8#PO=5mRQr9_6Vrt4!L8 znH*1=r`I?>ELc4MTPZ9+Nd*GY|L!Oy!Zif%1Eqhznd7`9-W&f=-;@s6(SzmdY?Q3) zR`|1cD@GtQ#~%{Kfe7c`!3dS#;J3RO^{{Fj~6;Jr=|0g zXb5>~T|CDIpApJ^0>Sf2QQ9ZMTsO(8NTehR+Fk~VRhW*zH}{=qS&+hTEz6!UNg&H1?TZ` zKEgET`CnPd=y-%__KrS>?@Cr*~0iS)DSAQ!aa)r^-7T9sY2^q}|Jc&vL(qEJ>dg6e*Pkonw^b z1ea&c-L6M6vj79U%b452elGZ^Wg$*Elye_*Zy)5C(bOv79m5E178zHQa3>$@no1hq z^Av?7a~Zp&@?v?Of|cCk0wCeH5Bc^LrZ4@Nf%Rpn{yXy;3*f+?I2a@5`9o2$o?*0; zsm4t8C7n%Gd)e11K?lq>8NLD8W`a8| zdgf(n=h7eP11=V@>}{Q_@+f%QH1G0?x9eXoaLOcR;F+xSU(z|`>vEtw*8Bf*M>j!y zER_l-??v4i0zSf-SWU=hwaR0+S>V%iYM)Cm!a7mH>^#z9*0KqI+tP9!r0B`^&*k+m z)`K0lU}pQH>EKH~=&XOjdlzr{4OozM;YVl(KfXTqS98V=493+0*rP=Dd&cx_0n#P% z<0VrmB7SEF!}EyB%OS1!ljaaGKk!8=YoDNv)^gF@_>7+3AUoek9|CEN&x-I_CB}Tw zSlv|5w^)U3JGS%F4$vdDb9q(Ht!JNTycjj8$f9SiS8v8D^9GNWjVd_-+Q!L{rg zEW|Gd@|~-ShZedxUk))?7qS`zCVD8dCv4agzU4&Pp6HYld=?LO=G31ruH+-G#5jLd zB}xbu^ktRO3mg1X@;O3q=H^SDX&CJeFGudJ#TSNh|UnSYyT4N?aK3qvv7GB5*4LXhxS= z-ae2n{mvBr3Y|^V{is=M5qWHTNFRZW4(@ACEqVoUJcFwS!3RSeoYC|2-^`%)u8g(9 z6J87ZEy+(&5YtQ8d~GTk+z|jpo?dpI?qJRp4+@-TRoMqbp^AH`nmuo`3&O@l*Qgiq z+^pP4w3O=&N;CTmxoZ~nUSlRJ;>bsAji1s+LY^HLmR{LTCEe=CNtl_U_!VCYgU|od z!sx5|>SDa6^yUyiGnBQ-<%N!C4BTy~*Gu^Dl&Ut=TvgrHJrYEuo(QK^1W08{9hBV< zXSkQOcK(%9O~RfpI8=JFOvZiK+NclEce6gebq{2+G@sA(+Cc+G*T${F=4>AZuFnxq zS`q!r#NvhRkf{C0<3%8~QqmVimYGxIK>#0m?ejo%mQ7v9i{Hh5+kr6Zm8X>&)wS4f zJ0A6>s(uQor+6OB*;hA|TaceCE4+s)5aNP^q6Ow4V4vHRr9&3)2dXl*Yd%z~n_m+9GS1P%xY-q&`X z;Uo;ad%pQo$>?tt;idtTty|o_?@!&zZcX#`Ogds{cw{u?4cr5DS zDv*}WNs0}(p8dz zyt7LNZqrflwPr7#B)$6BEu6lDSK$ti1UMcU+tb%0sKlQhaoSII<&CRNful-ul6=5d z4$4BGYJH4OJIQ;YA2n!}x(8^n{HydrN225L)_o3FtMhh#f5E7dzF7}jpFg!(j}PX&Q$&2sqB z*8dkHX1?OXx6QGh{9?3_kS@6awt=rLo3auoo0sjGllHTh=3*Hk;yKuv-AXT4WtcRu zzTRa5u@Xv!ODe7hV?;l58peVWVTXG&UgosKzpZHKA#eg7at5s;1COe$31|Oq7zbY$x^b8*HyYz5FwSbuH1KXy}J$essKX6ganqu`76fq^0APy?>T3>v&3?kM$jfR8F z3d4`y9Xa!LXuHSjY9ZAP=!+L1M*a=qKgC5Oib0;27kMwteb!*sMzH%4)F_{G5_DIo zam!6_|HOSJ3$1Rggur^k#f3jIOhXE7cnctmdpzhN4nWqW5Hz=_CZ!c$Qb?q}HCHaf z_B(5fGAer_C8Q{LTuhAU**BBnfBmAeaHs#}ZkGFLBM^aLx0MwZH0Est+>7UZ&IyoC z+Y5`?S`UGyXiIq5)`YE<0B{XcJ_xePk-MJ;>XIOy-&4C9b~Jg|*Wv2T)sl&M$@q=s zv_-DSxYGp|EEo8c!}mnROa3sTrf97e-QwKgbFPX+-hjDi!>vlKC=S?y?BkKE&@)Ei z#8zHcyw=Ki$oqMgH#(Ve++nb@09&8J_ z@5pc6HlJlxyG=i&QQH%9G*7)Y;PMZ8v{zupa}jv|9e2kk%I*UxAgW(hQyC(o1aXQLCz^WMLKcNCh4M`(1 z-?;@<0NcxyO;DyoCFffu=j1${}IrR zk>!0shsne!{{+^ontovq{k!t@rnzDV)=3M+aLw+Uf4Eh5*K?x=8P$B|PN~Ofr6*cQ zd$_2{VW!I?MefEm-b=K-ko$%y-mnAuK*Q&+17{iSP`dmVabII%@)?0@w8&B((V4ah z;_qLheof8XXc7B_>GhmWcU4b53a$9a5D?>Hil{2H`R&h%K*1zTkW=D~+<3`(AEbL! z_*h|&QRL`4>O!8Q1wS#7g#I8>c|+YUGGVi}9@RLT8X6{D#KYrxchYJNO?*vDzzJu} z0au^#T#j$F^E|SJ^@l<-{D)jMnHi2baA4-3rO01(N95c{j|b0f4|b4jS%y&6|H^GX zTd3oyKMx#|Y_6KDabk8dC`ysm@L{>fQ5O!t(YGJOVJ3yZA+mAgRqAed{&CwnnC$U# z+TN=Gw6wXzR5y11*Z3(B%0YmFiIVO6m3A{4hpl)|7$e*6YPOo>eEHiLo^3*-(3EP1l@YK4YjbXX_YnlaiecR|Ly0t_}uO5ii5)w%@#_)cdydLxq+16f9){KxF>4A zgDVeFr6VJppNHvErPSN22*)!>O@dt(+!=j|6CiT!PTlyUFx@W=xcLFErb1jho%h(c z6b)yd$|Kninp*mRnfQ~sRUs|gMd`8cl&@EV?!QEtIo&MM6L9T+ZJI57GlJoraB3WU zSauUuAE-LahwW%obJ8u$@hNc`1DW<957i@-Sx2mLkea<6C!#btusPEl?pCv~Qe9WA z$UZFR*`0l`Ql37~P41)+avH9!# z5WMCE24h?Sf56Lgm~AEub-k4@S=LxwHSOKNC%vRsL5fY0+w_&PwPdjyJfP(l5AV}< zQ83oIkm(i4e4;LVt}MstKOQJ`cbIg6#?>jAx=LR)rG%ixb-~keR8b$(I3ac3UVnBV zw08%4$md(}6DvJ#!rH$TU6*AJ03Sz%oClgg{}*W; zDmYW8{v?xnoDZ}{Z|ig%!g_X=#XPJ)NS%KfDUZX$Y(|`%tJd6ue7$GNC{dH()v@hI z&X_&yZVgZiH9Y$;7$Dd-CWDW&NjFA?Q4>ojvJt=RaN8!+jQ1%M>8x6>%aCJGvv8L{ zk%!QVQw_*qL+fSYrrD*&jkO1g(BsT=3M<3GVJ~L`{sP0R%kK}J`r|SK?UT>g;`d(Q zg)o>f_fpg@+G#gQ(&(WN8jQ<(_a0-m0F&553qL*_h4q(+XSo@f{%`k0#Sbe#J@B>SFw!!OuaV6y&gOk`-EPrlTO**-xa#;|2} zWAb-0ufdM7P@j8{Pjx#0`%g_QBsw}e!#pV1C|26Oy9D5swK2(U+sH*Z>chr3^wrgQ ztz)>qj5O0%W*7zZjP9IH1c)_0L-9|N<$gu9muYo);_2VUdVs^t08)$heSIW{x7B3g zjss>tOD-xBy-v*r_5HeRCt_k(dj!;spPavnD0sGfbK5f@VZ@#O*XYzAE74&n@KgeF z5j&mN1Ol!oG~D2~lIg8vz?tA$>7mt6t04rXgwexD=orYOnvL<3TMn>yaC9E-jGac9 z$+aBU8P@(8B!Ju@Hn`vyV|Ou{zn?8?lq`9cg>^69=*BO*XdaJwB^m;yVPgv`( zkp{uf|8DC3wctHIH`LTHVuvr>TW5hye(z{&uKipuod|giy0+7JAq^BSeg20_{`p6| zD(Cm`8zk@(`oS$3^He72efmVnYDaT(7xU-wARpuAcb^#hE2jn-J9gPB$8WYISe1*F1OA%UiFgedK`1#Mil$Zm*IFs{rN<)AuLu+*KC%UO&7~*mya)45y#` zo{%(7yo#^24}O_IgVTKJ)=x%b)3mSqT=Q(&EPotRiQ}Za#=TSA@27xXRBrl&#lIR& zzoXcE(s;C;bCgUnU~=<`iG50@1R^$t`Kd=J5HRnaQ1sp)3#Mfu5Bq9~(pb~`oewVY zGPEr;eV~NW6E=C0%TtFrk1>2$j&OK%v#k6jv{c?QH{0Sb<-Xya_%!v)=7D;}LxNcy zv+XntI7o)h_23kj2-p?V_3oFWIGV?CplziK=;1RU5~EzbdG`BXk9D?@jA${>F8~sf znkpfLvDF~Xt$N9NhVn1qhtp*X_#ChH-wu53l7?=9rrjmIrlcev6+yQ2LNc+|3NfHZ zTH&tteM&XcO8NDPbI1WD8M&)PW}$(L?l>8*H= zVW+RD9DKaCLYbsBn#y(b@Ox9%2({u|2+$TR$iJDAWf4`9R{M6+@$#2sO}*Mjy^=Zj z<7r=CSnORrHfRaeNul7_XJ*|PqUy{-L(1!OG+$8kKb5F$8eSXz_EJF4lffisrsw5mp~aKcoMs6Tz}nYShly>*p( z7JV_=1*$OAjD19dN{TKKJOl19PdFD1nJ_MH{|^%+$G!1n1%DaMym6ost-zk0f0~aV@B%e_*2dV)&$y zA7ikUGKM~j-&{wWaz8Q{TK-LGr7gXC=_UJ?NdT zX-!vfgU?Fhd;tPw2@2DP9zMG0PQG=cUt%LnXUTkS`<-kt!KG|2dO z&%fo4N)U$b_zZ@O?Cm2()D;pF_q|`v<+id-A8KOwCo&nJM}Ocp2ms7!m@G>h{T@UW!Pjob~14#uUcV1wLxB=%S;VSiH6rnvK{bHSuIJJM<=ciUUkt9^ghmLCz`j=2&69fjau_@R7$sguMP@eXM}jpJ=)f}IlVP!xwF@7J@?Cd?5IpMS8N_>JHbC46KrF#*)ETD^CoO; zi|N#sL)$fueTMG`zuJTh7ey0N_Dry1)_^`)56 zo$j->_PY_n3$t$La|$v-6_#Ye#;g{wzuaL>vBohPMHqb`yam3yx8owu0d@vF$;gSN z^eSw#ut7HHzeM_< zO0Pv`CF&~0+FPF|zwV-<#LcUDtnay`1Nzc!li{K(t2=AvZb2Rgo&8bg3!bupA7_Sl zbzq*gpT20hIlxfmVbyZD?LS{YPc`k6eEwpN;SdfRxopJRNnK$!gkiC++d0BW(fyd) z(h{i5c9o6WEcaiChC2b1NOs;r0W1KPvz&C;K;JFQp73>>l=fs}P>J3TTbjsFKk9AR zxVz2Lc!js|q!z_o$KO`vWkg>#nY;O|`A*Epx!=KcYm~jtNH@QS2KvIrsn~f-$Rn^+ z>85vBNEj)6o6cYp)l0EyT!kSW+x2wlL_+VqNJz@$*m6!U?mkf`(RI^%)*S$-IT%Jz-dU-bHJb({W`jR&m65@Nt)>h3H zV*fjF4Ih`p=WviAs>F$d^edp^>E$)Gi8M-lyYp4%{Kh2(JrTeK(TxkyYr;JG`syeF zR<28pM)I+@jW$-1#1vBOYzeF7TwunZ$iZEt6228Zg_kgtH;r@d)SVw{RyS<#Y|7}P zx#!+0iF_#v&ddB<5em7*p3nT;Jx-MYq6biBM)FEl z^?Beh{Lc`6oxZGJXpKaZs%Yw!)C6t6W=6rmQYU7CoSv-w?ge-2Yy1xsKdmbv1N|~; zAqg$lz{uPZCRRGTVF0OmLq7^w?re2W`@~gcK_JoF^)G+9#Urr}vy(57eX+*{4Atl4 zvNQq1wT#Xb%kQ)-tA#hM)}7FAUFOqr_O)1j$Okd_r4DXH zsEf>wE>KR>p+1y(j&gpSnuyH2)sEb!h_;?Eb~(GjNAW+54=Csl(gszvPTBb{)fU#$ zZcQvj05>dvjRFKY?$1inaD7bc687-YIl_$63K~4^F>r*x35^KN4El+3Tv3Yup_Zet zb2djrT4|sCxvW%sKCl5;^O6;h+h5V3R^*krZoQ%zw}PsZ+KxnShM0kB`eg*(7Q@zh zcBlB!4Kc%?#p?fwqUkeUNt>A`M|GU_msICul-R1)!VlbPXag;9b)A$D z+dL0Uq#NM{h0jlw(B7n0PF`(3X)T?l)2a1aS0r8Dn7I4M=9CMWfhye>&%Fm%wKAfL zY9F~J#vx?n<(VQ=Ka)n2wUW@pS;}P*G@zeZRd7)LLaGeXJYrjk-b)>n#5E0!?oy)K z(`b7$Y)7iBW`1l51=;&i{lTX`rzFZB+MWGMs1yL1e^$dt!CLVFCnWYM0Z6IQ{Hu4l zmSqIoL%&n<7oYvn>Eii2eM5+kM`}(;aJr&mnW`I7G47)Lsi(XLt;TKA&`sybh!?ZP zmF>XY*uYlTIM_DDyl(cV+#lH5Eqb3bzvBm5sh<2&|jSRW_&~5 zQ{z8Mm)%^_ny%xsmuJnkxhiU0-B0ZUke0?5i)KBRRp$TsB<^OL8MZvf#)NB+74pYk z@Eo)bWPk zwcN=8*WRY=5em1BNcGt0oZZ&Iz*d+_*D^yJhl4y1S(+V6W9{EvM1QfYHMBH3Au_z5 zY%m3-Zb@mmcJ$8F!4S1&nr0Vg@XgSpAFbPuWhToR&G>pH2khdXWz(N-QBO6TlnFbvyNLI$t{jH&aXt=vfnOTfNrEUAUCIx@p5%1k5JI&t#fjaYj=+d>PY6l?)GYY%yM@g$2B6{UVBe?z<; zYM*4`=QnRSpD=KSKSzZpdjyj$c{!KLgRHtaI6@9)##2K}v`E4~;^hqJAzB#|Lvkfu zatUN1GAbKNyCOVM33&a8saqY`Ikc+4#ylJg=r@>s9udOU{&mr zwmU|Ho&vJQ(>%DNeZ)l_PM$I1%znEFc;4|bZaU%6q6Uw7jP>%ynK z0Uh1)FW>}UL$=~cy2=`;yIc;#%a^9)U-)9WWB__#?sQ>g_da#qqq}n#=!OC9YN9h$ z1oWKnQrNZ+Y&9A9C$e`#KTqX!#0;xa%Gd>D_N!crkK2m495d zqI7MZa=n!y3!XH4#sB}(ACg6SqC@PxR-P$j3`l2WG6InM*6Njc=GXKx-R8`)DD>+< ziotv+lo?6=1Cn{TVn1IK76)tS@)qHqRSC%Zdj5;A8s+cnR(+p{;Y7bZ>lglUv`g>2;C za6!^CEABI^wTfP+WWV152&H3UAsN&R^z#qRD^FeDjYd5?+)|tj@?ZC;ABnwFC`;R? zlBCPrv)vdWF`BmCT4V$!H>t_hpZkl6Rx}8b8g+H?-55ZlFo=?36bX;iCCvjoMF4ni zB&TOSqjEzb1&$p1U%3Ua3ew?O zv-wbx@`9m0UZmEYh@7d?^Xgj5ZO8P=QNxZI-brV7&yH`x8qysB7YpT5iUX-7N_5TJ z(<6ZS2qpDSYv&HEugR3kPv^ugnhiUn40H4lPk$ln>eVKc3xaNPttBo`WJ(o6Z_REugq+!ZCl-?ASV;E90WCOx{xMeSCl_JYZsn$1bEWB*(BI!6HyZlP;hX!eF(WmJ+!MxJ8g4OTj>togHS~A z5ZgfbrtR|BU73$kGGx+9)NxNHqjerEz^4SZ*rez<(H?2AtK3JY*h~2=n(_~w_Sr>~ z-%D#X+kcXlr0p1T;x$%>0GYx~n1JoKfRV@r2`wSinbJ1oS-Ia!a}3Nq8AfP?3h75V z_9=b+>%1Qtr{FwIfm{zJ!>{hS>bXkWT_6!1P7wsMjYaS+MbfN+v#C(BaDxwo5KPNe z)%M(-W|M>ArC;wB^*<%%jiGJSsgggkm>yEw%|^6s-e=6A-JEU9;5=x6Rp;BbHl_wu zb6G}#wE2PTen>-m&X9s9_AAitlh7N;YfZ0?m=e${q>5!-@95^wb2<<9$C_EY?v<4E zMj74z=%ev?xV<&k`l8|>JeZ%X5(>IRVK+00SG5T0*!QBNLxo+ zL1sKcl=bu>{|L^D77Ku-Z=Qn7bM1tA_|=v zlN?Ak$=OqZ4;wM@R+YP9CoLk5MuhNeNQ+mU6czPOQJ6`WgH)dg#T|bm2A1V(K+x<_ zZ$XjZR)IwoSn6$ey7`Ag@Ar#5^>Ll!lbIocZ{|VBRkcAqTFAnf^*ZHo<9f+Mu^3jQ z6A^k;-*L<1K*)N@^?RD{V~+c~b(S6BzK${-vMtg3rqC<5$M0UQ7hA)B$Y8V)@gzN_ zm}OGkambnz{ekE2>e(OPYVi=fcs+G22Ra{;`PuCPf2eFvA&+&>F2|t9kW*FCfYKRR zTl#WhOnK{ou8i30jPGDg$EKHF2k&~g?xEAuHWr$r_=%C|fqSTak_M|ipBaWRsV21* zRKpz*33cxnIk#mDcvMO{M>kBAJu5BmqHb%GdjRc~fPgk#h?-3I1!5zI6wIn?28O0l z!MesRd+T0uL7^mIWXWQIzj$DL$nIAoT`jdt!H3!waq(|pSDXj@+=8$i(=JXSi5JfF zHST&)hQU%lIF%Nz>p1LO(D~s#kRF$ViS&vP)bMb3;H6iAU^r>+vb`C?s(iXNwEqVJarYEM`?33cZmhVUCaRZrui=70~(D^}(qZ}09` z094(+#9+M17A7fF?^RdSnM!-QJl@`dZ16mI3*1$!nsr2mj_tRd?l?fHmr*YT-Qjs8 zIMt0v%h47VbS-3>e1w&heq@!w0lP_t z4&UA3oKrf+!BY7@;>7$2p+eMD9a{MJr`l4|ks}yuEN9L4c|(sck&E8%dIQEC5{PrH5L3WxpTBmy=NK8G zU8^F8hVqiPnfmszBKu$PbFrlPriO@y^u{ILbBNT%Em$><2v%Op{XGjr0-^7z7oZOq zxOz9QEbI+FKSqC;0PU9M9^nA&g$lw+lWuSdW_jHsmI%4ekXiB8bY5Q&>zMWWG^P74 zOFT|MECq#{p5(NNKns;%T}aY7sZPh-^ltzr{Cd;SAU-^hkymn6XK2cvP~KJF~x>kjZ*PyxThlA9kr27T!5T_ zTmc(;M-`Hi12%>2Q&4^0Qm|vXnz9dnc1)h(m)LFkK@M^LxRP{#Idu?j74qVM+Vz(L z^di$xBDr*Kaf@j>`wiVy$X>9}2ZqIFe3zg|WE`o+?Sk+-%v4DgbQAG%0w1pZ;Z81K zBdx7`gDOBe>&|QzF-GRh$1;jZX;F_Xbbf5|JylN~z9V2W2(<>f6$C)6{lnIX^`uxl zUBPVh0vdHa&({iW8T6{*x4%fy)Sni+^3C^!&|W5Ns3Bn!iZ?+}Otv?{&E{@)EU^+v zN3SD^7tKn_OOg+)XS$~;X4*) zB~k@h$Co0#N_0m<18t9t2TL9Dns%wLQ5(^7_H!`W_}|#BUA0wcc)I;=#gDItW?%sy zyPC2Re#n;_@Xgj?XN|6dZwxSslBDCikbVYz=>^PN_EM?qNLnZ7N!RlGHCsXr=~gp( zd%DV@oJ)`=NS_>)eM@6;M*3Gu7!qeKm$;hcrd!?1+MhF2w;(k{XHf5I!3k`v{*56# z@`*)x;K#Sn`xY@dROTw)U5#%Qm*gDT*3D}=9P;G- zW_yg`v3bHeVJCxIO4;^1;F zap0dB{&8qWqrm}toiOC56W)8d5|3Ov__p^*{ka3I;jTxegVarda-0dB!r^@Ja}}Xs^1b_5ysfvYnIuu!K*JD>RdL1-MoxDJn6GuxTjO z-SUGh4`*iJW)K;x{$%|CbO z$tlDu@Qr8H>Ajo&C*9$nnYNEh;u0$L8c)oSljE3yRMTd` z7`Oq~6(ii~Sn#6}NgFjv6#7&?{(`yf#tM*}!Uj+@AP#OZJX;`Xkgm6V5A&2#uSv7- zDj@Ci)h#s?E!7V0Fw`@JZu9)E1$o`bKkO>Bumt~)qjQaC^8f$%X3W^IIqcxH4TYTM z5JEO*ot!!;#GImhg(L~v80JupNe4MrIx&(YF{e-}N>M3?kQ~bSyj}n6_uswU+2gU@ z*ysAZ->=v6=?f+8BV23rJTzNs`3>uV{=_Kpta1=h=*uXsBu*X4DmwuK_bDpE*Lc$o zY?3kdaY|CP2K>%2y1_mBbO^=lG|M3)kc^eh++){ zX?K1B4iXp2A#5)INerXylDe|e(*jK&Oiisjh&&@;1ZkArp`>_nRklFQ8d%3xVkS}Q z;#9U_;i}f^;G=oazz;o7WXQ-Haz=A=$xCE-|6>YKunv=Nx2Zu+{sbIR6-Ks*R=Vwq zF|5I)W3B&0%k* z`V;-)Butm7|25KoXaOVaTjG{%2Y9?xq-#|tbuyB#SDo@uBM(zLH4iK{lT?jcae_x?)s6@By*2Th8p8-XK08yFc_#FuD7Xl()d) z2AicI5>Tvr5LS2_WXU$m!~5ys{=eu38u42nm_M6@4yZn`ih{+wgf^ezOd!g7H;RiB zzGe2k_GQ-EW!WqNj0{%nSk*?-H<6N&dn(sw5Sq5dRzp|cr##%w{Apx!p6IUJy%vN? zk$=x=nC*O?sSz&ZwuTE>Fz+WF5tsErVOUPlpNJuggj$!Bf=`i6tg1xY|17G<@ImCs zb}P4?)2TPIc1DG(G$mc_Z~9ii5@P-f>)@}t_KBLLAqQ1B-`jVKog_zz@VyzM)Nl8E5nEsa( zxUf@y;mTw9aDtsLF6zB*AJiPv*3N2ty^D2eZiMLL zEgUBUt+QhdGh)Fs-q|YN@kL*_bjewUrr5DwYu@t=1cT{}budOh=}Nes2=r~5OkL%< z`i%WYrf1vASs!K=z2$W#H(Z*P3fsO4O@Xb8?3joD^47LnxqgmwR*+Ri5IN+lssJAY zmrG9D(7V}}HLlhvN6-B{4~g;8?4K)eYSDxm<9@vD8bJ9yVuk6Tg&*1JqmHgI6h9MG zYqYYK6DP4Q7FQe66}R3M%{QsH8bkuGV7kk)(&%K{-QOlp=gs(3*W)6@Nrte>NTFLr z>ryK+H5iVm-R=U+-a=``er6C;DTW!N16~}Le{Jy|mPBoLPKK$8peGrMKNA&%R)0wO z@L|&Qq~|SYWtI-s|FoU?(cA*4f_n^z2>V)=BInu7xb2$YE1ts#r;f@@H=!P-Fk_5l zqMpEJN$3?{*h~o>havUstH;6;urJ8w3f~jziM<_R(SG0!`=_bH`+$!*IT~s72NQpg zQ;nkeOdBWH*^tMmk+Y$rQTz29*Dn-ugoQsd$MKPXs>0&do>hfo?mJv@*AQ>RD2;I$ z0X}%fb?AX;^5xsvE@5pGgmC{usPMcnzSOBODYHWPi8`H-K(N_;c}F)-E$vsWz2bZR zDgv0pdPY>F$6FzdnwtQat}&Pp!e>ttJV6-n+tb5LWX225-UpcIyK>$^8);nzQ(3ONje?yWy;;cIDiGakO>;Q`X@cYH zX~dxs;b+9+mwMy@KXho2Yk*x> z4j;_;WVQbJQzsF;dg3@f2Qb>&{jZ*G&3TMD0XBC=Ko(-mfauw9lpMR8zS`zugWs9i z$V5ICvSJoOPN=OD{UYSmQn@f+^zH3V#UnyrTTt?0Z3P9%T7i%v z3yyB4(LM=~qoPA+SSwmN2cSBVdH85^k z6647FOZ844{Fn_Ox#lnA=n#U;HaB(OgT|zkBOYVVn5e??(Hoil*V!r1hi2@xtoLh) z7qv+>fNSPl;yiCvWl^Y|0QCJ;P3G+9>^CUhkR2mdO!ypiEF`$xPtS%TeS|ke$K|za z9DiCjzsC7W$87rY@JwmkH5vw{0RH`-JuRzwqIi$&D7w+lF=$fdkFO6c-{z{W+5w$)PTM~Da)(A>s83ht%z>=$r(!!_-Ez-)E1pfj)Ax;2!3>{*x>g$#s`9E^ ztnuH~E4hTW8%4u{cC_Db;kpl|cPKoeYpJl;zVrgupW?@W@!b*G!r{VdMXec$X(jbi z7Zs95sV5uBHD<7rznIW&<9-9NlQi<<_EC5(Wh>K-%gWgP08!0OzY3runOnfJQ7Bno3xv#-Ks`a;+$V+wiY*AhTkj zg~xo+o8uF0!w0d{9;P;Xh4Ru;d5kepZClRX9kb@#CZ8SLN76>wz;E?%t<-%l@-uJC zByjeyvRDXOFO^r5*Xt|p=Iq<{Y+j1Lf8Xq?fk74$oemfL+MRGFecrKAH#bk@OgkI8 zs6vYkN1Tj>o3&(S-6$4ed2VkDKY`yBja3)ViFiZoGH|a)Hypd3_b8Trr`W%5XAEt- zWKkDpJ$dNEai}@@{MdgKi5GXU4Nr*jM5pH&1wP4K%7l2X;q0 zK|AR`I?+&T?9Fks!ac$8zkm2(QT`@9@+?qNSP42nVrzx{o%eLPxIcjOWgfGqSbYn8 zXI1aKm#O`*?1L_*_w(Iz|GZUpA`MB8Y`jqjk0Ewb82Wlk0TM+{-(<^OaIN+6m`! z`v;sX?q{?uN;yizoD3wvNP3HH50qr@{4ca!ZoDVQez^$_OH+i3`nG>(#M+s`8q_Ms zfSJpKI~_P_AE?5viYo0|y!n(HSD?27)=!2Ou|Rp4s*(@$U3_3qr50$VS~WFXjtLGO zH0@=u4V&~y#)Vk9TqQUMu;!RRn#JE=EYQE2nS>gFldeY!Y5S%6_uFg*)=M ztRbHuKMGXujP2*pq_7mC74r};zsQuSKF_MO3=E`O{{fm}w#1c(DNn8LU)T2uN7g-x z0m`)4;y&l{OV~Sylpgb<-tGu|xNUja!H*M!_dT(klOZDf zKztCy5)+oW7q)t>0WmOo5}h*h(8qs8F}hOL-bssSNt2YJaje{jZr?^(3l+ye;zFd{ zs^a*`Mn#hSi=#^pwx%+#u1`|kSZ$8SYK!$y!gq1T@S*f4@%m+*lBRObI%eq0zpcb|q**=Z$ zX6{NyoH$`0f(A8l({3?*-4$yY&G5r}3W58l z{G+-mJf<{TAF*~EOgrD(YQ`1=^x>BA`o&!ayvuYK8#D4;wKVVf$I>H-DXm}%_?iZEWF!QqSS3``FU%)ZbsNj!C&~@HY!hvgxKxw$qco~A-WtCj-aK#c4^JTe6A+_ z)fzt=ga-wTMiacU8R}|eQa(IuNyS|>$9Q~(L7hw5gNp9>Gz@?i%gPI-kJ2KUK5@@sprKiu`aYqa>NNvk64=ppuJ>F|CQ)) zMIN+x;yJ?&;%{FZk4k8&OjrZBK=1wb^wT2il8(yHpK4lvqnegi}A60a@ax(rW|ilcdqt;Q7ymNG7bTxq2)z_gC*f(pRKV^A z`3f!cPi9^mXiZWa8?k^s%Y}Z;1Y8p_U?92G$LKB_C!oVgF#Ccsytu?6&v+07EbT}N z@OG*6*!sXj4W*`s>cpJj7eO)dKG+6@-Zo*^1#+aoLCiJUz4(k>yO(x$IzYSU>oJnp z#D$k9j|lGu`89c9^HN;AcZ}-mBrbgD=hHDlv`VLrtxlk@y-=E&3i4QNy8MY$PYt^_ z3AdYhJL0(2@5iL3vp5h>t$%do53swnQo=4@j#f~()U1L`|M^spMF<2bF$OSAkf2okIX`~H{k4v zkbZ>w-kmqHDWVfM=Ap=$Rq?;ze9G`wxVBsH3h~uHR&Vl?b0Yb61Bsm|_+$C7?_$rD z%JyFUVLohW<8)wiNy0F$?Fz)eR^*hSMLbLsNLo)K&>o2Vhmh!=W@IfKQ53Wqry`#s zEf`BupBG5VhB6`gTizLG=YEn38{e=a)yb+Kuc&a{@EhXZpwT0P*5~pC?DWfVXbYF# z-Ye}Y%lnJB+xrk=uOuqV)Iqo3m#c9^2luQ{13eRx@cJ|IC``Fy(y+FWq2y!ytx<3@ zP?o+EE=Lv8^Z=cAjYXBn*brQVsR6>hh~Q z4pL_nsC-u0Ppf~w6D1F?Ux|FO0Fu@vZRNHzjhmp?I*uQs<&C(pxYy*O7v-m>{bd=x z7iB?>6Cqiz#~B|cq!#B$=7fK)+KM;;_l1BK_g=ARl&#R9FK>_TBbP{jVy4IveXo%f z7>OaV)`p9u&l<%JZGrITK~bctQ=H~D9i^ie$eY+phk2l{gO`hp~0sVFCEi-KyG5Zx*=`7gN{;5{NUXT!3E_!CrnT=b)#l;S*$b&c;a5dkZN9Zy# z^sJeBCdf%oTrKHZ5&LbN*{LaU{3qrXIsBAN+Q1U})7Rds_|6AO zS$>>IZ9^myCLpQ4!mHS)A15T7ok=)XX^rQa)pzDe;SXKLr;3MK(40vDJPF8c};G(mLsx8Tl? zbUr}Tw7|OzrCW~n@R(?*(v?ib?hK<5g5^z7r{urnv9cu3H{nJJ%wV@03Hv*I&1Ec$0Es_av3WohI zgTqXmvfHDCRugtb4zO-#@xoKak+T0(G`BM+4{PA8t@^9E)=p=@0PqJ!twJpMA)~lR zjYVij708il4)u}}PO@u87N}=H=AuNZmv%T0;fnmY_;>H5kI6XA))uVIoBK{B+7T@o zJZW!42@rN)Ao|-?GRpDv0^h;$7oy_@;F?}qMCE!ud&^Yf^<-bmanM5Ic>%i@A5?Oo ztze>_6FSSV9VA^Z@*YVa68M=3Ym}3!UNdJegR&O)zpa*F^I9`gQx~*Q?p&Lk?+kdm zS*U$uC`NWdo=b26Mw7lW)UFMF)2wjX z&g`pecjt6MEnjcOF7^+MvVIAD4ar*;&Xl)>lzvOyA?czj*-do(OS^)N zW|D3x9T@9opoAfdn!)WAB6@G={>Ab<;}_1ef9%+bR)4L<8YcyvItQlIYzn;h?ODi@ z`wu<#-CNvVgZC6l?`9pWDx^x&D$EP_d1`2`9`32DCRBDn&Jj&%W{S9QaX|{>w~k?YnwU zOv3HM=O0ve6&2Lm_g^Wv&miduk~WIcrMC7xcK@hJ<1a@Jdj%%Sf*0x2IOE{=I>Px734+l;>o8N(}6Fx~&526M!Y zHOC1Ag!`6JBgwX&|B3e>`bkoCQ38lM*=-v^@xtL&>OH)3XzPe~AG|pp5?Q$X(#+i? zi*)6WK={4gwN9qVW`kqzim2g5-(h^yd zU+7tI<>a*qE#DRsJt_ZL*W+J=-nuJx2~{M~(vW{vm9jLZ)XWQHTz+g7jUvNb_msa9 z-B&K0s5DK8yZ}P~ZvmQ#YEPA6tx4#@uJaFz1yr!N(uSK4J_}R_{(1gS)BN)yZb>0p zn>m!$q?Dcx{djI;0rt!pc9NT7G76D^4R9P-sz_8<*h2YhjJ~g zZw%O8HS~RoE0G!NeFrTpb?CwkR({*@`Zuxqb{FS3@j*Zr<4tRk{|xiSh)GzsWl;DB zlaYO0jXXOR+exu~&N{ZvPXmD2MO|8|!c4wN>v84W0%J#~0~PY% zF-j~hNNr~o9_bc4$rV4TfjW3SYlg`>DxnHZUGLl4<7<9Em@TK zrQf+w+lrrI*JZoC7@}QKcpjdnv|jXOhuo>9;ikmhwE~%nTiN5T1&H_e^|FNc)RyJ> zBIxmYt6G(8pPdg`Xfn8pyKl1*cDMc=?GDG`=vAYm$Y;2ItH1<_aek-oZ-##rxM7@4 ztcPoukm95AEOOEB+ou+q1znrjVOSTJuDSa_HW@;i9D2dz#%A!j9;>0Aq zf}*z_(oOCAxBesWc9uNzcInxYdQ@DT#*|f&uvWaT<SwW869kdJHS*G~jaVGJI|&K|@qx zE~Q);CFZDba;v|uZGAYNC!{duz*ZmCF1Q4^ekc0iO7+!gMs?z zBYbK*@T60AS~FyLu`RTX(UX)#c~{(PeYA)9vvN!7SYr7UH6o1G0T@!ywK98A#eW?Z z^oLCSw``L0F2Nf zET0}O8&U$Vk<|wS|NV*mn3p4B0}0ef_3WA~nc*?&F@vbR30V1Jy@MpanR|ab``tlL zG5OEBv#HYelGjCK2j8{aBMw}9Pg!fNOjQdclg4k({S$t=M+<4_x}gyMOA$fw2tqrGtGC2Pk4d5<#BraL2HuXeGAf*l6!Ev@=W6xH#d`HK((ab zkz86r`qF;@&A`Gp5wqa1&=<~_`V_R?ZZC(yT8Y@d*ztppIP-+1s zijO;OXH~*I@4qb7m3Me|K5rniT;0x-4ta#E8n!t(FRoo@8f{ygUwn-YEM)!|i6AWE zb!u(`(e?>0H{Z4orvEtt52@^U)hpGP-#IO%-LVG@kw%}#Ai27NRi%}3TGxdp#I=l| z%FX1c8j=*wzxp|)8DYEQ=Bsm5E91e|*SWog9ccmK<~59ZuIEwy6u~zer7Er{oMx3989hGU%@a{c}pict6>mAI>tLeGO znSJc~CC$p53F`iBeoV&)-p=HxLM?2SKKP=!85qHtXGr&Pacz$J+6=DVtcXs6Y9NNx z#1zrlOwN`f%h?2ddbPIeg+2WgB4Q!TP!d_d|_XMCtc|(-jA*>+h1%^>4HR z1}-u_>k9RFX<6m++tH4dmwo!WB^!UP{XX6*$jQ%RpA;dO#6XACgiaMF+>FHgq?fra ziNIhX)uh?ttSZm7)QE;&qFnMtKF=^+UDSQ1#KoAo|{Cvm&M8Qwt1nqi6nWKd%0(HoNz-A!tip6Fdx7gT~4J`+bKp}p(t&A@ny?o{~!_omKB zi}>?a=@#B-P_hm?3Y~i6?dHt4iGo!84fOLX8$2}RIplu}>TTf|v0PGzS!W?J)cDOV zu!^|}={WcpyM227YVG&6hJ0dMmoN!w?GQ|w~LZR zbnfcg-TvNXK9_0wyrhA-&fOF!@gG8FV}MU;`hfb^^Jt}@P390_D!$7f$=wmeHb$i1 zAVj?(-(&e?1I1d`zRuq+P8_%9!0TmtMe}(Bh_ZtrfWx18e#!;i@Pp;5+sS{CN1m5C zOSh%$8F`bn3uk0v2*x~s)3lrBDQ3{I(5x?11_N5Pd)&w8w9wosdr71=W|??_C*q60 z`91qbqIL)80S?UP)!_3mGvAEWaC9X_tEWQB?P(Ej=EubD{kMBQ&}$~s9St`S3QNz8s7o8m9^?O zD19J8Sl{@5T20UI)nmNQoMEw=C^x&81}#LS8StRuhsGmYyLikVyG&5#EQIPhq-DRn z7v=C*0y6%9LlZ579LEBe++ezAkbB-@F32-zb+^2cx$dAnDsCBHs z^;5TEskZPHkUC%Ea@f%k_2`@T$XPQ0;WM4D`aio=>H{2g+)ApSJSCvrl!vv+!yj5}2+u1@2PvamuFqeL22<`oM7lrWJLoT^L z89i+%fuCfIpYHZn<_Y!U+UwkU=m})Q_uh4FZO{1{;<37BhNM>y(|32f$>5v7#}g`^ zdPcHcyOElul(~(}XHEW-%us2Spx=yHq(pVHp4#8haPc*)Cwo+Hp4|!rJy7yL;#qET z)q?rWn5Cx;lNUNc11Fw8HzXUAp)+z9gUn3BCHi?8_7OtUM+-Ad=k6`XxSi2mR;}e_ z4R*xzN60L;s{7*P3~1?c;}Gy56W;k@|HO=hRUq2VInrwk&N573B;H*$h~g`w$A&%ivua8z4h2teY6;x8RwVv@!xPW zC6>XLzOOszOY2Rruufl~rEhVnl>VVxfC)ak(#4zLDt@X;$xC=7|X`jLMCZi%U zKszLSc#Y^CmLij*SlPiOy_-_UNx$S_e)#H!j_2ZCon_dCt(?l=b7gPwf3Le3v`?!q zYt4sW``48&N>8741%u|(0n15|^-f>fE-2|Y*i?7ufuWg*G2(Y$N6&0YE%O!y_u@3u z7hNwGGg!8?H=0k^ok(i`EvUphoN8XXIZDkJV>P=^rvpIh3MHo%1m!s2spc+%{=%e& z;#pkQhc{`8&H%yP{RJT&NWP;2ualE3U}ZkBlec-tc~XDBo3(CD~H8fPe)ax*!Nin@X2$_Su zAk^U{zAjY#RB_U&eHsPL#E+%jv2j>qKC|9m37D>V01j><&ygt+J-JKhN?12}=L@h} zUzyG4BQIpjYy3s;&^+laI*maAylec^>-;sG0JWBq4Xs-se9xwExsV?e;RU4Xo$7VK z)L@sbVl4taj+b2%ILKY%|J|K@nLG^`qRoG=6WgTyRb6e6mt1u`;px!FU>v3$R*??; z8ffWh?}3OPJ`&(=1XdX%K}?JfQs5&=ja`8k1V4Jx0`dFw@o@3kOi_|6r`#y`DYObL=vd5Ou6XUYa2ZSp zOthY}=rkd46aMj5C7te?&i=}SfEM6d3y2ZWR<>Ui^dnCeASniifK&VkJ z6IQQrMQuR|6BFA=7__2J! zwa3Mx|LHP=x1E!^E-!9tg3;FY;FlVK(!tQ#lm5M_?;i6+@-qO3!=D|+p|O4ZTWqZ> zCwe`8!HTYO&OjcriEejilpnWz60iqM(&f~q`p|sg#KrZ zdkBq_R*?0kXmWEgw}GHoIQR;oFBL(*>Z-{(N+0a$LI2Q*=S%(dOt?L-U>cU_Yg}_H ztA|CwB=gJ_0R11U60h8B4LV&0WG|FpH;q;7*_Y>H2o3ee=UD+%Q_L!A zn?i#5-y)A?1pN`&7_oEwnqtOb-zM@5D8c?~2Bahy40cr{HOP`R4M=4kH-*U`=Y(D2 zW8+lBb(DSXSf>ebOfXm31+Tl9KL-UXTR3~pD@JBOXB#6@hWu^Bn1=@z24dOpdZ6v8 zVJnH#7X$|!YQQZc;Gm-^@H3Sj4cIwCl8KmP&aiJ~BHF6FEnBW7>_qI@^MLvQdNKok z{zsWZ3O)?#nJ&OP3O}_)6bT%9R+<4zL+Sqv>x@QvBpO5UW@gOTEB{(Wb>@ZTRMLTE zko^lZZ6fx>**m?z8e~$c*J|TEpAw43%`Y>nhAqb^MV!KuU4ICfTEh$)YEZQZvOcl* z%!@a#Q}I~=0eV?s(1<*`aG2)Cr_WN{UT9;f{lHs zDr$p`Qir1J-;yI7;U)E$zj10sC6~si`$f|H6&nxorEuGsvpGP)lEk31dAsyZ6y+6A z-A-^TC~*WjGh~v1cAf1utYz3azJpjBfO2#a@(|0;Okbvxus*u-);bFG`~6|_NW=LE z>F2N|sS+z}g$WHQPUwQLog_9Fve&(``WtG{mr7){Uc?z&&|A6>@i!HQ6R4>B+v@tI zAcho9OP8va2=X!iBc^8m{`0kU#RId}hqBDvu+SW7TD$hHqz6{cS_}<$E@DYapAI=} zqu~`7zm>-7w@A?PtUfi`{od->x3<79%Zgpk{0X`L^toJmKEwNGg3~V_{}Jhg3eYPw z<7`bF>9iaH#G)f~iYkOpJx}=dw>=tusYR)-gUJO|12VH3-33Lbnt2ZkMIMCuOtiQj zgT6&aUM$s9vo*dw)!`i!Ak)+&x!Gz7wlDZ1HN8`7r~8u<7%s-MrP$CesLZx8Z~!{Gr0nZ1a;C4SYM9_&?_%qa+An?&O&{z_`X|zVWfWhj>5}=H(e>+|OZs@Z92YJS9hsAs zZgs;)j3gcC4TJsHemc7t{ zTeOU5kp7$RQdMF*N!nKLeBQ0)kN!;`K+%(favz0tpkLoaejrVjN!GN^+3r?2na}U6 zzKT|p$lF?3!sXm3crV)Bh7&XJeFohp)9O?}N@fuHp1`i209qNXa-wg7-&O1!J2}L( z9A;Yn<@DRwFVu315wOJqop$4jLYL`J*PR{d0^-xMtC);I-$JM=FlIQlrq{lXmN7gd z@Z$+_za!ibo_XC%8LSmUwY_B(HjCnpv1fatWOH9(FH=yvn3MZ_8_q4eZ>Q*GBt#9i z-emx^XrJ>uO!8-4Q9`WApwAhHMZBoV>fyfX4wJh1==pWbVC)IaV0dqih4HZ|)14ZB z`;PlDKf&6^L1&KPy!F;nS5zD?_d?5RnBKbQ8XQ=%wrzSs`E}Ji<+|2(lFAs2YEm@O4Y-rcwa8&$w2U~ z_C7A(JSnI3RfMqb?xKn<3Dc$S+|!s)y6t}*fD2_po&W(pR@G7ZBKdQqX9^{AJc;mEkm&MT1);+O@R>{xr1_fMc$X z9~l+ey=fi<5q}fduAxU(8E%emyJMPtyYpSDS!&8`DPa1BUSPV({Cv6hSwqlG+GuBT zq{)ZVQ#4t9*Z`L+CkMSFxkjWbY_2q;!Rn;skGZbcb>_{?;%<>(1LES} zTrP03A}3$R?LO3KEs^$u+Yw8#>eWo?N9gT$`mwcOD?7#p%3lim>rJsOq0n}=aiz=_ zh{?@9BlEu+lvE}O2W#-ABiDQ9L<%=A{+W^sGPGm+f2gieH9i@;wGF$7&qjwf$8VGW z2-7%yASm$rNz(o8PEQxO_j2<1XCUaAxx2!{L@}?Wt-qT7i}1Evfc{A~s_O!}M~<^7 z^H(8{YpZvwq{)v~>FD~_r$SOqv?N8Q2NfCT{sjqIZq`MgPg2|a0sNd@g>zpk@#~== z^3@mf|EORo(zPDY-)Y$U{b?6DT~U;c6_ngbNXE3G>LEc3#G0YZ%=(MLxiRt*uY*|y zSKx5pDlzt<*uxDKQn%vDwRhP{YQ=_5-^$W@91D4va_aY5d{XFN*7Sr8bwa|4Atj2&5~Mxk6Fa#5k36m~+)Ry)AUzvOQ_ctduH(u2T`=w2 z6~9@$?UWzq%~0(^y<<%u{$XS;HYN-@D|XfuqvKpj)%Q(Qz?$sAwrdyHZS`@VeLZ?p z-VOhch5MJiaQ?<4Q4BFiF zw*$%sK6QiD>v#uKKLpTOIZsVpu_%o@)M(Fn0~GL8j8uPGzDV7@|3)8nQQzmOe7b{6 z9&3+jE2R6_?I!DwnT-#KUz(YP%q3i~wiCXdDgM=BaQ)+Ob5=EIMqJoG4|lEb0Q*Nn zBcl6X=nW@en_50n&WK}Va(vc>ykA%B6GW?tu0+%$}x}` zIuo5*=Q^w9_A0Ta7qXXP^&Xzq;Ic*WY#Ui)5 zV-HXj#%8bmE*@}ieQMT99vr)l(F|?b$&)L&5XclQJn5Z7m8yvZU; zmpj8`RNup-SjYKervik{FDy`dWZY$z81sMfW*>(Xd`0Le(mbsL7fSESbrop0`l4q( zEA$_l2s?pV|FY^)c_<>x@U9#5I#ycBuUp6R;lg>h$twu z{mcKa+8o~{QhYYfYGB*IMQnQ$zQ^_I;CT$Fvl{?QDaVd~cJ!x=l zL_$z!b=%$dd`V(Z4rG;1bmC^!|M0irn%=KM&?Zl2_cnv+@P}z{P~a`hFIup;<4oOY zrt%gV zlQNl})U-U+Zz+3ljc?KpJ|>Gqw~}W;U5z}%o@Igps3XJ!f>q&&oS#M1@^dFsJQp5y z%x`~?g9l=L5D9PoBiT1?;-W6-_gvO6(Rb1R+lM@#mT|A-C2bUPlHG|s=sX-A62ev& z$@#(Bo2U={zL&uw5M(=xwO&~%P@3ZHJbYG)Si0aH744^~rKR;XH1QI$HXM5Vd(uwj zPK2`xtl(ob$(pJ#e`LkllNtJ>edMDFX|DsLDvShqxI((*>^b{#k*{ z)B0uoHs?%cz1Yg8=SNryUTNx#Y{~JrJ|4@R%pEjJrxSW-tAc&BII)+BaFlPXz}P6M z%(}d@mO9L_U+#8;m(wZ70&VROhp&t}aD{cB((eG70oKa;NfNsgpe37BSbeTo9z;s8 z?cn7EbCp^#J+?)jc1?g+Dz^HZPC~sQ%_eVULBD+ES%@H1x%zO4>^7NxM}YNnDxq$O z8f*VkEU{mS*QZB&POu?RT=#Jfw9VLZwi)p8{nCwSiHDd;CwpymS?e+AJt2QX)zuJ* zLtUh=Qbk!#vi`Q!SYUUPqq6GnNLoQuo`ipfW4KtO+0YJ3f4$W%PxR02 z%)I9=d4^s4-WrmsiXjhdi6hXv!p3l8_ZrA2HoRt3pQ+ef@KrPfJ1*-CPX>d#=3-Pv z@!!|E3A(GcCh#5yNt@+)cFe{f!**NM%?G$H!RYvSAg}J_^9dhWSd3$9)a)+JGX}J% zYun(2J>~Y*)v*b`Jc?hjA!#ygBo}yocy^cVApd@swl8*jZZfEo+qUAcx8V2@F&VJF>smKBBFNz9lDYE#h4B@ZtFO}udU9o zz1&6N_%sRoO9>sJ^|_Q!-HdUeH0X3ly@8QQ+nlw*Zz|0GMcX{_*;SDN>7ZjakNKI? zdU&bs_>h1-f!{@ssy#s4i&sZFD#7 z+wS{WW^3OamUD9nE|8#7MetS!H=;dOpyiIbSBWRb5ISxHsB)?|k z{>dlNz8?M%?MROSDle2(5l5$4ejQJpNbh^%)$g`(m_eER3Hq!tUfJ zePfbp!=${Fk1KEn>oB?(rdF9wi*1UBT5?pv*y>Sq?b3>OF7+bA&5h7Io{5%LlCCI| z3F?BTY?1P~G5`K`=WzM7ujanAf9|{$frBso!p@TpLidkn?chdQ_O9@O%!a|l?Cex4 zM;iL)HHeqG_$QcCs*B{5xLHU6KNY`RI zq#^mA!t#FatQ-ad@MX({Y;TL^r(Wz02Hyg7rq@x_N7N!N!j?5Oe;sy}AM0hM`^1U^eGE6m3SV7J1&16>} z_6&mXZ&T!@{S5UCxOO*2?JJ0E%dI_U9ziw^9Xkg+?jEETKD%9n`w=%7l78EQ+r~-iz{Q28(Bf z+n32+N^*fY1tVrF9qwUz6Q4GIN~Ay1H}>A(1zDMuO8Hw znIStX?8%`QH>ri_1I{D9L-zqaL&x)e=f3}X`7K-KZTDI|w)<6FN{j@hW7PRNLajww zdp`s69m^2pSnd@0HV?V^T=dyX(f|ZdHODY3OZl4;A9mMf^nVcL+9e8Y3s>H^M?PIE zvg|cE?AuOw$P*oL-|a+2-!S5hX3izc$K3VyTpg(`GEI2}K)e{N{?{0_)tl#P-35Gw z2NHrJpCwV%D>TWczIYKEHDRtEMEJh>nDp=ms_9jNfZ9u@mB6?`4st5*w*U2>wJkVN zupo?TJ-B>Wpds--(-awLlw0D7NZO0$dF@7NYL~#|tjjTqO}sFnsLN#N8u8UI0-Kz! z5}ahH-!3RSR1eEM4@j8FEB^>tc3IE-BE_7iAD?Z_%mXsN^oTCf&8dBd*q0`MJG)r6 zhEjWmT{25IuS54?Lrildc;e9hu$E`*QXA~O%Yy3UG-FuwfTn$!Fqz5!xd9d~MSZKPC|(O2xIn<>Bvnhr+5JR->8ZUdPBAe(0E7~K^o9r zTGHJB0vBpjI4Gx2!jVWjxJe8=eT{f;k(wskfTIV?{53YZym1MW*v{Rj#+Amid@b&k zsTZbr9@zTx=`!4(xVRwR>gUb`1!i(4Yjfgefc_I8uRzdu+oGRfP~wGb9y}5Fi4R z8bN?}AMSb~d8UW)e-xdGKhuvN$9J%ejmPHB zQ5|x&w68T?bXtMCDkF1@V3q`22C}bUO32)xfqx)S)_4|7{^6k30)Jv91m+Va^6CjC zN;vk+yYI~m#bGf==iwIcct?d;x&K7U9B_xJyz|@if9N}gH9Wa-XB&z5ux+0nWq%&f z?=ad|G0D)4d%DW(ghqT;j5Jf;`BVpXWB;Rr$gFdEfGwI%YX14zQjXdo%+q^s~sm`{T&Aw*1}Fd&f(vqP1@JnY+5fdG`I_#@53p8hA`Bi z`KyrVk+R0u7@C+b5=8}++ob&;Q4CQXb)AG*HI8&oT0*Yw zeXU63R*W(u>51v%-Hy`|?@*SoS7k}zK{V4Gt(fB~*AmdH_b|a}Q#-hWPw>&AjCgFO zw7C3Pvr_tw`PKKvmS<%a{kGD6K1Y?j-Bw-4na+~1FP*GRg?*~!Z-Af06lAEzO?L%W zy^r8dt^&{iI>dB?`JeT0t-G3qIdLPn_9DVcdMj^46B_wU^&ad;Fm6R8Bw@$s*lDf6 zZ`n!DaG5|Zyko3IxFvSp1#qS=O;A~bq{DEXsFC2H#I+GADD)Z&hTQ7XC@ED_Lp>uz zG5-YzJLVo_q)(Fcejpa&EZB=sxq$|J^%$p9D0R2Jhm$!#O@!OMhDTcK9%65tX1QFC zc?D54XQ;8;a-Rr-L+8IaKgp5bmOAnemj877%v;9bFbY+o%E{V$i7Y4DYE3z%+~e5y zdYdIvR4FFqgY3ww-C3Yyi^{oE#*VEkVJAw*h@QUf^BCzf(^HntWrY)`JKdVF-xC-zK%9Aigcv* zf$1IGJ2_I$1mgC+HO7c~yWPjAisNEO#WHL7i-mfqWe5*y9` zzO$dQL$go{5W(5s?AQ=LuNHDl9$~REq1v-Zc6XM4beENup?@FE@EO^ARKS+g$ZGth zc}aG(=g}ES z)kxTdMBqG9f)gB%C3oR^37yNJ;66YlHN=yP~esBk6t_lc(x^g>%EKv?B6Wgt6v0 zW@}UR%wfYmKR#Zr(4Lpj4pI7XZYoEzU|h-TAmSma(7N`vboFD_J5aO{<#ekSyq!A! zvK?U5At9p5i;#0XiBtc*$*XmV&y9hO`0Bg{+di<+ezK9O1pSOW%#>9SdA0F26^)R! z`TxN8Y@<9pa_i?+!xRmm?bgMQ*vc_gr(m#g`hjA7=NY z{S$p2j26i}5bsF+;3U<4Pe?er%Tb*k^_E6M6y}I@4*ek87g(~4q(f=fc9YjV*+q6o zS`TYFi4o-vk>!-c_-R@RG;vH+`kQ%zcB=VhJLODqWK=ywQC6qs?THL2X(9Y}Zg(3` zr|cb33UqX4ZQ{e8$F8xltsbYfnn2`!^*FIrbowLI>iPYxlj@-j-9%HI-ia=5(+B9C zYxy}41E_21Cy;SWh)&GDUm1DP_~rKOgHj=jiqpwknF*0L-WPT2^<}o_HTPfXpNHLc z$b5{wZaZ~fDu4iOG@m9g?`6Tfe1ne(;9of1pStJAR96q+3AFp6I0nSxsW~x3*(X7m zY8tiCOFI)FHCPcb^G~+qys-T%Ci{Y@prarexRY$HhzJjl;51G>hwnwl6|~aYf^qUN zQC%XRa5HSmgOp%w0jJd2pUjzOU&9C8{K%eP+dS{g*AjIDcJ~IL+(=-|9m@3Ez` zI_{WnH||2?kCytZd4Hhxw-uFGq7Om|FR<@%+(S($)Kr*ZT_=~?Bndo$U{ws6q3eK< zkO;y~v0P-4F9TqnL$rPE`tWT{_i(0m?XUd){e$-XJzHnWa4K$@)6g>RaI$|p`}LNh z%}?hDlJ>J*5esT%nPMK#gBHY(lGA52B2|KfB!UFy*3tN#e5_c7Q4&<;U0dhna9!;l z?t~C${H)baKI59rym3WGf|S{Uo=jojeeFxd2T^A~kFOmzt$U}wLD`e99f{N+jn2oR z4R!^cn~Sa&-_arpx|7hF9Rjsnl>dyWOf8BsXHs@ddJz5AgOccy$ee&5ZkT9=-9O;K2 zdiPEeeL8%K(vD`wwrc_)lPn8xS4X+t0?{}O@^EWW{R=u{eT?9(Ei16leZ4JZ9VIZ%uBUboG4NrOX3#)=MJYVn#BNWAl?5 z(Xz2IDB>m6|6Y`OJOVacA;Aej{`-*!3~j#3_jR<0VG)et;A6Uo?h4>=8O|deE4>n< zPeEy33U#d6EgsE)sjN!V`)Jz zyEh}{-zK%#RaZZ|4+1^k=}f1g9!%0Jh%Qv zH4(BaM8B3x zunyFjkAY&-KU1|WcJyD=zWF1U5v?q2QFKKTbT9kpE9v&rfqAbX`@$~6fahl0UN_h% zHz!xlY;fY-8~l(p~z{8mSFWb~v9 zXHtyHJ<}{5zwBfuO5VNS3;ZGb_k~Ct997$!GcJ8p(Dl(}h~in&Uhs2aCEbwVYh^&luL7?_*cg2XhX% z^!R#tNI9LyK_h37BN3UheKD>t(Ys+mw+BQK;W|s7^L}*M@nAcZwl&cxz$KA%xvaMG z*yr{%@Tf$*VmlLYt4x^;Rgig?|IV~Y0u`FX&%G$Csxy7cve*)A0l)k2auk8=?TCtZ zx8mIQv%_)}cIX({jnLa^qmJ%5tl8jDwwo3Ce3AflGLzM%gH>PjCwq@>Wpl_2G>0A!Ox2?vPBg}(Z3YB!^m3a1TLZ=Pghuti3^Gq%us1|wf zkPy--C9fq#AA?lLx^%Gge~*9)1=s)r;W-`J|F#JW=)e*5!^qzHy>Z6=4`$~FjpaI~JIQ80Ge%G5*5*hqhvFuj3Eqo{ zlR1Bsl&X{Cq}x(lA)kbv++)KI6cfqca^l8DfVB^f3$)0r(M$oV(xdM0Ua}=>icr6k zGo+hqpXFNz(`HWj=gg#hWwjv9i;DlA+Iu7keiZLEb@6!Uo2=vhZqwSfl&AbO<7wax z)t$UZp?ItIyp>-^8y~N{F6V4Ko%So0-S$3hbmqfhtuwbosA7;&qgQu=_eWvg=RVk> z1H6MEy7!cx2kr6E1WY|9uRyC?V~uD7%%#hnDgFLgO$g}=V6~Snshpgzh}*mjqrB)? zP0j(%eT1y!UM{3j&-#i58L6*i7qW9&f&LX%ptz!C%HLd)5)pSsfOVRS7Ra7H0O-NA zlu9MN$l+G(_mJ+W=$s=od&{RrYx=i6&>VK$mn(-^@XtbhSmV77BMvr?NgNw@VbscP z#(aCwB4Qm-0$V5*|oVZatXwtw~UO zbd<$olK6Bx&BJ>vHHy(`b)K)@2$D+qi(1|Y?DrRskWq;!&B&7Y408@lO}lv6w8IH+ z*00dcvc>er$w!8_Vz=lJP{Ie);)^yM+8nHi-obI4Zf#+^T&_I`5599^OI(7$J@=+o zJcTOMHuYQY#c6SR=aDZnQByu1305$2cSuMuL=`Go8OTnHri!$*VYWlRM3gZ6LEfG} z%!Rl(Jnd(0@m`Ili(R0&F3kTiXA$_9p`lX#aYPNXz<*$f7BE zt9WD-0Nw^mQra?I)QR`s$C2V~|5P*2h?mtMRL+Ejx++@_o?o}ycM~#5J1wj15Rm=$ zIqiV_Z*3B5)RbKm`FbP=Bywt3JUmP9);Y0LEkwz!6&22?$rVca>t_Bs0lX&FV*ujm zMyl(l?bYk@1~2O-w~*%kEV-y*0q%*KTE`j3b;t1sM?CKkLh=iW9qXig6!FjT zjMZW@0pvJTFeeGbKGk78ssL$toA+J|@s?BmdRwuv6!fcTUR?yGX`yUdq9pA`8olo{ zEfDl{);GTZ+9e(l0HCV1I5ETs!h&(+wGWX%Pc66UbO>B=jd$zm}2zD`~)k)@x-5ud_iUTFM2N%XA zrqWF+-h#ZUD-cJPmdAcarxzgnrp8W=%3%YpiXQwvYUMk0xjL{fKwcu=8fmCoZPrB7 zru8z%FKN82mWZBe%@yTY)iUq>`3djW&J_8nb|Vfu`o%b4sTBEYx9r#rtPvfr+EgjE z*K9)@$Gu|L!EmW|FuKy_>kFhTk@6^v$-@u4qJEKCyHq&9pPF7Do|>!>Gjr8biNZrS z#;x6kdjqS_zYKBzBNFAAX-UcQr6N0caT$%zu!(H3p#;~H*LB*|XC_4@mlF~biMu;F znFpj!RkYPYcBk-?%~SWeCZ-a5Hge3&vQEwQ5^7@@neAbpZ^Jzix%zM7@Y$w z&z_*v4dtrz0`R3owzEQ*f)WwyR48VtK`TXTlDZU}e9EOg90l1=N{P?2NT_(nVJfVr z{u7%9xF9X_`I_O|Q?c}E=3Tc0D`{A+i?zrsPC<9Qy@w$#555D)6eMR(eklZ%*qaG12ii5lL;eA#~C?iwHaed8{i)*8%KP8{->kP}&`axL>e}*0l>1%tM2RcG$HcN?+cY)g0(PbOpX=yu zbxxpFl>L_xiQyy<2{K#7L)Qu~X0xz&zKQ@;dMCT58|6PFcEha|d#Ym88$~GpF4nGS z0Lj^TQk?5iCE~Rqj%&Vi+?oHI`*%uIGVzf*-h-6FxM_sYmTL9sm6CB+g zcWTa%Ve$6)K9mJhgJ6&uAo>~Rwn0BW;RI)^d6Wfc-F5(fYyWiRf-J}p-4WMNCe&H- zQimZk$_NC?nl%)904tev1O!T*iP_1keTHRq$M5d_k(J!;(pY z;|0-}wUq7$M2#2et(pED0g&L@d<5O$97&mXC;@jHXK95esvA6}H8?6YDPg8jCQ*XJ z!?KOD*ieJWI^~V`iT!G+bMmD4l_@^w|#$0NuzYOLqCH^sd=$2exH`R z#<+E`%kHLGr@+3oO^eyD()o&fnMKRSqrf(0uNnG>L!_QzVVpX?!^jn7njfcN>Sob+ zG3g8jYg8oGfc+9;cp~e#Jb%+V_V8PsOTyI$u7! zA9Bmi`jSzhafA6lbUO`{y4#?$UBUK0&(Y%vtrQAW4{IfPXNMz!I+TzuYOmRlO87zwT;E_Aa zFug#!ew23mi*)=jU`3B%9b*dL541A#bHvRQI>kz>;kM+(v6C@p3_0x*v-|1TjXDNa zxRtSdD0){4eI^XA3QW0if!7MIGDnsV=D(q>EDx8>dzi%Cv@D!BL52iOY>pd8ELqRH z>hQFk!>b-$5eb1TXH^Ms8yf(YI4H?EBVlQqeB#PKuDEkNV?be(` zRn7sAZU%-xQs=bg+Ff}z_Y2;^H6D`lleN})wn_dF;TkESIIhXM)RMHBtG)SGaT?|} z-_|SYmm&f#U!tIE#PzYNYJs-&1(K8?VOt+b66R6WX^Xie9OD!MB?e@ZnPQZn%MHCh z={o&m<`16-)dPc^5WPm%n6#J>#!+C=vm27ikS5bQs=yT_YP$Hag6}2HeOP(1Exve zDqS5~Jmeo$TflLH&NabJ?#L1CB^0mkE{5s7jNfbXQR~7@H#h*iaYkE30+npbT}sx_ zAasm>Y}#uZ#RDR0oMXPt?tUM7&Fq$A>$kU--Mdj0ZQ7`(!;YTVZM?V9!xE;s;>NOq z%VAe;4Y|BNKRX--GKP!??TK`tr->VQ@t3}9!j3XUmbElVB&g0lhZQ3FYTD56_ao~$ zYHEA&qdbWz?TM;pk*)%w0h&=9#0-=nR&6hh66Eay1H{3%LdTs#0#qN>N&$) z@^(^j51wLza7GexEi({u{_5dwD#S&p5{Z-BX?u&Y?Nr9PqbaFl z!BLL=St;sx{cu7G%($4TBKATuN=GnGfF+*zOBfj4A9}tSo}un2W)Y=T1O0(441osZ zfsZx7E42=nIVG692PtN?cC<2!ax*PZ!Rjjch*0nXwe1gVr%rjXEg^*nTh5mPZm6r{ zdG}_b@C%&S8-?R@)ao;$&)$&q6Br2Z?@qRVX8)_X zK&4Cx_e^Z6?G$v3b^1imWRlBKGN)5Q#mMzbMyPe%6I#=Nc-8m^Mb6%vyN0+$V0yW0 z_h`#m>MAAi@As#giA@`t_to6e2Nx8e2B3s#O{?9GYHg@0#&gK?%)Z4kx*Bn+c-MFn zD=7PiM%(#ArVeW~?3k7*MmJ$Z^Z(h_x1b1;*5WAJ{_rg02`meE2DJ{gwtoCHui7Yw zNDcu<)M-Ahch+EyjHgHH2E)qSKn6?MTM#ovYH+=}5^utCW+O22ocYB;v2B}l^(#+M z^m|%9k^`=e2Lh`(IXLQJcsdLFR(R;??SgzM_i^jKQ?T@gun@F4{;5=I4F^Gg?OD zzXnkrLEdZ`PkE>}AsN7>*kKc3HvxW2b+COMx-2F8DZf+ZKVGMaNCGYqm!h?1xg+#g zbsZo3V;48e*KeP5b)n~Ymu*d4>8MZY5zoR%-D(W%X?GB)*Q@olNGk`Vi~-bn&5AnJ z$!H$}^`pT&h20T!km0Ls3e&BRKyODM727kVyUTlPUqq~0;{{HR!e>Qjcf`@r`a5a4 z$A`;?$C@8XCaf4ol&h7e#nyI4dDh4|JedEN+*h6}7Im!IC!>-Vs zGomN5+KX=`InlCYFr=0J)8A9?0-iSUQtq&a5 zxt*Ff?wWa6ViP)xv3%R_>RbCDEo)2f-5$}xO-VCwB&MUjg*&L!oRqjPG;ynIAiDML zjleH*DcQiJm;ZHEEKy4}(Se#~6hvB8L|TNF!>8^kM!u5TqLm>KH)xPQVc~7fHsild zJI;7c>7Atig!J`f$G1brvx8u;{s%Occq(hVmc@J@iTkYu9}Ac?dBO9l5nb>q!=M{S z$oETvoh%5)U zYLdr%2xyO8b+S>1K>Sy)Ft7fa2dW`x?mr8+-El&V(RWhV>Km*g1ZjJBj-!Wwc@9aU zu>M}9wtMan^v?5F;OW+7%|Ta?!aY^H&)7=v-%;ibF7p!8s?;T{IOAg<@&c9lEWK*l z%sTvq{3rpI9?fpJVsRC&XIyeA=p^D@V9KnS_sw^O2bJn3;I5QaCR1uN{iVzw!cj-y zTL;juu7%bo&S?(pWQ*!TrO9rz?FmP2ca92ldHhNQ8)b;W`B#)EfP zt?M3%zec&hu0v@PpjV*jR^4YqtOF)wDRQ=qpGE*RF1;c&v*fT4ZF@l>!pgq7$LWRS z>4%`JBg4&3U0Vh3bZ|$tw9+wv9nM}kYZb{KcZt#-1P6+{N$UWpQy5R_{q?mLWt&9e zIc-6+w)VK{aNsTW+BJR^$Meowxf#feCsTjC9(C1exWWXsQu-ULvsV z*hW`qx7^xYaf>PM|Y?aXRfvxDP4u$(&w(gQY8`B`I-;*ou~x9{xXgp{mza z$DiQy(mvRIGK=E z_PTu8TtP+z4^S(1i2F4{j8o}#!779llK)5sUTU`k@u3U_hn+T|i@0=WpS2i}J!Wbo z*Dr})wMtk`fL<>v>hmjChe8t_qYxaN26qSTo zkE+CHIsvNGoPJyaz2=sSlyWMwpmVrc{D8EUbN&Pnlt!%RJ{%Ud%M#qpZVvwU^G0rg ztGv9WvYWW*vnB9P2%Q`q4P)u?7ZzlW{I`3z2;Jf^k|BQqI#@v{p^uvg+b40h+nnto z^>|EJEKU{KP6TmXrM6?qByoeeKB+?^pLmcv7|@a^khemha#hA^{*%|QdL|uS zqITb+d-9ve&o_?#^$)dgSL!+IUCvrVx2ydVYa9*y@ZILH#A~5M)7Y3-mz45nQXA#2 zQivw`t>P4H1ehH}((UinrLii0SAmQC_16GBvS>H4r z@mCrntcvHM++={j(z%Lx!b6vml{RXF7V5^Iy{JC1shnKS@u5AO1LGzR+LNKc{gglf z=G`I0QNQ`y*>7||Z>`*FyRxfUJhdwD?*}($Z+ewODY8cxq5@vD*om!bb-y=WzdQ2& zO1bGX=hfCZLZEV{)Sh_;30O~@g7)vdQq`en8|)EvhiNnu!Zx?@B)Q@4>J%?t$);~= zJ}A{41T+JHqU=<9qksV1_p6)WFSZe1NKhEkRgmJp+>@C=)CBu@x76;~)B-Js%y|ls z;k62=m#eI`m08yX2m|2Y$+n)>mqC|{@g3(kG@Cn5;_UN1qnSXE zyrKAtpm9d|%D0an5-+!(Z`6K}WBl1zI~=U@?2c#jZ0l=2AbXIfW7o7y13G^D0*|ng zkp`?-;X$h{e&*{RMNITF+GyAP^J0~i{R*P=3MqGnlEqvWCC>rh`n4XFBM-iwL6Lv>UPe@ z_n0cfEZLuBfMrW_12|ydQJH$J+H;xW?xEoWri;IkAp4UoWlvGr5+ShWHlpdiK?4`9Jk+ zz;ug-{%q|UZumG{ynG?z16J~xE*e680BH; z?{Er#UExE&Io4@gM^Fm*m+rFaOO}AZybAKZr1)@d{7JI@0%)nXY`7%h{l2{xyDmse zI=RBeJO9)g?Dh@s6aS09PoK2#qg$^8Yw)12E7ax9Zw_robr_LTGpt{-J1l%4N5wew zv3i$rP>_re^jml#hiZoFk-(p}rFP?!LXvwxZ(t=d8JC*N%e;GNPg}B0Zv`R6Qk7he zV2)VGZW2Dp(gicQkDAiUta95UB9UTdSOq63xL0pLb11pEC3wC zpQfdw_u;q70f0W$j)L&V?Khogjc z9@KA0cZX57jd(tN$UG+@AeldI#;mfrGH8{F2;uzsTP?XaOU24}=9psbgkeg62489P zes7s_ia@x>i(M<|+Bv@WcZW;ji0Xp0qwo87kX?;e>0-S>`rE1$wet3FLn8mk4f725 zFZg}zX*=NKp*>?)5BQZsjS_N(p@1jqDt)nbN0)qR4ox|~IHO++7B19fFHlbrg^iq)EE@)?DOQU^yBJ4{Nm9V8t)+NpnB4}4+8e{V4;3ghA>8d^%)%5kcOkFkFG9OXI zG@ggPk%>^ALIfzOs(I&ft6;^<8LrDwJfaw4{Ap`Z*^0+hp;VvD1H*}5nb;}(EH#3U zgA=OV)7~TL9&mnMK$4)Vk;ecVNV45^?E%x{)nuH-XIab0&zkP0i=V>sH&eFO(?-9S z5mGAV|1a~tu1stv21`7fUiyvJZ{EtAIjLJDtjy4_KFg?Fcn=x+cKJf2xpq=MToCkK zqOubOT@*8%*%64X`q`Mjp?b`ASyRSL6#Ly6KgaoSx^0l#@)^)MFzS`$e{8ZIomI{h z<740a6ePl~!*|ETJaeMMMceXNo{CKba zce5ZR=-$EXrl^?cmW!M6B`IE>5K^&4#A{_^xv|JR_P1cuuRx>$)a_%X=l`(osAHFLqXH+OcO@){L-CS6L_Jj3D@oT~^cU#VctQ+>D9W3|DI3Zje z^dEdlNDU=Wj^-jPGS&8-T-ChPKN8TC6=QbqHU2yf<+A3m!N5A^h`64uTH)Smlag2! zqj(A%l352&mH|UGKu3d!|B60x6`|z8q|iAaV8tOK$ksKORT;atn4dq5B5P0gi^dYn zeX@)3y5~mJ^>?|w)=(aXkmB=bSX7+sYdP$_>wd4;L-f;HxVsCeFL`RS)yU2KZqjX$U%aDCvL)QG0zJHk*q4kHaePBvHwQ6mVWIsQA3I+KCad)giyugA zol5(Q%K?u;B}~Pf12A2N`svn<4lUG9S~EM3EYNGUU3Fl5nMs|!~)kP&T$dnulxzZbe+R{o%q)cwP+Fo42m!tG=9)L~MQ zN()~gc?^X>syhBbZs|JtBOyoV&~L-kpgSJD-Oj(Zv!XQ#L1Lj!B3ySUkY<4ZJZmGih$F-*H%=_Ob z_4N38%ra|Ww2yg$)PUQZ)QKJ|`M^Um|!(M|EJInBSmM zI65L&$)aB3eeVbKf3P>cO7+#u+X@%$9N^R2WBXq`!=LrLVW!7UAwGpNC&>Ckj40rnQlmOuUDi_)*-fWRP%|^tx2$;&Hbzn!u(eyTN($Z)MHVrTEnbZY2t-5H0~d+20~9H-(k&%=>zku22AtGID)u&U)w!{gFWVzl<}XN;9DE zf9U-~$rs*-)W<4j?)VV54Im0_pv>=FPLbv1MPp(w<4>mleS|}f2Za@5RL6_EHRtQ1 zIWKNRQ_Ig#(p|l`9_%Wu%g}C>a=#V0uAi;KebLh3A=K##Qa0d}_7t7S$MYz}`rfdr zP@Ze^I#uD!S-kWhU=z?OsM*Lnrfzg!&U||L?N1bS*lB>=UvufuVK4e-tK-ibBOM># zD!tBC{y<4jR(#3+ruC-P_d65(15~0I;OJQnGj`1|C1+ea&$@uBZ4^~?V%=>c=-S9e zRgnc*0jHW_+!Or$PenDXIL}Hco-wjEHynG^eImlK4sL0h{nQH~sYkvAss9YIocxgWdq+sOoLoxTXyKu2 zhjqKB%WB29*vqRE9~7UJBF{s!3Lq`8l5tMQumA3c-Neb`TUdvknBVB?j(1MqaiFHZ zu-DcxNW-iAH1m55nfPrQ*kVqGCW+r{mom~+f@uYH+Li4lON;+X+}Kp~{ZOEoGddkD zIloji8$%v)`YS2z8_s7CITsG(qIv@ulMF3M8yli38uvHRIn`MyD8nWhcBT)!BRH6K zOuFrijMx2Nq!$*?M`O$t1PjPBt>ESo0D0yRxsFXZrS301oiGoKH%0AKz^j|@70yoH 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

    ^KL#W$yfG}vJL~! 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

    mkBu_uID)%?Odq%)tZ~QC4|5U(woD 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 b#C%c58#5;yj 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

    LhbOsMI&N{dwPc+97`9-fvK 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ÙWUdJHUwj7dK&rxzJX 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�l9BZ;Gf^!dm85 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%0AQ9S3}Jcd&%BBxCGY< zCt8pzoYgkF9~rWZV*4J& z#^NKUA!cu@`C$oH}*eU^~c~CyW9|-Oikis-9F*zzl9p<76wij z-_XWuwI5by?g=GLoDVZJw8VxatdsOr_3p=; z5gpxGI&ZI!IBT7ctQVD*HFV`ktG6Rt7;q)Z$rM2l<7Ts9tC1C8$>}oqSPr_f`2()5 z2Wds8JiBU4h2vc9h?-Foz9%GfYwX8UNXVt33rbqr>~xPIipXyh)3YH%m?Z_zDa(ol zufnmu^S_Q(kF6x*KnOPBm$0fQrj+aa8hpt8v#^s{<|~>GmQ?A5q1VRLB&fCAyNP!sxKu zjz#B6^f!sOW6t*0OeR?P$62u)*dwpDYi3LEJ(j45kF>4%{w#lZ164CO8Il-8OK9Ii@~*`g zRE(ciHVCus4n?-R$gRxt=fgb3vt;I`^!}dH`_EdgMgo4$85BgU>R<6?&?pEOB-fhw zsxard_4ebtaDtxzURrayUo7}60BMy7VZVE}zo=@GTVRtwf*4mM;sBt! zD(#QzV1C^XciX3Wkr*!4UncVNt6gTeTK1im)RCyHJR{63mi2<@Sf2}z+<+(njZ>%W zO6C%Gb&K&mNk`kK!5%F;f~nO#D!*cfK!B=XV+8~5#V~_B)7>01$7A`Q^e5~B_khPw z{7n~>g!l6Fvl=E+g>0C+&aWLZrB^sHyfQ(5@aDF-v~I@TQ8Th^g$Kp_c=2m?gUfDv=oT1qNFbhO~vOK6JR(xk~mYiLQ{% zHol*>(^?hT&J;3t-5>ycGJ~Z;0P3bhR)*`u09AoHwMX6cP@wo)nK98JN&Iy|x21(m zkRvk(LvR?1!dD(>2_t2yM66hab2_=Ol@otI#Q2$luZZO2rU|JumlXviMO%;!?!bwd}-pfd4R$y8JSN5+# z&&~Q37q>Q2zu?pwhQeeOEBcNVGb<{JItFR5-hXGJSBP`8ya@+IrqbP!mCsUkA%h7B z>LMX_ok@~9P40(%=GU)HWpdRterJM#Do4Mb9(a6&`k+i>iSwQ*J*J#2MA56J-B9P; zdfNC{+m+BkZ@w~p*&kix2xq8p-S;uh{SZ6Yt)p0`TaInJ#;8X(=E7!)&nX$LH9zFj zta<9|-&)agS!|Lb7Pi*_>b)=uUzP)a%?08B=3;<5PR$+zhj`;_kW9|F}IBOY`@MUmSw6n{aPc6U5ahgp^H5zpLvB}XMj@g^`_&ugq1>XC_1pA8D& zpRknccu>awb#l3ZUKkHg;&V!K-pA=L2GNOx-mUFxwv8i?>)gEfN$ZvHe4dVl+@9et zkW)m1ywBDZGyzUl$}rdhiYPdY(#gV*Usi*`@SZMh8iUollhm&^F8XroS_ajxU6W_1 z6*qe6jxCi`J8m>3baN6J8tPC#@1h`nR6!dlCw_aLS(^kgV1?9-UK>YVk&e{(r?0Lh zY%@XaMlUhx@541`KPGpe~r=V$vP7-5Y}U3V|JZ`~nNTBJ`8-8N=- zU_e0Q-hAX5PnGI7Z`625eMVv`!37hx!Xe>a1c6p=m~h%(M=UKuKAWr2*WfqzgSLT{ zkRe0IQ$FaiB+gS|ybxJNMW&Uwc#aBc*eo9qrjf26l~9nky~(WDqLZdlk&7Ilqe-JJ z@YcjJtW}xWFELl=8PG2AmHmw3)j1>mukKL159l7EI97Jf&pc1A>gP_I8r{q7zTPuN zWc(IhL<;otf`UCZxw$TPEv{6NZhD8HpV5Scsg^HHW20>iTn+8y=1`F;Dxdr*L@}dZFk7=L=0Rap=h!tD_Y^LoB~I`e=U3cFAYa9~D*!7JdVD3g zr#7iS%(KegIw4hUv*(^(_BSb-d#CDML2?38Fs-JoGHt~&(;5zUJ>lyiPyGCo`FV!` zGm511hPn)#xa9L)G=j$ZPTw8^zKPap?2iR8xSS9;(L}y@EPJ&gOj2Vfc`a|(e{uyg zFphc`a(o1*ogt%S%KlJs8 zJA?kHlDoUn@)c8v!Xbf6*35Y)7dfB=uuZo+;1rV*8A33ue&%4HjJ-fv;py1W|GisP zIIsQ?uh|Z@M$=YzTEG`Sm5U2gv7w?NZ3Ov1s_mVV2oLT1t-vlpcc1!BXMT)71_PtE z@STTjb4&y^|H2C;Z^KINLJw+tnOt}*^0lN+W9Zik6=Y2LF7ADk738ZApCF@DGw*w3>XFSUB+te_CBQ5fKfF`e7k-Bx z?)ULs9}bx)=vt0$qg#Y*Obj++}Ez|of&V~!E9A+3%mCW)NpZn zwSS`><;O#v4Dlq)EZTeoSTXQB(=DJz;-vLNM5K~7zjK9L zDp=$kSEOf^ZXF}7gIz2ET9+kv3Nypo{8AbB+N3T+^}!EzF&EVdAmtrw@{XN8*b5$-%U0wEp$#?N;sOD-#TTkL!;CAfA_>zT#- zT7zGoR_R;{&oHHr+|0%leu#agIGU_DFwfgki!_X1opUlY{|+VCExBfJaqUSxJ0@QC zlFQrq&(@~xJsnRj5b_MVL`M0m)|U9B`dkRpQJ}U)(|y*pDo}%TY8OrKcA1=s8-ank zOEt%6!y7eM(nz55D#5SeAW@&JsS-|VeW0AaH$reHl3Pb^_rkQn!Rjvtt+0a&BWp=a z#N^p&-ZvUe0TvluM9wb#zt@dlgo5KpZXO*N`kVG*>xrmjdn%k{ zgG@Unf)eRTW!AiThHA-YliY&ddp_77&yp8)-B)QnVM~-jEe}}kn!!LeR^%vynd46% z)rnPW4~Qz3HOICHaZK_n`FwuXK=XFsY>cE+4J@`=Y)GQC2|Z1ISCsekUCwD1=5y#) z%k*Z9+vu$vgi4&1s6Sx_!IgZ;^g_Ih9@6+cPkud%HtZd{?GFfhP7XDsl20;l%X6$T(?8V~4~Gc9tc!P0Svj0lcrmK<&7`nVo`EyH zTEG8=MZ?Y@gXf98__!sb1pwBo=QB9cG-RlmsLF8(}HErUZY^!>zSf)ucMGt@0c+kz5c+C6H~Gp?5a&~ zS17wr!kk~@g#M@y>U7l0vT6#1mx9B8)_(S&dGYT^5^vhes?`ISmE}eE@yx=@dy^mn z#?1X*64heCi^Be5tQt!%8cY|ryUbZPI+sYATPr3?{-Gv(YyhLXH(~w&)hB$(vfU zck7s=22^lM(mAWLK;8S_Z)4QHo)by8rPCLvYUpFATQbe5UubM`D=#+(ozrKlH~Lb}S#TsyXh;Ua^bBo`^^Y2o|zyEgpLCV)AAgLT^E6!i0yoXkdTTR;^{%&Wpfp%6M!6$%)P z?TXtBlqlj8?%^X2)dN^7wR`>YAF0at@Z`=yD{{Vr9u-P1#!3I!j5w8ssd^P=s0nz) zMQu;m-D8vE*%ndDi>kXf63?4f1$wJ63-Iz}2MwjF--{;);UCv8RlzGpmrB)yp|{kHI&RocdsR?dy9!Rf|CmD3xB{OAQQjAAeRW3* z#;HHU)8OsjHb3si*?0#{TdFpC)P{ymAjD#5 zV9-ri2|reM;dA`XUqVX*>zXG2jI_y@D_m{LfuhXY`WENgPGSkLJKip#bT|nmgf3?Y zf`sx6dZ>j}Bgag}wymYTtX~NgOfClwYrqKFh9aJAfs(W?fFKgLz zDAPh>m$ugEGg6W>&d=et9VbFpmp#_b+CgH06e|6>zWt~G&9;ZW9JAuEmgvt)*a+kX z;bO*`gwo7CC+1F;!LxIQm-0-<7^;(rm3w67>4eZencPQziYi&-9dUq8u2E}R=>e#Z zYN45m!0BbqI$Bt${%`J~)98~)s`IFDX6Ja~zk8brs-3f-Up{Ew1_0F-NS64nG?g^t zD#iLeeKFn*3~>A+&^tmqVl6vhC;VfrF8$Sz(vi5LzK6t)w%EVReBpALvkUp~k3~7y z$>tqIQhaW~6IFp3&Z0`x`q(g-pb)`n0xb$j)q`rmSRfHkqRsm1C?val51ly?*4qox zXHxV(0@-4;z}HGY?1dE;Vyg!-(lN)A7LA&5H3l0uyAuKN>1Vp|nyMc!%-}*WGBOUW zXBcSyEN+Bhm!C5;NjQCLyoxY1<^SyHaR_gt{;sbOgTopwc3X8}gQ*wiHujSw^o;~{ zr6l4Lwks-58G@)IZ0xgNG~%q-$Ccoyd%uIHCxqDz(i;olk>ESkcFtiH-?sow&0 zyeFu+jla)wNHcQ$Sx;vH-C174X13*)G7+CUD+q$bY8tJRD;G~*WY*nWXZ^Qsm?vnH zedUzX_pM7aF(2-PZ}+r2z!!%lePqoMJF?yF{J89Z`M!}HgE7^4V{420QiB*}elHMh zGo=Pi;Ivnf$DE}ZACgZP_TN2Qow^(&&iI9VlVmX)D00ngW|LJ$WzWuMeT{-cq^Q_3%h3hukPSU3pd{ij-k!Rg7fBPz?G6HhsYz?}bBs;OY*5wPiUWQ}=BC@NPtiJ`56 zs~nkh&8c-i99?^Gi2EL>GUWXj5&YFmuNVv=`a4~4YssFhi^xb_@r_)q&Hfchb&}V& zzJc^s5T4shj&bDn`^<7sleHe}+QT|GQTHv>M^vqU6(#5ftHszcJ$Kvg_& z91nKBmWAQ$xn;v=cNU6Hs#C4B`dI~1P@;%LBT6zN^W7$D$IfjsgiwR=z2#U~HFsbm zkJ-!75DE%z@Wt$zogaX`eoZaLWxv7dF{FvP@| z=6q;te1cS~Uic5k{ZWP-X0=6hik(^V7OG*~KnG!j-8zxAW47?p46tVc+L{F7!6oLX zX$@ye-D-m_>%`-I&ktq2V-y5_q`ySsOmRQe$&4>O)_ zDJ0x&ps#Yri~gFIEpN=rsB#bnmg8RMBAj2Xk@SlJHs0Yd#FV@kMFBv1`LZv@T9f#TPo{CueM77F>*VX7pLZPhgZO&L7uQy# z9+JiWg^cUjo{*%<5F*+Q!Eo8^FTt;JoI!fcs-}??+K5pZpduVR{64rTz zud1u>Gc@ju<`sP+I*QG6ps}ujldHAa8PVcL z3n(QI9&X?esD^MKhsFrEnO?*(o~yn0gnwbm5?T!HHEVu(BK@Na{V(&ZoQ9at;vVb8 zI-y-7_?dM#x+3W#u{`gcgX4b3?4M-Wn3-}U{K2a9*llqYh%`68+tA3D=P+T%)8tVP zYomzq54@a8b9LWj{X3+IB>k&hy3fMEOeC4o=YnT5-6}GdF@$mRtzZX<&iIh@(IV{w z5lR$(3?TfT_U}W!_6teS{KSA=yf?V&?kZ#OZ~w)oe@MU|TIxn<&iE^q!TZeU9$y;x zWq|FJSPPG)3IHjMK~$#FTIMhKP=5r+-S)aMcHr;#-B6c+yO4YmeiNE+(2|vin%rU-N+6WrB*f2n~H3f+%g*C z`zTvGAm{rZ(&jQ>YUBI~6_&oGvKZn!TY z7bnW>8PwEzYvcnV02?9pN!rU;`be@FfF?@i+)wG7oow}^0jr4k_oO`i;WXM@h0Y%X6*s7VNKv-Ltlpu1uo8PfF-@`9)-Cw z62giEq*%nBv$9#PyBrnu!RTKy*21L^|0gFC$_Fb6^xuOQ8gqTzTy;0#_eUUd^tcLQ z67zZ!V**96Ef@}%wYpc=oSm0wVwvmIFPmQ^LICSuzgOoW$9$j8o#zZ-01q^ZdJ;(S zB+o}ikd@Z5)Zvh62^TgHN5U|{NK^r}J=HbA>!`BqB)gA176)cz66|=fo+_V@QIrM^ zZm<4w`)kBp&vMSV(*#Z%Y9GW7Ysx4a%C14lw_(#jwjTMxmKz~-PY5k~kVR9%s4=Wa zUz%e|;58&mGJBKlg&4W&|JA^Om?63mxzya56WLDcxyH?$U(R)wk4*cgZj@X|UW?Ae z^NSY#Tk1Xc*zyGTR^yFeXH$%g&8~s~WA4^(B9CQJQeNB}rM(=xmr^eOY`SxUZF@qh zzkjeMj)zoljnv#TjNjh=bvHit~FTH;2Q`Id%o6e zME>5Vum*kghhs;S3P|pHKez=*7rS0>;-Nec+1i|A5U`u;t7%9Q23U%-lSzb!tY{Hd z1uhY5c2YY`Sc|Aah135iLi*=&qef#mucC^+0SS|qUnw!y#04JzY$>$3fIH@nx@Y1%`3#= zc)vO|bJ@Hw)*3G?5#qt63SQhEmbH>6II`8*5W?RpNlIBZK#EC8<;*?~*58Z0p5(6ojq_)z?rKS|M)rna{*g$nzb8o6f=htd4i zrBw=2bWXD&NKBl`C;*1(pQa%f&rFSWDM$!gyw^x@(m1fbYZTVzHoy{tc?51Dh^#f! zVo5`jeIws@H{~$<_^f?;COOUHtu4X?y~R7B39ZD_DxJ__7@G~np-YLZQ~kiTJo#_8 zYX>TzQ@pX`?36^%xZC=}Q6Iv9WpWlAiTC>(c@qM~N|ZS{nK~|-KVzZ~UBM&(wOCko z#lI36HF^h_7}>aG*NGfVHNOtZmcy=}_OQpEfYvJ7t>dGvvnY3sJ|HEPG**uqaHlen6^6RqPd3H?x?w48TF%2D zhRz+yCvn%}NIT!2EW9kyyq|H7($aVsDdXZ7aIr}z;2#m6h9P}OXOTn_{`Z6oZcZ4q zVows_*_~>!)_<2+^tg)^YW;8=(zIQk+uog^o?2W3WzWIrtedPBK&z=|V~-uNhhY1e z`RPKzS>&hXHQ-_@CM4N)u8d7^`b|I$)h4aFl)8m01PF=t=MhxQCWm6;PRYg~y=b4J!_`JKo@=6__E?2Kg*B{j%8$&c6$?U(yF za)j|^o-z4w+_I{$b!C0GEXy_R30U{ePMP^=(Ks^G9Ak}QT3RPMfHqs+XfbhSWNlF? z&dTa`2hz-t7x+&|P`qFDqLW-Z{MrAaq)dTSq!HDxLe25adF4NMm%d(yZFJ-$OO?lr zEzChxg)u!7TCwrQr4J?aPHA94V zs~K>Y=YDLC#~ro885Nlru}DiK(ka0a{iGUn9L5To7NzjS6DC!UFSdxy9}9z(Iv=2j z?F$I=mtB3N4^K%{HCws^qK;;-D(9|(2mvgDf*RA@-y-L`?GpjogJ)}{-7u%s4|uQV zEa2oxE1hnyJB(&tdq^m%wy`(Mu8643^U~O$p=P~qUYJg6xgJ~n_Y8d2k~(`_ zkwX@DUa*Lr+%AN(rW1hKtQB`y$>94Pw>OU_*(_5;tY7PD<+Fctes+%QPxqDkE=9xU zpgTLpW(ZUu+c29DdNQ6MEC^@F)XGciFWX)gxRUSK zLqt7UoelXMM|Sf$%l>Q)QlpF_w;B7s{?fl8@dF-DN7E>}!vD@}+$yVk%#DIK>RXS4 zR*q3#X!kdyK7+R#u+jhR2GY^H5G_Y!iKuvQa&o<-{Y>zc>-L#G-=Ev0A@eNxJF@*w z4PMK%$W0a3;?p!=w+W5dofudH^^#emyFqZ7cHXXV<9Cc)H80`FnaCX zp&r*glPr!S7=DnYzKpQr<)mqjyFhDa!VHom-d^ewVHSP5GIvwOI%^nGvG7XmGlgS5 zRuF;dM8G9AvZgE)`NyrXGI=V?b%J)qnmoAPkSZ8{)#ep~N1odYKHRL^fuCN$-^%18 z!Tj_;#s(H`_Se4J85y(s6OqYXIyIr_IU{_BYkjiF^mO4oJ(kvu4#In-U$bu7NmD6& zN{)4Y;|FLs8pK*ZJENDn{YzT_Q8+?F{lfPEY7uAc zOcqFhjviM)y)Dav@Rt%AuGguhPes$a8t4j#m{w!e^oPP{@Op-6KodyMx|`?0DG@z8 ziQyog#%18aVvI4^R`_wMZnGxMmrPZVN`8E&6g>7!!^R6A-$4*mFV5{MOj4VH41^&T zqad&{ldXvnQn5Y%!}@W-y(;+QPJ@jq`IBi&L&!nge;X2FnmuQ5zQ%Z{2!5{$1+x{| zO+yNVR)KLuF7iza?|6}H)UVugp>5X}U|glh&d`opzydb}F7bVLaGJgWHh6HW1b!

    l1FrCEMB>555C}b9Iz+jo- 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 literal 0 HcmV?d00001 diff --git a/web/tailwind.config.mjs b/web/tailwind.config.mjs new file mode 100644 index 0000000..19f0614 --- /dev/null +++ b/web/tailwind.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/web/tsconfig.json b/web/tsconfig.json new file mode 100644 index 0000000..fbc2f5f --- /dev/null +++ b/web/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "astro/tsconfigs/strictest" +}