From b7e1cc5f6bc4338fc2e1b36faaa5184cabd198f9 Mon Sep 17 00:00:00 2001 From: David Quintana Date: Sun, 28 Jul 2019 21:35:30 +0200 Subject: [PATCH] Fluid API rework (#5983) - Moved forge fluids into FluidAttributes companion object to the vanilla Fluid. By gigaherz - Redesigned the Fluid API to be closer to the Items API. By King Lemming Co-authored-by: King Lemming --- .../renderer/FluidBlockRenderer.java.patch | 15 + .../net/minecraft/fluid/Fluid.java.patch | 33 +- .../net/minecraft/item/BucketItem.java.patch | 23 +- .../client/FluidContainerColorer.java | 2 +- .../client/ForgeClientHandler.java | 50 --- .../client/ForgeHooksClient.java | 9 + .../client/model/ModelDynBucket.java | 14 +- .../client/model/ModelFluid.java | 22 +- .../client/model/ModelLoader.java | 1 - .../net/minecraftforge/common/ForgeMod.java | 5 - .../common/extensions/IForgeFluid.java | 7 + .../FluidIdRegistryMessageHandler.java | 2 - .../energy/CapabilityEnergy.java | 2 - .../fluids/DispenseFluidContainer.java | 3 +- .../{Fluid.java => FluidAttributes.java} | 376 +++++++++--------- .../net/minecraftforge/fluids/FluidEvent.java | 145 ------- .../minecraftforge/fluids/FluidRegistry.java | 51 --- .../net/minecraftforge/fluids/FluidStack.java | 15 +- .../net/minecraftforge/fluids/FluidTank.java | 357 ----------------- .../minecraftforge/fluids/FluidTankInfo.java | 44 -- .../net/minecraftforge/fluids/FluidUtil.java | 51 +-- .../minecraftforge/fluids/IFluidBlock.java | 12 +- .../net/minecraftforge/fluids/IFluidTank.java | 53 +-- .../fluids/UniversalBucket.java | 302 -------------- .../capability/CapabilityFluidHandler.java | 19 +- .../capability/FluidTankProperties.java | 98 ----- .../FluidTankPropertiesWrapper.java | 76 ---- .../fluids/capability/IFluidHandler.java | 71 +++- .../capability/IFluidTankProperties.java | 84 ---- .../fluids/capability/TileFluidHandler.java | 6 +- .../templates/EmptyFluidHandler.java | 68 ++-- .../templates/FluidHandlerConcatenate.java | 140 ------- .../templates/FluidHandlerFluidMap.java | 99 ----- .../templates/FluidHandlerItemStack.java | 43 +- .../FluidHandlerItemStackSimple.java | 39 +- .../capability/templates/FluidTank.java | 244 ++++++++++++ .../templates/VoidFluidHandler.java | 49 +-- .../wrappers/BlockLiquidWrapper.java | 159 -------- .../capability/wrappers/BlockWrapper.java | 19 +- .../wrappers/FluidBlockWrapper.java | 122 ------ .../wrappers/FluidBucketWrapper.java | 99 ++--- .../net/minecraftforge/fml/ModLoader.java | 2 +- .../MinecraftModLanguageProvider.java | 19 + .../debug/block/MaterialFogColorTest.java | 2 - .../debug/fluid/DynBucketTest.java | 8 +- .../debug/fluid/FluidPlacementTest.java | 2 +- .../debug/fluid/NewFluidTest.java | 206 ++++++++++ src/test/resources/META-INF/mods.toml | 2 + 48 files changed, 1077 insertions(+), 2193 deletions(-) create mode 100644 patches/minecraft/net/minecraft/client/renderer/FluidBlockRenderer.java.patch delete mode 100644 src/main/java/net/minecraftforge/client/ForgeClientHandler.java rename src/main/java/net/minecraftforge/fluids/{Fluid.java => FluidAttributes.java} (51%) delete mode 100644 src/main/java/net/minecraftforge/fluids/FluidEvent.java delete mode 100644 src/main/java/net/minecraftforge/fluids/FluidRegistry.java delete mode 100644 src/main/java/net/minecraftforge/fluids/FluidTank.java delete mode 100644 src/main/java/net/minecraftforge/fluids/FluidTankInfo.java delete mode 100644 src/main/java/net/minecraftforge/fluids/UniversalBucket.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/FluidTankProperties.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/FluidTankPropertiesWrapper.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/IFluidTankProperties.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerConcatenate.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerFluidMap.java create mode 100644 src/main/java/net/minecraftforge/fluids/capability/templates/FluidTank.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockLiquidWrapper.java delete mode 100644 src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBlockWrapper.java create mode 100644 src/test/java/net/minecraftforge/debug/fluid/NewFluidTest.java diff --git a/patches/minecraft/net/minecraft/client/renderer/FluidBlockRenderer.java.patch b/patches/minecraft/net/minecraft/client/renderer/FluidBlockRenderer.java.patch new file mode 100644 index 000000000..058dc1307 --- /dev/null +++ b/patches/minecraft/net/minecraft/client/renderer/FluidBlockRenderer.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/client/renderer/FluidBlockRenderer.java ++++ b/net/minecraft/client/renderer/FluidBlockRenderer.java +@@ -58,8 +58,10 @@ + + public boolean func_217638_a(IEnviromentBlockReader p_217638_1_, BlockPos p_217638_2_, BufferBuilder p_217638_3_, IFluidState p_217638_4_) { + boolean flag = p_217638_4_.func_206884_a(FluidTags.field_206960_b); +- TextureAtlasSprite[] atextureatlassprite = flag ? this.field_178272_a : this.field_178271_b; +- int i = flag ? 16777215 : BiomeColors.func_217612_c(p_217638_1_, p_217638_2_); ++ TextureAtlasSprite[] atextureatlassprite = net.minecraftforge.client.ForgeHooksClient.getFluidSprites(p_217638_1_, p_217638_2_, p_217638_4_); ++ if (atextureatlassprite == null) atextureatlassprite = flag ? this.field_178272_a : this.field_178271_b; ++ int i = p_217638_4_.func_206886_c().getAttributes().getColor(p_217638_1_, p_217638_2_); ++ if (i < 0) i = flag ? 16777215 : BiomeColors.func_217612_c(p_217638_1_, p_217638_2_); + float f = (float)(i >> 16 & 255) / 255.0F; + float f1 = (float)(i >> 8 & 255) / 255.0F; + float f2 = (float)(i & 255) / 255.0F; diff --git a/patches/minecraft/net/minecraft/fluid/Fluid.java.patch b/patches/minecraft/net/minecraft/fluid/Fluid.java.patch index c1238e348..4eb0f6dd0 100644 --- a/patches/minecraft/net/minecraft/fluid/Fluid.java.patch +++ b/patches/minecraft/net/minecraft/fluid/Fluid.java.patch @@ -9,7 +9,7 @@ public static final ObjectIntIdentityMap field_207201_d = new ObjectIntIdentityMap<>(); protected final StateContainer field_207202_e; private IFluidState field_207200_b; -@@ -102,4 +102,10 @@ +@@ -102,4 +102,41 @@ } public abstract VoxelShape func_215664_b(IFluidState p_215664_1_, IBlockReader p_215664_2_, BlockPos p_215664_3_); @@ -18,5 +18,36 @@ + @Override + public java.util.Set getTags() { + return reverseTags.getTagNames(); ++ } ++ ++ /** ++ * Creates the fluid attributes object, which will contain all the extended values for the fluid that aren't part of the vanilla system. ++ * Do not call this from outside. To retrieve the values use {@link Fluid#getAttributes()} ++ */ ++ protected net.minecraftforge.fluids.FluidAttributes createAttributes(Fluid fluid) ++ { ++ if (fluid instanceof EmptyFluid) ++ return net.minecraftforge.fluids.FluidAttributes.builder("empty", null, null) ++ .vanillaColor().density(0).temperature(0).luminosity(0).viscosity(0).density(0).build(); ++ if (fluid instanceof WaterFluid) ++ return net.minecraftforge.fluids.FluidAttributes.builder("water", ++ new net.minecraft.util.ResourceLocation("block/water_still"), ++ new net.minecraft.util.ResourceLocation("block/water_flow")) ++ .overlay(new net.minecraft.util.ResourceLocation("block/water_overlay")) ++ .vanillaColor().block(() -> net.minecraft.block.Blocks.field_150355_j).build(); ++ if (fluid instanceof LavaFluid) ++ return net.minecraftforge.fluids.FluidAttributes.builder("lava", ++ new net.minecraft.util.ResourceLocation("block/lava_still"), ++ new net.minecraft.util.ResourceLocation("block/lava_flow")) ++ .block(() -> net.minecraft.block.Blocks.field_150353_l) ++ .vanillaColor().luminosity(15).density(3000).viscosity(6000).temperature(1300).build(); ++ throw new RuntimeException("Mod fluids must override createAttributes."); ++ } ++ ++ private net.minecraftforge.fluids.FluidAttributes forgeFluidAttributes; ++ public final net.minecraftforge.fluids.FluidAttributes getAttributes() { ++ if (forgeFluidAttributes == null) ++ forgeFluidAttributes = createAttributes(this); ++ return forgeFluidAttributes; + } } diff --git a/patches/minecraft/net/minecraft/item/BucketItem.java.patch b/patches/minecraft/net/minecraft/item/BucketItem.java.patch index a094c152e..416a39120 100644 --- a/patches/minecraft/net/minecraft/item/BucketItem.java.patch +++ b/patches/minecraft/net/minecraft/item/BucketItem.java.patch @@ -9,8 +9,25 @@ if (raytraceresult.func_216346_c() == RayTraceResult.Type.MISS) { return new ActionResult<>(ActionResultType.PASS, itemstack); } else if (raytraceresult.func_216346_c() != RayTraceResult.Type.BLOCK) { -@@ -150,4 +152,12 @@ - SoundEvent soundevent = this.field_77876_a.func_207185_a(FluidTags.field_206960_b) ? SoundEvents.field_187627_L : SoundEvents.field_187624_K; +@@ -52,7 +54,10 @@ + Fluid fluid = ((IBucketPickupHandler)blockstate1.func_177230_c()).func_204508_a(p_77659_1_, blockpos, blockstate1); + if (fluid != Fluids.field_204541_a) { + p_77659_2_.func_71029_a(Stats.field_75929_E.func_199076_b(this)); +- p_77659_2_.func_184185_a(fluid.func_207185_a(FluidTags.field_206960_b) ? SoundEvents.field_187633_N : SoundEvents.field_187630_M, 1.0F, 1.0F); ++ ++ SoundEvent soundevent = field_77876_a.getAttributes().getEmptySound(); ++ if(soundevent == null) soundevent = fluid.func_207185_a(FluidTags.field_206960_b) ? SoundEvents.field_187633_N : SoundEvents.field_187630_M; ++ p_77659_2_.func_184185_a(soundevent, 1.0F, 1.0F); + ItemStack itemstack1 = this.func_150910_a(itemstack, p_77659_2_, fluid.func_204524_b()); + if (!p_77659_1_.field_72995_K) { + CriteriaTriggers.field_204813_j.func_204817_a((ServerPlayerEntity)p_77659_2_, new ItemStack(fluid.func_204524_b())); +@@ -147,7 +152,18 @@ + } + + protected void func_203791_b(@Nullable PlayerEntity p_203791_1_, IWorld p_203791_2_, BlockPos p_203791_3_) { +- SoundEvent soundevent = this.field_77876_a.func_207185_a(FluidTags.field_206960_b) ? SoundEvents.field_187627_L : SoundEvents.field_187624_K; ++ SoundEvent soundevent = field_77876_a.getAttributes().getEmptySound(); ++ if(soundevent == null) soundevent = this.field_77876_a.func_207185_a(FluidTags.field_206960_b) ? SoundEvents.field_187627_L : SoundEvents.field_187624_K; p_203791_2_.func_184133_a(p_203791_1_, p_203791_3_, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F); } + @@ -21,4 +38,6 @@ + else + return super.initCapabilities(stack, nbt); + } ++ ++ public Fluid getFluid() { return field_77876_a; } } diff --git a/src/main/java/net/minecraftforge/client/FluidContainerColorer.java b/src/main/java/net/minecraftforge/client/FluidContainerColorer.java index 9fa5f9cab..5ca337b09 100644 --- a/src/main/java/net/minecraftforge/client/FluidContainerColorer.java +++ b/src/main/java/net/minecraftforge/client/FluidContainerColorer.java @@ -32,7 +32,7 @@ public class FluidContainerColorer implements IItemColor { if (tintIndex != 1) return 0xFFFFFFFF; return FluidUtil.getFluidContained(stack) - .map(fstack -> fstack.getFluid().getColor(fstack)) + .map(fstack -> fstack.getFluid().getAttributes().getColor(fstack)) .orElse(0xFFFFFFFF); } } diff --git a/src/main/java/net/minecraftforge/client/ForgeClientHandler.java b/src/main/java/net/minecraftforge/client/ForgeClientHandler.java deleted file mode 100644 index 769734285..000000000 --- a/src/main/java/net/minecraftforge/client/ForgeClientHandler.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.client; - -import net.minecraftforge.client.event.ColorHandlerEvent; -import net.minecraftforge.client.event.ModelRegistryEvent; -import net.minecraftforge.client.model.ModelLoader; -import net.minecraftforge.common.ForgeMod; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fluids.FluidRegistry; - -public class ForgeClientHandler -{ - @SubscribeEvent - public static void registerModels(ModelRegistryEvent event) - { - // register model for the universal bucket, if it exists - if (FluidRegistry.isUniversalBucketEnabled()) - { - // TODO no more mesh definitions, this should be implemented with overrides -// ModelLoader.setBucketModelDefinition(ForgeMod.getInstance().universalBucket); - } - } - - @SubscribeEvent - public static void registerItemHandlers(ColorHandlerEvent.Item event) - { - if (FluidRegistry.isUniversalBucketEnabled()) - { - event.getItemColors().register(new FluidContainerColorer(), ForgeMod.getInstance().universalBucket); - } - } -} diff --git a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java index 857051d4c..516493547 100644 --- a/src/main/java/net/minecraftforge/client/ForgeHooksClient.java +++ b/src/main/java/net/minecraftforge/client/ForgeHooksClient.java @@ -560,6 +560,15 @@ public class ForgeHooksClient } } + public static TextureAtlasSprite[] getFluidSprites(IEnviromentBlockReader world, BlockPos pos, IFluidState fluidStateIn) + { + AtlasTexture atlas = Minecraft.getInstance().getTextureMap(); + return new TextureAtlasSprite[] { + atlas.getSprite(fluidStateIn.getFluid().getAttributes().getStill(world, pos)), + atlas.getSprite(fluidStateIn.getFluid().getAttributes().getFlowing(world, pos)), + }; + } + private static class LightGatheringTransformer extends QuadGatheringTransformer { private static final VertexFormat FORMAT = new VertexFormat().addElement(DefaultVertexFormats.TEX_2F).addElement(DefaultVertexFormats.TEX_2S); diff --git a/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java b/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java index fbd7942b3..1c5a03471 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java +++ b/src/main/java/net/minecraftforge/client/model/ModelDynBucket.java @@ -37,6 +37,7 @@ import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.client.renderer.vertex.VertexFormat; import net.minecraft.client.resources.data.AnimationMetadataSection; import net.minecraft.entity.LivingEntity; +import net.minecraft.fluid.Fluid; import net.minecraft.item.ItemStack; import net.minecraft.resources.IResource; import net.minecraft.resources.IResourceManager; @@ -46,7 +47,6 @@ import net.minecraft.world.World; import net.minecraftforge.versions.forge.ForgeVersion; import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidUtil; import java.util.function.Function; @@ -113,7 +113,7 @@ public final class ModelDynBucket implements IUnbakedModel if (coverLocation != null) builder.add(coverLocation); if (fluid != null) - builder.add(fluid.getStill()); + builder.add(fluid.getAttributes().getStillTexture()); return builder.build(); } @@ -132,7 +132,7 @@ public final class ModelDynBucket implements IUnbakedModel ImmutableMap transformMap = PerspectiveMapWrapper.getTransforms(state); // if the fluid is lighter than air, will manipulate the initial state to be rotated 180° to turn it upside down - if (flipGas && fluid != null && fluid.isLighterThanAir()) + if (flipGas && fluid != null && fluid.getAttributes().isLighterThanAir()) { sprite = new ModelStateComposition(state, TRSRTransformation.blockCenterToCorner(new TRSRTransformation(null, new Quat4f(0, 0, 1, 0), null, null))); state = sprite.getState(); @@ -144,7 +144,7 @@ public final class ModelDynBucket implements IUnbakedModel ImmutableList.Builder builder = ImmutableList.builder(); if(fluid != null) { - fluidSprite = spriteGetter.apply(fluid.getStill()); + fluidSprite = spriteGetter.apply(fluid.getAttributes().getStillTexture()); } Random random = new Random(); @@ -160,8 +160,8 @@ public final class ModelDynBucket implements IUnbakedModel { TextureAtlasSprite liquid = spriteGetter.apply(liquidLocation); // build liquid layer (inside) - builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, NORTH_Z_FLUID, Direction.NORTH, tint ? fluid.getColor() : 0xFFFFFFFF, 1)); - builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, SOUTH_Z_FLUID, Direction.SOUTH, tint ? fluid.getColor() : 0xFFFFFFFF, 1)); + builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, NORTH_Z_FLUID, Direction.NORTH, tint ? fluid.getAttributes().getColor() : 0xFFFFFFFF, 1)); + builder.addAll(ItemTextureQuadConverter.convertTexture(format, transform, liquid, fluidSprite, SOUTH_Z_FLUID, Direction.SOUTH, tint ? fluid.getAttributes().getColor() : 0xFFFFFFFF, 1)); particleSprite = fluidSprite; } if (coverLocation != null) @@ -441,7 +441,7 @@ public final class ModelDynBucket implements IUnbakedModel BakedDynBucket model = (BakedDynBucket)originalModel; Fluid fluid = fluidStack.getFluid(); - String name = fluid.getName(); + String name = fluid.getAttributes().getName(); if (!model.cache.containsKey(name)) { diff --git a/src/main/java/net/minecraftforge/client/model/ModelFluid.java b/src/main/java/net/minecraftforge/client/model/ModelFluid.java index f479aff14..526b957ad 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelFluid.java +++ b/src/main/java/net/minecraftforge/client/model/ModelFluid.java @@ -37,6 +37,7 @@ import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType; import net.minecraft.client.renderer.texture.ISprite; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.vertex.VertexFormat; +import net.minecraft.fluid.Fluid; import net.minecraft.resources.IResourceManager; import net.minecraft.util.Direction; import net.minecraft.util.ResourceLocation; @@ -45,10 +46,9 @@ import net.minecraftforge.client.model.data.IModelData; import net.minecraftforge.client.model.pipeline.IVertexConsumer; import net.minecraftforge.client.model.pipeline.TRSRTransformer; import net.minecraftforge.client.model.pipeline.UnpackedBakedQuad; +import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.versions.forge.ForgeVersion; -import net.minecraftforge.common.model.IModelState; import net.minecraftforge.common.model.TRSRTransformation; -import net.minecraftforge.fluids.Fluid; import org.apache.commons.lang3.tuple.Pair; import org.apache.logging.log4j.LogManager; @@ -79,9 +79,10 @@ public final class ModelFluid implements IUnbakedModel @Override public Collection getTextures(Function modelGetter, Set missingTextureErrors) { - return fluid.getOverlay() != null - ? ImmutableSet.of(fluid.getStill(), fluid.getFlowing(), fluid.getOverlay()) - : ImmutableSet.of(fluid.getStill(), fluid.getFlowing()); + FluidAttributes attrs = fluid.getAttributes(); + return attrs.getOverlayTexture() != null + ? ImmutableSet.of(attrs.getStillTexture(), attrs.getFlowingTexture(), attrs.getOverlayTexture()) + : ImmutableSet.of(attrs.getStillTexture(), attrs.getFlowingTexture()); } @Override @@ -93,15 +94,16 @@ public final class ModelFluid implements IUnbakedModel @Override public IBakedModel bake(ModelBakery bakery, Function spriteGetter, ISprite sprite, VertexFormat format) { + FluidAttributes attrs = fluid.getAttributes(); return new CachingBakedFluid( sprite.getState().apply(Optional.empty()), PerspectiveMapWrapper.getTransforms(sprite.getState()), format, - fluid.getColor(), - spriteGetter.apply(fluid.getStill()), - spriteGetter.apply(fluid.getFlowing()), - Optional.ofNullable(fluid.getOverlay()).map(spriteGetter), - fluid.isLighterThanAir(), + attrs.getColor(), + spriteGetter.apply(attrs.getStillTexture()), + spriteGetter.apply(attrs.getFlowingTexture()), + Optional.ofNullable(attrs.getOverlayTexture()).map(spriteGetter), + attrs.isLighterThanAir(), null ); } diff --git a/src/main/java/net/minecraftforge/client/model/ModelLoader.java b/src/main/java/net/minecraftforge/client/model/ModelLoader.java index 020cbc02d..2843ac184 100644 --- a/src/main/java/net/minecraftforge/client/model/ModelLoader.java +++ b/src/main/java/net/minecraftforge/client/model/ModelLoader.java @@ -85,7 +85,6 @@ import net.minecraftforge.common.model.Models; import net.minecraftforge.common.model.TRSRTransformation; import net.minecraftforge.common.model.animation.IClip; import net.minecraftforge.common.property.Properties; -import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fml.client.ClientModLoader; import net.minecraftforge.logging.ModelLoaderErrorMessage; import net.minecraftforge.registries.IRegistryDelegate; diff --git a/src/main/java/net/minecraftforge/common/ForgeMod.java b/src/main/java/net/minecraftforge/common/ForgeMod.java index e89c0d8d3..b82c11ce5 100644 --- a/src/main/java/net/minecraftforge/common/ForgeMod.java +++ b/src/main/java/net/minecraftforge/common/ForgeMod.java @@ -71,7 +71,6 @@ import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.items.CapabilityItemHandler; -import net.minecraftforge.fluids.UniversalBucket; import net.minecraftforge.fml.common.Mod; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.MarkerManager; @@ -98,8 +97,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook return INSTANCE; } - public UniversalBucket universalBucket; - public ForgeMod() { LOGGER.info(FORGEMOD,"Forge mod loading, version {}, for MC {} with MCP {}", ForgeVersion.getVersion(), MCPVersion.getMCVersion(), MCPVersion.getMCPVersion()); @@ -158,7 +155,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook DimensionManager.writeRegistry(dims); if (!dims.isEmpty()) forgeData.put("dims", dims); - // TODO fluids FluidRegistry.writeDefaultFluidList(forgeData); return forgeData; } @@ -167,7 +163,6 @@ public class ForgeMod implements WorldPersistenceHooks.WorldPersistenceHook { if (tag.contains("dims", 10)) DimensionManager.readRegistry(tag.getCompound("dims")); - // TODO fluids FluidRegistry.loadFluidDefaults(tag); } public void mappingChanged(FMLModIdMappingEvent evt) diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeFluid.java b/src/main/java/net/minecraftforge/common/extensions/IForgeFluid.java index d66ca0cec..c1e964e00 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeFluid.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeFluid.java @@ -27,6 +27,7 @@ import net.minecraft.block.material.Material; import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.entity.Entity; import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.Fluids; import net.minecraft.fluid.IFluidState; import net.minecraft.tags.Tag; import net.minecraft.util.BlockRenderLayer; @@ -35,6 +36,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.Explosion; import net.minecraft.world.IWorldReader; +import net.minecraftforge.fluids.FluidAttributes; public interface IForgeFluid { @@ -117,4 +119,9 @@ public interface IForgeFluid * This should be used in favor of TagCollection.getOwningTags, as this caches the result and automatically updates when the TagCollection changes. */ Set getTags(); + + /** + * Retrieves the non-vanilla fluid attributes, including localized name. + */ + FluidAttributes getAttributes(); } diff --git a/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java b/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java index b23b6868f..bdd505607 100644 --- a/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java +++ b/src/main/java/net/minecraftforge/common/network/FluidIdRegistryMessageHandler.java @@ -19,8 +19,6 @@ package net.minecraftforge.common.network; -import net.minecraftforge.fluids.FluidRegistry; - import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; diff --git a/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java b/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java index 006100057..470d45bb6 100644 --- a/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java +++ b/src/main/java/net/minecraftforge/energy/CapabilityEnergy.java @@ -19,8 +19,6 @@ package net.minecraftforge.energy; -import java.util.concurrent.Callable; - import net.minecraft.nbt.INBT; import net.minecraft.nbt.IntNBT; import net.minecraft.util.Direction; diff --git a/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java b/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java index 61d167e00..b8fc94264 100644 --- a/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java +++ b/src/main/java/net/minecraftforge/fluids/DispenseFluidContainer.java @@ -30,6 +30,7 @@ import net.minecraft.util.Direction; import net.minecraft.util.Hand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandlerItem; /** @@ -108,7 +109,7 @@ public class DispenseFluidContainer extends DefaultDispenseItemBehavior return super.dispenseStack(source, stack); } - FluidStack fluidStack = fluidHandler.drain(Fluid.BUCKET_VOLUME, false); + FluidStack fluidStack = fluidHandler.drain(FluidAttributes.BUCKET_VOLUME, IFluidHandler.FluidAction.EXECUTE); Direction dispenserFacing = source.getBlockState().get(DispenserBlock.FACING); BlockPos blockpos = source.getBlockPos().offset(dispenserFacing); FluidActionResult result = fluidStack != null ? FluidUtil.tryPlaceFluid(null, source.getWorld(), Hand.MAIN_HAND, blockpos, stack, fluidStack) : FluidActionResult.FAILURE; diff --git a/src/main/java/net/minecraftforge/fluids/Fluid.java b/src/main/java/net/minecraftforge/fluids/FluidAttributes.java similarity index 51% rename from src/main/java/net/minecraftforge/fluids/Fluid.java rename to src/main/java/net/minecraftforge/fluids/FluidAttributes.java index 5f42b8369..28cedafa8 100644 --- a/src/main/java/net/minecraftforge/fluids/Fluid.java +++ b/src/main/java/net/minecraftforge/fluids/FluidAttributes.java @@ -21,11 +21,17 @@ package net.minecraftforge.fluids; import javax.annotation.Nullable; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.fluid.IFluidState; import net.minecraft.particles.ParticleTypes; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraft.world.IEnviromentBlockReader; import java.util.Locale; +import java.util.function.Supplier; + import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.entity.player.PlayerEntity; @@ -54,33 +60,31 @@ import net.minecraft.item.Rarity; * water. * */ -public class Fluid +public class FluidAttributes { - private static final Logger LOGGER = LogManager.getLogger(); - public static final int BUCKET_VOLUME = 1000; /** The unique identification name for this fluid. */ - protected final String fluidName; + private final String fluidName; - /** The unlocalized name of this fluid. */ - protected String unlocalizedName; + /** The translation key of this fluid. */ + private String translationKey; - protected final ResourceLocation still; - protected final ResourceLocation flowing; + private final ResourceLocation stillTexture; + private final ResourceLocation flowingTexture; @Nullable - protected final ResourceLocation overlay; + private final ResourceLocation overlayTexture; - private SoundEvent fillSound; - private SoundEvent emptySound; + 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. */ - protected int luminosity = 0; + private final int luminosity; /** * Density of the fluid - completely arbitrary; negative density indicates that the fluid is @@ -88,7 +92,7 @@ public class Fluid * * Default value is approximately the real-life density of water in kg/m^3. */ - protected int density = 1000; + private final int density; /** * Temperature of the fluid - completely arbitrary; higher temperature indicates that the fluid is @@ -96,7 +100,7 @@ public class Fluid * * Default value is approximately the real-life room temperature of water in degrees Kelvin. */ - protected int temperature = 300; + private final int temperature; /** * Viscosity ("thickness") of the fluid - completely arbitrary; negative values are not @@ -108,28 +112,23 @@ public class Fluid * Lower viscosity means that a fluid flows more quickly, like helium. * */ - protected int viscosity = 1000; + private final int viscosity; /** * This indicates if the fluid is gaseous. * * Generally this is associated with negative density fluids. */ - protected boolean isGaseous; + private final boolean isGaseous; /** * The rarity of the fluid. * * Used primarily in tool tips. */ - protected Rarity rarity = Rarity.COMMON; + private final Rarity rarity; - /** - * If there is a Block implementation of the Fluid, the Block is linked here. - * - * The default value of null should remain for any Fluid without a Block implementation. - */ - protected Block block = null; + private final Supplier blockSupplier; /** * Color used by universal bucket and the ModelFluid baked model. @@ -139,105 +138,25 @@ public class Fluid * float b = ((color >> 0) & 0xFF) / 255f; // blue * float a = ((color >> 24) & 0xFF) / 255f; // alpha */ - protected int color = 0xFFFFFFFF; + private final int color; - public Fluid(String fluidName, ResourceLocation still, ResourceLocation flowing, int color) + protected FluidAttributes(Builder builder) { - this(fluidName, still, flowing, null, color); - } - - public Fluid(String fluidName, ResourceLocation still, ResourceLocation flowing, @Nullable ResourceLocation overlay, int color) - { - this(fluidName, still, flowing, overlay); - this.setColor(color); - } - - public Fluid(String fluidName, ResourceLocation still, ResourceLocation flowing) - { - this(fluidName, still, flowing, (ResourceLocation) null); - } - - public Fluid(String fluidName, ResourceLocation still, ResourceLocation flowing, @Nullable ResourceLocation overlay) - { - this.fluidName = fluidName.toLowerCase(Locale.ENGLISH); - this.unlocalizedName = fluidName; - this.still = still; - this.flowing = flowing; - this.overlay = overlay; - } - - public Fluid setUnlocalizedName(String unlocalizedName) - { - this.unlocalizedName = unlocalizedName; - return this; - } - - public Fluid setBlock(Block block) - { - if (this.block == null || this.block == block) - { - this.block = block; - } - else - { - LOGGER.warn("A mod has attempted to assign Block {} to the Fluid '{}' but this Fluid has already been linked to the Block {}. " - + "You may have duplicate Fluid Blocks as a result. It *may* be possible to configure your mods to avoid this.", block, fluidName, this.block); - } - return this; - } - - public Fluid setLuminosity(int luminosity) - { - this.luminosity = luminosity; - return this; - } - - public Fluid setDensity(int density) - { - this.density = density; - return this; - } - - public Fluid setTemperature(int temperature) - { - this.temperature = temperature; - return this; - } - - public Fluid setViscosity(int viscosity) - { - this.viscosity = viscosity; - return this; - } - - public Fluid setGaseous(boolean isGaseous) - { - this.isGaseous = isGaseous; - return this; - } - - public Fluid setRarity(Rarity rarity) - { - this.rarity = rarity; - return this; - } - - public Fluid setFillSound(SoundEvent fillSound) - { - this.fillSound = fillSound; - return this; - } - - public Fluid setEmptySound(SoundEvent emptySound) - { - this.emptySound = emptySound; - return this; - } - - public Fluid setColor(int color) - { - this.color = color; - return this; + this.fluidName = builder.name; + this.translationKey = builder.translationKey; + this.stillTexture = builder.stillTexture; + this.flowingTexture = builder.flowingTexture; + this.overlayTexture = builder.overlayTexture; + this.blockSupplier = builder.blockSupplier; + 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 final String getName() @@ -245,14 +164,24 @@ public class Fluid return this.fluidName; } - public final Block getBlock() + public BlockState getBlock(IEnviromentBlockReader reader, BlockPos pos, IFluidState state) { - return block; + return (blockSupplier != null ? blockSupplier.get() : Blocks.AIR).getDefaultState(); } - public final boolean canBePlacedInWorld() + public IFluidState getStateForPlacement(IEnviromentBlockReader reader, BlockPos pos, FluidStack state) { - return block != null; + return state.getFluid().getDefaultState(); + } + + public final boolean canBePlacedInWorld(IEnviromentBlockReader reader, BlockPos pos, IFluidState state) + { + return getBlock(reader, pos, state) != null; + } + + public final boolean canBePlacedInWorld(IEnviromentBlockReader reader, BlockPos pos, FluidStack state) + { + return getBlock(reader, pos, getStateForPlacement(reader, pos, state)) != null; } public final boolean isLighterThanAir() @@ -269,11 +198,12 @@ public class Fluid * @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(FluidStack fluidStack) + public boolean doesVaporize(IEnviromentBlockReader reader, BlockPos pos, FluidStack fluidStack) { - if (block == null) + BlockState blockstate = getBlock(reader, pos, getStateForPlacement(reader, pos, fluidStack)); + if (blockstate == null) return false; - return block.getDefaultState().getMaterial() == Material.WATER; + return blockstate.getMaterial() == Material.WATER; } /** @@ -299,26 +229,25 @@ public class Fluid /** * Returns the localized name of this fluid. */ - public String getLocalizedName(FluidStack stack) + public ITextComponent getDisplayName(FluidStack stack) { - String s = this.getUnlocalizedName(); - return s == null ? "" : LanguageMap.getInstance().translateKey(s); // TODO Server translation + return new TranslationTextComponent(getTranslationKey()); } /** * A FluidStack sensitive version of getUnlocalizedName */ - public String getUnlocalizedName(FluidStack stack) + public String getTranslationKey(FluidStack stack) { - return this.getUnlocalizedName(); + return this.getTranslationKey(); } /** * Returns the unlocalized name of this fluid. */ - public String getUnlocalizedName() + public String getTranslationKey() { - return "fluid." + this.unlocalizedName; + return "fluid." + this.translationKey; } /* Default Accessors */ @@ -357,53 +286,29 @@ public class Fluid return color; } - public ResourceLocation getStill() + public ResourceLocation getStillTexture() { - return still; + return stillTexture; } - public ResourceLocation getFlowing() + public ResourceLocation getFlowingTexture() { - return flowing; + return flowingTexture; } @Nullable - public ResourceLocation getOverlay() + public ResourceLocation getOverlayTexture() { - return overlay; + return overlayTexture; } public SoundEvent getFillSound() { - if(fillSound == null) - { - if(getBlock() != null && getBlock().getDefaultState().getMaterial() == Material.LAVA) - { - fillSound = SoundEvents.ITEM_BUCKET_FILL_LAVA; - } - else - { - fillSound = SoundEvents.ITEM_BUCKET_FILL; - } - } - return fillSound; } public SoundEvent getEmptySound() { - if(emptySound == null) - { - if(getBlock() != null && getBlock().getDefaultState().getMaterial() == Material.LAVA) - { - emptySound = SoundEvents.ITEM_BUCKET_EMPTY_LAVA; - } - else - { - emptySound = SoundEvents.ITEM_BUCKET_EMPTY; - } - } - return emptySound; } @@ -415,22 +320,135 @@ public class Fluid public boolean isGaseous(FluidStack stack){ return isGaseous(); } public Rarity getRarity(FluidStack stack){ return getRarity(); } public int getColor(FluidStack stack){ return getColor(); } - public ResourceLocation getStill(FluidStack stack) { return getStill(); } - public ResourceLocation getFlowing(FluidStack stack) { return getFlowing(); } + public ResourceLocation getStill(FluidStack stack) { return getStillTexture(); } + public ResourceLocation getFlowing(FluidStack stack) { return getFlowingTexture(); } public SoundEvent getFillSound(FluidStack stack) { return getFillSound(); } public SoundEvent getEmptySound(FluidStack stack) { return getEmptySound(); } /* World-based Accessors */ - public int getLuminosity(World world, BlockPos pos){ return getLuminosity(); } - public int getDensity(World world, BlockPos pos){ return getDensity(); } - public int getTemperature(World world, BlockPos pos){ return getTemperature(); } - public int getViscosity(World world, BlockPos pos){ return getViscosity(); } - public boolean isGaseous(World world, BlockPos pos){ return isGaseous(); } - public Rarity getRarity(World world, BlockPos pos){ return getRarity(); } - public int getColor(World world, BlockPos pos){ return getColor(); } - public ResourceLocation getStill(World world, BlockPos pos) { return getStill(); } - public ResourceLocation getFlowing(World world, BlockPos pos) { return getFlowing(); } - public SoundEvent getFillSound(World world, BlockPos pos) { return getFillSound(); } - public SoundEvent getEmptySound(World world, BlockPos pos) { return getEmptySound(); } + public int getLuminosity(IEnviromentBlockReader world, BlockPos pos){ return getLuminosity(); } + public int getDensity(IEnviromentBlockReader world, BlockPos pos){ return getDensity(); } + public int getTemperature(IEnviromentBlockReader world, BlockPos pos){ return getTemperature(); } + public int getViscosity(IEnviromentBlockReader world, BlockPos pos){ return getViscosity(); } + public boolean isGaseous(IEnviromentBlockReader world, BlockPos pos){ return isGaseous(); } + public Rarity getRarity(IEnviromentBlockReader world, BlockPos pos){ return getRarity(); } + public int getColor(IEnviromentBlockReader world, BlockPos pos){ return getColor(); } + public ResourceLocation getStill(IEnviromentBlockReader world, BlockPos pos) { return getStillTexture(); } + public ResourceLocation getFlowing(IEnviromentBlockReader world, BlockPos pos) { return getFlowingTexture(); } + public SoundEvent getFillSound(IEnviromentBlockReader world, BlockPos pos) { return getFillSound(); } + public SoundEvent getEmptySound(IEnviromentBlockReader world, BlockPos pos) { return getEmptySound(); } + public static Builder builder(String name, ResourceLocation stillTexture, ResourceLocation flowingTexture) { + return new Builder(name, stillTexture, flowingTexture); + } + + public static class Builder + { + private final String name; + private final ResourceLocation stillTexture; + private final ResourceLocation flowingTexture; + private ResourceLocation overlayTexture; + private int color = 0xFFFFFF; + private String translationKey; + private SoundEvent fillSound; + private SoundEvent emptySound; + private Supplier blockSupplier; + private int luminosity = 0; + private int density = 1000; + private int temperature = 300; + private int viscosity = 1000; + private boolean isGaseous; + private Rarity rarity = Rarity.COMMON; + + protected Builder(String name, ResourceLocation stillTexture, ResourceLocation flowingTexture) { + this.name = name.toLowerCase(Locale.ENGLISH); + this.stillTexture = stillTexture; + this.flowingTexture = flowingTexture; + this.translationKey = "fluid." + this.name + ".name"; + } + + 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 vanillaColor() + { + this.color = -1; + return this; + } + + public final Builder overlay(ResourceLocation texture) + { + overlayTexture = texture; + return this; + } + + public final Builder block(Supplier supplier) + { + blockSupplier = supplier; + 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() + { + return new FluidAttributes(this); + } + } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidEvent.java b/src/main/java/net/minecraftforge/fluids/FluidEvent.java deleted file mode 100644 index 9855305d8..000000000 --- a/src/main/java/net/minecraftforge/fluids/FluidEvent.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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 net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.Event; - -public class FluidEvent extends net.minecraftforge.eventbus.api.Event -{ - private final FluidStack fluid; - private final World world; - private final BlockPos pos; - - public FluidEvent(FluidStack fluid, World world, BlockPos pos) - { - this.fluid = fluid; - this.world = world; - this.pos = pos; - } - - public FluidStack getFluid() - { - return fluid; - } - - public World getWorld() - { - return world; - } - - public BlockPos getPos() - { - return pos; - } - - /** - * Mods should fire this event when they move fluids around. - * - */ - public static class FluidMotionEvent extends FluidEvent - { - public FluidMotionEvent(FluidStack fluid, World world, BlockPos pos) - { - super(fluid, world, pos); - } - } - - /** - * Mods should fire this event when a fluid is {@link IFluidTank#fill(FluidStack, boolean)} - * their tank implementation. {@link FluidTank} does. - * - */ - public static class FluidFillingEvent extends FluidEvent - { - private final IFluidTank tank; - private final int amount; - - public FluidFillingEvent(FluidStack fluid, World world, BlockPos pos, IFluidTank tank, int amount) - { - super(fluid, world, pos); - this.tank = tank; - this.amount = amount; - } - - public IFluidTank getTank() - { - return tank; - } - - public int getAmount() - { - return amount; - } - } - - /** - * Mods should fire this event when a fluid is {@link IFluidTank#drain(int, boolean)} from their - * tank. - * - */ - public static class FluidDrainingEvent extends FluidEvent - { - private final IFluidTank tank; - private final int amount; - - public FluidDrainingEvent(FluidStack fluid, World world, BlockPos pos, IFluidTank tank, int amount) - { - super(fluid, world, pos); - this.amount = amount; - this.tank = tank; - } - - public IFluidTank getTank() - { - return tank; - } - - public int getAmount() - { - return amount; - } - } - - /** - * Mods should fire this event when a fluid "spills", for example, if a block containing fluid - * is broken. - * - */ - public static class FluidSpilledEvent extends FluidEvent - { - public FluidSpilledEvent(FluidStack fluid, World world, BlockPos pos) - { - super(fluid, world, pos); - } - } - - /** - * A handy shortcut for firing the various fluid events. - * - * @param event - */ - public static final void fireEvent(FluidEvent event) - { - MinecraftForge.EVENT_BUS.post(event); - } -} diff --git a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java b/src/main/java/net/minecraftforge/fluids/FluidRegistry.java deleted file mode 100644 index 42e7969a5..000000000 --- a/src/main/java/net/minecraftforge/fluids/FluidRegistry.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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 org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.Marker; -import org.apache.logging.log4j.MarkerManager; - -/** - * Handles Fluid registrations. Fluids MUST be registered in order to function. - */ -public abstract class FluidRegistry -{ - private static final Logger LOGGER = LogManager.getLogger(); - private static final Marker FLUIDS = MarkerManager.getMarker("FLUIDS"); - - static boolean universalBucketEnabled = false; - - /** - * Enables the universal bucket in forge. - * Has to be called before pre-initialization. - * Actually just call it statically in your mod class. - */ - public static void enableUniversalBucket() - { - universalBucketEnabled = true; - } - - public static boolean isUniversalBucketEnabled() - { - return universalBucketEnabled; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/FluidStack.java b/src/main/java/net/minecraftforge/fluids/FluidStack.java index d9070408d..328a5135d 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidStack.java +++ b/src/main/java/net/minecraftforge/fluids/FluidStack.java @@ -19,8 +19,10 @@ package net.minecraftforge.fluids; +import net.minecraft.fluid.Fluid; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.text.ITextComponent; import net.minecraftforge.common.util.Constants; import net.minecraftforge.registries.IRegistryDelegate; @@ -123,14 +125,14 @@ public class FluidStack return fluidDelegate.get(); } - public String getLocalizedName() + public ITextComponent getDisplayName() { - return this.getFluid().getLocalizedName(this); + return this.getFluid().getAttributes().getDisplayName(this); } - public String getUnlocalizedName() + public String getTranslationKey() { - return this.getFluid().getUnlocalizedName(this); + return this.getFluid().getAttributes().getTranslationKey(this); } /** @@ -155,7 +157,7 @@ public class FluidStack private boolean isFluidStackTagEqual(FluidStack other) { - return tag == null ? other.tag == null : other.tag == null ? false : tag.equals(other.tag); + return tag == null ? other.tag == null : other.tag != null && tag.equals(other.tag); } /** @@ -163,7 +165,7 @@ public class FluidStack */ public static boolean areFluidStackTagsEqual(@Nullable FluidStack stack1, @Nullable FluidStack stack2) { - return stack1 == null && stack2 == null ? true : stack1 == null || stack2 == null ? false : stack1.isFluidStackTagEqual(stack2); + return stack1 == null && stack2 == null || (stack1 != null && stack2 != null && stack1.isFluidStackTagEqual(stack2)); } /** @@ -230,7 +232,6 @@ public class FluidStack { return false; } - return isFluidEqual((FluidStack) o); } } diff --git a/src/main/java/net/minecraftforge/fluids/FluidTank.java b/src/main/java/net/minecraftforge/fluids/FluidTank.java deleted file mode 100644 index 0e0be2699..000000000 --- a/src/main/java/net/minecraftforge/fluids/FluidTank.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.nbt.CompoundNBT; -import net.minecraft.tileentity.TileEntity; -import net.minecraftforge.fluids.capability.FluidTankPropertiesWrapper; -import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; - -/** - * Reference implementation of {@link IFluidTank}. Use/extend this or implement your own. - */ -public class FluidTank implements IFluidTank, IFluidHandler -{ - @Nullable - protected FluidStack fluid; - protected int capacity; - protected TileEntity tile; - protected boolean canFill = true; - protected boolean canDrain = true; - protected IFluidTankProperties[] tankProperties; - - public FluidTank(int capacity) - { - this(null, capacity); - } - - public FluidTank(@Nullable FluidStack fluidStack, int capacity) - { - this.fluid = fluidStack; - this.capacity = capacity; - } - - public FluidTank(Fluid fluid, int amount, int capacity) - { - this(new FluidStack(fluid, amount), capacity); - } - - public FluidTank readFromNBT(CompoundNBT nbt) - { - if (!nbt.contains("Empty")) - { - FluidStack fluid = FluidStack.loadFluidStackFromNBT(nbt); - setFluid(fluid); - } - else - { - setFluid(null); - } - return this; - } - - public CompoundNBT writeToNBT(CompoundNBT nbt) - { - if (fluid != null) - { - fluid.writeToNBT(nbt); - } - else - { - nbt.putString("Empty", ""); - } - return nbt; - } - - /* IFluidTank */ - @Override - @Nullable - public FluidStack getFluid() - { - return fluid; - } - - public void setFluid(@Nullable FluidStack fluid) - { - this.fluid = fluid; - } - - @Override - public int getFluidAmount() - { - if (fluid == null) - { - return 0; - } - return fluid.amount; - } - - @Override - public int getCapacity() - { - return capacity; - } - - public void setCapacity(int capacity) - { - this.capacity = capacity; - } - - public void setTileEntity(TileEntity tile) - { - this.tile = tile; - } - - @Override - public FluidTankInfo getInfo() - { - return new FluidTankInfo(this); - } - - @Override - public IFluidTankProperties[] getTankProperties() - { - if (this.tankProperties == null) - { - this.tankProperties = new IFluidTankProperties[] { new FluidTankPropertiesWrapper(this) }; - } - return this.tankProperties; - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - if (!canFillFluidType(resource)) - { - return 0; - } - - return fillInternal(resource, doFill); - } - - /** - * Use this method to bypass the restrictions from {@link #canFillFluidType(FluidStack)} - * Meant for use by the owner of the tank when they have {@link #canFill() set to false}. - */ - public int fillInternal(FluidStack resource, boolean doFill) - { - if (resource == null || resource.amount <= 0) - { - return 0; - } - - if (!doFill) - { - if (fluid == null) - { - return Math.min(capacity, resource.amount); - } - - if (!fluid.isFluidEqual(resource)) - { - return 0; - } - - return Math.min(capacity - fluid.amount, resource.amount); - } - - if (fluid == null) - { - fluid = new FluidStack(resource, Math.min(capacity, resource.amount)); - - onContentsChanged(); - - if (tile != null) - { - FluidEvent.fireEvent(new FluidEvent.FluidFillingEvent(fluid, tile.getWorld(), tile.getPos(), this, fluid.amount)); - } - return fluid.amount; - } - - if (!fluid.isFluidEqual(resource)) - { - return 0; - } - int filled = capacity - fluid.amount; - - if (resource.amount < filled) - { - fluid.amount += resource.amount; - filled = resource.amount; - } - else - { - fluid.amount = capacity; - } - - onContentsChanged(); - - if (tile != null) - { - FluidEvent.fireEvent(new FluidEvent.FluidFillingEvent(fluid, tile.getWorld(), tile.getPos(), this, filled)); - } - return filled; - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (!canDrainFluidType(getFluid())) - { - return null; - } - return drainInternal(resource, doDrain); - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - if (!canDrainFluidType(fluid)) - { - return null; - } - return drainInternal(maxDrain, doDrain); - } - - /** - * Use this method to bypass the restrictions from {@link #canDrainFluidType(FluidStack)} - * Meant for use by the owner of the tank when they have {@link #canDrain()} set to false}. - */ - @Nullable - public FluidStack drainInternal(FluidStack resource, boolean doDrain) - { - if (resource == null || !resource.isFluidEqual(getFluid())) - { - return null; - } - return drainInternal(resource.amount, doDrain); - } - - /** - * Use this method to bypass the restrictions from {@link #canDrainFluidType(FluidStack)} - * Meant for use by the owner of the tank when they have {@link #canDrain()} set to false}. - */ - @Nullable - public FluidStack drainInternal(int maxDrain, boolean doDrain) - { - if (fluid == null || maxDrain <= 0) - { - return null; - } - - int drained = maxDrain; - if (fluid.amount < drained) - { - drained = fluid.amount; - } - - FluidStack stack = new FluidStack(fluid, drained); - if (doDrain) - { - fluid.amount -= drained; - if (fluid.amount <= 0) - { - fluid = null; - } - - onContentsChanged(); - - if (tile != null) - { - FluidEvent.fireEvent(new FluidEvent.FluidDrainingEvent(fluid, tile.getWorld(), tile.getPos(), this, drained)); - } - } - return stack; - } - - /** - * Whether this tank can be filled with {@link IFluidHandler} - * - * @see IFluidTankProperties#canFill() - */ - public boolean canFill() - { - return canFill; - } - - /** - * Whether this tank can be drained with {@link IFluidHandler} - * - * @see IFluidTankProperties#canDrain() - */ - public boolean canDrain() - { - return canDrain; - } - - /** - * Set whether this tank can be filled with {@link IFluidHandler} - * - * @see IFluidTankProperties#canFill() - */ - public void setCanFill(boolean canFill) - { - this.canFill = canFill; - } - - /** - * Set whether this tank can be drained with {@link IFluidHandler} - * - * @see IFluidTankProperties#canDrain() - */ - public void setCanDrain(boolean canDrain) - { - this.canDrain = canDrain; - } - - /** - * Returns true if the tank can be filled with this type of fluid. - * Used as a filter for fluid types. - * Does not consider the current contents or capacity of the tank, - * only whether it could ever fill with this type of fluid. - * - * @see IFluidTankProperties#canFillFluidType(FluidStack) - */ - public boolean canFillFluidType(FluidStack fluid) - { - return canFill(); - } - - /** - * Returns true if the tank can drain out this type of fluid. - * Used as a filter for fluid types. - * Does not consider the current contents or capacity of the tank, - * only whether it could ever drain out this type of fluid. - * - * @see IFluidTankProperties#canDrainFluidType(FluidStack) - */ - public boolean canDrainFluidType(@Nullable FluidStack fluid) - { - return fluid != null && canDrain(); - } - - protected void onContentsChanged() - { - - } -} diff --git a/src/main/java/net/minecraftforge/fluids/FluidTankInfo.java b/src/main/java/net/minecraftforge/fluids/FluidTankInfo.java deleted file mode 100644 index 481adc731..000000000 --- a/src/main/java/net/minecraftforge/fluids/FluidTankInfo.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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; - -/** - * Wrapper class used to encapsulate information about an IFluidTank. - */ -public final class FluidTankInfo -{ - @Nullable - public final FluidStack fluid; - public final int capacity; - - public FluidTankInfo(@Nullable FluidStack fluid, int capacity) - { - this.fluid = fluid; - this.capacity = capacity; - } - - public FluidTankInfo(IFluidTank tank) - { - this.fluid = tank.getFluid(); - this.capacity = tank.getCapacity(); - } -} diff --git a/src/main/java/net/minecraftforge/fluids/FluidUtil.java b/src/main/java/net/minecraftforge/fluids/FluidUtil.java index 2b80730d7..d3ff6a758 100644 --- a/src/main/java/net/minecraftforge/fluids/FluidUtil.java +++ b/src/main/java/net/minecraftforge/fluids/FluidUtil.java @@ -27,6 +27,7 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.fluid.Fluid; import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext; @@ -121,7 +122,7 @@ public class FluidUtil * * @param container The container to be filled. Will not be modified. * Separate handling must be done to reduce the stack size, stow containers, etc, on success. - * See {@link #tryFillContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}. + * See {@link #tryFillContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, PlayerEntity, boolean)}. * @param fluidSource The fluid handler to be drained. * @param maxAmount The largest amount of fluid that should be transferred. * @param player The player to make the filling noise. Pass null for no noise. @@ -142,13 +143,13 @@ public class FluidUtil tryFluidTransfer(containerFluidHandler, fluidSource, maxAmount, true); if (player != null) { - SoundEvent soundevent = simulatedTransfer.getFluid().getFillSound(simulatedTransfer); + SoundEvent soundevent = simulatedTransfer.getFluid().getAttributes().getFillSound(simulatedTransfer); player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F); } } else { - containerFluidHandler.fill(simulatedTransfer, true); + containerFluidHandler.fill(simulatedTransfer, IFluidHandler.FluidAction.SIMULATE); } ItemStack resultContainer = containerFluidHandler.getContainer(); @@ -164,7 +165,7 @@ public class FluidUtil * * @param container The filled container. Will not be modified. * Separate handling must be done to reduce the stack size, stow containers, etc, on success. - * See {@link #tryEmptyContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, EntityPlayer, boolean)}. + * See {@link #tryEmptyContainerAndStow(ItemStack, IFluidHandler, IItemHandler, int, PlayerEntity, boolean)}. * @param fluidDestination The fluid handler to be filled by the container. * @param maxAmount The largest amount of fluid that should be transferred. * @param player Player for making the bucket drained sound. Pass null for no noise. @@ -185,7 +186,7 @@ public class FluidUtil { if (player != null) { - SoundEvent soundevent = transfer.getFluid().getEmptySound(transfer); + SoundEvent soundevent = transfer.getFluid().getAttributes().getEmptySound(transfer); player.world.playSound(null, player.posX, player.posY + 0.5, player.posZ, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F); } ItemStack resultContainer = containerFluidHandler.getContainer(); @@ -197,7 +198,7 @@ public class FluidUtil FluidStack simulatedTransfer = tryFluidTransfer(fluidDestination, containerFluidHandler, maxAmount, false); if (simulatedTransfer != null) { - containerFluidHandler.drain(simulatedTransfer, true); + containerFluidHandler.drain(simulatedTransfer, IFluidHandler.FluidAction.SIMULATE); ItemStack resultContainer = containerFluidHandler.getContainer(); return new FluidActionResult(resultContainer); } @@ -358,7 +359,7 @@ public class FluidUtil @Nullable public static FluidStack tryFluidTransfer(IFluidHandler fluidDestination, IFluidHandler fluidSource, int maxAmount, boolean doTransfer) { - FluidStack drainable = fluidSource.drain(maxAmount, false); + FluidStack drainable = fluidSource.drain(maxAmount, IFluidHandler.FluidAction.SIMULATE); if (drainable != null && drainable.amount > 0) { return tryFluidTransfer_Internal(fluidDestination, fluidSource, drainable, doTransfer); @@ -380,7 +381,7 @@ public class FluidUtil @Nullable public static FluidStack tryFluidTransfer(IFluidHandler fluidDestination, IFluidHandler fluidSource, FluidStack resource, boolean doTransfer) { - FluidStack drainable = fluidSource.drain(resource, false); + FluidStack drainable = fluidSource.drain(resource, IFluidHandler.FluidAction.SIMULATE); if (drainable != null && drainable.amount > 0 && resource.isFluidEqual(drainable)) { return tryFluidTransfer_Internal(fluidDestination, fluidSource, drainable, doTransfer); @@ -398,15 +399,15 @@ public class FluidUtil @Nullable private static FluidStack tryFluidTransfer_Internal(IFluidHandler fluidDestination, IFluidHandler fluidSource, FluidStack drainable, boolean doTransfer) { - int fillableAmount = fluidDestination.fill(drainable, false); + int fillableAmount = fluidDestination.fill(drainable, IFluidHandler.FluidAction.SIMULATE); if (fillableAmount > 0) { if (doTransfer) { - FluidStack drained = fluidSource.drain(fillableAmount, true); + FluidStack drained = fluidSource.drain(fillableAmount, IFluidHandler.FluidAction.EXECUTE); if (drained != null) { - drained.amount = fluidDestination.fill(drained, true); + drained.amount = fluidDestination.fill(drained, IFluidHandler.FluidAction.EXECUTE); return drained; } } @@ -445,7 +446,7 @@ public class FluidUtil { container = ItemHandlerHelper.copyStackWithSize(container, 1); return getFluidHandler(container) - .map(handler -> handler.drain(Integer.MAX_VALUE, false)); + .map(handler -> handler.drain(Integer.MAX_VALUE, IFluidHandler.FluidAction.SIMULATE)); } return LazyOptional.empty(); } @@ -513,7 +514,7 @@ public class FluidUtil } /** - * ItemStack version of {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, IFluidHandler, FluidStack)}. + * ItemStack version of {@link #tryPlaceFluid(PlayerEntity, World, BlockPos, IFluidHandler, FluidStack)}. * Use the returned {@link FluidActionResult} to update the container ItemStack. * * @param player Player who places the fluid. May be null for blocks like dispensers. @@ -541,7 +542,7 @@ public class FluidUtil * Honors the amount of fluid contained by the used container. * Checks if water-like fluids should vaporize like in the nether. * - * Modeled after {@link ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)} + * Modeled after {@link ItemBucket#tryPlaceContainedLiquid(PlayerEntity, World, BlockPos)} * * @param player Player who places the fluid. May be null for blocks like dispensers. * @param world World to place the fluid in @@ -559,12 +560,12 @@ public class FluidUtil } Fluid fluid = resource.getFluid(); - if (fluid == null || !fluid.canBePlacedInWorld()) + if (fluid == null || !fluid.getAttributes().canBePlacedInWorld(world, pos, resource)) { return false; } - if (fluidSource.drain(resource, false) == null) + if (fluidSource.drain(resource, IFluidHandler.FluidAction.SIMULATE) == null) { return false; } @@ -581,12 +582,12 @@ public class FluidUtil return false; // Non-air, solid, unreplacable block. We can't put fluid here. } - if (world.dimension.doesWaterVaporize() && fluid.doesVaporize(resource)) + if (world.dimension.doesWaterVaporize() && fluid.getAttributes().doesVaporize(world, pos, resource)) { - FluidStack result = fluidSource.drain(resource, true); + FluidStack result = fluidSource.drain(resource, IFluidHandler.FluidAction.EXECUTE); if (result != null) { - result.getFluid().vaporize(player, world, pos, result); + result.getFluid().getAttributes().vaporize(player, world, pos, result); return true; } } @@ -597,7 +598,7 @@ public class FluidUtil FluidStack result = tryFluidTransfer(handler, fluidSource, resource, true); if (result != null) { - SoundEvent soundevent = resource.getFluid().getEmptySound(resource); + SoundEvent soundevent = resource.getFluid().getAttributes().getEmptySound(resource); world.playSound(player, pos, soundevent, SoundCategory.BLOCKS, 1.0F, 1.0F); return true; } @@ -608,12 +609,12 @@ public class FluidUtil /** * Internal method for getting a fluid block handler for placing a fluid. * - * Modders: Instead of this method, use {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, ItemStack, FluidStack)} - * or {@link #tryPlaceFluid(EntityPlayer, World, BlockPos, IFluidHandler, FluidStack)} + * Modders: Instead of this method, use {@link #tryPlaceFluid(PlayerEntity, World, BlockPos, ItemStack, FluidStack)} + * or {@link #tryPlaceFluid(PlayerEntity, World, BlockPos, IFluidHandler, FluidStack)} */ private static IFluidHandler getFluidBlockHandler(Fluid fluid, World world, BlockPos pos) { - Block block = fluid.getBlock();/* TODO fluid blocks? + BlockState state = fluid.getAttributes().getBlock(world, pos, fluid.getDefaultState());/* TODO fluid blocks? if (block instanceof IFluidBlock) { return new FluidBlockWrapper((IFluidBlock) block, world, pos); @@ -624,13 +625,13 @@ public class FluidUtil } else*/ { - return new BlockWrapper(block, world, pos); + return new BlockWrapper(state, world, pos); } } /** * Destroys a block when a fluid is placed in the same position. - * Modeled after {@link ItemBucket#tryPlaceContainedLiquid(EntityPlayer, World, BlockPos)} + * Modeled after {@link ItemBucket#tryPlaceContainedLiquid(PlayerEntity, World, BlockPos)} * * This is a helper method for implementing {@link IFluidBlock#place(World, BlockPos, FluidStack, boolean)}. * diff --git a/src/main/java/net/minecraftforge/fluids/IFluidBlock.java b/src/main/java/net/minecraftforge/fluids/IFluidBlock.java index 024dd10b1..3e406b8d3 100644 --- a/src/main/java/net/minecraftforge/fluids/IFluidBlock.java +++ b/src/main/java/net/minecraftforge/fluids/IFluidBlock.java @@ -19,8 +19,10 @@ package net.minecraftforge.fluids; +import net.minecraft.fluid.Fluid; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fluids.capability.IFluidHandler; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -47,22 +49,22 @@ public interface IFluidBlock * @param world the world to place the block in * @param pos the position to place the block at * @param fluidStack the fluid stack to get the required data from - * @param doPlace if false, the placement will only be simulated + * @param action If SIMULATE, the placement will only be simulated * @return the amount of fluid extracted from the provided stack to achieve some fluid level */ - int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, boolean doPlace); + int place(World world, BlockPos pos, @Nonnull FluidStack fluidStack, IFluidHandler.FluidAction action); /** * Attempt to drain the block. This method should be called by devices such as pumps. * * NOTE: The block is intended to handle its own state changes. * - * @param doDrain - * If false, the drain will only be simulated. + * @param action + * If SIMULATE, the drain will only be simulated. * @return */ @Nullable - FluidStack drain(World world, BlockPos pos, boolean doDrain); + FluidStack drain(World world, BlockPos pos, IFluidHandler.FluidAction action); /** * Check to see if a block can be drained. This method should be called by devices such as diff --git a/src/main/java/net/minecraftforge/fluids/IFluidTank.java b/src/main/java/net/minecraftforge/fluids/IFluidTank.java index df6dba35f..2e64c05d4 100644 --- a/src/main/java/net/minecraftforge/fluids/IFluidTank.java +++ b/src/main/java/net/minecraftforge/fluids/IFluidTank.java @@ -19,15 +19,17 @@ package net.minecraftforge.fluids; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + import javax.annotation.Nullable; /** - * A tank is the unit of interaction with Fluid inventories. - * - * A reference implementation can be found at {@link FluidTank}. + * This interface represents a Fluid Tank. IT IS NOT REQUIRED but is provided for convenience. + * You are free to handle Fluids in any way that you wish - this is simply an easy default way. + * DO NOT ASSUME that these objects are used internally in all cases. */ -public interface IFluidTank -{ +public interface IFluidTank { + /** * @return FluidStack representing the fluid in the tank, null if the tank is empty. */ @@ -45,33 +47,32 @@ public interface IFluidTank int getCapacity(); /** - * Returns a wrapper object {@link FluidTankInfo } containing the capacity of the tank and the - * FluidStack it holds. - * - * Should prevent manipulation of the IFluidTank. See {@link FluidTank}. - * - * @return State information for the IFluidTank. + * @param stack Fluidstack holding the Fluid to be queried. + * @return If the tank can hold the fluid (EVER, not at the time of query). */ - FluidTankInfo getInfo(); + boolean isFluidValid(FluidStack stack); /** - * - * @param resource - * FluidStack attempting to fill the tank. - * @param doFill - * If false, the fill will only be simulated. - * @return Amount of fluid that was accepted by the tank. + * @param resource FluidStack attempting to fill the tank. + * @param action If SIMULATE, the fill will only be simulated. + * @return Amount of fluid that was accepted (or would be, if simulated) by the tank. */ - int fill(FluidStack resource, boolean doFill); + int fill(FluidStack resource, FluidAction action); /** - * - * @param maxDrain - * Maximum amount of fluid to be removed from the container. - * @param doDrain - * If false, the drain will only be simulated. - * @return Amount of fluid that was removed from the tank. + * @param maxDrain Maximum amount of fluid to be removed from the container. + * @param action If SIMULATE, the drain will only be simulated. + * @return Amount of fluid that was removed (or would be, if simulated) from the tank. */ @Nullable - FluidStack drain(int maxDrain, boolean doDrain); + FluidStack drain(int maxDrain, FluidAction action); + + /** + * @param resource Maximum amount of fluid to be removed from the container. + * @param action If SIMULATE, the drain will only be simulated. + * @return FluidStack representing fluid that was removed (or would be, if simulated) from the tank. + */ + @Nullable + FluidStack drain(FluidStack resource, FluidAction action); + } diff --git a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java b/src/main/java/net/minecraftforge/fluids/UniversalBucket.java deleted file mode 100644 index ebd1c4476..000000000 --- a/src/main/java/net/minecraftforge/fluids/UniversalBucket.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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 net.minecraft.block.DispenserBlock; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Items; -import net.minecraft.item.Item; -import net.minecraft.item.ItemGroup; -import net.minecraft.item.ItemStack; -import net.minecraft.nbt.CompoundNBT; -import net.minecraft.stats.Stats; -import net.minecraft.util.ActionResult; -import net.minecraft.util.ActionResultType; -import net.minecraft.util.Hand; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.BlockRayTraceResult; -import net.minecraft.util.math.RayTraceContext; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.RayTraceContext.FluidMode; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TranslationTextComponent; -import net.minecraft.util.text.translation.LanguageMap; -import net.minecraft.world.World; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.event.entity.player.FillBucketEvent; -import net.minecraftforge.event.ForgeEventFactory; -import net.minecraftforge.fluids.capability.wrappers.FluidBucketWrapper; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.items.ItemHandlerHelper; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import net.minecraft.item.Item.Properties; - -/** - * A universal bucket that can hold any liquid - */ -public class UniversalBucket extends Item -{ - - private final int capacity; // how much the bucket holds - @Nonnull - private final ItemStack empty; // empty item to return and recognize when filling - private final boolean nbtSensitive; - - public UniversalBucket(Properties properties) - { - this(properties, Fluid.BUCKET_VOLUME, new ItemStack(Items.BUCKET), false); - } - - /** - * @param capacity Capacity of the container - * @param empty Item used for filling with the bucket event and returned when emptied - * @param nbtSensitive Whether the empty item is NBT sensitive (usually true if empty and full are the same items) - */ - public UniversalBucket(Properties properties, int capacity, @Nonnull ItemStack empty, boolean nbtSensitive) - { - super(properties); - this.capacity = capacity; - this.empty = empty; - this.nbtSensitive = nbtSensitive; - - /* TODO move to builder construction - this.setMaxStackSize(1); - - this.setCreativeTab(CreativeTabs.MISC); -*/ - DispenserBlock.registerDispenseBehavior(this, DispenseFluidContainer.getInstance()); - } - - @Override - public boolean hasContainerItem(@Nonnull ItemStack stack) - { - return !getEmpty().isEmpty(); - } - - @Nonnull - @Override - public ItemStack getContainerItem(@Nonnull ItemStack itemStack) - { - if (!getEmpty().isEmpty()) - { - // Create a copy such that the game can't mess with it - return getEmpty().copy(); - } - return super.getContainerItem(itemStack); - } - - @Override - public void fillItemGroup(@Nullable ItemGroup tab, @Nonnull NonNullList subItems) - { - if (!this.isInGroup(tab)) - return;/* TODO fluids - for (Fluid fluid : FluidRegistry.getRegisteredFluids().values()) - { - if (fluid != FluidRegistry.WATER && fluid != FluidRegistry.LAVA && !fluid.getName().equals("milk")) - { - // add all fluids that the bucket can be filled with - FluidStack fs = new FluidStack(fluid, getCapacity()); - ItemStack stack = new ItemStack(this); - IFluidHandlerItem fluidHandler = new FluidBucketWrapper(stack); - if (fluidHandler.fill(fs, true) == fs.amount) - { - ItemStack filled = fluidHandler.getContainer(); - subItems.add(filled); - } - } - }*/ - } - - @Override - @Nonnull - public ITextComponent getDisplayName(@Nonnull ItemStack stack) - { - FluidStack fluidStack = getFluid(stack); - if (fluidStack == null) - { - if(!getEmpty().isEmpty()) - { - return getEmpty().getDisplayName(); - } - return super.getDisplayName(stack); - } - - String unloc = this.getTranslationKey(); - - // TODO this is not reliable on the server - if (LanguageMap.getInstance().exists(unloc + "." + fluidStack.getFluid().getName())) - { - return new TranslationTextComponent(unloc + "." + fluidStack.getFluid().getName()); - } - - return new TranslationTextComponent(unloc + ".name", fluidStack.getLocalizedName()); - } - - @Override - @Nonnull - public ActionResult onItemRightClick(@Nonnull World world, @Nonnull PlayerEntity player, @Nonnull Hand hand) - { - ItemStack itemstack = player.getHeldItem(hand); - FluidStack fluidStack = getFluid(itemstack); - // empty bucket shouldn't exist, do nothing since it should be handled by the bucket event - if (fluidStack == null) - { - return new ActionResult(ActionResultType.PASS, itemstack); - } - - // clicked on a block? - RayTraceResult rt = rayTrace(world, player, FluidMode.NONE); - - ActionResult ret = ForgeEventFactory.onBucketUse(player, world, itemstack, rt); - if (ret != null) return ret; - - if(rt == null || rt.getType() != RayTraceResult.Type.BLOCK) - { - return new ActionResult(ActionResultType.PASS, itemstack); - } - - BlockRayTraceResult brt = (BlockRayTraceResult) rt; - BlockPos clickPos = brt.getPos(); - // can we place liquid there? - if (world.isBlockModifiable(player, clickPos)) - { - // the block adjacent to the side we clicked on - BlockPos targetPos = clickPos.offset(brt.getFace()); - - // can the player place there? - if (player.canPlayerEdit(targetPos, brt.getFace(), itemstack)) - { - // try placing liquid - FluidActionResult result = FluidUtil.tryPlaceFluid(player, world, hand, targetPos, itemstack, fluidStack); - if (result.isSuccess() && !player.abilities.isCreativeMode) - { - // success! - player.addStat(Stats.ITEM_USED.get(this)); - - itemstack.shrink(1); - ItemStack drained = result.getResult(); - ItemStack emptyStack = !drained.isEmpty() ? drained.copy() : new ItemStack(this); - - // check whether we replace the item or add the empty one to the inventory - if (itemstack.isEmpty()) - { - return new ActionResult(ActionResultType.SUCCESS, emptyStack); - } - else - { - // add empty bucket to player inventory - ItemHandlerHelper.giveItemToPlayer(player, emptyStack); - return new ActionResult(ActionResultType.SUCCESS, itemstack); - } - } - } - } - - // couldn't place liquid there2 - return new ActionResult(ActionResultType.FAIL, itemstack); - } - - @SubscribeEvent(priority = EventPriority.LOW) // low priority so other mods can handle their stuff first - public void onFillBucket(FillBucketEvent event) - { - if (event.getResult() != net.minecraftforge.eventbus.api.Event.Result.DEFAULT) - { - // event was already handled - return; - } - - // not for us to handle - ItemStack emptyBucket = event.getEmptyBucket(); - if (emptyBucket.isEmpty() || - !emptyBucket.isItemEqual(getEmpty()) || - (isNbtSensitive() && ItemStack.areItemStackTagsEqual(emptyBucket, getEmpty()))) - { - return; - } - - // needs to target a block - RayTraceResult target = event.getTarget(); - if (target == null || target.getType() != RayTraceResult.Type.BLOCK) - { - return; - } - - World world = event.getWorld(); - BlockPos pos = ((BlockRayTraceResult) target).getPos(); - - ItemStack singleBucket = emptyBucket.copy(); - singleBucket.setCount(1); - - FluidActionResult filledResult = FluidUtil.tryPickUpFluid(singleBucket, event.getEntityPlayer(), world, pos, ((BlockRayTraceResult) target).getFace()); - if (filledResult.isSuccess()) - { - event.setResult(net.minecraftforge.eventbus.api.Event.Result.ALLOW); - event.setFilledBucket(filledResult.getResult()); - } - else - { - // cancel event, otherwise the vanilla minecraft ItemBucket would - // convert it into a water/lava bucket depending on the blocks material - event.setCanceled(true); - } - } - - @Nullable - public FluidStack getFluid(@Nonnull ItemStack container) - { - return FluidStack.loadFluidStackFromNBT(container.getTag()); - } - - public int getCapacity() - { - return capacity; - } - - @Nonnull - public ItemStack getEmpty() - { - return empty; - } - - public boolean isNbtSensitive() - { - return nbtSensitive; - } - - @Nullable - @Override - public String getCreatorModId(@Nonnull ItemStack itemStack) - { - FluidStack fluidStack = getFluid(itemStack); - String modId = null; // TODO fluids FluidRegistry.getModId(fluidStack); - return modId != null ? modId : super.getCreatorModId(itemStack); - } - - @Override - public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, CompoundNBT nbt) - { - return new FluidBucketWrapper(stack); - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java index 433eb0c09..c511ca839 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/CapabilityFluidHandler.java @@ -27,11 +27,10 @@ import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; -import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; +import net.minecraftforge.fluids.capability.templates.FluidTank; public class CapabilityFluidHandler { @@ -40,21 +39,21 @@ public class CapabilityFluidHandler @CapabilityInject(IFluidHandlerItem.class) public static Capability FLUID_HANDLER_ITEM_CAPABILITY = null; - public static void register() + public static void register() { - CapabilityManager.INSTANCE.register(IFluidHandler.class, new DefaultFluidHandlerStorage<>(), () -> new FluidTank(Fluid.BUCKET_VOLUME)); + CapabilityManager.INSTANCE.register(IFluidHandler.class, new DefaultFluidHandlerStorage<>(), () -> new FluidTank(FluidAttributes.BUCKET_VOLUME)); - CapabilityManager.INSTANCE.register(IFluidHandlerItem.class, new DefaultFluidHandlerStorage<>(), () -> new FluidHandlerItemStack(new ItemStack(Items.BUCKET), Fluid.BUCKET_VOLUME)); + CapabilityManager.INSTANCE.register(IFluidHandlerItem.class, new DefaultFluidHandlerStorage<>(), () -> new FluidHandlerItemStack(new ItemStack(Items.BUCKET), FluidAttributes.BUCKET_VOLUME)); } private static class DefaultFluidHandlerStorage implements Capability.IStorage { @Override public INBT writeNBT(Capability capability, T instance, Direction side) { - if (!(instance instanceof IFluidTank)) - throw new RuntimeException("IFluidHandler instance does not implement IFluidTank"); + if (!(instance instanceof FluidTank)) + throw new RuntimeException("Cannot serialize to an instance that isn't the default implementation"); CompoundNBT nbt = new CompoundNBT(); - IFluidTank tank = (IFluidTank) instance; + FluidTank tank = (FluidTank) instance; FluidStack fluid = tank.getFluid(); if (fluid != null) { @@ -72,7 +71,7 @@ public class CapabilityFluidHandler public void readNBT(Capability capability, T instance, Direction side, INBT nbt) { if (!(instance instanceof FluidTank)) - throw new RuntimeException("IFluidHandler instance is not instance of FluidTank"); + throw new RuntimeException("Cannot deserialize to an instance that isn't the default implementation"); CompoundNBT tags = (CompoundNBT) nbt; FluidTank tank = (FluidTank) instance; tank.setCapacity(tags.getInt("Capacity")); diff --git a/src/main/java/net/minecraftforge/fluids/capability/FluidTankProperties.java b/src/main/java/net/minecraftforge/fluids/capability/FluidTankProperties.java deleted file mode 100644 index 078fe8fdb..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/FluidTankProperties.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability; - -import javax.annotation.Nullable; - -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; - -/** - * Basic implementation of {@link IFluidTankProperties}. - */ -public class FluidTankProperties implements IFluidTankProperties -{ - public static FluidTankProperties[] convert(FluidTankInfo[] fluidTankInfos) - { - FluidTankProperties[] properties = new FluidTankProperties[fluidTankInfos.length]; - for (int i = 0; i < fluidTankInfos.length; i++) - { - FluidTankInfo info = fluidTankInfos[i]; - properties[i] = new FluidTankProperties(info.fluid, info.capacity); - } - return properties; - } - - @Nullable - private final FluidStack contents; - private final int capacity; - private final boolean canFill; - private final boolean canDrain; - - public FluidTankProperties(@Nullable FluidStack contents, int capacity) - { - this(contents, capacity, true, true); - } - - public FluidTankProperties(@Nullable FluidStack contents, int capacity, boolean canFill, boolean canDrain) - { - this.contents = contents; - this.capacity = capacity; - this.canFill = canFill; - this.canDrain = canDrain; - } - - @Nullable - @Override - public FluidStack getContents() - { - return contents == null ? null : contents.copy(); - } - - @Override - public int getCapacity() - { - return capacity; - } - - @Override - public boolean canFill() - { - return canFill; - } - - @Override - public boolean canDrain() - { - return canDrain; - } - - @Override - public boolean canFillFluidType(FluidStack fluidStack) - { - return canFill; - } - - @Override - public boolean canDrainFluidType(FluidStack fluidStack) - { - return canDrain; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/FluidTankPropertiesWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/FluidTankPropertiesWrapper.java deleted file mode 100644 index 80c487953..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/FluidTankPropertiesWrapper.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability; - -import javax.annotation.Nullable; - -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; - -/** - * Basic {@link IFluidTankProperties} wrapper for {@link FluidTank}. - */ -public class FluidTankPropertiesWrapper implements IFluidTankProperties -{ - protected final FluidTank tank; - - public FluidTankPropertiesWrapper(FluidTank tank) - { - this.tank = tank; - } - - @Nullable - @Override - public FluidStack getContents() - { - FluidStack contents = tank.getFluid(); - return contents == null ? null : contents.copy(); - } - - @Override - public int getCapacity() - { - return tank.getCapacity(); - } - - @Override - public boolean canFill() - { - return tank.canFill(); - } - - @Override - public boolean canDrain() - { - return tank.canDrain(); - } - - @Override - public boolean canFillFluidType(FluidStack fluidStack) - { - return tank.canFillFluidType(fluidStack); - } - - @Override - public boolean canDrainFluidType(FluidStack fluidStack) - { - return tank.canDrainFluidType(fluidStack); - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/IFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/IFluidHandler.java index d71dd3423..4b470a203 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/IFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/IFluidHandler.java @@ -19,6 +19,7 @@ package net.minecraftforge.fluids.capability; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraftforge.fluids.*; @@ -31,33 +32,82 @@ import net.minecraftforge.fluids.*; */ public interface IFluidHandler { + enum FluidAction { + EXECUTE, SIMULATE; + + public boolean execute() { + return this == EXECUTE; + } + + public boolean simulate() { + return this == SIMULATE; + } + } + /** - * Returns an array of objects which represent the internal tanks. - * These objects cannot be used to manipulate the internal tanks. + * Returns the number of fluid storage units ("tanks") available * - * @return Properties for the relevant internal tanks. + * @return The number of tanks available */ - IFluidTankProperties[] getTankProperties(); + int getTanks(); + + /** + * Returns the FluidStack in a given tank. + * + *

+ * IMPORTANT: This FluidStack MUST NOT be modified. This method is not for + * altering internal contents. Any implementers who are able to detect modification via this method + * should throw an exception. It is ENTIRELY reasonable and likely that the stack returned here will be a copy. + *

+ * + *

+ * SERIOUSLY: DO NOT MODIFY THE RETURNED FLUIDSTACK + *

+ * + * @param tank Tank to query. + * @return FluidStack in a given tank. NULL if the tank is empty. + */ + @Nullable + FluidStack getFluidInTank(int tank); + + /** + * Retrieves the maximum fluid amount for a given tank. + * + * @param tank Tank to query. + * @return The maximum fluid amount held by the tank. + */ + int getTankCapacity(int tank); + + /** + * This function is a way to determine which fluids can exist inside a given handler. General purpose tanks will + * basically always return TRUE for this. + * + * @param tank Tank to query for validity + * @param stack Stack to test with for validity + * @return TRUE if the tank can hold the FluidStack, not considering current state. + * (Basically, is a given fluid EVER allowed in this tank?) Return FALSE if the answer to that question is 'no.' + */ + boolean isFluidValid(int tank, @Nonnull FluidStack stack); /** * Fills fluid into internal tanks, distribution is left entirely to the IFluidHandler. * * @param resource FluidStack representing the Fluid and maximum amount of fluid to be filled. - * @param doFill If false, fill will only be simulated. + * @param action If SIMULATE, fill will only be simulated. * @return Amount of resource that was (or would have been, if simulated) filled. */ - int fill(FluidStack resource, boolean doFill); + int fill(FluidStack resource, FluidAction action); /** * Drains fluid out of internal tanks, distribution is left entirely to the IFluidHandler. * * @param resource FluidStack representing the Fluid and maximum amount of fluid to be drained. - * @param doDrain If false, drain will only be simulated. + * @param action If SIMULATE, drain will only be simulated. * @return FluidStack representing the Fluid and amount that was (or would have been, if * simulated) drained. */ @Nullable - FluidStack drain(FluidStack resource, boolean doDrain); + FluidStack drain(FluidStack resource, FluidAction action); /** * Drains fluid out of internal tanks, distribution is left entirely to the IFluidHandler. @@ -65,10 +115,11 @@ public interface IFluidHandler * This method is not Fluid-sensitive. * * @param maxDrain Maximum amount of fluid to drain. - * @param doDrain If false, drain will only be simulated. + * @param action If SIMULATE, drain will only be simulated. * @return FluidStack representing the Fluid and amount that was (or would have been, if * simulated) drained. */ @Nullable - FluidStack drain(int maxDrain, boolean doDrain); + FluidStack drain(int maxDrain, FluidAction action); + } diff --git a/src/main/java/net/minecraftforge/fluids/capability/IFluidTankProperties.java b/src/main/java/net/minecraftforge/fluids/capability/IFluidTankProperties.java deleted file mode 100644 index 89ce8abc0..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/IFluidTankProperties.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability; - -import javax.annotation.Nullable; - -import net.minecraftforge.fluids.FluidStack; - -/** - * Simplified Read-only Information about the internals of an {@link IFluidHandler}. - * This is useful for displaying information, and as hints for interacting with it. - * These properties are constant and do not depend on the fluid contents (except the contents themselves, of course). - * - * The information here may not tell the full story of how the tank actually works, - * for real fluid transactions you must use {@link IFluidHandler} to simulate, check, and then interact. - * None of the information in these properties is required to successfully interact using a {@link IFluidHandler}. - */ -public interface IFluidTankProperties -{ - /** - * @return A copy of the fluid contents of this tank. May be null. - * To modify the contents, use {@link IFluidHandler}. - */ - @Nullable - FluidStack getContents(); - - /** - * @return The maximum amount of fluid this tank can hold, in millibuckets. - */ - int getCapacity(); - - /** - * Returns true if the tank can be filled at any time (even if it is currently full). - * It does not consider the contents or capacity of the tank. - * - * This value is constant. If the tank behavior is more complicated, returns true. - */ - boolean canFill(); - - /** - * Returns true if the tank can be drained at any time (even if it is currently empty). - * It does not consider the contents or capacity of the tank. - * - * This value is constant. If the tank behavior is more complicated, returns true. - */ - boolean canDrain(); - - /** - * Returns true if the tank can be filled with a specific type of fluid. - * Used as a filter for fluid types. - * - * Does not consider the current contents or capacity of the tank, - * only whether it could ever fill with this type of fluid. - * {@link FluidStack} is used here because fluid properties can depend on NBT, the amount is ignored. - */ - boolean canFillFluidType(FluidStack fluidStack); - - /** - * Returns true if the tank can drain out this a specific of fluid. - * Used as a filter for fluid types. - * - * Does not consider the current contents or capacity of the tank, - * only whether it could ever drain out this type of fluid. - * {@link FluidStack} is used here because fluid properties can depend on NBT, the amount is ignored. - */ - boolean canDrainFluidType(FluidStack fluidStack); -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/TileFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/TileFluidHandler.java index 99161ab78..bff42ad71 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/TileFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/TileFluidHandler.java @@ -25,15 +25,15 @@ import net.minecraft.tileentity.TileEntityType; import net.minecraft.util.Direction; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.FluidAttributes; +import net.minecraftforge.fluids.capability.templates.FluidTank; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class TileFluidHandler extends TileEntity { - protected FluidTank tank = new FluidTank(Fluid.BUCKET_VOLUME); + protected FluidTank tank = new FluidTank(FluidAttributes.BUCKET_VOLUME); private final LazyOptional holder = LazyOptional.of(() -> tank); diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/EmptyFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/templates/EmptyFluidHandler.java index 797a24f69..372fda59a 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/EmptyFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/EmptyFluidHandler.java @@ -19,69 +19,47 @@ package net.minecraftforge.fluids.capability.templates; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; -import net.minecraftforge.fluids.capability.FluidTankProperties; -import net.minecraftforge.fluids.IFluidTank; -import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fluids.capability.IFluidHandler; -public class EmptyFluidHandler implements IFluidHandler, IFluidTank +public class EmptyFluidHandler implements IFluidHandler { public static final EmptyFluidHandler INSTANCE = new EmptyFluidHandler(); - public static final FluidTankInfo EMPTY_TANK_INFO = new FluidTankInfo(null, 0); - public static final IFluidTankProperties EMPTY_TANK_PROPERTIES = new FluidTankProperties(null, 0, false, false); - public static final IFluidTankProperties[] EMPTY_TANK_PROPERTIES_ARRAY = new IFluidTankProperties[] { EMPTY_TANK_PROPERTIES }; protected EmptyFluidHandler() {} @Override - public IFluidTankProperties[] getTankProperties() - { - return EMPTY_TANK_PROPERTIES_ARRAY; - } + public int getTanks() { return 1; } - @Override @Nullable - public FluidStack getFluid() + @Override + public FluidStack getFluidInTank(int tank) { return null; } + + @Override + public int getTankCapacity(int tank) { return 0; } + + @Override + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } + + @Override + public int fill(FluidStack resource, FluidAction action) + { + return resource.amount; + } + + @Nullable + @Override + public FluidStack drain(FluidStack resource, FluidAction action) { return null; } + @Nullable @Override - public int getFluidAmount() - { - return 0; - } - - @Override - public int getCapacity() - { - return 0; - } - - @Override - public FluidTankInfo getInfo() - { - return EMPTY_TANK_INFO; - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - return 0; - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - return null; - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) + public FluidStack drain(int maxDrain, FluidAction action) { return null; } diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerConcatenate.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerConcatenate.java deleted file mode 100644 index b04ddf843..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerConcatenate.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability.templates; - -import com.google.common.collect.Lists; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -/** - * FluidHandlerConcatenate is a template class for concatenating multiple handlers into one. - * If each tank is restricted to exactly one type of fluid, then use {@link FluidHandlerFluidMap} as it is more efficient. - */ -public class FluidHandlerConcatenate implements IFluidHandler -{ - protected final IFluidHandler[] subHandlers; - - public FluidHandlerConcatenate(IFluidHandler... subHandlers) - { - this.subHandlers = subHandlers; - } - - public FluidHandlerConcatenate(Collection subHandlers) - { - this.subHandlers = subHandlers.toArray(new IFluidHandler[subHandlers.size()]); - } - - @Override - public IFluidTankProperties[] getTankProperties() - { - List tanks = Lists.newArrayList(); - for (IFluidHandler handler : subHandlers) - { - Collections.addAll(tanks, handler.getTankProperties()); - } - return tanks.toArray(new IFluidTankProperties[tanks.size()]); - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - if (resource == null || resource.amount <= 0) - return 0; - - resource = resource.copy(); - - int totalFillAmount = 0; - for (IFluidHandler handler : subHandlers) - { - int fillAmount = handler.fill(resource, doFill); - totalFillAmount += fillAmount; - resource.amount -= fillAmount; - if (resource.amount <= 0) - break; - } - return totalFillAmount; - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (resource == null || resource.amount <= 0) - return null; - - resource = resource.copy(); - - FluidStack totalDrained = null; - for (IFluidHandler handler : subHandlers) - { - FluidStack drain = handler.drain(resource, doDrain); - if (drain != null) - { - if (totalDrained == null) - totalDrained = drain; - else - totalDrained.amount += drain.amount; - - resource.amount -= drain.amount; - if (resource.amount <= 0) - break; - } - } - return totalDrained; - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - if (maxDrain == 0) - return null; - FluidStack totalDrained = null; - for (IFluidHandler handler : subHandlers) - { - if (totalDrained == null) - { - totalDrained = handler.drain(maxDrain, doDrain); - if (totalDrained != null) - { - maxDrain -= totalDrained.amount; - } - } - else - { - FluidStack copy = totalDrained.copy(); - copy.amount = maxDrain; - FluidStack drain = handler.drain(copy, doDrain); - if (drain != null) - { - totalDrained.amount += drain.amount; - maxDrain -= drain.amount; - } - } - - if (maxDrain <= 0) - break; - } - return totalDrained; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerFluidMap.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerFluidMap.java deleted file mode 100644 index d5351d67f..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerFluidMap.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability.templates; - -import com.google.common.collect.Lists; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidHandler; - -import java.util.*; - -/** - * FluidHandlerFluidMap is a template class for concatenating multiple handlers into one, - * where each handler is associated with a different fluid. - */ -public class FluidHandlerFluidMap implements IFluidHandler -{ - protected final Map handlers; - - public FluidHandlerFluidMap() - { - // LinkedHashMap to ensure iteration order is consistent. - this(new LinkedHashMap()); - } - - public FluidHandlerFluidMap(Map handlers) - { - this.handlers = handlers; - } - - public FluidHandlerFluidMap addHandler(Fluid fluid, IFluidHandler handler) - { - handlers.put(fluid, handler); - return this; - } - - @Override - public IFluidTankProperties[] getTankProperties() - { - List tanks = Lists.newArrayList(); - for (IFluidHandler iFluidHandler : handlers.values()) - { - Collections.addAll(tanks, iFluidHandler.getTankProperties()); - } - return tanks.toArray(new IFluidTankProperties[tanks.size()]); - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - if (resource == null) - return 0; - IFluidHandler handler = handlers.get(resource.getFluid()); - if (handler == null) - return 0; - return handler.fill(resource, doFill); - } - - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (resource == null) - return null; - IFluidHandler handler = handlers.get(resource.getFluid()); - if (handler == null) - return null; - return handler.drain(resource, doDrain); - } - - @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - for (IFluidHandler handler : handlers.values()) - { - FluidStack drain = handler.drain(maxDrain, doDrain); - if (drain != null) - return drain; - } - return null; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java index d84c4161c..6a4c8ffd6 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStack.java @@ -30,15 +30,13 @@ import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.*; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.FluidTankProperties; import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.fluids.capability.IFluidTankProperties; /** * FluidHandlerItemStack is a template capability provider for ItemStacks. * Data is stored directly in the vanilla NBT, in the same way as the old ItemFluidContainer. * - * This class allows an itemStack to contain any partial level of fluid up to its capacity, unlike {@link FluidHandlerItemStackSimple} + * This class allows an ItemStack to contain any partial level of fluid up to its capacity, unlike {@link FluidHandlerItemStackSimple} * * Additional examples are provided to enable consumable fluid containers (see {@link Consumable}), * fluid containers with different empty and full items (see {@link SwapEmpty}, @@ -94,13 +92,32 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv } @Override - public IFluidTankProperties[] getTankProperties() - { - return new FluidTankProperties[] { new FluidTankProperties(getFluid(), capacity) }; + public int getTanks() { + + return 1; + } + + @Nullable + @Override + public FluidStack getFluidInTank(int tank) { + + return getFluid(); } @Override - public int fill(FluidStack resource, boolean doFill) + public int getTankCapacity(int tank) { + + return capacity; + } + + @Override + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { + + return true; + } + + @Override + public int fill(FluidStack resource, FluidAction doFill) { if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !canFillFluidType(resource)) { @@ -112,7 +129,7 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv { int fillAmount = Math.min(capacity, resource.amount); - if (doFill) + if (doFill.execute()) { FluidStack filled = resource.copy(); filled.amount = fillAmount; @@ -127,7 +144,7 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv { int fillAmount = Math.min(capacity - contained.amount, resource.amount); - if (doFill && fillAmount > 0) { + if (doFill.execute() && fillAmount > 0) { contained.amount += fillAmount; setFluid(contained); } @@ -140,17 +157,17 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv } @Override - public FluidStack drain(FluidStack resource, boolean doDrain) + public FluidStack drain(FluidStack resource, FluidAction action) { if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !resource.isFluidEqual(getFluid())) { return null; } - return drain(resource.amount, doDrain); + return drain(resource.amount, action); } @Override - public FluidStack drain(int maxDrain, boolean doDrain) + public FluidStack drain(int maxDrain, FluidAction action) { if (container.getCount() != 1 || maxDrain <= 0) { @@ -168,7 +185,7 @@ public class FluidHandlerItemStack implements IFluidHandlerItem, ICapabilityProv FluidStack drained = contained.copy(); drained.amount = drainAmount; - if (doDrain) + if (action.execute()) { contained.amount -= drainAmount; if (contained.amount == 0) diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java index d9326b126..4a3d1624f 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidHandlerItemStackSimple.java @@ -29,9 +29,7 @@ import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.FluidTankProperties; import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; /** @@ -91,13 +89,32 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili } @Override - public IFluidTankProperties[] getTankProperties() - { - return new IFluidTankProperties[] { new FluidTankProperties(getFluid(), capacity) }; + public int getTanks() { + + return 1; + } + + @Nullable + @Override + public FluidStack getFluidInTank(int tank) { + + return getFluid(); } @Override - public int fill(FluidStack resource, boolean doFill) + public int getTankCapacity(int tank) { + + return capacity; + } + + @Override + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { + + return true; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !canFillFluidType(resource)) { @@ -109,7 +126,7 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili { int fillAmount = Math.min(capacity, resource.amount); if (fillAmount == capacity) { - if (doFill) { + if (action.execute()) { FluidStack filled = resource.copy(); filled.amount = fillAmount; setFluid(filled); @@ -123,17 +140,17 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili } @Override - public FluidStack drain(FluidStack resource, boolean doDrain) + public FluidStack drain(FluidStack resource, FluidAction action) { if (container.getCount() != 1 || resource == null || resource.amount <= 0 || !resource.isFluidEqual(getFluid())) { return null; } - return drain(resource.amount, doDrain); + return drain(resource.amount, action); } @Override - public FluidStack drain(int maxDrain, boolean doDrain) + public FluidStack drain(int maxDrain, FluidAction action) { if (container.getCount() != 1 || maxDrain <= 0) { @@ -150,7 +167,7 @@ public class FluidHandlerItemStackSimple implements IFluidHandlerItem, ICapabili if (drainAmount == capacity) { FluidStack drained = contained.copy(); - if (doDrain) { + if (action.execute()) { setContainerToEmpty(); } diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/FluidTank.java b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidTank.java new file mode 100644 index 000000000..2cc19acad --- /dev/null +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/FluidTank.java @@ -0,0 +1,244 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * 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.capability.templates; + +import net.minecraft.nbt.CompoundNBT; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidTank; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.function.Predicate; + +/** + * Flexible implementation of a Fluid Storage object. NOT REQUIRED. + * + * @author King Lemming + */ +public class FluidTank implements IFluidHandler, IFluidTank { + + protected Predicate validator; + @Nullable + protected FluidStack fluid = null; + protected int capacity; + + public FluidTank(int capacity) + { + this(capacity, e -> true); + } + + public FluidTank(int capacity, Predicate validator) + { + this.capacity = capacity; + this.validator = validator; + } + + public FluidTank setCapacity(int capacity) + { + this.capacity = capacity; + return this; + } + + public FluidTank setValidator(Predicate validator) + { + if (validator != null) { + this.validator = validator; + } + return this; + } + + public boolean isFluidValid(FluidStack stack) + { + return validator.test(stack); + } + + public int getCapacity() + { + return capacity; + } + + public FluidStack getFluid() + { + return fluid; + } + + public int getFluidAmount() + { + + if (fluid == null) + { + return 0; + } + return fluid.amount; + } + + public FluidTank readFromNBT(CompoundNBT nbt) { + + FluidStack fluid = null; + if (!nbt.contains("Empty")) + { + fluid = FluidStack.loadFluidStackFromNBT(nbt); + } + setFluid(fluid); + return this; + } + + public CompoundNBT writeToNBT(CompoundNBT nbt) { + + if (fluid != null) + { + fluid.writeToNBT(nbt); + } + else + { + nbt.putString("Empty", ""); + } + return nbt; + } + + @Override + public int getTanks() { + + return 1; + } + + @Nullable + @Override + public FluidStack getFluidInTank(int tank) { + + return getFluid(); + } + + @Override + public int getTankCapacity(int tank) { + + return getCapacity(); + } + + @Override + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { + + return isFluidValid(stack); + } + + @Override + public int fill(FluidStack resource, FluidAction action) + { + if (resource == null || !isFluidValid(resource)) + { + return 0; + } + if (action.simulate()) + { + if (fluid == null) + { + return Math.min(capacity, resource.amount); + } + if (!fluid.isFluidEqual(resource)) + { + return 0; + } + return Math.min(capacity - fluid.amount, resource.amount); + } + if (fluid == null) + { + onContentsChanged(); + fluid = new FluidStack(resource, Math.min(capacity, resource.amount)); + return fluid.amount; + } + if (!fluid.isFluidEqual(resource)) + { + return 0; + } + int filled = capacity - fluid.amount; + + if (resource.amount < filled) + { + fluid.amount += resource.amount; + filled = resource.amount; + } + else + { + fluid.amount = capacity; + } + return filled; + } + + @Override + public FluidStack drain(FluidStack resource, FluidAction action) + { + if (resource == null || !resource.isFluidEqual(fluid)) + { + return null; + } + return drain(resource.amount, action); + } + + @Override + public FluidStack drain(int maxDrain, FluidAction action) + { + if (fluid == null) + { + return null; + } + int drained = maxDrain; + if (fluid.amount < drained) + { + drained = fluid.amount; + } + FluidStack stack = new FluidStack(fluid, drained); + if (action.execute()) + { + fluid.amount -= drained; + if (fluid.amount <= 0) + { + fluid = null; + } + } + return stack; + } + + protected void onContentsChanged() + { + + } + + public void setFluid(FluidStack stack) + { + this.fluid = stack; + } + + public boolean isEmpty() + { + return fluid == null || fluid.amount <= 0; + } + + public int getSpace() + { + if (fluid == null) + { + return capacity; + } + return fluid.amount >= capacity ? 0 : capacity - fluid.amount; + } + +} diff --git a/src/main/java/net/minecraftforge/fluids/capability/templates/VoidFluidHandler.java b/src/main/java/net/minecraftforge/fluids/capability/templates/VoidFluidHandler.java index 7b85d8772..d2945da87 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/templates/VoidFluidHandler.java +++ b/src/main/java/net/minecraftforge/fluids/capability/templates/VoidFluidHandler.java @@ -20,73 +20,50 @@ package net.minecraftforge.fluids.capability.templates; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTankInfo; -import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.fluids.capability.IFluidHandler; -import net.minecraftforge.fluids.capability.IFluidTankProperties; + +import javax.annotation.Nonnull; import javax.annotation.Nullable; - -import javax.annotation.Nullable; - -import static net.minecraftforge.fluids.capability.templates.EmptyFluidHandler.EMPTY_TANK_INFO; -import static net.minecraftforge.fluids.capability.templates.EmptyFluidHandler.EMPTY_TANK_PROPERTIES_ARRAY; - /** * VoidFluidHandler is a template fluid handler that can be filled indefinitely without ever getting full. * It does not store fluid that gets filled into it, but "destroys" it upon receiving it. */ -public class VoidFluidHandler implements IFluidHandler, IFluidTank +public class VoidFluidHandler implements IFluidHandler { public static final VoidFluidHandler INSTANCE = new VoidFluidHandler(); public VoidFluidHandler() {} @Override - public IFluidTankProperties[] getTankProperties() - { - return EMPTY_TANK_PROPERTIES_ARRAY; - } + public int getTanks() { return 1; } - @Override @Nullable - public FluidStack getFluid() - { - return null; - } + @Override + public FluidStack getFluidInTank(int tank) { return null; } @Override - public int getFluidAmount() - { - return 0; - } + public int getTankCapacity(int tank) { return Integer.MAX_VALUE; } @Override - public int getCapacity() - { - return Integer.MAX_VALUE; - } + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return true; } @Override - public FluidTankInfo getInfo() - { - return EMPTY_TANK_INFO; - } - - @Override - public int fill(FluidStack resource, boolean doFill) + public int fill(FluidStack resource, FluidAction action) { return resource.amount; } + @Nullable @Override - public FluidStack drain(FluidStack resource, boolean doDrain) + public FluidStack drain(FluidStack resource, FluidAction action) { return null; } + @Nullable @Override - public FluidStack drain(int maxDrain, boolean doDrain) + public FluidStack drain(int maxDrain, FluidAction action) { return null; } diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockLiquidWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockLiquidWrapper.java deleted file mode 100644 index 5412d8df7..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockLiquidWrapper.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability.wrappers; -/* -import javax.annotation.Nullable; - -import net.minecraft.block.BlockLiquid; -import net.minecraft.block.material.Material; -import net.minecraft.block.state.IBlockState; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.init.Blocks; -import net.minecraft.item.ItemBucket; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.FluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidHandler; - -/** - * Wrapper to handle vanilla Water or Lava as an IFluidHandler. - * Methods are modeled after {@link ItemBucket#onItemRightClick(World, EntityPlayer, EnumHand)} - * / -public class BlockLiquidWrapper implements IFluidHandler -{ - protected final BlockLiquid blockLiquid; - protected final World world; - protected final BlockPos blockPos; - - public BlockLiquidWrapper(BlockLiquid blockLiquid, World world, BlockPos blockPos) - { - this.blockLiquid = blockLiquid; - this.world = world; - this.blockPos = blockPos; - } - - @Override - public IFluidTankProperties[] getTankProperties() - { - FluidStack containedStack = null; - IBlockState blockState = world.getBlockState(blockPos); - if (blockState.getBlock() == blockLiquid) - { - containedStack = getStack(blockState); - } - return new FluidTankProperties[]{new FluidTankProperties(containedStack, Fluid.BUCKET_VOLUME, false, true)}; - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - // NOTE: "Filling" means placement in this context! - if (resource.amount < Fluid.BUCKET_VOLUME) - { - return 0; - } - - if (doFill) - { - Material material = blockLiquid.getDefaultState().getMaterial(); - BlockLiquid block = BlockLiquid.getFlowingBlock(material); - world.setBlockState(blockPos, block.getDefaultState().withProperty(BlockLiquid.LEVEL, 0), 11); - } - - return Fluid.BUCKET_VOLUME; - } - - @Nullable - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (resource == null || resource.amount < Fluid.BUCKET_VOLUME) - { - return null; - } - - IBlockState blockState = world.getBlockState(blockPos); - if (blockState.getBlock() == blockLiquid && blockState.getValue(BlockLiquid.LEVEL) == 0) - { - FluidStack containedStack = getStack(blockState); - if (containedStack != null && resource.containsFluid(containedStack)) - { - if (doDrain) - { - world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), Constants.BlockFlags.DEFAULT_AND_RERENDER); - } - return containedStack; - } - - } - return null; - } - - @Nullable - @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - if (maxDrain < Fluid.BUCKET_VOLUME) - { - return null; - } - - IBlockState blockState = world.getBlockState(blockPos); - if (blockState.getBlock() == blockLiquid) - { - FluidStack containedStack = getStack(blockState); - if (containedStack != null && containedStack.amount <= maxDrain) - { - if (doDrain) - { - world.setBlockState(blockPos, Blocks.AIR.getDefaultState(), Constants.BlockFlags.DEFAULT_AND_RERENDER); - } - return containedStack; - } - - } - return null; - } - - @Nullable - private FluidStack getStack(IBlockState blockState) - { - Material material = blockState.getMaterial(); - if (material == Material.WATER && blockState.getValue(BlockLiquid.LEVEL) == 0) - { - return new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME); - } - else if (material == Material.LAVA && blockState.getValue(BlockLiquid.LEVEL) == 0) - { - return new FluidStack(FluidRegistry.LAVA, Fluid.BUCKET_VOLUME); - } - else - { - return null; - } - } -} -*/ diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java index 5f6f50bd8..bd0c1ac42 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java +++ b/src/main/java/net/minecraftforge/fluids/capability/wrappers/BlockWrapper.java @@ -20,10 +20,11 @@ package net.minecraftforge.fluids.capability.wrappers; import net.minecraft.block.Block; +import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; -import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.capability.templates.VoidFluidHandler; @@ -35,30 +36,30 @@ import net.minecraftforge.fluids.capability.templates.VoidFluidHandler; */ public class BlockWrapper extends VoidFluidHandler { - protected final Block block; + protected final BlockState state; protected final World world; protected final BlockPos blockPos; - public BlockWrapper(Block block, World world, BlockPos blockPos) + public BlockWrapper(BlockState state, World world, BlockPos blockPos) { - this.block = block; + this.state = state; this.world = world; this.blockPos = blockPos; } @Override - public int fill(FluidStack resource, boolean doFill) + public int fill(FluidStack resource, FluidAction action) { // NOTE: "Filling" means placement in this context! - if (resource.amount < Fluid.BUCKET_VOLUME) + if (resource.amount < FluidAttributes.BUCKET_VOLUME) { return 0; } - if (doFill) + if (action.execute()) { FluidUtil.destroyBlockOnFluidPlacement(world, blockPos); - world.setBlockState(blockPos, block.getDefaultState(), Constants.BlockFlags.DEFAULT_AND_RERENDER); + world.setBlockState(blockPos, state, Constants.BlockFlags.DEFAULT_AND_RERENDER); } - return Fluid.BUCKET_VOLUME; + return FluidAttributes.BUCKET_VOLUME; } } diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBlockWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBlockWrapper.java deleted file mode 100644 index 0f7b6094d..000000000 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBlockWrapper.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Minecraft Forge - * Copyright (c) 2016-2019. - * - * 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.capability.wrappers; - -import javax.annotation.Nullable; - -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.FluidTankProperties; -import net.minecraftforge.fluids.IFluidBlock; -import net.minecraftforge.fluids.capability.IFluidTankProperties; -import net.minecraftforge.fluids.capability.IFluidHandler; - -/** - * Wrapper to handle {@link IFluidBlock} as an IFluidHandler - */ -public class FluidBlockWrapper implements IFluidHandler -{ - protected final IFluidBlock fluidBlock; - protected final World world; - protected final BlockPos blockPos; - - public FluidBlockWrapper(IFluidBlock fluidBlock, World world, BlockPos blockPos) - { - this.fluidBlock = fluidBlock; - this.world = world; - this.blockPos = blockPos; - } - - @Override - public IFluidTankProperties[] getTankProperties() - { - float percentFilled = fluidBlock.getFilledPercentage(world, blockPos); - if (percentFilled < 0) - { - percentFilled *= -1; - } - int amountFilled = Math.round(Fluid.BUCKET_VOLUME * percentFilled); - FluidStack fluid = amountFilled > 0 ? new FluidStack(fluidBlock.getFluid(), amountFilled) : null; - return new FluidTankProperties[]{ new FluidTankProperties(fluid, Fluid.BUCKET_VOLUME, false, true)}; - } - - @Override - public int fill(FluidStack resource, boolean doFill) - { - // NOTE: "Filling" means placement in this context! - if (resource == null) - { - return 0; - } - return fluidBlock.place(world, blockPos, resource, doFill); - } - - @Nullable - @Override - public FluidStack drain(FluidStack resource, boolean doDrain) - { - if (resource == null || !fluidBlock.canDrain(world, blockPos)) - { - return null; - } - - FluidStack simulatedDrain = fluidBlock.drain(world, blockPos, false); - if (resource.containsFluid(simulatedDrain)) - { - if (doDrain) - { - return fluidBlock.drain(world, blockPos, true); - } - else - { - return simulatedDrain; - } - } - - return null; - } - - @Nullable - @Override - public FluidStack drain(int maxDrain, boolean doDrain) - { - if (maxDrain <= 0 || !fluidBlock.canDrain(world, blockPos)) - { - return null; - } - - FluidStack simulatedDrain = fluidBlock.drain(world, blockPos, false); - if (simulatedDrain != null && simulatedDrain.amount <= maxDrain) - { - if (doDrain) - { - return fluidBlock.drain(world, blockPos, true); - } - else - { - return simulatedDrain; - } - } - - return null; - } -} diff --git a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java b/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java index 2579ea7bd..629b89d81 100644 --- a/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java +++ b/src/main/java/net/minecraftforge/fluids/capability/wrappers/FluidBucketWrapper.java @@ -22,22 +22,15 @@ package net.minecraftforge.fluids.capability.wrappers; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import net.minecraft.item.Items; -import net.minecraft.item.Item; -import net.minecraft.item.MilkBucketItem; -import net.minecraft.item.ItemStack; +import net.minecraft.item.*; import net.minecraft.util.Direction; -import net.minecraftforge.common.ForgeMod; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidAttributes; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidUtil; -import net.minecraftforge.fluids.capability.FluidTankProperties; import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; /** @@ -76,24 +69,17 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide @Nullable public FluidStack getFluid() { - Item item = container.getItem();/* TODO fluids - if (item == Items.WATER_BUCKET) + Item item = container.getItem(); + if (item instanceof BucketItem) { - return new FluidStack(FluidRegistry.WATER, Fluid.BUCKET_VOLUME); - } - else if (item == Items.LAVA_BUCKET) - { - return new FluidStack(FluidRegistry.LAVA, Fluid.BUCKET_VOLUME); + return new FluidStack(((BucketItem)item).getFluid(), FluidAttributes.BUCKET_VOLUME); } + /* TODO fluids else if (item == Items.MILK_BUCKET) { return FluidRegistry.getFluidStack("milk", Fluid.BUCKET_VOLUME); } - else*/ if (item == ForgeMod.getInstance().universalBucket) - { - return ForgeMod.getInstance().universalBucket.getFluid(container); - } - else + else*/ { return null; } @@ -108,32 +94,51 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide } @Override - public IFluidTankProperties[] getTankProperties() - { - return new FluidTankProperties[] { new FluidTankProperties(getFluid(), Fluid.BUCKET_VOLUME) }; - } + public int getTanks() { - @Override - public int fill(FluidStack resource, boolean doFill) - { - if (container.getCount() != 1 || resource == null || resource.amount < Fluid.BUCKET_VOLUME || container.getItem() instanceof MilkBucketItem || getFluid() != null || !canFillFluidType(resource)) - { - return 0; - } - - if (doFill) - { - setFluid(resource); - } - - return Fluid.BUCKET_VOLUME; + return 1; } @Nullable @Override - public FluidStack drain(FluidStack resource, boolean doDrain) + public FluidStack getFluidInTank(int tank) { + + return getFluid(); + } + + @Override + public int getTankCapacity(int tank) { + + return FluidAttributes.BUCKET_VOLUME; + } + + @Override + public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { + + return true; + } + + @Override + public int fill(FluidStack resource, FluidAction action) { - if (container.getCount() != 1 || resource == null || resource.amount < Fluid.BUCKET_VOLUME) + if (container.getCount() != 1 || resource == null || resource.amount < FluidAttributes.BUCKET_VOLUME || container.getItem() instanceof MilkBucketItem || getFluid() != null || !canFillFluidType(resource)) + { + return 0; + } + + if (action.execute()) + { + setFluid(resource); + } + + return FluidAttributes.BUCKET_VOLUME; + } + + @Nullable + @Override + public FluidStack drain(FluidStack resource, FluidAction action) + { + if (container.getCount() != 1 || resource == null || resource.amount < FluidAttributes.BUCKET_VOLUME) { return null; } @@ -141,9 +146,9 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide FluidStack fluidStack = getFluid(); if (fluidStack != null && fluidStack.isFluidEqual(resource)) { - if (doDrain) + if (action.execute()) { - setFluid((FluidStack) null); + setFluid(null); } return fluidStack; } @@ -153,9 +158,9 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide @Nullable @Override - public FluidStack drain(int maxDrain, boolean doDrain) + public FluidStack drain(int maxDrain, FluidAction action) { - if (container.getCount() != 1 || maxDrain < Fluid.BUCKET_VOLUME) + if (container.getCount() != 1 || maxDrain < FluidAttributes.BUCKET_VOLUME) { return null; } @@ -163,9 +168,9 @@ public class FluidBucketWrapper implements IFluidHandlerItem, ICapabilityProvide FluidStack fluidStack = getFluid(); if (fluidStack != null) { - if (doDrain) + if (action.execute()) { - setFluid((FluidStack) null); + setFluid(null); } return fluidStack; } diff --git a/src/main/java/net/minecraftforge/fml/ModLoader.java b/src/main/java/net/minecraftforge/fml/ModLoader.java index 0e1de13aa..dc50926b8 100644 --- a/src/main/java/net/minecraftforge/fml/ModLoader.java +++ b/src/main/java/net/minecraftforge/fml/ModLoader.java @@ -214,7 +214,7 @@ public class ModLoader if (containers.size() != modInfoMap.size()) { LOGGER.fatal(LOADING,"File {} constructed {} mods: {}, but had {} mods specified: {}", modFile.getFilePath(), - containers.size(), containers.stream().map(ModContainer::getModId).collect(Collectors.toList()), + containers.size(), containers.stream().map(c -> c != null ? c.getModId() : "(null)").collect(Collectors.toList()), modInfoMap.size(), modInfoMap.values().stream().map(IModInfo::getModId).collect(Collectors.toList())); loadingExceptions.add(new ModLoadingException(null, ModLoadingStage.CONSTRUCT, "fml.modloading.missingclasses", null, modFile.getFilePath())); } diff --git a/src/main/java/net/minecraftforge/fml/mclanguageprovider/MinecraftModLanguageProvider.java b/src/main/java/net/minecraftforge/fml/mclanguageprovider/MinecraftModLanguageProvider.java index cace516e0..47da64afd 100644 --- a/src/main/java/net/minecraftforge/fml/mclanguageprovider/MinecraftModLanguageProvider.java +++ b/src/main/java/net/minecraftforge/fml/mclanguageprovider/MinecraftModLanguageProvider.java @@ -1,3 +1,22 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2019. + * + * 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.fml.mclanguageprovider; import net.minecraftforge.fml.ModContainer; diff --git a/src/test/java/net/minecraftforge/debug/block/MaterialFogColorTest.java b/src/test/java/net/minecraftforge/debug/block/MaterialFogColorTest.java index ae2f092d7..1ec7063fa 100644 --- a/src/test/java/net/minecraftforge/debug/block/MaterialFogColorTest.java +++ b/src/test/java/net/minecraftforge/debug/block/MaterialFogColorTest.java @@ -32,8 +32,6 @@ import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.event.RegistryEvent; -import net.minecraftforge.fluids.Fluid; -import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; diff --git a/src/test/java/net/minecraftforge/debug/fluid/DynBucketTest.java b/src/test/java/net/minecraftforge/debug/fluid/DynBucketTest.java index f62fc6a57..bd60d70a1 100644 --- a/src/test/java/net/minecraftforge/debug/fluid/DynBucketTest.java +++ b/src/test/java/net/minecraftforge/debug/fluid/DynBucketTest.java @@ -63,7 +63,7 @@ import net.minecraftforge.event.entity.player.FillBucketEvent; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.FluidTankOld; import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.fluids.UniversalBucket; @@ -136,7 +136,7 @@ public class DynBucketTest @net.minecraftforge.eventbus.api.SubscribeEvent public void registerRecipes(RegistryEvent.Register event) { - ItemStack filledBucket = FluidUtil.getFilledBucket(new FluidStack(ModelFluidTest.FLUID, Fluid.BUCKET_VOLUME)); + ItemStack filledBucket = FluidUtil.getFilledBucket(new FluidStack(ModelFluidTest.FLUID, FluidAttributes.BUCKET_VOLUME)); GameRegistry.addShapelessRecipe(new ResourceLocation(MODID, "diamond_to_fluid"), null, filledBucket, Ingredient.fromItem(Items.DIAMOND)); } @@ -162,7 +162,7 @@ public class DynBucketTest if (state.getBlock() instanceof IFluidBlock) { Fluid fluid = ((IFluidBlock) state.getBlock()).getFluid(); - FluidStack fs = new FluidStack(fluid, Fluid.BUCKET_VOLUME); + FluidStack fs = new FluidStack(fluid, FluidAttributes.BUCKET_VOLUME); ItemStack bucket = event.getEmptyBucket(); IFluidHandlerItem fluidHandler = FluidUtil.getFluidHandler(bucket); @@ -331,7 +331,7 @@ public class DynBucketTest public static class TileSimpleTank extends TileEntity { - FluidTank tank = new FluidTank(4000); + FluidTankOld tank = new FluidTankOld(4000); @Override public void readFromNBT(NBTTagCompound tags) diff --git a/src/test/java/net/minecraftforge/debug/fluid/FluidPlacementTest.java b/src/test/java/net/minecraftforge/debug/fluid/FluidPlacementTest.java index a3277982a..8b586f7ad 100644 --- a/src/test/java/net/minecraftforge/debug/fluid/FluidPlacementTest.java +++ b/src/test/java/net/minecraftforge/debug/fluid/FluidPlacementTest.java @@ -213,7 +213,7 @@ public class FluidPlacementTest @Override public int fill(FluidStack resource, boolean doFill) { - if (container.getCount() != 1 || resource == null || resource.amount > Fluid.BUCKET_VOLUME || container + if (container.getCount() != 1 || resource == null || resource.amount > FluidAttributes.BUCKET_VOLUME || container .getItem() instanceof ItemBucketMilk || getFluid() != null || !canFillFluidType(resource)) { return 0; diff --git a/src/test/java/net/minecraftforge/debug/fluid/NewFluidTest.java b/src/test/java/net/minecraftforge/debug/fluid/NewFluidTest.java new file mode 100644 index 000000000..38e97c500 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/fluid/NewFluidTest.java @@ -0,0 +1,206 @@ +package net.minecraftforge.debug.fluid; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.FlowingFluidBlock; +import net.minecraft.block.material.Material; +import net.minecraft.fluid.FlowingFluid; +import net.minecraft.fluid.Fluid; +import net.minecraft.fluid.Fluids; +import net.minecraft.fluid.IFluidState; +import net.minecraft.inventory.container.ContainerType; +import net.minecraft.item.BucketItem; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraft.item.Items; +import net.minecraft.state.StateContainer; +import net.minecraft.tags.FluidTags; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; +import net.minecraft.util.Direction; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockReader; +import net.minecraft.world.IEnviromentBlockReader; +import net.minecraft.world.IWorld; +import net.minecraft.world.IWorldReader; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fluids.FluidAttributes; +import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.ObjectHolder; + +@Mod("new_fluid_test") +public class NewFluidTest +{ + public static final ResourceLocation FLUID_STILL = new ResourceLocation("minecraft:block/brown_mushroom_block"); + public static final ResourceLocation FLUID_FLOWING = new ResourceLocation("minecraft:block/mushroom_stem"); + + @ObjectHolder("forge:test_fluid") + public static FlowingFluid test_fluid; + + @ObjectHolder("forge:test_fluid_flowing") + public static Fluid test_fluid_flowing; + + @ObjectHolder("forge:test_fluid_bucket") + public static Item test_fluid_bucket; + + @ObjectHolder("forge:test_fluid_block") + public static Block test_fluid_block; + + public NewFluidTest() + { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + + modEventBus.addGenericListener(Block.class, this::registerBlocks); + modEventBus.addGenericListener(Item.class, this::registerItems); + modEventBus.addGenericListener(Fluid.class, this::registerFluids); + } + + public void registerBlocks(RegistryEvent.Register event) + { + (test_fluid = new MyFlowingFluid.Source()).setRegistryName("forge:test_fluid"); + test_fluid_flowing = new MyFlowingFluid.Flowing().setRegistryName("forge:test_fluid_flowing"); + + event.getRegistry().registerAll( + new FlowingFluidBlock(test_fluid, Block.Properties.create(Material.WATER).doesNotBlockMovement().hardnessAndResistance(100.0F).noDrops()) + {} + .setRegistryName("forge:test_fluid_block") + ); + } + + public void registerItems(RegistryEvent.Register event) + { + event.getRegistry().registerAll( + new BucketItem(test_fluid, new Item.Properties().containerItem(Items.BUCKET).maxStackSize(1).group(ItemGroup.MISC)).setRegistryName("forge:test_fluid_bucket") + ); + } + + public void registerFluids(RegistryEvent.Register event) + { + event.getRegistry().registerAll(test_fluid, test_fluid_flowing); + } + + private static final FluidAttributes ATTRIBUTES = FluidAttributes.builder("test_fluid", FLUID_STILL, FLUID_FLOWING).build(); + + private static abstract class MyFlowingFluid extends FlowingFluid + { + @Override + public Fluid getFlowingFluid() + { + return test_fluid_flowing; + } + + @Override + public Fluid getStillFluid() + { + return test_fluid; + } + + @Override + protected boolean canSourcesMultiply() + { + return false; + } + + @Override + protected void beforeReplacingBlock(IWorld worldIn, BlockPos pos, BlockState state) + { + // copied from the WaterFluid implementation + TileEntity tileentity = state.getBlock().hasTileEntity() ? worldIn.getTileEntity(pos) : null; + Block.spawnDrops(state, worldIn.getWorld(), pos, tileentity); + } + + @Override + protected int getSlopeFindDistance(IWorldReader worldIn) + { + return 4; + } + + @Override + protected int getLevelDecreasePerBlock(IWorldReader worldIn) + { + return 1; + } + + @Override + public BlockRenderLayer getRenderLayer() + { + return BlockRenderLayer.TRANSLUCENT; + } + + @Override + public Item getFilledBucket() + { + return test_fluid_bucket; + } + + @Override + protected boolean func_215665_a(IFluidState p_215665_1_, IBlockReader p_215665_2_, BlockPos p_215665_3_, Fluid p_215665_4_, Direction p_215665_5_) + { + return p_215665_5_ == Direction.DOWN && !p_215665_4_.isIn(FluidTags.WATER); + } + + @Override + public int getTickRate(IWorldReader p_205569_1_) + { + return 5; + } + + @Override + protected float getExplosionResistance() + { + return 1; + } + + @Override + protected BlockState getBlockState(IFluidState state) + { + return test_fluid_block.getDefaultState().with(FlowingFluidBlock.LEVEL, getLevelFromState(state)); + } + + @Override + public boolean isEquivalentTo(Fluid fluidIn) { + return fluidIn == test_fluid || fluidIn == test_fluid_flowing; + } + + @Override + public FluidAttributes createAttributes(Fluid fluid) + { + return ATTRIBUTES; + } + + public static class Flowing extends MyFlowingFluid + { + { + setDefaultState(getStateContainer().getBaseState().with(LEVEL_1_8, 7)); + } + + protected void fillStateContainer(StateContainer.Builder builder) { + super.fillStateContainer(builder); + builder.add(LEVEL_1_8); + } + + public int getLevel(IFluidState p_207192_1_) { + return p_207192_1_.get(LEVEL_1_8); + } + + public boolean isSource(IFluidState state) { + return false; + } + } + + public static class Source extends MyFlowingFluid { + public int getLevel(IFluidState p_207192_1_) { + return 8; + } + + public boolean isSource(IFluidState state) { + return true; + } + } + } +} diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 0555ce5dd..842f8d52d 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -43,6 +43,8 @@ loaderVersion="[28,)" modId="command_event_test" [[mods]] modId="entity_selector_test" +[[mods]] + modId="new_fluid_test" [[mods]] modId="data_gen_test" [[mods]]