1
0
JasonWang 6 жил өмнө
parent
commit
ca92fb83ef
29 өөрчлөгдсөн 499 нэмэгдсэн , 131 устгасан
  1. 8 49
      src/MineCase.Core/Block/Block.cs
  2. 4 7
      src/MineCase.Core/Block/BlockAir.cs
  3. 2 7
      src/MineCase.Core/Block/BlockBedrock.cs
  4. 2 10
      src/MineCase.Core/Block/BlockCobblestone.cs
  5. 2 7
      src/MineCase.Core/Block/BlockDirt.cs
  6. 2 10
      src/MineCase.Core/Block/BlockGrassBlock.cs
  7. 5 9
      src/MineCase.Core/Block/BlockSapling.cs
  8. 1 1
      src/MineCase.Core/Block/BlockStates.cs
  9. 2 12
      src/MineCase.Core/Block/BlockStone.cs
  10. 5 7
      src/MineCase.Core/Block/BlockWater.cs
  11. 2 8
      src/MineCase.Core/Block/BlockWoodPlanks.cs
  12. 22 0
      src/MineCase.Core/Block/Blocks.cs
  13. 70 0
      src/MineCase.Core/Block/Material/Material.cs
  14. 48 0
      src/MineCase.Core/Block/Material/MaterialColor.cs
  15. 63 0
      src/MineCase.Core/Block/Material/MaterialColors.cs
  16. 52 0
      src/MineCase.Core/Block/Material/Materials.cs
  17. 15 0
      src/MineCase.Core/Block/Material/PushReaction.cs
  18. 26 0
      src/MineCase.Core/Block/State/BooleanProperty.cs
  19. 10 0
      src/MineCase.Core/Block/State/DirectionProperty.cs
  20. 34 0
      src/MineCase.Core/Block/State/EnumProperty.cs
  21. 11 0
      src/MineCase.Core/Block/State/IStateProperty.cs
  22. 30 0
      src/MineCase.Core/Block/State/IntegerProperty.cs
  23. 27 0
      src/MineCase.Core/Block/State/PropertyValue.cs
  24. 20 0
      src/MineCase.Core/Block/State/StateProperty.cs
  25. 10 0
      src/MineCase.Core/Loot/LootTableLoader.cs
  26. 16 0
      src/MineCase.Core/Util/Collections/ObjectIntDictionary.cs
  27. 2 0
      src/MineCase.Protocol/Protocol/Protocol.cs
  28. 4 0
      src/MineCase.Server.Grains/Game/Blocks/BlockHandler.cs
  29. 4 4
      src/MineCase.Server.Grains/Network/Login/LoginFlowGrain.cs

+ 8 - 49
src/MineCase.Core/Block/Block.cs

@@ -1,12 +1,15 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.Block.State;
 using MineCase.Item;
 
 namespace MineCase.Block
 {
     public abstract class Block
     {
+        public Material.Material Material { get; set; }
+
         /** Is it a full block */
         public bool FullBlock { get; set; }
 
@@ -43,60 +46,16 @@ namespace MineCase.Block
 
         public float BlockParticleGravity { get; set; }
 
-        public BlockState BlockState { get; set; }
-
-        public String UnlocalizedName { get; set; }
+        public String Name { get; set; }
 
-        public abstract ItemState BlockBrokenItem(ItemState hand, bool silktouch);
+        public BlockState BaseBlockState { get; set; }
 
         public static Block FromBlockState(BlockState blockState)
         {
-            if (blockState == BlockStates.Air())
-            {
-                return new BlockAir();
-            }
-            else if (blockState.IsId(BlockId.Stone))
-            {
-                var stone = new BlockStone();
-                stone.BlockState = blockState;
-                return stone;
-            }
-            else if (blockState == BlockStates.GrassBlock())
-            {
-                return new BlockGrassBlock();
-            }
-            else if (blockState == BlockStates.Dirt())
-            {
-                return new BlockDirt();
-            }
-            else if (blockState == BlockStates.Cobblestone())
-            {
-                return new BlockCobblestone();
-            }
-            else if (blockState.IsId(BlockId.OakPlanks))
-            {
-                var planks = new BlockWoodPlanks();
-                planks.BlockState = blockState;
-                return planks;
-            }
-            else if (blockState.IsId(BlockId.OakSapling))
-            {
-                var planks = new BlockSapling();
-                planks.BlockState = blockState;
-                return planks;
-            }
-            else if (blockState == BlockStates.Bedrock())
-            {
-                return new BlockBedrock();
-            }
-            else if (blockState == BlockStates.Water())
-            {
-                return new BlockWater();
-            }
+            if (!Blocks.IntToBlock.ContainsKey((int)blockState.Id))
+                return Blocks.Air;
             else
-            {
-                return new BlockAir();
-            }
+                return Blocks.IntToBlock[(int)blockState.Id];
         }
     }
 }

