User Tools

Site Tools


zh_cn:tutorial:fluids

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
zh_cn:tutorial:fluids [2020/11/15 01:13] – [使用流体abstract] solidblockzh_cn:tutorial:fluids [2023/05/04 11:22] – [创建抽象流体] solidblock
Line 3: Line 3:
 在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。 在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。
 ===== 创建抽象流体 ===== ===== 创建抽象流体 =====
-原版流体扩展了''net.minecraft.fluid.FlowableFluid'',我们也应如此。 +原版流体继承了 ''<yarn net.minecraft.class_3609>'',我们也应如此。 
-<code java [enable_line_numbers="true"]> +<yarncode java [enable_line_numbers="true"]> 
-public abstract class TutorialFluid extends FlowableFluid +public abstract class TutorialFluid extends class_3609 {
-{+
  /**  /**
- * @return is the given fluid an instance of this fluid?+ * @return 给定的流体是否为该流体的实例?
  */  */
  @Override  @Override
- public boolean matchesType(Fluid fluid) + public boolean method_15780(class_3611 fluid) {
- {+
  return fluid == getStill() || fluid == getFlowing();  return fluid == getStill() || fluid == getFlowing();
  }  }
   
  /**  /**
- * @return is the fluid infinite like water?+ * @return 流体是否可以像无限刷水的方法一样无限生成?在原版,这取决于游戏规则。
  */  */
  @Override  @Override
- protected boolean isInfinite() + protected boolean method_15737() {
- {+
  return false;  return false;
  }  }
   
  /**  /**
-Perform actions when fluid flows into a replaceable block. Water drops +流体流入一个可替换的方块时的行为。 
-the block's loot table. Lava plays the "block.lava.extinguish" sound.+水会掉落方块的战利品表。熔岩会播放“block.lava.extinguish”音效。
  */  */
  @Override  @Override
- protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) + protected void method_15730(class_1936 world, class_2338 pos, class_2680 state) {
- {+
  final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null;  final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null;
  Block.dropStacks(state, world, pos, blockEntity);  Block.dropStacks(state, world, pos, blockEntity);
Line 37: Line 33:
   
  /**  /**
-Lava returns true if its FluidState is above a certain height and the +熔岩在其 FluidState 高于指定的高度且该流体为水时返回 true。
- * Fluid is Water.+
  
- * @return if the given Fluid can flow into this FluidState?+ * @return 给定的流体能否流入它的 FluidState
  */  */
  @Override  @Override
- protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction) + protected boolean method_15777(class_3610 fluidState, class_1922 blockView, class_2338 blockPos, class_3611 fluid, class_2350 direction) {
- {+
  return false;  return false;
  }  }
   
  /**  /**
-Possibly related to the distance checks for flowing into nearby holes? +或许与流入周围附近凹洞的距离检查有关? 
-Water returns 4. Lava returns in the Overworld and in the Nether.+水返回4。熔岩在主世界返回2,而在下界返回4
  */  */
  @Override  @Override
- protected int getFlowSpeed(WorldView worldView) + protected int method_15733(class_4538 worldView) {
- {+
  return 4;  return 4;
  }  }
   
  /**  /**
-Water returns 1. Lava returns in the Overworld and in the Nether.+返回每次流动一格,其等级减少的数值。水返回1,熔岩在主世界返回2,在下界返回1
  */  */
  @Override  @Override
- protected int getLevelDecreasePerBlock(WorldView worldView) + protected int method_15739(class_4538 worldView) {
- {+
  return 1;  return 1;
  }  }
   
  /**  /**
-Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether.+返回每流一格需要花费的时间(按刻计算)。水返回5。熔岩在主世界返回30,在下界返回10
  */  */
  @Override  @Override
- public int getTickRate(WorldView worldView) + public int method_15789(class_4538 worldView) {
- {+
  return 5;  return 5;
  }  }
   
  /**  /**
-Water and Lava both return 100.0F.+返回爆炸抗性。水和熔岩都返回100.0F
  */  */
  @Override  @Override
- protected float getBlastResistance() + protected float method_15784() {
- {+
  return 100.0F;  return 100.0F;
  }  }
 } }
