zh_cn:tutorial:fluids
Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
zh_cn:tutorial:fluids [2019/12/19 10:16] – created lightcolour | zh_cn:tutorial:fluids [2023/05/04 11:31] (current) – [渲染设置] solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== | + | ====== |
- | ===== Overview | + | ===== 概述 |
- | Here we'll cover creation of a custom fluid. If you plan to create several fluids, it is recommended to make an abstract basic fluid class where you'll set necessary defaults that will be shared in its subclasses. We'll also make it generate in the world like lakes. | + | 在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。 |
- | ===== Making an abstract fluid ===== | + | ===== 创建抽象流体 |
- | Vanilla fluids extend **net.minecraft.fluid.BaseFluid** class, and so will our abstract fluid. It can be like this: | + | 原版流体继承了 ''< |
- | <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 boolean method_15777(class_3610 fluidState, class_1922 blockView, class_2338 blockPos, class_3611 |
- | * @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。 |
- | protected int getLevelDecreasePerBlock(ViewableWorld world) | + | */ |
- | | + | @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; |
- | + | } | |
- | | + | |
- | @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.1576750615.txt.gz · Last modified: 2019/12/19 10:16 by lightcolour