Minecraft Fabric模组开发教程#11 添加流体

首发于Enaium的个人博客


前言

本教程将会教你如何添加流体,什么是流体呢?就是像水、熔岩这样的东西,我们将会添加一种新的流体。

创建流体

在原版中流体都继承了net.minecraft.fluid.FlowableFluid,所以我们也继承它。

首先创建一个抽象类AwesomeFluid,然后继承FlowableFluid,然后实现一些方法。

  • matchesType:判断流体是否是我们的流体
  • isInfinite:是否是无限流体,就是像水一样,无限多
  • beforeBreakingBlock:当流体破坏方块时,会调用这个方法,我们在这里把方块掉落,比如火把被水破坏时,会掉落火把
  • canBeReplacedWith:是否可以被替换
  • getFlowSpeed:流体流动速度
  • getLevelDecreasePerBlock:水返回 1,熔岩在主世界时返回 2 并且在下界时返回 1
  • getTickRate:水返回 5,熔岩在主世界时返回 30 并且在下界时返回 10
  • getBlastResistance:爆炸抗性,水和熔岩都是 100
java 复制代码
public abstract class AwesomeFluid extends FlowableFluid {
    @Override
    public boolean matchesType(Fluid fluid) {
        return fluid == getStill() || fluid == getFlowing();
    }

    @Override
    protected boolean isInfinite(World world) {
        return true;
    }

    @Override
    protected void beforeBreakingBlock(WorldAccess world, BlockPos pos, BlockState state) {
        final BlockEntity blockEntity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
        Block.dropStacks(state, world, pos, blockEntity);
    }

    @Override
    protected boolean canBeReplacedWith(FluidState state, BlockView world, BlockPos pos, Fluid fluid, Direction direction) {
        return false;
    }

    @Override
    protected int getFlowSpeed(WorldView world) {
        return 4;
    }

    @Override
    protected int getLevelDecreasePerBlock(WorldView world) {
        return 1;
    }

    @Override
    public int getTickRate(WorldView world) {
        return 5;
    }

    @Override
    protected float getBlastResistance() {
        return 100;
    }
}

之后我们创建一个EndWaterFluid枚举类,继承AwesomeFluid,然后实现一些方法,这里先返回null,我们之后会修改。

java 复制代码
public abstract class EndWaterFluid extends AwesomeFluid {
    @Override
    public Fluid getStill() {
        return null;
    }

    @Override
    public Fluid getFlowing() {
        return null;
    }

    @Override
    public Item getBucketItem() {
        return null;
    }

    @Override
    protected BlockState toBlockState(FluidState state) {
        return null;
    }
}

接着我们在EndWaterFluid类中创建一个FlowingStill类,继承EndWaterFluid,然后实现一些方法。

  • getStill:是否是静止流体
  • getLevel:流体的等级
  • appendProperties:添加属性
java 复制代码
public static class Flowing extends EndWaterFluid {
    @Override
    public boolean isStill(FluidState state) {
        return false;
    }

    @Override
    public int getLevel(FluidState state) {
        return state.get(LEVEL);
    }

    @Override
    protected void appendProperties(StateManager.Builder<Fluid, FluidState> builder) {
        super.appendProperties(builder);
        builder.add(LEVEL);
    }
}
  • getStill:是否是静止流体
  • getLevel:流体的等级
java 复制代码
public static class Still extends EndWaterFluid {
    @Override
    public boolean isStill(FluidState state) {
        return true;
    }

    @Override
    public int getLevel(FluidState state) {
        return 8;
    }
}

注册流体

分别注册静止流体和流动流体,然后注册流体桶,最后注册流体方块,这里我们使用FabricBlockSettings.copy复制水的属性。

java 复制代码
public static final FlowableFluid STILL_END_WATER = Registry.register(Registries.FLUID, new Identifier("awesome", "end_water"), new EndWaterFluid.Still());
public static final FlowableFluid FLOWING_END_WATER = Registry.register(Registries.FLUID, new Identifier("awesome", "flowing_end_water"), new EndWaterFluid.Flowing());
public static final Item END_WATER_BUCKET = Registry.register(Registries.ITEM, new Identifier("awesome", "end_water_bucket"), new BucketItem(STILL_END_WATER, new FabricItemSettings().recipeRemainder(Items.BUCKET).maxCount(1)));
public static final Block END_WATER = Registry.register(Registries.BLOCK, new Identifier("awesome", "end_water"), new FluidBlock(STILL_END_WATER, FabricBlockSettings.copy(Blocks.WATER)));

最后补全EndWaterFluid类。

