zh_cn:tutorial:fluids
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
zh_cn:tutorial:fluids [2020/11/15 01:13] – [使用流体abstract] solidblock | zh_cn:tutorial:fluids [2020/11/15 01:30] – [创建抽象流体] solidblock | ||
---|---|---|---|
Line 8: | Line 8: | ||
{ | { | ||
/** | /** | ||
- | * @return | + | * @return |
*/ | */ | ||
@Override | @Override | ||
Line 17: | Line 17: | ||
/** | /** | ||
- | * @return | + | * @return |
*/ | */ | ||
@Override | @Override | ||
Line 26: | Line 26: | ||
/** | /** | ||
- | * Perform actions when fluid flows into a replaceable block. Water drops | + | * 流体流入一个可替换的方块时的行为。 |
- | * the block' | + | * 水会掉落方块的战利品表。熔岩会播放“block.lava.extinguish”音效。 |
*/ | */ | ||
@Override | @Override | ||
Line 40: | Line 40: | ||
* Fluid is Water. | * Fluid is Water. | ||
* | * | ||
- | * @return | + | * @return |
*/ | */ | ||
@Override | @Override | ||
Line 49: | Line 49: | ||
/** | /** | ||
- | * Possibly related to the distance checks for flowing into nearby holes? | + | * 或许与流入周围附近凹洞的距离检查有关? |
- | * Water returns | + | * 水返回4。熔岩在主世界返回2,而在下界返回4。 |
*/ | */ | ||
@Override | @Override | ||
Line 59: | Line 59: | ||
/** | /** | ||
- | * Water returns | + | * 返回每次流动一格,其等级减少的数值。水返回1,熔岩在主世界返回2,在下界返回1。 |
*/ | */ | ||
@Override | @Override | ||
Line 68: | Line 68: | ||
/** | /** | ||
- | * Water returns | + | * 返回每流一格需要花费的时间(按刻计算)。水返回5。熔岩在主世界返回30,在下界返回10。 |
*/ | */ | ||
@Override | @Override | ||
Line 77: | Line 77: | ||
/** | /** | ||
- | * Water and Lava both return | + | * 返回爆炸抗性。水和熔岩都返回100.0F。 |
*/ | */ | ||
@Override | @Override | ||
Line 88: | Line 88: | ||
===== 进行 ===== | ===== 进行 ===== | ||
+ | 现在让我们制作一个拥有静止和流动两个变种的实际流体。在此教程中,我们将其称为“酸”。缺失的引用稍后补全。 | ||
- | 现在让我们进行实际的研究。 它将具有// | + | <code java [enable_line_numbers=" |
- | + | public abstract class AcidFluid | |
- | <code java> | + | |
- | public abstract class Acid extends | + | |
{ | { | ||
- | | + | @Override |
- | public Item getBucketItem() | + | public Fluid getStill() |
- | { | + | { |
- | return | + | return < |
- | } | + | } |
- | @Override | + | |
- | protected BlockState toBlockState(FluidState | + | @Override |
- | { | + | public Fluid getFlowing() |
- | return | + | { |
- | } | + | return < |
+ | } | ||
+ | |||
+ | @Override | ||
+ | public Item getBucketItem() | ||
+ | { | ||
+ | return | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | protected BlockState toBlockState(FluidState | ||
+ | { | ||
+ | // method_15741 converts the LEVEL_1_8 of the fluid state to the LEVEL_15 the fluid block uses | ||
+ | return | ||
+ | } | ||
+ | |||
+ | public static class Flowing extends AcidFluid | ||
+ | { | ||
+ | @Override | ||
+ | protected void appendProperties(StateManager.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 java [enable_line_numbers=" | ||
+ | // ... | ||
- | @Override | + | public static FlowableFluid STILL_ACID; |
- | public | + | public |
- | { | + | |
- | return null; | + | |
- | } | + | |
- | @Override | + | public |
- | | + | |
- | { | + | |
- | return null; | + | |
- | } | + | |
- | @Override | + | // ... |
- | public boolean matchesType(Fluid fluid) | + | |
- | { | + | |
- | return false; | + | |
- | } | + | |
- | | + | @Override |
- | | + | public void onInitialize() |
- | { | + | { |
+ | // ... | ||
+ | |||
+ | STILL_ACID = Registry.register(Registry.FLUID, | ||
+ | |||
+ | FLOWING_ACID = Registry.register(Registry.FLUID, | ||
+ | |||
+ | ACID_BUCKET = Registry.register(Registry.ITEM, | ||
+ | |||
+ | // ... | ||
+ | } | ||
- | @Override | + | // ... |
- | | + | </ |
- | { | + | |
- | return true; | + | |
- | } | + | |
- | | + | 为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:对于水,制作'' |
- | * @return height of the fluid block | + | <code json [enable_line_numbers=" |
- | */ | + | { |
- | | + | " |
- | | + | " |
- | { | + | [ |
- | | + | " |
- | } | + | " |
- | } | + | ] |
+ | } | ||
+ | </ | ||
- | // flowing acid | ||
- | public static class Flowing extends | ||
- | { | ||
- | @Override | + | ==== 制作一个流体方块 ==== |
- | | + | 接下来,我们需要在世界中创建表示酸的方块。'' |
- | { | + | <code java [enable_line_numbers=" |
- | | + | // ... |
- | } | + | |
- | /** | + | public |
- | * @return height of the fluid block | + | |
- | */ | + | |
- | @Override | + | |
- | | + | |
- | { | + | |
- | return fluidState.get(LEVEL); | + | |
- | } | + | |
- | @Override | + | // ... |
- | protected void appendProperties(StateFactory.Builder< | + | |
- | { | + | |
- | super.appendProperties(stateFactoryBuilder); | + | |
- | stateFactoryBuilder.add(LEVEL); | + | |
- | } | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | 接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。 在您的** ModInitializer **中: | + | |
- | <code java> | + | |
- | + | @Override | |
- | public static Acid stillAcid; | + | public void onInitialize() |
- | public static Acid flowingAcid; | + | |
- | + | ||
- | public static BucketItem acidBucket; | + | |
- | + | ||
- | | + | |
- | public void onInitialize() | + | |
- | { | + | |
- | + | ||
- | stillAcid = Registry.register(Registry.FLUID, | + | |
- | flowingAcid = Registry.register(Registry.FLUID, | + | |
- | + | ||
- | acidBucket = new BucketItem(stillAcid, | + | |
- | Registry.register(Registry.ITEM, | + | |
- | } | + | |
- | </ | + | |
- | 为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:制作一个文件'' | + | |
- | <code json> | + | |
{ | { | ||
- | " | + | // ... |
- | " | + | |
- | "modid: | + | ACID = Registry.register(Registry.BLOCK, |
- | " | + | |
- | ] | + | // ... |
} | } | ||
+ | |||
+ | // ... | ||
</ | </ | ||
- | ==== 制作一个流体方块 ==== | + | 既然我们有了这些静态对象,我们回到'' |
- | 接下来,我们需要创建一个代表世界酸的图块。 '' | + | <code java [enable_line_numbers=" |
- | <code java> | + | public |
- | public class BaseFluidBlock | + | |
{ | { | ||
- | | + | @Override |
- | { | + | public |
- | super(fluid, | + | { |
- | } | + | 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_15, method_15741(fluidState)); | ||
+ | } | ||
+ | |||
+ | // ... | ||
+ | } | ||
</ | </ | ||
+ | ===== 渲染设置 ===== | ||
+ | 为了让流体拥有材质,或者与一个颜色绑定,你需要为其注册一个'' | ||
- | 现在创建一个静态块实例: | + | <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, | + | |
- | Registry.register(Registry.BLOCK, | + | |
- | } | + | |
- | </ | + | |
- | 现在,当我们有了这些静态对象时,我们返回** Acid **类并完成重写的方法: | + | |
- | <code java> | + | |
- | public | + | |
{ | { | ||
- | | + | // ... |
- | public | + | |
- | { | + | @Override |
- | | + | public |
- | } | + | { |
- | + | // ... | |
- | | + | |
- | | + | setupFluidRendering(TutorialMod.STILL_ACID, |
- | { | + | BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), |
- | //don't ask me what **method_15741** does... | + | |
- | | + | // ... |
- | } | + | } |
- | + | ||
- | @Override | + | // ... |
- | public | + | |
- | { | + | public static void setupFluidRendering(final Fluid still, final Fluid flowing, final Identifier textureFluidId, |
- | return | + | { |
- | } | + | final Identifier stillSpriteId = new Identifier(textureFluidId.getNamespace(), |
- | + | final Identifier flowingSpriteId = new Identifier(textureFluidId.getNamespace(), | |
- | @Override | + | |
- | public | + | // If they're not already present, add the sprites to the block atlas |
- | { | + | ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX).register((atlasTexture, |
- | return | + | { |
- | } | + | registry.register(stillSpriteId); |
- | + | registry.register(flowingSpriteId); | |
- | @Override | + | }); |
- | public | + | |
- | { | + | final Identifier fluidId = Registry.FLUID.getId(still); |
- | return | + | final Identifier listenerId = new Identifier(fluidId.getNamespace(), fluidId.getPath() + " |
- | } | + | |
- | + | final Sprite[] fluidSprites = { null, null }; | |
- | ... | + | |
- | | + | ResourceManagerHelper.get(ResourceType.CLIENT_RESOURCES).registerReloadListener(new SimpleSynchronousResourceReloadListener() |
- | } | + | { |
+ | @Override | ||
+ | public | ||
+ | { | ||
+ | return | ||
+ | } | ||
+ | |||
+ | /** | ||
+ | * Get the sprites from the block atlas when resources are reloaded | ||
+ | */ | ||
+ | @Override | ||
+ | public void apply(ResourceManager resourceManager) | ||
+ | { | ||
+ | final Function< | ||
+ | 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 | ||
+ | { | ||
+ | return | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public | ||
+ | { | ||
+ | return | ||
+ | } | ||
+ | }; | ||
+ | |||
+ | FluidRenderHandlerRegistry.INSTANCE.register(still, | ||
+ | FluidRenderHandlerRegistry.INSTANCE.register(flowing, | ||
+ | } | ||
+ | |||
+ | // ... | ||
+ | } | ||
</ | </ | ||
- | 现在我们可以断言Acid类已完成。 | + | 如果你需要使用你自己的流体材质,你可以参考原版资源包(('' |
- | ===== Rendering setup ===== | + | |
- | 是时候做客户端的事情了。 | + | ===== 在世界中生成 ===== |
- | <code java> | + | 为使得酸湖在世界中生成,你可以在你的'' |
- | @Override | + | |
- | public void onInitializeClient() | + | |
- | { | + | |
- | + | ||
- | // adding the sprites to the block texture atlas | + | |
- | ClientSpriteRegistryCallback.event(SpriteAtlasTexture.BLOCK_ATLAS_TEX).register((spriteAtlasTexture, | + | |
- | + | ||
- | Identifier stillSpriteLocation = new Identifier(" | + | |
- | Identifier dynamicSpriteLocation = new Identifier(" | + | |
- | // 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, | + | |
- | } | + | |
- | | + | <code java [enable_line_numbers=" |
- | @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, | + | |
- | }); | + | |
- | </code> | + | @Override |
+ | public void onInitialize() | ||
+ | { | ||
+ | // ... | ||
+ | |||
+ | ACID_LAKE = Registry.register(Registry.FEATURE, | ||
+ | |||
+ | // 在沼泽中生成,类似于水湖,但是概率为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, | + | |
- | + | ||
- | </code> | + | |
- | 然后将其放入所需的生物群系中以生成: | + | |
- | <code java> | + | |
- | | + | |
- | Biomes.FOREST.addFeature(GenerationStep.Feature.LOCAL_MODIFICATIONS, | + | |
</ | </ | ||
- | 本教程到此结束。 | ||
zh_cn/tutorial/fluids.txt · Last modified: 2023/05/04 11:31 by solidblock