-</code>+</yarncode>
  
 ===== 进行 ===== ===== 进行 =====
 +现在让我们制作一个拥有静止和流动两个变种的实际流体。在此教程中,我们将其称为“酸”。缺失的引用稍后补全。
  
-现在让我们进行实际的研究。 它将具有//still// 和 //flowing//变体; 将其命名为“酸性”: +<code java [enable_line_numbers="true"]
- +public abstract class AcidFluid extends TutorialFluid
-<code java> +
-public abstract class Acid extends BasicFluid+
 { {
-    @Override + @Override 
-    public Item getBucketItem() + public Fluid getStill() 
-    +
-        return null+ return <YOUR_STILL_FLUID_HERE>; 
-    +
-    @Override +  
-    protected BlockState toBlockState(FluidState var1+ @Override 
-    + public Fluid getFlowing() 
-        return null+
-    }+ return <YOUR_FLOWING_FLUID_HERE>; 
 +
 +  
 + @Override 
 + public Item getBucketItem() 
 +
 + return <YOUR_BUCKET_ITEM_HERE>
 +
 +  
 + @Override 
 + protected BlockState toBlockState(FluidState fluidState
 +
 + // method_15741 converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses 
 + return <YOUR_FLUID_BLOCK_HERE>.getDefaultState().with(Properties.LEVEL_15, method_15741(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; 
 +
 +
 +
 +</code> 
 +接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。 在您的''ModInitializer''中: 
 +<code java [enable_line_numbers="true"]> 
 +// ...
  
-    @Override +public static FlowableFluid STILL_ACID; 
-    public Fluid getFlowing() +public static FlowableFluid FLOWING_ACID;
-    { +
-        return null; +
-    }+
  
-    @Override +public static Item ACID_BUCKET;
-    public Fluid getStill() +
-    { +
-        return null; +
-    }+
  
-    @Override +// ...
-    public boolean matchesType(Fluid fluid) +
-    { +
-        return false; +
-    }+
  
-    // still acid +@Override 
-    public static class Still extends Acid +public void onInitialize() 
-    {+
 + // ... 
 +  
 + STILL_ACID = Registry.register(Registry.FLUID, new Identifier(MOD_ID, "acid"), new AcidFluid.Still()); 
 +  
 + FLOWING_ACID = Registry.register(Registry.FLUID, new Identifier(MOD_ID, "flowing_acid"), new AcidFluid.Flowing()); 
 +  
 + ACID_BUCKET = Registry.register(Registry.ITEM, new Identifier(MOD_ID, "acid_bucket"), new BucketItem(STILL_ACID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1))); 
 +  
 + // ... 
 +}
  
-        @Override +// ... 
-        public boolean isStill(FluidState fluidState) +</code>
-        { +
-            return true; +
-        }+
  
-        /** +为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:对于水,制作''data/minecraft/tags/fluids/ water.json''文件,并在其中写入流体的标识符: 
-         * @return height of the fluid block +<code json [enable_line_numbers="true"]> 
-         */ +{ 
-        @Override + "replace": false, 
-        public int getLevel(FluidState fluidState) + "values": 
-        { + [ 
-            return 8; + "your_mod_id:acid", 
-        } + "your_mod_id:flowing_acid" 
-    }+ ] 
 +} 
 +</code>
  
-    // flowing acid 
-    public static class Flowing extends  Acid 
-    { 
  
-        @Override +==== 制作一个流体方块 ==== 
-        public boolean isStill(FluidState fluidState) +接下来,我们需要在世界中创建表示酸的方块。''net.minecraft.block.FluidBlock''是我们需要使用的类,但由于其构造器受保护,我们不能直接构造它。一种解决方法是制作子类或者匿名子类。这里我们展示后一种方式。在您的''ModInitializer''中: 
-        { +<code java [enable_line_numbers="true"]> 
-            return false; +// ...
-        }+
  
-        /** +public static Block ACID;
-         * @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); +
-        } +
-    } +
-+
-</code> +
-接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。 在您的** ModInitializer **中: +
-<code java>+
  
-     +@Override 
-    public static Acid stillAcid; +public void onInitialize()
-    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); +
-    }     +
-</code> +
-为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:制作一个文件''data/minecraft/tags/fluids/ water.json'',并在其中写入流体的标识符: +
-<code json>+
 { {
-  "replace": false, + // ... 
-  "values": [ +  
-    "modid:acid_still", + ACID = Registry.register(Registry.BLOCK, new Identifier(MOD_ID, "acid")new FluidBlock(STILL_ACID, FabricBlockSettings.copy(Blocks.WATER)){}); 
-    "modid:acid_flowing" +  
-  ]+ // ...
 } }
 +
 +// ...    
 </code> </code>
  
-==== 制作一个流体方块 ==== +既然我们有了这些静态对象,我们回到''AcidFluid''并补全被重写的方: 
-接下来,我们需要创建一个代表世界酸的图块。 ''net.minecraft.block.FluidBlock''我们需要使用的类,但是出于''mojang''原因,其构造函数受到保护。 该解决案是众所周知的-创建它的子类并更改构造函数的可见性: +<code java [enable_line_numbers="true"]
-<code java> +public abstract class AcidFluid extends TutorialFluid
-public class BaseFluidBlock extends FluidBlock+
 { {
-    public BaseFluidBlock(BaseFluid fluid, Settings settings+ @Override 
-    + public Fluid getStill() 
-        super(fluid, settings); +
-    + 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) 
 +
 + // method_15741 converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses 
 + return TutorialMod.ACID.getDefaultState().with(Properties.LEVEL_15method_15741(fluidState)); 
 + } 
 +  
 + // ... 
 +   
 </code> </code>
 +===== 渲染设置 =====
 +为了让流体拥有纹理,或者与一个颜色绑定,你需要为其注册一个''FluidRenderHandler''。这里,我们重用水的纹理,并仅仅改变用于其上的颜色。为确保纹理渲染为半透明的,你可以使用Fabric的''BlockRenderLayerMap''
  
-现在创建一个静态块实例: +<code java [enable_line_numbers="true"]
-<code java+public class TutorialModClient implements ClientModInitializer
-    ... +
-     +
-    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); +
-    }     +
-</code> +
-现在,当我们有了这些静态对象时,我们返回** Acid **类并完成重写的方法: +
-<code java+
-public abstract class Acid extends BasicFluid+
 { {
-    @Override + // ... 
-    public Item getBucketItem() +  
-    + @Override 
-        return Mod.acidBucket+ public void onInitializeClient() 
-    +
-     + // ... 
-    @Override +  
-    protected BlockState toBlockState(FluidState fluidState+ setupFluidRendering(TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID, new Identifier("minecraft", "water"), 0x4CC248)
-    + BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID); 
-        //don't ask me what **method_15741** does... +  
-        return Mod.acid.getDefaultState().with(FluidBlock.LEVELmethod_15741(fluidState)); + // ... 
-    +
- +  
-    @Override + // ... 
-    public Fluid getFlowing() +  
-    + public static void setupFluidRendering(final Fluid still, final Fluid flowing, final Identifier textureFluidId, final int color
-        return Mod.flowingAcid+
-    + final Identifier stillSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_still"); 
- + final Identifier flowingSpriteId = new Identifier(textureFluidId.getNamespace(), "block/" + textureFluidId.getPath() + "_flow"); 
-    @Override +  
-    public Fluid getStill() + // If they're not already present, add the sprites to the block atlas 
-    + ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX).register((atlasTexture, registry) -> 
-        return Mod.stillAcid+
-    + registry.register(stillSpriteId); 
- + registry.register(flowingSpriteId)
-    @Override + }); 
-    public boolean matchesType(Fluid fluid_1+  
-    + final Identifier fluidId = Registry.FLUID.getId(still); 
-        return fluid_1==Mod.flowingAcid || fluid_1==Mod.stillAcid+ final Identifier listenerId = new Identifier(fluidId.getNamespace()fluidId.getPath() + "_reload_listener"); 
-    +  
-     + final Sprite[] fluidSprites = { null, null }; 
-    ... +  
-     + ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() 
-   + { 
 + @Override 
 + public Identifier getFabricId() 
 +
 + return listenerId; 
 +
 +  
 + /** 
 + * Get the sprites from the block atlas when resources are reloaded 
 + */ 
 + @Override 
 + public void apply(ResourceManager resourceManager) 
 +
 + final Function<Identifier, Sprite> atlas = MinecraftClient.getInstance().getSpriteAtlas(SpriteAtlasTexture.BLOCK_ATLAS_TEX)
 + fluidSprites[0] = atlas.apply(stillSpriteId); 
 + fluidSprites[1] = atlas.apply(flowingSpriteId); 
 +
 + }); 
 +  
 + // The FluidRenderer gets the sprites and color from a FluidRenderHandler during rendering 
 + final FluidRenderHandler renderHandler = new FluidRenderHandler() 
 + { 
 + @Override 
 + public Sprite[] getFluidSprites(BlockRenderView view, BlockPos pos, FluidState state
 +
 + return fluidSprites
 +
 +  
 + @Override 
 + public int getFluidColor(BlockRenderView view, BlockPos pos, FluidState state
 +
 + return color; 
 +
 + }; 
 +  
 + FluidRenderHandlerRegistry.INSTANCE.register(still, renderHandler); 
 + FluidRenderHandlerRegistry.INSTANCE.register(flowing, renderHandler)
 +
 +  
 + // ... 
 +}
 </code> </code>
  
-现在我们可以断言Acid类已完成 +如果你需要使用你自己的流体纹理,你可以参考原版资源包((''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''))作为一个模板
-===== Rendering setup =====+
  
-是时候做客户端的事情了。 ** ClientModInitializer **,您需要流体指定精灵的位置并定义其渲染。 我将重复使用水纹理只是更改应用于它们颜色。 +===== 世界生成 ===== 
-<code java> +为使得酸湖在世界中生成你可以在你''ModInitializer''中创建一个''net.minecraft.world.gen.feature.LakeFeature'',然后将其添加到你需要让它生成的生物群系中:
-    @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 +<code java [enable_line_numbers="true"]> 
-                @Override +// ...
-                public int getFluidColor(ExtendedBlockView view, BlockPos pos, FluidState state) +
-                { +
-                    return 0x4cc248; +
-                } +
-            };+
  
-            // registering the same renderer for both fluid variants is intentional+public static LakeFeature ACID_LAKE;
  
-            FluidRenderHandlerRegistry.INSTANCE.register(Mod.stillAcid, acidRenderHandler); +// ...
-            FluidRenderHandlerRegistry.INSTANCE.register(Mod.flowingAcid, acidRenderHandler); +
-        });+
  
