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);
相关推荐
懒羊羊不懒@19 分钟前
Java基础语法—最小单位、及注释
java·c语言·开发语言·数据结构·学习·算法
ss27323 分钟前
手写Spring第4弹: Spring框架进化论:15年技术变迁:从XML配置到响应式编程的演进之路
xml·java·开发语言·后端·spring
DokiDoki之父35 分钟前
MyBatis—增删查改操作
java·spring boot·mybatis
兩尛1 小时前
Spring面试
java·spring·面试
Java中文社群1 小时前
服务器被攻击!原因竟然是他?真没想到...
java·后端
Full Stack Developme1 小时前
java.nio 包详解
java·python·nio
零千叶1 小时前
【面试】Java JVM 调优面试手册
java·开发语言·jvm
代码充电宝2 小时前
LeetCode 算法题【简单】290. 单词规律
java·算法·leetcode·职场和发展·哈希表
li3714908902 小时前
nginx报400bad request 请求头过大异常处理
java·运维·nginx
摇滚侠2 小时前
Spring Boot 项目, idea 控制台日志设置彩色
java·spring boot·intellij-idea