瀏覽代碼

new effects, barrels, finished stews (vats + bowl), herbs, nobodies(entities) to hold texts, tweaks and bugfixes

Kajetan Johannes Hammerle 7 年之前
父節點
當前提交
20b91b0142
共有 100 個文件被更改,包括 1943 次插入165 次删除
  1. 21 8
      src/main/java/me/km/ClientProxy.java
  2. 19 2
      src/main/java/me/km/KajetansMod.java
  3. 1 0
      src/main/java/me/km/ObjectRegistry.java
  4. 9 2
      src/main/java/me/km/api/Utils.java
  5. 86 0
      src/main/java/me/km/blocks/BlockBarrel.java
  6. 6 0
      src/main/java/me/km/blocks/BlockCampFire.java
  7. 92 14
      src/main/java/me/km/blocks/BlockModCauldron.java
  8. 187 0
      src/main/java/me/km/blocks/CauldronColorMixer.java
  9. 27 7
      src/main/java/me/km/blocks/ModBlocks.java
  10. 71 32
      src/main/java/me/km/blocks/TileEntityCauldron.java
  11. 18 1
      src/main/java/me/km/effects/Effect.java
  12. 19 0
      src/main/java/me/km/effects/active/ArmorBoost.java
  13. 34 0
      src/main/java/me/km/effects/active/BladeStorm.java
  14. 17 0
      src/main/java/me/km/effects/active/Charge.java
  15. 3 3
      src/main/java/me/km/effects/active/Cripple.java
  16. 25 0
      src/main/java/me/km/effects/active/Disarm.java
  17. 19 0
      src/main/java/me/km/effects/active/DragonSkin.java
  18. 0 1
      src/main/java/me/km/effects/active/Earthquake.java
  19. 1 1
      src/main/java/me/km/effects/active/Flying.java
  20. 19 0
      src/main/java/me/km/effects/active/Ignorance.java
  21. 2 2
      src/main/java/me/km/effects/active/Kick.java
  22. 2 2
      src/main/java/me/km/effects/active/Lucky.java
  23. 30 0
      src/main/java/me/km/effects/active/PullAttack.java
  24. 24 0
      src/main/java/me/km/effects/active/Revenge.java
  25. 30 0
      src/main/java/me/km/effects/active/Shield.java
  26. 4 0
      src/main/java/me/km/effects/active/Silence.java
  27. 25 0
      src/main/java/me/km/effects/active/SilencePunch.java
  28. 26 0
      src/main/java/me/km/effects/active/StrongStunPunch.java
  29. 25 0
      src/main/java/me/km/effects/active/StunPunch.java
  30. 19 0
      src/main/java/me/km/effects/active/Thorns.java
  31. 19 0
      src/main/java/me/km/effects/active/TimedHeal.java
  32. 2 1
      src/main/java/me/km/effects/active/Unlucky.java
  33. 31 0
      src/main/java/me/km/effects/active/WarCall.java
  34. 19 1
      src/main/java/me/km/effects/passive/ArrowEffects.java
  35. 75 2
      src/main/java/me/km/effects/passive/EntityDamageEffects.java
  36. 1 5
      src/main/java/me/km/entities/EntityHuman.java
  37. 229 0
      src/main/java/me/km/entities/EntityNobody.java
  38. 2 1
      src/main/java/me/km/entities/ModEntities.java
  39. 1 1
      src/main/java/me/km/entities/ModelHuman.java
  40. 29 0
      src/main/java/me/km/entities/RenderNobody.java
  41. 272 0
      src/main/java/me/km/items/ItemColoredSoup.java
  42. 23 0
      src/main/java/me/km/items/ItemFood.java
  43. 19 19
      src/main/java/me/km/items/ItemGun.java
  44. 25 0
      src/main/java/me/km/items/ItemHerbs.java
  45. 50 0
      src/main/java/me/km/items/ItemSpecialHerbs.java
  46. 26 13
      src/main/java/me/km/items/ModItems.java
  47. 5 0
      src/main/java/me/km/items/noglint/ItemNoGlintLingeringPotion.java
  48. 5 0
      src/main/java/me/km/items/noglint/ItemNoGlintPotion.java
  49. 5 0
      src/main/java/me/km/items/noglint/ItemNoGlintSplashPotion.java
  50. 1 8
      src/main/java/me/km/snuviscript/CommandGiveUp.java
  51. 15 0
      src/main/java/me/km/snuviscript/ScriptEvents.java
  52. 0 17
      src/main/java/me/km/utils/ReflectionUtils.java
  53. 5 0
      src/main/resources/assets/km/blockstates/barrel_acacia.json
  54. 5 0
      src/main/resources/assets/km/blockstates/barrel_big_oak.json
  55. 5 0
      src/main/resources/assets/km/blockstates/barrel_birch.json
  56. 5 0
      src/main/resources/assets/km/blockstates/barrel_jungle.json
  57. 5 0
      src/main/resources/assets/km/blockstates/barrel_oak.json
  58. 5 0
      src/main/resources/assets/km/blockstates/barrel_spruce.json
  59. 1 0
      src/main/resources/assets/km/blockstates/cauldron_acacia.json
  60. 1 0
      src/main/resources/assets/km/blockstates/cauldron_big_oak.json
  61. 1 0
      src/main/resources/assets/km/blockstates/cauldron_birch.json
  62. 1 0
      src/main/resources/assets/km/blockstates/cauldron_jungle.json
  63. 1 0
      src/main/resources/assets/km/blockstates/cauldron_oak.json
  64. 1 0
      src/main/resources/assets/km/blockstates/cauldron_spruce.json
  65. 23 6
      src/main/resources/assets/km/lang/en_US.lang
  66. 68 0
      src/main/resources/assets/km/models/block/barrel/barrel.json
  67. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_acacia.json
  68. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_big_oak.json
  69. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_birch.json
  70. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_jungle.json
  71. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_oak.json
  72. 10 0
      src/main/resources/assets/km/models/block/barrel/barrel_spruce.json
  73. 1 0
      src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_empty.json
  74. 1 0
      src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level1.json
  75. 1 0
      src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level2.json
  76. 1 0
      src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level3.json
  77. 1 0
      src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_empty.json
  78. 1 0
      src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level1.json
  79. 1 0
      src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level2.json
  80. 1 0
      src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level3.json
  81. 1 0
      src/main/resources/assets/km/models/block/cauldron/birch/cauldron_empty.json
  82. 1 0
      src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level1.json
  83. 1 0
      src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level2.json
  84. 1 0
      src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level3.json
  85. 5 4
      src/main/resources/assets/km/models/block/cauldron/cauldron_empty.json
  86. 4 4
      src/main/resources/assets/km/models/block/cauldron/cauldron_level1.json
  87. 4 4
      src/main/resources/assets/km/models/block/cauldron/cauldron_level2.json
  88. 4 4
      src/main/resources/assets/km/models/block/cauldron/cauldron_level3.json
  89. 1 0
      src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_empty.json
  90. 1 0
      src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level1.json
  91. 1 0
      src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level2.json
  92. 1 0
      src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level3.json
  93. 1 0
      src/main/resources/assets/km/models/block/cauldron/oak/cauldron_empty.json
  94. 1 0
      src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level1.json
  95. 1 0
      src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level2.json
  96. 1 0
      src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level3.json
  97. 1 0
      src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_empty.json
  98. 1 0
      src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level1.json
  99. 1 0
      src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level2.json
  100. 1 0
      src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level3.json

+ 21 - 8
src/main/java/me/km/ClientProxy.java

@@ -1,8 +1,11 @@
 package me.km;
 
+import java.awt.Color;
 import me.km.blocks.ModBlocks;
 import me.km.blocks.TileEntityCauldron;
 import me.km.entities.ModEntities;
+import me.km.items.ItemColoredSoup;
+import me.km.items.ModItems;
 import me.km.items.ModelCylinder;
 import me.km.items.ModelHat;
 import me.km.networking.KeyManager;
@@ -14,10 +17,12 @@ import net.minecraft.client.renderer.block.model.ModelBakery;
 import net.minecraft.client.renderer.block.model.ModelResourceLocation;
 import net.minecraft.client.renderer.block.statemap.StateMapperBase;
 import net.minecraft.client.renderer.color.BlockColors;
+import net.minecraft.client.renderer.color.ItemColors;
 import net.minecraft.client.renderer.color.IBlockColor;
 import net.minecraft.client.renderer.entity.Render;
 import net.minecraft.entity.Entity;
 import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.IBlockAccess;
@@ -72,6 +77,7 @@ public class ClientProxy extends CommonProxy
         ModEntities.initClient();
         MinecraftForge.EVENT_BUS.register(new ClientEvents());
         MinecraftForge.EVENT_BUS.register(new KeyManager());
+        
         IBlockColor colorer = (IBlockState state, IBlockAccess w, BlockPos pos, int tintIndex) -> 
         {
             TileEntityCauldron tile = (TileEntityCauldron) w.getTileEntity(pos);
@@ -79,15 +85,22 @@ public class ClientProxy extends CommonProxy
             {
                 return -16777216;
             }
-            return -16777216 | tile.getRed() << 16 | tile.getGreen() << 8 | tile.getBlue();
+            Color c = tile.getColor();
+            return -16777216 | c.getRed() << 16 | c.getGreen() << 8 | c.getBlue();
         };
-        BlockColors colors = Minecraft.getMinecraft().getBlockColors();
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronOak);
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronAcacia);
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronBigOak);
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronBirch);
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronJungle);
-        colors.registerBlockColorHandler(colorer, ModBlocks.cauldronSpruce);
+        BlockColors bColors = Minecraft.getMinecraft().getBlockColors();
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronOak);
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronAcacia);
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronBigOak);
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronBirch);
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronJungle);
+        bColors.registerBlockColorHandler(colorer, ModBlocks.cauldronSpruce);
+        
+        ItemColors iColors = Minecraft.getMinecraft().getItemColors();
+        iColors.registerItemColorHandler((ItemStack stack, int tintIndex) -> 
+        {
+            return tintIndex > 0 ? -1 : ((ItemColoredSoup) stack.getItem()).getColor(stack);
+        }, ModItems.coloredSoup);
     }
 
     @Override

+ 19 - 2
src/main/java/me/km/KajetansMod.java

@@ -12,6 +12,7 @@ import me.km.databank.DataBank;
 import me.km.dimensions.ModWorldGeneration;
 import me.km.dimensions.WorldData;
 import me.km.effects.EffectUtils;
+import me.km.items.ModItems;
 import me.km.jobsystem.JobAPI;
 import me.km.networking.ModPacketHandler;
 import me.km.permissions.PermissionManager;
@@ -104,11 +105,27 @@ public class KajetansMod
                         net.minecraft.entity.player.EntityPlayerMP p = e.getPlayer();
                         net.minecraft.util.math.BlockPos pos = Utils.getPlayerTarget(p);
                         String[] parts = e.getMessage().split(" ");
-                        ((me.km.blocks.TileEntityCauldron) p.world.getTileEntity(pos))
-                                .setColor(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
+                        switch(parts[0])
+                        {
+                            case "color":
+                                ((me.km.blocks.TileEntityCauldron) p.world.getTileEntity(pos))
+                                    .setColor(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
+                                break;
+                            case "ent":
+                                me.km.entities.EntityNobody ent = new me.km.entities.EntityNobody(p.world);
+                                ent.setLocationAndAngles(p.posX, p.posY, p.posZ, 0, 0);
+                                ent.setCustomNameTag("Test name");
+                                p.world.spawnEntity(ent);
+                                break;
+                            case "search":
+                                Utils.getEntities(p.world, p.posX, p.posY, p.posZ, 5, net.minecraft.entity.Entity.class)
+                                        .forEach(s -> System.out.println(s));
+                                break;
+                        }
                     }
                     catch(Exception ex)
                     {
+                        ex.printStackTrace();
                     }
                 }
             });

+ 1 - 0
src/main/java/me/km/ObjectRegistry.java

@@ -7,6 +7,7 @@ import me.km.recipes.ModRecipes;
 import me.km.sounds.Sounds;
 import net.minecraft.block.Block;
 import net.minecraft.init.Blocks;
+import net.minecraft.init.Items;
 import net.minecraft.item.Item;
 import net.minecraft.item.crafting.IRecipe;
 import net.minecraft.util.SoundEvent;

+ 9 - 2
src/main/java/me/km/api/Utils.java

@@ -5,7 +5,6 @@ import java.io.File;
 import me.km.utils.ItemStackBuilder;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.List;
 import java.util.Random;
 import java.util.stream.Collectors;
@@ -56,7 +55,6 @@ import net.minecraft.tileentity.TileEntitySkull;
 import net.minecraft.util.CombatRules;
 import net.minecraft.util.DamageSource;
 import net.minecraft.util.math.RayTraceResult;
-import net.minecraft.util.text.ITextComponent;
 import net.minecraft.world.WorldServer;
 
 public class Utils 
@@ -530,6 +528,15 @@ public class Utils
         double sqareRadius = radius * radius;
         return w.playerEntities.stream().filter(p -> p.getDistanceSq(x, y, z) <= sqareRadius).collect(Collectors.toList());
     }