+ 4 - 7
src/MineCase.Core/Block/BlockAir.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.Block.State;
 using MineCase.Item;
 
 namespace MineCase.Block
@@ -9,6 +10,7 @@ namespace MineCase.Block
     {
         public BlockAir()
         {
+            Material = MineCase.Block.Material.Materials.Air;
             FullBlock = true;
             LightOpacity = 0;
             Translucent = false;
@@ -21,13 +23,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Air();
-            UnlocalizedName = "air";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.Air, MetaValue = 0 };
+            Name = "air";
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Air, MetaValue = 0 };
         }
     }
 }

+ 2 - 7
src/MineCase.Core/Block/BlockBedrock.cs

@@ -1,6 +1,7 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.Block.State;
 using MineCase.Item;
 
 namespace MineCase.Block
@@ -21,13 +22,7 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Bedrock();
-            UnlocalizedName = "bedrock";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.Air, MetaValue = 0 };
+            Name = "bedrock";
         }
     }
 }

+ 2 - 10
src/MineCase.Core/Block/BlockCobblestone.cs

@@ -21,16 +21,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Cobblestone();
-            UnlocalizedName = "cobblestone";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            if (hand.IsPickaxe())
-                return new ItemState { Id = (uint)BlockId.Cobblestone, MetaValue = 0 };
-            else
-                return new ItemState { Id = (uint)BlockId.Air, MetaValue = 0 };
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Cobblestone, MetaValue = 0 };
+            Name = "cobblestone";
         }
     }
 }

+ 2 - 7
src/MineCase.Core/Block/BlockDirt.cs

@@ -21,13 +21,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Dirt();
-            UnlocalizedName = "dirt";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.Dirt, MetaValue = 0 };
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Dirt, MetaValue = 0 };
+            Name = "dirt";
         }
     }
 }

+ 2 - 10
src/MineCase.Core/Block/BlockGrassBlock.cs

@@ -21,16 +21,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.GrassBlock();
-            UnlocalizedName = "grass";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            if (silktouch)
-                return new ItemState { Id = (uint)BlockId.GrassBlock, MetaValue = 0 };
-            else
-                return new ItemState { Id = (uint)BlockId.Dirt, MetaValue = 0 };
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Grass, MetaValue = 0 };
+            Name = "grass";
         }
     }
 }

+ 5 - 9
src/MineCase.Core/Block/BlockSapling.cs

@@ -1,13 +1,16 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.Block.State;
 using MineCase.Item;
 
 namespace MineCase.Block
 {
     public class BlockSapling : Block
     {
-        public BlockSapling()
+        public static IntegerProperty StageProperty = new IntegerProperty("stage", 2);
+
+        public BlockSapling(string name = "sapling")
         {
             FullBlock = false;
             LightOpacity = 0;
@@ -21,14 +24,7 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.OakSapling();
-            UnlocalizedName = "sapling";
-        }
-
-        // FIXME the broken item is not correct
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.OakSapling, MetaValue = BlockState.MetaValue };
+            Name = name;
         }
     }
 }

+ 1 - 1
src/MineCase.Core/Block/BlockStates.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Text;
 

+ 2 - 12
src/MineCase.Core/Block/BlockStone.cs

@@ -21,18 +21,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Stone();
-            UnlocalizedName = "stone";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            if (silktouch)
-                return new ItemState { Id = (uint)BlockId.Stone, MetaValue = 0 };
-            else if (hand.IsPickaxe())
-                return new ItemState { Id = (uint)BlockId.Cobblestone, MetaValue = 0 };
-            else
-                return new ItemState { Id = (uint)BlockId.Air, MetaValue = 0 };
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Stone, MetaValue = 0 };
+            Name = "stone";
         }
     }
 }

+ 5 - 7
src/MineCase.Core/Block/BlockWater.cs

