From e5cb0802d3cbc4e0519894673219b8f8ddcca551 Mon Sep 17 00:00:00 2001
From: Forstride <forstride@gmail.com>
Date: Wed, 3 Jan 2024 21:57:43 -0500
Subject: [PATCH] Cleaned up canteen classes and prevented drinking from
 canteens when thirst is full

---
 .../main/java/toughasnails/init/ModItems.java |  58 ++---
 ...CanteenItem.java => EmptyCanteenItem.java} |  54 ++++-
 .../item/EmptyCopperCanteenItem.java          |  97 --------
 .../item/EmptyDiamondCanteenItem.java         |  97 --------
 .../item/EmptyGoldCanteenItem.java            |  97 --------
 .../item/EmptyIronCanteenItem.java            |  97 --------
 .../item/EmptyNetheriteCanteenItem.java       |  97 --------
 .../toughasnails/item/FilledCanteenItem.java  | 208 ++++++++++++++++++
 .../item/FilledCopperCanteenItem.java         | 101 ---------
 .../item/FilledDiamondCanteenItem.java        | 101 ---------
 .../item/FilledGoldCanteenItem.java           | 101 ---------
 .../item/FilledIronCanteenItem.java           | 101 ---------
 .../item/FilledLeatherCanteenItem.java        | 101 ---------
 .../item/FilledNetheriteCanteenItem.java      | 101 ---------
 14 files changed, 285 insertions(+), 1126 deletions(-)
 rename common/src/main/java/toughasnails/item/{EmptyLeatherCanteenItem.java => EmptyCanteenItem.java} (66%)
 delete mode 100644 common/src/main/java/toughasnails/item/EmptyCopperCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/EmptyDiamondCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/EmptyGoldCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/EmptyIronCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/EmptyNetheriteCanteenItem.java
 create mode 100644 common/src/main/java/toughasnails/item/FilledCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledCopperCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledDiamondCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledGoldCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledIronCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledLeatherCanteenItem.java
 delete mode 100644 common/src/main/java/toughasnails/item/FilledNetheriteCanteenItem.java

diff --git a/common/src/main/java/toughasnails/init/ModItems.java b/common/src/main/java/toughasnails/init/ModItems.java
index e25bad8e..c6ec1de5 100644
--- a/common/src/main/java/toughasnails/init/ModItems.java
+++ b/common/src/main/java/toughasnails/init/ModItems.java
@@ -42,35 +42,35 @@ public static void registerItems(BiConsumer<ResourceLocation, Item> func)
         TANItems.ICE_CREAM = register(func, "ice_cream", new StackableBowlFoodItem(new Item.Properties().stacksTo(16).food(new FoodProperties.Builder().nutrition(0).saturationMod(0.0F).alwaysEat().build())));
         TANItems.CHARC_0S = register(func, "charc_os", new StackableBowlFoodItem(new Item.Properties().stacksTo(16).food(new FoodProperties.Builder().nutrition(0).saturationMod(0.0F).alwaysEat().build())));
 