+    
+    public static List<EntityPlayer> getPlayers(Entity not, double radius)
+    {       
+        double sqareRadius = radius * radius;
+        double x = not.posX;
+        double y = not.posY;
+        double z = not.posZ;
+        return not.world.playerEntities.stream().filter(p -> p != not && p.getDistanceSq(x, y, z) <= sqareRadius).collect(Collectors.toList());
+    }
 
     public static <T extends Entity> T getEntity(World w, double x, double y, double z, double radius, Class<T> type)
     {

+ 86 - 0
src/main/java/me/km/blocks/BlockBarrel.java

@@ -0,0 +1,86 @@
+package me.km.blocks;
+
+import java.util.List;
+import javax.annotation.Nullable;
+import static net.minecraft.block.Block.FULL_BLOCK_AABB;
+import net.minecraft.block.material.Material;
+import net.minecraft.block.state.BlockFaceShape;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.math.AxisAlignedBB;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+public class BlockBarrel extends BlockBase
+{
+    protected static final AxisAlignedBB AABB_LEGS = new AxisAlignedBB(0.0D, 0.0625D, 0.0D, 1.0D, 0.875D, 1.0D);
+    protected static final AxisAlignedBB AABB_WALL_NORTH = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 1.0D, 0.125D);
+    protected static final AxisAlignedBB AABB_WALL_SOUTH = new AxisAlignedBB(0.0D, 0.0D, 0.875D, 1.0D, 1.0D, 1.0D);
+    protected static final AxisAlignedBB AABB_WALL_EAST = new AxisAlignedBB(0.875D, 0.0D, 0.0D, 1.0D, 1.0D, 1.0D);
+    protected static final AxisAlignedBB AABB_WALL_WEST = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.125D, 1.0D, 1.0D);
+
+    public BlockBarrel(String name, String local) 
+    {
+        super(Material.WOOD, name, local);
+        super.setCreativeTab(CreativeTabs.DECORATIONS);
+    }
+
+    @Override
+    public void addCollisionBoxToList(IBlockState state, World w, BlockPos pos, AxisAlignedBB eBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity ent, boolean p_185477_7_)
+    {
+        addCollisionBoxToList(pos, eBox, collidingBoxes, AABB_LEGS);
+        addCollisionBoxToList(pos, eBox, collidingBoxes, AABB_WALL_WEST);
+        addCollisionBoxToList(pos, eBox, collidingBoxes, AABB_WALL_NORTH);
+        addCollisionBoxToList(pos, eBox, collidingBoxes, AABB_WALL_EAST);
+        addCollisionBoxToList(pos, eBox, collidingBoxes, AABB_WALL_SOUTH);
+    }
+
+    @Override
+    public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
+    {
+        return FULL_BLOCK_AABB;
+    }
+
+    @Override
+    public boolean isOpaqueCube(IBlockState state)
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isFullCube(IBlockState state)
+    {
+        return false;
+    }
+
+    /*@Override
+    public Item getItemDropped(IBlockState state, Random rand, int fortune)
+    {
+        return Items.CAULDRON;
+    }
+
+    @Override
+    public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
+    {
+        return new ItemStack(Items.CAULDRON);
+    }*/
+
+    @Override
+    public boolean isPassable(IBlockAccess worldIn, BlockPos pos)
+    {
+        return true;
+    }
+
+    @Override
+    public BlockFaceShape getBlockFaceShape(IBlockAccess w, IBlockState state, BlockPos pos, EnumFacing face)
+    {
+        if(face == EnumFacing.UP)
+        {
+            return BlockFaceShape.BOWL;
+        }
+        return face == EnumFacing.DOWN ? BlockFaceShape.UNDEFINED : BlockFaceShape.SOLID;
+    }
+}

+ 6 - 0
src/main/java/me/km/blocks/BlockCampFire.java

@@ -119,4 +119,10 @@ public class BlockCampFire extends BlockBase
             }
         }
     }
+    
+    @Override
+    public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
+    {
+        return false;
+    }
 }

+ 92 - 14
src/main/java/me/km/blocks/BlockModCauldron.java

@@ -2,33 +2,34 @@ package me.km.blocks;
 
 import java.util.Random;
 import me.km.KajetansMod;
+import me.km.items.ModItems;
 import net.minecraft.block.BlockCauldron;
 import net.minecraft.block.ITileEntityProvider;
 import net.minecraft.block.SoundType;
 import net.minecraft.block.state.IBlockState;
+import net.minecraft.creativetab.CreativeTabs;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.Items;
 import net.minecraft.item.Item;
 import net.minecraft.item.ItemStack;
 import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.EnumHand;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.World;
 
 public class BlockModCauldron extends BlockCauldron implements IBlockBase, ITileEntityProvider
 {
     protected String name;
-    private Item cauldron;
 
     public BlockModCauldron(String name, String local) 
     {
         this.name = name;
         this.setRegistryName(name);
         super.setUnlocalizedName(local);
-        this.cauldron = null;
         super.setHardness(2.0F);
-    }
-    
-    public void setItem(Item cauldron)
-    {
-        this.cauldron = cauldron;
+        super.setCreativeTab(CreativeTabs.BREWING);
     }
     
     @Override
@@ -43,28 +44,105 @@ public class BlockModCauldron extends BlockCauldron implements IBlockBase, ITile
         super.setSoundType(sound);
         return this;
     }
+
+    @Override
+    public TileEntity createNewTileEntity(World worldIn, int meta) 
+    {
+        return new TileEntityCauldron();
+    }
+    
+    @Override
+    public void breakBlock(World w, BlockPos pos, IBlockState state)
+    {
+        w.removeTileEntity(pos);
+    }
     
     @Override
     public Item getItemDropped(IBlockState state, Random rand, int fortune)
     {
-        return cauldron;
+        return Item.getItemFromBlock(this);
     }
 
     @Override
     public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
     {
-        return new ItemStack(cauldron);
+        return new ItemStack(Item.getItemFromBlock(this), 1, this.damageDropped(state));
     }
 
     @Override
-    public TileEntity createNewTileEntity(World worldIn, int meta) 
+    public boolean onBlockActivated(World w, BlockPos pos, IBlockState state, EntityPlayer p, 
+            EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
     {
-        return new TileEntityCauldron();
+        if(w.isRemote)
+        {
+            return true;
+        }
+        else
+        {
+            TileEntity te = w.getTileEntity(pos);
+            if(te instanceof TileEntityCauldron)
+            {
+                TileEntityCauldron cauldron = (TileEntityCauldron) te;
+                boolean b = false;
+                if(cauldron.hasDefaultColor())
+                {
+                    b = super.onBlockActivated(w, pos, state, p, hand, facing, hitX, hitY, hitZ);
+                }
+                ItemStack stack = p.getHeldItem(hand);
+                if(stack.isEmpty() || b)
+                {
+                    return true;
+                }
+                else if(stack.getItem() == Items.BOWL)
+                {
+                    int waterLevel = state.getValue(LEVEL);
+                    if(waterLevel > 0)
+                    {
+                        ItemStack stew = new ItemStack(ModItems.coloredSoup);
+                        ModItems.coloredSoup.addIngredient(stew, cauldron.getIngredients());
+                        ModItems.coloredSoup.setColor(stew, cauldron.getColor().getRGB());
+                        ModItems.coloredSoup.setFoodStats(stew, cauldron.getIngredients());
+                        stack.shrink(1);
+                        if(stack.isEmpty())
+                        {
+                            p.setHeldItem(hand, stew);
+                        }
+                        else if(!p.inventory.addItemStackToInventory(stew))
+                        {
+                            p.dropItem(stew, false);
+                        }
+                        else if(p instanceof EntityPlayerMP)
+                        {
+                            ((EntityPlayerMP) p).sendContainerToPlayer(p.inventoryContainer);
+                        }
+                        this.setWaterLevel(w, pos, state, waterLevel - 1);
+                    }
+                    return true;
+                }
+                if(cauldron.getNumberOfIngredients() < 3 && cauldron.addItemStack(stack))
+                {
+                    if(!p.capabilities.isCreativeMode)
+                    {
+                        stack.shrink(1);
+                    }
+                }
+                return true;
+            }
+            return true;
+        }
     }
-    
+
     @Override
-    public void breakBlock(World w, BlockPos pos, IBlockState state)
+    public void setWaterLevel(World w, BlockPos pos, IBlockState state, int level) 
     {
-        w.removeTileEntity(pos);
+        if(level <= 0 && !w.isRemote)
+        {
+            TileEntity te = w.getTileEntity(pos);
+            if(te instanceof TileEntityCauldron)
+            {
+                ((TileEntityCauldron) te).reset();
+            }
+        }
+        super.setWaterLevel(w, pos, state, level);
     }
 }

+ 187 - 0
src/main/java/me/km/blocks/CauldronColorMixer.java

@@ -0,0 +1,187 @@
+package me.km.blocks;
+
+import java.awt.Color;
+import java.util.LinkedList;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.item.ItemFishFood;
+
+public class CauldronColorMixer 
+{
+    public final static Color DEFAULT = new Color(47, 67, 244); 
+    
+    private final static Color POISON = new Color(0, 128, 43);   
+    
+    private final static Color PUMPKIN = new Color(197, 120, 23, 255);
+    private final static Color APPLE = new Color(195, 30, 38);
+    private final static Color APPLE_GOLDEN = new Color(164, 149, 56);
+    private final static Color BEEF_RAW = new Color(155, 48, 42);
+    private final static Color BEETROOT = new Color(144, 86, 69);
+    private final static Color BEETROOT_SEEDS = new Color(229, 221, 210);
+    //private final static Color BLAZE_POWDER = new Color(183, 100, 15); 
+    private final static Color CARROT = new Color(144, 121, 29);
+    private final static Color CARROT_GOLDEN = new Color(129, 104, 26);   
+    private final static Color CHICKEN_RAW = new Color(191, 148, 135);   
+    private final static Color FISH_CLOWNFISH_RAW = new Color(216, 170, 143, 255);
+    private final static Color FISH_COD_RAW = new Color(163, 180, 180);   
+    private final static Color FISH_SALMON_RAW = new Color(207, 188, 186, 255); 
+    //private final static Color MAGMA_CREAM = new Color(168, 118, 55);    
+    private final static Color MELON = new Color(155, 90, 46);
+    private final static Color MELON_SPECKLED = new Color(173, 114, 62);
+    private final static Color MUTTON_RAW = new Color(175, 60, 53);
+    private final static Color NETHER_WART = new Color(115, 27, 34, 255);
+    private final static Color PORKCHOP_RAW = new Color(202, 114, 114);
+    private final static Color POTATO = new Color(206, 169, 91);  
+    private final static Color RABBIT_FOOT = new Color(169, 130, 86);  
+    private final static Color RABBIT_RAW = new Color(213, 170, 155);
+    private final static Color SEEDS_MELON = new Color(57, 48, 23);
+    private final static Color SEEDS_PUMPKIN = new Color(201, 199, 146);
+    private final static Color SEEDS_WHEAT = new Color(61, 134, 27);
+    private final static Color SPIDER_EYE_FERMENTED = new Color(117, 44, 54);
+    private final static Color SUGAR = new Color(185, 185, 195); 
+    //private final static Color WHEAT = new Color(122, 125, 36);    
+    
+    private LinkedList<ItemStack> items;
+    private LinkedList<Color> colors;
+    private Color cachedColor; 
+
+    public CauldronColorMixer()
+    {
+        items = new LinkedList<>();
+        colors = new LinkedList<>();
+        reset();
+    }
+    
+    public final void reset(Color c)
+    {
+        cachedColor = c;
+        colors.clear();
+        items.clear();
+    }
+    
+    public final void reset()
+    {
+        reset(DEFAULT);
+    }
+    
+    public LinkedList<ItemStack> getItems()
+    {
+        return items;
+    }
+    
+    private Color getItemColor(ItemStack stack)
+    {
+        switch(Item.getIdFromItem(stack.getItem()))
+        {
+            case 86: return PUMPKIN;   
+            case 260: return APPLE;      
+            case 295: return SEEDS_WHEAT;
+            //case 296: return WHEAT;
+            case 319: return PORKCHOP_RAW;
+            case 322: return APPLE_GOLDEN;                
+            case 349:   
+                switch(ItemFishFood.FishType.byItemStack(stack))
+                {
+                    case CLOWNFISH:
+                        return FISH_CLOWNFISH_RAW;  
+                    case COD:
+                        return FISH_COD_RAW;  
+                    case PUFFERFISH:
+                        return POISON;
+                    case SALMON:
+                        return FISH_SALMON_RAW;
+                }
+                break;
+            case 353: return SUGAR;         
+            case 360: return MELON;
+            case 361: return SEEDS_PUMPKIN;
+            case 362: return SEEDS_MELON;
+            case 363: return BEEF_RAW;       
+            case 365: return CHICKEN_RAW;
+            case 372: return NETHER_WART;
+            case 394: // poison potato
+            case 375: return POISON; // spider eye
+            case 376: return SPIDER_EYE_FERMENTED;
+            //case 377: return BLAZE_POWDER;
+            //case 378: return MAGMA_CREAM;  
+            case 382: return MELON_SPECKLED;
+            case 391: return CARROT;
+            case 392: return POTATO; 
+            case 396: return CARROT_GOLDEN;
+            case 411: return RABBIT_RAW;
+            case 414: return RABBIT_FOOT;
+            case 423: return MUTTON_RAW;
+            case 434: return BEETROOT;
+            case 435: return BEETROOT_SEEDS;
+        }
+        return null;
+    }
+
+    public boolean addColor(ItemStack stack)
+    {
+        Color c = getItemColor(stack);
+        if(c == null)
+        {
+            return false;
+        }
+        colors.add(c);
+        ItemStack copy = stack.copy();
+        copy.setCount(1);
+        items.add(copy);
+        cachedColor = mixColors();
+        return true;
+    }
+    
+    public void cache()
+    {
+        if(items.isEmpty())
+        {
+            colors.clear();
+            cachedColor = DEFAULT;
+            return;
+        }
+        if(colors.size() != items.size())
+        {
+            colors.clear();
+            Color c;
+            for(ItemStack stack : items)
+            {
+                c = getItemColor(stack);
+                if(c != null)
+                {
+                    colors.add(c);
+                }
+            }
+        }
+        cachedColor = mixColors();
+    }
+
+    public Color getMixedColor()
+    {
+        return cachedColor;
+    }
+    
+    private Color mixColors()
+    {
+        int alpha = 0;
+        int red = 0;
+        int green = 0;
+        int blue = 0;
+        for(Color c : colors)
+        {
+            alpha += c.getAlpha();
+            red += c.getRed();
+            green += c.getGreen();
+            blue += c.getBlue();
+        }
+        if(!colors.isEmpty())
+        {
+            int size = colors.size();
+            alpha /= size;
+            red /= size;
+            green /= size;
+            blue /= size;
+        }
+        return new Color(red, green, blue, alpha);
+    }
+}

