This is an old revision of the document!
Table of Contents
创建流体
概述
在这里,我们将介绍自定义流体的创建。如果计划创建多个流体,建议创建一个抽象的基本流体类,在其中设置必要的默认值,这些默认值将在其子类中共享。我们还将使其像湖泊一样在世界中生成。
创建抽象流体
原版流体扩展了net.minecraft.fluid.FlowableFluid
,我们也应如此。
public abstract class TutorialFluid extends FlowableFluid { /** * @return is the given fluid an instance of this fluid? */ @Override public boolean matchesType(Fluid fluid) { return fluid == getStill() || fluid == getFlowing(); } /** * @return is the fluid infinite like water? */ @Override protected boolean isInfinite() { 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. */ @Override protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) { final BlockEntity blockEntity = state.getBlock().hasBlockEntity() ? world.getBlockEntity(pos) : null; Block.dropStacks(state, world, pos, blockEntity); } /** * Lava returns true if its FluidState is above a certain height and the * Fluid is Water. * * @return if the given Fluid can flow into this FluidState? */ @Override protected boolean canBeReplacedWith(FluidState fluidState, BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction) { return false; } /** * Possibly related to the distance checks for flowing into nearby holes? * Water returns 4. Lava returns 2 in the Overworld and 4 in the Nether. */ @Override protected int getFlowSpeed(WorldView worldView) { return 4; } /** * Water returns 1. Lava returns 2 in the Overworld and 1 in the Nether. */ @Override protected int getLevelDecreasePerBlock(WorldView worldView) { return 1; } /** * Water returns 5. Lava returns 30 in the Overworld and 10 in the Nether. */ @Override public int getTickRate(WorldView worldView) { return 5; } /** * Water and Lava both return 100.0F. */ @Override protected float getBlastResistance() { return 100.0F; } }
进行
现在让我们制作一个拥有静止和流动两个变种的实际流体。在此教程中,我们将其称为“酸”。缺失的引用稍后补全。
public abstract class AcidFluid extends TutorialFluid { @Override public Fluid getStill() { return <YOUR_STILL_FLUID_HERE>; } @Override public Fluid getFlowing() { 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; } } }
接下来,我们将制作静态和动态酸变体的静态实例,以及一个酸桶。 在您的ModInitializer
中:
// ... public static FlowableFluid STILL_ACID; public static FlowableFluid FLOWING_ACID; public static Item ACID_BUCKET; // ... @Override public void onInitialize() { // ... // ... } // ...
为了使自定义流体表现得像水或熔岩,您必须将其添加到相应的流体标签中:对于水,制作data/minecraft/tags/fluids/ water.json
文件,并在其中写入流体的标识符:
{ "replace": false, "values": [ "your_mod_id:acid", "your_mod_id:flowing_acid" ] }
制作一个流体方块
接下来,我们需要创建一个代表世界酸的图块。 net.minecraft.block.FluidBlock
是我们需要使用的类,但是出于mojang
的原因,其构造函数受到保护。 该解决方案是众所周知的-创建它的子类并更改构造函数的可见性:
public class BaseFluidBlock extends FluidBlock { public BaseFluidBlock(BaseFluid fluid, Settings settings) { super(fluid, settings); } }
现在创建一个静态块实例:
... 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); }
现在,当我们有了这些静态对象时,我们返回 Acid 类并完成重写的方法:
public abstract class Acid extends BasicFluid { @Override public Item getBucketItem() { return Mod.acidBucket; } @Override protected BlockState toBlockState(FluidState fluidState) { //don't ask me what **method_15741** does... return Mod.acid.getDefaultState().with(FluidBlock.LEVEL, method_15741(fluidState)); } @Override public Fluid getFlowing() { return Mod.flowingAcid; } @Override public Fluid getStill() { return Mod.stillAcid; } @Override public boolean matchesType(Fluid fluid_1) { return fluid_1==Mod.flowingAcid || fluid_1==Mod.stillAcid; } ... }
现在我们可以断言Acid类已完成。
Rendering setup
是时候做客户端的事情了。 在 ClientModInitializer 中,您需要为流体指定精灵的位置并定义其渲染。 我将重复使用水纹理,只是更改应用于它们的颜色。
@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 @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, acidRenderHandler); FluidRenderHandlerRegistry.INSTANCE.register(Mod.flowingAcid, acidRenderHandler); });
然后剩下要做的就是创建必要的Json文件和纹理,但是您现在应该知道该怎么做。
Generation in a world
要在世界上产生酸湖,可以使用在ModInitializer中创建的 net.minecraft.world.gen.feature.LakeFeature :
LakeFeature acidFeature = Registry.register(Registry.FEATURE, new Identifier(MODID,"acid_lake"), new LakeFeature(dynamic -> new LakeFeatureConfig(acid.getDefaultState())));
然后将其放入所需的生物群系中以生成:
// 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)));
本教程到此结束。