From 0e84d40cc800521bf64b55ec032280fa33e90f97 Mon Sep 17 00:00:00 2001 From: XFactHD Date: Sat, 25 May 2024 20:53:23 +0200 Subject: [PATCH] Move all extensible enums and their usages to data-driven enum extension --- gradle.properties | 3 +- .../vertex/VertexFormatElement.java.patch | 9 +- .../client/RecipeBookCategories.java.patch | 24 +- .../net/minecraft/client/gui/Gui.java.patch | 18 +- .../client/model/HumanoidModel.java.patch | 34 +-- .../damagesource/DamageEffects.java.patch | 47 ++-- .../damagesource/DamageScaling.java.patch | 39 ++-- .../damagesource/DeathMessageType.java.patch | 39 ++-- .../world/entity/MobCategory.java.patch | 39 +--- .../world/entity/raid/Raid.java.patch | 50 ++-- .../world/inventory/RecipeBookType.java.patch | 18 +- .../world/item/ItemDisplayContext.java.patch | 58 +++-- .../minecraft/world/item/Rarity.java.patch | 46 +--- .../component/FireworkExplosion.java.patch | 41 ++-- .../biome/BiomeSpecialEffects.java.patch | 48 ++-- projects/neoforge/build.gradle | 1 - .../neoforge/common/IExtensibleEnum.java | 70 ------ .../neoforge/common/NeoForgeMod.java | 19 -- .../common/data/ExtensibleEnumProvider.java | 220 ++++++++++++++++++ .../registries/NeoForgeRegistries.java | 7 - .../registries/NeoForgeRegistriesSetup.java | 4 - .../resources/META-INF/accesstransformer.cfg | 3 +- .../damage_type/test.json | 6 +- .../neoforge/debug/client/RenderTests.java | 11 +- .../debug/damagesource/DamageTypeTests.java | 21 +- .../neoforge/debug/item/ItemTests.java | 14 +- .../model/CustomItemDisplayContextTest.java | 10 +- .../CreateEntityClassificationTest.java | 2 +- .../entity/player/ItemUseAnimationTest.java | 22 +- .../RecipeBookExtensionClientHelper.java | 21 +- .../recipebook/RecipeBookExtensionTest.java | 2 +- .../neoforge/oldtest/world/RaidEnumTest.java | 12 +- .../main/resources/META-INF/enumextender.json | 112 +++++++++ .../resources/META-INF/neoforge.mods.toml | 1 + 34 files changed, 647 insertions(+), 424 deletions(-) delete mode 100644 src/main/java/net/neoforged/neoforge/common/IExtensibleEnum.java create mode 100644 src/main/java/net/neoforged/neoforge/common/data/ExtensibleEnumProvider.java create mode 100644 tests/src/main/resources/META-INF/enumextender.json diff --git a/gradle.properties b/gradle.properties index b30c42f8ad3..2d43de60ab9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -31,7 +31,7 @@ jetbrains_annotations_version=24.0.1 slf4j_api_version=2.0.7 apache_maven_artifact_version=3.8.5 jarjar_version=0.4.1 -fancy_mod_loader_version=3.0.45 +fancy_mod_loader_version=4.0.2 mojang_logging_version=1.1.1 log4j_version=2.22.1 guava_version=31.1.2-jre @@ -39,7 +39,6 @@ gson_version=2.10.1 apache_commons_lang3_version=3.13.0 jopt_simple_version=5.0.4 commons_io_version=2.13.0 -unsafe_version=0.2.+ typetools_version=0.6.3 nashorn_core_version=15.3 lwjgl_glfw_version=3.3.2 diff --git a/patches/com/mojang/blaze3d/vertex/VertexFormatElement.java.patch b/patches/com/mojang/blaze3d/vertex/VertexFormatElement.java.patch index 171f07a16ad..58433a6f82c 100644 --- a/patches/com/mojang/blaze3d/vertex/VertexFormatElement.java.patch +++ b/patches/com/mojang/blaze3d/vertex/VertexFormatElement.java.patch @@ -16,12 +16,13 @@ @OnlyIn(Dist.CLIENT) public static enum Type { FLOAT(4, "Float", 5126), -@@ -113,7 +_,7 @@ +@@ -113,7 +_,8 @@ } @OnlyIn(Dist.CLIENT) - public static enum Usage { -+ public static enum Usage implements net.neoforged.neoforge.common.IExtensibleEnum { ++ @net.neoforged.fml.common.asm.enumextension.NamedEnum ++ public static enum Usage implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { POSITION( "Position", (p_349733_, p_349734_, p_349735_, p_349736_, p_349737_) -> GlStateManager._vertexAttribPointer( @@ -31,8 +32,8 @@ void setupBufferState(int p_167053_, int p_167054_, int p_167055_, long p_167056_, int p_167057_); + } + -+ public static Usage create(String name, String usageName, SetupState setupState) { -+ throw new IllegalArgumentException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(VertexFormatElement.Usage.class); } } } diff --git a/patches/net/minecraft/client/RecipeBookCategories.java.patch b/patches/net/minecraft/client/RecipeBookCategories.java.patch index 8de2ed39c11..6cf176e5823 100644 --- a/patches/net/minecraft/client/RecipeBookCategories.java.patch +++ b/patches/net/minecraft/client/RecipeBookCategories.java.patch @@ -5,11 +5,11 @@ @OnlyIn(Dist.CLIENT) -public enum RecipeBookCategories { -+public enum RecipeBookCategories implements net.neoforged.neoforge.common.IExtensibleEnum { ++public enum RecipeBookCategories implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { CRAFTING_SEARCH(new ItemStack(Items.COMPASS)), CRAFTING_BUILDING_BLOCKS(new ItemStack(Blocks.BRICKS)), CRAFTING_REDSTONE(new ItemStack(Items.REDSTONE)), -@@ -38,16 +_,7 @@ +@@ -38,20 +_,20 @@ public static final List CRAFTING_CATEGORIES = ImmutableList.of( CRAFTING_SEARCH, CRAFTING_EQUIPMENT, CRAFTING_BUILDING_BLOCKS, CRAFTING_MISC, CRAFTING_REDSTONE ); @@ -24,9 +24,22 @@ - ImmutableList.of(SMOKER_FOOD) - ); + public static final Map> AGGREGATE_CATEGORIES = net.neoforged.neoforge.client.RecipeBookManager.getAggregateCategories(); ++ @Deprecated // Neo: Empty for custom categories. Use the getter. private final List itemIcons; ++ private final java.util.function.Supplier> itemIconsSupplier; ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private RecipeBookCategories(ItemStack... p_92267_) { + this.itemIcons = ImmutableList.copyOf(p_92267_); ++ this.itemIconsSupplier = () -> this.itemIcons; ++ } ++ ++ private RecipeBookCategories(java.util.function.Supplier> itemIconsSupplier) { ++ this.itemIcons = List.of(); ++ this.itemIconsSupplier = itemIconsSupplier; + } + + public static List getCategories(RecipeBookType p_92270_) { @@ -60,10 +_,15 @@ case FURNACE -> FURNACE_CATEGORIES; case BLAST_FURNACE -> BLAST_FURNACE_CATEGORIES; @@ -36,10 +49,11 @@ } public List getIconItems() { - return this.itemIcons; +- return this.itemIcons; ++ return this.itemIconsSupplier.get(); + } + -+ public static RecipeBookCategories create(String name, ItemStack... icons) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(RecipeBookCategories.class); } } diff --git a/patches/net/minecraft/client/gui/Gui.java.patch b/patches/net/minecraft/client/gui/Gui.java.patch index 73aae38cda8..2cefaca0949 100644 --- a/patches/net/minecraft/client/gui/Gui.java.patch +++ b/patches/net/minecraft/client/gui/Gui.java.patch @@ -381,11 +381,11 @@ + @OnlyIn(Dist.CLIENT) - public static enum HeartType { -+ public static enum HeartType implements net.neoforged.neoforge.common.IExtensibleEnum { ++ public static enum HeartType implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { CONTAINER( ResourceLocation.withDefaultNamespace("hud/heart/container"), ResourceLocation.withDefaultNamespace("hud/heart/container_blinking"), -@@ -1409,8 +_,23 @@ +@@ -1409,8 +_,13 @@ } else { gui$hearttype = NORMAL; } @@ -394,18 +394,8 @@ return gui$hearttype; + } + -+ public static HeartType create( -+ String name, -+ ResourceLocation full, -+ ResourceLocation fullBlinking, -+ ResourceLocation half, -+ ResourceLocation halfBlinking, -+ ResourceLocation hardcoreFull, -+ ResourceLocation hardcoreFullBlinking, -+ ResourceLocation hardcoreHalf, -+ ResourceLocation hardcoreHalfBlinking -+ ) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(Gui.HeartType.class); } } } diff --git a/patches/net/minecraft/client/model/HumanoidModel.java.patch b/patches/net/minecraft/client/model/HumanoidModel.java.patch index d305c8ea66d..b067ead7deb 100644 --- a/patches/net/minecraft/client/model/HumanoidModel.java.patch +++ b/patches/net/minecraft/client/model/HumanoidModel.java.patch @@ -23,37 +23,39 @@ @OnlyIn(Dist.CLIENT) - public static enum ArmPose { -+ public static enum ArmPose implements net.neoforged.neoforge.common.IExtensibleEnum { ++ public static enum ArmPose implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { EMPTY(false), ITEM(false), BLOCK(false), -@@ -462,10 +_,29 @@ +@@ -459,13 +_,31 @@ + BRUSH(false); + private final boolean twoHanded; ++ @org.jetbrains.annotations.Nullable ++ private final net.neoforged.neoforge.client.IArmPoseTransformer forgeArmPose; + ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private ArmPose(boolean p_102896_) { this.twoHanded = p_102896_; + this.forgeArmPose = null; - } - - public boolean isTwoHanded() { - return this.twoHanded; - } -+ // FORGE START -+ @org.jetbrains.annotations.Nullable -+ private final net.neoforged.neoforge.client.IArmPoseTransformer forgeArmPose; ++ } + -+ private ArmPose(boolean twoHanded, @javax.annotation.Nonnull net.neoforged.neoforge.client.IArmPoseTransformer forgeArmPose) { ++ private ArmPose(boolean twoHanded, net.neoforged.neoforge.client.IArmPoseTransformer forgeArmPose) { + this.twoHanded = twoHanded; + com.google.common.base.Preconditions.checkNotNull(forgeArmPose, "Cannot create new ArmPose with null transformer!"); + this.forgeArmPose = forgeArmPose; -+ } -+ -+ public static ArmPose create(String name, boolean twoHanded, @javax.annotation.Nonnull net.neoforged.neoforge.client.IArmPoseTransformer forgeArmPose) { -+ throw new IllegalStateException("Enum not extended"); + } + + public boolean isTwoHanded() { + return this.twoHanded; + } + + public void applyTransform(HumanoidModel model, T entity, net.minecraft.world.entity.HumanoidArm arm) { + if (this.forgeArmPose != null) this.forgeArmPose.applyTransform(model, entity, arm); + } -+ // FORGE END ++ ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(HumanoidModel.ArmPose.class); + } } } diff --git a/patches/net/minecraft/world/damagesource/DamageEffects.java.patch b/patches/net/minecraft/world/damagesource/DamageEffects.java.patch index e5e7b48a373..e694d480baa 100644 --- a/patches/net/minecraft/world/damagesource/DamageEffects.java.patch +++ b/patches/net/minecraft/world/damagesource/DamageEffects.java.patch @@ -1,32 +1,39 @@ --- a/net/minecraft/world/damagesource/DamageEffects.java +++ b/net/minecraft/world/damagesource/DamageEffects.java -@@ -5,7 +_,7 @@ +@@ -5,7 +_,9 @@ import net.minecraft.sounds.SoundEvents; import net.minecraft.util.StringRepresentable; -public enum DamageEffects implements StringRepresentable { -+public enum DamageEffects implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.NamedEnum ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++public enum DamageEffects implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { HURT("hurt", SoundEvents.PLAYER_HURT), THORNS("thorns", SoundEvents.THORNS_HIT), DROWNING("drowning", SoundEvents.PLAYER_HURT_DROWN), -@@ -13,13 +_,13 @@ - POKING("poking", SoundEvents.PLAYER_HURT_SWEET_BERRY_BUSH), - FREEZING("freezing", SoundEvents.PLAYER_HURT_FREEZE); +@@ -15,11 +_,19 @@ -- public static final Codec CODEC = StringRepresentable.fromEnum(DamageEffects::values); -+ public static final Codec CODEC = Codec.lazyInitialized(() -> StringRepresentable.fromEnum(DamageEffects::values)); + public static final Codec CODEC = StringRepresentable.fromEnum(DamageEffects::values); private final String id; + @Deprecated // Neo: Always set to null. Use the getter. private final SoundEvent sound; ++ private final java.util.function.Supplier soundSupplier; ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private DamageEffects(String p_270875_, SoundEvent p_270383_) { - this.id = p_270875_; - this.sound = p_270383_; + this(p_270875_, () -> p_270383_); ++ } ++ ++ private DamageEffects(String id, java.util.function.Supplier sound) { ++ this.id = id; ++ this.soundSupplier = sound; ++ this.sound = null; } @Override -@@ -28,6 +_,30 @@ +@@ -28,6 +_,10 @@ } public SoundEvent sound() { @@ -34,27 +41,7 @@ + return this.soundSupplier.get(); + } + -+ private final java.util.function.Supplier soundSupplier; -+ -+ private DamageEffects(String id, java.util.function.Supplier sound) { -+ this.id = id; -+ this.soundSupplier = sound; -+ this.sound = null; -+ } -+ -+ /** -+ * Creates a new DamageEffects with the specified ID and sound.
-+ * Example usage: -+ *
-+     * public static final DamageEffects ELECTRIFYING = DamageEffects.create("MYMOD_ELECTRIFYING", "mymod:electrifying", MySounds.ELECTRIFYING);
-+     * 
-+ * @param name The {@linkplain Enum#name() true enum name}. Prefix this with your modid. -+ * @param id The {@linkplain StringRepresentable#getSerializedName() serialized name}. Prefix this with your modid and `:` -+ * @param sound The sound event that will play when a damage type with this effect deals damage to a player. -+ * @return A newly created DamageEffects. Store this result in a static final field. -+ * @apiNote This method must be called as early as possible, as if {@link #CODEC} is resolved before this is called, it will be unusable. -+ */ -+ public static DamageEffects create(String name, String id, java.util.function.Supplier sound) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(DamageEffects.class); } } diff --git a/patches/net/minecraft/world/damagesource/DamageScaling.java.patch b/patches/net/minecraft/world/damagesource/DamageScaling.java.patch index d6c682a1706..5f8532b4cef 100644 --- a/patches/net/minecraft/world/damagesource/DamageScaling.java.patch +++ b/patches/net/minecraft/world/damagesource/DamageScaling.java.patch @@ -1,34 +1,35 @@ --- a/net/minecraft/world/damagesource/DamageScaling.java +++ b/net/minecraft/world/damagesource/DamageScaling.java -@@ -3,20 +_,51 @@ +@@ -3,20 +_,41 @@ import com.mojang.serialization.Codec; import net.minecraft.util.StringRepresentable; -public enum DamageScaling implements StringRepresentable { -+public enum DamageScaling implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.NamedEnum ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++public enum DamageScaling implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { NEVER("never"), WHEN_CAUSED_BY_LIVING_NON_PLAYER("when_caused_by_living_non_player"), ALWAYS("always"); -- public static final Codec CODEC = StringRepresentable.fromEnum(DamageScaling::values); -+ public static final Codec CODEC = Codec.lazyInitialized(() -> StringRepresentable.fromEnum(DamageScaling::values)); + public static final Codec CODEC = StringRepresentable.fromEnum(DamageScaling::values); private final String id; ++ private final net.neoforged.neoforge.common.damagesource.IScalingFunction scaling; ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private DamageScaling(String p_270266_) { - this.id = p_270266_; + this(p_270266_, net.neoforged.neoforge.common.damagesource.IScalingFunction.DEFAULT); - } - - @Override - public String getSerializedName() { - return this.id; + } + -+ private final net.neoforged.neoforge.common.damagesource.IScalingFunction scaling; -+ + private DamageScaling(String id, net.neoforged.neoforge.common.damagesource.IScalingFunction scaling) { + this.id = id; + this.scaling = scaling; + } + + @Override + public String getSerializedName() { + return this.id; + } + + /** @@ -39,19 +40,7 @@ + return this.scaling; + } + -+ /** -+ * Creates a new DamageScaling with the specified ID and scaling function.
-+ * Example usage: -+ *
-+     * public static final DamageScaling CUSTOM_SCALING = DamageEffects.create("MYMOD_CUSTOM", "mymod:custom", MyMod.CUSTOM_SCALING_FUNCTION);
-+     * 
-+ * @param name The {@linkplain Enum#name() true enum name}. Prefix this with your modid. -+ * @param id The {@linkplain StringRepresentable#getSerializedName() serialized name}. Prefix this with your modid and `:` -+ * @param scaling The scaling function that will be used when a player is hurt by a damage type with this type of scaling. -+ * @return A newly created DamageScaling. Store this result in a static final field. -+ * @apiNote This method must be called as early as possible, as if {@link #CODEC} is resolved before this is called, it will be unusable. -+ */ -+ public static DamageScaling create(String name, String id, net.neoforged.neoforge.common.damagesource.IScalingFunction scaling) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(DamageScaling.class); } } diff --git a/patches/net/minecraft/world/damagesource/DeathMessageType.java.patch b/patches/net/minecraft/world/damagesource/DeathMessageType.java.patch index 3095a21a68f..b3a4b1e4293 100644 --- a/patches/net/minecraft/world/damagesource/DeathMessageType.java.patch +++ b/patches/net/minecraft/world/damagesource/DeathMessageType.java.patch @@ -1,34 +1,35 @@ --- a/net/minecraft/world/damagesource/DeathMessageType.java +++ b/net/minecraft/world/damagesource/DeathMessageType.java -@@ -3,20 +_,51 @@ +@@ -3,20 +_,41 @@ import com.mojang.serialization.Codec; import net.minecraft.util.StringRepresentable; -public enum DeathMessageType implements StringRepresentable { -+public enum DeathMessageType implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.NamedEnum ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++public enum DeathMessageType implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { DEFAULT("default"), FALL_VARIANTS("fall_variants"), INTENTIONAL_GAME_DESIGN("intentional_game_design"); -- public static final Codec CODEC = StringRepresentable.fromEnum(DeathMessageType::values); -+ public static final Codec CODEC = Codec.lazyInitialized(() -> StringRepresentable.fromEnum(DeathMessageType::values)); + public static final Codec CODEC = StringRepresentable.fromEnum(DeathMessageType::values); private final String id; ++ private final net.neoforged.neoforge.common.damagesource.IDeathMessageProvider msgFunction; ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private DeathMessageType(String p_270201_) { - this.id = p_270201_; + this(p_270201_, net.neoforged.neoforge.common.damagesource.IDeathMessageProvider.DEFAULT); - } - - @Override - public String getSerializedName() { - return this.id; + } + -+ private final net.neoforged.neoforge.common.damagesource.IDeathMessageProvider msgFunction; -+ + private DeathMessageType(String id, net.neoforged.neoforge.common.damagesource.IDeathMessageProvider msgFunction) { + this.id = id; + this.msgFunction = msgFunction; + } + + @Override + public String getSerializedName() { + return this.id; + } + + /** @@ -39,19 +40,7 @@ + return this.msgFunction; + } + -+ /** -+ * Creates a new DeathMessageType with the specified ID and death message provider.
-+ * Example usage: -+ *
-+     * public static final DeathMessageType CUSTOM_FUNCTION = DeathMessageType.create("MYMOD_CUSTOM", "mymod:custom", MyMod.CUSTOM_MESSAGE_PROVIDER);
-+     * 
-+ * @param name The {@linkplain Enum#name() true enum name}. Prefix this with your modid. -+ * @param id The {@linkplain StringRepresentable#getSerializedName() serialized name}. Prefix this with your modid and `:` -+ * @param scaling The scaling function that will be used when a player is hurt by a damage type with this type of scaling. -+ * @return A newly created DamageScaling. Store this result in a static final field. -+ * @apiNote This method must be called as early as possible, as if {@link #CODEC} is resolved before this is called, it will be unusable. -+ */ -+ public static DeathMessageType create(String name, String id, net.neoforged.neoforge.common.damagesource.IDeathMessageProvider msgFunction) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(DeathMessageType.class); } } diff --git a/patches/net/minecraft/world/entity/MobCategory.java.patch b/patches/net/minecraft/world/entity/MobCategory.java.patch index 82cac1f9bc7..f6931a27a47 100644 --- a/patches/net/minecraft/world/entity/MobCategory.java.patch +++ b/patches/net/minecraft/world/entity/MobCategory.java.patch @@ -1,43 +1,22 @@ --- a/net/minecraft/world/entity/MobCategory.java +++ b/net/minecraft/world/entity/MobCategory.java -@@ -3,7 +_,7 @@ +@@ -3,7 +_,8 @@ import com.mojang.serialization.Codec; import net.minecraft.util.StringRepresentable; -public enum MobCategory implements StringRepresentable { -+public enum MobCategory implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.NamedEnum ++public enum MobCategory implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { MONSTER("monster", 70, false, false, 128), CREATURE("creature", 10, true, true, 128), AMBIENT("ambient", 15, true, false, 128), -@@ -13,7 +_,8 @@ - WATER_AMBIENT("water_ambient", 20, true, false, 64), - MISC("misc", -1, true, true, 128); +@@ -56,5 +_,9 @@ -- public static final Codec CODEC = StringRepresentable.fromEnum(MobCategory::values); -+ public static final Codec CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createCodecForExtensibleEnum(MobCategory::values, MobCategory::byName); -+ private static final java.util.Map BY_NAME = java.util.Arrays.stream(values()).collect(java.util.stream.Collectors.toMap(MobCategory::getName, mobCategory -> mobCategory)); - private final int max; - private final boolean isFriendly; - private final boolean isPersistent; -@@ -48,6 +_,21 @@ - - public boolean isPersistent() { - return this.isPersistent; -+ } -+ -+ public static MobCategory create(String name, String id, int maxNumberOfCreatureIn, boolean isPeacefulCreatureIn, boolean isAnimalIn, int despawnDistance) { -+ throw new IllegalStateException("Enum not extended"); + public int getNoDespawnDistance() { + return 32; + } + -+ @Override -+ @Deprecated -+ public void init() { -+ BY_NAME.put(this.getName(), this); -+ } -+ -+ // Forge: Access enum members by name -+ public static MobCategory byName(String name) { -+ return BY_NAME.get(name); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(MobCategory.class); } - - public int getDespawnDistance() { + } diff --git a/patches/net/minecraft/world/entity/raid/Raid.java.patch b/patches/net/minecraft/world/entity/raid/Raid.java.patch index c57342dfb09..2175381fabf 100644 --- a/patches/net/minecraft/world/entity/raid/Raid.java.patch +++ b/patches/net/minecraft/world/entity/raid/Raid.java.patch @@ -1,32 +1,56 @@ --- a/net/minecraft/world/entity/raid/Raid.java +++ b/net/minecraft/world/entity/raid/Raid.java +@@ -503,7 +_,7 @@ + int k = 0; + + for (int l = 0; l < j; l++) { +- Raider raider = raid$raidertype.entityType.create(this.level); ++ Raider raider = raid$raidertype.entityTypeSupplier.get().create(this.level); + if (raider == null) { + break; + } +@@ -515,7 +_,7 @@ + } + + this.joinRaid(i, raider, p_37756_, false); +- if (raid$raidertype.entityType == EntityType.RAVAGER) { ++ if (raid$raidertype.entityTypeSupplier.get() == EntityType.RAVAGER) { + Raider raider1 = null; + if (i == this.getNumGroups(Difficulty.NORMAL)) { + raider1 = EntityType.PILLAGER.create(this.level); @@ -834,7 +_,7 @@ } } -- static enum RaiderType { -+ public static enum RaiderType implements net.neoforged.neoforge.common.IExtensibleEnum { +- public static enum RaiderType { ++ public static enum RaiderType implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { VINDICATOR(EntityType.VINDICATOR, new int[]{0, 0, 2, 0, 1, 4, 2, 5}), EVOKER(EntityType.EVOKER, new int[]{0, 0, 0, 0, 0, 1, 1, 2}), PILLAGER(EntityType.PILLAGER, new int[]{0, 4, 3, 3, 4, 4, 4, 2}), -@@ -848,6 +_,20 @@ +@@ -842,12 +_,26 @@ + RAVAGER(EntityType.RAVAGER, new int[]{0, 0, 0, 1, 0, 1, 0, 2}); + + static final Raid.RaiderType[] VALUES = values(); ++ @Deprecated // Neo: null for custom types, use the supplier instead + final EntityType entityType; + final int[] spawnsPerWaveBeforeBonus; ++ final java.util.function.Supplier> entityTypeSupplier; + ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private RaiderType(EntityType p_37821_, int[] p_37822_) { this.entityType = p_37821_; this.spawnsPerWaveBeforeBonus = p_37822_; ++ this.entityTypeSupplier = () -> p_37821_; + } + -+ /** -+ * The waveCountsIn integer decides how many entities of the EntityType defined in typeIn will spawn in each wave. -+ * For example, one ravager will always spawn in wave 3. -+ */ -+ public static RaiderType create(String name, EntityType typeIn, int[] waveCountsIn) { -+ throw new IllegalStateException("Enum not extended"); ++ private RaiderType(java.util.function.Supplier> entityTypeSupplier, int[] spawnsPerWave) { ++ this.entityType = null; ++ this.spawnsPerWaveBeforeBonus = spawnsPerWave; ++ this.entityTypeSupplier = entityTypeSupplier; + } + -+ @Override -+ @Deprecated -+ public void init() { -+ VALUES = values(); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(Raid.RaiderType.class); } } } diff --git a/patches/net/minecraft/world/inventory/RecipeBookType.java.patch b/patches/net/minecraft/world/inventory/RecipeBookType.java.patch index 781f8d6f256..067d904167d 100644 --- a/patches/net/minecraft/world/inventory/RecipeBookType.java.patch +++ b/patches/net/minecraft/world/inventory/RecipeBookType.java.patch @@ -1,22 +1,24 @@ --- a/net/minecraft/world/inventory/RecipeBookType.java +++ b/net/minecraft/world/inventory/RecipeBookType.java -@@ -1,8 +_,18 @@ +@@ -1,8 +_,20 @@ package net.minecraft.world.inventory; -public enum RecipeBookType { -+public enum RecipeBookType implements net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++public enum RecipeBookType implements net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { CRAFTING, FURNACE, BLAST_FURNACE, SMOKER; + -+ public static RecipeBookType create(String name) { -+ throw new IllegalStateException("Enum not extended!"); ++ RecipeBookType() { ++ if (ordinal() >= 4) { ++ String name = this.name().toLowerCase(java.util.Locale.ROOT).replace("_", ""); ++ net.minecraft.stats.RecipeBookSettings.addTagsForType(this, "is" + name + "GuiOpen", "is" + name + "FilteringCraftable"); ++ } + } + -+ @Override -+ public void init() { -+ String name = this.name().toLowerCase(java.util.Locale.ROOT).replace("_",""); -+ net.minecraft.stats.RecipeBookSettings.addTagsForType(this, "is" + name + "GuiOpen", "is" + name + "FilteringCraftable"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(RecipeBookType.class); + } } diff --git a/patches/net/minecraft/world/item/ItemDisplayContext.java.patch b/patches/net/minecraft/world/item/ItemDisplayContext.java.patch index 41f8bbeaadf..8b3daba123e 100644 --- a/patches/net/minecraft/world/item/ItemDisplayContext.java.patch +++ b/patches/net/minecraft/world/item/ItemDisplayContext.java.patch @@ -1,60 +1,56 @@ --- a/net/minecraft/world/item/ItemDisplayContext.java +++ b/net/minecraft/world/item/ItemDisplayContext.java -@@ -5,7 +_,7 @@ +@@ -5,7 +_,10 @@ import net.minecraft.util.ByIdMap; import net.minecraft.util.StringRepresentable; -public enum ItemDisplayContext implements StringRepresentable { -+public enum ItemDisplayContext implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.IndexedEnum ++@net.neoforged.fml.common.asm.enumextension.NamedEnum(1) ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++public enum ItemDisplayContext implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { NONE(0, "none"), THIRD_PERSON_LEFT_HAND(1, "thirdperson_lefthand"), THIRD_PERSON_RIGHT_HAND(2, "thirdperson_righthand"), -@@ -16,14 +_,16 @@ - GROUND(7, "ground"), - FIXED(8, "fixed"); - -- public static final Codec CODEC = StringRepresentable.fromEnum(ItemDisplayContext::values); -- public static final IntFunction BY_ID = ByIdMap.continuous(ItemDisplayContext::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); -+ public static final Codec CODEC = net.neoforged.neoforge.registries.NeoForgeRegistries.DISPLAY_CONTEXTS.byNameCodec(); -+ public static final IntFunction BY_ID = id -> java.util.Objects.requireNonNullElse(net.neoforged.neoforge.registries.NeoForgeRegistries.DISPLAY_CONTEXTS.byId(id < 0 ? Byte.MAX_VALUE + -id : id), NONE); - private byte id; +@@ -20,10 +_,22 @@ + public static final IntFunction BY_ID = ByIdMap.continuous(ItemDisplayContext::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO); + private final byte id; private final String name; ++ private final boolean isModded; ++ private final java.util.function.Supplier fallback; ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor private ItemDisplayContext(int p_270624_, String p_270851_) { this.name = p_270851_; this.id = (byte)p_270624_; + this.isModded = false; -+ this.fallback = null; ++ this.fallback = () -> null; ++ } ++ ++ private ItemDisplayContext(int id, String name, @org.jetbrains.annotations.Nullable String fallbackName) { ++ this.id = (byte)id; ++ this.name = name; ++ this.isModded = true; ++ this.fallback = fallbackName == null ? () -> null : com.google.common.base.Suppliers.memoize(() -> ItemDisplayContext.valueOf(fallbackName)); } @Override -@@ -38,4 +_,29 @@ +@@ -37,5 +_,18 @@ + public boolean firstPerson() { return this == FIRST_PERSON_LEFT_HAND || this == FIRST_PERSON_RIGHT_HAND; - } -+ -+ // Forge start -+ private final boolean isModded; -+ @org.jetbrains.annotations.Nullable -+ private final ItemDisplayContext fallback; -+ -+ private ItemDisplayContext(net.minecraft.resources.ResourceLocation serializeName, ItemDisplayContext fallback) { -+ this.id = 0; // If the context is never registered then it should be treated as the NONE one -+ this.name = java.util.Objects.requireNonNull(serializeName, "Modded ItemDisplayContexts must have a non-null serializeName").toString(); -+ this.isModded = true; -+ this.fallback = fallback; + } + + public boolean isModded() { + return isModded; + } + -+ public @org.jetbrains.annotations.Nullable ItemDisplayContext fallback() { -+ return fallback; ++ @org.jetbrains.annotations.Nullable ++ public ItemDisplayContext fallback() { ++ return fallback.get(); + } + -+ public static ItemDisplayContext create(String keyName, net.minecraft.resources.ResourceLocation serializedName, @org.jetbrains.annotations.Nullable ItemDisplayContext fallback) { -+ throw new IllegalStateException("Enum not extended!"); -+ } -+ public static final net.neoforged.neoforge.registries.callback.AddCallback ADD_CALLBACK = (registry, id, key, obj) -> obj.id = id > Byte.MAX_VALUE ? (byte) -(id - Byte.MAX_VALUE) : (byte) id; // if the ID is > 127 start doing negative IDs ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(ItemDisplayContext.class); + } } diff --git a/patches/net/minecraft/world/item/Rarity.java.patch b/patches/net/minecraft/world/item/Rarity.java.patch index 382082dec70..b2d929a1261 100644 --- a/patches/net/minecraft/world/item/Rarity.java.patch +++ b/patches/net/minecraft/world/item/Rarity.java.patch @@ -1,22 +1,18 @@ --- a/net/minecraft/world/item/Rarity.java +++ b/net/minecraft/world/item/Rarity.java -@@ -9,31 +_,69 @@ +@@ -9,7 +_,10 @@ import net.minecraft.util.ByIdMap; import net.minecraft.util.StringRepresentable; -public enum Rarity implements StringRepresentable { -+public enum Rarity implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++@net.neoforged.fml.common.asm.enumextension.IndexedEnum ++@net.neoforged.fml.common.asm.enumextension.NamedEnum(1) ++@net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.BIDIRECTIONAL) ++public enum Rarity implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { COMMON(0, "common", ChatFormatting.WHITE), UNCOMMON(1, "uncommon", ChatFormatting.YELLOW), RARE(2, "rare", ChatFormatting.AQUA), - EPIC(3, "epic", ChatFormatting.LIGHT_PURPLE); - -- public static final Codec CODEC = StringRepresentable.fromValues(Rarity::values); -+ private static final java.util.Map BY_NAME = java.util.Arrays.stream(values()).collect(java.util.stream.Collectors.toMap(rarity -> rarity.name, rarity -> rarity)); -+ public static final Codec CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createCodecForExtensibleEnum(Rarity::values, Rarity::byName); - public static final IntFunction BY_ID = ByIdMap.continuous(p_335877_ -> p_335877_.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO); -- public static final StreamCodec STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, p_335484_ -> p_335484_.id); -+ public static final StreamCodec STREAM_CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createStreamCodecForExtensibleEnum(Rarity::values); +@@ -21,19 +_,38 @@ private final int id; private final String name; private final ChatFormatting color; @@ -31,18 +27,14 @@ + this.styleModifier = style -> style.withColor(p_43028_); + } + -+ Rarity(net.minecraft.resources.ResourceLocation serializedName, java.util.function.UnaryOperator styleModifier) { -+ this.id = 0; -+ this.name = java.util.Objects.requireNonNull(serializedName, "Modded Rarities must have a non-null serializedName").toString(); ++ Rarity(int id, String name, java.util.function.UnaryOperator styleModifier) { ++ this.id = id; ++ this.name = name; + this.color = ChatFormatting.BLACK; + this.styleModifier = styleModifier; + } + -+ Rarity(net.minecraft.resources.ResourceLocation serializedName, ChatFormatting color) { -+ this(0, java.util.Objects.requireNonNull(serializedName, "Modded Rarities must have a non-null serializedName").toString(), color); -+ } -+ -+ /** @deprecated Forge: Use {@link #getStyleModifier()} */ ++ /** @deprecated NeoForge: Use {@link #getStyleModifier()} */ + @Deprecated public ChatFormatting color() { return this.color; @@ -57,21 +49,7 @@ return this.name; + } + -+ @Override -+ @Deprecated -+ public void init() { -+ BY_NAME.put(this.name, this); -+ } -+ -+ public static Rarity byName(String name) { -+ return BY_NAME.get(name); -+ } -+ -+ public static Rarity create(String name, net.minecraft.resources.ResourceLocation serializedName, ChatFormatting color) { -+ throw new IllegalStateException("Enum not extended"); -+ } -+ -+ public static Rarity create(String name, net.minecraft.resources.ResourceLocation serializedName, java.util.function.UnaryOperator styleModifier) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(Rarity.class); } } diff --git a/patches/net/minecraft/world/item/component/FireworkExplosion.java.patch b/patches/net/minecraft/world/item/component/FireworkExplosion.java.patch index da064b016e2..ca06424293f 100644 --- a/patches/net/minecraft/world/item/component/FireworkExplosion.java.patch +++ b/patches/net/minecraft/world/item/component/FireworkExplosion.java.patch @@ -1,40 +1,25 @@ --- a/net/minecraft/world/item/component/FireworkExplosion.java +++ b/net/minecraft/world/item/component/FireworkExplosion.java -@@ -107,7 +_,7 @@ +@@ -107,7 +_,10 @@ return new FireworkExplosion(this.shape, this.colors, new IntArrayList(p_330678_), this.hasTrail, this.hasTwinkle); } - public static enum Shape implements StringRepresentable { -+ public static enum Shape implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++ @net.neoforged.fml.common.asm.enumextension.IndexedEnum ++ @net.neoforged.fml.common.asm.enumextension.NamedEnum(1) ++ @net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.BIDIRECTIONAL) ++ public static enum Shape implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { SMALL_BALL(0, "small_ball"), LARGE_BALL(1, "large_ball"), STAR(2, "star"), -@@ -117,8 +_,8 @@ - private static final IntFunction BY_ID = ByIdMap.continuous( - FireworkExplosion.Shape::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO - ); -- public static final StreamCodec STREAM_CODEC = ByteBufCodecs.idMapper(BY_ID, FireworkExplosion.Shape::getId); -- public static final Codec CODEC = StringRepresentable.fromValues(FireworkExplosion.Shape::values); -+ public static final StreamCodec STREAM_CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createStreamCodecForExtensibleEnum(Shape::values); -+ public static final Codec CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createCodecForExtensibleEnum(Shape::values, Shape::getShape); - private final int id; - private final String name; - -@@ -137,6 +_,17 @@ - - public static FireworkExplosion.Shape byId(int p_330838_) { - return BY_ID.apply(p_330838_); -+ } -+ -+ public static FireworkExplosion.Shape getShape(String name) { -+ for (Shape ret : values()) -+ if (ret.name().equals(name)) -+ return ret; -+ return SMALL_BALL; +@@ -142,6 +_,10 @@ + @Override + public String getSerializedName() { + return this.name; + } + -+ public static Shape create(String registryName, int id, String shapeName) { -+ throw new IllegalStateException("Enum not extended"); ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(FireworkExplosion.Shape.class); } - - @Override + } + } diff --git a/patches/net/minecraft/world/level/biome/BiomeSpecialEffects.java.patch b/patches/net/minecraft/world/level/biome/BiomeSpecialEffects.java.patch index 401e3805cfd..212f97fe12d 100644 --- a/patches/net/minecraft/world/level/biome/BiomeSpecialEffects.java.patch +++ b/patches/net/minecraft/world/level/biome/BiomeSpecialEffects.java.patch @@ -1,51 +1,53 @@ --- a/net/minecraft/world/level/biome/BiomeSpecialEffects.java +++ b/net/minecraft/world/level/biome/BiomeSpecialEffects.java -@@ -212,7 +_,7 @@ +@@ -212,7 +_,9 @@ } } - public static enum GrassColorModifier implements StringRepresentable { -+ public static enum GrassColorModifier implements StringRepresentable, net.neoforged.neoforge.common.IExtensibleEnum { ++ @net.neoforged.fml.common.asm.enumextension.NamedEnum ++ @net.neoforged.fml.common.asm.enumextension.NetworkedEnum(net.neoforged.fml.common.asm.enumextension.NetworkedEnum.NetworkCheck.CLIENTBOUND) ++ public static enum GrassColorModifier implements StringRepresentable, net.neoforged.fml.common.asm.enumextension.IExtensibleEnum { NONE("none") { @Override public int modifyColor(double p_48081_, double p_48082_, int p_48083_) { -@@ -234,14 +_,37 @@ +@@ -234,12 +_,22 @@ }; private final String name; -- public static final Codec CODEC = StringRepresentable.fromEnum(BiomeSpecialEffects.GrassColorModifier::values); -+ public static final Codec CODEC = net.neoforged.neoforge.common.IExtensibleEnum.createCodecForExtensibleEnum(BiomeSpecialEffects.GrassColorModifier::values, BiomeSpecialEffects.GrassColorModifier::byName); -+ private static final java.util.Map BY_NAME = java.util.Arrays.stream(values()).collect(java.util.stream.Collectors.toMap(BiomeSpecialEffects.GrassColorModifier::getName, grassColorModifier -> grassColorModifier)); ++ private final ColorModifier delegate; + public static final Codec CODEC = StringRepresentable.fromEnum(BiomeSpecialEffects.GrassColorModifier::values); - public abstract int modifyColor(double p_48065_, double p_48066_, int p_48067_); + public int modifyColor(double p_48065_, double p_48066_, int p_48067_) { + return delegate.modifyGrassColor(p_48065_, p_48066_, p_48067_); + } ++ @net.neoforged.fml.common.asm.enumextension.ReservedConstructor GrassColorModifier(String p_48058_) { this.name = p_48058_; ++ this.delegate = null; ++ } ++ ++ GrassColorModifier(String name, ColorModifier delegate) { ++ this.name = name; ++ this.delegate = delegate; } -+ private ColorModifier delegate; -+ private GrassColorModifier(String name, ColorModifier delegate) { -+ this(name); -+ this.delegate = delegate; -+ } -+ public static GrassColorModifier create(String name, String id, ColorModifier delegate) { -+ throw new IllegalStateException("Enum not extended"); -+ } -+ @Override -+ public void init() { -+ BY_NAME.put(this.getName(), this); + public String getName() { +@@ -249,6 +_,15 @@ + @Override + public String getSerializedName() { + return this.name; + } -+ // Forge: Access enum members by name -+ public static BiomeSpecialEffects.GrassColorModifier byName(String name) { -+ return BY_NAME.get(name); ++ ++ public static net.neoforged.fml.common.asm.enumextension.ExtensionInfo getExtensionInfo() { ++ return net.neoforged.fml.common.asm.enumextension.ExtensionInfo.nonExtended(BiomeSpecialEffects.GrassColorModifier.class); + } ++ + @FunctionalInterface + public interface ColorModifier { + int modifyGrassColor(double x, double z, int color); -+ } - public String getName() { - return this.name; } + } + } diff --git a/projects/neoforge/build.gradle b/projects/neoforge/build.gradle index 453ca110051..119dcbea8e9 100644 --- a/projects/neoforge/build.gradle +++ b/projects/neoforge/build.gradle @@ -73,7 +73,6 @@ dependencies { installer "net.neoforged:bus:${project.eventbus_version}" installer "net.neoforged:coremods:${project.coremods_version}" installer "cpw.mods:modlauncher:${project.modlauncher_version}" - installer "net.minecraftforge:unsafe:${project.unsafe_version}" installer "net.neoforged:mergetool:${project.mergetool_version}:api" installer "com.electronwill.night-config:core:${project.nightconfig_version}" installer "com.electronwill.night-config:toml:${project.nightconfig_version}" diff --git a/src/main/java/net/neoforged/neoforge/common/IExtensibleEnum.java b/src/main/java/net/neoforged/neoforge/common/IExtensibleEnum.java deleted file mode 100644 index 5d21f0c0776..00000000000 --- a/src/main/java/net/neoforged/neoforge/common/IExtensibleEnum.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.neoforged.neoforge.common; - -import com.mojang.datafixers.util.Either; -import com.mojang.serialization.Codec; -import com.mojang.serialization.DataResult; -import io.netty.buffer.ByteBuf; -import java.util.function.Function; -import java.util.function.IntFunction; -import java.util.function.Supplier; -import java.util.function.ToIntFunction; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.util.StringRepresentable; - -/** - * To be implemented on vanilla enums that should be enhanced with ASM to be - * extensible. If this is implemented on a class, the class must define a static - * method called "create" which takes a String (enum name), and the rest of the - * parameters matching a constructor. - *

- * For example, an enum with the constructor {@code MyEnum(Object foo)} would - * require the method: - * - *

- * public static MyEnum create(String name, Object foo) {
- *     throw new IllegalStateException("Enum not extended");
- * }
- * 
- * - * The method contents will be replaced with ASM at runtime. Multiple - * {@code create} methods can be defined as long as each - * matches a constructor. - */ -public interface IExtensibleEnum { - /** - * Called by generated factory code to do any post-constructor setup required by - * the enum. Should not be called manually. - */ - @Deprecated - default void init() {} - - /** - * Use this instead of {@link StringRepresentable#fromEnum(Supplier)} for extensible enums because this not cache the enum values on construction - */ - static & StringRepresentable> Codec createCodecForExtensibleEnum(Supplier valuesSupplier, Function enumValueFromNameFunction) { - return Codec.either(Codec.STRING, Codec.INT).comapFlatMap( - either -> either.map( - str -> { - var val = enumValueFromNameFunction.apply(str); - return val != null ? DataResult.success(val) : DataResult.error(() -> "Unknown enum value name: " + str); - }, - num -> { - var values = valuesSupplier.get(); - return num >= 0 && num < values.length ? DataResult.success(values[num]) : DataResult.error(() -> "Unknown enum id: " + num); - }), - value -> Either.left(value.getSerializedName())); - } - - /** - * Use this instead of {@link ByteBufCodecs#idMapper(IntFunction, ToIntFunction)} for extensible enums because this not cache the enum values on construction - */ - static & StringRepresentable> StreamCodec createStreamCodecForExtensibleEnum(Supplier valuesSupplier) { - return ByteBufCodecs.VAR_INT.map(i -> valuesSupplier.get()[i], Enum::ordinal); - } -} diff --git a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java index 535ce408b95..71861b234ad 100644 --- a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java +++ b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java @@ -9,7 +9,6 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import java.util.Arrays; import java.util.EnumSet; import java.util.List; import java.util.Optional; @@ -18,7 +17,6 @@ import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; -import java.util.function.Predicate; import net.minecraft.DetectedVersion; import net.minecraft.advancements.critereon.EntitySubPredicate; import net.minecraft.advancements.critereon.ItemSubPredicate; @@ -31,8 +29,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; -import net.minecraft.core.MappedRegistry; -import net.minecraft.core.RegistrationInfo; import net.minecraft.core.RegistryCodecs; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.Registries; @@ -56,7 +52,6 @@ import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.RangedAttribute; import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.BlockGetter; @@ -78,7 +73,6 @@ import net.minecraft.world.level.pathfinder.PathType; import net.minecraft.world.phys.Vec3; import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.CrashReportCallables; import net.neoforged.fml.ModContainer; @@ -599,7 +593,6 @@ public NeoForgeMod(IEventBus modEventBus, Dist dist, ModContainer container) { modEventBus.addListener(this::gatherData); modEventBus.addListener(this::loadComplete); modEventBus.addListener(this::registerFluids); - modEventBus.addListener(EventPriority.HIGHEST, this::registerVanillaDisplayContexts); modEventBus.addListener(this::registerLootData); ATTRIBUTES.register(modEventBus); COMMAND_ARGUMENT_TYPES.register(modEventBus); @@ -728,18 +721,6 @@ public ResourceLocation getFlowingTexture() { } } - @SuppressWarnings("unchecked") - public void registerVanillaDisplayContexts(RegisterEvent event) { - if (!event.getRegistryKey().equals(NeoForgeRegistries.Keys.DISPLAY_CONTEXTS)) { - return; - } - MappedRegistry forgeRegistry = (MappedRegistry) event.getRegistry(); - - Arrays.stream(ItemDisplayContext.values()) - .filter(Predicate.not(ItemDisplayContext::isModded)) - .forEach(ctx -> forgeRegistry.register(ctx.getId(), ResourceKey.create(NeoForgeRegistries.Keys.DISPLAY_CONTEXTS, ResourceLocation.fromNamespaceAndPath("minecraft", ctx.getSerializedName())), ctx, RegistrationInfo.BUILT_IN)); - } - public void registerLootData(RegisterEvent event) { if (!event.getRegistryKey().equals(Registries.LOOT_CONDITION_TYPE)) return; diff --git a/src/main/java/net/neoforged/neoforge/common/data/ExtensibleEnumProvider.java b/src/main/java/net/neoforged/neoforge/common/data/ExtensibleEnumProvider.java new file mode 100644 index 00000000000..b0bb7264588 --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/common/data/ExtensibleEnumProvider.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.common.data; + +import com.google.common.base.Preconditions; +import com.google.common.primitives.Primitives; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonNull; +import com.google.gson.JsonObject; +import com.mojang.datafixers.util.Pair; +import com.mojang.logging.LogUtils; +import java.lang.reflect.AccessFlag; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import net.minecraft.data.CachedOutput; +import net.minecraft.data.DataProvider; +import net.minecraft.data.PackOutput; +import net.neoforged.fml.common.asm.enumextension.IExtensibleEnum; +import net.neoforged.fml.common.asm.enumextension.ReservedConstructor; +import net.neoforged.fml.util.ObfuscationReflectionHelper; +import org.objectweb.asm.Type; +import org.slf4j.Logger; + +public abstract class ExtensibleEnumProvider implements DataProvider { + private static final Logger LOGGER = LogUtils.getLogger(); + + private final PackOutput packOutput; + private final String modId; + private final List> builders = new ArrayList<>(); + + public ExtensibleEnumProvider(PackOutput packOutput, String modId) { + this.packOutput = packOutput; + this.modId = modId; + } + + protected abstract void addEnumExtensions(); + + protected final & IExtensibleEnum> EnumEntryBuilder builder(Class enumClass) { + EnumEntryBuilder builder = new EnumEntryBuilder<>(modId, enumClass); + builders.add(builder); + return builder; + } + + @Override + public final CompletableFuture run(CachedOutput output) { + addEnumExtensions(); + if (!builders.isEmpty()) { + JsonObject json = new JsonObject(); + json.addProperty("modid", modId); + JsonArray entryArr = new JsonArray(builders.size()); + for (EnumEntryBuilder builder : builders) { + entryArr.add(builder.build()); + } + json.add("entries", entryArr); + return DataProvider.saveStable( + output, + json, + packOutput.getOutputFolder().resolve("META-INF").resolve("enumextender.json")); + } + return CompletableFuture.allOf(); + } + + @Override + public String getName() { + return "enum_extensions"; + } + + public static class EnumEntryBuilder & IExtensibleEnum> { + private static final Set FLAGS = Set.of(AccessFlag.PUBLIC, AccessFlag.STATIC, AccessFlag.FINAL); + + private final String modId; + private final Class enumClass; + private String fieldName; + private Class[] ctorParamTypes; + private String ctorDescriptor; + private List constParams; + private Pair, String> lazyParams; + + private EnumEntryBuilder(String modId, Class enumClass) { + this.modId = modId; + this.enumClass = enumClass; + } + + public EnumEntryBuilder fieldName(String fieldName) { + if (!fieldName.toLowerCase(Locale.ROOT).startsWith(modId)) { + fieldName = modId + "_" + fieldName; + LOGGER.warn("Unprefixed enum field '{}' automatically prefixed with mod ID '{}'", fieldName, modId); + } + this.fieldName = fieldName; + return this; + } + + public EnumEntryBuilder constructor(Class... paramTypes) { + Class[] realParamTypes = new Class[2 + paramTypes.length]; + realParamTypes[0] = String.class; + realParamTypes[1] = int.class; + System.arraycopy(paramTypes, 0, realParamTypes, 2, paramTypes.length); + Constructor ctor = ObfuscationReflectionHelper.findConstructor(enumClass, realParamTypes); + if (ctor == null || ctor.isAnnotationPresent(ReservedConstructor.class)) { + throw new IllegalArgumentException(String.format( + Locale.ROOT, + "Cannot locate valid constructor in enum '%s' with parameters '%s'", + enumClass.getName(), + Arrays.toString(paramTypes))); + } + this.ctorParamTypes = paramTypes; + this.ctorDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, Arrays.stream(paramTypes).map(Type::getType).toArray(Type[]::new)); + return this; + } + + public EnumEntryBuilder constParameters(Object... parameters) { + Preconditions.checkState(lazyParams == null, "Cannot use both constant and lazy parameters"); + this.constParams = List.of(parameters); + return this; + } + + public EnumEntryBuilder lazyParameters(Class srcClass, String fieldName) { + Preconditions.checkState(constParams == null, "Cannot use both constant and lazy parameters"); + Field field = ObfuscationReflectionHelper.findField(srcClass, fieldName); + if (field == null) { + throw new IllegalArgumentException(String.format( + Locale.ROOT, + "Cannot locate field '%s' in class '%s'", + fieldName, + srcClass.getName())); + } + if (!field.accessFlags().containsAll(FLAGS)) { + throw new IllegalArgumentException(String.format( + Locale.ROOT, + "Parameter field '%s' in class '%s' must be public static final", + fieldName, + srcClass.getName())); + } + if (!List.class.isAssignableFrom(field.getType())) { + throw new IllegalArgumentException(String.format( + Locale.ROOT, + "Parameter field '%s' in class '%s' must be of type List", + fieldName, + srcClass.getName())); + } + this.lazyParams = Pair.of(srcClass, fieldName); + return this; + } + + JsonObject build() { + Preconditions.checkNotNull(fieldName, "Enum field name not set"); + Preconditions.checkNotNull(ctorDescriptor, "Constructor not set"); + Preconditions.checkState(constParams != null || lazyParams != null, "Parameters not set"); + + JsonObject obj = new JsonObject(); + obj.addProperty("enum", enumClass.getName().replace('.', '/')); + obj.addProperty("name", fieldName); + obj.addProperty("constructor", ctorDescriptor); + + JsonElement params; + if (constParams != null) { + params = buildConstantParameters(ctorParamTypes, constParams); + } else { + JsonObject paramObj = new JsonObject(); + paramObj.addProperty("class", lazyParams.getFirst().getName().replace('.', '/')); + paramObj.addProperty("field", lazyParams.getSecond()); + params = paramObj; + } + obj.add("parameters", params); + + return obj; + } + + private static JsonArray buildConstantParameters(Class[] ctorParamTypes, List constParams) { + JsonArray paramArr = new JsonArray(); + for (int idx = 0; idx < constParams.size(); idx++) { + Object param = constParams.get(idx); + + Class type = ctorParamTypes[idx]; + boolean valid = true; + if (type.isPrimitive()) { + if (param == null || !Primitives.wrap(type).isInstance(param)) { + valid = false; + } + } else { + if (param != null && !type.isInstance(param)) { + valid = false; + } + } + if (!valid) { + throw new IllegalArgumentException(String.format( + Locale.ROOT, + "Type of parameter '%s' does not match expected type '%s'", + param, + type.getName())); + } + + switch (param) { + case String string -> paramArr.add(string); + case Character ch -> paramArr.add(ch); + case Byte b -> paramArr.add(b); + case Short s -> paramArr.add(s); + case Integer i -> paramArr.add(i); + case Long l -> paramArr.add(l); + case Float f -> paramArr.add(f); + case Double d -> paramArr.add(d); + case Boolean bool -> paramArr.add(bool); + case null -> paramArr.add(JsonNull.INSTANCE); + default -> throw new IllegalArgumentException("Unsupported constant parameter: " + param); + } + } + return paramArr; + } + } +} diff --git a/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistries.java b/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistries.java index f5b0c7dccc1..964d86a8618 100644 --- a/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistries.java +++ b/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistries.java @@ -12,7 +12,6 @@ import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.ItemDisplayContext; import net.neoforged.neoforge.attachment.AttachmentType; import net.neoforged.neoforge.common.conditions.ICondition; import net.neoforged.neoforge.common.crafting.IngredientType; @@ -38,11 +37,6 @@ public class NeoForgeRegistries { public static final Registry> STRUCTURE_MODIFIER_SERIALIZERS = new RegistryBuilder<>(Keys.STRUCTURE_MODIFIER_SERIALIZERS).create(); public static final Registry FLUID_TYPES = new RegistryBuilder<>(Keys.FLUID_TYPES).sync(true).create(); public static final Registry HOLDER_SET_TYPES = new RegistryBuilder<>(Keys.HOLDER_SET_TYPES).create(); - public static final Registry DISPLAY_CONTEXTS = new RegistryBuilder<>(Keys.DISPLAY_CONTEXTS) - .sync(true) - .maxId(128 * 2) // 0 -> 127 gets positive ID, 128 -> 256 gets negative ID - .defaultKey(ResourceLocation.withDefaultNamespace("none")) - .create(); public static final Registry> INGREDIENT_TYPES = new RegistryBuilder<>(Keys.INGREDIENT_TYPES).sync(true).create(); public static final Registry> FLUID_INGREDIENT_TYPES = new RegistryBuilder<>(Keys.FLUID_INGREDIENT_TYPES).sync(true).create(); public static final Registry> CONDITION_SERIALIZERS = new RegistryBuilder<>(Keys.CONDITION_CODECS).create(); @@ -58,7 +52,6 @@ public static final class Keys { public static final ResourceKey>> STRUCTURE_MODIFIER_SERIALIZERS = key("structure_modifier_serializers"); public static final ResourceKey> FLUID_TYPES = key("fluid_type"); public static final ResourceKey> HOLDER_SET_TYPES = key("holder_set_type"); - public static final ResourceKey> DISPLAY_CONTEXTS = key("display_contexts"); public static final ResourceKey>> INGREDIENT_TYPES = key("ingredient_serializer"); public static final ResourceKey>> FLUID_INGREDIENT_TYPES = key("fluid_ingredient_type"); public static final ResourceKey>> CONDITION_CODECS = key("condition_codecs"); diff --git a/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistriesSetup.java b/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistriesSetup.java index d244c9473eb..cc7655bc384 100644 --- a/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistriesSetup.java +++ b/src/main/java/net/neoforged/neoforge/registries/NeoForgeRegistriesSetup.java @@ -8,7 +8,6 @@ import java.util.Set; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.world.item.ItemDisplayContext; import net.neoforged.bus.api.IEventBus; import org.jetbrains.annotations.ApiStatus; @@ -65,7 +64,6 @@ private static void registerRegistries(NewRegistryEvent event) { event.register(NeoForgeRegistries.STRUCTURE_MODIFIER_SERIALIZERS); event.register(NeoForgeRegistries.FLUID_TYPES); event.register(NeoForgeRegistries.HOLDER_SET_TYPES); - event.register(NeoForgeRegistries.DISPLAY_CONTEXTS); event.register(NeoForgeRegistries.INGREDIENT_TYPES); event.register(NeoForgeRegistries.FLUID_INGREDIENT_TYPES); event.register(NeoForgeRegistries.CONDITION_SERIALIZERS); @@ -81,7 +79,5 @@ private static void modifyRegistries(ModifyRegistriesEvent event) { BuiltInRegistries.ITEM.addCallback(NeoForgeRegistryCallbacks.ItemCallbacks.INSTANCE); BuiltInRegistries.ATTRIBUTE.addCallback(NeoForgeRegistryCallbacks.AttributeCallbacks.INSTANCE); BuiltInRegistries.POINT_OF_INTEREST_TYPE.addCallback(NeoForgeRegistryCallbacks.PoiTypeCallbacks.INSTANCE); - // We add this callback here to not cause a tricky classloading loop with ForgeRegistries#DISPLAY_CONTEXTS and ItemDisplayContext#CODEC - NeoForgeRegistries.DISPLAY_CONTEXTS.addCallback(ItemDisplayContext.ADD_CALLBACK); } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 91e303bda6b..85cd1afc280 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -306,7 +306,7 @@ protected net.minecraft.world.entity.monster.WitherSkeleton getStepSound()Lnet/m public net.minecraft.world.entity.npc.VillagerType (Ljava/lang/String;)V # constructor public net.minecraft.world.entity.player.Player closeContainer()V # closeContainer protected net.minecraft.world.entity.projectile.Projectile (Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V # constructor -private-f net.minecraft.world.entity.raid.Raid$RaiderType VALUES # VALUES +public net.minecraft.world.entity.raid.Raid$RaiderType public net.minecraft.world.entity.schedule.Activity (Ljava/lang/String;)V # constructor protected net.minecraft.world.entity.vehicle.VehicleEntity getDropItem()Lnet/minecraft/world/item/Item; # getDropItem - make VehicleEntity implementable protected net.minecraft.world.entity.monster.Zombie conversionTime @@ -336,7 +336,6 @@ public net.minecraft.world.item.HoeItem (Lnet/minecraft/world/item/Tier;IF public net.minecraft.world.item.PickaxeItem (Lnet/minecraft/world/item/Tier;IFLnet/minecraft/world/item/Item$Properties;)V # constructor public net.minecraft.world.item.RecordItem (ILnet/minecraft/sounds/SoundEvent;Lnet/minecraft/world/item/Item$Properties;I)V # constructor #endgroup -private-f net.minecraft.world.item.ItemDisplayContext id # id private-f net.minecraft.world.item.Item components public net.minecraft.world.item.ItemStack (Lnet/minecraft/world/level/ItemLike;ILjava/util/Optional;)V # constructor public net.minecraft.world.item.ItemStackLinkedSet TYPE_AND_TAG # TYPE_AND_TAG diff --git a/tests/src/generated/resources/data/neotests_dmg_type_tests/damage_type/test.json b/tests/src/generated/resources/data/neotests_dmg_type_tests/damage_type/test.json index a6781ad5477..51f150e66d4 100644 --- a/tests/src/generated/resources/data/neotests_dmg_type_tests/damage_type/test.json +++ b/tests/src/generated/resources/data/neotests_dmg_type_tests/damage_type/test.json @@ -1,7 +1,7 @@ { - "death_message_type": "test:msgtype", - "effects": "test:effects", + "death_message_type": "neotests:msgtype", + "effects": "neotests:effects", "exhaustion": 0.0, "message_id": "test_mod", - "scaling": "test:scaling" + "scaling": "neotests:scaling" } \ No newline at end of file diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/client/RenderTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/client/RenderTests.java index 1462758b1c8..19dd9dba5a2 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/client/RenderTests.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/client/RenderTests.java @@ -9,6 +9,7 @@ import com.mojang.blaze3d.vertex.VertexFormatElement; import java.util.concurrent.atomic.AtomicInteger; import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.common.asm.enumextension.EnumProxy; import net.neoforged.neoforge.client.event.RenderLevelStageEvent; import net.neoforged.testframework.DynamicTest; import net.neoforged.testframework.annotation.ForEachTest; @@ -16,12 +17,18 @@ @ForEachTest(side = Dist.CLIENT, groups = { "client.render", "render" }) public class RenderTests { + private static final AtomicInteger STATE = new AtomicInteger(); + @SuppressWarnings("unused") // Referenced by enumextender.json + public static final EnumProxy USAGE_ENUM_PARAMS = new EnumProxy<>( + VertexFormatElement.Usage.class, + "neotests:test", + (VertexFormatElement.Usage.SetupState) (size, type, stride, offset, index) -> STATE.incrementAndGet()); + @TestHolder(description = { "Tests if custom VertexFormatElement.Usage setup and clear callbacks were called" }, enabledByDefault = true) static void setupClearVertexFormatElement(final DynamicTest test) { test.framework().modEventBus().addListener(RenderLevelStageEvent.RegisterStageEvent.class, event -> { var state = new AtomicInteger(); - var usage = VertexFormatElement.Usage.create("TEST", "Test", - (size, type, stride, offset, index) -> state.incrementAndGet()); + var usage = USAGE_ENUM_PARAMS.getValue(); var element = new VertexFormatElement(VertexFormatElement.findNextId(), 0, VertexFormatElement.Type.BYTE, usage, 4); var format = VertexFormat.builder().add("TEST", element).build(); diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/damagesource/DamageTypeTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/damagesource/DamageTypeTests.java index ac122f7aac4..24a5bbc89f8 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/damagesource/DamageTypeTests.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/damagesource/DamageTypeTests.java @@ -6,6 +6,7 @@ package net.neoforged.neoforge.debug.damagesource; import java.util.Set; +import java.util.function.Supplier; import net.minecraft.core.Holder; import net.minecraft.core.Registry; import net.minecraft.core.RegistrySetBuilder; @@ -14,6 +15,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.Difficulty; import net.minecraft.world.damagesource.DamageEffects; @@ -31,6 +33,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; +import net.neoforged.fml.common.asm.enumextension.EnumProxy; import net.neoforged.neoforge.common.damagesource.IDeathMessageProvider; import net.neoforged.neoforge.common.damagesource.IScalingFunction; import net.neoforged.neoforge.common.data.DatapackBuiltinEntriesProvider; @@ -58,9 +61,15 @@ public class DamageTypeTests { return Component.literal(entity.getName().getString() + " was killed via test damage by " + dmgSrc.getDirectEntity().getName().getString()); }; - public static final DamageEffects EFFECTS = DamageEffects.create("TEST_EFFECTS", "test:effects", () -> SoundEvents.DONKEY_ANGRY);; - public static final DamageScaling SCALING = DamageScaling.create("TEST_SCALING", "test:scaling", SCALE_FUNC); - public static final DeathMessageType MSGTYPE = DeathMessageType.create("TEST_MSGTYPE", "test:msgtype", MSG_PROVIDER); + @SuppressWarnings("unused") // referenced by enumextender.json + public static final EnumProxy EFFECTS_ENUM_PARAMS = new EnumProxy<>( + DamageEffects.class, "neotests:effects", (Supplier) () -> SoundEvents.DONKEY_ANGRY); + @SuppressWarnings("unused") // referenced by enumextender.json + public static final EnumProxy SCALING_ENUM_PARAMS = new EnumProxy<>( + DamageScaling.class, "neotests:scaling", SCALE_FUNC); + @SuppressWarnings("unused") // referenced by enumextender.json + public static final EnumProxy MSGTYPE_ENUM_PARAMS = new EnumProxy<>( + DeathMessageType.class, "neotests:msgtype", MSG_PROVIDER); @GameTest @EmptyTemplate @@ -68,6 +77,10 @@ public class DamageTypeTests { static void dmgTypeTests(final DynamicTest test, final RegistrationHelper reg) { ResourceKey TEST_DMG_TYPE = ResourceKey.create(Registries.DAMAGE_TYPE, ResourceLocation.fromNamespaceAndPath(reg.modId(), "test")); + DamageEffects effects = EFFECTS_ENUM_PARAMS.getValue(); + DamageScaling scaling = SCALING_ENUM_PARAMS.getValue(); + DeathMessageType msgType = MSGTYPE_ENUM_PARAMS.getValue(); + Holder customSword = reg.registrar(Registries.ITEM).register("custom_damage_sword", () -> new Item(new Item.Properties()) { @Override public boolean onLeftClickEntity(ItemStack stack, Player player, Entity entity) { @@ -80,7 +93,7 @@ public boolean onLeftClickEntity(ItemStack stack, Player player, Entity entity) RegistrySetBuilder registrySetBuilder = new RegistrySetBuilder(); registrySetBuilder.add(Registries.DAMAGE_TYPE, bootstrap -> { - bootstrap.register(TEST_DMG_TYPE, new DamageType("test_mod", SCALING, 0.0f, EFFECTS, MSGTYPE)); + bootstrap.register(TEST_DMG_TYPE, new DamageType("test_mod", scaling, 0.0f, effects, msgType)); }); reg.addProvider(event -> new DatapackBuiltinEntriesProvider( diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java index c1efb45eda5..850d82434db 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java @@ -6,6 +6,7 @@ package net.neoforged.neoforge.debug.item; import java.util.function.Supplier; +import java.util.function.UnaryOperator; import net.minecraft.ChatFormatting; import net.minecraft.client.renderer.entity.PigRenderer; import net.minecraft.core.BlockPos; @@ -13,6 +14,7 @@ import net.minecraft.core.dispenser.BlockSource; import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; import net.minecraft.gametest.framework.GameTest; +import net.minecraft.network.chat.Style; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.InteractionHand; @@ -140,11 +142,21 @@ public InteractionResultHolder use(Level level, Player player, Intera .thenSucceed()); } + @SuppressWarnings("unused") // Referenced by enumextender.json + public static Object getRarityEnumParameter(int idx, Class type) { + return type.cast(switch (idx) { + case 0 -> -1; + case 1 -> "neotests:custom"; + case 2 -> (UnaryOperator