@@ -1,12 +1,15 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.Block.State;
 using MineCase.Item;
 
 namespace MineCase.Block
 {
     public class BlockWater : Block
     {
+        public static IntegerProperty LevelProperty = new IntegerProperty("level", 16);
+
         public BlockWater()
         {
             FullBlock = true;
@@ -21,13 +24,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.Water();
-            UnlocalizedName = "water";
-        }
-
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.Air, MetaValue = 0 };
+            BaseBlockState = new BlockState { Id = (uint)BlockId.Water, MetaValue = 0 };
+            Name = "water";
         }
     }
 }

+ 2 - 8
src/MineCase.Core/Block/BlockWoodPlanks.cs

@@ -21,14 +21,8 @@ namespace MineCase.Block
             IsBlockContainer = false;
             BlockSoundType = null;
             BlockParticleGravity = 1.0f;
-            BlockState = BlockStates.OakPlanks();
-            UnlocalizedName = "planks";
-        }
-
-        // FIXME: drop WoodPlanks
-        public override ItemState BlockBrokenItem(ItemState hand, bool silktouch)
-        {
-            return new ItemState { Id = (uint)BlockId.Air, MetaValue = BlockState.MetaValue };
+            BaseBlockState = BlockStates.OakPlanks();
+            Name = "planks";
         }
     }
 }

+ 22 - 0
src/MineCase.Core/Block/Blocks.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using MineCase.Util.Collections;
+
+namespace MineCase.Block
+{
+    public class Blocks
+    {
+        public static ObjectIntDictionary<Block> BlocksToInt = new ObjectIntDictionary<Block>();
+        public static Dictionary<int, Block> IntToBlock = new Dictionary<int, Block>();
+
+        public static Block Air = Register("air", new BlockAir());
+        public static Block Stone = Register("stone", new BlockStone());
+
+        protected static Block Register(string name, Block block)
+        {
+            IntToBlock.Add(IntToBlock.Count, block);
+            return block;
+        }
+    }
+}

+ 70 - 0
src/MineCase.Core/Block/Material/Material.cs

@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.Material
+{
+    public class Material : IEquatable<Material>
+    {
+        public MaterialColor Color { get; set; }
+
+        public PushReaction PushReaction { get; set; } = PushReaction.Normal;
+
+        public bool BlocksMovement { get; set; } = true;
+
+        public bool Flammable { get; set; } = false;
+
+        public bool RequiresNoTool { get; set; } = true;
+
+        public bool Liquid { get; set; } = false;
+
+        public bool Opaque { get; set; } = true;
+
+        public bool Replaceable { get; set; } = false;
+
+        public bool Solid { get; set; } = true;
+
+        public override bool Equals(object obj)
+        {
+            return obj is Material && Equals((Material)obj);
+        }
+
+        public bool Equals(Material other)
+        {
+            return Color == other.Color &&
+                   PushReaction == other.PushReaction &&
+                   BlocksMovement == other.BlocksMovement &&
+                   Flammable == other.Flammable &&
+                   RequiresNoTool == other.RequiresNoTool &&
+                   Liquid == other.Liquid &&
+                   Opaque == other.Opaque &&
+                   Replaceable == other.Replaceable &&
+                   Solid == other.Solid;
+        }
+
+        public override int GetHashCode()
+        {
+            var hashCode = -81208087;
+            hashCode = hashCode * -1521134295 + Color.GetHashCode();
+            hashCode = hashCode * -1521134295 + PushReaction.GetHashCode();
+            hashCode = hashCode * -1521134295 + BlocksMovement.GetHashCode();
+            hashCode = hashCode * -1521134295 + Flammable.GetHashCode();
+            hashCode = hashCode * -1521134295 + RequiresNoTool.GetHashCode();
+            hashCode = hashCode * -1521134295 + Liquid.GetHashCode();
+            hashCode = hashCode * -1521134295 + Opaque.GetHashCode();
+            hashCode = hashCode * -1521134295 + Replaceable.GetHashCode();
+            hashCode = hashCode * -1521134295 + Solid.GetHashCode();
+            return hashCode;
+        }
+
+        public static bool operator ==(Material state1, Material state2)
+        {
+            return state1.Equals(state2);
+        }
+
+        public static bool operator !=(Material state1, Material state2)
+        {
+            return !(state1 == state2);
+        }
+    }
+}

+ 48 - 0
src/MineCase.Core/Block/Material/MaterialColor.cs

