454 lines
15 KiB
Java
454 lines
15 KiB
Java
/*
|
|
* Minecraft Forge
|
|
* Copyright (c) 2016-2020.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation version 2.1
|
|
* of the License.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
package net.minecraftforge.fluids;
|
|
|
|
import javax.annotation.Nullable;
|
|
|
|
import net.minecraft.block.BlockState;
|
|
import net.minecraft.fluid.Fluid;
|
|
import net.minecraft.fluid.FluidState;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.particles.ParticleTypes;
|
|
import net.minecraft.util.*;
|
|
import net.minecraft.util.text.ITextComponent;
|
|
import net.minecraft.util.text.TranslationTextComponent;
|
|
import net.minecraft.world.IBlockDisplayReader;
|
|
|
|
import java.util.function.BiFunction;
|
|
import java.util.stream.Stream;
|
|
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.world.World;
|
|
import net.minecraft.item.Rarity;
|
|
import net.minecraft.world.biome.BiomeColors;
|
|
|
|
/**
|
|
* Minecraft Forge Fluid Implementation
|
|
*
|
|
* This class is a fluid (liquid or gas) equivalent to "Item." It describes the nature of a fluid
|
|
* and contains its general properties.
|
|
*
|
|
* These properties do not have inherent gameplay mechanics - they are provided so that mods may
|
|
* choose to take advantage of them.
|
|
*
|
|
* Fluid implementations are not required to actively use these properties, nor are objects
|
|
* interfacing with fluids required to make use of them, but it is encouraged.
|
|
*
|
|
* The default values can be used as a reference point for mods adding fluids such as oil or heavy
|
|
* water.
|
|
*
|
|
*/
|
|
public class FluidAttributes
|
|
{
|
|
public static final int BUCKET_VOLUME = 1000;
|
|
|
|
private String translationKey;
|
|
|
|
private final ResourceLocation stillTexture;
|
|
private final ResourceLocation flowingTexture;
|
|
|
|
@Nullable
|
|
private final ResourceLocation overlayTexture;
|
|
|
|
private final SoundEvent fillSound;
|
|
private final SoundEvent emptySound;
|
|
|
|
/**
|
|
* The light level emitted by this fluid.
|
|
*
|
|
* Default value is 0, as most fluids do not actively emit light.
|
|
*/
|
|
private final int luminosity;
|
|
|
|
/**
|
|
* Density of the fluid - completely arbitrary; negative density indicates that the fluid is
|
|
* lighter than air.
|
|
*
|
|
* Default value is approximately the real-life density of water in kg/m^3.
|
|
*/
|
|
private final int density;
|
|
|
|
/**
|
|
* Temperature of the fluid - completely arbitrary; higher temperature indicates that the fluid is
|
|
* hotter than air.
|
|
*
|
|
* Default value is approximately the real-life room temperature of water in degrees Kelvin.
|
|
*/
|
|
private final int temperature;
|
|
|
|
/**
|
|
* Viscosity ("thickness") of the fluid - completely arbitrary; negative values are not
|
|
* permissible.
|
|
*
|
|
* Default value is approximately the real-life density of water in m/s^2 (x10^-3).
|
|
*
|
|
* Higher viscosity means that a fluid flows more slowly, like molasses.
|
|
* Lower viscosity means that a fluid flows more quickly, like helium.
|
|
*
|
|
*/
|
|
private final int viscosity;
|
|
|
|
/**
|
|
* This indicates if the fluid is gaseous.
|
|
*
|
|
* Generally this is associated with negative density fluids.
|
|
*/
|
|
private final boolean isGaseous;
|
|
|
|
/**
|
|
* The rarity of the fluid.
|
|
*
|
|
* Used primarily in tool tips.
|
|
*/
|
|
private final Rarity rarity;
|
|
|
|
/**
|
|
* Color used by universal bucket and the ModelFluid baked model.
|
|
* Note that this int includes the alpha so converting this to RGB with alpha would be
|
|
* float r = ((color >> 16) & 0xFF) / 255f; // red
|
|
* float g = ((color >> 8) & 0xFF) / 255f; // green
|
|
* float b = ((color >> 0) & 0xFF) / 255f; // blue
|
|
* float a = ((color >> 24) & 0xFF) / 255f; // alpha
|
|
*/
|
|
private final int color;
|
|
|
|
protected FluidAttributes(Builder builder, Fluid fluid)
|
|
{
|
|
this.translationKey = builder.translationKey != null ? builder.translationKey : Util.makeTranslationKey("fluid", fluid.getRegistryName());
|
|
this.stillTexture = builder.stillTexture;
|
|
this.flowingTexture = builder.flowingTexture;
|
|
this.overlayTexture = builder.overlayTexture;
|
|
this.color = builder.color;
|
|
this.fillSound = builder.fillSound;
|
|
this.emptySound = builder.emptySound;
|
|
this.luminosity = builder.luminosity;
|
|
this.temperature = builder.temperature;
|
|
this.viscosity = builder.viscosity;
|
|
this.density = builder.density;
|
|
this.isGaseous = builder.isGaseous;
|
|
this.rarity = builder.rarity;
|
|
}
|
|
|
|
public ItemStack getBucket(FluidStack stack)
|
|
{
|
|
return new ItemStack(stack.getFluid().getFilledBucket());
|
|
}
|
|
|
|
public BlockState getBlock(IBlockDisplayReader reader, BlockPos pos, FluidState state)
|
|
{
|
|
return state.getBlockState();
|
|
}
|
|
|
|
public FluidState getStateForPlacement(IBlockDisplayReader reader, BlockPos pos, FluidStack state)
|
|
{
|
|
return state.getFluid().getDefaultState();
|
|
}
|
|
|
|
public final boolean canBePlacedInWorld(IBlockDisplayReader reader, BlockPos pos, FluidState state)
|
|
{
|
|
return !getBlock(reader, pos, state).isAir(reader, pos);
|
|
}
|
|
|
|
public final boolean canBePlacedInWorld(IBlockDisplayReader reader, BlockPos pos, FluidStack state)
|
|
{
|
|
return !getBlock(reader, pos, getStateForPlacement(reader, pos, state)).isAir(reader, pos);
|
|
}
|
|
|
|
public final boolean isLighterThanAir()
|
|
{
|
|
return this.density <= 0;
|
|
}
|
|
|
|
/**
|
|
* Determines if this fluid should vaporize in dimensions where water vaporizes when placed.
|
|
* To preserve the intentions of vanilla, fluids that can turn lava into obsidian should vaporize.
|
|
* This prevents players from making the nether safe with a single bucket.
|
|
* Based on {@link net.minecraft.item.BucketItem#tryPlaceContainedLiquid(PlayerEntity, World, BlockPos)}
|
|
*
|
|
* @param fluidStack The fluidStack is trying to be placed.
|
|
* @return true if this fluid should vaporize in dimensions where water vaporizes when placed.
|
|
*/
|
|
public boolean doesVaporize(IBlockDisplayReader reader, BlockPos pos, FluidStack fluidStack)
|
|
{
|
|
BlockState blockstate = getBlock(reader, pos, getStateForPlacement(reader, pos, fluidStack));
|
|
if (blockstate == null)
|
|
return false;
|
|
return blockstate.getMaterial() == net.minecraft.block.material.Material.WATER;
|
|
}
|
|
|
|
/**
|
|
* Called instead of placing the fluid block if {@link net.minecraft.world.dimension.Dimension#doesWaterVaporize()} and {@link #doesVaporize(FluidStack)} are true.
|
|
* Override this to make your explosive liquid blow up instead of the default smoke, etc.
|
|
* Based on {@link net.minecraft.item.BucketItem#tryPlaceContainedLiquid(PlayerEntity, World, BlockPos)}
|
|
*
|
|
* @param player Player who tried to place the fluid. May be null for blocks like dispensers.
|
|
* @param worldIn World to vaporize the fluid in.
|
|
* @param pos The position in the world the fluid block was going to be placed.
|
|
* @param fluidStack The fluidStack that was going to be placed.
|
|
*/
|
|
public void vaporize(@Nullable PlayerEntity player, World worldIn, BlockPos pos, FluidStack fluidStack)
|
|
{
|
|
worldIn.playSound(player, pos, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (worldIn.rand.nextFloat() - worldIn.rand.nextFloat()) * 0.8F);
|
|
|
|
for (int l = 0; l < 8; ++l)
|
|
{
|
|
worldIn.addOptionalParticle(ParticleTypes.LARGE_SMOKE, (double) pos.getX() + Math.random(), (double) pos.getY() + Math.random(), (double) pos.getZ() + Math.random(), 0.0D, 0.0D, 0.0D);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the localized name of this fluid.
|
|
*/
|
|
public ITextComponent getDisplayName(FluidStack stack)
|
|
{
|
|
return new TranslationTextComponent(getTranslationKey());
|
|
}
|
|
|
|
/**
|
|
* A FluidStack sensitive version of getTranslationKey
|
|
*/
|
|
public String getTranslationKey(FluidStack stack)
|
|
{
|
|
return this.getTranslationKey();
|
|
}
|
|
|
|
/**
|
|
* Returns the translation key of this fluid.
|
|
*/
|
|
public String getTranslationKey()
|
|
{
|
|
return this.translationKey;
|
|
}
|
|
|
|
/* Default Accessors */
|
|
public final int getLuminosity()
|
|
{
|
|
return this.luminosity;
|
|
}
|
|
|
|
public final int getDensity()
|
|
{
|
|
return this.density;
|
|
}
|
|
|
|
public final int getTemperature()
|
|
{
|
|
return this.temperature;
|
|
}
|
|
|
|
public final int getViscosity()
|
|
{
|
|
return this.viscosity;
|
|
}
|
|
|
|
public final boolean isGaseous()
|
|
{
|
|
return this.isGaseous;
|
|
}
|
|
|
|
public Rarity getRarity()
|
|
{
|
|
return rarity;
|
|
}
|
|
|
|
public int getColor()
|
|
{
|
|
return color;
|
|
}
|
|
|
|
public ResourceLocation getStillTexture()
|
|
{
|
|
return stillTexture;
|
|
}
|
|
|
|
public ResourceLocation getFlowingTexture()
|
|
{
|
|
return flowingTexture;
|
|
}
|
|
|
|
@Nullable
|
|
public ResourceLocation getOverlayTexture()
|
|
{
|
|
return overlayTexture;
|
|
}
|
|
|
|
public SoundEvent getFillSound()
|
|
{
|
|
return fillSound;
|
|
}
|
|
|
|
public SoundEvent getEmptySound()
|
|
{
|
|
return emptySound;
|
|
}
|
|
|
|
/* Stack-based Accessors */
|
|
public int getLuminosity(FluidStack stack){ return getLuminosity(); }
|
|
public int getDensity(FluidStack stack){ return getDensity(); }
|
|
public int getTemperature(FluidStack stack){ return getTemperature(); }
|
|
public int getViscosity(FluidStack stack){ return getViscosity(); }
|
|
public boolean isGaseous(FluidStack stack){ return isGaseous(); }
|
|
public Rarity getRarity(FluidStack stack){ return getRarity(); }
|
|
public int getColor(FluidStack stack){ return getColor(); }
|
|
public ResourceLocation getStillTexture(FluidStack stack) { return getStillTexture(); }
|
|
public ResourceLocation getFlowingTexture(FluidStack stack) { return getFlowingTexture(); }
|
|
public SoundEvent getFillSound(FluidStack stack) { return getFillSound(); }
|
|
public SoundEvent getEmptySound(FluidStack stack) { return getEmptySound(); }
|
|
|
|
/* World-based Accessors */
|
|
public int getLuminosity(IBlockDisplayReader world, BlockPos pos){ return getLuminosity(); }
|
|
public int getDensity(IBlockDisplayReader world, BlockPos pos){ return getDensity(); }
|
|
public int getTemperature(IBlockDisplayReader world, BlockPos pos){ return getTemperature(); }
|
|
public int getViscosity(IBlockDisplayReader world, BlockPos pos){ return getViscosity(); }
|
|
public boolean isGaseous(IBlockDisplayReader world, BlockPos pos){ return isGaseous(); }
|
|
public Rarity getRarity(IBlockDisplayReader world, BlockPos pos){ return getRarity(); }
|
|
public int getColor(IBlockDisplayReader world, BlockPos pos){ return getColor(); }
|
|
public ResourceLocation getStillTexture(IBlockDisplayReader world, BlockPos pos) { return getStillTexture(); }
|
|
public ResourceLocation getFlowingTexture(IBlockDisplayReader world, BlockPos pos) { return getFlowingTexture(); }
|
|
public SoundEvent getFillSound(IBlockDisplayReader world, BlockPos pos) { return getFillSound(); }
|
|
public SoundEvent getEmptySound(IBlockDisplayReader world, BlockPos pos) { return getEmptySound(); }
|
|
|
|
public static Builder builder(ResourceLocation stillTexture, ResourceLocation flowingTexture) {
|
|
return new Builder(stillTexture, flowingTexture, FluidAttributes::new);
|
|
}
|
|
|
|
public Stream<ResourceLocation> getTextures()
|
|
{
|
|
if (overlayTexture != null)
|
|
return Stream.of(stillTexture, flowingTexture, overlayTexture);
|
|
return Stream.of(stillTexture, flowingTexture);
|
|
}
|
|
|
|
public static class Builder
|
|
{
|
|
private final ResourceLocation stillTexture;
|
|
private final ResourceLocation flowingTexture;
|
|
private ResourceLocation overlayTexture;
|
|
private int color = 0xFFFFFFFF;
|
|
private String translationKey;
|
|
private SoundEvent fillSound;
|
|
private SoundEvent emptySound;
|
|
private int luminosity = 0;
|
|
private int density = 1000;
|
|
private int temperature = 300;
|
|
private int viscosity = 1000;
|
|
private boolean isGaseous;
|
|
private Rarity rarity = Rarity.COMMON;
|
|
private BiFunction<Builder,Fluid,FluidAttributes> factory;
|
|
|
|
protected Builder(ResourceLocation stillTexture, ResourceLocation flowingTexture, BiFunction<Builder,Fluid,FluidAttributes> factory) {
|
|
this.factory = factory;
|
|
this.stillTexture = stillTexture;
|
|
this.flowingTexture = flowingTexture;
|
|
}
|
|
|
|
public final Builder translationKey(String translationKey)
|
|
{
|
|
this.translationKey = translationKey;
|
|
return this;
|
|
}
|
|
|
|
public final Builder color(int color)
|
|
{
|
|
this.color = color;
|
|
return this;
|
|
}
|
|
|
|
public final Builder overlay(ResourceLocation texture)
|
|
{
|
|
overlayTexture = texture;
|
|
return this;
|
|
}
|
|
|
|
public final Builder luminosity(int luminosity)
|
|
{
|
|
this.luminosity = luminosity;
|
|
return this;
|
|
}
|
|
|
|
public final Builder density(int density)
|
|
{
|
|
this.density = density;
|
|
return this;
|
|
}
|
|
|
|
public final Builder temperature(int temperature)
|
|
{
|
|
this.temperature = temperature;
|
|
return this;
|
|
}
|
|
|
|
public final Builder viscosity(int viscosity)
|
|
{
|
|
this.viscosity = viscosity;
|
|
return this;
|
|
}
|
|
|
|
public final Builder gaseous()
|
|
{
|
|
isGaseous = true;
|
|
return this;
|
|
}
|
|
|
|
public final Builder rarity(Rarity rarity)
|
|
{
|
|
this.rarity = rarity;
|
|
return this;
|
|
}
|
|
|
|
public final Builder sound(SoundEvent sound)
|
|
{
|
|
this.fillSound = this.emptySound = sound;
|
|
return this;
|
|
}
|
|
|
|
public final Builder sound(SoundEvent fillSound, SoundEvent emptySound)
|
|
{
|
|
this.fillSound = fillSound;
|
|
this.emptySound = emptySound;
|
|
return this;
|
|
}
|
|
|
|
public FluidAttributes build(Fluid fluid)
|
|
{
|
|
return factory.apply(this, fluid);
|
|
}
|
|
}
|
|
|
|
public static class Water extends FluidAttributes
|
|
{
|
|
protected Water(Builder builder, Fluid fluid)
|
|
{
|
|
super(builder, fluid);
|
|
}
|
|
|
|
@Override
|
|
public int getColor(IBlockDisplayReader world, BlockPos pos)
|
|
{
|
|
return BiomeColors.getWaterColor(world, pos) | 0xFF000000;
|
|
}
|
|
|
|
public static Builder builder(ResourceLocation stillTexture, ResourceLocation flowingTexture) {
|
|
return new Builder(stillTexture, flowingTexture, Water::new);
|
|
}
|
|
}
|
|
}
|