+ 27 - 7
src/main/java/me/km/blocks/ModBlocks.java

@@ -5,7 +5,6 @@ import me.km.fluids.BlockFluidHoney;
 import me.km.fluids.BlockFluidPoison;
 import me.km.fluids.ModFluids;
 import me.km.items.ItemMetal;
-import me.km.items.ModItems;
 import net.minecraft.block.Block;
 import net.minecraft.block.material.MapColor;
 import net.minecraft.block.material.Material;
@@ -50,6 +49,13 @@ public class ModBlocks
     public static BlockWoodCauldron cauldronSpruce;
     public static BlockWoodCauldron cauldronBigOak;
     
+    public static BlockBarrel barrelOak;
+    public static BlockBarrel barrelBirch;
+    public static BlockBarrel barrelAcacia;
+    public static BlockBarrel barrelJungle;
+    public static BlockBarrel barrelSpruce;
+    public static BlockBarrel barrelBigOak;
+    
     public static BlockCampFire campFire;
     public static BlockCampFireBurning campFireBurning;
     public static BlockCampFireBurnt campFireBurnt;
@@ -99,6 +105,13 @@ public class ModBlocks
         cauldronBigOak = register(r, new BlockWoodCauldron("cauldron_big_oak", "cauldronBigOak"));
         GameRegistry.registerTileEntity(TileEntityCauldron.class, "km:cauldron");
         
+        barrelOak = register(r, new BlockBarrel("barrel_oak", "barrelOak"));
+        barrelBirch = register(r, new BlockBarrel("barrel_birch", "barrelBirch"));
+        barrelAcacia = register(r, new BlockBarrel("barrel_acacia", "barrelAcacia"));
+        barrelJungle = register(r, new BlockBarrel("barrel_jungle", "barrelJungle"));
+        barrelSpruce = register(r, new BlockBarrel("barrel_spruce", "barrelSpruce"));
+        barrelBigOak = register(r, new BlockBarrel("barrel_big_oak", "barrelBigOak"));
+        
         campFire = register(r, new BlockCampFire("camp_fire", "campFire"));
         campFireBurning = (BlockCampFireBurning) register(r, new BlockCampFireBurning("camp_fire_burning", "campFireBurning")).setLightLevel(1);
         campFireBurnt = register(r, new BlockCampFireBurnt("camp_fire_burnt", "campFireBurnt"));
@@ -148,12 +161,19 @@ public class ModBlocks
         register(r, crateOak, getItemBlock(crateOak));
         register(r, crateSpruce, getItemBlock(crateSpruce));
         
-        cauldronOak.setItem(ModItems.cauldronOak);
-        cauldronBirch.setItem(ModItems.cauldronBirch);
-        cauldronAcacia.setItem(ModItems.cauldronAcacia);
-        cauldronJungle.setItem(ModItems.cauldronJungle);
-        cauldronSpruce.setItem(ModItems.cauldronSpruce);
-        cauldronBigOak.setItem(ModItems.cauldronBigOak);
+        register(r, cauldronAcacia, getItemBlock(cauldronAcacia));
+        register(r, cauldronBigOak, getItemBlock(cauldronBigOak));
+        register(r, cauldronBirch, getItemBlock(cauldronBirch));
+        register(r, cauldronJungle, getItemBlock(cauldronJungle));
+        register(r, cauldronOak, getItemBlock(cauldronOak));
+        register(r, cauldronSpruce, getItemBlock(cauldronSpruce));
+        
+        register(r, barrelAcacia, getItemBlock(barrelAcacia));
+        register(r, barrelBigOak, getItemBlock(barrelBigOak));
+        register(r, barrelBirch, getItemBlock(barrelBirch));
+        register(r, barrelJungle, getItemBlock(barrelJungle));
+        register(r, barrelOak, getItemBlock(barrelOak));
+        register(r, barrelSpruce, getItemBlock(barrelSpruce));
         
         // traps
         register(r, spikes, getItemMetal(spikes));

+ 71 - 32
src/main/java/me/km/blocks/TileEntityCauldron.java

@@ -1,7 +1,12 @@
 package me.km.blocks;
 
+import java.awt.Color;
+import java.util.LinkedList;
 import net.minecraft.block.state.IBlockState;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
 import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
 import net.minecraft.network.NetworkManager;
 import net.minecraft.network.play.server.SPacketUpdateTileEntity;
 import net.minecraft.tileentity.TileEntity;
@@ -10,26 +15,53 @@ import net.minecraft.world.World;
 
 public class TileEntityCauldron extends TileEntity
 {
-    private byte red;
-    private byte green;
-    private byte blue;
+    private CauldronColorMixer mixer;
     
     public TileEntityCauldron()
     {
-        red = -81;
-        green = -61;
-        blue = 116;
+        mixer = new CauldronColorMixer();
     }
     
     @Override
     public NBTTagCompound writeToNBT(NBTTagCompound com)
     {
         super.writeToNBT(com);
-        com.setByte("red", red);
-        com.setByte("green", green);
-        com.setByte("blue", blue);
+        
+        NBTTagList list = new NBTTagList();
+        LinkedList<ItemStack> items = mixer.getItems();
+        items.stream().forEach(stack -> 
+        {
+            NBTTagCompound nbttagcompound = new NBTTagCompound();
+            stack.writeToNBT(nbttagcompound);
+            list.appendTag(nbttagcompound);
+        });
+        
+        com.setTag("items", list);
         return com;
     }
+    
+    @Override
+    public void readFromNBT(NBTTagCompound com)
+    {
+        super.readFromNBT(com);
+        readItems(com);
+    }
+    
+    private void readItems(NBTTagCompound com)
+    {
+        if(com.hasKey("items", 9))
+        {
+            mixer.reset();
+            NBTTagList list = com.getTagList("items", 10);
+            LinkedList<ItemStack> items = mixer.getItems();
+            for(NBTBase base : list)
+            {
+                items.add(new ItemStack((NBTTagCompound) base));
+            }
+            
+            mixer.cache();
+        }
+    }
 
     @Override
     protected void setWorldCreate(World w)
@@ -37,35 +69,45 @@ public class TileEntityCauldron extends TileEntity
         this.setWorld(w);
     }
 
-    @Override
-    public void readFromNBT(NBTTagCompound com)
+    public boolean hasDefaultColor()
     {
-        super.readFromNBT(com);
-        red = com.getByte("red");
-        green = com.getByte("green");
-        blue = com.getByte("blue");
+        return mixer.getItems().isEmpty();
     }
-
-    public int getRed() 
+    
+    public int getNumberOfIngredients()
     {
-        return red + 128;
+        return mixer.getItems().size();
     }
-
-    public int getGreen() 
+    
+    public LinkedList<ItemStack> getIngredients()
     {
-        return green + 128;
+        return mixer.getItems();
     }
-
-    public int getBlue() 
+    
+    public Color getColor() 
+    {
+        return mixer.getMixedColor();
+    }
+    
+    public void reset()
+    {
+        mixer.reset();
+    }
+    
+    public boolean addItemStack(ItemStack stack)
     {
-        return blue + 128;
+        boolean b = mixer.addColor(stack);
+        if(b)
+        {
+            notifyBlockUpdate();
+            markDirty();
+        }
+        return b;
     }
 
     public void setColor(int red, int green, int blue)
     {
-        this.red = (byte) ((red & 0xFF) - 128);
-        this.green = (byte) ((green & 0xFF) - 128);
-        this.blue = (byte) ((blue & 0xFF) - 128);
+        mixer.reset(new Color(red, green, blue));
         notifyBlockUpdate();
         markDirty();
     }
@@ -85,17 +127,14 @@ public class TileEntityCauldron extends TileEntity
     @Override
     public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) 
     {
-        NBTTagCompound com = pkt.getNbtCompound();
-        red = com.getByte("red");
-        green = com.getByte("green");
-        blue = com.getByte("blue");
+        readItems(pkt.getNbtCompound());
         notifyBlockUpdate();
     }
 
     @Override
     public NBTTagCompound getUpdateTag()
     {
-        return this.writeToNBT(new NBTTagCompound());
+        return writeToNBT(new NBTTagCompound());
     }
     
     @Override

+ 18 - 1
src/main/java/me/km/effects/Effect.java

@@ -60,10 +60,15 @@ public enum Effect
     USE_WAND                ,
     LESS_ITEM_LOSS          ,
     NO_ARMOR_DROPPING       ,
+    DODGE                   ,
+    BLOOD_THIRST            ,
     
     // active effects
     POISON_VOLLEY           (new PoisonVolley()),
+    STRONG_STUN_PUNCH       (new StrongStunPunch()),
+    IGNORANCE               (new Ignorance()),
     FIRE                    (new Fire()),
+    ARMOR_BOOST             (new ArmorBoost()),
     SHADOW_STEP             (new ShadowStep()),
     BLINDING_SHOT           (new BlindingShot()),
     KICK                    (new Kick()),
@@ -89,20 +94,24 @@ public enum Effect
     NAIL_TRAP               (new NailTrap()),
     NIGHT                   (new Night()),
     AREA_DAMAGE             (new AreaDamage()),
+    SILENCE_PUNCH           (new SilencePunch()),
     EARTHQUAKE              (new Earthquake()),
     FIREBALL                (new Fireball()),
     JUMP                    (new Jump()),
+    STUN_PUNCH              (new StunPunch()),
     PUSH_UP                 (new PushUp()),
     THOR                    (new Thor()),
     GRAPPLING_HOOK          (new GrapplingHook()),
     QUICK_SHOT              (new QuickShot()),
     CALL_BACK               (new CallBack()),
+    THORNS                  (new Thorns()),
     SHADOW_HIT              (new ShadowHit()),
     LOCK_PICK               (new LockPick()),
     HEART_SEEKER            (new HeartSeeker()),
     TELEPORT_PLAYER         (new TeleportPlayer()),
     SPRINT                  (new Sprint()),
     LIFE_BREAKER            (new LifeBreaker()),
+    TIMED_HEAL              (new TimedHeal()),
     POWER                   (new Power()),
     MUSKET                  (new Musket()),
     HEARTS                  (new Hearts()),
@@ -115,23 +124,30 @@ public enum Effect
     LIFE_STEAL              (new LifeSteal()),
     SHADOW                  (new Shadow()),
     SLOWING_SHOT            (new SlowingShot()),
+    WAR_CALL                (new WarCall()),
     VINE_TRAP               (new VineTrap()),
     RAPID_FIRE              (new RapidFire()),
     STONE                   (new Stone()),
     FIRE_PROTECTION_RAIN    (new FireProtectionRain()),
     BONE_BREAKER            (new BoneBreaker()),
+    PULL_ATTACK             (new PullAttack()),
     ARCANE_SHOT             (new ArcaneShot()),
     RAIN                    (new Rain()),
     INVISIBILITY            (new Invisibility()),
+    REVENGE                 (new Revenge()),
     DAY                     (new Day()),
     FLYING                  (new Flying()),
     EXPLOSION               (new Explosion()),
     SMOKE_BOMB              (new SmokeBomb()),
+    CHARGE                  (new Charge()),
     HARVEST                 (new Harvest()),
     FREEZE                  (new Freeze()),
     FALL_IMMUNITY           (new FallImmunity()),
+    DISARM                  (new Disarm()),
     BLOCK_EXPLOSION         (new BlockExplosion()),
+    BLADE_STORM             (new BladeStorm()),
     ELVISH_HORN             (new ElvishHorn()),
+    SHIELD                  (new Shield()),
     GRAVITY                 (new Gravity()),
     TELEPORT_BLOCK          (new TeleportBlock()),
     CLUSTER_BOMB            (new ClusterBomb()),
@@ -139,7 +155,8 @@ public enum Effect
     SILENCE                 (new Silence()),
     POWER_ATTACK            (new PowerAttack()),
     HEAL                    (new Heal()),
-    JUMP_ATTACK             (new JumpAttack());
+    JUMP_ATTACK             (new JumpAttack()),
+    DRAGON_SKIN             (new DragonSkin());
     
     private static Effect[] effects = Effect.values();
     

+ 19 - 0
src/main/java/me/km/effects/active/ArmorBoost.java

@@ -0,0 +1,19 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class ArmorBoost extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        if(!KajetansMod.playerbank.getData(p).hasData("armorboost"))
+        {
+            KajetansMod.playerbank.getData(p).addGoodTimedData("armorboost", 1.2f, power * 20, " + 20 % Armor", 200);
+            return true;
+        }
+        return false;
+    }
+}

+ 34 - 0
src/main/java/me/km/effects/active/BladeStorm.java

@@ -0,0 +1,34 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.EnumParticleTypes;
+import net.minecraft.world.WorldServer;
+
+public class BladeStorm extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        WorldServer w = p.getServerWorld();
+        DamageSource ds = DamageSource.causePlayerDamage(p);
+        
+        for(int i = 1; i < 6; i++)
+        {
+            KajetansMod.scheduler.scheduleTask(() -> 
+            {
+                EffectUtils.spawnParticleCircle(w, p, EnumParticleTypes.SWEEP_ATTACK, 3, 12);
+                EffectUtils.spawnParticleCircle(w, p, EnumParticleTypes.SWEEP_ATTACK, 2, 12);
+                EffectUtils.spawnParticleCircle(w, p, EnumParticleTypes.SWEEP_ATTACK, 1, 12);
+                EffectUtils.getEntsOfNotGuild(p, 3).stream().forEach((m) -> 
+                {
+                    m.attackEntityFrom(ds, power);                           
+                });
+            }, 10 * i);
+        }
+        return true;
+    } 
+}