@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.Material
+{
+    public struct MaterialColor : IEquatable<MaterialColor>
+    {
+        public int ColorValue { get; set; }
+
+        public int ColorIndex { get; set; }
+
+        public MaterialColor(int index, int value)
+        {
+            ColorIndex = index;
+            ColorValue = value;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return obj is MaterialColor && Equals((MaterialColor)obj);
+        }
+
+        public bool Equals(MaterialColor other)
+        {
+            return ColorValue == other.ColorValue &&
+                   ColorIndex == other.ColorIndex;
+        }
+
+        public override int GetHashCode()
+        {
+            var hashCode = -81208087;
+            hashCode = hashCode * -1521134295 + ColorValue.GetHashCode();
+            hashCode = hashCode * -1521134295 + ColorIndex.GetHashCode();
+            return hashCode;
+        }
+
+        public static bool operator ==(MaterialColor state1, MaterialColor state2)
+        {
+            return state1.Equals(state2);
+        }
+
+        public static bool operator !=(MaterialColor state1, MaterialColor state2)
+        {
+            return !(state1 == state2);
+        }
+    }
+}

+ 63 - 0
src/MineCase.Core/Block/Material/MaterialColors.cs

@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.Material
+{
+    public class MaterialColors
+    {
+        public static readonly MaterialColor[] Colors = new MaterialColor[64];
+        public static readonly MaterialColor Air = new MaterialColor(0, 0);
+        public static readonly MaterialColor Grass = new MaterialColor(1, 8368696);
+        public static readonly MaterialColor Sand = new MaterialColor(2, 16247203);
+        public static readonly MaterialColor Wool = new MaterialColor(3, 13092807);
+        public static readonly MaterialColor Tnt = new MaterialColor(4, 16711680);
+        public static readonly MaterialColor Ice = new MaterialColor(5, 10526975);
+        public static readonly MaterialColor Iron = new MaterialColor(6, 10987431);
+        public static readonly MaterialColor Foliage = new MaterialColor(7, 31744);
+        public static readonly MaterialColor Snow = new MaterialColor(8, 16777215);
+        public static readonly MaterialColor Clay = new MaterialColor(9, 10791096);
+        public static readonly MaterialColor Dirt = new MaterialColor(10, 9923917);
+        public static readonly MaterialColor Stone = new MaterialColor(11, 7368816);
+        public static readonly MaterialColor Water = new MaterialColor(12, 4210943);
+        public static readonly MaterialColor Wood = new MaterialColor(13, 9402184);
+        public static readonly MaterialColor Quartz = new MaterialColor(14, 16776437);
+        public static readonly MaterialColor Adobe = new MaterialColor(15, 14188339);
+        public static readonly MaterialColor Magenta = new MaterialColor(16, 11685080);
+        public static readonly MaterialColor LightBlue = new MaterialColor(17, 6724056);
+        public static readonly MaterialColor Yellow = new MaterialColor(18, 15066419);
+        public static readonly MaterialColor Lime = new MaterialColor(19, 8375321);
+        public static readonly MaterialColor Pink = new MaterialColor(20, 15892389);
+        public static readonly MaterialColor Gray = new MaterialColor(21, 5000268);
+        public static readonly MaterialColor LightGray = new MaterialColor(22, 10066329);
+        public static readonly MaterialColor Cyan = new MaterialColor(23, 5013401);
+        public static readonly MaterialColor Purple = new MaterialColor(24, 8339378);
+        public static readonly MaterialColor Blue = new MaterialColor(25, 3361970);
+        public static readonly MaterialColor Brown = new MaterialColor(26, 6704179);
+        public static readonly MaterialColor Green = new MaterialColor(27, 6717235);
+        public static readonly MaterialColor Red = new MaterialColor(28, 10040115);
+        public static readonly MaterialColor Black = new MaterialColor(29, 1644825);
+        public static readonly MaterialColor Gold = new MaterialColor(30, 16445005);
+        public static readonly MaterialColor Diamond = new MaterialColor(31, 6085589);
+        public static readonly MaterialColor Lapis = new MaterialColor(32, 4882687);
+        public static readonly MaterialColor Emerald = new MaterialColor(33, 55610);
+        public static readonly MaterialColor Obsidian = new MaterialColor(34, 8476209);
+        public static readonly MaterialColor Netherrack = new MaterialColor(35, 7340544);
+        public static readonly MaterialColor WhiteTerracotta = new MaterialColor(36, 13742497);
+        public static readonly MaterialColor OrangeTerracotta = new MaterialColor(37, 10441252);
+        public static readonly MaterialColor MagentaTerracotta = new MaterialColor(38, 9787244);
+        public static readonly MaterialColor LightBlueTerracotta = new MaterialColor(39, 7367818);
+        public static readonly MaterialColor YellowTerracotta = new MaterialColor(40, 12223780);
+        public static readonly MaterialColor LimeTerracotta = new MaterialColor(41, 6780213);
+        public static readonly MaterialColor PinkTerracotta = new MaterialColor(42, 10505550);
+        public static readonly MaterialColor GrayTerracotta = new MaterialColor(43, 3746083);
+        public static readonly MaterialColor LightGrayTerracotta = new MaterialColor(44, 8874850);
+        public static readonly MaterialColor CyanTerracotta = new MaterialColor(45, 5725276);
+        public static readonly MaterialColor PurpleTerracotta = new MaterialColor(46, 8014168);
+        public static readonly MaterialColor BlueTerracotta = new MaterialColor(47, 4996700);
+        public static readonly MaterialColor BrownTerracotta = new MaterialColor(48, 4993571);
+        public static readonly MaterialColor GreenTerracotta = new MaterialColor(49, 5001770);
+        public static readonly MaterialColor RedTerracotta = new MaterialColor(50, 9321518);
+        public static readonly MaterialColor BlackTerracotta = new MaterialColor(51, 2430480);
+    }
+}

