User Tools

Site Tools


tutorial:fluids

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
tutorial:fluids [2023/05/04 11:31] – [Rendering setup] solidblocktutorial:fluids [2026/02/20 12:08] (current) – Migrated Names to Mojmap & updated text to 1.21.11 infinitychances
Line 5: Line 5:
  
 ===== Making an abstract fluid ===== ===== Making an abstract fluid =====
-Vanilla fluids extend ''<yarn net.minecraft.class_3609>'', and so shall we. +Vanilla fluids extend ''net.minecraft.world.level.material.FlowingFluid'', and so shall we. 
-<yarncode java [enable_line_numbers="true"]> +<code java [enable_line_numbers="true"]> 
-public abstract class TutorialFluid extends class_3609 {+public abstract class TutorialFluid extends FlowingFluid {
  /**  /**
  * @return whether the given fluid an instance of this fluid  * @return whether the given fluid an instance of this fluid
  */  */
  @Override  @Override
- public boolean method_15780(class_3611 fluid) { + public boolean isSame(Fluid fluid) { 
- return fluid == method_15751() || fluid == method_15750();+ return fluid == getSource() || fluid == getFlowing();
  }  }
  
Line 20: Line 20:
  */  */
  @Override  @Override
- protected boolean method_15737() {+ protected boolean canConvertToSource() {
  return false;  return false;
  }  }
Line 29: Line 29:
  */  */
  @Override  @Override
- protected void method_15730(class_1936 worldclass_2338 pos, class_2680 state) { + protected void beforeDestroyingBlock(LevelAccessor levelBlockPos pos, BlockState state) { 
- final class_2586 blockEntity = state.method_31709() ? world.method_8321(pos) : null; + final BlockEntity entity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; 
- class_2248.method_9610(state, world, pos, blockEntity);+ Block.dropResources(state, level, pos, entity);
  }  }
  
Line 41: Line 41:
  */  */
  @Override  @Override
- protected boolean method_15777(class_3610 fluidStateclass_1922 blockViewclass_2338 blockPosclass_3611 fluid, class_2350 direction) {+ protected boolean canBeReplacedWith(FluidState stateBlockGetter levelBlockPos posFluid fluid, Direction direction) {
  return false;  return false;
  }  }
Line 50: Line 50:
  */  */
  @Override  @Override
- protected int method_15733(class_4538 worldView) {+ protected int getSlopeFindDistance(LevelReader reader) {
  return 4;  return 4;
  }  }
  
  /**  /**
- * Water returns 1. Lava returns 2 in the Overworld and 1 in the Nether.+ * Water returns 1. Lava returns 2 in the overworld and 1 in the nether. 
 + * @return How many levels a fluid loses per block.
  */  */
  @Override  @Override
- protected int method_15739(class_4538 worldView) {+ protected int getDropOff(LevelReader reader) {
  return 1;  return 1;
  }  }
Line 64: Line 65:
  /**  /**
  * Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether.  * Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether.
 + * Seems to return the delay before it updates its state.
  */  */
  @Override  @Override
- public int method_15789(class_4538 worldView) {+ public int getTickDelay(LevelReader reader) {
  return 5;  return 5;
  }  }
Line 74: Line 76:
  */  */
  @Override  @Override
- protected float method_15784() {+ protected float getExplosionResistance() {
  return 100.0F;  return 100.0F;
  }  }
 } }
-</yarncode>+</code>
  
 ===== Implementation ===== ===== 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. 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.
  