+ 17 - 0
src/main/java/me/km/effects/active/Charge.java

@@ -0,0 +1,17 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.math.Vec3d;
+
+public class Charge extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        Vec3d v = p.getLookVec().scale(1 + (power / 20f));
+        Utils.addVelocity(p, v.x, v.y, v.z);
+        return true;
+    }
+}

+ 3 - 3
src/main/java/me/km/effects/active/Cripple.java

@@ -2,10 +2,10 @@ package me.km.effects.active;
 
 import me.km.api.Utils;
 import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
 import net.minecraft.entity.EntityLivingBase;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.init.MobEffects;
-import net.minecraft.potion.PotionEffect;
 
 public class Cripple extends ActiveEffectBase
 {
@@ -17,8 +17,8 @@ public class Cripple extends ActiveEffectBase
         {
             return false;
         }
-        liv.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, power * 20, 2));
-        liv.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, power * 20, 1));
+        EffectUtils.addPotionTo(liv, MobEffects.SLOWNESS, power * 20, 2);
+        EffectUtils.addPotionTo(liv, MobEffects.NAUSEA, power * 20, 1);
         return true;
     }
 }

+ 25 - 0
src/main/java/me/km/effects/active/Disarm.java

@@ -0,0 +1,25 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.MobEffects;
+import net.minecraft.util.DamageSource;
+
+public class Disarm extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        EntityLivingBase liv = Utils.getTargetedEntity(p, 4, EntityLivingBase.class);
+        if(liv == null)
+        {
+            return false;
+        }
+        liv.attackEntityFrom(DamageSource.causePlayerDamage(p), 0.125f);
+        EffectUtils.addPotionTo(liv, MobEffects.WEAKNESS, 20 * power, 50);
+        return true;
+    }
+}

+ 19 - 0
src/main/java/me/km/effects/active/DragonSkin.java

@@ -0,0 +1,19 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class DragonSkin extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        if(!KajetansMod.playerbank.getData(p).hasData("dragonskin"))
+        {
+            KajetansMod.playerbank.getData(p).addGoodTimedData("dragonskin", true, power * 20, "Dragon Skin", 202);
+            return true;
+        }
+        return false;
+    }
+}

+ 0 - 1
src/main/java/me/km/effects/active/Earthquake.java

@@ -5,7 +5,6 @@ import me.km.effects.EffectUtils;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.util.DamageSource;
 import net.minecraft.util.EnumParticleTypes;
-import net.minecraft.util.math.Vec3d;
 import net.minecraft.world.WorldServer;
 
 public class Earthquake extends ActiveEffectBase

+ 1 - 1
src/main/java/me/km/effects/active/Flying.java

@@ -15,7 +15,7 @@ public class Flying extends ActiveEffectBase
         EffectUtils.playSound(p, SoundEvents.ENTITY_FIREWORK_LAUNCH);
         EffectUtils.spawnSpell(p, power);
         Vec3d v = p.getLookVec().scale(1 + (power / 20f));
-        Utils.setVelocity(p, v.x, v.y, v.z);
+        Utils.addVelocity(p, v.x, v.y, v.z);
         return true;
     }
 }

+ 19 - 0
src/main/java/me/km/effects/active/Ignorance.java

@@ -0,0 +1,19 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class Ignorance extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        if(!KajetansMod.playerbank.getData(p).hasData("ignorance"))
+        {
+            KajetansMod.playerbank.getData(p).addGoodTimedData("ignorance", true, power * 60, "Ignorance", 204);
+            return true;
+        }
+        return false;
+    }
+}

+ 2 - 2
src/main/java/me/km/effects/active/Kick.java

@@ -2,10 +2,10 @@ package me.km.effects.active;
 
 import me.km.api.Utils;
 import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
 import net.minecraft.entity.EntityLivingBase;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.init.MobEffects;
-import net.minecraft.potion.PotionEffect;
 import net.minecraft.util.math.Vec3d;
 
 public class Kick extends ActiveEffectBase
@@ -20,7 +20,7 @@ public class Kick extends ActiveEffectBase
         }
         Vec3d v = liv.getPositionVector().subtract(p.getPositionVector()).normalize().scale(2).addVector(0, 0.4, 0);
         Utils.setVelocity(liv, v.x, v.y, v.z);
-        liv.addPotionEffect(new PotionEffect(MobEffects.NAUSEA, 120, 10));
+        EffectUtils.addPotionTo(liv, MobEffects.NAUSEA, 120, 10);
         return true;
     }
 }

+ 2 - 2
src/main/java/me/km/effects/active/Lucky.java

@@ -1,16 +1,16 @@
 package me.km.effects.active;
 
 import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.init.MobEffects;
-import net.minecraft.potion.PotionEffect;
 
 public class Lucky extends ActiveEffectBase
 {
     @Override
     protected boolean executeEffect(EntityPlayerMP p, int power) 
     {
-        p.addPotionEffect(new PotionEffect(MobEffects.LUCK, 200 + 200 * power, 9));
+        EffectUtils.addPotionTo(p, MobEffects.LUCK, 200 + 200 * power, 9);
         return true;
     }
 }

+ 30 - 0
src/main/java/me/km/effects/active/PullAttack.java

@@ -0,0 +1,30 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.math.Vec3d;
+
+public class PullAttack extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        Vec3d v = p.getPositionVector();
+        EffectUtils.getEntsOfNotGuild(p, power + 2).stream().forEach(ent -> 
+        {
+            Vec3d v2 = v.subtract(ent.getPositionVector()).normalize();
+            Utils.setVelocity(ent, v2.x, v2.y, v2.z);
+            if(ent instanceof EntityPlayerMP)
+            {
+                ((EntityPlayerMP) ent).attackTargetEntityWithCurrentItem(p);
+            }
+            else
+            {
+                ent.setRevengeTarget(p);
+            }
+        });
+        return true;
+    }
+}

+ 24 - 0
src/main/java/me/km/effects/active/Revenge.java

@@ -0,0 +1,24 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.util.DamageSource;
+
+public class Revenge extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        EntityLivingBase liv = Utils.getTargetedEntity(p, 4, EntityLivingBase.class);
+        if(liv == null)
+        {
+            return false;
+        }
+        float damage = power;
+        damage *= liv.getMaxHealth() / liv.getHealth();
+        liv.attackEntityFrom(DamageSource.causePlayerDamage(p), damage);
+        return true;
+    }
+}

+ 30 - 0
src/main/java/me/km/effects/active/Shield.java

@@ -0,0 +1,30 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.api.GlobalText;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class Shield extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        if(!KajetansMod.playerbank.getData(p).hasData("armorboost"))
+        {
+            KajetansMod.playerbank.getData(p).addGoodTimedData("armorboost", 1.4f, 200, " + 40 % Armor", 200);
+        }
+        try
+        {
+            EffectUtils.getPlayersOfGuild(p, power + 2).stream()
+                    .filter(pl -> !KajetansMod.playerbank.getData((EntityPlayerMP) pl).hasData("armorboost"))
+                    .forEach(pl -> KajetansMod.playerbank.getData((EntityPlayerMP) pl).addGoodTimedData("armorboost", 1.4f, 200, " + 40 % Armor", 200));
+        }
+        catch(ClassCastException ex)
+        {
+            System.out.println(GlobalText.shouldNotHappen());
+        }
+        return true;
+    }
+}

+ 4 - 0
src/main/java/me/km/effects/active/Silence.java

@@ -15,6 +15,10 @@ public class Silence extends ActiveEffectBase
         {
             return false;
         }
+        if(KajetansMod.playerbank.getData(affectedPlayer).hasData("ignorance"))
+        {
+            return true;
+        }
         KajetansMod.playerbank.getData(affectedPlayer).addBadTimedData("silence", 0, 60 * power, "Silence", 50);
         return true;
     }

+ 25 - 0
src/main/java/me/km/effects/active/SilencePunch.java

@@ -0,0 +1,25 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.MobEffects;
+
+public class SilencePunch extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        EntityPlayerMP affectedPlayer = Utils.getTargetedEntity(p, 4, EntityPlayerMP.class);
+        if(affectedPlayer == null)
+        {
+            return false;
+        }
+        power *= 20;
+        EffectUtils.addPotionTo(p, MobEffects.NAUSEA, power, 0);
+        KajetansMod.playerbank.getData(affectedPlayer).addBadTimedData("silence", 0, power, "Silence", 50);
+        return true;
+    }
+}

+ 26 - 0
src/main/java/me/km/effects/active/StrongStunPunch.java

@@ -0,0 +1,26 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.MobEffects;
+import net.minecraft.util.DamageSource;
+
+public class StrongStunPunch extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        EntityLivingBase liv = Utils.getTargetedEntity(p, 4, EntityLivingBase.class);
+        if(liv == null)
+        {
+            return false;
+        }
+        liv.attackEntityFrom(DamageSource.causePlayerDamage(p), 0.125f);
+        EffectUtils.addPotionTo(liv, MobEffects.SLOWNESS, 20 * power, 50);
+        EffectUtils.addPotionTo(liv, MobEffects.JUMP_BOOST, 20 * power, 128);
+        return true;
+    }
+}

+ 25 - 0
src/main/java/me/km/effects/active/StunPunch.java

@@ -0,0 +1,25 @@
+package me.km.effects.active;
+
+import me.km.api.Utils;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.MobEffects;
+import net.minecraft.util.DamageSource;
+
+public class StunPunch extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        EntityLivingBase liv = Utils.getTargetedEntity(p, 4, EntityLivingBase.class);
+        if(liv == null)
+        {
+            return false;
+        }
+        liv.attackEntityFrom(DamageSource.causePlayerDamage(p), 0.125f);
+        EffectUtils.addPotionTo(liv, MobEffects.SLOWNESS, 10 * power, 50);
+        return true;
+    }
+}

+ 19 - 0
src/main/java/me/km/effects/active/Thorns.java

@@ -0,0 +1,19 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class Thorns extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        if(!KajetansMod.playerbank.getData(p).hasData("thorns"))
+        {
+            KajetansMod.playerbank.getData(p).addGoodTimedData("thorns", 0.3f, power * 20, "30% Thorns", 203);
+            return true;
+        }
+        return false;
+    }
+}

+ 19 - 0
src/main/java/me/km/effects/active/TimedHeal.java

@@ -0,0 +1,19 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.effects.ActiveEffectBase;
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class TimedHeal extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        float amount = (p.getMaxHealth() * power) / 100F;
+        for(int i = 1; i < 6; i++)
+        {
+            KajetansMod.scheduler.scheduleTask(() -> p.heal(amount), i * 20);
+        }
+        return true;
+    }
+}

+ 2 - 1
src/main/java/me/km/effects/active/Unlucky.java

@@ -1,6 +1,7 @@
 package me.km.effects.active;
 
 import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.init.MobEffects;
 import net.minecraft.potion.PotionEffect;
@@ -10,7 +11,7 @@ public class Unlucky extends ActiveEffectBase
     @Override
     protected boolean executeEffect(EntityPlayerMP p, int power) 
     {
-        p.addPotionEffect(new PotionEffect(MobEffects.UNLUCK, 200 + 200 * power, 9));
+        EffectUtils.addPotionTo(p, MobEffects.UNLUCK, 200 + 200 * power, 9);
         return true;
     }
 }

+ 31 - 0
src/main/java/me/km/effects/active/WarCall.java

@@ -0,0 +1,31 @@
+package me.km.effects.active;
+
+import me.km.KajetansMod;
+import me.km.api.GlobalText;
+import me.km.effects.ActiveEffectBase;
+import me.km.effects.EffectUtils;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.MobEffects;
+import net.minecraft.init.SoundEvents;
+
+public class WarCall extends ActiveEffectBase
+{
+    @Override
+    protected boolean executeEffect(EntityPlayerMP p, int power) 
+    {
+        try
+        {
+            EffectUtils.playSound(p, SoundEvents.ENTITY_GHAST_SCREAM);
+            EffectUtils.getPlayersOfGuild(p, power + 2).forEach(pl -> 
+            {
+                EffectUtils.addPotionTo(p, MobEffects.FIRE_RESISTANCE, 300, 0);
+                KajetansMod.playerbank.getData((EntityPlayerMP) pl).addGoodTimedData("magicarmorboost", 1.2f, 300, " + 20 % Magic Armor", 201);
+            });
+        }
+        catch(ClassCastException ex)
+        {
+            System.out.println(GlobalText.shouldNotHappen());
+        }
+        return true;
+    }
+}

+ 19 - 1
src/main/java/me/km/effects/passive/ArrowEffects.java

@@ -11,6 +11,7 @@ import me.km.effects.EffectUtils;
 import me.km.events.ArrowHitGroundEvent;
 import me.km.events.ArrowLaunchEvent;
 import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityLivingBase;
 import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.entity.projectile.EntityArrow;
@@ -23,6 +24,7 @@ import net.minecraft.util.EnumParticleTypes;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.WorldServer;
 import net.minecraftforge.event.entity.ThrowableImpactEvent;
+import net.minecraftforge.event.entity.living.LivingAttackEvent;
 import net.minecraftforge.event.entity.living.LivingHurtEvent;
 import net.minecraftforge.event.entity.player.ArrowLooseEvent;
 import net.minecraftforge.fml.common.eventhandler.EventPriority;