-        TANItems.EMPTY_LEATHER_CANTEEN = register(func, "empty_leather_canteen", new EmptyLeatherCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.LEATHER_DIRTY_WATER_CANTEEN = register(func, "leather_dirty_water_canteen", new FilledLeatherCanteenItem((new Item.Properties()).durability(5)));
-        TANItems.LEATHER_WATER_CANTEEN = register(func, "leather_water_canteen", new FilledLeatherCanteenItem((new Item.Properties()).durability(5)));
-        TANItems.LEATHER_PURIFIED_WATER_CANTEEN = register(func, "leather_purified_water_canteen", new FilledLeatherCanteenItem((new Item.Properties()).durability(5)));
-
-        TANItems.EMPTY_COPPER_CANTEEN = register(func, "empty_copper_canteen", new EmptyCopperCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.COPPER_DIRTY_WATER_CANTEEN = register(func, "copper_dirty_water_canteen", new FilledCopperCanteenItem((new Item.Properties()).durability(6)));
-        TANItems.COPPER_WATER_CANTEEN = register(func, "copper_water_canteen", new FilledCopperCanteenItem((new Item.Properties()).durability(6)));
-        TANItems.COPPER_PURIFIED_WATER_CANTEEN = register(func, "copper_purified_water_canteen", new FilledCopperCanteenItem((new Item.Properties()).durability(6)));
-
-        TANItems.EMPTY_IRON_CANTEEN = register(func, "empty_iron_canteen", new EmptyIronCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.IRON_DIRTY_WATER_CANTEEN = register(func, "iron_dirty_water_canteen", new FilledIronCanteenItem((new Item.Properties()).durability(7)));
-        TANItems.IRON_WATER_CANTEEN = register(func, "iron_water_canteen", new FilledIronCanteenItem((new Item.Properties()).durability(7)));
-        TANItems.IRON_PURIFIED_WATER_CANTEEN = register(func, "iron_purified_water_canteen", new FilledIronCanteenItem((new Item.Properties()).durability(7)));
-
-        TANItems.EMPTY_GOLD_CANTEEN = register(func, "empty_gold_canteen", new EmptyGoldCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.GOLD_DIRTY_WATER_CANTEEN = register(func, "gold_dirty_water_canteen", new FilledGoldCanteenItem((new Item.Properties()).durability(10)));
-        TANItems.GOLD_WATER_CANTEEN = register(func, "gold_water_canteen", new FilledGoldCanteenItem((new Item.Properties()).durability(10)));
-        TANItems.GOLD_PURIFIED_WATER_CANTEEN = register(func, "gold_purified_water_canteen", new FilledGoldCanteenItem((new Item.Properties()).durability(10)));
-
-        TANItems.EMPTY_DIAMOND_CANTEEN = register(func, "empty_diamond_canteen", new EmptyDiamondCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.DIAMOND_DIRTY_WATER_CANTEEN = register(func, "diamond_dirty_water_canteen", new FilledDiamondCanteenItem((new Item.Properties()).durability(15)));
-        TANItems.DIAMOND_WATER_CANTEEN = register(func, "diamond_water_canteen", new FilledDiamondCanteenItem((new Item.Properties()).durability(15)));
-        TANItems.DIAMOND_PURIFIED_WATER_CANTEEN = register(func, "diamond_purified_water_canteen", new FilledDiamondCanteenItem((new Item.Properties()).durability(15)));
-
-        TANItems.EMPTY_NETHERITE_CANTEEN = register(func, "empty_netherite_canteen", new EmptyNetheriteCanteenItem((new Item.Properties()).stacksTo(1)));
-        TANItems.NETHERITE_DIRTY_WATER_CANTEEN = register(func, "netherite_dirty_water_canteen", new FilledNetheriteCanteenItem((new Item.Properties()).durability(25)));
-        TANItems.NETHERITE_WATER_CANTEEN = register(func, "netherite_water_canteen", new FilledNetheriteCanteenItem((new Item.Properties()).durability(25)));
-        TANItems.NETHERITE_PURIFIED_WATER_CANTEEN = register(func, "netherite_purified_water_canteen", new FilledNetheriteCanteenItem((new Item.Properties()).durability(25)));
+        TANItems.EMPTY_LEATHER_CANTEEN = register(func, "empty_leather_canteen", new EmptyCanteenItem(0, (new Item.Properties()).stacksTo(1)));
+        TANItems.LEATHER_DIRTY_WATER_CANTEEN = register(func, "leather_dirty_water_canteen", new FilledCanteenItem(0, (new Item.Properties()).durability(5)));
+        TANItems.LEATHER_WATER_CANTEEN = register(func, "leather_water_canteen", new FilledCanteenItem(0, (new Item.Properties()).durability(5)));
+        TANItems.LEATHER_PURIFIED_WATER_CANTEEN = register(func, "leather_purified_water_canteen", new FilledCanteenItem(0, (new Item.Properties()).durability(5)));
+
+        TANItems.EMPTY_COPPER_CANTEEN = register(func, "empty_copper_canteen", new EmptyCanteenItem(1, (new Item.Properties()).stacksTo(1)));
+        TANItems.COPPER_DIRTY_WATER_CANTEEN = register(func, "copper_dirty_water_canteen", new FilledCanteenItem(1, (new Item.Properties()).durability(6)));
+        TANItems.COPPER_WATER_CANTEEN = register(func, "copper_water_canteen", new FilledCanteenItem(1, (new Item.Properties()).durability(6)));
+        TANItems.COPPER_PURIFIED_WATER_CANTEEN = register(func, "copper_purified_water_canteen", new FilledCanteenItem(1, (new Item.Properties()).durability(6)));
+
+        TANItems.EMPTY_IRON_CANTEEN = register(func, "empty_iron_canteen", new EmptyCanteenItem(2, (new Item.Properties()).stacksTo(1)));
+        TANItems.IRON_DIRTY_WATER_CANTEEN = register(func, "iron_dirty_water_canteen", new FilledCanteenItem(2, (new Item.Properties()).durability(7)));
+        TANItems.IRON_WATER_CANTEEN = register(func, "iron_water_canteen", new FilledCanteenItem(2, (new Item.Properties()).durability(7)));
+        TANItems.IRON_PURIFIED_WATER_CANTEEN = register(func, "iron_purified_water_canteen", new FilledCanteenItem(2, (new Item.Properties()).durability(7)));
+
+        TANItems.EMPTY_GOLD_CANTEEN = register(func, "empty_gold_canteen", new EmptyCanteenItem(3, (new Item.Properties()).stacksTo(1)));
+        TANItems.GOLD_DIRTY_WATER_CANTEEN = register(func, "gold_dirty_water_canteen", new FilledCanteenItem(3, (new Item.Properties()).durability(10)));
+        TANItems.GOLD_WATER_CANTEEN = register(func, "gold_water_canteen", new FilledCanteenItem(3, (new Item.Properties()).durability(10)));
+        TANItems.GOLD_PURIFIED_WATER_CANTEEN = register(func, "gold_purified_water_canteen", new FilledCanteenItem(3, (new Item.Properties()).durability(10)));
+
+        TANItems.EMPTY_DIAMOND_CANTEEN = register(func, "empty_diamond_canteen", new EmptyCanteenItem(4, (new Item.Properties()).stacksTo(1)));
+        TANItems.DIAMOND_DIRTY_WATER_CANTEEN = register(func, "diamond_dirty_water_canteen", new FilledCanteenItem(4, (new Item.Properties()).durability(15)));
+        TANItems.DIAMOND_WATER_CANTEEN = register(func, "diamond_water_canteen", new FilledCanteenItem(4, (new Item.Properties()).durability(15)));
+        TANItems.DIAMOND_PURIFIED_WATER_CANTEEN = register(func, "diamond_purified_water_canteen", new FilledCanteenItem(4, (new Item.Properties()).durability(15)));
+
+        TANItems.EMPTY_NETHERITE_CANTEEN = register(func, "empty_netherite_canteen", new EmptyCanteenItem(5, (new Item.Properties()).stacksTo(1)));
+        TANItems.NETHERITE_DIRTY_WATER_CANTEEN = register(func, "netherite_dirty_water_canteen", new FilledCanteenItem(5, (new Item.Properties()).durability(25)));
+        TANItems.NETHERITE_WATER_CANTEEN = register(func, "netherite_water_canteen", new FilledCanteenItem(5, (new Item.Properties()).durability(25)));
+        TANItems.NETHERITE_PURIFIED_WATER_CANTEEN = register(func, "netherite_purified_water_canteen", new FilledCanteenItem(5, (new Item.Properties()).durability(25)));
 
         TANItems.DIRTY_WATER_BOTTLE = register(func, "dirty_water_bottle", new DirtyWaterBottleItem((new Item.Properties()).stacksTo(1)));
         TANItems.PURIFIED_WATER_BOTTLE = register(func, "purified_water_bottle", new PurifiedWaterBottleItem((new Item.Properties()).stacksTo(1)));
diff --git a/common/src/main/java/toughasnails/item/EmptyLeatherCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyCanteenItem.java
similarity index 66%
rename from common/src/main/java/toughasnails/item/EmptyLeatherCanteenItem.java
rename to common/src/main/java/toughasnails/item/EmptyCanteenItem.java
index b6a8f895..f9de9de5 100644
--- a/common/src/main/java/toughasnails/item/EmptyLeatherCanteenItem.java
+++ b/common/src/main/java/toughasnails/item/EmptyCanteenItem.java
@@ -27,11 +27,14 @@
 import toughasnails.block.RainCollectorBlock;
 import toughasnails.init.ModTags;
 
-public class EmptyLeatherCanteenItem extends Item
+public class EmptyCanteenItem extends Item
 {
-    public EmptyLeatherCanteenItem(Properties properties)
+    int tier;
+
+    public EmptyCanteenItem(int tier, Properties properties)
     {
         super(properties);
+        this.tier = tier;
     }
 
     @Override
@@ -57,7 +60,7 @@ public InteractionResultHolder<ItemStack> use(Level world, Player player, Intera
                     {
                         world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
                         ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.LEATHER_PURIFIED_WATER_CANTEEN)));
+                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(getPurifiedWaterCanteen())));
                     }
                 }
                 else if (world.getFluidState(pos).is(FluidTags.WATER))
@@ -70,15 +73,15 @@ else if (world.getFluidState(pos).is(FluidTags.WATER))
 
                     if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
                     {
-                        canteenItem = TANItems.LEATHER_DIRTY_WATER_CANTEEN;
+                        canteenItem = getDirtyWaterCanteen();
                     }
                     else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
                     {
-                        canteenItem = TANItems.LEATHER_PURIFIED_WATER_CANTEEN;
+                        canteenItem = getPurifiedWaterCanteen();
                     }
                     else
                     {
-                        canteenItem = TANItems.LEATHER_WATER_CANTEEN;
+                        canteenItem = getWaterCanteen();
                     }
 
                     return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
@@ -94,4 +97,43 @@ protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack
         player.awardStat(Stats.ITEM_USED.get(this));
         return ItemUtils.createFilledResult(oldStack, player, newStack);
     }
