diff --git a/build.gradle.kts b/build.gradle.kts index 8b9a57d..d708be5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,13 @@ +import com.github.minecraftschurlimods.helperplugin.version + plugins { idea + id("net.neoforged.gradle.userdev") id ("com.github.minecraftschurlimods.helperplugin") } +helper.withTestSourceSet() + repositories { maven { name = "blamejared Maven" @@ -14,21 +19,23 @@ repositories { } } +val jei = helper.dependencies.jei() + dependencies { implementation(helper.neoforge()) - compileOnly("mezz.jei:jei-1.20.4-common-api:${project.properties["dependency.jei.version"]}") - runtimeOnly("mezz.jei:jei-1.20.4-neoforge:${project.properties["dependency.jei.version"]}") + val jeiApiDep = helper.minecraftVersion.zip(jei.version) { mc, version -> "mezz.jei:jei-${mc}-common-api:${version}" } + val jeiDep = helper.minecraftVersion.zip(jei.version) { mc, version -> "mezz.jei:jei-${mc}-neoforge:${version}" } + compileOnly(jeiApiDep) + runtimeOnly(jeiDep) implementation("org.jetbrains:annotations:23.0.0") "testCompileOnly"("org.jetbrains:annotations:23.0.0") } -helper.withTestSourceSet() helper.withCommonRuns() helper.withGameTestRuns() helper.modproperties.put( - "catalogueItemIcon", helper.projectId.map { "$it:potion_bundle{Potion:\"minecraft:water\"}" } + "catalogueItemIcon", helper.projectId.map { "$it:potion_bundle[minecraft:potion_contents=\"minecraft:water\"]" } ) -helper.dependencies.jei() helper.publication.pom { organization { diff --git a/changelog.md b/changelog.md index e3d9d9e..c844cda 100644 --- a/changelog.md +++ b/changelog.md @@ -1,2 +1 @@ -# Changes -- Fixed a rare compatibility issue +# Updated to 1.20.6 diff --git a/gradle.properties b/gradle.properties index 1a05e56..69ae236 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,8 @@ org.gradle.daemon=false org.gradle.parallel=true org.gradle.caching=true +neogradle.subsystems.conventions.runs.create-default-run-per-type=false + mod.group=com.github.minecraftschurlimods mod.id=potionbundles mod.version=1.8 @@ -12,7 +14,7 @@ mod.authors=IchHabeHunger54, Minecraftschurli mod.description=Potions can now be bound into bundles, to save inventory space. mod.url=https://www.curseforge.com/minecraft/mc-mods/potion-bundles -java_version=17 +java_version=21 github.owner=MinecraftschurliMods github.repo=PotionBundles @@ -21,19 +23,19 @@ license.name=GPLv3 license.url=https://www.gnu.org/licenses/gpl-3.0.en.html license.file=LICENSE -neogradle.subsystems.parchment.minecraftVersion=1.20.3 -neogradle.subsystems.parchment.mappingsVersion=2023.12.31 +neogradle.subsystems.parchment.minecraftVersion=1.20.6 +neogradle.subsystems.parchment.mappingsVersion=2024.06.16 -mc_version=1.20.4 -mc_version_range=[1.20.4,1.20.5) +mc_version=1.20.6 +mc_version_range=[1.20.6,1.21) -neo_version=20.4.80-beta -neo_version_range=[20.4.80-beta,20.5) +neo_version=20.6.119 +neo_version_range=[20.6.115,21) -dependency.jei.version=17.3.0.49 -dependency.jei.version.range=[17.3,18) +dependency.jei.version=18.0.0.65 +dependency.jei.version.range=[18,19) -loader.version=[1,) +loader.version=[3,) mc-publish.curseforge=382836 mc-publish.modrinth=ZZLWU8jS diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 17655d0..48c0a02 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/settings.gradle.kts b/settings.gradle.kts index b2e09f8..6d1cef4 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ pluginManagement { plugins { - id("net.neoforged.gradle.userdev") version "7.0.80" - id("com.github.minecraftschurlimods.helperplugin") version "1.7" + id("net.neoforged.gradle.userdev") version "7.0.154" + id("com.github.minecraftschurlimods.helperplugin") version "1.14" } repositories { mavenLocal() @@ -12,7 +12,7 @@ pluginManagement { } plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.5.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "0.7.0" } rootProject.name = "PotionBundles" diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java index e0b178e..5e6fb93 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractPotionBundle.java @@ -1,25 +1,33 @@ package com.github.minecraftschurlimods.potionbundles; +import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; import net.minecraft.world.item.PotionItem; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.level.Level; +import net.minecraft.world.item.alchemy.PotionContents; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; import java.util.List; +import java.util.Optional; public abstract class AbstractPotionBundle extends PotionItem { public AbstractPotionBundle() { super(new Item.Properties().stacksTo(1)); } + @Override + public ItemStack getDefaultInstance() { + ItemStack itemstack = super.getDefaultInstance(); + itemstack.set(PotionBundles.USES, getMaxUses()); + return itemstack; + } + @VisibleForTesting public int getMaxUses() { return PotionBundles.POTION_BUNDLE_SIZE; @@ -32,7 +40,7 @@ public int getBarWidth(ItemStack stack) { } @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltip, TooltipFlag flag) { tooltip.add(Component.translatable(getDescriptionId() + ".uses", PotionBundleUtils.getUses(stack))); } @@ -48,15 +56,18 @@ public boolean isBarVisible(ItemStack stack) { @Override public Component getName(ItemStack stack) { - return Component.translatable(getDescriptionId(), Items.POTION.getName(stack)); + return Component.translatable(getDescriptionId(), PotionBundleUtils.getPotionForBundle(this).getName(stack)); + } + + @VisibleForTesting + public ItemStack createStack(@Nullable PotionBundleString string, Holder potion, List customEffects, @Nullable Integer customColor) { + return createStack(string, new PotionContents(Optional.of(potion), Optional.ofNullable(customColor), customEffects)); } @VisibleForTesting - public ItemStack createStack(ItemStack string, Potion potion, List customEffects, @Nullable Integer customColor) { + public ItemStack createStack(@Nullable PotionBundleString string, PotionContents potionContents) { ItemStack stack = new ItemStack(this); - PotionUtils.setPotion(stack, potion); - PotionUtils.setCustomEffects(stack, customEffects); - if (customColor != null) stack.getOrCreateTag().putInt("CustomPotionColor", customColor); + stack.set(DataComponents.POTION_CONTENTS, potionContents); PotionBundleUtils.setUses(stack, getMaxUses()); PotionBundleUtils.setString(stack, string); return stack; diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractThrowablePotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractThrowablePotionBundle.java index 792a20e..d16ced2 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractThrowablePotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/AbstractThrowablePotionBundle.java @@ -1,12 +1,12 @@ package com.github.minecraftschurlimods.potionbundles; +import net.minecraft.core.component.DataComponents; import net.minecraft.stats.Stats; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.ThrownPotion; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.PotionUtils; import net.minecraft.world.level.Level; public abstract class AbstractThrowablePotionBundle extends AbstractPotionBundle { @@ -16,17 +16,20 @@ public InteractionResultHolder use(Level world, Player player, Intera playThrowSound(world, player); if (!world.isClientSide) { ThrownPotion thrownpotion = new ThrownPotion(world, player); - ItemStack fake = new ItemStack(PotionBundleUtils.getPotionForBundle(world, this)); - PotionUtils.setPotion(fake, PotionUtils.getPotion(itemstack)); - PotionUtils.setCustomEffects(fake, PotionUtils.getCustomEffects(itemstack)); + ItemStack fake = new ItemStack(PotionBundleUtils.getPotionForBundle(this)); + fake.set(DataComponents.POTION_CONTENTS, itemstack.get(DataComponents.POTION_CONTENTS)); thrownpotion.setItem(fake); - thrownpotion.shootFromRotation(player, player.getXRot(), player.getYRot(), -20F, 0.5F, 1F); + thrownpotion.shootFromRotation(player, player.getXRot(), player.getYRot(), -20.0F, 0.5F, 1.0F); world.addFreshEntity(thrownpotion); } - PotionBundleUtils.decrementUses(itemstack); + if (!player.hasInfiniteMaterials()) { + PotionBundleUtils.decrementUses(itemstack); + } player.awardStat(Stats.ITEM_USED.get(this)); - if (PotionBundleUtils.getUses(itemstack) == 0) itemstack = Config.SERVER.returnString.get() ? PotionBundleUtils.getString(itemstack) : ItemStack.EMPTY; - return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + if (PotionBundleUtils.getUses(itemstack) != 0) { + return InteractionResultHolder.sidedSuccess(itemstack, world.isClientSide()); + } + return InteractionResultHolder.sidedSuccess(Config.SERVER.returnString.get() ? PotionBundleUtils.getString(itemstack) : ItemStack.EMPTY, world.isClientSide()); } protected abstract void playThrowSound(Level world, Player player); diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/ClientHandler.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/ClientHandler.java index e11650d..a2cd500 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/ClientHandler.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/ClientHandler.java @@ -2,23 +2,24 @@ import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.client.renderer.item.ItemPropertyFunction; +import net.minecraft.core.component.DataComponents; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.neoforged.api.distmarker.Dist; +import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.Mod; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.registries.DeferredHolder; -@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD, modid = PotionBundles.MODID) +@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = PotionBundles.MODID) public class ClientHandler { @SubscribeEvent public static void clientSetup(FMLClientSetupEvent e) { e.enqueueWork(() -> { @SuppressWarnings("deprecation") - ItemPropertyFunction propertyFunction = (stack, world, living, seed) -> !stack.hasTag() || !stack.getOrCreateTag().contains(PotionBundleUtils.USES_KEY) ? 0 : PotionBundleUtils.getUses(stack); + ItemPropertyFunction propertyFunction = (stack, world, living, seed) -> stack.getOrDefault(PotionBundles.USES, 0); ResourceLocation uses = new ResourceLocation(PotionBundles.MODID, "uses"); for (DeferredHolder item : PotionBundles.ITEMS.getEntries()) { ItemProperties.register(item.get(), uses, propertyFunction); @@ -28,6 +29,6 @@ public static void clientSetup(FMLClientSetupEvent e) { @SubscribeEvent public static void registerItemColorHandler(RegisterColorHandlersEvent.Item e) { - e.register((stack, index) -> index > 0 ? -1 : PotionUtils.getColor(stack), PotionBundles.ITEMS.getEntries().stream().map(DeferredHolder::get).toArray(Item[]::new)); + e.register((stack, index) -> index > 0 ? -1 : stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor(), PotionBundles.ITEMS.getEntries().stream().map(DeferredHolder::get).toArray(Item[]::new)); } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/JEICompat.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/JEICompat.java index b5227c4..f477868 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/JEICompat.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/JEICompat.java @@ -10,15 +10,27 @@ import mezz.jei.api.registration.ISubtypeRegistration; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.core.Holder; +import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; -import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.item.crafting.*; +import net.minecraft.world.item.alchemy.Potion; +import net.minecraft.world.item.alchemy.PotionContents; +import net.minecraft.world.item.crafting.CraftingBookCategory; +import net.minecraft.world.item.crafting.CraftingRecipe; +import net.minecraft.world.item.crafting.Ingredient; +import net.minecraft.world.item.crafting.RecipeHolder; +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.item.crafting.RecipeType; +import net.minecraft.world.item.crafting.ShapelessRecipe; +import net.neoforged.neoforge.common.crafting.DataComponentIngredient; import java.util.Objects; +import java.util.Optional; import java.util.stream.Stream; @JeiPlugin @@ -38,35 +50,38 @@ public void registerRecipes(final IRecipeRegistration registration) { .map(RecipeHolder::value) .filter(PotionBundleRecipe.class::isInstance) .map(PotionBundleRecipe.class::cast) - .flatMap(this::mapRecipes) + .flatMap(recipe -> mapRecipes(recipe, level.registryAccess())) .toList(); registration.addRecipes(RecipeTypes.CRAFTING, recipes); } - private Stream> mapRecipes(final PotionBundleRecipe recipe) { + private Stream> mapRecipes(final PotionBundleRecipe recipe, HolderLookup.Provider registries) { String group = "jei.potionbundle"; AbstractPotionBundle bundleItem = recipe.getBundleItem(); int maxUses = bundleItem.getMaxUses(); Item potionItem = recipe.getPotionItem(); - return BuiltInRegistries.POTION + return registries + .lookup(Registries.POTION) .stream() + .flatMap(HolderLookup::listElements) .map(potion -> { - Ingredient potionIngredient = Ingredient.of(PotionUtils.setPotion(new ItemStack(potionItem), potion)); + PotionContents potionContents = new PotionContents(potion); + Ingredient potionIngredient = DataComponentIngredient.of(false, DataComponents.POTION_CONTENTS, potionContents, potionItem); NonNullList inputs = NonNullList.withSize(maxUses + 1, Ingredient.EMPTY); for (int i = 0; i < maxUses; i++) { inputs.set(i, potionIngredient); } inputs.set(maxUses, recipe.getString()); - ItemStack output = PotionUtils.setPotion(new ItemStack(bundleItem), potion); + ItemStack output = PotionContents.createItemStack(bundleItem, potion); PotionBundleUtils.setUses(output, maxUses); - ResourceLocation id = new ResourceLocation(ModIds.MINECRAFT_ID, group + "." + output.getDescriptionId() + "." + potion.getName("")); + ResourceLocation id = new ResourceLocation(ModIds.MINECRAFT_ID, group + "." + output.getDescriptionId() + "." + Potion.getName(Optional.of(potion), "")); return new RecipeHolder<>(id, new ShapelessRecipe(group, CraftingBookCategory.EQUIPMENT, output, inputs)); }); } @Override public void registerItemSubtypes(ISubtypeRegistration r) { - IIngredientSubtypeInterpreter byPotion = (ingredient, context) -> String.valueOf(BuiltInRegistries.POTION.getKey(PotionUtils.getPotion(ingredient))); + IIngredientSubtypeInterpreter byPotion = (ingredient, context) -> ingredient.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).potion().map(Holder::getRegisteredName).orElse("unknown"); r.registerSubtypeInterpreter(VanillaTypes.ITEM_STACK, PotionBundles.POTION_BUNDLE.get(), byPotion); r.registerSubtypeInterpreter(VanillaTypes.ITEM_STACK, PotionBundles.SPLASH_POTION_BUNDLE.get(), byPotion); r.registerSubtypeInterpreter(VanillaTypes.ITEM_STACK, PotionBundles.LINGERING_POTION_BUNDLE.get(), byPotion); diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/LingeringPotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/LingeringPotionBundle.java index 8f65646..23446bb 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/LingeringPotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/LingeringPotionBundle.java @@ -1,22 +1,22 @@ package com.github.minecraftschurlimods.potionbundles; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; import java.util.List; public class LingeringPotionBundle extends AbstractThrowablePotionBundle { @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - PotionUtils.addPotionTooltip(stack, tooltip, 0.25F, world == null ? 20.0F : world.tickRateManager().tickrate()); - super.appendHoverText(stack, world, tooltip, flag); + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltip, TooltipFlag flag) { + stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).addPotionTooltip(tooltip::add, 0.25F, context.tickRate()); + super.appendHoverText(stack, context, tooltip, flag); } @Override diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundle.java index 34fae4e..1dcd1cf 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundle.java @@ -1,42 +1,63 @@ package com.github.minecraftschurlimods.potionbundles; import net.minecraft.advancements.CriteriaTriggers; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.stats.Stats; -import net.minecraft.world.effect.MobEffectInstance; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.level.Level; +import net.minecraft.world.level.gameevent.GameEvent; import net.neoforged.neoforge.items.ItemHandlerHelper; -import org.jetbrains.annotations.Nullable; import java.util.List; public class PotionBundle extends AbstractPotionBundle { @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - PotionUtils.addPotionTooltip(stack, tooltip, 1.0F, world == null ? 20.0F : world.tickRateManager().tickrate()); - super.appendHoverText(stack, world, tooltip, flag); + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltip, TooltipFlag flag) { + stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).addPotionTooltip(tooltip::add, 1.0F, context.tickRate()); + super.appendHoverText(stack, context, tooltip, flag); } @Override public ItemStack finishUsingItem(ItemStack stack, Level world, LivingEntity entity) { Player player = entity instanceof Player ? (Player) entity : null; if (player instanceof ServerPlayer) CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) player, stack); - if (!world.isClientSide) for (MobEffectInstance effect : PotionUtils.getMobEffects(stack)) { - if (effect.getEffect().isInstantenous()) effect.getEffect().applyInstantenousEffect(player, player, entity, effect.getAmplifier(), 1); - else entity.addEffect(new MobEffectInstance(effect)); + if (!world.isClientSide) { + PotionContents potioncontents = stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY); + potioncontents.forEachEffect(effectInstance -> { + if (effectInstance.getEffect().value().isInstantenous()) { + effectInstance.getEffect().value().applyInstantenousEffect(player, player, entity, effectInstance.getAmplifier(), 1.0); + } else { + entity.addEffect(effectInstance); + } + }); } - PotionBundleUtils.decrementUses(stack); - if (player != null) { - player.awardStat(Stats.ITEM_USED.get(this)); - ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.GLASS_BOTTLE)); + + if (player == null || !player.hasInfiniteMaterials()) { + PotionBundleUtils.decrementUses(stack); + + if (player != null) { + player.awardStat(Stats.ITEM_USED.get(this)); + ItemHandlerHelper.giveItemToPlayer(player, new ItemStack(Items.GLASS_BOTTLE)); + } + } + + entity.gameEvent(GameEvent.DRINK); + + if (PotionBundleUtils.getUses(stack) != 0) { + return stack; + } + + if (Config.SERVER.returnString.get()) { + return PotionBundleUtils.getString(stack); } - return PotionBundleUtils.getUses(stack) == 0 ? Config.SERVER.returnString.get() ? PotionBundleUtils.getString(stack) : ItemStack.EMPTY : stack; + + return ItemStack.EMPTY; } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleRecipe.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleRecipe.java index 10422cb..172ca58 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleRecipe.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleRecipe.java @@ -1,33 +1,43 @@ package com.github.minecraftschurlimods.potionbundles; -import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; +import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.core.RegistryAccess; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponents; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.PotionUtils; -import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.level.Level; -import java.util.List; +import java.util.Objects; import java.util.function.Function; public class PotionBundleRecipe extends CustomRecipe { - private static final Codec CODEC = RecordCodecBuilder.create(inst -> inst.group( + private static final MapCodec CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group( Ingredient.CODEC_NONEMPTY.fieldOf("string").forGetter(PotionBundleRecipe::getString), BuiltInRegistries.ITEM.byNameCodec().fieldOf("potion").forGetter(PotionBundleRecipe::getPotionItem), BuiltInRegistries.ITEM.byNameCodec().comapFlatMap(bundle -> bundle instanceof AbstractPotionBundle bundle1 ? DataResult.success(bundle1) : DataResult.error(() -> "The defined PotionBundle is not an instance of AbstractPotionBundle"), Function.identity()).fieldOf("bundle").forGetter(PotionBundleRecipe::getBundleItem) ).apply(inst, PotionBundleRecipe::new)); + private static final StreamCodec STREAM_CODEC = StreamCodec.composite( + Ingredient.CONTENTS_STREAM_CODEC, + PotionBundleRecipe::getString, + ByteBufCodecs.registry(Registries.ITEM), + PotionBundleRecipe::getPotionItem, + ByteBufCodecs.registry(Registries.ITEM).map(AbstractPotionBundle.class::cast, Function.identity()), + PotionBundleRecipe::getBundleItem, + PotionBundleRecipe::new + ); private final Ingredient string; private final Item potion; @@ -44,9 +54,7 @@ public PotionBundleRecipe(Ingredient string, Item potion, AbstractPotionBundle b public boolean matches(CraftingContainer inv, Level world) { int potions = 0; boolean string = false; - Potion potion = Potions.EMPTY; - List customEffects = null; - int color = 0; + PotionContents potionContents = null; for (int i = 0; i < inv.getContainerSize(); i++) { ItemStack is = inv.getItem(i); if (this.string.test(is)) { @@ -56,14 +64,12 @@ public boolean matches(CraftingContainer inv, Level world) { } if (is.getItem() == this.potion) { if (potions == 0) { - color = PotionUtils.getColor(is); - potion = PotionUtils.getPotion(is); - customEffects = PotionUtils.getCustomEffects(is); + potionContents = is.get(DataComponents.POTION_CONTENTS); potions++; } else if (potions > 0) { - if (PotionUtils.getColor(is) != color) return false; - if (PotionUtils.getPotion(is) != potion) return false; - if (!PotionUtils.getCustomEffects(is).equals(customEffects)) return false; + if (!Objects.equals(potionContents, is.get(DataComponents.POTION_CONTENTS))) { + return false; + } potions++; } if (potions > this.bundle.getMaxUses()) return false; @@ -75,20 +81,18 @@ public boolean matches(CraftingContainer inv, Level world) { } @Override - public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { - Potion potion = null; - List customEffects = null; - ItemStack string = null; - Integer customColor = null; + public ItemStack assemble(CraftingContainer inv, HolderLookup.Provider provider) { + PotionBundleString string = null; + PotionContents potionContents = null; for (int i = 0; i < inv.getContainerSize(); i++) { ItemStack is = inv.getItem(i); - if (potion == null && is.is(this.potion)) { - potion = PotionUtils.getPotion(is); - customEffects = PotionUtils.getCustomEffects(is); - if (is.getOrCreateTag().contains("CustomPotionColor", 99)) customColor = PotionUtils.getColor(is); + if (potionContents == null && is.is(this.potion)) { + potionContents = is.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY); } - if (string == null && this.string.test(is)) string = is.copy().split(1); - if (potion != null && string != null) return this.bundle.createStack(string, potion, customEffects, customColor); + if (string == null && this.string.test(is)) { + string = PotionBundleString.fromItemStack(is); + } + if (potionContents != null && string != null) return this.bundle.createStack(string, potionContents); } return ItemStack.EMPTY; } @@ -117,24 +121,13 @@ public Ingredient getString() { static class Serializer implements RecipeSerializer { @Override - public Codec codec() { + public MapCodec codec() { return CODEC; } @Override - public PotionBundleRecipe fromNetwork(FriendlyByteBuf buf) { - Ingredient string = Ingredient.fromNetwork(buf); - Item potion = BuiltInRegistries.ITEM.get(buf.readResourceLocation()); - Item bundle = BuiltInRegistries.ITEM.get(buf.readResourceLocation()); - assert bundle instanceof AbstractPotionBundle; - return new PotionBundleRecipe(string, potion, (AbstractPotionBundle) bundle); - } - - @Override - public void toNetwork(FriendlyByteBuf buf, PotionBundleRecipe recipe) { - recipe.string.toNetwork(buf); - buf.writeResourceLocation(BuiltInRegistries.ITEM.getKey(recipe.potion)); - buf.writeResourceLocation(BuiltInRegistries.ITEM.getKey(recipe.bundle)); + public StreamCodec streamCodec() { + return STREAM_CODEC; } } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleString.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleString.java new file mode 100644 index 0000000..d318ec1 --- /dev/null +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleString.java @@ -0,0 +1,47 @@ +package com.github.minecraftschurlimods.potionbundles; + +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponentPatch; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +public record PotionBundleString(Holder item, DataComponentPatch components) { + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group( + BuiltInRegistries.ITEM.holderByNameCodec().fieldOf("item").forGetter(PotionBundleString::item), + DataComponentPatch.CODEC.fieldOf("components").forGetter(PotionBundleString::components) + ).apply(inst, PotionBundleString::new)); + public static final StreamCodec STREAM_CODEC = StreamCodec.composite( + ByteBufCodecs.holderRegistry(Registries.ITEM), + PotionBundleString::item, + DataComponentPatch.STREAM_CODEC, + PotionBundleString::components, + PotionBundleString::new + ); + + public ItemStack toItemStack() { + return new ItemStack(item(), 1, components()); + } + + public static PotionBundleString fromItemHolder(Holder item) { + return new PotionBundleString(item, DataComponentPatch.EMPTY); + } + + public static PotionBundleString fromItem(Item item) { + return fromItem(item, DataComponentPatch.EMPTY); + } + + public static PotionBundleString fromItem(Item item, DataComponentPatch components) { + return new PotionBundleString(item.builtInRegistryHolder(), components); + } + + public static PotionBundleString fromItemStack(ItemStack itemStack) { + return new PotionBundleString(itemStack.getItemHolder(), itemStack.getComponentsPatch()); + } +} diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleUtils.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleUtils.java index 57d7cc8..5efd122 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleUtils.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundleUtils.java @@ -1,26 +1,30 @@ package com.github.minecraftschurlimods.potionbundles; -import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeType; -import net.minecraft.world.level.Level; +import org.apache.commons.lang3.NotImplementedException; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + public final class PotionBundleUtils { - public static final String USES_KEY = "Uses"; - public static final String STRING_KEY = "String"; + private static final Map POTION_FOR_BUNDLE_CACHE = new HashMap<>(); - private PotionBundleUtils() {} + private PotionBundleUtils() { + throw new NotImplementedException("You can't instantiate a utility class"); + } public static int getUses(ItemStack stack) { - return stack.getOrCreateTag().getInt(USES_KEY); + return stack.getOrDefault(PotionBundles.USES, 0); } public static void setUses(ItemStack stack, int uses) { - stack.getOrCreateTag().putInt(USES_KEY, uses); + stack.set(PotionBundles.USES, uses); } public static void decrementUses(ItemStack stack) { @@ -28,26 +32,29 @@ public static void decrementUses(ItemStack stack) { } public static ItemStack getString(ItemStack stack) { - ItemStack s = ItemStack.of(stack.getOrCreateTag().getCompound(STRING_KEY)); - return s.isEmpty() ? new ItemStack(Items.STRING) : s; + PotionBundleString string = stack.get(PotionBundles.STRING); + return string == null ? new ItemStack(Items.STRING) : string.toItemStack(); + } + + public static void setString(ItemStack stack, @Nullable PotionBundleString string) { + stack.set(PotionBundles.STRING, string); } - public static void setString(ItemStack stack, ItemStack string) { - stack.getOrCreateTag().put(STRING_KEY, string.save(new CompoundTag())); + static void onReload() { + POTION_FOR_BUNDLE_CACHE.clear(); } - @Nullable - public static Item getPotionForBundle(Level world, AbstractPotionBundle bundle) { - return world.getRecipeManager() + public static Item getPotionForBundle(AbstractPotionBundle bundle) { + return POTION_FOR_BUNDLE_CACHE.computeIfAbsent(bundle, b -> Optional.ofNullable(SidedGetter.getRecipeManager()).flatMap(recipeManager -> recipeManager .getAllRecipesFor(RecipeType.CRAFTING) .stream() .map(RecipeHolder::value) .filter(recipe -> recipe.getSerializer() == PotionBundles.POTION_BUNDLE_RECIPE_SERIALIZER.get()) .filter(PotionBundleRecipe.class::isInstance) .map(PotionBundleRecipe.class::cast) - .filter(recipe -> recipe.getBundleItem() == bundle) + .filter(recipe -> recipe.getBundleItem() == b) .findFirst() - .map(PotionBundleRecipe::getPotionItem) - .orElse(null); + .map(PotionBundleRecipe::getPotionItem)) + .orElse(Items.POTION)); } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundles.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundles.java index c834eab..cfd4230 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundles.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/PotionBundles.java @@ -1,94 +1,115 @@ package com.github.minecraftschurlimods.potionbundles; import com.mojang.logging.LogUtils; -import net.minecraft.core.RegistryAccess; +import com.mojang.serialization.Codec; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.component.DataComponentType; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.server.packs.resources.PreparableReloadListener; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.Potion; -import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.crafting.Recipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.item.crafting.RecipeSerializer; +import net.neoforged.fml.ModContainer; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.AddReloadListenerEvent; import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.common.Mod; import net.neoforged.fml.config.ModConfig; -import net.neoforged.fml.javafmlmod.FMLJavaModLoadingContext; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredItem; import net.neoforged.neoforge.registries.DeferredRegister; +import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executor; +import java.util.function.Supplier; @Mod(PotionBundles.MODID) public class PotionBundles { public static final String MODID = "potionbundles"; public static final int POTION_BUNDLE_SIZE = 3; static final Logger LOGGER = LogUtils.getLogger(); + static final DeferredRegister.DataComponents DATA_COMPONENTS = DeferredRegister.createDataComponents(MODID); static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(MODID); static final DeferredRegister> RECIPE_SERIALIZERS = DeferredRegister.create(Registries.RECIPE_SERIALIZER, MODID); + public static final Supplier> USES = DATA_COMPONENTS.registerComponentType("uses", builder -> builder.persistent(Codec.INT).networkSynchronized(ByteBufCodecs.VAR_INT)); + public static final Supplier> STRING = DATA_COMPONENTS.registerComponentType("string", builder -> builder.persistent(PotionBundleString.CODEC.codec()).networkSynchronized(PotionBundleString.STREAM_CODEC)); public static final DeferredItem POTION_BUNDLE = ITEMS.register("potion_bundle", PotionBundle::new); public static final DeferredItem SPLASH_POTION_BUNDLE = ITEMS.register("splash_potion_bundle", SplashPotionBundle::new); public static final DeferredItem LINGERING_POTION_BUNDLE = ITEMS.register("lingering_potion_bundle", LingeringPotionBundle::new); public static final DeferredHolder, RecipeSerializer> POTION_BUNDLE_RECIPE_SERIALIZER = RECIPE_SERIALIZERS.register("crafting_special_potion_bundle", PotionBundleRecipe.Serializer::new); - public PotionBundles(IEventBus modEventBus) { + public PotionBundles(ModContainer container, IEventBus modEventBus) { + DATA_COMPONENTS.register(modEventBus); ITEMS.register(modEventBus); RECIPE_SERIALIZERS.register(modEventBus); modEventBus.addListener(PotionBundles::registerItemsToCreativeTabs); - ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, Config.clientSpec); - ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, Config.serverSpec); + container.registerConfig(ModConfig.Type.CLIENT, Config.clientSpec); + container.registerConfig(ModConfig.Type.SERVER, Config.serverSpec); + NeoForge.EVENT_BUS.addListener((AddReloadListenerEvent evt) -> evt.addListener((SimpleReloadListener) PotionBundleUtils::onReload)); } private static void registerItemsToCreativeTabs(BuildCreativeModeTabContentsEvent event) { if (event.getTabKey() != CreativeModeTabs.FOOD_AND_DRINKS) return; - ItemStack stringBasic; - ItemStack stringSplash; - ItemStack stringLingering; - if (event.getParameters().holders() instanceof RegistryAccess registryAccess) { - RecipeManager recipeManager = SidedGetter.getRecipeManager(); - if (recipeManager != null) { - stringBasic = getStringFromRecipe(POTION_BUNDLE.get(), registryAccess, recipeManager); - stringSplash = getStringFromRecipe(SPLASH_POTION_BUNDLE.get(), registryAccess, recipeManager); - stringLingering = getStringFromRecipe(LINGERING_POTION_BUNDLE.get(), registryAccess, recipeManager); - } else { - LOGGER.error("No RecipeManager available, can't get correct string for potion bundles."); - stringBasic = stringSplash = stringLingering = ItemStack.EMPTY; - } + PotionBundleString stringBasic; + PotionBundleString stringSplash; + PotionBundleString stringLingering; + HolderLookup.Provider holderLookupProvider = event.getParameters().holders(); + RecipeManager recipeManager = SidedGetter.getRecipeManager(); + if (recipeManager != null) { + stringBasic = getStringFromRecipe(POTION_BUNDLE.get(), holderLookupProvider, recipeManager); + stringSplash = getStringFromRecipe(SPLASH_POTION_BUNDLE.get(), holderLookupProvider, recipeManager); + stringLingering = getStringFromRecipe(LINGERING_POTION_BUNDLE.get(), holderLookupProvider, recipeManager); } else { - LOGGER.error("No RegistryAccess available, can't get correct string for potion bundles."); - stringBasic = stringSplash = stringLingering = ItemStack.EMPTY; + LOGGER.error("No RecipeManager available, can't get correct string for potion bundles."); + stringBasic = stringSplash = stringLingering = null; } addBundlesForAllPotions(event, POTION_BUNDLE.get(), stringBasic); addBundlesForAllPotions(event, SPLASH_POTION_BUNDLE.get(), stringSplash); addBundlesForAllPotions(event, LINGERING_POTION_BUNDLE.get(), stringLingering); } - private static void addBundlesForAllPotions(BuildCreativeModeTabContentsEvent populator, AbstractPotionBundle bundle, ItemStack string) { - for (Potion potion : BuiltInRegistries.POTION) { - if (potion == Potions.EMPTY) continue; - ItemStack stack = bundle.createStack(string, potion, List.of(), null); - if (!stack.isEmpty()) populator.accept(stack); - } + private static void addBundlesForAllPotions(BuildCreativeModeTabContentsEvent populator, AbstractPotionBundle bundle, @Nullable PotionBundleString string) { + BuiltInRegistries.POTION.holders().forEach(potion -> { + ItemStack stack = bundle.createStack(string, new PotionContents(potion)); + if (!stack.isEmpty()) { + populator.accept(stack); + } + }); } - private static ItemStack getStringFromRecipe(AbstractPotionBundle bundle, RegistryAccess registryAccess, RecipeManager recipeManager) { + @Nullable + private static PotionBundleString getStringFromRecipe(AbstractPotionBundle bundle, HolderLookup.Provider holderLookupProvider, RecipeManager recipeManager) { for (RecipeHolder holder : recipeManager.getRecipes()) { Recipe recipe = holder.value(); if (recipe.getSerializer() != POTION_BUNDLE_RECIPE_SERIALIZER.get()) continue; - if (recipe.getResultItem(registryAccess).getItem() != bundle) continue; + if (recipe.getResultItem(holderLookupProvider).getItem() != bundle) continue; for (ItemStack stack : ((PotionBundleRecipe) recipe).getString().getItems()) { if (!stack.isEmpty()) { - return stack; + return PotionBundleString.fromItemStack(stack); } } } - return ItemStack.EMPTY; + return null; + } + + @FunctionalInterface + private interface SimpleReloadListener extends PreparableReloadListener { + @Override + default CompletableFuture reload(PreparationBarrier preparationBarrier, ResourceManager resourceManager, ProfilerFiller preparationsProfiler, ProfilerFiller reloadProfiler, Executor backgroundExecutor, Executor gameExecutor) { + return CompletableFuture.completedFuture(null).thenCompose(preparationBarrier::wait).thenAcceptAsync(($) -> onReload(), gameExecutor); + } + + void onReload(); } } diff --git a/src/main/java/com/github/minecraftschurlimods/potionbundles/SplashPotionBundle.java b/src/main/java/com/github/minecraftschurlimods/potionbundles/SplashPotionBundle.java index eb5e31c..2a1e4d6 100644 --- a/src/main/java/com/github/minecraftschurlimods/potionbundles/SplashPotionBundle.java +++ b/src/main/java/com/github/minecraftschurlimods/potionbundles/SplashPotionBundle.java @@ -1,22 +1,22 @@ package com.github.minecraftschurlimods.potionbundles; +import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; import java.util.List; public class SplashPotionBundle extends AbstractThrowablePotionBundle { @Override - public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - PotionUtils.addPotionTooltip(stack, tooltip, 1F, world == null ? 20.0F : world.tickRateManager().tickrate()); - super.appendHoverText(stack, world, tooltip, flag); + public void appendHoverText(ItemStack stack, TooltipContext context, List tooltip, TooltipFlag flag) { + stack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).addPotionTooltip(tooltip::add, 1.0F, context.tickRate()); + super.appendHoverText(stack, context, tooltip, flag); } @Override diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta deleted file mode 100644 index bdd1899..0000000 --- a/src/main/resources/pack.mcmeta +++ /dev/null @@ -1 +0,0 @@ -{"pack":{"description":"potionbundles resources","pack_format":15}} diff --git a/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java b/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java index dff35ab..0bb2d75 100644 --- a/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java +++ b/src/test/java/com/github/minecraftschurlimods/potionbundles/test/PotionBundleTest.java @@ -2,6 +2,7 @@ import com.github.minecraftschurlimods.potionbundles.*; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.gametest.framework.GameTest; import net.minecraft.gametest.framework.GameTestAssertException; import net.minecraft.gametest.framework.GameTestHelper; @@ -15,14 +16,16 @@ import net.minecraft.world.entity.projectile.ThrownPotion; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.alchemy.Potions; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.gametest.GameTestHolder; import net.neoforged.neoforge.gametest.PrefixGameTestTemplate; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; import java.util.List; @PrefixGameTestTemplate(false) @@ -30,7 +33,7 @@ public class PotionBundleTest { @GameTest(template = "empty_3x3") public static void testPotionBundle(GameTestHelper helper) { - ItemStack string = new ItemStack(Items.STRING); + PotionBundleString string = PotionBundleString.fromItem(Items.STRING); PotionBundle potionBundle = PotionBundles.POTION_BUNDLE.get(); int maxUses = potionBundle.getMaxUses(); MobEffectInstance customEffect = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20); @@ -68,7 +71,7 @@ public static void testLingeringPotionBundle(GameTestHelper helper) { } private static void testThrownPotionBundle(GameTestHelper helper, AbstractThrowablePotionBundle potionBundle) { - ItemStack string = new ItemStack(Items.STRING); + PotionBundleString string = PotionBundleString.fromItem(Items.STRING); MobEffectInstance customEffect = new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 20); int maxUses = potionBundle.getMaxUses(); ItemStack bundle = potionBundle.createStack(string, Potions.WATER, List.of(customEffect), null); @@ -87,10 +90,12 @@ private static void testThrownPotionBundle(GameTestHelper helper, AbstractThrowa if (potions.size() > 1) { fail("Threw too many potions"); } - ThrownPotion thrownPotion = potions.get(0); + ThrownPotion thrownPotion = potions.getFirst(); ItemStack thrownPotionItem = thrownPotion.getItem(); - List mobEffects = PotionUtils.getMobEffects(thrownPotionItem); - if (mobEffects.size() != 1 || !mobEffects.get(0).equals(customEffect)) { + PotionContents potionContents = thrownPotionItem.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY); + List mobEffects = new ArrayList<>(); + potionContents.forEachEffect(mobEffects::add); + if (mobEffects.size() != 1 || !mobEffects.getFirst().equals(customEffect)) { fail("Wrong potion thrown"); } if (potionBundle == PotionBundles.SPLASH_POTION_BUNDLE.get()) { @@ -109,11 +114,11 @@ private static void testThrownPotionBundle(GameTestHelper helper, AbstractThrowa sequence.thenSucceed(); } - private static void assertBundleUsed(Player player, int index, int maxUses, ItemStack string, ItemStack bundle) { + private static void assertBundleUsed(Player player, int index, int maxUses, PotionBundleString string, ItemStack bundle) { ItemStack inHand = player.getItemInHand(InteractionHand.MAIN_HAND); assertNotEmpty(inHand, "Bundle should not be empty"); if (index == maxUses) { - assertSameItem(inHand, string, "Bundle should be empty and returned the string"); + assertSameItem(inHand, string.toItemStack(), "Bundle should be empty and returned the string"); } else { assertSameItem(inHand, bundle, "Wrong item in hand"); assertUses(inHand, maxUses - index, "Uses not decremented"); @@ -151,7 +156,7 @@ private static void fail(String message) { } private static @NotNull Player setupPlayer(GameTestHelper helper, ItemStack bundle) { - Player player = helper.makeMockSurvivalPlayer(); + Player player = helper.makeMockPlayer(GameType.SURVIVAL); player.setPos(helper.absoluteVec(Vec3.ZERO)); helper.getLevel().addFreshEntity(player); player.setItemInHand(InteractionHand.MAIN_HAND, bundle); diff --git a/summary.txt b/summary.txt index 3fad348..47c8588 100644 --- a/summary.txt +++ b/summary.txt @@ -1 +1 @@ -Fixed a rare compatibility issue +Update to 1.20.6