From b8197dc48bbfb26c592a04a82717d775dd0276be Mon Sep 17 00:00:00 2001 From: srs-bsns Date: Wed, 10 Jul 2024 23:06:49 -0400 Subject: [PATCH] update to 1.21 and reclassify as a GAMELIBRARY - Explicitly set FMLModType to GAMELIBRARY (behavior prior to neoforged/FancyModLoader#96) so that the lib is available in the GAME module layer to have access to Minecraft. (reversion from previous changes to classify as a LIBRARY, which seems less useful here) - Update ComponentUtil to use Component#translatableWithFallback due to the removal of I18nExtension. Signed-off-by: srs-bsns --- build.gradle | 3 +- gradle.properties | 4 +- .../de/srsco/srslib/util/ComponentUtil.java | 91 ++--- src/main/java/de/srsco/srslib/util/Util.java | 355 ++++++++---------- 4 files changed, 214 insertions(+), 239 deletions(-) diff --git a/build.gradle b/build.gradle index 85ec4ff..d8d0425 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,8 @@ tasks.withType(Jar).configureEach { 'Implementation-Title' : "${base.archivesName.get()}", 'Implementation-Version' : "${project.version}", 'Build-Jdk' : "${System.properties['java.vendor']} ${System.properties['java.vm.version']}", - 'Build-Timestamp' : java.time.OffsetDateTime.now() as String + 'Build-Timestamp' : java.time.OffsetDateTime.now() as String, + "FMLModType" : "GAMELIBRARY" ]) } diff --git a/gradle.properties b/gradle.properties index 735d34a..b059451 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ group = de.srsco lib_name = srsLib -mc_version = 1.20.5 -neo_version = 20.5.5-beta +mc_version = 1.21 +neo_version = 21.0.78-beta diff --git a/src/main/java/de/srsco/srslib/util/ComponentUtil.java b/src/main/java/de/srsco/srslib/util/ComponentUtil.java index c7a55b7..e6e0e15 100644 --- a/src/main/java/de/srsco/srslib/util/ComponentUtil.java +++ b/src/main/java/de/srsco/srslib/util/ComponentUtil.java @@ -30,24 +30,16 @@ package de.srsco.srslib.util; -import java.util.Arrays; -import java.util.function.BiFunction; - import javax.annotation.Nullable; -import org.slf4j.Logger; - -import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; -import net.neoforged.neoforge.common.I18nExtension; @SuppressWarnings({"unused", "WeakerAccess"}) public final class ComponentUtil { - private static final Logger LOGGER = Util.getLogger(ComponentUtil.class); - private static final String EMPTY_STRING = ""; + private static final Object[] EMPTY_ARGS = new Object[0]; private ComponentUtil() {} @@ -55,77 +47,90 @@ private ComponentUtil() {} /* Text & Component Helpers */ /** - *

A BiFunction to generate an error message for a missing langkey.

- * (If the langkey was not found in the lang file and a fallback was not provided.) - * Logs an error as well as returns a Component for in-game feedback. + *

Creates a translatable Component for a langkey.

+ * + * @param key A langkey + * @return A translatable Component. * * @since 0.1.0, MC 1.19.1, 2022.08.08 */ - public static final BiFunction INVALID_LANGKEY = (key, objs) -> { - LOGGER.debug("Bad langkey: {}, Using Objects: {}", key, objs); - return Component.literal("Bad langkey: " + key + ", Using Objects: " + objs); - }; + public static Component getTranslation(final String key) + { + return getTranslation(key, null, null, EMPTY_ARGS); + } /** - *

Creates a translatable Component for a langkey.

- * Uses {@link I18nExtension} + *

Creates a translatable Component for a langkey or uses a fallback string if the langkey does not exist.

* - * @param key A langkey - * @return A translatable Component, or a literal Component if the langkey does not exist. + * @param key A langkey + * @param fallback An optional fallback string. + * @return A translatable Component. * - * @since 0.1.0, MC 1.19.1, 2022.08.08 + * @since 4.0.0, MC 1.21, 2024.07.10 */ - public static Component getTranslation(final String key) + public static Component getTranslation(final String key, @Nullable final String fallback) { - return getTranslation(key, CommonComponents.EMPTY); + return getTranslation(key, fallback, null, EMPTY_ARGS); } /** *

Creates a translatable Component for a langkey.

- * Uses {@link I18nExtension} * * @param key A langkey - * @param objs Objects to be used in a formatted text string. - * @return A translatable Component, or a literal Component if the langkey does not exist. + * @param objs Objects to be used in a formatted text string + * @return A translatable Component, or a literal Component if the langkey does not exist * * @since 0.1.0, MC 1.19.1, 2022.08.08 */ public static Component getTranslation(final String key, final Object... objs) { - return getTranslation(key, CommonComponents.EMPTY, null, objs); + return getTranslation(key, null, null, objs); } /** - *

Creates a translatable Component for a langkey using a possibly supplied Component.

- * Uses {@link I18nExtension} + *

Creates a translatable Component for a langkey or uses a fallback string if the langkey does not exist.

+ * + * @param key A langkey + * @param fallback An optional fallback string + * @param objs Objects to be used in a formatted text string + * @return A translatable Component, or a literal Component if the langkey does not exist + * + * @since 4.0.0, MC 1.21, 2024.07.10 + */ + public static Component getTranslation(final String key, @Nullable final String fallback, final Object... objs) + { + return getTranslation(key, fallback, null, objs); + } + + /** + *

Creates a translatable Component for a langkey using an optional supplied Component.

* - * @param component A possible Component to be used for translation (i.e. a {@link Player} display name). * @param key A langkey - * @param objs Objects to be used in a formatted text string. - * @return A translatable Component, or a literal Component if the langkey does not exist. + * @param component A possible Component to be used for translation (i.e. a {@link Player} display name) + * @param objs Objects to be used in a formatted text string + * @return A translatable Component, or a literal Component if the langkey does not exist * * @since 0.1.0, MC 1.19.1, 2022.08.08 */ public static Component getTranslation(final String key, @Nullable final Component component, final Object... objs) { - return getTranslation(key, component, null, objs); + return getTranslation(key, null, component, objs); } /** - *

Creates a translatable Component for a langkey using a possible supplied Component or uses a fallback string if the langkey does not exist.

- * Uses {@link I18nExtension} + *

Creates a translatable Component for a langkey using an optional supplied Component or uses a fallback string if the langkey does not exist.

* - * @param component A possible Component to be used for translation (i.e. a {@link Player} display name). * @param key A langkey - * @param objs Objects to be used in a formatted text string. - * @return A translatable Component, or a literal Component if the langkey does not exist. + * @param fallback An optional fallback string + * @param component A possible Component to be used for translation (i.e. a {@link Player} display name) + * @param objs Objects to be used in a formatted text string + * @return A translatable Component * - * @since 0.1.0, MC 1.19.1, 2022.08.08 + * @since 4.0.0, MC 1.21, 2024.07.10 */ - public static Component getTranslation(final String key, @Nullable final Component component, @Nullable final Component fallback, final Object... objs) + public static Component getTranslation(final String key, @Nullable final String fallback, @Nullable final Component component, final Object... objs) { - return I18nExtension.getPattern(key, () -> EMPTY_STRING).equals(EMPTY_STRING) - ? fallback != null ? fallback : INVALID_LANGKEY.apply(key, Arrays.toString(objs)) - : component != null ? Component.translatable(key, component, objs) : Component.translatable(key, objs); + final var fb = (fallback != null && fallback.isBlank()) ? null : fallback; + return component == null ? Component.translatableWithFallback(key, fb, objs) : Component.translatableWithFallback(key, fb, component, objs); } } diff --git a/src/main/java/de/srsco/srslib/util/Util.java b/src/main/java/de/srsco/srslib/util/Util.java index be4b7b3..d015a0b 100644 --- a/src/main/java/de/srsco/srslib/util/Util.java +++ b/src/main/java/de/srsco/srslib/util/Util.java @@ -30,56 +30,92 @@ package de.srsco.srslib.util; import java.util.Arrays; -import java.util.List; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; import java.util.stream.Collector; +import java.util.stream.Stream; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import com.google.common.collect.ImmutableList; +import com.mojang.serialization.MapCodec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.minecraft.advancements.CriterionTrigger; +import net.minecraft.advancements.critereon.ItemSubPredicate; +import net.minecraft.commands.synchronization.ArgumentTypeInfo; import net.minecraft.core.DefaultedRegistry; +import net.minecraft.core.Holder; import net.minecraft.core.Registry; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.particles.ParticleType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.numbers.NumberFormatType; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvent; import net.minecraft.stats.StatType; +import net.minecraft.util.valueproviders.FloatProviderType; +import net.minecraft.util.valueproviders.IntProviderType; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.memory.MemoryModuleType; import net.minecraft.world.entity.ai.sensing.SensorType; import net.minecraft.world.entity.ai.village.poi.PoiType; -import net.minecraft.world.entity.decoration.PaintingVariant; +import net.minecraft.world.entity.animal.CatVariant; +import net.minecraft.world.entity.animal.FrogVariant; import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.VillagerType; import net.minecraft.world.entity.schedule.Activity; import net.minecraft.world.entity.schedule.Schedule; import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.item.ArmorMaterial; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Instrument; import net.minecraft.world.item.Item; import net.minecraft.world.item.alchemy.Potion; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.level.Level; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.entity.DecoratedPotPattern; import net.minecraft.world.level.chunk.status.ChunkStatus; +import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.world.level.gameevent.PositionSourceType; +import net.minecraft.world.level.levelgen.blockpredicates.BlockPredicateType; import net.minecraft.world.level.levelgen.carver.WorldCarver; import net.minecraft.world.level.levelgen.feature.Feature; +import net.minecraft.world.level.levelgen.feature.featuresize.FeatureSizeType; import net.minecraft.world.level.levelgen.feature.foliageplacers.FoliagePlacerType; +import net.minecraft.world.level.levelgen.feature.rootplacers.RootPlacerType; import net.minecraft.world.level.levelgen.feature.stateproviders.BlockStateProviderType; import net.minecraft.world.level.levelgen.feature.treedecorators.TreeDecoratorType; +import net.minecraft.world.level.levelgen.feature.trunkplacers.TrunkPlacerType; +import net.minecraft.world.level.levelgen.heightproviders.HeightProviderType; +import net.minecraft.world.level.levelgen.placement.PlacementModifierType; +import net.minecraft.world.level.levelgen.structure.StructureType; +import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceType; +import net.minecraft.world.level.levelgen.structure.placement.StructurePlacementType; +import net.minecraft.world.level.levelgen.structure.pools.StructurePoolElementType; +import net.minecraft.world.level.levelgen.structure.templatesystem.PosRuleTestType; +import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType; +import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; +import net.minecraft.world.level.levelgen.structure.templatesystem.rule.blockentity.RuleBlockEntityModifierType; import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.saveddata.maps.MapDecorationType; +import net.minecraft.world.level.storage.loot.entries.LootPoolEntryType; +import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; +import net.minecraft.world.level.storage.loot.predicates.LootItemConditionType; +import net.minecraft.world.level.storage.loot.providers.nbt.LootNbtProviderType; +import net.minecraft.world.level.storage.loot.providers.number.LootNumberProviderType; +import net.minecraft.world.level.storage.loot.providers.score.LootScoreProviderType; @SuppressWarnings({"unused", "WeakerAccess"}) @@ -117,73 +153,69 @@ public static Logger getLogger(@Nonnull final Object obj) /* Common Registry Helpers */ /** - *

A helper method to get a {@link ResourceLocation} for a {@link Block}.

- * Maps a ResourceKey to a ResourceLocation as {@link DefaultedRegistry#getKey} returns the registry default key instead of null. - * - * @param block The Block to get a ResourceLocation for. - * @return The ResourceLocation. - * - * @since 0.1.0, MC 1.19.1, 2022.08.08 - */ - public static Optional getResLoc(final Block block) - { - return getRegistryFor(Block.class).flatMap(rh -> rh.getResourceKey(block).map(ResourceKey::location)); - } - - /** - *

A helper method to get a {@link ResourceLocation} for a {@link Fluid}.

- * Maps a ResourceKey to a ResourceLocation as {@link DefaultedRegistry#getKey} returns the registry default key instead of null. + *

A helper method to get a {@link ResourceKey} for a registered object of nonambiguous type.

* - * @param fluid The Biome to get a ResourceLocation for. - * @return The ResourceLocation. + * @param obj The object to get a ResourceKey for. + * @return The ResourceKey. * - * @since 0.1.0, MC 1.19.1, 2022.08.08 + * @since 4.0.0, MC 1.21, 2024.07.04 */ - public static Optional getResLoc(final Fluid fluid) + public static Optional> getResKey(final T obj) { - return getRegistryFor(Fluid.class).flatMap(rh -> rh.getResourceKey(fluid).map(ResourceKey::location)); + return getRegistryFor(obj).flatMap(rh -> rh.getResourceKey(obj)); } /** - *

A helper method to get a {@link ResourceLocation} for a {@link Item}.

- * Maps a ResourceKey to a ResourceLocation as {@link DefaultedRegistry#getKey} returns the registry default key instead of null. + *

A helper method to get a {@link ResourceKey} for a registered MapCodec.

* - * @param item The Item to get a ResourceLocation for. - * @return The ResourceLocation. + * @param obj The MapCodec to get a ResourceKey for. + * @return The ResourceKey. * - * @since 0.1.0, MC 1.19.1, 2022.08.08 + * @since 4.0.0, MC 1.21, 2024.07.04 */ - public static Optional getResLoc(final Item item) + public static > Optional> getResKey(final T obj) { - return getRegistryFor(Item.class).flatMap(rh -> rh.getResourceKey(item).map(ResourceKey::location)); + return Stream.of( + // MapCodec registries as of 1.21 + BuiltInRegistries.BIOME_SOURCE, + BuiltInRegistries.CHUNK_GENERATOR, + BuiltInRegistries.MATERIAL_CONDITION, + BuiltInRegistries.MATERIAL_RULE, + BuiltInRegistries.DENSITY_FUNCTION_TYPE, + BuiltInRegistries.BLOCK_TYPE, + BuiltInRegistries.POOL_ALIAS_BINDING_TYPE, + BuiltInRegistries.ENTITY_SUB_PREDICATE_TYPE, + BuiltInRegistries.ENCHANTMENT_LEVEL_BASED_VALUE_TYPE, + BuiltInRegistries.ENCHANTMENT_ENTITY_EFFECT_TYPE, + BuiltInRegistries.ENCHANTMENT_LOCATION_BASED_EFFECT_TYPE, + BuiltInRegistries.ENCHANTMENT_VALUE_EFFECT_TYPE, + BuiltInRegistries.ENCHANTMENT_PROVIDER_TYPE + ) + .flatMap(Registry::holders) + .filter(h -> h.value().equals(obj)) + .findFirst() + .map(Holder.Reference::key); } /** - *

A helper method to get a {@link ResourceLocation} for a {@link Feature}.

- * Maps a ResourceKey to a ResourceLocation. + *

A helper method to get a {@link ResourceKey} for a registered DataComponentType.

* - * @param feature The Biome to get a ResourceLocation for. - * @return The ResourceLocation. + * @param obj The DataComponentType to get a ResourceKey for. + * @return The ResourceKey. * - * @since 0.1.0, MC 1.19.1, 2022.08.08 + * @since 4.0.0, MC 1.21, 2024.07.04 */ - public static Optional getResLoc(final Feature feature) + public static > Optional> getResKey(final T obj) { - return getRegistryFor(Feature.class).flatMap(rh -> rh.getResourceKey(feature).map(ResourceKey::location)); - } - - /** - *

A helper method to get a {@link ResourceLocation} for a {@link EntityType}.

- * Maps a ResourceKey to a ResourceLocation as {@link DefaultedRegistry#getKey} returns the registry default key instead of null. - * - * @param entityType The Biome to get a ResourceLocation for. - * @return The ResourceLocation. - * - * @since 0.1.0, MC 1.19.1, 2022.08.08 - */ - public static Optional getResLoc(final EntityType entityType) - { - return getRegistryFor(EntityType.class).flatMap(rh -> rh.getResourceKey(entityType).map(ResourceKey::location)); + return Stream.of( + // DataComponentType registries as of 1.21 + BuiltInRegistries.DATA_COMPONENT_TYPE, + BuiltInRegistries.ENCHANTMENT_EFFECT_COMPONENT_TYPE + ) + .flatMap(Registry::holders) + .filter(h -> h.value().equals(obj)) + .findFirst() + .map(Holder.Reference::key); } /** @@ -196,154 +228,91 @@ public static Optional getResLoc(final EntityType entityTyp * * @since 0.1.0, MC 1.19.1, 2022.08.08 */ - public static Optional getResLoc(final Level level, final Biome biome) + public static Optional> getResKey(final Level level, final Biome biome) { - return level.registryAccess().registry(Registries.BIOME).flatMap(registry -> registry.getResourceKey(biome).map(ResourceKey::location)); + return level.registryAccess().registry(Registries.BIOME).flatMap(registry -> registry.getResourceKey(biome)); } - /** - *

A helper to get the associated {@link ResourceKey} of a {@link Registry} for an object like a Block or Item.

- * - * @param obj An object to look up a ResourceKey for. - * @param The type of object. - * @return A ResourceKey of a registry associated with the object if it exist. - */ @SuppressWarnings("unchecked") - public static Optional>> getKeyFor(final Class obj) + public static Optional> getRegistryFor(final T obj) { - return getRegistryFor(obj).map(Registry::key).map(key -> (ResourceKey>) key); - } - - /** - *

A helper to get the associated {@link Registry} for an object like a Block or Item.

- * - * @param type An object to look up a IForgeRegistry for. - * @param The type of object. - * @return A registry instance associated with the object if it exist. - */ - public static Optional> getRegistryFor(final Class type) - { - return RegistryHelper.getFromType(type); - } - - public static final class Identity - { - private Identity() {} - - /** - *

A Helper to check if two {@link ResourceKey}s are equal base on their internal data.

- * - * @param first The first ResourceKey - * @param second The second ResourceKey - * @return true if the ResourceKeys are equal - */ - public static boolean isEqual(final ResourceKey first, final ResourceKey second) - { - return first.registry().equals(second.registry()) && first.location().equals(second.location()); - } - - /** - *

A Helper to generate a hashCode for a {@link ResourceKey} from its internal data.

- * - * @param key The ResourceKey - * @return The hashCode - */ - public static int getResKeyHashCode(final ResourceKey key) - { - return 31 * key.registry().hashCode() + key.location().hashCode(); - } + return Optional.ofNullable( + (Registry) switch (obj) { + case GameEvent ignored -> BuiltInRegistries.GAME_EVENT; + case SoundEvent ignored -> BuiltInRegistries.SOUND_EVENT; + case Fluid ignored -> BuiltInRegistries.FLUID; + case MobEffect ignored -> BuiltInRegistries.MOB_EFFECT; + case Block ignored -> BuiltInRegistries.BLOCK; + case EntityType ignored -> BuiltInRegistries.ENTITY_TYPE; + case Item ignored -> BuiltInRegistries.ITEM; + case Potion ignored -> BuiltInRegistries.POTION; + case ParticleType ignored -> BuiltInRegistries.PARTICLE_TYPE; + case BlockEntityType ignored -> BuiltInRegistries.BLOCK_ENTITY_TYPE; + case ResourceLocation ignored -> BuiltInRegistries.CUSTOM_STAT; + case ChunkStatus ignored -> BuiltInRegistries.CHUNK_STATUS; + case RuleTestType ignored -> BuiltInRegistries.RULE_TEST; + case RuleBlockEntityModifierType ignored -> BuiltInRegistries.RULE_BLOCK_ENTITY_MODIFIER; + case PosRuleTestType ignored -> BuiltInRegistries.POS_RULE_TEST; + case MenuType ignored -> BuiltInRegistries.MENU; + case RecipeType ignored -> BuiltInRegistries.RECIPE_TYPE; + case RecipeSerializer ignored -> BuiltInRegistries.RECIPE_SERIALIZER; + case Attribute ignored -> BuiltInRegistries.ATTRIBUTE; + case PositionSourceType ignored -> BuiltInRegistries.POSITION_SOURCE_TYPE; + case ArgumentTypeInfo ignored -> BuiltInRegistries.COMMAND_ARGUMENT_TYPE; + case StatType ignored -> BuiltInRegistries.STAT_TYPE; + case VillagerType ignored -> BuiltInRegistries.VILLAGER_TYPE; + case VillagerProfession ignored -> BuiltInRegistries.VILLAGER_PROFESSION; + case PoiType ignored -> BuiltInRegistries.POINT_OF_INTEREST_TYPE; + case MemoryModuleType ignored -> BuiltInRegistries.MEMORY_MODULE_TYPE; + case SensorType ignored -> BuiltInRegistries.SENSOR_TYPE; + case Schedule ignored -> BuiltInRegistries.SCHEDULE; + case Activity ignored -> BuiltInRegistries.ACTIVITY; + case LootPoolEntryType ignored -> BuiltInRegistries.LOOT_POOL_ENTRY_TYPE; + case LootItemFunctionType ignored -> BuiltInRegistries.LOOT_FUNCTION_TYPE; + case LootItemConditionType ignored -> BuiltInRegistries.LOOT_CONDITION_TYPE; + case LootNumberProviderType ignored -> BuiltInRegistries.LOOT_NUMBER_PROVIDER_TYPE; + case LootNbtProviderType ignored -> BuiltInRegistries.LOOT_NBT_PROVIDER_TYPE; + case LootScoreProviderType ignored -> BuiltInRegistries.LOOT_SCORE_PROVIDER_TYPE; + case FloatProviderType ignored -> BuiltInRegistries.FLOAT_PROVIDER_TYPE; + case IntProviderType ignored -> BuiltInRegistries.INT_PROVIDER_TYPE; + case HeightProviderType ignored -> BuiltInRegistries.HEIGHT_PROVIDER_TYPE; + case BlockPredicateType ignored -> BuiltInRegistries.BLOCK_PREDICATE_TYPE; + case WorldCarver ignored -> BuiltInRegistries.CARVER; + case Feature ignored -> BuiltInRegistries.FEATURE; + case StructurePlacementType ignored -> BuiltInRegistries.STRUCTURE_PLACEMENT; + case StructurePieceType ignored -> BuiltInRegistries.STRUCTURE_PIECE; + case StructureType ignored -> BuiltInRegistries.STRUCTURE_TYPE; + case PlacementModifierType ignored -> BuiltInRegistries.PLACEMENT_MODIFIER_TYPE; + case BlockStateProviderType ignored -> BuiltInRegistries.BLOCKSTATE_PROVIDER_TYPE; + case FoliagePlacerType ignored -> BuiltInRegistries.FOLIAGE_PLACER_TYPE; + case TrunkPlacerType ignored -> BuiltInRegistries.TRUNK_PLACER_TYPE; + case RootPlacerType ignored -> BuiltInRegistries.ROOT_PLACER_TYPE; + case TreeDecoratorType ignored -> BuiltInRegistries.TREE_DECORATOR_TYPE; + case FeatureSizeType ignored -> BuiltInRegistries.FEATURE_SIZE_TYPE; + case StructureProcessorType ignored -> BuiltInRegistries.STRUCTURE_PROCESSOR; + case StructurePoolElementType ignored -> BuiltInRegistries.STRUCTURE_POOL_ELEMENT; + case CatVariant ignored -> BuiltInRegistries.CAT_VARIANT; + case FrogVariant ignored -> BuiltInRegistries.FROG_VARIANT; + case Instrument ignored -> BuiltInRegistries.INSTRUMENT; + case DecoratedPotPattern ignored -> BuiltInRegistries.DECORATED_POT_PATTERN; + case CreativeModeTab ignored -> BuiltInRegistries.CREATIVE_MODE_TAB; + case CriterionTrigger ignored -> BuiltInRegistries.TRIGGER_TYPES; + case NumberFormatType ignored -> BuiltInRegistries.NUMBER_FORMAT_TYPE; + case ArmorMaterial ignored -> BuiltInRegistries.ARMOR_MATERIAL; + case ItemSubPredicate.Type ignored -> BuiltInRegistries.ITEM_SUB_PREDICATE_TYPE; + case MapDecorationType ignored -> BuiltInRegistries.MAP_DECORATION_TYPE; + default -> null; + } + ); } - /** - *

A helper class to get the associated {@link Registry} for an object like a Block or Item.

- * - * @since 2.0.0, MC 1.20.4, 2023.12.18 - INTERNAL - */ - private static final class RegistryHelper + @SuppressWarnings("unchecked") + public Optional> getRegistryFor(final ResourceKey key) { - - /** - * Use a List instead of a HashSet because we don't want RegistryEntry#hashCode being called from a static context, which will cause - * the associated Registry to be supplied to get it's RegistryKey. This could cause a ClassNotFoundException in a dev environment - * since this will likely load before Minecraft classes. - */ - private static final List> ENTRIES; - - static - { - ENTRIES = ImmutableList.>builder().add( - RegistryEntry.make(Block.class, () -> BuiltInRegistries.BLOCK), - RegistryEntry.make(Fluid.class, () -> BuiltInRegistries.FLUID), - RegistryEntry.make(Item.class, () -> BuiltInRegistries.ITEM), - RegistryEntry.make(MobEffect.class, () -> BuiltInRegistries.MOB_EFFECT), - RegistryEntry.make(Potion.class, () -> BuiltInRegistries.POTION), - RegistryEntry.make(Attribute.class, () -> BuiltInRegistries.ATTRIBUTE), - RegistryEntry.make(StatType.class, () -> BuiltInRegistries.STAT_TYPE), - RegistryEntry.make(SoundEvent.class, () -> BuiltInRegistries.SOUND_EVENT), - RegistryEntry.make(Enchantment.class, () -> BuiltInRegistries.ENCHANTMENT), - RegistryEntry.make(EntityType.class, () -> BuiltInRegistries.ENTITY_TYPE), - RegistryEntry.make(PaintingVariant.class, () -> BuiltInRegistries.PAINTING_VARIANT), - RegistryEntry.make(ParticleType.class, () -> BuiltInRegistries.PARTICLE_TYPE), - RegistryEntry.make(MenuType.class, () -> BuiltInRegistries.MENU), - RegistryEntry.make(BlockEntityType.class, () -> BuiltInRegistries.BLOCK_ENTITY_TYPE), - RegistryEntry.make(RecipeType.class, () -> BuiltInRegistries.RECIPE_TYPE), - RegistryEntry.make(RecipeSerializer.class, () -> BuiltInRegistries.RECIPE_SERIALIZER), - RegistryEntry.make(VillagerProfession.class, () -> BuiltInRegistries.VILLAGER_PROFESSION), - RegistryEntry.make(PoiType.class, () -> BuiltInRegistries.POINT_OF_INTEREST_TYPE), - RegistryEntry.make(MemoryModuleType.class, () -> BuiltInRegistries.MEMORY_MODULE_TYPE), - RegistryEntry.make(SensorType.class, () -> BuiltInRegistries.SENSOR_TYPE), - RegistryEntry.make(Schedule.class, () -> BuiltInRegistries.SCHEDULE), - RegistryEntry.make(Activity.class, () -> BuiltInRegistries.ACTIVITY), - RegistryEntry.make(WorldCarver.class, () -> BuiltInRegistries.CARVER), - RegistryEntry.make(Feature.class, () -> BuiltInRegistries.FEATURE), - RegistryEntry.make(ChunkStatus.class, () -> BuiltInRegistries.CHUNK_STATUS), - RegistryEntry.make(BlockStateProviderType.class, () -> BuiltInRegistries.BLOCKSTATE_PROVIDER_TYPE), - RegistryEntry.make(FoliagePlacerType.class, () -> BuiltInRegistries.FOLIAGE_PLACER_TYPE), - RegistryEntry.make(TreeDecoratorType.class, () -> BuiltInRegistries.TREE_DECORATOR_TYPE) - ).build(); - } - - @SuppressWarnings("unchecked") - public static Optional> getFromType(final Class type) - { - return ENTRIES.stream() - .filter(entry -> entry.type().isAssignableFrom(type)) - .findFirst() - .map(RegistryEntry::registry) - .map(Supplier::get) - .map(registry -> (Registry) registry); - } - - /** - *

An entry class linking a Class to an associated {@link Registry} for an object like a Block or Item.

- * - * @param registry A Supplier for the Registry instance. - * @param The object type of the registry. - */ - public record RegistryEntry(Class type, Supplier> registry) - { - /** - * The {@link ResourceKey} of the {@link Registry} is sufficient in determining equality. - */ - @Override - public boolean equals(final Object obj) - { - return this == obj || obj instanceof RegistryEntry other && Identity.isEqual(registry().get().key(), other.registry().get().key()); - } - - /** - * The {@link ResourceKey} of the {@link Registry} is sufficient in calculating the hashCode. - */ - @Override - public int hashCode() - { - return Identity.getResKeyHashCode(registry().get().key()); - } - - private static RegistryEntry make(final Class type, final Supplier> registry) - { - return new RegistryEntry<>(type, registry); - } + if (key.registry().equals(Registries.ROOT_REGISTRY_NAME)) { + return BuiltInRegistries.REGISTRY.getHolder(key.location()).map(holder -> (Registry) holder.value()); + } else { + return BuiltInRegistries.REGISTRY.getHolder(key.registry()).map(holder -> (Registry) holder.value()); } }