Создание жидкостей
Введение
Здесь мы рассмотрим создание жидкости. Если вы планируете создать несколько жидкостей, рекомендуется создать абстрактный базовый класс жидкостей, в котором вы зададите необходимые значения по умолчанию, которые будут общими для его подклассов. Мы также сделаем так, чтобы жидкость генерировалась в мире, как озера.
Создание абстрактной жидкости
Ванильные жидкости используют net.minecraft.fluid.FlowableFluid
, сделаем так же.
public abstract class TutorialFluid extends FlowableFluid {
/**
* @вернём, является ли данная жидкость экземпляром этой жидкости
*/
@Override
public boolean matchesType(Fluid fluid) {
return fluid == getStill() || fluid == getFlowing();
}
/**
* @вернём, является ли жидкость бесконечной, как вода
*/
@Override
protected boolean isInfinite() {
return false;
}
/**
* Выполняйте действия, когда жидкость поступает в следующий блок. Вода ссылается
* на таблицу добычи блока. Лава воспроизводит звук "block.lava.extinguish".
*/
@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);
}
/**
* Лава возвращает значение true, если ее FluidState превышает определенную высоту и
* Жидкость - это Вода.
*
* @вернём, может ли данная жидкость перетекать в этот FluidState
*/
@Override
protected boolean canBeReplacedWith
(FluidState fluidState,
BlockView blockView, BlockPos blockPos, Fluid fluid, Direction direction
) { return false;
}
/**
* На каком расстоянии проверять попадания в близлежащие отверстия?
* Вода возвращает 4. Лава возвращает 2 в Верхнем мире и 4 в Нижнем мире.
*/
@Override
protected int getFlowSpeed(WorldView worldView) {
return 4;
}
/**
* Вода возвращает 1. Лава возвращает 2 в Верхнем мире и 1 в Нижнем мире.
*/
@Override
protected int getLevelDecreasePerBlock(WorldView worldView) {
return 1;
}
/**
* Вода возвращает 5. Лава возвращает 30 в Верхнем мире и 10 в Нижнем мире.
*/
@Override
public int getTickRate(WorldView worldView) {
return 5;
}
/**
* Вода и лава возвращают 100.0F.
*/
@Override
protected float getBlastResistance() {
return 100.0F;
}
}
Реализация
Теперь давайте создадим настоящую жидкость, которая будет иметь неподвижные и текучие варианты. В этом уроке мы будем называть его Acid(Кислота). Недостающие ссылки будут заполнены в ближайшее время.
public abstract class AcidFluid extends TutorialFluid {
@Override
public Fluid getStill() {
return VASH_STILL_FLUID_ZDES;
}
@Override
public Fluid getFlowing() {
return VASH_FLOWING_FLUID_ZDES;
}
@Override
public Item getBucketItem() {
return VASH_BUCKET_ITEM_ZDES;
}
@Override
protected BlockState toBlockState(FluidState fluidState) {
return VASH_FLUID_BLOCK_ZDES.
getDefaultState().
with(Properties.
LEVEL_15, getBlockStateLevel
(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() {
STILL_ACID
= Registry.
register(Registry.
field_11154,
new Identifier
(MOD_ID,
"acid"),
new AcidFluid.
Still()); FLOWING_ACID
= Registry.
register(Registry.
field_11154,
new Identifier
(MOD_ID,
"flowing_acid"),
new AcidFluid.
Flowing()); ACID_BUCKET
= Registry.
register(Registry.
field_11142,
new Identifier
(MOD_ID,
"acid_bucket"),
new BucketItem(STILL_ACID, new Item.Settings().recipeRemainder(Items.BUCKET).maxCount(1)));
// ...
}
// ...
Чтобы ваша жидкость вела себя больше как вода или лава, вы должны добавить ее в соответствующий тег жидкости: для воды создайте файл data /minecraft/tags/fluids/water.json
и запишите туда идентификаторы ваших жидкостей:
{
"replace": false,
"values":
[
"your_mod_id:acid",
"your_mod_id:flowing_acid"
]
}
Создание блока жидкости
Далее нам нужно создать блок, который будет представлять кислоту в мире. net.minecraft.block.FluidBlock
- это класс, который нам нужно использовать, но поскольку его конструктор защищен, мы не можем создать его напрямую. Некоторые способы его использования заключаются в создании подкласса или анонимного подкласса. Здесь мы покажем последнее. В вашем ModInitializer
:
public static Block ACID;
@Override
public void onInitialize() {
ACID
= Registry.
register(Registry.
field_11146,
new Identifier
(MOD_ID,
"acid"),
new FluidBlock
(STILL_ACID, FabricBlockSettings.
copy(Blocks.
WATER)){});
// ...
}
Теперь, когда у нас есть эти статические объекты, мы можем вернуться к AcidFluid
и заполнить переопределенные методы:
public abstract class AcidFluid extends TutorialFluid {
@Override
public Fluid getStill() {
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) {
// getBlockStateLevel 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, getBlockStateLevel
(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;
}
}
}
Настройка рендеринга
Чтобы ваши жидкости имели текстуру или были окрашены в определенный цвет, вам нужно будет зарегистрировать для них FluidRenderHandler
. Здесь мы будем повторно использовать текстуры воды и просто изменим цвет оттенка, примененный к ним. Чтобы убедиться, что текстуры отображаются как полупрозрачные, вы можете использовать BlockRenderLayerMap
Fabric'а.
public class TutorialModClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
FluidRenderHandlerRegistry.INSTANCE.register(TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID, new SimpleFluidRenderHandler(
new Identifier("minecraft:block/water_still"),
new Identifier("minecraft:block/water_flow"),
0x4CC248
));
BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), TutorialMod.STILL_ACID, TutorialMod.FLOWING_ACID);
//если вы хотите использовать свои текстуры, они должны быть зарегистрированы.
//В этом примере в этом нет необходимости, поскольку текстуры ванильной воды уже зарегистрированы.
//Чтобы зарегистрировать свои пользовательские текстуры, используйте этот метод:
//ClientSpriteRegistryCallback.event(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE).register((atlasTexture, registry) -> {
// registry.register(new Identifier("modid:block/custom_fluid_still"));
// registry.register(new Identifier("modid:block/custom_fluid_flowing"));
//});
// ...
}
}
Если вы хотите использовать свои собственные текучие текстуры, вы можете обратиться к ванильным ресурсам 1) as a template.
Генерация в мире
Чтобы заставить озера кислоты генерироваться в мире, вы можете создать net.minecraft.world.gen.feature.LakeFeature
в вашем ModInitializer
а затем добавить его в биомы, в которых вы хотите, чтобы он генерировался:
public static LakeFeature ACID_LAKE;
@Override
public void onInitialize() {
ACID_LAKE
= Registry.
register(Registry.
FEATURE,
new Identifier
(MOD_ID,
"acid_lake"),
new LakeFeature
(SingleStateFeatureConfig
::deserialize
));
// генерация в болотах, похожих на водные озера, но с вероятностью 40 (чем выше число, тем ниже вероятность генерации)
Biomes.SWAMP.addFeature(
GenerationStep.Feature.LOCAL_MODIFICATIONS,
ACID_LAKE.configure(new SingleStateFeatureConfig(ACID.getDefaultState()))
.createDecoratedFeature(Decorator.WATER_LAKE.configure(new ChanceDecoratorConfig(40)))
);
}