User Tools

Site Tools


ru:tutorial:fluids

This is an old revision of the document!


map2fabricyarn - Page contains unknown Intermediary names:
field_11154 field_11142 field_11146

Создание жидкостей

Ознакомление

Здесь мы рассмотрим создание жидкости. Если вы планируете создать несколько жидкостей, рекомендуется создать абстрактный базовый класс жидкостей, в котором вы зададите необходимые значения по умолчанию, которые будут общими для его подклассов. Мы также сделаем так, чтобы она генерировалась в мире, как озера.

Создание абстрактной жидкости

Ванильные жидкости используют net.minecraft.fluid.FlowableFluid, сделаем так же.

  1. public abstract class TutorialFluid extends FlowableFluid {
  2. /**
  3. * @вернём, является ли данная жидкость экземпляром этой жидкости
  4. */
  5. @Override
  6. public boolean matchesType(Fluid fluid) {
  7. return fluid == getStill() || fluid == getFlowing();
  8. }
  9.  
  10. /**
  11. * @вернём, является ли жидкость бесконечной, как вода
  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.hasBlockEntity() ? world.getBlockEntity(pos) : null;
  25. Block.dropStacks(state, world, pos, blockEntity);
  26. }
  27.  
  28. /**
  29. * Лава возвращает значение true, если ее FluidState превышает определенную высоту и
  30. * Жидкость - это Вода.
  31. *
  32. * @вернём, может ли данная жидкость перетекать в это FluidState
  33. */
  34. @Override
  35. protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction) {
  36. return false;
  37. }
  38.  
  39. /**
  40. * Возможно, это связано с проверкой расстояния на предмет попадания в близлежащие отверстия?
  41. * Вода возвращает 4. Лава возвращает 2 в Верхнем мире и 4 в Нижнем.
  42. */
  43. @Override
  44. protected int getFlowSpeed(WorldView worldView) {
  45. return 4;
  46. }
  47.  
  48. /**
  49. * Water returns 1. Lava returns 2 in the Overworld and 1 in the Nether.
  50. */
  51. @Override
  52. protected int getLevelDecreasePerBlock(WorldView worldView) {
  53. return 1;
  54. }
  55.  
  56. /**
  57. * Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether.
  58. */
  59. @Override
  60. public int getTickRate(WorldView worldView) {
  61. return 5;
  62. }
  63.  
  64. /**
  65. * Water and Lava both return 100.0F.
  66. */
  67. @Override
  68. protected float getBlastResistance() {
  69. return 100.0F;
  70. }
  71. }

Implementation

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.

  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. }

Next, we'll make static instances of still and flowing acid variants, and an acid bucket. In your 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(Registry.field_11154, new Identifier(MOD_ID, "acid"), new AcidFluid.Still());
  8. FLOWING_ACID = Registry.register(Registry.field_11154, new Identifier(MOD_ID, "flowing_acid"), new AcidFluid.Flowing());
  9. ACID_BUCKET = Registry.register(Registry.field_11142, new Identifier(MOD_ID, "acid_bucket"),
  10. new BucketItem(STILL_ACID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1)));
  11.  
  12. // ...
  13. }
  14.  
  15. // ...

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:

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

Making a fluid block

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:

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

Now that we have these static objects, we can go back to AcidFluid and fill in the overridden methods:

  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 converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses
  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. }

Rendering setup

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.

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

If you want to use your own fluid textures, you can refer to vanilla's assets 1) as a template.

Generation in the world

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:

  1. public static LakeFeature ACID_LAKE;
  2.  
  3. @Override
  4. public void onInitialize() {
  5. ACID_LAKE = Registry.register(Registry.FEATURE, new Identifier(MOD_ID, "acid_lake"), new LakeFeature(SingleStateFeatureConfig::deserialize));
  6.  
  7. // generate in swamps, similar to water lakes, but with a chance of 40 (the higher the number, the lower the generation chance)
  8. Biomes.SWAMP.addFeature(
  9. GenerationStep.Feature.LOCAL_MODIFICATIONS,
  10. ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState()))
  11. .createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40)))
  12. );
  13. }
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
ru/tutorial/fluids.1645739069.txt.gz · Last modified: 2022/02/24 21:44 by furnygo