Default the fluid cost of a registration to one bucket

This commit is contained in:
ABKQPO committed 2026-09-11 10:01:36 +08:00
1 parent 7adaa4841d
commit 6209d67ba7
4 files changed
+226 -10

No files matched your search

@@ -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.
* <p>
* 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.
* <p>
* 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.
* <p>
@@ -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.
* <p>
* 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);
}
}
@@ -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.
* <p>
* 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.
* <p>
* 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<Block, Fluid> indexFluidBlocks() {
Map<String, Fluid> fluids = FluidRegistry.getRegisteredFluids();
if (fluids.size() == indexedFluidCount) return FLUID_BLOCKS;
@@ -1963,6 +1963,32 @@ public class StructureUtility {
return ofFluidBlock(block, meta, new FluidStack(fluid, amount), policy);
}
/**
* Accept a fluid block, and pay for it with {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the given fluid.
*
* @param fluid the fluid one block of this state costs
* @param block the fluid block
* @param meta the block meta that has to be there
* @see #ofFluid(Fluid, int, Block, int)
*/
public static <T> IStructureElement<T> ofFluid(Fluid fluid, Block block, int meta) {
return ofFluid(fluid, block, meta, FluidFillPolicy.EXACT_STATE);
}
/**
* Accept a fluid block, and pay for it with {@link FluidPlacementRegistry#DEFAULT_FLUID_AMOUNT} of the given fluid.
*
* @param fluid the fluid one block of this state costs
* @param block the fluid block
* @param meta the block meta that has to be there
* @param policy how much fluid an already partially filled position has to hold to be accepted as is
* @see #ofFluid(Fluid, int, Block, int)
*/
public static <T> IStructureElement<T> ofFluid(Fluid fluid, Block block, int meta, FluidFillPolicy policy) {
if (fluid == null) throw new IllegalArgumentException();
return ofFluidBlock(block, meta, FluidBlockPlacement.of(fluid), policy);
}
// endregion
// region adders