@@ -61,7 +63,7 @@ public class ArrowEffects extends ModuleListener
     @SubscribeEvent(receiveCanceled = false, priority = EventPriority.LOW)
     public void handleHurtShots(LivingHurtEvent e)
     {        
-        Entity ent = e.getEntity();
+        EntityLivingBase ent = e.getEntityLiving();
         if(!KajetansMod.worldManager.getWorldPreferences(ent.world).skills)
         {
             return;
@@ -80,6 +82,22 @@ public class ArrowEffects extends ModuleListener
         }
     }
     
+    @SubscribeEvent(receiveCanceled = false)
+    public void handleDragonSkin(LivingAttackEvent e)
+    {        
+        EntityLivingBase liv = e.getEntityLiving();
+        if(!KajetansMod.worldManager.getWorldPreferences(liv.world).skills || !(liv instanceof EntityPlayerMP))
+        {
+            return;
+        }
+        Entity ent = e.getSource().getImmediateSource();
+        if(ent instanceof EntityArrow && KajetansMod.playerbank.getData((EntityPlayerMP) liv).hasData("dragonskin"))
+        {
+            e.setCanceled(true);
+            Utils.scaleVelocity(ent, -0.1);
+        }
+    }
+    
     private void runArrowEffects(EntityArrow arrow)
     {
         EntityPlayer player = Utils.getPlayerFromProjectile(arrow);

+ 75 - 2
src/main/java/me/km/effects/passive/EntityDamageEffects.java

@@ -12,11 +12,14 @@ import me.km.playerbank.PlayerData;
 import me.km.utils.ReflectionUtils;
 import net.minecraft.entity.Entity;
 import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.SharedMonsterAttributes;
 import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.entity.player.EntityPlayerMP;
 import net.minecraft.init.MobEffects;
 import net.minecraft.util.CombatRules;
 import net.minecraft.util.DamageSource;
+import net.minecraftforge.event.entity.living.LivingAttackEvent;
+import net.minecraftforge.event.entity.living.LivingDeathEvent;
 import net.minecraftforge.event.entity.living.LivingHealEvent;
 import net.minecraftforge.event.entity.living.LivingHurtEvent;
 import net.minecraftforge.fml.common.eventhandler.EventPriority;
@@ -189,11 +192,48 @@ public class EntityDamageEffects extends ModuleListener
                 if(ds.isMagicDamage() && !ds.isDamageAbsolute())
                 {
                     ReflectionUtils.damageArmor(liv, damageAmount);
-                    damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, DamageUtils.getMagicDefense(liv), 0);
+                    int armor = DamageUtils.getMagicDefense(liv);
+                    if(liv instanceof EntityPlayerMP)
+                    {
+                        Float f = KajetansMod.playerbank.getData((EntityPlayerMP) liv).getData("magicarmorboost", Float.class);
+                        if(f != null)
+                        {
+                            armor = Math.round(armor * f);
+                        }
+                    }
+                    damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, armor, 0);
                 }
                 else
                 {
-                    damageAmount = ReflectionUtils.applyArmorCalculations(liv, ds, damageAmount);
+                    if(!ds.isUnblockable())
+                    {
+                        ReflectionUtils.damageArmor(liv, damageAmount);
+                        int armor = liv.getTotalArmorValue();
+                        Float thorns = null;
+                        if(liv instanceof EntityPlayerMP)
+                        {
+                            Float f = KajetansMod.playerbank.getData((EntityPlayerMP) liv).getData("armorboost", Float.class);
+                            thorns = KajetansMod.playerbank.getData((EntityPlayerMP) liv).getData("thorns", Float.class);
+                            if(f != null)
+                            {
+                                armor = Math.round(armor * f);
+                            }
+                        }
+                        damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, armor, 
+                                (float) liv.getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).getAttributeValue());
+                        // physical damage - doing thorns here
+                        if(thorns != null)
+                        {
+                            Entity ent = ds.getImmediateSource();
+                            if(ent != null)
+                            {
+                                DamageSource reflect = DamageSource.causePlayerDamage((EntityPlayerMP) liv);
+                                reflect.setMagicDamage();
+                                ent.attackEntityFrom(reflect, thorns * damageAmount);
+                            }
+                        }
+                        // end of thorns
+                    }
                 }           
                 damageAmount = ReflectionUtils.applyPotionDamageCalculations(liv, ds, damageAmount);
             }
@@ -216,6 +256,39 @@ public class EntityDamageEffects extends ModuleListener
         }
     }
     
+    @SubscribeEvent(receiveCanceled = false)
+    public void handleDodging(LivingAttackEvent e)
+    {        
+        EntityLivingBase liv = e.getEntityLiving();
+        if(!KajetansMod.worldManager.getWorldPreferences(liv.world).skills || !(liv instanceof EntityPlayerMP))
+        {
+            return;
+        }
+        int dodge = EffectUtils.getEffectLevel((EntityPlayerMP) liv, Effect.DODGE);
+        if(dodge > 0 && liv.getRNG().nextInt(20) + 1 <= dodge)
+        {
+            e.setCanceled(true);
+        }
+    }
+    
+    @SubscribeEvent
+    public void handleBloodThirst(LivingDeathEvent e)
+    {        
+        EntityLivingBase liv = e.getEntityLiving();
+        if(!KajetansMod.worldManager.getWorldPreferences(liv.world).skills)
+        {
+            return;
+        }
+        float heal = liv instanceof EntityPlayer ? 30 : 6;
+        Utils.getPlayers(liv, 5).forEach(p -> 
+        {
+            if(EffectUtils.getEffectLevel(p, Effect.BLOOD_THIRST) >= 1)
+            {
+                p.heal(heal);
+            }
+        });
+    }
+    
     @SubscribeEvent(receiveCanceled = false)
     public void onEntityHeal(LivingHealEvent e)
     {         

+ 1 - 5
src/main/java/me/km/entities/EntityHuman.java

@@ -178,7 +178,7 @@ public class EntityHuman extends EntityCreature implements IEntityAdditionalSpaw
             this.setDead();
             return false;
         }
-        if(!KajetansMod.singlePlayer)
+        if(!world.isRemote)
         {
             Entity ent = source.getTrueSource();
             if(ent instanceof EntityPlayer)
@@ -186,10 +186,6 @@ public class EntityHuman extends EntityCreature implements IEntityAdditionalSpaw
                 KajetansMod.scripts.getEvent(ScriptEvents.class).onHumanHurt((EntityPlayer) ent, this);
             }
         }
-        else
-        {
-            this.setDead();
-        }
         return false;
     }
 

+ 229 - 0
src/main/java/me/km/entities/EntityNobody.java

@@ -0,0 +1,229 @@
+package me.km.entities;
+
+import net.minecraft.block.material.Material;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.MoverType;
+import net.minecraft.entity.effect.EntityLightningBolt;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.SoundEvent;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.world.World;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+
+public class EntityNobody extends Entity
+{
+    public EntityNobody(World w)
+    {
+        super(w);
+    }
+
+    @Override
+    public void onUpdate()
+    {
+        this.onEntityUpdate();
+    }
+
+    @Override
+    public void onEntityUpdate()
+    {
+        this.world.profiler.startSection("entityBaseTick");
+
+        if(this.isRiding() && this.getRidingEntity().isDead)
+        {
+            this.dismountRidingEntity();
+        }
+
+        if(this.rideCooldown > 0)
+        {
+            --this.rideCooldown;
+        }
+
+        if(this.posY < -64.0D)
+        {
+            this.outOfWorld();
+        }
+
+        this.firstUpdate = false;
+        this.world.profiler.endSection();
+    }
+
+    @Override
+    public void move(MoverType type, double x, double y, double z)
+    {
+    }
+
+    @Override
+    protected void doBlockCollisions()
+    {
+    }
+
+    @Override
+    public void playSound(SoundEvent soundIn, float volume, float pitch)
+    {
+    }
+
+    @Override
+    public boolean isSilent()
+    {
+        return true;
+    }
+
+    @Override
+    public void setSilent(boolean isSilent)
+    {
+    }
+
+    @Override
+    public boolean hasNoGravity()
+    {
+        return true;
+    }
+
+    @Override
+    public void setNoGravity(boolean noGravity)
+    {
+    }
+
+    @Override
+    protected boolean canTriggerWalking()
+    {
+        return false;
+    }
+
+    @Override
+    protected void updateFallState(double y, boolean onGroundIn, IBlockState state, BlockPos pos)
+    {
+    }
+
+    @Override
+    protected void dealFireDamage(int amount)
+    {
+    }
+
+    @Override
+    public boolean isWet()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isInWater()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isOverWater()
+    {
+        return false;
+    }
+
+    @Override
+    public boolean handleWaterMovement()
+    {
+        return false;
+    }
+
+    @Override
+    protected void doWaterSplashEffect()
+    {
+    }
+
+    @Override
+    public void spawnRunningParticles()
+    {
+    }
+
+    @Override
+    protected void createRunningParticles()
+    {
+    }
+
+    @Override
+    public boolean isInsideOfMaterial(Material materialIn)
+    {
+        return false;
+    }
+
+    @Override
+    public boolean isInLava()
+    {
+        return false;
+    }
+
+    @Override
+    public void moveRelative(float strafe, float up, float forward, float friction)
+    {
+    }
+
+    @SideOnly(Side.CLIENT)
+    @Override
+    public int getBrightnessForRender()
+    {
+        return 0;
+    }
+
+    @Override
+    public float getBrightness()
+    {
+        return 0;
+    }
+
+    @Override
+    public void applyEntityCollision(Entity entityIn)
+    {
+    }
+
+    @Override
+    public void addVelocity(double x, double y, double z)
+    {
+    }
+
+    @Override
+    public void setPortal(BlockPos pos)
+    {
+    }
+
+    @Override
+    public void onStruckByLightning(EntityLightningBolt lightningBolt)
+    {
+    }
+
+    @Override
+    protected boolean pushOutOfBlocks(double x, double y, double z)
+    {
+        return false;
+    }
+
+    @Override
+    public String getName()
+    {
+        if(this.hasCustomName())
+        {
+            return this.getCustomNameTag();
+        }
+        return "Nobody";
+    }
+
+    @Override
+    public boolean isPushedByWater()
+    {
+        return true;
+    }
+
+    @Override
+    protected void entityInit() {
+    }
+
+    @Override
+    protected void readEntityFromNBT(NBTTagCompound compound) 
+    {
+    }
+
+    @Override
+    protected void writeEntityToNBT(NBTTagCompound compound) 
+    {
+    }
+}

+ 2 - 1
src/main/java/me/km/entities/ModEntities.java

@@ -1,7 +1,6 @@
 package me.km.entities;
 
 import me.km.KajetansMod;
-import net.minecraft.client.Minecraft;
 import net.minecraft.client.renderer.entity.Render;
 import net.minecraft.entity.Entity;
 import net.minecraft.util.ResourceLocation;
@@ -16,6 +15,7 @@ public class ModEntities
         register(1, EntityBrownBear.class, "BrownBear", "bear/brownbear");
         register(2, EntityBlackBear.class, "BlackBear", "bear/blackbear");
         register(3, EntityHuman.class, "Human", "human");
+        register(4, EntityNobody.class, "Nobody", "nobody");
     }
     
     @SideOnly(Side.CLIENT)
@@ -24,6 +24,7 @@ public class ModEntities
         register(1, EntityBrownBear.class, "BrownBear", "bear/brownbear", new RenderBrownBear());
         register(2, EntityBlackBear.class, "BlackBear", "bear/blackbear", new RenderBlackBear());
         register(3, EntityHuman.class, "Human", "human", new RenderHuman());
+        register(4, EntityNobody.class, "Nobody", "nobody", new RenderNobody());
     }
 
     @SideOnly(Side.CLIENT)

+ 1 - 1
src/main/java/me/km/entities/ModelHuman.java

@@ -17,7 +17,7 @@ public class ModelHuman extends ModelPlayer
         this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, ent);
         GlStateManager.pushMatrix();
         
-        if (ent.isSneaking())
+        if(ent.isSneaking())
         {
             GlStateManager.translate(0.0F, 0.2F, 0.0F);
         }

+ 29 - 0
src/main/java/me/km/entities/RenderNobody.java

@@ -0,0 +1,29 @@
+package me.km.entities;
+
+import me.km.KajetansMod;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.entity.Render;
+import net.minecraft.util.ResourceLocation;
+
+public class RenderNobody extends Render<EntityNobody>
+{
+    private static final ResourceLocation LOC = new ResourceLocation(KajetansMod.MODID, "nobody");
+    
+    public RenderNobody()
+    {
+        super(Minecraft.getMinecraft().getRenderManager());
+        super.setRenderOutlines(false);
+    }
+    
+    @Override
+    protected ResourceLocation getEntityTexture(EntityNobody entity) 
+    {
+        return LOC;
+    }
+    
+    @Override
+    protected boolean canRenderName(EntityNobody entity)
+    {
+        return true;
+    }
+}

+ 272 - 0
src/main/java/me/km/items/ItemColoredSoup.java