+ 52 - 0
src/MineCase.Core/Block/Material/Materials.cs

@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.Material
+{
+    public class Materials
+    {
+        public static readonly Material Air = new Material { Color = MaterialColors.Air, BlocksMovement = false, Opaque = false, Solid = false, Replaceable = true };
+        public static readonly Material StructureVoid = new Material { Color = MaterialColors.Air, BlocksMovement = false, Opaque = false, Solid = false, Replaceable = true };
+        public static readonly Material Portal = new Material { Color = MaterialColors.Air, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Block };
+        public static readonly Material Carpet = new Material { Color = MaterialColors.Wool, BlocksMovement = false, Opaque = false, Solid = false, Flammable = true };
+        public static readonly Material Plants = new Material { Color = MaterialColors.Foliage, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy };
+        public static readonly Material OceanPlant = new Material { Color = MaterialColors.Water, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy };
+        public static readonly Material TallPlants = new Material { Color = MaterialColors.Foliage, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true, Flammable = true };
+        public static readonly Material SeaGrass = new Material { Color = MaterialColors.Water, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true };
+        public static readonly Material Water = new Material { Color = MaterialColors.Water, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true, Liquid = true };
+        public static readonly Material BubbleColumn = new Material { Color = MaterialColors.Water, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true, Liquid = true };
+        public static readonly Material Lava = new Material { Color = MaterialColors.Tnt, BlocksMovement = false, Opaque = true, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true, Liquid = true };
+        public static readonly Material Snow = new Material { Color = MaterialColors.Snow, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true, RequiresNoTool = false };
+        public static readonly Material Fire = new Material { Color = MaterialColors.Air, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy, Replaceable = true };
+        public static readonly Material Miscellaneous = new Material { Color = MaterialColors.Air, BlocksMovement = false, Opaque = false, Solid = false, PushReaction = PushReaction.Destroy };
+        public static readonly Material Web = new Material { Color = MaterialColors.Wool, BlocksMovement = false, Opaque = false, PushReaction = PushReaction.Destroy, RequiresNoTool = false };
+        public static readonly Material RedstoneLight = new Material { Color = MaterialColors.Air };
+        public static readonly Material Clay = new Material { Color = MaterialColors.Clay };
+        public static readonly Material Earth = new Material { Color = MaterialColors.Dirt };
+        public static readonly Material Organic = new Material { Color = MaterialColors.Grass };
+        public static readonly Material PackedIce = new Material { Color = MaterialColors.Ice };
+        public static readonly Material Sand = new Material { Color = MaterialColors.Sand };
+        public static readonly Material Sponge = new Material { Color = MaterialColors.Yellow };
+        public static readonly Material Shulker = new Material { Color = MaterialColors.Purple };
+        public static readonly Material Wood = new Material { Color = MaterialColors.Wood, Flammable = true };
+        public static readonly Material BambooSapling = new Material { Color = MaterialColors.Wood, Flammable = true, PushReaction = PushReaction.Destroy, BlocksMovement = false };
+        public static readonly Material Bamboo = new Material { Color = MaterialColors.Wood, Flammable = true, PushReaction = PushReaction.Destroy };
+        public static readonly Material Wool = new Material { Color = MaterialColors.Wool, Flammable = true };
+        public static readonly Material Tnt = new Material { Color = MaterialColors.Tnt, Flammable = true, Opaque = true };
+        public static readonly Material Leaves = new Material { Color = MaterialColors.Foliage, Flammable = true, Opaque = false, PushReaction = PushReaction.Destroy };
+        public static readonly Material Glass = new Material { Color = MaterialColors.Air, Opaque = true };
+        public static readonly Material Ice = new Material { Color = MaterialColors.Ice, Opaque = true };
+        public static readonly Material Cactus = new Material { Color = MaterialColors.Foliage, Opaque = false, PushReaction = PushReaction.Destroy };
+        public static readonly Material Rock = new Material { Color = MaterialColors.Stone, RequiresNoTool = false };
+        public static readonly Material Iron = new Material { Color = MaterialColors.Iron, RequiresNoTool = false };
+        public static readonly Material SnowBlock = new Material { Color = MaterialColors.Snow, RequiresNoTool = false };
+        public static readonly Material Anvil = new Material { Color = MaterialColors.Iron, RequiresNoTool = false, PushReaction = PushReaction.Block };
+        public static readonly Material Barrier = new Material { Color = MaterialColors.Air, RequiresNoTool = false, PushReaction = PushReaction.Block };
+        public static readonly Material Pison = new Material { Color = MaterialColors.Stone, PushReaction = PushReaction.Block };
+        public static readonly Material Coral = new Material { Color = MaterialColors.Foliage, PushReaction = PushReaction.Destroy };
+        public static readonly Material Gourd = new Material { Color = MaterialColors.Foliage, PushReaction = PushReaction.Destroy };
+        public static readonly Material DragonEgg = new Material { Color = MaterialColors.Foliage, PushReaction = PushReaction.Destroy };
+        public static readonly Material Cake = new Material { Color = MaterialColors.Air, PushReaction = PushReaction.Destroy };
+    }
+}

