zh_cn:tutorial:fluids
                Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| zh_cn:tutorial:fluids [2019/12/19 10:19] – lightcolour | zh_cn:tutorial:fluids [2023/05/04 11:31] (current) – [渲染设置] solidblock | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== 创建流体 ====== | ====== 创建流体 ====== | ||
| - | ===== Overview  | + | ===== 概述  | 
| - | 在这里,我们将介绍自定义流体的创建。 如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。 我们还将使其像湖泊一样在世界上产生。 | + | 在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。 | 
| - | ===== 使抽象流畅 ===== | + | ===== 创建抽象流体 ===== | 
| - | 香草流体扩展了**net.minecraft.fluid.BaseFluid**类,我们的抽象流体也将扩展。 可能是这样的: | + | 原版流体继承了 ''< | 
| - | <code java> | + | <yarncode  | 
| - | public abstract class BasicFluid  | + | public abstract class TutorialFluid  | 
| - | { | + | /** | 
| - | /** | + | 	 * @return  | 
| - |       | + | */ | 
| - |       | + | @Override | 
| - | @Override | + | 	public  | 
| - |      | + | 		return  | 
| - |      | + | } | 
| - |         return  | + | |
| - | } | + | /** | 
| - | + | 	 * @return  | |
| - | // make it transparent | + | */ | 
| - | @Override | + | @Override | 
| - | protected BlockRenderLayer getRenderLayer() | + | protected boolean method_15737() { | 
| - | { | + | return false; | 
| - | return BlockRenderLayer.TRANSLUCENT; | + | } | 
| - | } | + | |
| - | + | /** | |
| - | /** | + | * 流体流入一个可替换的方块时的行为。 | 
| - | * | + | * 水会掉落方块的战利品表。熔岩会播放“block.lava.extinguish”音效。 | 
| - |      * @return  | + | */ | 
| - |       | + | @Override | 
| - | @Override | + | 	protected  | 
| - |      | + | final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null; | 
| - | + | Block.dropStacks(state, world, pos, blockEntity); | |
| - | /** | + | } | 
| - |       | + | |
| - |       | + | /** | 
| - |       | + | * 熔岩在其 FluidState 高于指定的高度且该流体为水时返回 true。 | 
| - | @Override | + | * | 
| - |     protected  | + | 	 * @return  | 
| - | + | */ | |
| - | /** | + | @Override | 
| - | * | + | 	protected  | 
| - | * @return flowing static instance of this fluid | + | 		return  | 
| - | */ | + | } | 
| - | @Override | + | |
| - | public abstract Fluid getFlowing(); | + | /** | 
| - | + | * 或许与流入周围附近凹洞的距离检查有关? | |
| - | /** | + | * 水返回4。熔岩在主世界返回2,而在下界返回4。 | 
| - |       | + | */ | 
| - |       | + | @Override | 
| - |       | + | 	protected  | 
| - | @Override | + | 		return  | 
| - |      | + | } | 
| - | + | ||
| - | // how much does the height of the fluid block decreases | + | /** | 
| - | @Override | + | * 返回每次流动一格,其等级减少的数值。水返回1,熔岩在主世界返回2,在下界返回1。 | 
| - |      | + | */ | 
| - |      | + | @Override | 
| - |         return  | + | protected int method_15739(class_4538 worldView) { | 
| - | } | + | 		return  | 
| - | + | } | |
| - | /** | + | |
| - |       | + | /** | 
| - |       | + | * 返回每流一格需要花费的时间(按刻计算)。水返回5。熔岩在主世界返回30,在下界返回10。 | 
| - |       | + | */ | 
| - | @Override | + | @Override | 
| - |      | + | 	public  | 
| - |      | + | 		return  | 
| - |         return  | + | } | 
| - | } | + | |
| - | + | /** | |
| - |      | + | * 返回爆炸抗性。水和熔岩都返回100.0F。 | 
| - |      | + | */ | 
| - | { | + | @Override | 
| - | return 100; | + | protected float method_15784() { | 
| - | } | + | return 100.0F; | 
| - | + | } | |
| - |     // this seems to determine fluid' | + | |
| - | @Override | + | |
| - | protected int method_15733(ViewableWorld world) | + | |
| - |      | + | |
| - |         return  | + | |
| - | } | + | |
| - | + | ||
| - | // I don't know what this does, but it's present in the water fluid | + | |
| - | @Override | + | |
| - |      | + | |
| - | BlockEntity blockEntity = blockState.getBlock().hasBlockEntity() ? world.getBlockEntity(blockPos) : null; | + | |
| - |         Block.dropStacks(blockState, | + | |
| - | } | + | |
| - | + | ||
| - | // also don't know what it does | + | |
| - |      | + | |
| - |         return  | + | |
| - | } | + | |
| - | + | ||
| - | /** | + | |
| - |       | + | |
| - | * @return is given fluid instance of this fluid? | + | |
| - | */ | + | |
| - | @Override | + | |
| - |      | + | |
| } | } | ||
| - | </code> | + | </yarncode> | 
| - | ===== Implementation  | + | ===== 实现  | 
| - | Now let's make an actual fluid; it will have a //still// and //flowing// variants; will name it " | + | 现在让我们制作一个拥有静止和流动两个变种的实际流体。在此教程中,我们将其称为“酸”。缺失的引用稍后补全。 | 
| - | <code java> | + | <yarncode  | 
| - | public abstract class Acid extends  | + | public abstract class AcidFluid  | 
| - | { | + | @Override | 
| - | @Override | + | 	public  | 
| - |     public  | + | 		return  | 
| - | { | + | } | 
| - | return null; | + | |
| - | } | + | |
| - | @Override | + | |
| - | protected BlockState toBlockState(FluidState var1) | + | |
| - |      | + | |
| - |         return  | + | |
| - | } | + | |
| - |      | + | @Override | 
| - |     public  | + | 	public  | 
| - |      | + | 		return  | 
| - |         return  | + | } | 
| - | } | + | |
| - |      | + | @Override | 
| - |     public  | + | 	public  | 
| - |      | + | 		return  | 
| - |         return  | + | } | 
| - | } | + | |
| - |      | + | @Override | 
| - |      | + | protected class_2680 method_15790(class_3610 fluidState) { | 
| - |      | + | 		return  | 
| - |         return  | + | } | 
| - | } | + | |
| - | // still acid | + | 	public static class Flowing  | 
| - |      | + | @Override | 
| - | { | + | 		protected void method_15775(class_2689.class_2690< | 
| + | 			super.method_15775(builder); | ||
| + | 			builder.method_11667(field_15900); | ||
| + | } | ||
| - |          | + | @Override | 
| - |         public  | + | 		public  | 
| - |          | + | 			return  | 
| - |             return  | + | } | 
| - | } | + | |
| - | /** | + | @Override | 
| - | * @return height of the fluid block | + | 		public  | 
| - | */ | + | 			return  | 
| - |          | + | } | 
| - |         public  | + | } | 
| - |          | + | |
| - |             return  | + | |
| - | } | + | |
| - | } | + | |
| - | // flowing acid | + | 	public static class Still extends  | 
| - |      | + | @Override | 
| - | { | + | 		public int method_15779(class_3610 fluidState)  | 
| + | return 8; | ||
| + | } | ||
| - |          | + | @Override | 
| - |         public boolean  | + | 		public boolean  | 
| - |          | + | 			return  | 
| - |             return  | + | } | 
| - | } | + | } | 
| - | + | ||
| - | /** | + | |
| - | * @return height of the fluid block | + | |
| - | */ | + | |
| - | @Override | + | |
| - | public int getLevel(FluidState fluidState) | + | |
| - | { | + | |
| - |             return fluidState.get(LEVEL); | + | |
| - | } | + | |
| - | + | ||
| - | @Override | + | |
| - |         protected void appendProperties(StateFactory.Builder< | + | |
| - | { | + | |
| - |             super.appendProperties(stateFactoryBuilder); | + | |
| - | stateFactoryBuilder.add(LEVEL); | + | |
| - | } | + | |
| - | } | + | |
| } | } | ||
| - | </code> | + | </yarncode> | 
| - | + | 接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。在您的 '' | |
| - | Next, we'll make static instances of still and flowing acid variants, and an acid bucket. In your **ModInitializer**: | + | <yarncode  | 
| - | + | public static  | |
| - | <code java> | + | public static  | 
| - | + | public static  | |
| - | + | ||
| - |      | + | @Override | 
| - |     public static  | + | public void onInitialize() { | 
| - | + | 	STILL_ACID  | |
| - |      | + | 	FLOWING_ACID  | 
| - | + | 	ACID_BUCKET = class_2378.method_10230(class_7923.field_41178, | |
| - | @Override | + | new class_1755(STILL_ACID, new class_1792.class_1793().method_7896(class_1802.field_8550).method_7889(1))); | 
| - | public void onInitialize() | + | |
| - |      | + | // ... | 
| - | + | } | |
| - |         stillAcid  | + | |
| - |          | + | // ... | 
| - | + | </yarncode> | |
| - |          | + | |
| - |          | + | |
| - | } | + | |
| - | </code> | + | |
| - | To make the custom fluid behave like water or lava, you must add it to a corresponding fluid tag: make a file "data/ | + | 为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:对于水,制作 '' | 
| - | <code json> | + | <code json [enable_line_numbers=" | 
| { | { | ||
| - |    | + | 	" | 
| - |   " | + | 	" | 
| - | "modid:acid_still", | + | [ | 
| - | "modid:acid_flowing" | + | "tutorial:acid", | 
| - | ] | + | "tutorial:flowing_acid" | 
| + | ] | ||
| } | } | ||
| </ | </ | ||
| - | ==== 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 for " | ||
| - | <code java> | + | ==== 制作一个流体方块 ==== | 
| - | public  | + | 接下来,我们需要在世界中创建表示酸的方块。'' | 
| - | { | + | < | 
| - | public BaseFluidBlock(BaseFluid fluid, Settings settings) | + | public  | 
| - | { | + | |
| - |         super(fluid, | + | |
| - | } | + | |
| - | } | + | |
| - | </ | + | |
| - | Now make a static block instance: | + | @Override | 
| + | public void onInitialize() { | ||
| + | 	ACID = class_2378.method_10230(class_7923.field_41175, | ||
| + | |||
| + | // ... | ||
| + | } | ||
| + | </ | ||
| - | <code java> | + | 既然我们有了这些静态对象,我们回到 '' | 
| - | ... | + | <yarncode  | 
| - | + | public abstract class AcidFluid extends TutorialFluid { | |
| - |     public  | + | @Override | 
| + | public class_3611 method_15751() { | ||
| + | 		return TutorialMod.STILL_ACID; | ||
| + | } | ||
| + | |||
| + | @Override | ||
| + | public class_3611 method_15750() { | ||
| + | 		return TutorialMod.FLOWING_ACID; | ||
| + | } | ||
| + | |||
| + | @Override | ||
| + | 	public  | ||
| + | return TutorialMod.ACID_BUCKET; | ||
| + | } | ||
| + | |||
| + | @Override | ||
| + | protected class_2680 method_15790(class_3610 fluidState) { | ||
| + | // method_15741 将流体状态的 LEVEL_1_8 转换为流体方块使用的 LEVEL_15 | ||
| + | 		return TutorialMod.ACID.method_9564().method_11657(class_2741.field_12538, | ||
| + | } | ||
| - |      | + | public static class Flowing extends AcidFluid { | 
| - |      | + | @Override | 
| - |      | + | 		protected  | 
| - | + | super.method_15775(builder); | |
| - |          | + | builder.method_11667(field_15900); | 
| - | + | } | |
| - | acid = new BaseFluidBlock(stillAcid, FabricBlockSettings.of(Material.WATER).dropsNothing().build()); | + | |
| - |          | + | |
| - | } | + | |
| - | </ | + | |
| - | Now when we have these static objects, we go back to **Acid** class and complete the overridden methods: | + | @Override | 
| + | public int method_15779(class_3610 fluidState) { | ||
| + | 			return fluidState.method_11654(field_15900); | ||
| + | } | ||
| - | <code java> | + | @Override | 
| - | public abstract class Acid extends BasicFluid | + | 		public  | 
| - | { | + | 			return  | 
| - |      | + | } | 
| - |     public  | + | } | 
| - |      | + | |
| - |         return  | + | |
| - | } | + | |
| - | + | ||
| - | @Override | + | |
| - | protected BlockState toBlockState(FluidState fluidState) | + | |
| - | { | + | |
| - |         // | + | |
| - |         return Mod.acid.getDefaultState().with(FluidBlock.LEVEL, | + | |
| - |      | + | |
| - |      | + | public static class Still extends AcidFluid { | 
| - |     public  | + | @Override | 
| - |      | + | 		public  | 
| - |         return  | + | 			return  | 
| - | } | + | } | 
| - |      | + | @Override | 
| - |     public  | + | 		public  | 
| - |      | + | 			return  | 
| - |         return  | + | } | 
| - | } | + | } | 
| + | } | ||
| + | </ | ||
| + | ===== 渲染设置 ===== | ||
| + | 为了让流体拥有纹理,或者与一个颜色绑定,你需要为其注册一个'' | ||
| - |      | + | < | 
| - | public boolean matchesType(Fluid fluid_1) | + | @Environment(EnvType.CLIENT) | 
| - | { | + | public class TutorialModClient implements ClientModInitializer  | 
| - |         return fluid_1==Mod.flowingAcid || fluid_1==Mod.stillAcid; | + | |
| - | } | + | |
| - | + | ||
| - | ... | + | |
| - | + | ||
| - | } | + | |
| - | </ | + | |
| - | Now we can assert that the Acid class is complete. | + | @Override | 
| + | public void onInitializeClient() { | ||
| + | 		FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.STILL_ACID, | ||
| + | 				new class_2960(" | ||
| + | 				new class_2960(" | ||
| + | 0x4CC248 | ||
| + | )); | ||
| - | ===== Rendering setup ===== | + | 		BlockRenderLayerMap.INSTANCE.putFluids(class_1921.method_23583(), | 
| - | Time to do client-side things. In your **ClientModInitializer**  | + | 		// | 
| + | 		//In this example this is unnecessary because the vanilla  | ||
| + | //To register your custom textures use this method. | ||
| + | 		// | ||
| + | 		//    registry.register(new Identifier(" | ||
| + | 		//    registry.register(new Identifier(" | ||
| + | //}); | ||
| - | <code java> | + | // ... | 
| - | @Override | + | } | 
| - | public void onInitializeClient() | + | } | 
| - | { | + | </yarncode> | 
| - | + | ||
| - |          | + | |
| - |         ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX).register((spriteAtlasTexture, | + | |
| - | + | ||
| - |              | + | |
| - |              | + | |
| - | // here I tell to use only 16x16 area of the water texture | + | |
| - |             FabricSprite stillAcidSprite = new FabricSprite(stillSpriteLocation, | + | |
| - | // same, but 32 | + | |
| - |             FabricSprite dynamicAcidSprite = new FabricSprite(dynamicSpriteLocation, | + | |
| - | + | ||
| - |             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/ | + | |
| - | @Override | + | |
| - |                 public Sprite[] getFluidSprites(ExtendedBlockView extendedBlockView, | + | |
| - | { | + | |
| - |                     return new Sprite[] {stillAcidSprite, | + | |
| - | } | + | |
| - |                  | + | 如果你需要使用你自己的流体纹理,你可以参考原版资源包(('' | 
| - | @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, | + | <code java [enable_line_numbers=" | 
| - |              | + | // ... | 
| - | }); | + | |
| - | </ | + | public static LakeFeature ACID_LAKE; | 
| - | Then what's left to do is to create necessary Json files and textures, but you should know how to do that at this point. | + | // ... | 
| - | ===== Generation in a world ===== | + | @Override | 
| + | public void onInitialize() | ||
| + | { | ||
| + | // ... | ||
| + | |||
| + | 	ACID_LAKE  | ||
| + | |||
| + | // 在沼泽中生成,类似于水湖,但是概率为40(数字越高,生成几率越低) | ||
| + | Biomes.SWAMP.addFeature( | ||
| + | 		GenerationStep.Feature.LOCAL_MODIFICATIONS, | ||
| + | ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState())) | ||
| + | .createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40))) | ||
| + | ); | ||
| + | |||
| + | // ... | ||
| + | } | ||
| - | To make acid lakes generate in the world, you can use **net.minecraft.world.gen.feature.LakeFeature**, | + | // ... | 
| - | <code java> | + | |
| - | + | ||
| - |         LakeFeature acidFeature = Registry.register(Registry.FEATURE, | + | |
| - | + | ||
| - | </code> | + | |
| - | Then put it into desired biomes to generate: | + | |
| - | <code java> | + | |
| - |          | + | |
| - |         Biomes.FOREST.addFeature(GenerationStep.Feature.LOCAL_MODIFICATIONS, | + | |
| </ | </ | ||
| - | This is the end of the tutorial. | ||
zh_cn/tutorial/fluids.1576750765.txt.gz · Last modified: 2019/12/19 10:19 by lightcolour