@@ -0,0 +1,272 @@
+package me.km.items;
+
+import java.util.LinkedList;
+import java.util.List;
+import me.km.blocks.CauldronColorMixer;
+import net.minecraft.client.util.ITooltipFlag;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.init.MobEffects;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemFishFood;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.nbt.NBTTagString;
+import net.minecraft.potion.PotionEffect;
+import net.minecraft.util.text.TextFormatting;
+import net.minecraft.util.text.translation.I18n;
+import net.minecraft.world.World;
+import net.minecraftforge.common.capabilities.ICapabilityProvider;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+
+public class ItemColoredSoup extends ItemFood
+{
+    public ItemColoredSoup(String name, String local) 
+    {
+        super(name, local, 0, 0, false);
+        super.setMaxStackSize(1);
+    }
+
+    @Override
+    public ItemStack onItemUseFinish(ItemStack stack, World w, EntityLivingBase liv)
+    {
+        super.onItemUseFinish(stack, w, liv);
+        return new ItemStack(Items.BOWL);
+    }
+
+    @Override
+    public ICapabilityProvider initCapabilities(ItemStack stack, NBTTagCompound nbt) 
+    {
+        getTagCompound(stack);
+        return null;
+    }  
+    
+    @SideOnly(Side.CLIENT)
+    @Override
+    public void addInformation(ItemStack stack, World w, List<String> lore, ITooltipFlag flag) 
+    {
+        String text = getLocalizedIngredientList(stack);
+        if(!text.isEmpty())
+        {
+            lore.add(1, text);
+        }
+    }
+    
+    private NBTTagCompound getTagCompound(ItemStack stack)
+    {
+        NBTTagCompound com = stack.getTagCompound();
+        if(com == null)
+        {
+            com = new NBTTagCompound();
+            com.setInteger("color", CauldronColorMixer.DEFAULT.getRGB());
+            com.setTag("ingredients", new NBTTagList());
+            com.setFloat("saturation", 0);
+            com.setInteger("food", 0);
+            stack.setTagCompound(com);
+        }
+        else
+        {
+            if(!com.hasKey("color"))
+            {
+                com.setInteger("color", CauldronColorMixer.DEFAULT.getRGB());   
+            }
+            if(!com.hasKey("ingredients", 9))
+            {
+                com.setTag("ingredients", new NBTTagList());   
+            }
+            if(!com.hasKey("saturation"))
+            {
+                com.setFloat("saturation", 0);   
+            }
+            if(!com.hasKey("food"))
+            {
+                com.setInteger("food", 0);   
+            }
+        }
+        return com;
+    }
+    
+    @SuppressWarnings(value = "")
+    public void addIngredient(ItemStack stew, Iterable<ItemStack> stacks)     
+    {
+        NBTTagCompound com = stew.getTagCompound();
+        NBTTagList list = com.getTagList("ingredients", 8);
+        for(ItemStack stack : stacks)
+        {
+            list.appendTag(new NBTTagString(stack.getUnlocalizedName() + ".name"));
+        }
+    }
+    
+    @SideOnly(Side.CLIENT)
+    @SuppressWarnings(value = "")
+    public String getLocalizedIngredientList(ItemStack stack)
+    {
+        NBTTagCompound com = stack.getTagCompound();
+        NBTTagList list = com.getTagList("ingredients", 8);
+        switch(list.tagCount())
+        {
+            case 0: return "";
+            case 1: return TextFormatting.GRAY + I18n.translateToLocal(list.getStringTagAt(0));
+            default:
+                StringBuilder sb = new StringBuilder(TextFormatting.GRAY.toString());
+                sb.append(I18n.translateToLocal(list.getStringTagAt(0)));
+                for(int i = 1; i < list.tagCount(); i++)
+                {
+                    sb.append(", ");
+                    sb.append(I18n.translateToLocal(list.getStringTagAt(i)));
+                }
+                return sb.toString();
+        }
+    }
+
+    public void setColor(ItemStack stack, int color)
+    {
+        getTagCompound(stack).setInteger("color", color);
+    }
+    
+    public int getColor(ItemStack stack)
+    {
+        return getTagCompound(stack).getInteger("color");
+    }
+    
+    public void setFoodStats(ItemStack stack, LinkedList<ItemStack> ingredients)
+    {
+        float saturation = 0;
+        int food = 0;
+        
+        for(ItemStack item : ingredients)
+        {
+            switch(Item.getIdFromItem(item.getItem()))
+            {
+                case 86: // pumpkin
+                    food += 6;
+                    saturation += 0.3F;
+                    break;  
+                case 260: // apple
+                    food += 4;
+                    saturation += 0.3F;
+                    break;   
+                case 322: // golden Apple
+                    food += 4;
+                    saturation += 1.2F;
+                    break;   
+                case 435: // beetroot Seeds
+                case 362: // melon Seeds
+                case 361: // pumpkin Seeds
+                case 295: // wheat Seeds
+                    food += 1;
+                    saturation += 0.1F;
+                    break; 
+                case 363: // beef
+                case 319: // pork
+                    food += 8;
+                    saturation += 0.8F;
+                    break;             
+                case 349: // fish
+                    switch(ItemFishFood.FishType.byItemStack(item))
+                    {
+                        case CLOWNFISH:
+                            food += 1;
+                            saturation += 0.1F;
+                            break;
+                        case COD:
+                            food += 5;
+                            saturation += 0.6F;
+                            break;
+                        case PUFFERFISH:
+                            food -= 75;
+                            saturation -= 0.8F;
+                            break;
+                        case SALMON:
+                            food += 6;
+                            saturation += 0.8F;
+                            break;
+                    }
+                    break; 
+                case 353: // sugar
+                    food += 1;
+                    saturation += 0.1F;
+                    break;  
+                case 382: // golden melon
+                case 360: // melon
+                    food += 2;
+                    saturation += 0.3F;
+                    break; 
+                case 365: // chicken
+                    food += 6;
+                    saturation += 0.6F;
+                    break; 
+                case 394: // poison potato
+                case 375: // spider eye
+                    food += -25;
+                    saturation -= 0.2F;
+                    break; 
+                case 414: // rabbit foot
+                case 372: // nether wart
+                case 376: // spider eye fermented
+                    food += 1;
+                    saturation += 0.1F;
+                    break; 
+                /*case 378: // magma cream    
+                case 377: // blaze powder
+                    food -= 1;
+                    saturation -= 0.1F;
+                    break; */
+                case 396: // golden carrot
+                case 391: // carrot
+                    food += 3;
+                    saturation += 0.6F;
+                    break; 
+                case 411: // rabbit
+                case 392: // potato
+                    food += 5;
+                    saturation += 0.6F;
+                    break;     
+                case 423: // mutton
+                    food += 6;
+                    saturation += 0.8F;
+                    break; 
+                case 434: // beetroot
+                    food += 1;
+                    saturation += 0.6F;
+                    break; 
+            }
+        }
+        
+        getTagCompound(stack).setFloat("saturation", saturation);
+        getTagCompound(stack).setInteger("food", food);
+    }
+
+    @Override
+    public float getSaturationModifier(ItemStack stack) 
+    {
+        return getTagCompound(stack).getFloat("saturation");
+    }
+
+    @Override
+    public int getHealAmount(ItemStack stack) 
+    {
+        int food = getTagCompound(stack).getInteger("food");
+        if(food < 0)
+        {
+            return 0;
+        }
+        return food;
+    }
+    
+    @Override
+    protected void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player)
+    {
+        if(!worldIn.isRemote)
+        {
+            int food = getTagCompound(stack).getInteger("food");
+            if(food < 0)
+            {
+                player.addPotionEffect(new PotionEffect(MobEffects.POISON, 100, (-food) / 25));
+            }
+        }
+    }
+}

+ 23 - 0
src/main/java/me/km/items/ItemFood.java

@@ -0,0 +1,23 @@
+package me.km.items;
+
+import me.km.KajetansMod;
+import net.minecraft.item.Item;
+
+public class ItemFood extends net.minecraft.item.ItemFood implements ItemModelProvider
+{
+    protected String name;
+    
+    public ItemFood(String name, String local, int amount, float saturation, boolean isWolfFood) 
+    {
+        super(amount, saturation, isWolfFood);
+        this.name = name;
+        super.setUnlocalizedName(local);
+        this.setRegistryName(KajetansMod.MODID, name);
+    }
+
+    @Override
+    public void registerItemModel(Item item) 
+    {
+        KajetansMod.proxy.registerItemRenderer(this, 0, name);
+    }
+}

+ 19 - 19
src/main/java/me/km/items/ItemGun.java

@@ -212,30 +212,30 @@ public class ItemGun extends ItemWeapon
             playSound(p, w, soundReload);
             return new ActionResult(EnumActionResult.SUCCESS, p.getHeldItem(hand));
         }
-        if(p.isSneaking())
+        ItemStack stack = p.getHeldItem(hand);    
+        int load = getLoad(stack);
+        if(load <= 0)
         {
-            ItemStack stack = p.getHeldItem(hand);    
-            int load = getLoad(stack);
-            if(load <= 0)
+            if(!p.isSneaking())
+            {
+                return new ActionResult<>(EnumActionResult.FAIL, p.getHeldItem(hand));
+            }
+            ItemStack ammoStack = findAmmo(p);
+            if(!ammoStack.isEmpty())
             {
-                ItemStack ammoStack = findAmmo(p);
-                if(!ammoStack.isEmpty())
+                int newLoad = Math.min(ammoStack.getCount(), maxLoad);
+                setLoad(stack, newLoad);
+                p.getCooldownTracker().setCooldown(this, cooldown * newLoad);
+                ammoStack.shrink(newLoad);
+                if(ammoStack.isEmpty())
                 {
-                    int newLoad = Math.min(ammoStack.getCount(), maxLoad);
-                    setLoad(stack, newLoad);
-                    p.getCooldownTracker().setCooldown(this, cooldown * newLoad);
-                    ammoStack.shrink(newLoad);
-                    if(ammoStack.isEmpty())
-                    {
-                        p.inventory.deleteStack(ammoStack);
-                    }
-                    playSound(p, w, soundReload);
+                    p.inventory.deleteStack(ammoStack);
                 }
-                return new ActionResult(EnumActionResult.FAIL, stack);
+                playSound(p, w, soundReload);
             }
-            p.setActiveHand(hand);
-            return new ActionResult<>(EnumActionResult.SUCCESS, p.getHeldItem(hand));
+            return new ActionResult(EnumActionResult.FAIL, stack);
         }
-        return new ActionResult<>(EnumActionResult.FAIL, p.getHeldItem(hand));
+        p.setActiveHand(hand);
+        return new ActionResult<>(EnumActionResult.SUCCESS, p.getHeldItem(hand));
     }
 }

+ 25 - 0
src/main/java/me/km/items/ItemHerbs.java

@@ -0,0 +1,25 @@
+package me.km.items;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.potion.PotionEffect;
+
+public class ItemHerbs extends ItemFood
+{
+    public ItemHerbs(String name, String local) 
+    {
+        super(name, local, 0, 0, false);
+        super.setAlwaysEdible();
+    }
+    
+    public ItemHerbs(String name, String local, PotionEffect effect) 
+    {
+        this(name, local);
+        super.setPotionEffect(effect, 1);
+    }
+
+    @Override
+    public int getMaxItemUseDuration(ItemStack stack)
+    {
+        return 8;
+    }
+}

+ 50 - 0
src/main/java/me/km/items/ItemSpecialHerbs.java

@@ -0,0 +1,50 @@
+package me.km.items;
+
+import me.km.KajetansMod;
+import net.minecraft.advancements.CriteriaTriggers;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.init.SoundEvents;
+import net.minecraft.item.ItemStack;
+import net.minecraft.stats.StatList;
+import net.minecraft.util.SoundCategory;
+import net.minecraft.world.World;
+
+public class ItemSpecialHerbs extends ItemHerbs
+{
+    private String effect;
+    private int time;
+    
+    public ItemSpecialHerbs(String name, String local, String effect, int time) 
+    {
+        super(name, local);
+        this.effect = effect;
+        this.time = time;
+    }
+
+    @Override
+    public ItemStack onItemUseFinish(ItemStack stack, World w, EntityLivingBase liv)
+    {
+        if(liv instanceof EntityPlayer)
+        {
+            EntityPlayer p = (EntityPlayer) liv;
+            p.getFoodStats().addStats(this, stack);
+            w.playSound(null, p.posX, p.posY, p.posZ, SoundEvents.ENTITY_PLAYER_BURP, SoundCategory.PLAYERS, 0.5F, w.rand.nextFloat() * 0.1F + 0.9F);
+            this.onFoodEaten(stack, w, p);
+            p.addStat(StatList.getObjectUseStats(this));
+
+            if(p instanceof EntityPlayerMP)
+            {
+                CriteriaTriggers.CONSUME_ITEM.trigger((EntityPlayerMP) p, stack);
+                if(!w.isRemote)
+                {
+                    // change id
+                    KajetansMod.playerbank.getData((EntityPlayerMP) p).addGoodTimedData(effect, true, time, effect, 300);
+                }
+            }
+        }
+        stack.shrink(1);
+        return stack;
+    }
+}

+ 26 - 13
src/main/java/me/km/items/ModItems.java

@@ -9,12 +9,14 @@ import me.km.items.noglint.ItemNoGlintSplashPotion;
 import me.km.sounds.Sounds;
 import net.minecraft.creativetab.CreativeTabs;
 import net.minecraft.init.Items;
+import net.minecraft.init.MobEffects;
 import net.minecraft.init.SoundEvents;
 import net.minecraft.inventory.EntityEquipmentSlot;
 import net.minecraft.item.EnumDyeColor;
 import net.minecraft.item.Item;
 import net.minecraft.item.ItemArmor.ArmorMaterial;
 import net.minecraft.item.ItemStack;
+import net.minecraft.potion.PotionEffect;
 import net.minecraftforge.common.util.EnumHelper;
 import net.minecraftforge.registries.IForgeRegistry;
 
@@ -185,12 +187,17 @@ public class ModItems
     public static ItemBase wolfFur; 
     public static ItemBlockSpecial campFire; 
     
