チュートリアル
インストール
基本
- 規則と用語
- レジストリへの登録
- 開発ツール
ここでは、カスタムの液体の作成について説明します。複数の流体を作成する場合は、サブクラスで共有される必要なデフォルトを設定する抽象基本液体クラスを作成することをお勧めします。また、湖のように世界に生成されるようにします。
バニラの液体は net.minecraft.fluid.FlowableFluid
を拡張します。
public abstract class TutorialFluid extends FlowableFluid { /** * @return 指定された流体がこの流体のインスタンスかどうか */ @Override public boolean matchesType(Fluid fluid) { return fluid == getStill() || fluid == getFlowing(); } /** * @return 流体が水のように無限かどうか */ @Override protected boolean isInfinite() { return false; } /** * 液体が交換可能なブロックに流れ込んだときにアクションを実行します。 * 水はブロックのルートテーブルを落とします。 * 溶岩は "block.lava.extinguish" 〔溶岩が水と衝突したとき〕の音を再生します。 */ @Override protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) { final BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null; Block.dropStacks(state, world, pos, blockEntity); } /** * FluidState が特定の高さより高く、Fluid が Water の場合、Lava は true を返します。 * * @return 指定された Fluid がこの FluidState に流れ込むことができるかどうか */ @Override protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction) { return false; } /** * おそらく、近くの穴に流れ込むための距離チェックに関連しています。 * 水は 4 を返します。溶岩はオーバーワールドで 2、ネザーで 4 を返します。 */ @Override protected int getFlowSpeed(WorldView worldView) { return 4; } /** * 水は 1 を返します。溶岩はオーバーワールドで 2、ネザーで 1 を返します。 */ @Override protected int getLevelDecreasePerBlock(WorldView worldView) { return 1; } /** * 水は 5 を返します。溶岩はオーバーワールドで 30、ネザーで 10 を返します。 */ @Override public int getTickRate(WorldView worldView) { return 5; } /** * 水と溶岩はどちらも 100.0F を返します。 */ @Override protected float getBlastResistance() { return 100.0F; } }
Now let's make an actual fluid which will have still and flowing variants. For this tutorial, we will call it Acid. The missing references will be filled in shortly.
public abstract class AcidFluid extends TutorialFluid { @Override public Fluid getStill() { return YOUR_STILL_FLUID_HERE; } @Override public Fluid getFlowing() { return YOUR_FLOWING_FLUID_HERE; } @Override public Item getBucketItem() { return YOUR_BUCKET_ITEM_HERE; } @Override protected BlockState toBlockState(FluidState fluidState) { return YOUR_FLUID_BLOCK_HERE.getDefaultState().with(Properties.LEVEL_15, getBlockStateLevel(fluidState)); } public static class Flowing extends AcidFluid { @Override protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) { super.appendProperties(builder); builder.add(LEVEL); } @Override public int getLevel(FluidState fluidState) { return fluidState.get(LEVEL); } @Override public boolean isStill(FluidState fluidState) { return false; } } public static class Still extends AcidFluid { @Override public int getLevel(FluidState fluidState) { return 8; } @Override public boolean isStill(FluidState fluidState) { return true; } } }
Next, we'll make static instances of still and flowing acid variants, and an acid bucket. In your ModInitializer
:
public static FlowableFluid STILL_ACID; public static FlowableFluid FLOWING_ACID; public static Item ACID_BUCKET; @Override public void onInitialize() { new BucketItem(STILL_ACID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1))); // ... } // ...
To make a custom fluid behave more like water or lava, you must add it to a corresponding fluid tag: For water, make a data/minecraft/tags/fluids/water.json
file and write the identifiers of your fluids in there:
{ "replace": false, "values": [ "your_mod_id:acid", "your_mod_id:flowing_acid" ] }
Next we need to create a block which will represent acid in the world. net.minecraft.block.FluidBlock
is the class we need to use, but since its constructor is protected, we can't construct it directly. Some ways to use it are to make a subclass or an anonymous subclass. Here we will be showing the latter. In your ModInitializer
:
public static Block ACID; @Override public void onInitialize() { // ... }
Now that we have these static objects, we can go back to AcidFluid
and fill in the overridden methods:
public abstract class AcidFluid extends TutorialFluid { @Override public Fluid getStill() { return TutorialMod.STILL_ACID; } @Override public Fluid getFlowing() { return TutorialMod.FLOWING_ACID; } @Override public Item getBucketItem() { return TutorialMod.ACID_BUCKET; } @Override protected BlockState toBlockState(FluidState fluidState) { // getBlockStateLevel converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses return TutorialMod.ACID.getDefaultState().with(Properties.LEVEL_15, getBlockStateLevel(fluidState)); } public static class Flowing extends AcidFluid { @Override protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) { super.appendProperties(builder); builder.add(LEVEL); } @Override public int getLevel(FluidState fluidState) { return fluidState.get(LEVEL); } @Override public boolean isStill(FluidState fluidState) { return false; } } public static class Still extends AcidFluid { @Override public int getLevel(FluidState fluidState) { return 8; } @Override public boolean isStill(FluidState fluidState) { return true; } } }
For your fluids to have textures or be tinted with a color, you will need to register a FluidRenderHandler
for them. Here, we will reuse water's textures and just change the tint color applied to them. To make sure the textures are rendered as translucent, you can use Fabric's BlockRenderLayerMap
.
public class TutorialModClient implements ClientModInitializer { @Override public void onInitializeClient() { FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID, new SimpleFluidRenderHandler( new Identifier("minecraft:block/water_still"), new Identifier("minecraft:block/water_flow"), 0x4CC248 )); BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID); //if you want to use custom textures they needs to be registered. //In this example this is unnecessary because the vanilla water textures are already registered. //To register your custom textures use this method. //ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> { // registry.register(new Identifier("modid:block/custom_fluid_still")); // registry.register(new Identifier("modid:block/custom_fluid_flowing")); //}); // ... } }
If you want to use your own fluid textures, you can refer to vanilla's assets 1) as a template.
To make lakes of acid generate in the world, you can create a net.minecraft.world.gen.feature.LakeFeature
in your ModInitializer
and then add it to the biomes you want it to generate in:
public static LakeFeature ACID_LAKE; @Override public void onInitialize() { // generate in swamps, similar to water lakes, but with a chance of 40 (the higher the number, the lower the generation chance) Biomes.SWAMP.addFeature( GenerationStep.Feature.LOCAL_MODIFICATIONS, ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState())) .createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40))) ); }
assets/minecraft/blockstates/water.json
assets/minecraft/models/block/water.json
assets/minecraft/textures/block/water_still.png
assets/minecraft/textures/block/water_still.png.mcmeta
assets/minecraft/textures/block/water_flow.png
assets/minecraft/textures/block/water_flow.png.mcmeta