+
+    public Item getDirtyWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_DIRTY_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_DIRTY_WATER_CANTEEN;
+            case 2: return TANItems.IRON_DIRTY_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_DIRTY_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_DIRTY_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_DIRTY_WATER_CANTEEN;
+        }
+    }
+
+    public Item getWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_WATER_CANTEEN;
+            case 2: return TANItems.IRON_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_WATER_CANTEEN;
+        }
+    }
+
+    public Item getPurifiedWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_PURIFIED_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_PURIFIED_WATER_CANTEEN;
+            case 2: return TANItems.IRON_PURIFIED_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_PURIFIED_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_PURIFIED_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_PURIFIED_WATER_CANTEEN;
+        }
+    }
 }
diff --git a/common/src/main/java/toughasnails/item/EmptyCopperCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyCopperCanteenItem.java
deleted file mode 100644
index 9ca86d58..00000000
--- a/common/src/main/java/toughasnails/item/EmptyCopperCanteenItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Holder;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.biome.Biome;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.block.TANBlocks;
-import toughasnails.api.item.TANItems;
-import toughasnails.block.RainCollectorBlock;
-import toughasnails.init.ModTags;
-
-public class EmptyCopperCanteenItem extends Item
-{
-    public EmptyCopperCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos))
-            {
-                BlockState state = world.getBlockState(pos);
-
-                if (state.getBlock() instanceof RainCollectorBlock)
-                {
-                    // Fill the canteen from purified water from a rain collector
-                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
-
-                    if (waterLevel > 0 && !world.isClientSide())
-                    {
-                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.COPPER_PURIFIED_WATER_CANTEEN)));
-                    }
-                }
-                else if (world.getFluidState(pos).is(FluidTags.WATER))
-                {
-                    // Fill the canteen with water in the world
-                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-
-                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
-                    Item canteenItem;
-
-                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.COPPER_DIRTY_WATER_CANTEEN;
-                    }
-                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.COPPER_PURIFIED_WATER_CANTEEN;
-                    }
-                    else
-                    {
-                        canteenItem = TANItems.COPPER_WATER_CANTEEN;
-                    }
-
-                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
-                }
-            }
-        }
-
-        return InteractionResultHolder.pass(stack);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/EmptyDiamondCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyDiamondCanteenItem.java
deleted file mode 100644
index 50cf14f0..00000000
--- a/common/src/main/java/toughasnails/item/EmptyDiamondCanteenItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Holder;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.biome.Biome;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.block.TANBlocks;
-import toughasnails.api.item.TANItems;
-import toughasnails.block.RainCollectorBlock;
-import toughasnails.init.ModTags;
-
-public class EmptyDiamondCanteenItem extends Item
-{
-    public EmptyDiamondCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos))
-            {
-                BlockState state = world.getBlockState(pos);
-
-                if (state.getBlock() instanceof RainCollectorBlock)
-                {
-                    // Fill the canteen from purified water from a rain collector
-                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
-
-                    if (waterLevel > 0 && !world.isClientSide())
-                    {
-                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.DIAMOND_PURIFIED_WATER_CANTEEN)));
-                    }
-                }
-                else if (world.getFluidState(pos).is(FluidTags.WATER))
-                {
-                    // Fill the canteen with water in the world
-                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-
-                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
-                    Item canteenItem;
-
-                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.DIAMOND_DIRTY_WATER_CANTEEN;
-                    }
-                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.DIAMOND_PURIFIED_WATER_CANTEEN;
-                    }
-                    else
-                    {
-                        canteenItem = TANItems.DIAMOND_WATER_CANTEEN;
-                    }
-
-                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
-                }
-            }
-        }
-
-        return InteractionResultHolder.pass(stack);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/EmptyGoldCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyGoldCanteenItem.java
deleted file mode 100644
index b785b560..00000000
--- a/common/src/main/java/toughasnails/item/EmptyGoldCanteenItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Holder;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.biome.Biome;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.block.TANBlocks;
-import toughasnails.api.item.TANItems;
-import toughasnails.block.RainCollectorBlock;
-import toughasnails.init.ModTags;
-
-public class EmptyGoldCanteenItem extends Item
-{
-    public EmptyGoldCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos))
-            {
-                BlockState state = world.getBlockState(pos);
-
-                if (state.getBlock() instanceof RainCollectorBlock)
-                {
-                    // Fill the canteen from purified water from a rain collector
-                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
-
-                    if (waterLevel > 0 && !world.isClientSide())
-                    {
-                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.GOLD_PURIFIED_WATER_CANTEEN)));
-                    }
-                }
-                else if (world.getFluidState(pos).is(FluidTags.WATER))
-                {
-                    // Fill the canteen with water in the world
-                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-
-                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
-                    Item canteenItem;
-
-                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.GOLD_DIRTY_WATER_CANTEEN;
-                    }
-                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.GOLD_PURIFIED_WATER_CANTEEN;
-                    }
-                    else
-                    {
-                        canteenItem = TANItems.GOLD_WATER_CANTEEN;
-                    }
-
-                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
-                }
-            }
-        }
-
-        return InteractionResultHolder.pass(stack);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/EmptyIronCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyIronCanteenItem.java
deleted file mode 100644
index bb2c4c03..00000000
--- a/common/src/main/java/toughasnails/item/EmptyIronCanteenItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Holder;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.biome.Biome;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.block.TANBlocks;
-import toughasnails.api.item.TANItems;
-import toughasnails.block.RainCollectorBlock;
-import toughasnails.init.ModTags;
-
-public class EmptyIronCanteenItem extends Item
-{
-    public EmptyIronCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos))
-            {
-                BlockState state = world.getBlockState(pos);
-
-                if (state.getBlock() instanceof RainCollectorBlock)
-                {
-                    // Fill the canteen from purified water from a rain collector
-                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
-
-                    if (waterLevel > 0 && !world.isClientSide())
-                    {
-                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.IRON_PURIFIED_WATER_CANTEEN)));
-                    }
-                }
-                else if (world.getFluidState(pos).is(FluidTags.WATER))
-                {
-                    // Fill the canteen with water in the world
-                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-
-                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
-                    Item canteenItem;
-
-                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.IRON_DIRTY_WATER_CANTEEN;
-                    }
-                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.IRON_PURIFIED_WATER_CANTEEN;
-                    }
-                    else
-                    {
-                        canteenItem = TANItems.IRON_WATER_CANTEEN;
-                    }
-
-                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
-                }
-            }
-        }
-
-        return InteractionResultHolder.pass(stack);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/EmptyNetheriteCanteenItem.java b/common/src/main/java/toughasnails/item/EmptyNetheriteCanteenItem.java
deleted file mode 100644
index fe27b107..00000000
--- a/common/src/main/java/toughasnails/item/EmptyNetheriteCanteenItem.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Holder;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.level.biome.Biome;
-import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.block.TANBlocks;
-import toughasnails.api.item.TANItems;
-import toughasnails.block.RainCollectorBlock;
-import toughasnails.init.ModTags;
-
-public class EmptyNetheriteCanteenItem extends Item
-{
-    public EmptyNetheriteCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos))
-            {
-                BlockState state = world.getBlockState(pos);
-
-                if (state.getBlock() instanceof RainCollectorBlock)
-                {
-                    // Fill the canteen from purified water from a rain collector
-                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
-
-                    if (waterLevel > 0 && !world.isClientSide())
-                    {
-                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
-                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(TANItems.NETHERITE_PURIFIED_WATER_CANTEEN)));
-                    }
-                }
-                else if (world.getFluidState(pos).is(FluidTags.WATER))
-                {
-                    // Fill the canteen with water in the world
-                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-
-                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
-                    Item canteenItem;
-
-                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.NETHERITE_DIRTY_WATER_CANTEEN;
-                    }
-                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
-                    {
-                        canteenItem = TANItems.NETHERITE_PURIFIED_WATER_CANTEEN;
-                    }
-                    else
-                    {
-                        canteenItem = TANItems.NETHERITE_WATER_CANTEEN;
-                    }
-
-                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
-                }
-            }
-        }
-
-        return InteractionResultHolder.pass(stack);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledCanteenItem.java b/common/src/main/java/toughasnails/item/FilledCanteenItem.java
new file mode 100644
index 00000000..f4ef863f
--- /dev/null
+++ b/common/src/main/java/toughasnails/item/FilledCanteenItem.java
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright 2021, the Glitchfiend Team.
+ * All rights reserved.
+ ******************************************************************************/
+package toughasnails.item;
+
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Holder;
+import net.minecraft.sounds.SoundEvents;
+import net.minecraft.sounds.SoundSource;
+import net.minecraft.stats.Stats;
+import net.minecraft.tags.FluidTags;
+import net.minecraft.world.InteractionHand;
+import net.minecraft.world.InteractionResultHolder;
+import net.minecraft.world.entity.LivingEntity;
+import net.minecraft.world.entity.player.Player;
+import net.minecraft.world.item.Item;
+import net.minecraft.world.item.ItemStack;
+import net.minecraft.world.item.ItemUtils;
+import net.minecraft.world.item.UseAnim;
+import net.minecraft.world.level.ClipContext;
+import net.minecraft.world.level.Level;
+import net.minecraft.world.level.biome.Biome;
+import net.minecraft.world.level.block.state.BlockState;
+import net.minecraft.world.phys.BlockHitResult;
+import net.minecraft.world.phys.HitResult;
+import toughasnails.api.block.TANBlocks;
+import toughasnails.api.item.TANItems;
+import toughasnails.api.thirst.ThirstHelper;
+import toughasnails.block.RainCollectorBlock;
+import toughasnails.init.ModTags;
+
+public class FilledCanteenItem extends Item
+{
+    int tier;
+
+    public FilledCanteenItem(int tier, Properties properties)
+    {
+        super(properties);
+        this.tier = tier;
+    }
+
+    @Override
+    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
+    {
+        ItemStack stack = player.getItemInHand(hand);
+        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
+
+        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
+        {
+            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
+
+            if (world.mayInteract(player, pos))
+            {
+                BlockState state = world.getBlockState(pos);
+
+                if (state.getBlock() instanceof RainCollectorBlock)
+                {
+                    // Fill the canteen from purified water from a rain collector
+                    int waterLevel = state.getValue(RainCollectorBlock.LEVEL);
+
+                    if (waterLevel > 0 && !world.isClientSide())
+                    {
+                        world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
+                        ((RainCollectorBlock) TANBlocks.RAIN_COLLECTOR).setWaterLevel(world, pos, state, waterLevel - 1);
+                        return InteractionResultHolder.success(this.replaceCanteen(stack, player, new ItemStack(getPurifiedWaterCanteen())));
+                    }
+                }
+                else if (world.getFluidState(pos).is(FluidTags.WATER))
+                {
+                    // Fill the canteen with water in the world
+                    world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
+
+                    Holder<Biome> biome = player.level().getBiome(player.blockPosition());
+                    Item canteenItem;
+
+                    if (biome.is(ModTags.Biomes.DIRTY_WATER_BIOMES))
+                    {
+                        canteenItem = getDirtyWaterCanteen();
+                    }
+                    else if (biome.is(ModTags.Biomes.PURIFIED_WATER_BIOMES))
+                    {
+                        canteenItem = getPurifiedWaterCanteen();
+                    }
+                    else
+                    {
+                        canteenItem = getWaterCanteen();
+                    }
+
+                    return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(canteenItem)), world.isClientSide());
+                }
+            }
+        }
+
+        if (ThirstHelper.canDrink(player, this.canAlwaysDrink()))
+        {
+            return ItemUtils.startUsingInstantly(world, player, hand);
+        }
+
+        return InteractionResultHolder.fail(player.getItemInHand(hand));
+    }
+
+    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
+    {
+        player.awardStat(Stats.ITEM_USED.get(this));
+        return ItemUtils.createFilledResult(oldStack, player, newStack);
+    }
+
+    @Override
+    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
+    {
+        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
+
+        // Do nothing if this isn't a player
+        if (player == null)
+            return stack;
+
+        player.awardStat(Stats.ITEM_USED.get(this));
+
+        // Damage the item if we're on the server and the player isn't in creative mode
+        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
+        {
+            boolean[] broken = new boolean[]{false};
+            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
+            if (broken[0])
+            {
+                return new ItemStack(getEmptyCanteen());
+            }
+        }
+
+        return stack;
+    }
+
+    @Override
+    public int getUseDuration(ItemStack stack)
+    {
+        return 32;
+    }
+
+    @Override
+    public UseAnim getUseAnimation(ItemStack stack)
+    {
+        return UseAnim.DRINK;
+    }
+
+    @Override
+    public boolean isEnchantable(ItemStack stack)
+    {
+        return false;
+    }
+
+    public boolean canAlwaysDrink()
+    {
+        return false;
+    }
+
+    public Item getEmptyCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.EMPTY_LEATHER_CANTEEN;
+            case 1: return TANItems.EMPTY_COPPER_CANTEEN;
+            case 2: return TANItems.EMPTY_IRON_CANTEEN;
+            case 3: return TANItems.EMPTY_GOLD_CANTEEN;
+            case 4: return TANItems.EMPTY_DIAMOND_CANTEEN;
+            case 5: return TANItems.EMPTY_NETHERITE_CANTEEN;
+        }
+    }
+
+    public Item getDirtyWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_DIRTY_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_DIRTY_WATER_CANTEEN;
+            case 2: return TANItems.IRON_DIRTY_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_DIRTY_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_DIRTY_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_DIRTY_WATER_CANTEEN;
+        }
+    }
+
+    public Item getWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_WATER_CANTEEN;
+            case 2: return TANItems.IRON_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_WATER_CANTEEN;
+        }
+    }
+
+    public Item getPurifiedWaterCanteen()
+    {
+        switch (this.tier)
+        {
+            default: case 0: return TANItems.LEATHER_PURIFIED_WATER_CANTEEN;
+            case 1: return TANItems.COPPER_PURIFIED_WATER_CANTEEN;
+            case 2: return TANItems.IRON_PURIFIED_WATER_CANTEEN;
+            case 3: return TANItems.GOLD_PURIFIED_WATER_CANTEEN;
+            case 4: return TANItems.DIAMOND_PURIFIED_WATER_CANTEEN;
+            case 5: return TANItems.NETHERITE_PURIFIED_WATER_CANTEEN;
+        }
+    }
+}
diff --git a/common/src/main/java/toughasnails/item/FilledCopperCanteenItem.java b/common/src/main/java/toughasnails/item/FilledCopperCanteenItem.java
deleted file mode 100644
index cc6dedcc..00000000
--- a/common/src/main/java/toughasnails/item/FilledCopperCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledCopperCanteenItem extends Item
-{
-    public FilledCopperCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.COPPER_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_COPPER_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledDiamondCanteenItem.java b/common/src/main/java/toughasnails/item/FilledDiamondCanteenItem.java
deleted file mode 100644
index 92140d90..00000000
--- a/common/src/main/java/toughasnails/item/FilledDiamondCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledDiamondCanteenItem extends Item
-{
-    public FilledDiamondCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.DIAMOND_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_DIAMOND_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledGoldCanteenItem.java b/common/src/main/java/toughasnails/item/FilledGoldCanteenItem.java
deleted file mode 100644
index a6f5b942..00000000
--- a/common/src/main/java/toughasnails/item/FilledGoldCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledGoldCanteenItem extends Item
-{
-    public FilledGoldCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.GOLD_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_GOLD_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledIronCanteenItem.java b/common/src/main/java/toughasnails/item/FilledIronCanteenItem.java
deleted file mode 100644
index a0fe8f3d..00000000
--- a/common/src/main/java/toughasnails/item/FilledIronCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledIronCanteenItem extends Item
-{
-    public FilledIronCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.IRON_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_IRON_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledLeatherCanteenItem.java b/common/src/main/java/toughasnails/item/FilledLeatherCanteenItem.java
deleted file mode 100644
index 6d203f5e..00000000
--- a/common/src/main/java/toughasnails/item/FilledLeatherCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledLeatherCanteenItem extends Item
-{
-    public FilledLeatherCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.LEATHER_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_LEATHER_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}
diff --git a/common/src/main/java/toughasnails/item/FilledNetheriteCanteenItem.java b/common/src/main/java/toughasnails/item/FilledNetheriteCanteenItem.java
deleted file mode 100644
index 40fb4295..00000000
--- a/common/src/main/java/toughasnails/item/FilledNetheriteCanteenItem.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*******************************************************************************
- * Copyright 2021, the Glitchfiend Team.
- * All rights reserved.
- ******************************************************************************/
-package toughasnails.item;
-
-import net.minecraft.core.BlockPos;
-import net.minecraft.sounds.SoundEvents;
-import net.minecraft.sounds.SoundSource;
-import net.minecraft.stats.Stats;
-import net.minecraft.tags.FluidTags;
-import net.minecraft.world.InteractionHand;
-import net.minecraft.world.InteractionResultHolder;
-import net.minecraft.world.entity.LivingEntity;
-import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
-import net.minecraft.world.item.ItemStack;
-import net.minecraft.world.item.ItemUtils;
-import net.minecraft.world.item.UseAnim;
-import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
-import net.minecraft.world.phys.BlockHitResult;
-import net.minecraft.world.phys.HitResult;
-import toughasnails.api.item.TANItems;
-
-public class FilledNetheriteCanteenItem extends Item
-{
-    public FilledNetheriteCanteenItem(Properties properties)
-    {
-        super(properties);
-    }
-
-    @Override
-    public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand)
-    {
-        ItemStack stack = player.getItemInHand(hand);
-        HitResult rayTraceResult = getPlayerPOVHitResult(world, player, ClipContext.Fluid.SOURCE_ONLY);
-
-        if (rayTraceResult.getType() == HitResult.Type.BLOCK)
-        {
-            BlockPos pos = ((BlockHitResult)rayTraceResult).getBlockPos();
-
-            if (world.mayInteract(player, pos) && world.getFluidState(pos).is(FluidTags.WATER))
-            {
-                world.playSound(player, player.getX(), player.getY(), player.getZ(), SoundEvents.BOTTLE_FILL, SoundSource.NEUTRAL, 1.0F, 1.0F);
-                return InteractionResultHolder.sidedSuccess(this.replaceCanteen(stack, player, new ItemStack(TANItems.NETHERITE_WATER_CANTEEN)), world.isClientSide());
-            }
-        }
-
-        return ItemUtils.startUsingInstantly(world, player, hand);
-    }
-
-    protected ItemStack replaceCanteen(ItemStack oldStack, Player player, ItemStack newStack)
-    {
-        player.awardStat(Stats.ITEM_USED.get(this));
-        return ItemUtils.createFilledResult(oldStack, player, newStack);
-    }
-
-    @Override
-    public ItemStack finishUsingItem(ItemStack stack, Level worldIn, LivingEntity entityLiving)
-    {
-        Player player = entityLiving instanceof Player ? (Player)entityLiving : null;
-
-        // Do nothing if this isn't a player
-        if (player == null)
-            return stack;
-
-        player.awardStat(Stats.ITEM_USED.get(this));
-
-        // Damage the item if we're on the server and the player isn't in creative mode
-        if (!worldIn.isClientSide && !player.getAbilities().instabuild)
-        {
-            boolean[] broken = new boolean[]{false};
-            stack.hurtAndBreak(1, player, (entity) -> broken[0] = true);
-            if (broken[0])
-            {
-                return new ItemStack(TANItems.EMPTY_NETHERITE_CANTEEN);
-            }
-        }
-
-        return stack;
-    }
-
-    @Override
-    public int getUseDuration(ItemStack stack)
-    {
-        return 32;
-    }
-
-    @Override
-    public UseAnim getUseAnimation(ItemStack stack)
-    {
-        return UseAnim.DRINK;
-    }
-
-    @Override
-    public boolean isEnchantable(ItemStack stack)
-    {
-        return false;
-    }
-}