Vamos a aprender cómo crear un fluido dentro de Minecraft.
¿Cómo crear un fluido?
Crear un fluido en Minecraft es algo complejo, pero si seguimos unos pasos básicos será algo sencillo.
Crear fluido
Para crear el fluido necesitaremos crear una clase el cual contendrá todas las propiedades de nuestro fluido. Esta clase la llamaremos ModFluid y deberá extender FlowableFluid.
package dev.polv.cursofabric.fluid;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.fluid.FlowableFluid;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView;
public abstract class ModFluid extends FlowableFluid {
/**
* @return whether the given fluid an instance of this fluid
*/ @Override
public boolean matchesType(Fluid fluid) {
return fluid == getStill() || fluid == getFlowing();
}
/**
* @return whether the fluid is infinite (which means can be infinitely created like water). In vanilla, it depends on the game rule.
*/ @Override
protected boolean isInfinite(World world) {
return false;
}
/**
* Perform actions when the 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.hasBlockEntity() ? world.getBlockEntity(pos) : null;
Block.dropStacks(state, world, pos, blockEntity);
}
/**
* Lava returns true if it's FluidState is above a certain height and the * Fluid is Water. * * @return whether 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;
}
}
Ejemplo de https://fabricmc.net/wiki/tutorial:fluids
Cuando tengamos este ModFluidBase, crearemos nuestro fluido. Este lo haremos creando la clase UraniumFluid que extenderá la clase que acabamos de crear.
package dev.polv.cursofabric.fluid;
import net.minecraft.block.BlockState;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.FluidState;
import net.minecraft.item.Item;
import net.minecraft.state.StateManager;
import net.minecraft.state.property.Properties;
public abstract class UraniumFluid extends ModFluid {
@Override
public Fluid getStill() {
return ModFluids.URANIUM_FLUID.staticFluid();
}
@Override
public Fluid getFlowing() {
return ModFluids.URANIUM_FLUID.flowingFluid();
}
@Override
public Item getBucketItem() {
return ModFluids.URANIUM_FLUID.fluidBucket();
}
@Override
protected BlockState toBlockState(FluidState fluidState) {
return ModFluids.URANIUM_FLUID_BLOCK.getDefaultState().with(Properties.LEVEL_15, getBlockStateLevel(fluidState));
}
public static class Flowing extends UraniumFluid {
@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 UraniumFluid {
@Override
public int getLevel(FluidState fluidState) {
return 8;
}
@Override
public boolean isStill(FluidState fluidState) {
return true;
}
}
}
Ejemplo de https://fabricmc.net/wiki/tutorial:fluids
Ade
En esta clase lo que hemos hecho es crear dos variantes de nuestro fluido, uno que será quieto, el cual estará estático, y otro que será capaz de extenderse.
Podemos observar métodos dentro de estas clases que hemos extendido para poder implementar funcionalidad personalizada, como hacer daño al jugador cuando esté dentro o hacerlo caminar más lento.
Ahora crearemos la clase ModFluids en plural para registrar nuestros fluidos.
private static RegisteredFluid registeredFluid(String fluidId, Fluid staticFluid, Fluid flowingFluid) {
Fluid registeredStaticFluid = Registry.register(Registries.FLUID, new Identifier(CursoFabric.MODID, "static_" + fluidId), staticFluid);
Fluid registeredFlowingFluid = Registry.register(Registries.FLUID, new Identifier(CursoFabric.MODID, "flowing_" + fluidId), flowingFluid);
BucketItem bucketItem = Registry.register(Registries.ITEM, new Identifier(CursoFabric.MODID, fluidId + "_bucket"), new BucketItem(registeredFlowingFluid, new Item.Settings().maxCount(1)));
return new RegisteredFluid(registeredStaticFluid, registeredFlowingFluid, bucketItem);
}
public static void registerFluids() {
CursoFabric.LOGGER.info("Registrando fluidos...");
}
public static final RegisteredFluid URANIUM_FLUID = registeredFluid(
"uranium",
new UraniumFluid.Still(),
new UraniumFluid.Flowing()
);
Además deberemos añadir la textura del cubo del líquido.
Si quisiéramos que nuestro fluido se comportara como el agua o como la lava, podríamos añadirle un tag desde nuestro FluidTagProvider.
Creando bloques de fluido
Muy bien, por ahora tenemos el fluido creado, pero ahora necesitamos crear el bloque el cual representará el fluido dentro del mundo.
Para ello, dentro de nuestra clase ModBlocks, crearemos un nuevo bloque el cual se encargará de esto.
public static final FluidBlock URANIUM_FLUID_BLOCK = registeredFluidBlock(
"uranium",
URANIUM_FLUID.staticFluid()
);
private static FluidBlock registeredFluidBlock(String fluidId, Fluid staticFluid) {
FluidBlock fluidBlock = Registry.register(Registries.BLOCK, new Identifier(CursoFabric.MODID, fluidId + "_liquid"), new FluidBlock((FlowableFluid) staticFluid, FabricBlockSettings.copy(Blocks.WATER)));
return fluidBlock;
}
Y por último queda añadir los ítems y bloques que hemos creado dentro de nuestro fluido.
Renderizando el fluido
Ahora tocará registrar en el cliente el renderizado del fluido. Para ello podemos usar unas nuevas texturas o coger la textura del agua y cambiarle el color. Para hacer este tutorial más sencillo usaremos la textura del agua.
@Override
public void onInitializeClient() {
FluidRenderHandlerRegistry.INSTANCE.register(ModFluids.URANIUM_FLUID.staticFluid(), ModFluids.URANIUM_FLUID.flowingFluid(), new SimpleFluidRenderHandler(
new Identifier("minecraft:block/water_still"),
new Identifier("minecraft:block/water_flow"),
0x00ff00
));
BlockRenderLayerMap.INSTANCE.putFluids(RenderLayer.getTranslucent(), ModFluids.URANIUM_FLUID.staticFluid(), ModFluids.URANIUM_FLUID.flowingFluid());
}
Y listo, así tendremos nuestro fluido creado.