-<yarncode java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"]>
 public abstract class AcidFluid extends TutorialFluid { public abstract class AcidFluid extends TutorialFluid {
  @Override  @Override
- public class_3611 method_15751() { + public Fluid getSource() { 
- return YOUR_STILL_FLUID_HERE;+ return YOUR_SOURCE_FLUID_HERE;
  }  }
  
  @Override  @Override
- public class_3611 method_15750() {+ public Fluid getFlowing() {
  return YOUR_FLOWING_FLUID_HERE;  return YOUR_FLOWING_FLUID_HERE;
  }  }
  
  @Override  @Override
- public class_1792 method_15774() {+ public Item getBucket() {
  return YOUR_BUCKET_ITEM_HERE;  return YOUR_BUCKET_ITEM_HERE;
  }  }
  
  @Override  @Override
- protected class_2680 method_15790(class_3610 fluidState) { + protected BlockState createLegacyBlock(FluidState state) { 
- return YOUR_FLUID_BLOCK_HERE.method_9564().method_11657(class_2741.field_12538method_15741(fluidState));+ return YOUR_FLUID_BLOCK_HERE.defaultBlockState().setValue(BlockStateProperties.LEVELgetLegacyLevel(state));
  }  }
  
  public static class Flowing extends AcidFluid {  public static class Flowing extends AcidFluid {
  @Override  @Override
- protected void method_15775(class_2689.class_2690<class_3611class_3610> builder) { + protected void createFluidStateDefinition(StateDefinition.Builder<FluidFluidState> builder) { 
- super.method_15775(builder); + super.createFluidStateDefinition(builder); 
- builder.method_11667(field_15900);+ builder.add(LEVEL);
  }  }
  
  @Override  @Override
- public int method_15779(class_3610 fluidState) { + public boolean isSource(FluidState state) { 
- return fluidState.method_11654(field_15900);+ return false;
  }  }
  
  @Override  @Override
- public boolean method_15793(class_3610 fluidState) { + public int getAmount(FluidState state) { 
- return false;+ return state.getValue(LEVEL);
  }  }
  }  }
Line 125: Line 127:
  public static class Still extends AcidFluid {  public static class Still extends AcidFluid {
  @Override  @Override
- public int method_15779(class_3610 fluidState) { + public boolean isSource(FluidState state) { 
- return 8;+ return true;
  }  }
  
  @Override  @Override
- public boolean method_15793(class_3610 fluidState) { + public int getAmount(FluidState state) { 
- return true;+ return 8;
  }  }
  }  }
 } }
-</yarncode>+</code>
  
 Next, we'll make static instances of still and flowing acid variants, and an acid bucket. In your ''ModInitializer'': Next, we'll make static instances of still and flowing acid variants, and an acid bucket. In your ''ModInitializer'':
  