java 复制代码
public abstract class EndWaterFluid extends AwesomeFluid {
    @Override
    public Fluid getStill() {
        return ExampleMod.STILL_END_WATER;
    }

    @Override
    public Fluid getFlowing() {
        return ExampleMod.FLOWING_END_WATER;
    }

    @Override
    public Item getBucketItem() {
        return ExampleMod.END_WATER_BUCKET;
    }

    @Override
    protected BlockState toBlockState(FluidState state) {
        return ExampleMod.END_WATER.getDefaultState().with(FluidBlock.LEVEL, WaterFluid.getBlockStateLevel(state));
    }
}

渲染设置

onInitialize设置流体渲染。

静止流体和流动流体的纹理都是minecraft:block/water_stillminecraft:block/water_flow,颜色是0x730D95

java 复制代码
FluidRenderHandlerRegistry.INSTANCE.register(STILL_END_WATER, FLOWING_END_WATER, new SimpleFluidRenderHandler(
            new Identifier("minecraft:block/water_still"),
            new Identifier("minecraft:block/water_flow"),
            0x730D95
));

BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), STILL_END_WATER, FLOWING_END_WATER);

流体桶纹理

流体生成

和矿物生成差不多,都需要在configured_featureplaced_feature中创建配置。

我们找到原版游戏中的data/minecraft/worldgen/configured_feature/spring_water.jsondata/minecraft/worldgen/placed_feature/spring_water.json,然后将其修改为我们的配置。

首先在configured_feature中创建,end_water.json

json 复制代码
{
  "type": "minecraft:spring_feature",
  "config": {
    "hole_count": 1,
    "requires_block_below": true,
    "rock_count": 4,
    "state": {
      "Name": "awesome:end_water",
      "Properties": {
        "falling": "true"
      }
    },
    "valid_blocks": [
      "minecraft:stone",
      "minecraft:granite",
      "minecraft:diorite",
      "minecraft:andesite",
      "minecraft:deepslate",
      "minecraft:tuff",
      "minecraft:calcite",
      "minecraft:dirt",
      "minecraft:snow_block",
      "minecraft:powder_snow",
      "minecraft:packed_ice"
    ]
  }
}

之后在placed_feature中创建,end_water.json

json 复制代码
{
  "feature": "awesome:end_water",
  "placement": [
    {
      "type": "minecraft:count",
      "count": 25
    },
    {
      "type": "minecraft:in_square"
    },
    {
      "type": "minecraft:height_range",
      "height": {
        "type": "minecraft:uniform",
        "max_inclusive": {
          "absolute": 192
        },
        "min_inclusive": {
          "above_bottom": 0
        }
      }
    },
    {
      "type": "minecraft:biome"
    }
  ]
}

最后注册PlacedFeature

java 复制代码
public static final RegistryKey<PlacedFeature> END_WATER_PLACED_FEATURE = RegistryKey.of(RegistryKeys.PLACED_FEATURE, new Identifier("awesome", "end_water"));

并且在BiomeModifications中注册END_WATER_PLACED_FEATURE

java 复制代码
BiomeModifications.addFeature(BiomeSelectors.foundInOverworld(), GenerationStep.Feature.FLUID_SPRINGS, END_WATER_PLACED_FEATURE);
相关推荐
10km14 分钟前
java:Apache Commons Configuration2占位符解析异常的正确解法:${prefix:name:-default}
java·apache·configuration2·变量插值·interpolation
customer0815 分钟前
【开源免费】基于SpringBoot+Vue.JS个人博客系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源
灰色人生qwer22 分钟前
SpringBoot 项目配置日志输出
java·spring boot·后端
2301_7930698232 分钟前
Spring Boot +SQL项目优化策略,GraphQL和SQL 区别,Spring JDBC 等原理辨析(万字长文+代码)
java·数据库·spring boot·sql·jdbc·orm
阿华的代码王国39 分钟前
【从0做项目】Java搜索引擎(6)& 正则表达式鲨疯了&优化正文解析
java·后端·搜索引擎·正则表达式·java项目·从0到1做项目
服务端相声演员39 分钟前
Oracle JDK、Open JDK zulu下载地址
java·开发语言
是姜姜啊!40 分钟前
java连接redis
java·redis
hhw19911241 分钟前
spring boot知识点5
java·数据库·spring boot
EQUINOX143 分钟前
lab4 CSAPP:Cachelab
java·后端·spring
customer081 小时前
【开源免费】基于SpringBoot+Vue.JS打卡健康评测系统(JAVA毕业设计)
java·vue.js·spring boot·后端·开源