diff --git a/src/main/java/net/minecraft/core/block/Block.java b/src/main/java/net/minecraft/core/block/Block.java
index 26431f3ac..c0cb1f72c 100644
--- a/src/main/java/net/minecraft/core/block/Block.java
+++ b/src/main/java/net/minecraft/core/block/Block.java
@@ -9,6 +9,9 @@ import java.util.Random;
 import java.util.function.Function;
 import java.util.function.Supplier;
 
+import net.minecraft.core.block.support.FullSupport;
+import net.minecraft.core.block.support.ISupport;
+import net.minecraft.core.block.support.PartialSupport;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
@@ -656,6 +659,10 @@ public class Block
 		}
 	}
 
+    public ISupport getSupport(World world, int x, int y, int z, Side side) {
+        return FullSupport.INSTANCE;
+    }
+
     public boolean canBlockStay(World world, int x, int y, int z)
     {
         return true;
diff --git a/src/main/java/net/minecraft/core/block/support/FullSupport.java b/src/main/java/net/minecraft/core/block/support/FullSupport.java
new file mode 100644
index 000000000..9a822344c
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/support/FullSupport.java
@@ -0,0 +1,14 @@
+package net.minecraft.core.block.support;
+
+import net.minecraft.core.util.helper.Side;
+
+public class FullSupport implements ISupport {
+    public static final FullSupport INSTANCE = new FullSupport();
+
+    private FullSupport() { }
+
+    @Override
+    public boolean canSupport(final ISupport other, final Side side) {
+        return true;
+    }
+}
diff --git a/src/main/java/net/minecraft/core/block/support/ISupport.java b/src/main/java/net/minecraft/core/block/support/ISupport.java
new file mode 100644
index 000000000..30819f84d
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/support/ISupport.java
@@ -0,0 +1,15 @@
+package net.minecraft.core.block.support;
+
+import net.minecraft.core.util.helper.Side;
+
+/**
+ * Used to indicate how one block can support another "hangable" block.
+ */
+public interface ISupport {
+    /**
+     * Used to verify that one block can be hung off another.
+     * @param other The block to check against.
+     * @return Whether the block keyed by "other" can be hung.
+     */
+    boolean canSupport(final ISupport other, final Side side);
+}
diff --git a/src/main/java/net/minecraft/core/block/support/ISupportable.java b/src/main/java/net/minecraft/core/block/support/ISupportable.java
new file mode 100644
index 000000000..b472066d1
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/support/ISupportable.java
@@ -0,0 +1,19 @@
+package net.minecraft.core.block.support;
+
+import net.minecraft.core.block.Block;
+import net.minecraft.core.util.helper.Side;
+import net.minecraft.core.world.World;
+
+public interface ISupportable {
+    ISupport getSupportConstraint(final World world, final int x, final int y, final int z, final Side side);
+
+    default boolean isSupported(final World world, final int x, final int y, final int z, final Side side) {
+        final Block supportingBlock = world.getBlock(x, y, z);
+        if (supportingBlock == null) {
+            return false;
+        }
+        final ISupport supporting = supportingBlock.getSupport(world, x, y, z, side.getOpposite());
+        final ISupport supported = getSupportConstraint(world, x, y, z, side);
+        return supporting.canSupport(supported, side.getOpposite());
+    }
+}
diff --git a/src/main/java/net/minecraft/core/block/support/PartialSupport.java b/src/main/java/net/minecraft/core/block/support/PartialSupport.java
new file mode 100644
index 000000000..f188faaa1
--- /dev/null
+++ b/src/main/java/net/minecraft/core/block/support/PartialSupport.java
@@ -0,0 +1,70 @@
+package net.minecraft.core.block.support;
+
+import net.minecraft.core.util.helper.Side;
+
+public class PartialSupport implements ISupport {
+    private static final byte UP = 0b00001;
+    private static final byte DOWN = 0b00010;
+    private static final byte LEFT = 0b00100;
+    private static final byte RIGHT = 0b01000;
+    private static final byte CENTER = 0b10000;
+
+    public static final PartialSupport INSTANCE;
+    private static final PartialSupport[] PERMUTATIONS = new PartialSupport[32];
+
+    static {
+        for (int i = 0; i < 32; i++) {
+            PERMUTATIONS[i] = new PartialSupport((byte) i);
+        }
+        INSTANCE = PERMUTATIONS[0];
+    }
+
+    private final byte supportField;
+
+    public PartialSupport(final byte supportField) {
+        this.supportField = supportField;
+    }
+
+    public PartialSupport up() {
+        return PERMUTATIONS[this.supportField | UP];
+    }
+
+    public PartialSupport down() {
+        return PERMUTATIONS[this.supportField | DOWN];
+    }
+
+    public PartialSupport left() {
+        return PERMUTATIONS[this.supportField | LEFT];
+    }
+
+    public PartialSupport right() {
+        return PERMUTATIONS[this.supportField | RIGHT];
+    }
+
+    public PartialSupport center() {
+        return PERMUTATIONS[this.supportField | CENTER];
+    }
+
+    @Override
+    public boolean canSupport(final ISupport other, final Side side) {
+        if (other instanceof PartialSupport) {
+            byte supportField = this.supportField;
+            // Check if flip
+            if (side == Side.TOP || side == Side.SOUTH || side == Side.EAST) {
+                final boolean left = (this.supportField & LEFT) > 0;
+                final boolean right = (this.supportField & RIGHT) > 0;
+                supportField &= ~(LEFT | RIGHT);
+                if (left) {
+                    supportField |= RIGHT;
+                }
+                if (right) {
+                    supportField |= LEFT;
+                }
+            }
+            PartialSupport partialOther = (PartialSupport) other;
+            return (supportField & partialOther.supportField) == partialOther.supportField;
+        } else {
+            return false;
+        }
+    }
+}
