User Tools

Site Tools


zh_cn:tutorial:fluids

This is an old revision of the document!


创建流体

概述

在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。

创建抽象流体

原版流体扩展了net.minecraft.fluid.FlowableFluid,我们也应如此。

  1. public abstract class TutorialFluid extends FlowableFluid
  2. {
  3. /**
  4. * @return is the given fluid an instance of this fluid?
  5. */
  6. @Override
  7. public boolean matchesType(Fluid fluid)
  8. {
  9. return fluid == getStill() || fluid == getFlowing();
  10. }
  11.  
  12. /**
  13. * @return is the fluid infinite like water?
  14. */
  15. @Override
  16. protected boolean isInfinite()
  17. {
  18. return false;
  19. }
  20.  
  21. /**
  22. * Perform actions when fluid flows into a replaceable block. Water drops
  23. * the block's loot table. Lava plays the "block.lava.extinguish" sound.
  24. */
  25. @Override
  26. protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state)
  27. {
  28. final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null;
  29. Block.dropStacks(state, world, pos, blockEntity);
  30. }
  31.  
  32. /**
  33. * Lava returns true if its FluidState is above a certain height and the
  34. * Fluid is Water.
  35. *
  36. * @return if the given Fluid can flow into this FluidState?
  37. */
  38. @Override
  39. protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction)
  40. {
  41. return false;
  42. }
  43.  
  44. /**
  45. * Possibly related to the distance checks for flowing into nearby holes?
  46. * Water returns 4. Lava returns 2 in the Overworld and 4 in the Nether.
  47. */
  48. @Override
  49. protected int getFlowSpeed(WorldView worldView)
  50. {
  51. return 4;
  52. }
  53.  
  54. /**
  55. * Water returns 1. Lava returns 2 in the Overworld and 1 in the Nether.
  56. */
  57. @Override
  58. protected int getLevelDecreasePerBlock(WorldView worldView)
  59. {
  60. return 1;
  61. }
  62.  
  63. /**
  64. * Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether.
  65. */
  66. @Override
  67. public int getTickRate(WorldView worldView)
  68. {
  69. return 5;
  70. }
  71.  
  72. /**
  73. * Water and Lava both return 100.0F.
  74. */
  75. @Override
  76. protected float getBlastResistance()
  77. {
  78. return 100.0F;
  79. }
  80. }

进行

现在让我们进行实际的研究。 它将具有stillflowing变体; 将其命名为“酸性”:

public abstract class Acid extends BasicFluid
{
    @Override
    public Item getBucketItem()
    {
        return null;
    }
    @Override
    protected BlockState toBlockState(FluidState var1)
    {
        return null;
    }
 
    @Override
    public Fluid getFlowing()
    {
        return null;
    }
 
    @Override
    public Fluid getStill()
    {
        return null;
    }
 
    @Override
    public boolean matchesType(Fluid fluid)
    {
        return false;
    }
 
    // still acid
    public static class Still extends Acid
    {
 
        @Override
        public boolean isStill(FluidState fluidState)
        {
            return true;
        }
 
        /**
         * @return height of the fluid block
         */
        @Override
        public int getLevel(FluidState fluidState)
        {
            return 8;
        }
    }
 
    // flowing acid
    public static class Flowing extends  Acid
    {
 
        @Override
        public boolean isStill(FluidState fluidState)
        {
            return false;
        }
 
        /**
         * @return height of the fluid block
         */
        @Override
        public int getLevel(FluidState fluidState)
        {
            return fluidState.get(LEVEL);
        }
 
        @Override
        protected void appendProperties(StateFactory.Builder<Fluid, FluidState> stateFactoryBuilder)
        {
            super.appendProperties(stateFactoryBuilder);
            stateFactoryBuilder.add(LEVEL);
        }
    }
}

接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。 在您的 ModInitializer 中:

 
    public static Acid stillAcid;
    public static Acid flowingAcid;
 
    public static BucketItem acidBucket;
 
    @Override
    public void onInitialize()
    {
 
        stillAcid = Registry.register(Registry.FLUID, new Identifier(MODID,"acid_still"), new Acid.Still());
        flowingAcid = Registry.register(Registry.FLUID, new Identifier(MODID,"acid_flowing"), new Acid.Flowing());
 
        acidBucket = new BucketItem(stillAcid, new Item.Settings().maxCount(1));
        Registry.register(Registry.ITEM, new Identifier(MODID,"acid_bucket"), acidBucket);
    }    

为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:制作一个文件data/minecraft/tags/fluids/ water.json,并在其中写入流体的标识符:

{
  "replace": false,
  "values": [
    "modid:acid_still",
    "modid:acid_flowing"
  ]
}