+ 15 - 0
src/MineCase.Core/Block/Material/PushReaction.cs

@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.Material
+{
+    public enum PushReaction
+    {
+        Normal,
+        Destroy,
+        Block,
+        Ignore,
+        PushOnly
+    }
+}

+ 26 - 0
src/MineCase.Core/Block/State/BooleanProperty.cs

@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public class BooleanProperty : StateProperty<bool>
+    {
+        public BooleanProperty()
+        {
+        }
+
+        public override int StateNumber()
+        {
+            return 2;
+        }
+
+        public override int ToInt(bool value)
+        {
+            if (value)
+                return 1;
+            else
+                return 0;
+        }
+    }
+}

+ 10 - 0
src/MineCase.Core/Block/State/DirectionProperty.cs

@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public class DirectionProperty : EnumProperty<FacingDirectionType>
+    {
+    }
+}

+ 34 - 0
src/MineCase.Core/Block/State/EnumProperty.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public class EnumProperty<T> : StateProperty<T>
+        where T : System.Enum
+    {
+        private Dictionary<T, int> _map;
+
+        public EnumProperty()
+        {
+            _map = new Dictionary<T, int>();
+            var enumValues = typeof(T).GetEnumValues();
+            int index = 0;
+            foreach (var value in enumValues)
+            {
+                _map[(T)value] = index;
+                ++index;
+            }
+        }
+
+        public override int StateNumber()
+        {
+            return typeof(T).GetEnumValues().Length;
+        }
+
+        public override int ToInt(T value)
+        {
+            return _map[value];
+        }
+    }
+}

+ 11 - 0
src/MineCase.Core/Block/State/IStateProperty.cs

@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public interface IStateProperty
+    {
+        string GetName();
+    }
+}

+ 30 - 0
src/MineCase.Core/Block/State/IntegerProperty.cs

@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public class IntegerProperty : StateProperty<int>
+    {
+        private int _max;
+
+        public IntegerProperty(string name, int maxNumber)
+        {
+            Name = name;
+            _max = maxNumber;
+        }
+
+        public override int StateNumber()
+        {
+            return _max;
+        }
+
+        public override int ToInt(int value)
+        {
+            if (value > _max)
+                throw new ArgumentException("Value is greater than max number of the property.");
+
+            return value;
+        }
+    }
+}

