User Tools

Site Tools


zh_cn:tutorial:fluids

创建流体

概述

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

创建抽象流体

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

  1. public abstract class TutorialFluid extends FlowableFluid {
  2. /**
  3. * @return 给定的流体是否为该流体的实例?
  4. */
  5. @Override
  6. public boolean matchesType(Fluid fluid) {
  7. return fluid == getStill() || fluid == getFlowing();
  8. }
  9.  
  10. /**
  11. * @return 流体是否可以像无限刷水的方法一样无限生成?在原版,这取决于游戏规则。
  12. */
  13. @Override
  14. protected boolean isInfinite() {
  15. return false;
  16. }
  17.  
  18. /**
  19. * 流体流入一个可替换的方块时的行为。
  20. * 水会掉落方块的战利品表。熔岩会播放“block.lava.extinguish”音效。
  21. */
  22. @Override
  23. protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
  24. final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null;
  25. Block.dropStacks(state, world, pos, blockEntity);
  26. }
  27.  
  28. /**
  29. * 熔岩在其 FluidState 高于指定的高度且该流体为水时返回 true。
  30. *
  31. * @return 给定的流体能否流入它的 FluidState?
  32. */
  33. @Override
  34. protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction) {
  35. return false;
  36. }
  37.  
  38. /**
  39. * 或许与流入周围附近凹洞的距离检查有关?
  40. * 水返回4。熔岩在主世界返回2,而在下界返回4。
  41. */
  42. @Override
  43. protected int getFlowSpeed(WorldView worldView) {
  44. return 4;
  45. }
  46.  
  47. /**
  48. * 返回每次流动一格,其等级减少的数值。水返回1,熔岩在主世界返回2,在下界返回1。
  49. */
  50. @Override
  51. protected int getLevelDecreasePerBlock(WorldView worldView) {
  52. return 1;
  53. }
  54.  
  55. /**
  56. * 返回每流一格需要花费的时间(按刻计算)。水返回5。熔岩在主世界返回30,在下界返回10。
  57. */
  58. @Override
  59. public int getTickRate(WorldView worldView) {
  60. return 5;
  61. }
  62.  
  63. /**
  64. * 返回爆炸抗性。水和熔岩都返回100.0F。
  65. */
  66. @Override
  67. protected float getBlastResistance() {
  68. return 100.0F;
  69. }
  70. }

实现

现在让我们制作一个拥有静止和流动两个变种的实际流体。在此教程中,我们将其称为“酸”。缺失的引用稍后补全。

  1. public abstract class AcidFluid extends TutorialFluid {
  2. @Override
  3. public Fluid getStill() {
  4. return YOUR_STILL_FLUID_HERE;
  5. }
  6.  
  7. @Override
  8. public Fluid getFlowing() {
  9. return YOUR_FLOWING_FLUID_HERE;
  10. }
  11.  
  12. @Override
  13. public Item getBucketItem() {
  14. return YOUR_BUCKET_ITEM_HERE;
  15. }
  16.  
  17. @Override
  18. protected BlockState toBlockState(FluidState fluidState) {
  19. return YOUR_FLUID_BLOCK_HERE.getDefaultState().with(Properties.LEVEL_15, getBlockStateLevel(fluidState));
  20. }
  21.  
  22. public static class Flowing extends AcidFluid {
  23. @Override
  24. protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
  25. super.appendProperties(builder);
  26. builder.add(LEVEL);
  27. }
  28.  
  29. @Override
  30. public int getLevel(FluidState fluidState) {
  31. return fluidState.get(LEVEL);
  32. }
  33.  
  34. @Override
  35. public boolean isStill(FluidState fluidState) {
  36. return false;
  37. }
  38. }
  39.  
  40. public static class Still extends AcidFluid {
  41. @Override
  42. public int getLevel(FluidState fluidState) {
  43. return 8;
  44. }
  45.  
  46. @Override
  47. public boolean isStill(FluidState fluidState) {
  48. return true;
  49. }
  50. }
  51. }
接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。在您的 ModInitializer 中:
  1. public static FlowableFluid STILL_ACID;
  2. public static FlowableFluid FLOWING_ACID;
  3. public static Item ACID_BUCKET;
  4.  
  5. @Override
  6. public void onInitialize() {
  7. STILL_ACID = Registry.register(Registries.FLUID, new Identifier("tutorial", "acid"), new AcidFluid.Still());
  8. FLOWING_ACID = Registry.register(Registries.FLUID, new Identifier("tutorial", "flowing_acid"), new AcidFluid.Flowing());
  9. ACID_BUCKET = Registry.register(Registries.ITEM, new Identifier("tutorial", "acid_bucket"),
  10. new BucketItem(STILL_ACID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1)));
  11.  
  12. // ...
  13. }
  14.  
  15. // ...

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

  1. {
  2. "replace": false,
  3. "values":
  4. [
  5. "tutorial:acid",
  6. "tutorial:flowing_acid"
  7. ]
  8. }