制作一个流体方块

接下来,我们需要创建一个代表世界酸的图块。 net.minecraft.block.FluidBlock 是我们需要使用的类,但是出于mojang的原因,其构造函数受到保护。 该解决方案是众所周知的-创建它的子类并更改构造函数的可见性:

public class BaseFluidBlock extends FluidBlock
{
    public BaseFluidBlock(BaseFluid fluid, Settings settings)
    {
        super(fluid, settings);
    }
}

现在创建一个静态块实例:

    ...
 
    public static FluidBlock acid;
 
    @Override
    public void onInitialize()
    {
 
        ...
 
        acid = new BaseFluidBlock(stillAcid, FabricBlockSettings.of(Material.WATER).dropsNothing().build());
        Registry.register(Registry.BLOCK, new Identifier(MODID, "acid_block"), acid);
    }    

现在,当我们有了这些静态对象时,我们返回 Acid 类并完成重写的方法:

public abstract class Acid extends BasicFluid
{
    @Override
    public Item getBucketItem()
    {
        return Mod.acidBucket;
    }
 
    @Override
    protected BlockState toBlockState(FluidState fluidState)
    {
        //don't ask me what **method_15741** does...
        return Mod.acid.getDefaultState().with(FluidBlock.LEVEL, method_15741(fluidState));
    }
 
    @Override
    public Fluid getFlowing()
    {
        return Mod.flowingAcid;
    }
 
    @Override
    public Fluid getStill()
    {
        return Mod.stillAcid;
    }
 
    @Override
    public boolean matchesType(Fluid fluid_1)
    {
        return fluid_1==Mod.flowingAcid || fluid_1==Mod.stillAcid;
    }
 
    ...
 
}    

现在我们可以断言Acid类已完成。

Rendering setup

是时候做客户端的事情了。 在 ClientModInitializer 中,您需要为流体指定精灵的位置并定义其渲染。 我将重复使用水纹理,只是更改应用于它们的颜色。

    @Override
    public void onInitializeClient()
    {
 
        // adding the sprites to the block texture atlas
        ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX).register((spriteAtlasTexture, registry) -> {
 
            Identifier stillSpriteLocation = new Identifier("block/water_still");
            Identifier dynamicSpriteLocation = new Identifier("block/water_flow");
            // here I tell to use only 16x16 area of the water texture
            FabricSprite stillAcidSprite = new FabricSprite(stillSpriteLocation, 16, 16);
            // same, but 32
            FabricSprite dynamicAcidSprite = new FabricSprite(dynamicSpriteLocation, 32, 32);
 
            registry.register(stillAcidSprite);
            registry.register(dynamicAcidSprite);
 
 
            // this renderer is responsible for drawing fluids in a world
            FluidRenderHandler acidRenderHandler = new FluidRenderHandler()
            {
                // return the sprites: still sprite goes first into the array, flowing/dynamic goes last
                @Override
                public Sprite[] getFluidSprites(ExtendedBlockView extendedBlockView, BlockPos blockPos, FluidState fluidState)
                {
                    return new Sprite[] {stillAcidSprite, dynamicAcidSprite};
                }
 
                // apply light green color
                @Override
                public int getFluidColor(ExtendedBlockView view, BlockPos pos, FluidState state)
                {
                    return 0x4cc248;
                }
            };
 
            // registering the same renderer for both fluid variants is intentional
 
            FluidRenderHandlerRegistry.INSTANCE.register(Mod.stillAcid, acidRenderHandler);
            FluidRenderHandlerRegistry.INSTANCE.register(Mod.flowingAcid, acidRenderHandler);
        });

然后剩下要做的就是创建必要的Json文件和纹理,但是您现在应该知道该怎么做。

Generation in a world

要在世界上产生酸湖,可以使用在ModInitializer中创建的 net.minecraft.world.gen.feature.LakeFeature

        LakeFeature acidFeature = Registry.register(Registry.FEATURE, new Identifier(MODID,"acid_lake"), new LakeFeature(dynamic -> new LakeFeatureConfig(acid.getDefaultState())));

然后将其放入所需的生物群系中以生成:

        // I tell it to generate like water lakes, with a rarity of 40 (the higher is the number, the lesser is the generation chance):
        Biomes.FOREST.addFeature(GenerationStep.Feature.LOCAL_MODIFICATIONS, Biome.configureFeature(acidFeature, new LakeFeatureConfig(acid.getDefaultState()), Decorator.WATER_LAKE, new LakeDecoratorConfig(40)));

本教程到此结束。

zh_cn/tutorial/fluids.1605402792.txt.gz · Last modified: 2020/11/15 01:13 by solidblock