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);
相关推荐
进阶的架构师1 分钟前
互联网Java工程师面试题及答案整理(2024年最新版)
java·开发语言
黄俊懿1 分钟前
【深入理解SpringCloud微服务】手写实现各种限流算法——固定时间窗、滑动时间窗、令牌桶算法、漏桶算法
java·后端·算法·spring cloud·微服务·架构
木子020410 分钟前
java高并发场景RabbitMQ的使用
java·开发语言
夜雨翦春韭21 分钟前
【代码随想录Day29】贪心算法Part03
java·数据结构·算法·leetcode·贪心算法
大霞上仙44 分钟前
jmeter学习(1)线程组与发送请求
java·学习·jmeter
笃励1 小时前
Java面试题二
java·开发语言·python
易雪寒1 小时前
IDEA在git提交时添加忽略文件
java·git·intellij-idea
打码人的日常分享2 小时前
企业人力资源管理,人事档案管理,绩效考核,五险一金,招聘培训,薪酬管理一体化管理系统(源码)
java·数据库·python·需求分析·规格说明书
27669582922 小时前
京东e卡滑块 分析
java·javascript·python·node.js·go·滑块·京东
爱写代码的刚子2 小时前
C++知识总结
java·开发语言·c++