diff --git a/src/main/java/me/desht/pneumaticcraft/common/capabilities/PNCFluidHandlerItemStack.java b/src/main/java/me/desht/pneumaticcraft/common/capabilities/PNCFluidHandlerItemStack.java index 6696396ab..f23a9842d 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/capabilities/PNCFluidHandlerItemStack.java +++ b/src/main/java/me/desht/pneumaticcraft/common/capabilities/PNCFluidHandlerItemStack.java @@ -19,6 +19,11 @@ public PNCFluidHandlerItemStack(ItemStack container, int capacity, Predicate> aerialInterfaceDimensionBlacklist; public ModConfigSpec.IntValue vortexCannonPlayerBoostRate; public ModConfigSpec.DoubleValue pressurizedSpawnerMinPressure; + public ModConfigSpec.ConfigValue defaultXPFluid; } public static class Armor { public ModConfigSpec.IntValue jetBootsAirUsage; @@ -354,6 +355,11 @@ public static class Drones { .comment("Minimum interval in ticks which the player can use the Vortex Cannon to boost their own speed") .translation("pneumaticcraft.config.common.machines.vortex_cannon.player_boost_rate") .defineInRange("vortex_cannon_player_boost_rate", 10, 1, Integer.MAX_VALUE); + machines.defaultXPFluid = builder + .comment("Default XP fluid produced by the Memory Stick, and by Drones picking up experience orbs. This must be the ID of a valid registered fluid; it should also be in the `forge:experience` fluid tag, and its native mod should use an XP->mB ratio of 1:20 for the fluid.") + .translation("pneumaticcraft.config.common.machines.default_experience_fluid") + .define("default_experience_fluid", "pneumaticcraft:memory_essence"); + builder.pop(); builder.push("Pneumatic Armor"); diff --git a/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHelper.java b/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHelper.java index a4a2b6ae9..cb79ca1f0 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHelper.java +++ b/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHelper.java @@ -19,8 +19,18 @@ import me.desht.pneumaticcraft.client.pneumatic_armor.ComponentInit; import me.desht.pneumaticcraft.common.drone.progwidgets.IProgWidget.WidgetDifficulty; +import me.desht.pneumaticcraft.common.registry.ModFluids; +import me.desht.pneumaticcraft.lib.Log; +import net.minecraft.ResourceLocationException; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.material.Fluid; public class ConfigHelper { + static Fluid cachedXPFluid = null; + public static ClientConfig client() { return ConfigHolder.client; } @@ -55,4 +65,17 @@ public static void setShowEnchantGlint(boolean show) { public static void setComponentInit(ComponentInit when) { ConfigHolder.client.armor.componentInitMessages.set(when); } + + public static Fluid getExperienceFluid() { + if (cachedXPFluid == null) { + try { + ResourceLocation id = new ResourceLocation(ConfigHolder.common.machines.defaultXPFluid.get()); + cachedXPFluid = BuiltInRegistries.FLUID.getOrThrow(ResourceKey.create(Registries.FLUID, id)); + } catch (ResourceLocationException | IllegalStateException e) { + Log.error("invalid resource location {} for 'default_experience_fluid'", ConfigHolder.common.machines.defaultXPFluid.get()); + cachedXPFluid = ModFluids.MEMORY_ESSENCE.get(); + } + } + return cachedXPFluid; + } } diff --git a/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHolder.java b/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHolder.java index cf1f292ff..5b8cfe72d 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHolder.java +++ b/src/main/java/me/desht/pneumaticcraft/common/config/ConfigHolder.java @@ -65,5 +65,6 @@ static void refreshClient() { static void refreshCommon() { OilLakeFilter.DimensionFilter.clearMatcherCaches(); AerialInterfaceBlockEntity.clearDimensionBlacklist(); + ConfigHelper.cachedXPFluid = null; } } diff --git a/src/main/java/me/desht/pneumaticcraft/common/item/MemoryStickItem.java b/src/main/java/me/desht/pneumaticcraft/common/item/MemoryStickItem.java index 0e8799574..a7244df42 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/item/MemoryStickItem.java +++ b/src/main/java/me/desht/pneumaticcraft/common/item/MemoryStickItem.java @@ -21,16 +21,18 @@ import me.desht.pneumaticcraft.client.ColorHandlers; import me.desht.pneumaticcraft.common.XPFluidManager; import me.desht.pneumaticcraft.common.capabilities.PNCFluidHandlerItemStack; +import me.desht.pneumaticcraft.common.config.ConfigHelper; import me.desht.pneumaticcraft.common.network.NetworkHandler; import me.desht.pneumaticcraft.common.network.PacketLeftClickEmpty; -import me.desht.pneumaticcraft.common.registry.ModFluids; import me.desht.pneumaticcraft.common.registry.ModItems; import me.desht.pneumaticcraft.common.thirdparty.curios.Curios; import me.desht.pneumaticcraft.common.thirdparty.curios.CuriosUtils; import me.desht.pneumaticcraft.common.util.EnchantmentUtils; import me.desht.pneumaticcraft.common.util.IOHelper; import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; +import me.desht.pneumaticcraft.lib.Log; import net.minecraft.ChatFormatting; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; @@ -43,6 +45,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; +import net.minecraft.world.level.material.Fluid; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.common.Mod; import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent; @@ -76,9 +79,15 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In ItemStack stack = playerIn.getItemInHand(handIn); if (stack.getCount() != 1) return InteractionResultHolder.pass(stack); + Fluid xpFluid = ConfigHelper.getExperienceFluid(); + if (!worldIn.isClientSide) { + int ratio = XPFluidManager.getInstance().getXPRatio(xpFluid); + if (ratio == 0) { + Log.error("configured fluid {} does not have a valid xp -> mB ratio!", BuiltInRegistries.FLUID.getKey(xpFluid)); + return InteractionResultHolder.fail(stack); + } IOHelper.getFluidHandlerForItem(stack).ifPresent(handler -> { - int ratio = XPFluidManager.getInstance().getXPRatio(ModFluids.MEMORY_ESSENCE.get()); int playerXp = EnchantmentUtils.getPlayerXP(playerIn); if (playerIn.isShiftKeyDown()) { // take XP fluid from the stick and give to player @@ -97,12 +106,15 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In if (xpToTake == 0) { xpToTake = playerXp - EnchantmentUtils.getExperienceForLevel(playerIn.experienceLevel - 1); } + // if the stick already has some fluid, use that; otherwise use our default XP fluid + FluidStack f = handler.drain(1, IFluidHandler.FluidAction.SIMULATE); + Fluid fillType = f.isEmpty() ? xpFluid : f.getFluid(); int fluidAmount = xpToTake * ratio; - FluidStack toFill = new FluidStack(ModFluids.MEMORY_ESSENCE.get(), fluidAmount); + FluidStack toFill = new FluidStack(fillType, fluidAmount); int filled = handler.fill(toFill, IFluidHandler.FluidAction.SIMULATE); if (filled >= ratio) { EnchantmentUtils.addPlayerXP(playerIn, -(filled / ratio)); - handler.fill(new FluidStack(ModFluids.MEMORY_ESSENCE.get(), filled), IFluidHandler.FluidAction.EXECUTE); + handler.fill(new FluidStack(fillType, filled), IFluidHandler.FluidAction.EXECUTE); playerIn.setItemInHand(handIn, handler.getContainer()); } } @@ -110,11 +122,14 @@ public InteractionResultHolder use(Level worldIn, Player playerIn, In }); } else { IOHelper.getFluidHandlerForItem(stack).ifPresent(handler -> { - int amount = handler.getFluidInTank(0).getAmount(); - if (EnchantmentUtils.getPlayerXP(playerIn) > 0 && amount < handler.getTankCapacity(0) && !playerIn.isShiftKeyDown() - || handler.getFluidInTank(0).getAmount() > 0 && playerIn.isShiftKeyDown()) { - playerIn.playSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 0.1f, - (worldIn.random.nextFloat() - worldIn.random.nextFloat()) * 0.35F + 0.9F); + if (handler.isFluidValid(0, new FluidStack(xpFluid, 1))) { + int amount = handler.getFluidInTank(0).getAmount(); + if (EnchantmentUtils.getPlayerXP(playerIn) > 0 + && amount < handler.getTankCapacity(0) && !playerIn.isShiftKeyDown() + || handler.getFluidInTank(0).getAmount() > 0 && playerIn.isShiftKeyDown()) { + playerIn.playSound(SoundEvents.EXPERIENCE_ORB_PICKUP, 0.1f, + (worldIn.random.nextFloat() - worldIn.random.nextFloat()) * 0.35F + 0.9F); + } } }); } @@ -127,7 +142,7 @@ public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List { - int ratio = XPFluidManager.getInstance().getXPRatio(ModFluids.MEMORY_ESSENCE.get()); + int ratio = XPFluidManager.getInstance().getXPRatio(ConfigHelper.getExperienceFluid()); if (ratio > 0) { // could be 0 if queried too early, e.g. JEI item scanning FluidStack fluidStack = handler.getFluidInTank(0); int amount = fluidStack.getAmount(); @@ -212,7 +227,7 @@ public static void cacheMemoryStickLocation(Player entityIn, MemoryStickLocator @Override public IFluidHandlerItem provideFluidCapability(ItemStack stack) { - return new PNCFluidHandlerItemStack(stack, XP_FLUID_CAPACITY, fluid -> fluid == ModFluids.MEMORY_ESSENCE.get()); + return new PNCFluidHandlerItemStack(stack, XP_FLUID_CAPACITY, fluid -> XPFluidManager.getInstance().getXPRatio(fluid) > 0); } @Mod.EventBusSubscriber(modid = Names.MOD_ID) diff --git a/src/main/java/me/desht/pneumaticcraft/common/thirdparty/jei/JEIMemoryEssenceCategory.java b/src/main/java/me/desht/pneumaticcraft/common/thirdparty/jei/JEIMemoryEssenceCategory.java index d46d9c513..8261a2303 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/thirdparty/jei/JEIMemoryEssenceCategory.java +++ b/src/main/java/me/desht/pneumaticcraft/common/thirdparty/jei/JEIMemoryEssenceCategory.java @@ -19,8 +19,8 @@ import com.google.common.collect.ImmutableList; import me.desht.pneumaticcraft.common.XPFluidManager; +import me.desht.pneumaticcraft.common.config.ConfigHelper; import me.desht.pneumaticcraft.common.registry.ModBlocks; -import me.desht.pneumaticcraft.common.registry.ModFluids; import me.desht.pneumaticcraft.common.registry.ModItems; import me.desht.pneumaticcraft.common.upgrades.ModUpgrades; import me.desht.pneumaticcraft.common.util.PneumaticCraftUtils; @@ -49,7 +49,7 @@ public class JEIMemoryEssenceCategory extends AbstractPNCCategory { public JEIMemoryEssenceCategory() { super(RecipeTypes.MEMORY_ESSENCE, - new FluidStack(ModFluids.MEMORY_ESSENCE.get(), 1000).getDisplayName(), + new FluidStack(ConfigHelper.getExperienceFluid(), 1000).getDisplayName(), guiHelper().createDrawable(Textures.GUI_JEI_MEMORY_ESSENCE, 0, 0, 146, 73), guiHelper().createDrawableIngredient(VanillaTypes.ITEM_STACK, new ItemStack(ModItems.MEMORY_ESSENCE_BUCKET.get())) ); @@ -66,13 +66,13 @@ public void setRecipe(IRecipeLayoutBuilder builder, MemoryEssenceRecipe recipe, .addTooltipCallback(new Tooltip(recipe, 1)); } builder.addSlot(RecipeIngredientRole.OUTPUT, 112, 29) - .addIngredients(NeoForgeTypes.FLUID_STACK, Collections.singletonList(new FluidStack(ModFluids.MEMORY_ESSENCE.get(), 1000))); + .addIngredients(NeoForgeTypes.FLUID_STACK, Collections.singletonList(new FluidStack(ConfigHelper.getExperienceFluid(), 1000))); } @Override public void draw(MemoryEssenceRecipe recipe, IRecipeSlotsView recipeSlotsView, GuiGraphics graphics, double mouseX, double mouseY) { Font fr = Minecraft.getInstance().font; - int ratio = XPFluidManager.getInstance().getXPRatio(ModFluids.MEMORY_ESSENCE.get()); + int ratio = XPFluidManager.getInstance().getXPRatio(ConfigHelper.getExperienceFluid()); String s = "1 XP = " + ratio + " mB"; int w = fr.width(s); graphics.drawString(fr, s, (getBackground().getWidth() - w) / 2, 0, 0x404040, false); @@ -97,7 +97,7 @@ static List getAllRecipes() { ); } - static class MemoryEssenceRecipe { + public static class MemoryEssenceRecipe { final ItemStack input1; final ItemStack input2; final String[] tooltips = new String[] {"", ""}; diff --git a/src/main/java/me/desht/pneumaticcraft/common/util/PneumaticCraftUtils.java b/src/main/java/me/desht/pneumaticcraft/common/util/PneumaticCraftUtils.java index dec84d5e9..06c55a08c 100644 --- a/src/main/java/me/desht/pneumaticcraft/common/util/PneumaticCraftUtils.java +++ b/src/main/java/me/desht/pneumaticcraft/common/util/PneumaticCraftUtils.java @@ -25,6 +25,7 @@ import me.desht.pneumaticcraft.api.lib.Names; import me.desht.pneumaticcraft.api.misc.Symbols; import me.desht.pneumaticcraft.common.XPFluidManager; +import me.desht.pneumaticcraft.common.config.ConfigHelper; import me.desht.pneumaticcraft.common.item.ItemRegistry; import me.desht.pneumaticcraft.common.registry.ModFluids; import net.minecraft.ChatFormatting; @@ -586,9 +587,14 @@ public static Optional getTileEntityAt(BlockGetter w, * @return true if the XP orb was (or could be) fully absorbed into the fluid handler */ public static boolean fillTankWithOrb(IFluidHandler handler, ExperienceOrb orb, FluidAction action) { - int ratio = XPFluidManager.getInstance().getXPRatio(ModFluids.MEMORY_ESSENCE.get()); + Fluid xpFluid = ConfigHelper.getExperienceFluid(); + int ratio = XPFluidManager.getInstance().getXPRatio(xpFluid); + if (ratio == 0) { + return false; + } + int fluidAmount = orb.getValue() * ratio; - FluidStack toFill = new FluidStack(ModFluids.MEMORY_ESSENCE.get(), fluidAmount); + FluidStack toFill = new FluidStack(xpFluid, fluidAmount); int filled = handler.fill(toFill, action); if (filled > 0 && filled < fluidAmount && action.execute()) { orb.value = orb.value - Math.max(1, filled / ratio); // partial fill, adjust the orb