diff --git a/common/src/main/java/satisfyu/vinery/client/gui/config/ClothConfigScreen.java b/common/src/main/java/satisfyu/vinery/client/gui/config/ClothConfigScreen.java index 55cf57a32..3ca4fd705 100644 --- a/common/src/main/java/satisfyu/vinery/client/gui/config/ClothConfigScreen.java +++ b/common/src/main/java/satisfyu/vinery/client/gui/config/ClothConfigScreen.java @@ -8,6 +8,7 @@ import me.shedaniel.clothconfig2.api.ConfigEntryBuilder; import me.shedaniel.clothconfig2.gui.entries.BooleanListEntry; import me.shedaniel.clothconfig2.gui.entries.IntegerListEntry; +import me.shedaniel.clothconfig2.gui.entries.StringListListEntry; import me.shedaniel.clothconfig2.gui.entries.TextListEntry; import me.shedaniel.clothconfig2.impl.builders.SubCategoryBuilder; import net.minecraft.ChatFormatting; @@ -20,6 +21,8 @@ import satisfyu.vinery.Vinery; import satisfyu.vinery.config.VineryConfig; +import java.util.List; + public class ClothConfigScreen { private static Screen lastScreen; @@ -46,6 +49,7 @@ private static class ConfigEntries { private final ConfigCategory category; private final BooleanListEntry enableWineMakerSetBonus, enableNetherLattices; private final IntegerListEntry wineTraderChance, yearLengthInDays, yearsPerEffectLevel, fermentationBarrelTime, damagePerUse, probabilityForDamage, probabilityToKeepBoneMeal, grapeGrowthSpeed; + private final StringListListEntry disabledWines; @@ -60,6 +64,12 @@ public ConfigEntries(ConfigEntryBuilder builder, VineryConfig config, ConfigCate grapeGrowthSpeed = createIntField("grapeGrowthSpeed", config.grapeGrowthSpeed(), VineryConfig.DEFAULT.grapeGrowthSpeed(), null, 1, 100); enableNetherLattices = createBooleanField("enableNetherLattices", config.enableNetherLattices(), VineryConfig.DEFAULT.enableNetherLattices(), null); + disabledWines = builder.startStrList(Component.translatable("vinery.config.entry.disabledWines"), config.disabledWines()) + .setDefaultValue(VineryConfig.DEFAULT.disabledWines()) + .setTooltip(Component.translatable("vinery.config.entry.disabledWines.tooltip")) + .build(); + category.addEntry(disabledWines); + SubCategoryBuilder wineMaker = new SubCategoryBuilder(Component.empty(), Component.translatable("vinery.config.subCategory.wineMaker")); enableWineMakerSetBonus = createBooleanField("enableWineMakerSetBonus", config.enableWineMakerSetBonus(), VineryConfig.DEFAULT.enableWineMakerSetBonus(), wineMaker); @@ -73,7 +83,7 @@ public ConfigEntries(ConfigEntryBuilder builder, VineryConfig config, ConfigCate public VineryConfig createConfig() { - return new VineryConfig(wineTraderChance.getValue(), yearLengthInDays.getValue(), yearsPerEffectLevel.getValue(), enableWineMakerSetBonus.getValue(), damagePerUse.getValue(), probabilityForDamage.getValue(), probabilityToKeepBoneMeal.getValue(), fermentationBarrelTime.getValue(), grapeGrowthSpeed.getValue(), enableNetherLattices.getValue()); + return new VineryConfig(wineTraderChance.getValue(), yearLengthInDays.getValue(), yearsPerEffectLevel.getValue(), enableWineMakerSetBonus.getValue(), damagePerUse.getValue(), probabilityForDamage.getValue(), probabilityToKeepBoneMeal.getValue(), fermentationBarrelTime.getValue(), grapeGrowthSpeed.getValue(), enableNetherLattices.getValue(), disabledWines.getValue()); } diff --git a/common/src/main/java/satisfyu/vinery/config/VineryConfig.java b/common/src/main/java/satisfyu/vinery/config/VineryConfig.java index 902b1e582..e5fe0a7e1 100644 --- a/common/src/main/java/satisfyu/vinery/config/VineryConfig.java +++ b/common/src/main/java/satisfyu/vinery/config/VineryConfig.java @@ -4,17 +4,20 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import de.cristelknight.doapi.config.jankson.config.CommentedConfig; import net.minecraft.Util; +import net.minecraft.resources.ResourceLocation; import java.util.HashMap; +import java.util.List; public record VineryConfig(int wineTraderChance, int yearLengthInDays, int yearsPerEffectLevel, - boolean enableWineMakerSetBonus, int damagePerUse, int probabilityForDamage, int probabilityToKeepBoneMeal, int fermentationBarrelTime, int grapeGrowthSpeed, boolean enableNetherLattices) + boolean enableWineMakerSetBonus, int damagePerUse, int probabilityForDamage, int probabilityToKeepBoneMeal, int fermentationBarrelTime, int grapeGrowthSpeed, boolean enableNetherLattices, + List disabledWines) implements CommentedConfig { private static VineryConfig INSTANCE = null; - public static final VineryConfig DEFAULT = new VineryConfig(50, 16, 4, true, 1, 30, 100, 50, 100, false); + public static final VineryConfig DEFAULT = new VineryConfig(50, 16, 4, true, 1, 30, 100, 50, 100, false, List.of()); public static final Codec CODEC = RecordCodecBuilder.create(builder -> builder.group( @@ -27,7 +30,8 @@ public record VineryConfig(int wineTraderChance, int yearLengthInDays, int years Codec.intRange(1, 100).fieldOf("probability_to_keep_bone_meal").orElse(DEFAULT.probabilityToKeepBoneMeal).forGetter(c -> c.probabilityToKeepBoneMeal), Codec.intRange(1, 10000).fieldOf("fermentation_barrel_time").orElse(DEFAULT.fermentationBarrelTime).forGetter(c -> c.fermentationBarrelTime), Codec.intRange(0, 100).fieldOf("grape_growth_speed").orElse(DEFAULT.grapeGrowthSpeed).forGetter(c -> c.grapeGrowthSpeed), - Codec.BOOL.fieldOf("enable_nether_lattices").orElse(DEFAULT.enableNetherLattices).forGetter(c -> c.enableNetherLattices) + Codec.BOOL.fieldOf("enable_nether_lattices").orElse(DEFAULT.enableNetherLattices).forGetter(c -> c.enableNetherLattices), + Codec.STRING.listOf().fieldOf("disabled_wines").orElse(DEFAULT.disabledWines).forGetter(c -> c.disabledWines) ).apply(builder, VineryConfig::new) ); @@ -55,6 +59,9 @@ public HashMap getComments() { Ticks it takes to ferment a bottle"""); map.put("enable_nether_lattices", """ (It is recommended to download NetherVinery instead)"""); + map.put("disabled_wines", """ + List of wine item IDs to completely disable (e.g. vinery:eiswein). + Disabled wines can't be crafted, are hidden from the creative menu / JEI / REI / villager trades, and existing bottles can't be drunk."""); }); } @@ -98,4 +105,15 @@ public boolean isSorted() { public void setInstance(VineryConfig instance) { INSTANCE = instance; } + + /** True if the given item id is listed in {@code disabled_wines}. */ + public boolean isWineDisabled(ResourceLocation id) { + return id != null && this.disabledWines.contains(id.toString()); + } + + /** Convenience accessor against the currently-loaded config; safe to call before the config is loaded. */ + public static boolean isDisabled(ResourceLocation id) { + VineryConfig config = DEFAULT.getConfig(); + return config != null && config.isWineDisabled(id); + } } diff --git a/common/src/main/java/satisfyu/vinery/dynamicassets/VineryServerDataProvider.java b/common/src/main/java/satisfyu/vinery/dynamicassets/VineryServerDataProvider.java index 693e259d4..a47f19ab4 100644 --- a/common/src/main/java/satisfyu/vinery/dynamicassets/VineryServerDataProvider.java +++ b/common/src/main/java/satisfyu/vinery/dynamicassets/VineryServerDataProvider.java @@ -6,13 +6,18 @@ import net.mehvahdjukaar.moonlight.api.resources.pack.DynamicTexturePack; import net.mehvahdjukaar.moonlight.api.set.BlockSetAPI; import net.mehvahdjukaar.moonlight.api.set.wood.WoodType; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.GsonHelper; import org.apache.logging.log4j.Logger; import satisfyu.vinery.Vinery; import satisfyu.vinery.VineryIdentifier; import satisfyu.vinery.config.VineryConfig; +import java.util.List; import java.util.concurrent.atomic.AtomicInteger; public class VineryServerDataProvider { @@ -55,6 +60,43 @@ public void regenerateDynamicAssets(ResourceManager resourceManager) { latticeCount.getAndIncrement(); }); this.getLogger().debug("Generated {} lattice recipes", latticeCount); + + // Keep the "wine_collector" advancement completable when wines are disabled: its single + // criterion requires holding every wine at once, so drop any disabled wine's requirement. + List disabledWines = VineryConfig.DEFAULT.getConfig().disabledWines(); + if (disabledWines != null && !disabledWines.isEmpty()) { + try { + StaticResource wineCollector = StaticResource.getOrFail(resourceManager, new VineryIdentifier("advancements/main/wine_collector.json")); + this.addSimilarJsonResource(resourceManager, wineCollector, + content -> filterWineCollector(content, disabledWines), + path -> path); + this.getLogger().info("Patched wine_collector advancement to skip {} disabled wine(s)", disabledWines.size()); + } catch (Exception e) { + this.getLogger().error("Failed to patch wine_collector advancement for disabled wines", e); + } + } + } + + /** Removes any {@code inventory_changed} item predicate that references a disabled wine. */ + private static String filterWineCollector(String json, List disabledWines) { + JsonObject obj = GsonHelper.parse(json); + JsonObject conditions = obj.getAsJsonObject("criteria").getAsJsonObject("get_wines").getAsJsonObject("conditions"); + JsonArray items = conditions.getAsJsonArray("items"); + JsonArray kept = new JsonArray(); + for (JsonElement entry : items) { + boolean disabled = false; + for (JsonElement id : entry.getAsJsonObject().getAsJsonArray("items")) { + if (disabledWines.contains(id.getAsString())) { + disabled = true; + break; + } + } + if (!disabled) { + kept.add(entry); + } + } + conditions.add("items", kept); + return obj.toString(); } } } diff --git a/common/src/main/java/satisfyu/vinery/entity/wanderingwinemaker/WanderingWinemakerEntity.java b/common/src/main/java/satisfyu/vinery/entity/wanderingwinemaker/WanderingWinemakerEntity.java index b8044be2e..cd6b7ab81 100644 --- a/common/src/main/java/satisfyu/vinery/entity/wanderingwinemaker/WanderingWinemakerEntity.java +++ b/common/src/main/java/satisfyu/vinery/entity/wanderingwinemaker/WanderingWinemakerEntity.java @@ -5,6 +5,8 @@ import net.minecraft.world.entity.npc.WanderingTrader; import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.Level; +import net.minecraft.core.registries.BuiltInRegistries; +import satisfyu.vinery.config.VineryConfig; import satisfyu.vinery.registry.ObjectRegistry; import java.util.HashMap; @@ -49,6 +51,7 @@ protected void updateTrades() { this.offers = new MerchantOffers(); } this.addOffersFromItemListings(this.offers, TRADES.get(1), 8); + this.offers.removeIf(offer -> VineryConfig.isDisabled(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()))); } } \ No newline at end of file diff --git a/common/src/main/java/satisfyu/vinery/item/DrinkBlockItem.java b/common/src/main/java/satisfyu/vinery/item/DrinkBlockItem.java index e3a9e0eeb..7b4dda2cc 100644 --- a/common/src/main/java/satisfyu/vinery/item/DrinkBlockItem.java +++ b/common/src/main/java/satisfyu/vinery/item/DrinkBlockItem.java @@ -5,6 +5,7 @@ import de.cristelknight.doapi.common.block.entity.StorageBlockEntity; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.InteractionHand; @@ -22,6 +23,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.Nullable; +import satisfyu.vinery.config.VineryConfig; import satisfyu.vinery.registry.ObjectRegistry; import satisfyu.vinery.util.GeneralUtil; import satisfyu.vinery.util.WineYears; @@ -144,6 +146,10 @@ public ItemStack finishUsingItem(ItemStack itemStack, Level level, LivingEntity @Override public InteractionResultHolder use(Level level, Player player, InteractionHand interactionHand) { + if (VineryConfig.isDisabled(BuiltInRegistries.ITEM.getKey(this))) { + // Disabled wines are inert: any existing bottle can't be drunk. + return InteractionResultHolder.fail(player.getItemInHand(interactionHand)); + } return ItemUtils.startUsingInstantly(level, player, interactionHand); } } \ No newline at end of file diff --git a/common/src/main/java/satisfyu/vinery/mixin/RecipeManagerMixin.java b/common/src/main/java/satisfyu/vinery/mixin/RecipeManagerMixin.java new file mode 100644 index 000000000..77abe30fb --- /dev/null +++ b/common/src/main/java/satisfyu/vinery/mixin/RecipeManagerMixin.java @@ -0,0 +1,105 @@ +package satisfyu.vinery.mixin; + +import com.google.common.collect.ImmutableMap; +import com.google.gson.JsonElement; +import net.minecraft.core.RegistryAccess; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.util.profiling.ProfilerFiller; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.crafting.Recipe; +import net.minecraft.world.item.crafting.RecipeManager; +import net.minecraft.world.item.crafting.RecipeType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import satisfyu.vinery.config.VineryConfig; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Drops any recipe whose result item is a disabled wine (see {@code disabled_wines} in the Vinery config), + * regardless of recipe type. This single hook covers the fermentation barrel, the apple press, and Create + * mixing/pressing recipes (Create's {@code ProcessingRecipe#getResultItem} returns its first rollable output, + * and every Vinery wine recipe is single-output). JEI, REI and the vanilla recipe book inherit the filtered + * set for free because they all read from the (client-synced) RecipeManager. + *

+ * The only theoretical gap is a disabled wine appearing as a non-first output of a multi-output recipe (no + * Vinery recipe does this); recipes whose {@link Recipe#getResultItem} throws are skipped defensively. + *

+ * {@code apply} only runs on the logical server (datapack load); the client receives the already-filtered set + * via the recipe sync packet, so this does not need to run client-side. + */ +@Mixin(RecipeManager.class) +public abstract class RecipeManagerMixin { + + @Shadow private Map, Map>> recipes; + + @Shadow private Map> byName; + + private static final Logger VINERY$LOGGER = LoggerFactory.getLogger("Vinery/DisabledWines"); + + @Inject( + method = "apply(Ljava/util/Map;Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/util/profiling/ProfilerFiller;)V", + at = @At("TAIL") + ) + private void vinery$filterDisabledWines(Map object, ResourceManager resourceManager, ProfilerFiller profiler, CallbackInfo ci) { + VineryConfig config = VineryConfig.DEFAULT.getConfig(); + if (config == null) { + return; + } + List disabled = config.disabledWines(); + if (disabled == null || disabled.isEmpty()) { + return; + } + + int[] removed = {0}; + + Map> newByName = new HashMap<>(); + this.byName.forEach((id, recipe) -> { + if (vinery$isDisabledResult(recipe)) { + removed[0]++; + } else { + newByName.put(id, recipe); + } + }); + + Map, Map>> newByType = new HashMap<>(); + this.recipes.forEach((type, byId) -> { + Map> kept = new HashMap<>(); + byId.forEach((id, recipe) -> { + if (!vinery$isDisabledResult(recipe)) { + kept.put(id, recipe); + } + }); + newByType.put(type, ImmutableMap.copyOf(kept)); + }); + + this.byName = ImmutableMap.copyOf(newByName); + this.recipes = ImmutableMap.copyOf(newByType); + + if (removed[0] > 0) { + VINERY$LOGGER.info("Removed {} recipe(s) producing disabled wines: {}", removed[0], disabled); + } + } + + private boolean vinery$isDisabledResult(Recipe recipe) { + try { + ItemStack result = recipe.getResultItem(RegistryAccess.EMPTY); + if (result == null || result.isEmpty()) { + return false; + } + return VineryConfig.isDisabled(BuiltInRegistries.ITEM.getKey(result.getItem())); + } catch (Throwable t) { + // A misbehaving third-party recipe must never break datapack loading. + return false; + } + } +} diff --git a/common/src/main/java/satisfyu/vinery/registry/TabRegistry.java b/common/src/main/java/satisfyu/vinery/registry/TabRegistry.java index 22a418a5c..2dcbb3270 100644 --- a/common/src/main/java/satisfyu/vinery/registry/TabRegistry.java +++ b/common/src/main/java/satisfyu/vinery/registry/TabRegistry.java @@ -3,12 +3,15 @@ import dev.architectury.registry.registries.DeferredRegister; import dev.architectury.registry.registries.RegistrySupplier; import net.mehvahdjukaar.moonlight.api.set.wood.WoodType; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; import satisfyu.vinery.Vinery; +import satisfyu.vinery.config.VineryConfig; import static com.mojang.serialization.codecs.RecordCodecBuilder.build; @@ -91,33 +94,33 @@ public class TabRegistry { out.accept(ObjectRegistry.JUNGLE_WHITE_GRAPEJUICE_BOTTLE.get()); out.accept(ObjectRegistry.SAVANNA_RED_GRAPEJUICE_BOTTLE.get()); out.accept(ObjectRegistry.SAVANNA_WHITE_GRAPEJUICE_BOTTLE.get()); - out.accept(ObjectRegistry.CHORUS_WINE.get()); - out.accept(ObjectRegistry.CHERRY_WINE.get()); - out.accept(ObjectRegistry.MAGNETIC_WINE.get()); - out.accept(ObjectRegistry.NOIR_WINE.get()); - out.accept(ObjectRegistry.LILITU_WINE.get()); - out.accept(ObjectRegistry.MELLOHI_WINE.get()); - out.accept(ObjectRegistry.STAL_WINE.get()); - out.accept(ObjectRegistry.STRAD_WINE.get()); - out.accept(ObjectRegistry.SOLARIS_WINE.get()); - out.accept(ObjectRegistry.BOLVAR_WINE.get()); - out.accept(ObjectRegistry.AEGIS_WINE.get()); - out.accept(ObjectRegistry.CLARK_WINE.get()); - out.accept(ObjectRegistry.CHENET_WINE.get()); - out.accept(ObjectRegistry.KELP_CIDER.get()); - out.accept(ObjectRegistry.APPLE_WINE.get()); - out.accept(ObjectRegistry.APPLE_CIDER.get()); - out.accept(ObjectRegistry.JELLIE_WINE.get()); - out.accept(ObjectRegistry.RED_WINE.get()); - out.accept(ObjectRegistry.PRAETORIAN_WINE.get()); - out.accept(ObjectRegistry.JO_SPECIAL_MIXTURE.get()); - out.accept(ObjectRegistry.CRISTEL_WINE.get()); - out.accept(ObjectRegistry.CREEPERS_CRUSH.get()); - out.accept(ObjectRegistry.VILLAGERS_FRIGHT.get()); - out.accept(ObjectRegistry.GLOWING_WINE.get()); - out.accept(ObjectRegistry.MEAD.get()); - out.accept(ObjectRegistry.BOTTLE_MOJANG_NOIR.get()); - out.accept(ObjectRegistry.EISWEIN.get()); + acceptWine(out, ObjectRegistry.CHORUS_WINE.get()); + acceptWine(out, ObjectRegistry.CHERRY_WINE.get()); + acceptWine(out, ObjectRegistry.MAGNETIC_WINE.get()); + acceptWine(out, ObjectRegistry.NOIR_WINE.get()); + acceptWine(out, ObjectRegistry.LILITU_WINE.get()); + acceptWine(out, ObjectRegistry.MELLOHI_WINE.get()); + acceptWine(out, ObjectRegistry.STAL_WINE.get()); + acceptWine(out, ObjectRegistry.STRAD_WINE.get()); + acceptWine(out, ObjectRegistry.SOLARIS_WINE.get()); + acceptWine(out, ObjectRegistry.BOLVAR_WINE.get()); + acceptWine(out, ObjectRegistry.AEGIS_WINE.get()); + acceptWine(out, ObjectRegistry.CLARK_WINE.get()); + acceptWine(out, ObjectRegistry.CHENET_WINE.get()); + acceptWine(out, ObjectRegistry.KELP_CIDER.get()); + acceptWine(out, ObjectRegistry.APPLE_WINE.get()); + acceptWine(out, ObjectRegistry.APPLE_CIDER.get()); + acceptWine(out, ObjectRegistry.JELLIE_WINE.get()); + acceptWine(out, ObjectRegistry.RED_WINE.get()); + acceptWine(out, ObjectRegistry.PRAETORIAN_WINE.get()); + acceptWine(out, ObjectRegistry.JO_SPECIAL_MIXTURE.get()); + acceptWine(out, ObjectRegistry.CRISTEL_WINE.get()); + acceptWine(out, ObjectRegistry.CREEPERS_CRUSH.get()); + acceptWine(out, ObjectRegistry.VILLAGERS_FRIGHT.get()); + acceptWine(out, ObjectRegistry.GLOWING_WINE.get()); + acceptWine(out, ObjectRegistry.MEAD.get()); + acceptWine(out, ObjectRegistry.BOTTLE_MOJANG_NOIR.get()); + acceptWine(out, ObjectRegistry.EISWEIN.get()); out.accept(ObjectRegistry.WINE_BOTTLE.get()); out.accept(ObjectRegistry.APPLE_MASH.get()); out.accept(ObjectRegistry.GRAPEVINE_STEM.get()); @@ -169,6 +172,13 @@ public class TabRegistry { }) .build()); + /** Adds a wine to the creative tab only if it is not listed in {@code disabled_wines}. */ + private static void acceptWine(CreativeModeTab.Output out, ItemLike wine) { + if (!VineryConfig.isDisabled(BuiltInRegistries.ITEM.getKey(wine.asItem()))) { + out.accept(wine); + } + } + public static void init() { CREATIVE_MODE_TABS.register(); } diff --git a/common/src/main/java/satisfyu/vinery/util/VillagerUtil.java b/common/src/main/java/satisfyu/vinery/util/VillagerUtil.java index 6b19f220f..65581f91c 100644 --- a/common/src/main/java/satisfyu/vinery/util/VillagerUtil.java +++ b/common/src/main/java/satisfyu/vinery/util/VillagerUtil.java @@ -1,5 +1,6 @@ package satisfyu.vinery.util; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; @@ -9,6 +10,7 @@ import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.Block; +import satisfyu.vinery.config.VineryConfig; public class VillagerUtil { @@ -73,6 +75,10 @@ public SellItemFactory(ItemStack stack, int price, int count, int maxUses, int e @Override public MerchantOffer getOffer(Entity entity, RandomSource random) { + if (VineryConfig.isDisabled(BuiltInRegistries.ITEM.getKey(this.sell.getItem()))) { + // Don't offer disabled wines; vanilla trade generation skips null offers. + return null; + } return new MerchantOffer( new ItemStack(Items.EMERALD, this.price), new ItemStack(this.sell.getItem(), this.count), this.maxUses, this.experience, this.multiplier ); diff --git a/common/src/main/resources/assets/vinery/lang/en_us.json b/common/src/main/resources/assets/vinery/lang/en_us.json index 0eaa37da2..7c095362b 100644 --- a/common/src/main/resources/assets/vinery/lang/en_us.json +++ b/common/src/main/resources/assets/vinery/lang/en_us.json @@ -278,6 +278,8 @@ "vinery.config.entry.fermentationBarrelTime": "Fermentation Barrel Time", "vinery.config.entry.grapeGrowthSpeed": "Grape Growth speed (in %)", "vinery.config.entry.enableNetherLattices": "Enable Nether Lattices", + "vinery.config.entry.disabledWines": "Disabled Wines", + "vinery.config.entry.disabledWines.tooltip": "Wine item IDs to completely disable (e.g. vinery:eiswein). Disabled wines can't be crafted or traded, are hidden from the creative menu and JEI/REI, and existing bottles can't be drunk.", "vinery.config.subCategory.wineMaker": "Winemaker Set Bonus", "vinery.config.title": "Vinery", "vinery.tooltip.winemaker_armor": "Winemaker's Desire:", diff --git a/common/src/main/resources/vinery-common.mixins.json b/common/src/main/resources/vinery-common.mixins.json index 46195424a..8b5548a6a 100644 --- a/common/src/main/resources/vinery-common.mixins.json +++ b/common/src/main/resources/vinery-common.mixins.json @@ -16,7 +16,8 @@ "PlantBlockMixin", "ShovelItemMixin", "SpreadingSnowyDirtBlockMixin", - "WanderingTraderManagerMixin" + "WanderingTraderManagerMixin", + "RecipeManagerMixin" ], "injectors": { "defaultRequire": 1