制作一个流体方块

接下来,我们需要在世界中创建表示酸的方块。net.minecraft.block.FluidBlock 是我们需要使用的类,但由于其构造器受保护,我们不能直接构造它。一种解决方法是制作子类或者匿名子类。这里我们展示后一种方式。在您的 ModInitializer 中:

  1. public static Block ACID;
  2.  
  3. @Override
  4. public void onInitialize() {
  5. ACID = Registry.register(Registries.BLOCK, new Identifier("tutorial", "acid"), new FluidBlock(STILL_ACID, FabricBlockSettings.copy(Blocks.WATER)){});
  6.  
  7. // ...
  8. }

既然我们有了这些静态对象,我们回到 AcidFluid 并补全被重写的方法:

  1. public abstract class AcidFluid extends TutorialFluid {
  2. @Override
  3. public Fluid getStill() {
  4. return TutorialMod.STILL_ACID;
  5. }
  6.  
  7. @Override
  8. public Fluid getFlowing() {
  9. return TutorialMod.FLOWING_ACID;
  10. }
  11.  
  12. @Override
  13. public Item getBucketItem() {
  14. return TutorialMod.ACID_BUCKET;
  15. }
  16.  
  17. @Override
  18. protected BlockState toBlockState(FluidState fluidState) {
  19. // getBlockStateLevel 将流体状态的 LEVEL_1_8 转换为流体方块使用的 LEVEL_15
  20. return TutorialMod.ACID.getDefaultState().with(Properties.LEVEL_15, getBlockStateLevel(fluidState));
  21. }
  22.  
  23. public static class Flowing extends AcidFluid {
  24. @Override
  25. protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
  26. super.appendProperties(builder);
  27. builder.add(LEVEL);
  28. }
  29.  
  30. @Override
  31. public int getLevel(FluidState fluidState) {
  32. return fluidState.get(LEVEL);
  33. }
  34.  
  35. @Override
  36. public boolean isStill(FluidState fluidState) {
  37. return false;
  38. }
  39. }
  40.  
  41. public static class Still extends AcidFluid {
  42. @Override
  43. public int getLevel(FluidState fluidState) {
  44. return 8;
  45. }
  46.  
  47. @Override
  48. public boolean isStill(FluidState fluidState) {
  49. return true;
  50. }
  51. }
  52. }

渲染设置

为了让流体拥有纹理,或者与一个颜色绑定,你需要为其注册一个FluidRenderHandler。这里,我们重用水的纹理,并仅仅改变用于其上的颜色。为确保纹理渲染为半透明的,你可以使用 Fabric 的 BlockRenderLayerMap(参见 blockappearance)。

  1. @Environment(EnvType.CLIENT)
  2. public class TutorialModClient implements ClientModInitializer {
  3.  
  4. @Override
  5. public void onInitializeClient() {
  6. FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID, new SimpleFluidRenderHandler(
  7. new Identifier("minecraft:block/water_still"),
  8. new Identifier("minecraft:block/water_flow"),
  9. 0x4CC248
  10. ));
  11.  
  12. BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID);
  13.  
  14. //if you want to use custom textures they needs to be registered.
  15. //In this example this is unnecessary because the vanilla water textures are already registered.
  16. //To register your custom textures use this method.
  17. //ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
  18. // registry.register(new Identifier("tutorial:block/custom_fluid_still"));
  19. // registry.register(new Identifier("tutorial:block/custom_fluid_flowing"));
  20. //});
  21.  
  22. // ...
  23. }
  24. }

如果你需要使用你自己的流体纹理,你可以参考原版资源包1)作为一个模板。

在世界中生成

为使得酸湖在世界中生成,你可以在你的ModInitializer中创建一个net.minecraft.world.gen.feature.LakeFeature,然后将其添加到你需要让它生成的生物群系中:

  1. // ...
  2.  
  3. public static LakeFeature ACID_LAKE;
  4.  
  5. // ...
  6.  
  7. @Override
  8. public void onInitialize()
  9. {
  10. // ...
  11.  
  12. ACID_LAKE = Registry.register(Registry.FEATURE, new Identifier(MOD_ID, "acid_lake"), new LakeFeature(SingleStateFeatureConfig::deserialize));
  13.  
  14. // 在沼泽中生成,类似于水湖,但是概率为40(数字越高,生成几率越低)
  15. Biomes.SWAMP.addFeature(
  16. GenerationStep.Feature.LOCAL_MODIFICATIONS,
  17. ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState()))
  18. .createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40)))
  19. );
  20.  
  21. // ...
  22. }
  23.  
  24. // ...
1)
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
zh_cn/tutorial/fluids.txt · Last modified: 2023/05/04 11:31 by solidblock