-    public static ItemBlockSpecial cauldronOak;
-    public static ItemBlockSpecial cauldronBirch;
-    public static ItemBlockSpecial cauldronAcacia;
-    public static ItemBlockSpecial cauldronJungle;
-    public static ItemBlockSpecial cauldronSpruce;
-    public static ItemBlockSpecial cauldronBigOak;
+    // food
+    public static ItemColoredSoup coloredSoup;
+    
+    // herbs
+    public static ItemHerbs herbStrong;
+    public static ItemHerbs herbShadow;
+    public static ItemHerbs herbXp;
+    public static ItemHerbs herbSea;
+    public static ItemHerbs herbGold;
+    public static ItemHerbs herbBreathing;
+    public static ItemHerbs herbFire;
     
     public static void init(IForgeRegistry<Item> r) 
     {
@@ -326,14 +333,20 @@ public class ModItems
         batWing = register(r, new ItemBase("bat_wing", "batWing").setCreativeTab(CreativeTabs.MATERIALS));
         wolfFur = register(r, new ItemBase("wolf_fur", "wolfFur").setCreativeTab(CreativeTabs.MATERIALS));
         
-        campFire = register(r, new ItemBlockSpecial("camp_fire", "camp_fire_item", "campFire", ModBlocks.campFire));
+        // food
+        coloredSoup = register(r, new ItemColoredSoup("colored_soup", "soupColored"));
+        
+        // herbs
+        herbStrong = register(r, new ItemHerbs("herb_strong", "herbStrong", new PotionEffect(MobEffects.SPEED, 6000, 1)));
+        herbShadow = register(r, new ItemHerbs("herb_shadow", "herbShadow", new PotionEffect(MobEffects.NIGHT_VISION, 3600, 0)));
+        herbXp = register(r, new ItemHerbs("herb_xp", "herbXp"));
+        herbSea = register(r, new ItemSpecialHerbs("herb_sea", "herbSea", "Aqua Affinity", 6000));
+        herbGold = register(r, new ItemSpecialHerbs("herb_gold", "herbGold", "+50% Gold", 12000));
+        herbBreathing = register(r, new ItemHerbs("herb_breathing", "herbBreathing", new PotionEffect(MobEffects.WATER_BREATHING, 2400, 0)));
+        herbFire = register(r, new ItemHerbs("herb_fire", "herbFire", new PotionEffect(MobEffects.FIRE_RESISTANCE, 2400, 0)));
         
-        cauldronOak = register(r, new ItemBlockSpecial("cauldron_oak", "cauldron_oak_item", "cauldronOak", ModBlocks.cauldronOak));
-        cauldronBirch = register(r, new ItemBlockSpecial("cauldron_birch", "cauldron_birch_item", "cauldronBirch", ModBlocks.cauldronBirch));
-        cauldronAcacia = register(r, new ItemBlockSpecial("cauldron_acacia", "cauldron_acacia_item", "cauldronAcacia", ModBlocks.cauldronAcacia));
-        cauldronJungle = register(r, new ItemBlockSpecial("cauldron_jungle", "cauldron_jungle_item", "cauldronJungle", ModBlocks.cauldronJungle));
-        cauldronSpruce = register(r, new ItemBlockSpecial("cauldron_spruce", "cauldron_spruce_item", "cauldronSpruce", ModBlocks.cauldronSpruce));
-        cauldronBigOak = register(r, new ItemBlockSpecial("cauldron_big_oak", "cauldron_big_oak_item", "cauldronBigOak", ModBlocks.cauldronBigOak));
+        // block special
+        campFire = register(r, new ItemBlockSpecial("camp_fire", "camp_fire_item", "campFire", ModBlocks.campFire).setCreativeTab(CreativeTabs.DECORATIONS));
         
         try
         {

+ 5 - 0
src/main/java/me/km/items/noglint/ItemNoGlintLingeringPotion.java

@@ -7,6 +7,11 @@ import net.minecraftforge.fml.relauncher.SideOnly;
 
 public class ItemNoGlintLingeringPotion extends ItemLingeringPotion
 {
+    public ItemNoGlintLingeringPotion()
+    {
+        super.setMaxStackSize(16);
+    }
+    
     @SideOnly(Side.CLIENT)
     @Override
     public boolean hasEffect(ItemStack stack)

+ 5 - 0
src/main/java/me/km/items/noglint/ItemNoGlintPotion.java

@@ -7,6 +7,11 @@ import net.minecraftforge.fml.relauncher.SideOnly;
 
 public class ItemNoGlintPotion extends ItemPotion
 {
+    public ItemNoGlintPotion()
+    {
+        super.setMaxStackSize(16);
+    }
+    
     @SideOnly(Side.CLIENT)
     @Override
     public boolean hasEffect(ItemStack stack)

+ 5 - 0
src/main/java/me/km/items/noglint/ItemNoGlintSplashPotion.java

@@ -7,6 +7,11 @@ import net.minecraftforge.fml.relauncher.SideOnly;
 
 public class ItemNoGlintSplashPotion extends ItemSplashPotion
 {
+    public ItemNoGlintSplashPotion()
+    {
+        super.setMaxStackSize(16);
+    }
+    
     @SideOnly(Side.CLIENT)
     @Override
     public boolean hasEffect(ItemStack stack)

+ 1 - 8
src/main/java/me/km/snuviscript/CommandGiveUp.java

@@ -38,16 +38,9 @@ public class CommandGiveUp extends ModuleCommand
             this.getModule().send(cs, "Du hast gerade keine Quest.");
             return true;
         }
-        if(!KajetansMod.scripts.getSnuviParser().callEvent("player_giveup", qd, (sc) -> 
-            {
-                ScriptVars.setPlayerVars(qd, p); 
-            }, (sc) -> 
-            {
-                this.getModule().send(cs, "Du hast deine Quest aufgegeben.");
-            }))
+        if(!KajetansMod.scripts.getSnuviParser().callEvent("player_giveup", qd, (sc) -> ScriptVars.setPlayerVars(qd, p), null))
         {
             KajetansMod.scripts.removePlayerFromScript(p, qd);
-            this.getModule().send(cs, "Du hast deine Quest aufgegeben.");
         }
         return true;
     }

+ 15 - 0
src/main/java/me/km/snuviscript/ScriptEvents.java

@@ -240,6 +240,21 @@ public class ScriptEvents extends ModuleListener
         });
     } 
     
+    @SubscribeEvent
+    public void onPlayerDamage(LivingHealEvent e)
+    {        
+        if(e.getEntityLiving() instanceof EntityPlayer)
+        {
+            handleEvent((EntityPlayer) e.getEntityLiving(), "player_heal", (qd) -> 
+            {
+                qd.setVar("cancel", e.isCanceled()); 
+            }, (qd) -> 
+            {
+                e.setCanceled(qd.getBooleanVar("cancel")); 
+            });
+        }
+    } 
+    
     @SubscribeEvent
     public void onLivingDeath(LivingDeathEvent e)
     {        

+ 0 - 17
src/main/java/me/km/utils/ReflectionUtils.java

@@ -267,23 +267,6 @@ public class ReflectionUtils
     // EntityLivingBase stuff
     // -----------------------------------------------------------------------------------
     
-    private final static Method APPLY_ARMOR_CALCULATIONS = getMethod(
-            EntityLivingBase.class, 
-            "applyArmorCalculations", 
-            "func_70655_b", DamageSource.class, float.class);
-    
-    public static float applyArmorCalculations(EntityLivingBase liv, DamageSource ds, float damage)
-    {
-        try
-        {
-            return (float) APPLY_ARMOR_CALCULATIONS.invoke(liv, ds, damage);
-        }
-        catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex)
-        {
-            return damage;
-        }
-    }
-    
     private final static Method APPLY_POTION_DAMAGE_CALCULATIONS = getMethod(
             EntityLivingBase.class, 
             "applyPotionDamageCalculations", 

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_acacia.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_acacia" }
+    }
+}

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_big_oak.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_big_oak" }
+    }
+}

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_birch.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_birch" }
+    }
+}

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_jungle.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_jungle" }
+    }
+}

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_oak.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_oak" }
+    }
+}

+ 5 - 0
src/main/resources/assets/km/blockstates/barrel_spruce.json

@@ -0,0 +1,5 @@
+{
+    "variants": {
+        "normal": { "model": "km:barrel/barrel_spruce" }
+    }
+}

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_acacia.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/acacia/cauldron_empty" },
         "level=0": { "model": "km:cauldron/acacia/cauldron_empty" },
         "level=1": { "model": "km:cauldron/acacia/cauldron_level1" },
         "level=2": { "model": "km:cauldron/acacia/cauldron_level2" },

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_big_oak.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/big_oak/cauldron_empty" },
         "level=0": { "model": "km:cauldron/big_oak/cauldron_empty" },
         "level=1": { "model": "km:cauldron/big_oak/cauldron_level1" },
         "level=2": { "model": "km:cauldron/big_oak/cauldron_level2" },

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_birch.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/birch/cauldron_empty" },
         "level=0": { "model": "km:cauldron/birch/cauldron_empty" },
         "level=1": { "model": "km:cauldron/birch/cauldron_level1" },
         "level=2": { "model": "km:cauldron/birch/cauldron_level2" },

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_jungle.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/jungle/cauldron_empty" },
         "level=0": { "model": "km:cauldron/jungle/cauldron_empty" },
         "level=1": { "model": "km:cauldron/jungle/cauldron_level1" },
         "level=2": { "model": "km:cauldron/jungle/cauldron_level2" },

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_oak.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/oak/cauldron_empty" },
         "level=0": { "model": "km:cauldron/oak/cauldron_empty" },
         "level=1": { "model": "km:cauldron/oak/cauldron_level1" },
         "level=2": { "model": "km:cauldron/oak/cauldron_level2" },

+ 1 - 0
src/main/resources/assets/km/blockstates/cauldron_spruce.json

@@ -1,5 +1,6 @@
 {
     "variants": {
+        "normal": { "model": "km:cauldron/spruce/cauldron_empty" },
         "level=0": { "model": "km:cauldron/spruce/cauldron_empty" },
         "level=1": { "model": "km:cauldron/spruce/cauldron_level1" },
         "level=2": { "model": "km:cauldron/spruce/cauldron_level2" },

+ 23 - 6
src/main/resources/assets/km/lang/en_US.lang

@@ -51,6 +51,20 @@ tile.crateJungle.name=Jungle Crate
 tile.crateOak.name=Oak Crate
 tile.crateSpruce.name=Spruce Crate
 
+tile.cauldronOak.name=Oak Vat
+tile.cauldronBirch.name=Birch Vat
+tile.cauldronAcacia.name=Acacia Vat
+tile.cauldronJungle.name=Jungle Vat
+tile.cauldronSpruce.name=Spruce Vat
+tile.cauldronBigOak.name=Dark Oak Vat
+
+tile.barrelOak.name=Oak Barrel
+tile.barrelBirch.name=Birch Barrel
+tile.barrelAcacia.name=Acacia Barrel
+tile.barrelJungle.name=Jungle Barrel
+tile.barrelSpruce.name=Spruce Barrel
+tile.barrelBigOak.name=Dark Oak Barrel
+
 tile.spikes.copper.name=Copper Spikes
 tile.spikes.tin.name=Tin Spikes
 tile.spikes.bronze.name=Bronze Spikes
@@ -138,12 +152,15 @@ item.bundleHay.name=Hay Bundle
 item.batWing.name=Bat Wing
 item.wolfFur.name=Wolf Fur
 
-item.cauldronOak.name=Oak Cauldron
-item.cauldronBirch.name=Birch Cauldron
-item.cauldronAcacia.name=Acacia Cauldron
-item.cauldronJungle.name=Jungle Cauldron
-item.cauldronSpruce.name=Spruce Cauldron
-item.cauldronBigOak.name=Big Oak Cauldron
+item.soupColored.name=Stew
+
+item.herbStrong.name=Power Herb
+item.herbShadow.name=Shadow Herb
+item.herbXp.name=Apprentice Herb
+item.herbSea.name=Sea Herb
+item.herbGold.name=Gold Herb
+item.herbBreathing.name=Dianthus Herb
+item.herbFire.name=Fire Herb
 
 entity.BrownBear.name=Brown Bear
 entity.BlackBear.name=Black Bear

+ 68 - 0
src/main/resources/assets/km/models/block/barrel/barrel.json

@@ -0,0 +1,68 @@
+{
+    "parent": "block/block",
+    "ambientocclusion": false,
+    "elements": [
+        {
+            "from": [ 0.00, 0.00, 0.00 ], 
+            "to": [ 2.00, 16.00, 16.00 ], 
+            "faces": {
+                "down":  { "texture": "#top" },
+                "up":    { "texture": "#top", "cullface": "up" },
+                "north": { "texture": "#side", "cullface": "north" },
+                "south": { "texture": "#side", "cullface": "south" },
+                "west":  { "texture": "#side", "cullface": "west" },
+                "east":  { "texture": "#sidev" }
+            }
+        },
+        {
+            "from": [ 2.00, 1.00, 2.00 ], 
+            "to": [ 14.00, 2.00, 14.00 ], 
+            "faces": {
+                "down":  { "texture": "#inside" }
+            }
+        },
+        {
+            "from": [ 14.00, 0.00, 0.00 ], 
+            "to": [ 16.00, 16.00, 16.00 ], 
+            "faces": {
+                "down":  { "texture": "#top" },
+                "up":    { "texture": "#top", "cullface": "up" },
+                "north": { "texture": "#side", "cullface": "north" },
+                "south": { "texture": "#side", "cullface": "south" },
+                "west":  { "texture": "#sidev" },
+                "east":  { "texture": "#side", "cullface": "east" }
+            }
+        },
+        {
+            "from": [ 2.00, 0.00, 0.00 ], 
+            "to": [ 14.00, 16.00, 2.00 ], 
+            "faces": {
+                "down":  { "texture": "#top" },
+                "up":    { "texture": "#top", "cullface": "up" },
+                "north": { "texture": "#side", "cullface": "north" },
+                "south": { "texture": "#sidev" },
+                "west":  { "texture": "#side", "cullface": "west" },
+                "east":  { "texture": "#side", "cullface": "east" }
+            }
+        },
+        {
+            "from": [ 2.00, 0.00, 14.00 ], 
+            "to": [ 14.00, 16.00, 16.00 ], 
+            "faces": {
+                "down":  { "texture": "#top" },
+                "up":    { "texture": "#top", "cullface": "up" },
+                "north": { "texture": "#sidev" },
+                "south": { "texture": "#side", "cullface": "south" },
+                "west":  { "texture": "#side", "cullface": "west" },
+                "east":  { "texture": "#side", "cullface": "east" }
+            }
+        },
+        {
+            "from": [ 2.00, 13.00, 2.00 ], 
+            "to": [ 14.00, 14.00, 14.00 ], 
+            "faces": {
+                "up":    { "texture": "#inside", "cullface": "up" }
+            }
+        }
+    ]
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_acacia.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/acacia/barrel_side",
+        "top": "km:blocks/cauldron/acacia/cauldron_top",
+        "side": "km:blocks/cauldron/acacia/barrel_side",
+        "sidev": "km:blocks/cauldron/acacia/cauldron_sidev",
+        "inside": "km:blocks/cauldron/acacia/cauldron_inner"
+    }
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_big_oak.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/big_oak/barrel_side",
+        "top": "km:blocks/cauldron/big_oak/cauldron_top",
+        "side": "km:blocks/cauldron/big_oak/barrel_side",
+        "sidev": "km:blocks/cauldron/big_oak/cauldron_sidev",
+        "inside": "km:blocks/cauldron/big_oak/cauldron_inner"
+    }
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_birch.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/birch/barrel_side",
+        "top": "km:blocks/cauldron/birch/cauldron_top",
+        "side": "km:blocks/cauldron/birch/barrel_side",
+        "sidev": "km:blocks/cauldron/birch/cauldron_sidev",
+        "inside": "km:blocks/cauldron/birch/cauldron_inner"
+    }
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_jungle.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/jungle/barrel_side",
+        "top": "km:blocks/cauldron/jungle/cauldron_top",
+        "side": "km:blocks/cauldron/jungle/barrel_side",
+        "sidev": "km:blocks/cauldron/jungle/cauldron_sidev",
+        "inside": "km:blocks/cauldron/jungle/cauldron_inner"
+    }
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_oak.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/oak/barrel_side",
+        "top": "km:blocks/cauldron/oak/cauldron_top",
+        "side": "km:blocks/cauldron/oak/barrel_side",
+        "sidev": "km:blocks/cauldron/oak/cauldron_sidev",
+        "inside": "km:blocks/cauldron/oak/cauldron_inner"
+    }
+}

