diff --git a/src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java b/src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java index 9316bb3d..3748f9f7 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java +++ b/src/main/java/com/gtnewhorizon/structurelib/StructureLibAPI.java @@ -17,6 +17,7 @@ import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing; import com.gtnewhorizon.structurelib.fluid.FluidBlockPlacement; +import com.gtnewhorizon.structurelib.fluid.FluidBlockPlacer; import com.gtnewhorizon.structurelib.fluid.FluidPlacementRegistry; import com.gtnewhorizon.structurelib.fluid.FluidSourceProviders; import com.gtnewhorizon.structurelib.fluid.FluidStackExtractor; @@ -412,6 +413,66 @@ public class StructureLibAPI { FluidPlacementRegistry.register(block, meta, cost, forceFluid); } + /** + * Register what it costs to place a fluid block, with {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the + * fluid the block holds, preferring the item form when the block has one. + *
+ * The amount is the whole cost of that state, so a block whose meta says how full it is wants one registration per + * meta it can be in, or no registration at all, in which case the default amount is scaled down for a partially + * filled position. + * + * @param block the fluid block + * @param meta the block meta. {@link net.minecraftforge.oredict.OreDictionary#WILDCARD_VALUE} covers every meta of + * this block. + * @throws IllegalArgumentException if the block holds no fluid, or this state is already registered + * @see #registerFluidBlockCost(Block, int, FluidBlockPlacement) + */ + public static void registerFluidBlockCost(Block block, int meta) { + FluidPlacementRegistry.register(block, meta); + } + + /** + * Register what it costs to place a fluid block, with {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the + * fluid the block holds. + * + * @param block the fluid block + * @param meta the block meta. {@link net.minecraftforge.oredict.OreDictionary#WILDCARD_VALUE} covers every + * meta of this block. + * @param forceFluid whether to always pay with fluid, even when this block also has an item form + * @see #registerFluidBlockCost(Block, int) + */ + public static void registerFluidBlockCost(Block block, int meta, boolean forceFluid) { + FluidPlacementRegistry.register(block, meta, forceFluid); + } + + /** + * Register the whole block, i.e. every meta of it that has no registration of its own, with + * {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the fluid it holds. + * + * @param block the fluid block + * @see #registerFluidBlockCost(Block, int) + */ + public static void registerFluidBlockCost(Block block) { + FluidPlacementRegistry.register(block); + } + + /** + * Register what it costs to place a fluid block, with {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the + * fluid the block holds, and placed the way the given placer says. + *
+ * Use this for a fluid block that cannot be placed with a plain block set, e.g. one that has to be filled through + * its own API. + * + * @param block the fluid block + * @param meta the block meta. {@link net.minecraftforge.oredict.OreDictionary#WILDCARD_VALUE} covers every meta + * of this block. + * @param placer how to write the block into the world + * @see #registerFluidBlockCost(Block, int, FluidBlockPlacement) + */ + public static void registerFluidBlockCost(Block block, int meta, FluidBlockPlacer placer) { + FluidPlacementRegistry.register(block, meta, placer); + } + /** * Register a way to pull fluid out of an item, so that autoplace can pay for a fluid block with it. *
diff --git a/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidBlockPlacement.java b/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidBlockPlacement.java index 91669d46..8cf8f225 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidBlockPlacement.java +++ b/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidBlockPlacement.java @@ -2,6 +2,7 @@ package com.gtnewhorizon.structurelib.fluid; import javax.annotation.Nullable; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import com.github.bsideup.jabel.Desugar; @@ -39,4 +40,65 @@ public record FluidBlockPlacement(FluidStack cost, boolean forceFluid, @Nullable public static FluidBlockPlacement forced(FluidStack cost) { return new FluidBlockPlacement(cost, true, null); } + + /** + * A placement that pays {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of given fluid, prefers the item form + * when there is one, and places the block directly. + */ + public static FluidBlockPlacement of(Fluid fluid) { + return of(defaultCost(fluid)); + } + + /** + * A placement that pays {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of given fluid, and always pays with + * fluid even when the block has an item form. + */ + public static FluidBlockPlacement forced(Fluid fluid) { + return forced(defaultCost(fluid)); + } + + /** + * A placement that pays with given fluid, and writes the block into the world the way the given placer says. + *
+ * Use this for a fluid block that cannot be placed with a plain block set, e.g. one that has to be filled through + * its own API. + */ + public static FluidBlockPlacement of(FluidStack cost, @Nullable FluidBlockPlacer placer) { + return new FluidBlockPlacement(cost, false, placer); + } + + /** + * A placement that pays with given fluid, always pays with fluid, and writes the block into the world the way the + * given placer says. + */ + public static FluidBlockPlacement forced(FluidStack cost, @Nullable FluidBlockPlacer placer) { + return new FluidBlockPlacement(cost, true, placer); + } + + /** + * A placement that pays {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of given fluid, and writes the block + * into the world the way the given placer says. + */ + public static FluidBlockPlacement of(Fluid fluid, @Nullable FluidBlockPlacer placer) { + return of(defaultCost(fluid), placer); + } + + /** + * A placement that pays {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of given fluid, always pays with fluid, + * and writes the block into the world the way the given placer says. + */ + public static FluidBlockPlacement forced(Fluid fluid, @Nullable FluidBlockPlacer placer) { + return forced(defaultCost(fluid), placer); + } + + /** + * What one block of given fluid costs unless something else was registered for it, which is one bucket. + * + * @param fluid the fluid to pay with + * @throws IllegalArgumentException if the fluid is null + */ + public static FluidStack defaultCost(Fluid fluid) { + if (fluid == null) throw new IllegalArgumentException("fluid must not be null"); + return new FluidStack(fluid, FluidPlacementRegistry.DEFAULT_FLUID_AMOUNT); + } } diff --git a/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidPlacementRegistry.java b/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidPlacementRegistry.java index 43f757f5..4f3c1a3b 100644 --- a/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidPlacementRegistry.java +++ b/src/main/java/com/gtnewhorizon/structurelib/fluid/FluidPlacementRegistry.java @@ -43,16 +43,10 @@ public class FluidPlacementRegistry { private static volatile int indexedFluidCount = -1; static { - register(Blocks.water, 0, FluidBlockPlacement.of(new FluidStack(FluidRegistry.WATER, DEFAULT_FLUID_AMOUNT))); - register( - Blocks.flowing_water, - 0, - FluidBlockPlacement.of(new FluidStack(FluidRegistry.WATER, DEFAULT_FLUID_AMOUNT))); - register(Blocks.lava, 0, FluidBlockPlacement.of(new FluidStack(FluidRegistry.LAVA, DEFAULT_FLUID_AMOUNT))); - register( - Blocks.flowing_lava, - 0, - FluidBlockPlacement.of(new FluidStack(FluidRegistry.LAVA, DEFAULT_FLUID_AMOUNT))); + register(Blocks.water, 0); + register(Blocks.flowing_water, 0); + register(Blocks.lava, 0); + register(Blocks.flowing_lava, 0); } private FluidPlacementRegistry() {} @@ -74,6 +68,63 @@ public class FluidPlacementRegistry { register(block, meta, FluidBlockPlacement.of(cost)); } + /** + * Register what it costs to place the given block state, with {@link #DEFAULT_FLUID_AMOUNT} of the fluid the block + * holds, preferring the item form when the block has one. + *
+ * The amount is the whole cost of that state. A block whose meta says how full it is therefore wants one + * registration per meta it can be in, or no registration at all, in which case {@link #resolve(Block, int)} scales + * the default amount down for a partially filled block. + * + * @param block the fluid block + * @param meta the block meta. {@link OreDictionary#WILDCARD_VALUE} covers every meta of this block. + * @throws IllegalArgumentException if the block holds no fluid, or this state is already registered + */ + public static void register(Block block, int meta) { + register(block, meta, false); + } + + /** + * Register what it costs to place the given block state, with {@link #DEFAULT_FLUID_AMOUNT} of the fluid the block + * holds. + * + * @param block the fluid block + * @param meta the block meta. {@link OreDictionary#WILDCARD_VALUE} covers every meta of this block. + * @param forceFluid whether to always pay with fluid, even when this block also has an item form + * @throws IllegalArgumentException if the block holds no fluid, or this state is already registered + */ + public static void register(Block block, int meta, boolean forceFluid) { + FluidStack cost = FluidBlockPlacement.defaultCost(fluidOf(block)); + register(block, meta, forceFluid ? FluidBlockPlacement.forced(cost) : FluidBlockPlacement.of(cost)); + } + + /** + * Register the whole block, i.e. every meta of it that has no registration of its own, with + * {@link #DEFAULT_FLUID_AMOUNT} of the fluid it holds. + * + * @param block the fluid block + * @throws IllegalArgumentException if the block holds no fluid, or the wildcard meta is already registered + */ + public static void register(Block block) { + register(block, OreDictionary.WILDCARD_VALUE); + } + + /** + * Register what it costs to place the given block state, with {@link #DEFAULT_FLUID_AMOUNT} of the fluid the block + * holds, and placed the way the given placer says. + *
+ * Use this for a fluid block that cannot be placed with a plain block set, e.g. one that has to be filled through
+ * its own API.
+ *
+ * @param block the fluid block
+ * @param meta the block meta. {@link OreDictionary#WILDCARD_VALUE} covers every meta of this block.
+ * @param placer how to write the block into the world
+ * @throws IllegalArgumentException if the block holds no fluid, or this state is already registered
+ */
+ public static void register(Block block, int meta, FluidBlockPlacer placer) {
+ register(block, meta, FluidBlockPlacement.of(FluidBlockPlacement.defaultCost(fluidOf(block)), placer));
+ }
+
/**
* Register what it costs to place the given block state.
*
@@ -181,6 +232,22 @@ public class FluidPlacementRegistry {
return null;
}
+ /**
+ * The fluid held by given block, for the registrations that default to {@link #DEFAULT_FLUID_AMOUNT} of it.
+ *
+ * @throws IllegalArgumentException if the block is null or holds no fluid
+ */
+ private static Fluid fluidOf(Block block) {
+ Fluid fluid = getFluidOf(block);
+ if (fluid == null) {
+ throw new IllegalArgumentException(
+ "Block " + (block == null ? "null" : block.getUnlocalizedName())
+ + " holds no fluid,"
+ + " register it with an explicit cost instead");
+ }
+ return fluid;
+ }
+
private static synchronized Map