-</code>+@Override 
 +public void onInitialize() 
 +
 + // ... 
 +  
 + ACID_LAKE = Registry.register(Registry.FEATURE, new Identifier(MOD_ID, "acid_lake"), new LakeFeature(SingleStateFeatureConfig::deserialize)); 
 +  
 + // 在沼泽中生成,类似于水湖,但是概率为40(数字越高,生成几率越低) 
 + Biomes.SWAMP.addFeature( 
 + GenerationStep.Feature.LOCAL_MODIFICATIONS, 
 + ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState())) 
 + .createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40))) 
 + ); 
 +  
 + // ... 
 +}
  
-然后剩下要做的就是创建必要的Json文件和纹理,但是您现在应该知道该怎么做。 +// ...
- +
-===== Generation in a world ===== +
- +
-要在世界上产生酸湖,可以使用在ModInitializer中创建的** net.minecraft.world.gen.feature.LakeFeature **: +
-<code java> +
-         +
-        LakeFeature acidFeature = Registry.register(Registry.FEATURE, new Identifier(MODID,"acid_lake"), new LakeFeature(dynamic -> new LakeFeatureConfig(acid.getDefaultState()))); +
- +
-</code> +
-然后将其放入所需的生物群系中以生成: +
-<code java> +
-        // 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)));+
 </code> </code>
-本教程到此结束。 
  
zh_cn/tutorial/fluids.txt · Last modified: 2023/05/04 11:31 by solidblock