+ 10 - 0
src/main/resources/assets/km/models/block/barrel/barrel_spruce.json

@@ -0,0 +1,10 @@
+{
+    "parent": "km:block/barrel/barrel",
+    "textures": {
+        "particle": "km:blocks/cauldron/spruce/barrel_side",
+        "top": "km:blocks/cauldron/spruce/cauldron_top",
+        "side": "km:blocks/cauldron/spruce/barrel_side",
+        "sidev": "km:blocks/cauldron/spruce/cauldron_sidev",
+        "inside": "km:blocks/cauldron/spruce/cauldron_inner"
+    }
+}

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/acacia/cauldron_top",
         "bottom": "km:blocks/cauldron/acacia/cauldron_bottom",
         "side": "km:blocks/cauldron/acacia/cauldron_side",
+        "sidev": "km:blocks/cauldron/acacia/cauldron_sidev",
         "inside": "km:blocks/cauldron/acacia/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/acacia/cauldron_top",
         "bottom": "km:blocks/cauldron/acacia/cauldron_bottom",
         "side": "km:blocks/cauldron/acacia/cauldron_side",
+        "sidev": "km:blocks/cauldron/acacia/cauldron_sidev",
         "inside": "km:blocks/cauldron/acacia/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/acacia/cauldron_top",
         "bottom": "km:blocks/cauldron/acacia/cauldron_bottom",
         "side": "km:blocks/cauldron/acacia/cauldron_side",
+        "sidev": "km:blocks/cauldron/acacia/cauldron_sidev",
         "inside": "km:blocks/cauldron/acacia/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/acacia/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/acacia/cauldron_top",
         "bottom": "km:blocks/cauldron/acacia/cauldron_bottom",
         "side": "km:blocks/cauldron/acacia/cauldron_side",
+        "sidev": "km:blocks/cauldron/acacia/cauldron_sidev",
         "inside": "km:blocks/cauldron/acacia/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/big_oak/cauldron_top",
         "bottom": "km:blocks/cauldron/big_oak/cauldron_bottom",
         "side": "km:blocks/cauldron/big_oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/big_oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/big_oak/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/big_oak/cauldron_top",
         "bottom": "km:blocks/cauldron/big_oak/cauldron_bottom",
         "side": "km:blocks/cauldron/big_oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/big_oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/big_oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/big_oak/cauldron_top",
         "bottom": "km:blocks/cauldron/big_oak/cauldron_bottom",
         "side": "km:blocks/cauldron/big_oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/big_oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/big_oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/big_oak/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/big_oak/cauldron_top",
         "bottom": "km:blocks/cauldron/big_oak/cauldron_bottom",
         "side": "km:blocks/cauldron/big_oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/big_oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/big_oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/birch/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/birch/cauldron_top",
         "bottom": "km:blocks/cauldron/birch/cauldron_bottom",
         "side": "km:blocks/cauldron/birch/cauldron_side",
+        "sidev": "km:blocks/cauldron/birch/cauldron_sidev",
         "inside": "km:blocks/cauldron/birch/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/birch/cauldron_top",
         "bottom": "km:blocks/cauldron/birch/cauldron_bottom",
         "side": "km:blocks/cauldron/birch/cauldron_side",
+        "sidev": "km:blocks/cauldron/birch/cauldron_sidev",
         "inside": "km:blocks/cauldron/birch/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/birch/cauldron_top",
         "bottom": "km:blocks/cauldron/birch/cauldron_bottom",
         "side": "km:blocks/cauldron/birch/cauldron_side",
+        "sidev": "km:blocks/cauldron/birch/cauldron_sidev",
         "inside": "km:blocks/cauldron/birch/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/birch/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/birch/cauldron_top",
         "bottom": "km:blocks/cauldron/birch/cauldron_bottom",
         "side": "km:blocks/cauldron/birch/cauldron_side",
+        "sidev": "km:blocks/cauldron/birch/cauldron_sidev",
         "inside": "km:blocks/cauldron/birch/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 5 - 4
src/main/resources/assets/km/models/block/cauldron/cauldron_empty.json

@@ -1,4 +1,5 @@
 {
+    "parent": "block/block",
     "ambientocclusion": false,
     "elements": [
         {   "from": [ 0, 3, 0 ],
@@ -9,7 +10,7 @@
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
-                "east":  { "texture": "#side" }
+                "east":  { "texture": "#sidev" }
             }
         },
         {   "from": [ 2, 3, 2 ],
@@ -30,7 +31,7 @@
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
-                "west":  { "texture": "#side" },
+                "west":  { "texture": "#sidev" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
         },
@@ -40,7 +41,7 @@
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
-                "south": { "texture": "#side" },
+                "south": { "texture": "#sidev" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
@@ -50,7 +51,7 @@
             "faces": {
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
-                "north": { "texture": "#side" },
+                "north": { "texture": "#sidev" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }

+ 4 - 4
src/main/resources/assets/km/models/block/cauldron/cauldron_level1.json

@@ -9,7 +9,7 @@
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
-                "east":  { "texture": "#side" }
+                "east":  { "texture": "#sidev" }
             }
         },
         {   "from": [ 2, 3, 2 ],
@@ -30,7 +30,7 @@
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
-                "west":  { "texture": "#side" },
+                "west":  { "texture": "#sidev" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
         },
@@ -40,7 +40,7 @@
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
-                "south": { "texture": "#side" },
+                "south": { "texture": "#sidev" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
@@ -50,7 +50,7 @@
             "faces": {
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
-                "north": { "texture": "#side" },
+                "north": { "texture": "#sidev" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }

+ 4 - 4
src/main/resources/assets/km/models/block/cauldron/cauldron_level2.json

@@ -9,7 +9,7 @@
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
-                "east":  { "texture": "#side" }
+                "east":  { "texture": "#sidev" }
             }
         },
         {   "from": [ 2, 3, 2 ],
@@ -30,7 +30,7 @@
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
-                "west":  { "texture": "#side" },
+                "west":  { "texture": "#sidev" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
         },
@@ -40,7 +40,7 @@
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
-                "south": { "texture": "#side" },
+                "south": { "texture": "#sidev" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
@@ -50,7 +50,7 @@
             "faces": {
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
-                "north": { "texture": "#side" },
+                "north": { "texture": "#sidev" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }

+ 4 - 4
src/main/resources/assets/km/models/block/cauldron/cauldron_level3.json

@@ -9,7 +9,7 @@
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
-                "east":  { "texture": "#side" }
+                "east":  { "texture": "#sidev" }
             }
         },
         {   "from": [ 2, 3, 2 ],
@@ -30,7 +30,7 @@
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
                 "south": { "texture": "#side", "cullface": "south" },
-                "west":  { "texture": "#side" },
+                "west":  { "texture": "#sidev" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
         },
@@ -40,7 +40,7 @@
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
                 "north": { "texture": "#side", "cullface": "north" },
-                "south": { "texture": "#side" },
+                "south": { "texture": "#sidev" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }
             }
@@ -50,7 +50,7 @@
             "faces": {
                 "down":  { "texture": "#inside" },
                 "up":    { "texture": "#top", "cullface": "up" },
-                "north": { "texture": "#side" },
+                "north": { "texture": "#sidev" },
                 "south": { "texture": "#side", "cullface": "south" },
                 "west":  { "texture": "#side", "cullface": "west" },
                 "east":  { "texture": "#side", "cullface": "east" }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/jungle/cauldron_top",
         "bottom": "km:blocks/cauldron/jungle/cauldron_bottom",
         "side": "km:blocks/cauldron/jungle/cauldron_side",
+        "sidev": "km:blocks/cauldron/jungle/cauldron_sidev",
         "inside": "km:blocks/cauldron/jungle/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/jungle/cauldron_top",
         "bottom": "km:blocks/cauldron/jungle/cauldron_bottom",
         "side": "km:blocks/cauldron/jungle/cauldron_side",
+        "sidev": "km:blocks/cauldron/jungle/cauldron_sidev",
         "inside": "km:blocks/cauldron/jungle/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/jungle/cauldron_top",
         "bottom": "km:blocks/cauldron/jungle/cauldron_bottom",
         "side": "km:blocks/cauldron/jungle/cauldron_side",
+        "sidev": "km:blocks/cauldron/jungle/cauldron_sidev",
         "inside": "km:blocks/cauldron/jungle/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/jungle/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/jungle/cauldron_top",
         "bottom": "km:blocks/cauldron/jungle/cauldron_bottom",
         "side": "km:blocks/cauldron/jungle/cauldron_side",
+        "sidev": "km:blocks/cauldron/jungle/cauldron_sidev",
         "inside": "km:blocks/cauldron/jungle/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/oak/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/oak/cauldron_top",
         "bottom": "km:blocks/cauldron/oak/cauldron_bottom",
         "side": "km:blocks/cauldron/oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/oak/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/oak/cauldron_top",
         "bottom": "km:blocks/cauldron/oak/cauldron_bottom",
         "side": "km:blocks/cauldron/oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/oak/cauldron_top",
         "bottom": "km:blocks/cauldron/oak/cauldron_bottom",
         "side": "km:blocks/cauldron/oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/oak/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/oak/cauldron_top",
         "bottom": "km:blocks/cauldron/oak/cauldron_bottom",
         "side": "km:blocks/cauldron/oak/cauldron_side",
+        "sidev": "km:blocks/cauldron/oak/cauldron_sidev",
         "inside": "km:blocks/cauldron/oak/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_empty.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/spruce/cauldron_top",
         "bottom": "km:blocks/cauldron/spruce/cauldron_bottom",
         "side": "km:blocks/cauldron/spruce/cauldron_side",
+        "sidev": "km:blocks/cauldron/spruce/cauldron_sidev",
         "inside": "km:blocks/cauldron/spruce/cauldron_inner"
     }
 }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level1.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/spruce/cauldron_top",
         "bottom": "km:blocks/cauldron/spruce/cauldron_bottom",
         "side": "km:blocks/cauldron/spruce/cauldron_side",
+        "sidev": "km:blocks/cauldron/spruce/cauldron_sidev",
         "inside": "km:blocks/cauldron/spruce/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level2.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/spruce/cauldron_top",
         "bottom": "km:blocks/cauldron/spruce/cauldron_bottom",
         "side": "km:blocks/cauldron/spruce/cauldron_side",
+        "sidev": "km:blocks/cauldron/spruce/cauldron_sidev",
         "inside": "km:blocks/cauldron/spruce/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

+ 1 - 0
src/main/resources/assets/km/models/block/cauldron/spruce/cauldron_level3.json

@@ -5,6 +5,7 @@
         "top": "km:blocks/cauldron/spruce/cauldron_top",
         "bottom": "km:blocks/cauldron/spruce/cauldron_bottom",
         "side": "km:blocks/cauldron/spruce/cauldron_side",
+        "sidev": "km:blocks/cauldron/spruce/cauldron_sidev",
         "inside": "km:blocks/cauldron/spruce/cauldron_inner",
         "water": "km:blocks/grey_water_still"
     }

部分文件因文件數量過多而無法顯示