-<yarncode java [enable_line_numbers="true"]> +<code java [enable_line_numbers="true"]> 
-public static class_3609 STILL_ACID+public static FlowingFluid ACID_SOURCE
-public static class_3609 FLOWING_ACID; +public static FlowingFluid FLOWING_ACID; 
-public static class_1792 ACID_BUCKET;+public static Item ACID_BUCKET;
    
 @Override @Override
 public void onInitialize() { public void onInitialize() {
- STILL_ACID class_2378.method_10230(class_7923.field_41173new class_2960("tutorial", "acid"), new AcidFluid.Still()); + ACID_SOURCE Registry.register(BuiltInRegistries.FLUIDIdentifier.fromNamespaceAndPath("tutorial", "acid"), new AcidFluid.Still()) 
- FLOWING_ACID = class_2378.method_10230(class_7923.field_41173new class_2960("tutorial", "flowing_acid"), new AcidFluid.Flowing()); + FLOWING_ACID =  Registry.register(BuiltInRegistries.FLUIDIdentifier.fromNamespaceAndPath("tutorial", "flowing_acid"), new AcidFluid.Flowing()); 
- ACID_BUCKET = class_2378.method_10230(class_7923.field_41178new class_2960("tutorial", "acid_bucket"),  + ACID_BUCKET = Registry.register(BuiltInRegistries.ITEMIdentifier.fromNamespaceAndPath("tutorial", "acid_bucket"),  
-        new class_1755(STILL_ACID, new class_1792.class_1793().method_7896(class_1802.field_8550).method_7889(1)));+        new BucketItem(ACID_SOURCE, properties), new Item.Properties().craftRemainder(Items.BUCKET).stacksTo(1);
    
  // ...  // ...
Line 155: Line 157:
    
 // ... // ...
-</yarncode>+</code>
  
-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:+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/fluid/water.json'' file and write the identifiers of your fluids in there:
 <code json [enable_line_numbers="true"]> <code json [enable_line_numbers="true"]>
 { {
Line 170: Line 172:
  
 ===== Making a fluid block ===== ===== Making a fluid block =====
-Next we need to create a block which will represent acid in the world. ''<yarn net.minecraft.class_2404>'' 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'':+Next we need to create a block which will represent acid in the world. ''net.minecraft.world.level.block.LiquidBlock'' is the class we need to use. In your ''ModInitializer'':
  
-<yarncode java [enable_line_numbers="true"]> +<code java [enable_line_numbers="true"]> 
-public static class_2248 ACID;+public static Block ACID;
  
 @Override @Override
 public void onInitialize() { public void onInitialize() {
- ACID = class_2378.method_10230(class_7923.field_41175new class_2960(MOD_ID, "acid"), new class_2404(STILL_ACIDFabricBlockSettings.method_9630(class_2246.field_10382)){});+ ACID = Registry.register(BuiltInRegistries.BLOCKIdentifier.fromNamespaceAndPath("tutorial", "acid"), new LiquidBlock(ACID_SOURCEBlockBehaviour.Properties.ofFullCopy(Blocks.WATER)));
   
  // ...  // ...
  
-</yarncode>+</code>
  
 Now that we have these static objects, we can go back to ''AcidFluid'' and fill in the overridden methods: Now that we have these static objects, we can go back to ''AcidFluid'' and fill in the overridden methods:
  
-<yarncode java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"]>
 public abstract class AcidFluid extends TutorialFluid { public abstract class AcidFluid extends TutorialFluid {
  @Override  @Override
- public class_3611 method_15751() { + public Fluid getSource() { 
- return TutorialMod.STILL_ACID;+ return TutorialMod.ACID_SOURCE;
  }  }
- +
  @Override  @Override
- public class_3611 method_15750() {+ public Fluid getFlowing() {
  return TutorialMod.FLOWING_ACID;  return TutorialMod.FLOWING_ACID;
  }  }
- +
  @Override  @Override
- public class_1792 method_15774() {+ public Item getBucket() {
  return TutorialMod.ACID_BUCKET;  return TutorialMod.ACID_BUCKET;
  }  }
- +
  @Override  @Override
- protected class_2680 method_15790(class_3610 fluidState) { + protected BlockState createLegacyBlock(FluidState state) { 
- // method_15741 converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses + return TutorialMod.ACID.defaultBlockState().setValue(BlockStateProperties.LEVELgetLegacyLevel(state));
- return TutorialMod.ACID.method_9564().method_11657(class_2741.field_12538method_15741(fluidState));+
  }  }
  
  public static class Flowing extends AcidFluid {  public static class Flowing extends AcidFluid {
  @Override  @Override
- protected void method_15775(class_2689.class_2690<class_3611class_3610> builder) { + protected void createFluidStateDefinition(StateDefinition.Builder<FluidFluidState> builder) { 
- super.method_15775(builder); + super.createFluidStateDefinition(builder); 
- builder.method_11667(field_15900);+ builder.add(LEVEL);
  }  }
  
  @Override  @Override
- public int method_15779(class_3610 fluidState) { + public boolean isSource(FluidState state) { 
- return fluidState.method_11654(field_15900);+ return false;
  }  }
  
  @Override  @Override
- public boolean method_15793(class_3610 fluidState) { + public int getAmount(FluidState state) { 
- return false;+ return state.getValue(LEVEL);
  }  }
  }  }
Line 228: Line 229:
  public static class Still extends AcidFluid {  public static class Still extends AcidFluid {
  @Override  @Override
- public int method_15779(class_3610 fluidState) { + public boolean isSource(FluidState state) { 
- return 8;+ return true;
  }  }
  
  @Override  @Override
- public boolean method_15793(class_3610 fluidState) { + public int getAmount(FluidState state) { 
- return true;+ return 8;
  }  }
  }  }
-  +
-</yarncode>+</code>
  
 ===== Rendering setup ===== ===== 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'' (see [[blockappearance]]). 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'' (see [[blockappearance]]).
  
-<yarncode java [enable_line_numbers="true"]>+<code java [enable_line_numbers="true"]>
 @Environment(EnvType.CLIENT) @Environment(EnvType.CLIENT)
 public class TutorialModClient implements ClientModInitializer { public class TutorialModClient implements ClientModInitializer {
Line 249: Line 250:
  @Override  @Override
  public void onInitializeClient() {  public void onInitializeClient() {
- FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID, new SimpleFluidRenderHandler( + FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.ACID_SOURCE, TutorialMod.FLOWING_ACID, SimpleFluidRenderHandler.coloredWater(0x4CC248));
- new class_2960("minecraft:block/water_still"), +
- new class_2960("minecraft:block/water_flow"), +
- 0x4CC248 +
- ));+
  
- BlockRenderLayerMap.INSTANCE.putFluids(class_1921.method_23583(), TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID); + BlockRenderLayerMap.putFluids(ChunkSectionLayer.TRANSLUCENT, TutorialMod.ACID_SOURCE, 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("tutorial:block/custom_fluid_still")); +
- //    registry.register(new Identifier("tutorial:block/custom_fluid_flowing")); +
- //}); +
- +
- // ...+
  }  }
 } }
-</yarncode>+</code>
  
 If you want to use your own fluid textures, you can refer to vanilla's assets ((''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'')) as a template. If you want to use your own fluid textures, you can refer to vanilla's assets ((''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'')) as a template.
  
-===== Generation in the world ===== 
-TODO Update to 1.19.4 
-</code> 
tutorial/fluids.txt · Last modified: 2026/02/20 12:08 by infinitychances