+ 27 - 0
src/MineCase.Core/Block/State/PropertyValue.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public class PropertyValue
+    {
+        private IStateProperty _property;
+
+        private string _value;
+
+        public PropertyValue(IStateProperty prop, string value)
+        {
+            _property = prop;
+            _value = value;
+        }
+
+        public override int GetHashCode()
+        {
+            var hashCode = -81208087;
+            hashCode = hashCode * -1521134295 + _property.GetHashCode();
+            hashCode = hashCode * -1521134295 + _value.GetHashCode();
+            return hashCode;
+        }
+    }
+}

+ 20 - 0
src/MineCase.Core/Block/State/StateProperty.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Block.State
+{
+    public abstract class StateProperty<T> : IStateProperty
+    {
+        public string Name { get; set; }
+
+        public string GetName()
+        {
+            return Name;
+        }
+
+        public abstract int StateNumber();
+
+        public abstract int ToInt(T value);
+    }
+}

+ 10 - 0
src/MineCase.Core/Loot/LootTableLoader.cs

@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Loot
+{
+    public class LootTableLoader
+    {
+    }
+}

+ 16 - 0
src/MineCase.Core/Util/Collections/ObjectIntDictionary.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Util.Collections
+{
+    public class ObjectIntDictionary<T>
+    {
+        private Dictionary<T, int> _dict = new Dictionary<T, int>();
+
+        public void Add(T obj, int value)
+        {
+            _dict.Add(obj, value);
+        }
+    }
+}

+ 2 - 0
src/MineCase.Protocol/Protocol/Protocol.cs

@@ -8,6 +8,8 @@ namespace MineCase.Protocol
     {
         public const uint Version = 578;
 
+        public const string VersionName = "1.15.2";
+
         public static void ValidatePacketLength(uint length)
         {
             if (length > 16 * 1024)

+ 4 - 0
src/MineCase.Server.Grains/Game/Blocks/BlockHandler.cs

@@ -72,6 +72,8 @@ namespace MineCase.Server.Game.Blocks
 
         public virtual Slot DropBlock(ItemState item, BlockState blockState)
         {
+            // TODO: Wait for loot table
+            /*
             Block.Block blockObject = Block.Block.FromBlockState(blockState);
             switch ((BlockId)blockState.Id)
             {
@@ -82,6 +84,8 @@ namespace MineCase.Server.Game.Blocks
                     ItemState dropItem = blockObject.BlockBrokenItem(item, false);
                     return new Slot { BlockId = (short)dropItem.Id, ItemCount = 1 };
             }
+            */
+            return Slot.Empty;
         }
     }
 

+ 4 - 4
src/MineCase.Server.Grains/Network/Login/LoginFlowGrain.cs

@@ -29,11 +29,11 @@ namespace MineCase.Server.Network.Login
 
                 if (await user.GetProtocolVersion() > MineCase.Protocol.Protocol.Version)
                 {
-                    await SendLoginDisconnect("{\"text\":\"Outdated server!I'm still on 1.12\"}");
+                    await SendLoginDisconnect($"{{\"text\":\"Outdated server!I'm still on {Protocol.Protocol.VersionName}\"}}");
                 }
                 else if (await user.GetProtocolVersion() < MineCase.Protocol.Protocol.Version)
                 {
-                    await SendLoginDisconnect("{\"text\":\"Outdated client!Please use 1.12\"}");
+                    await SendLoginDisconnect($"{{\"text\":\"Outdated client!Please use {Protocol.Protocol.VersionName}\"}}");
                 }
                 else
                 {
@@ -53,11 +53,11 @@ namespace MineCase.Server.Network.Login
 
                 if (await nonAuthenticatedUser.GetProtocolVersion() > MineCase.Protocol.Protocol.Version)
                 {
-                    await SendLoginDisconnect("{\"text\":\"Outdated server!I'm still on 1.12\"}");
+                    await SendLoginDisconnect($"{{\"text\":\"Outdated server!I'm still on {Protocol.Protocol.VersionName}\"}}");
                 }
                 else if (await nonAuthenticatedUser.GetProtocolVersion() < MineCase.Protocol.Protocol.Version)
                 {
-                    await SendLoginDisconnect("{\"text\":\"Outdated client!Please use 1.12\"}");
+                    await SendLoginDisconnect($"{{\"text\":\"Outdated client!Please use {Protocol.Protocol.VersionName}\"}}");
                 }
                 else
                 {