From 26112ddc93de53c2c77a078bc42cbbd0a5448ae6 Mon Sep 17 00:00:00 2001
From: simibubi <31564874+simibubi@users.noreply.github.com>
Date: Thu, 9 Jul 2020 01:28:14 +0200
Subject: [PATCH] Fix build issues

- Not sure why but this seems to have worked
---
 .../structureMovement/StructureTransform.java | 36 ++++----
 .../contraptions/relays/belt/BeltBlock.java   | 86 +++++++------------
 .../relays/belt/BeltGenerator.java            | 38 ++++----
 .../contraptions/relays/belt/BeltHelper.java  | 11 ++-
 .../contraptions/relays/belt/BeltPart.java    | 14 +++
 .../relays/belt/BeltRenderer.java             | 13 ++-
 .../contraptions/relays/belt/BeltShapes.java  | 58 ++++++-------
 .../contraptions/relays/belt/BeltSlope.java   | 14 +++
 .../relays/belt/BeltTileEntity.java           | 25 +++---
 .../relays/belt/item/BeltConnectorItem.java   | 30 +++----
 .../relays/belt/transport/BeltInventory.java  |  4 +-
 .../belt/transport/BeltMovementHandler.java   | 20 ++---
 .../BeltTunnelInteractionHandler.java         |  4 +-
 .../belts/observer/BeltObserverBlock.java     | 10 +--
 .../block/belts/tunnel/BeltTunnelBlock.java   |  4 +-
 .../belts/tunnel/BrassTunnelTileEntity.java   | 78 ++++++++++++++++-
 .../schematics/block/LaunchedItem.java        |  4 +-
 .../block/SchematicannonTileEntity.java       | 12 +--
 18 files changed, 265 insertions(+), 196 deletions(-)
 create mode 100644 src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java
 create mode 100644 src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java

diff --git a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java
index 2a2c2cd38..a152542f7 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/StructureTransform.java
@@ -9,7 +9,7 @@ import com.simibubi.create.AllBlocks;
 import com.simibubi.create.content.contraptions.base.DirectionalAxisKineticBlock;
 import com.simibubi.create.content.contraptions.components.structureMovement.chassis.AbstractChassisBlock;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.foundation.utility.DirectionHelper;
 import com.simibubi.create.foundation.utility.VecHelper;
 
@@ -195,25 +195,25 @@ public class StructureTransform {
 
 	protected BlockState transformBelt(BlockState state, boolean halfTurn) {
 		Direction initialDirection = state.get(BeltBlock.HORIZONTAL_FACING);
-		boolean diagonal = state.get(BeltBlock.SLOPE) == Slope.DOWNWARD || state.get(BeltBlock.SLOPE) == Slope.UPWARD;
+		boolean diagonal = state.get(BeltBlock.SLOPE) == BeltSlope.DOWNWARD || state.get(BeltBlock.SLOPE) == BeltSlope.UPWARD;
 		
 		if (!diagonal) {
 			for (int i = 0; i < rotation.ordinal(); i++) {
 				Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
-				Slope slope = state.get(BeltBlock.SLOPE);
-				boolean vertical = slope == Slope.VERTICAL;
-				boolean horizontal = slope == Slope.HORIZONTAL;
-				boolean sideways = slope == Slope.SIDEWAYS;
+				BeltSlope slope = state.get(BeltBlock.SLOPE);
+				boolean vertical = slope == BeltSlope.VERTICAL;
+				boolean horizontal = slope == BeltSlope.HORIZONTAL;
+				boolean sideways = slope == BeltSlope.SIDEWAYS;
 				
 				Direction newDirection = direction.getOpposite();
-				Slope newSlope = Slope.VERTICAL;
+				BeltSlope newSlope = BeltSlope.VERTICAL;
 
 				if (vertical) {
 					if (direction.getAxis() == rotationAxis) {
 						newDirection = direction.rotateYCCW();
-						newSlope = Slope.SIDEWAYS;
+						newSlope = BeltSlope.SIDEWAYS;
 					} else {
-						newSlope = Slope.HORIZONTAL;
+						newSlope = BeltSlope.HORIZONTAL;
 						newDirection = direction;
 						if (direction.getAxis() == Axis.Z)
 							newDirection = direction.getOpposite();
@@ -223,7 +223,7 @@ public class StructureTransform {
 				if (sideways) {
 					newDirection = direction;
 					if (direction.getAxis() == rotationAxis) 
-						newSlope = Slope.HORIZONTAL;
+						newSlope = BeltSlope.HORIZONTAL;
 					else 
 						newDirection = direction.rotateYCCW();
 				}
@@ -231,7 +231,7 @@ public class StructureTransform {
 				if (horizontal) {
 					newDirection = direction;
 					if (direction.getAxis() == rotationAxis) 
-						newSlope = Slope.SIDEWAYS;
+						newSlope = BeltSlope.SIDEWAYS;
 				}
 
 				state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection);
@@ -242,14 +242,14 @@ public class StructureTransform {
 			for (int i = 0; i < rotation.ordinal(); i++) {
 				Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
 				Direction newDirection = direction.getOpposite();
-				Slope slope = state.get(BeltBlock.SLOPE);
-				boolean upward = slope == Slope.UPWARD;
-				boolean downward = slope == Slope.DOWNWARD;
+				BeltSlope slope = state.get(BeltBlock.SLOPE);
+				boolean upward = slope == BeltSlope.UPWARD;
+				boolean downward = slope == BeltSlope.DOWNWARD;
 
 				// Rotate diagonal
 				if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ downward
 					^ direction.getAxis() == Axis.Z) {
-					state = state.with(BeltBlock.SLOPE, upward ? Slope.DOWNWARD : Slope.UPWARD);
+					state = state.with(BeltBlock.SLOPE, upward ? BeltSlope.DOWNWARD : BeltSlope.UPWARD);
 				} else {
 					state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection);
 				}
@@ -258,12 +258,12 @@ public class StructureTransform {
 		} else if (halfTurn) {
 			Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
 			Direction newDirection = direction.getOpposite();
-			Slope slope = state.get(BeltBlock.SLOPE);
-			boolean vertical = slope == Slope.VERTICAL;
+			BeltSlope slope = state.get(BeltBlock.SLOPE);
+			boolean vertical = slope == BeltSlope.VERTICAL;
 			
 			if (diagonal) {
 				state = state.with(BeltBlock.SLOPE,
-					slope == Slope.UPWARD ? Slope.DOWNWARD : slope == Slope.DOWNWARD ? Slope.UPWARD : slope);
+					slope == BeltSlope.UPWARD ? BeltSlope.DOWNWARD : slope == BeltSlope.DOWNWARD ? BeltSlope.UPWARD : slope);
 			} else if (vertical) {
 				state = state.with(BeltBlock.HORIZONTAL_FACING, newDirection);
 			}
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java
index ceb92d25e..200fa5989 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java
@@ -19,7 +19,6 @@ import com.simibubi.create.content.schematics.ItemRequirement;
 import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
 import com.simibubi.create.foundation.block.ITE;
 import com.simibubi.create.foundation.utility.Iterate;
-import com.simibubi.create.foundation.utility.Lang;
 
 import net.minecraft.block.Block;
 import net.minecraft.block.BlockRenderType;
@@ -48,7 +47,6 @@ import net.minecraft.util.Direction;
 import net.minecraft.util.Direction.Axis;
 import net.minecraft.util.Direction.AxisDirection;
 import net.minecraft.util.Hand;
-import net.minecraft.util.IStringSerializable;
 import net.minecraft.util.NonNullList;
 import net.minecraft.util.Rotation;
 import net.minecraft.util.math.BlockPos;
@@ -71,14 +69,14 @@ import net.minecraftforge.items.IItemHandler;
 
 public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEntity>, ISpecialBlockItemRequirement {
 
-	public static final IProperty<Slope> SLOPE = EnumProperty.create("slope", Slope.class);
-	public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
+	public static final IProperty<BeltSlope> SLOPE = EnumProperty.create("slope", BeltSlope.class);
+	public static final IProperty<BeltPart> PART = EnumProperty.create("part", BeltPart.class);
 	public static final BooleanProperty CASING = BooleanProperty.create("casing");
 
 	public BeltBlock(Properties properties) {
 		super(properties);
-		setDefaultState(getDefaultState().with(SLOPE, Slope.HORIZONTAL)
-			.with(PART, Part.START)
+		setDefaultState(getDefaultState().with(SLOPE, BeltSlope.HORIZONTAL)
+			.with(PART, BeltPart.START)
 			.with(CASING, false));
 	}
 
@@ -100,7 +98,7 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 
 	@Override
 	public Axis getRotationAxis(BlockState state) {
-		if (state.get(SLOPE) == Slope.SIDEWAYS)
+		if (state.get(SLOPE) == BeltSlope.SIDEWAYS)
 			return Axis.Y;
 		return state.get(HORIZONTAL_FACING)
 			.rotateY()
@@ -210,8 +208,8 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 	public static boolean canTransport(BlockState state) {
 		if (!AllBlocks.BELT.has(state))
 			return false;
-		Slope slope = state.get(SLOPE);
-		return slope != Slope.VERTICAL && slope != Slope.SIDEWAYS;
+		BeltSlope slope = state.get(SLOPE);
+		return slope != BeltSlope.VERTICAL && slope != BeltSlope.SIDEWAYS;
 	}
 
 	@Override
@@ -261,13 +259,13 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 		}
 
 		if (isShaft) {
-			if (state.get(PART) != Part.MIDDLE)
+			if (state.get(PART) != BeltPart.MIDDLE)
 				return ActionResultType.PASS;
 			if (world.isRemote)
 				return ActionResultType.SUCCESS;
 			if (!player.isCreative())
 				heldItem.shrink(1);
-			world.setBlockState(pos, state.with(PART, Part.PULLEY), 2);
+			world.setBlockState(pos, state.with(PART, BeltPart.PULLEY), 2);
 			belt.attachKinetics();
 			return ActionResultType.SUCCESS;
 		}
@@ -302,10 +300,10 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 			return ActionResultType.SUCCESS;
 		}
 
-		if (state.get(PART) == Part.PULLEY) {
+		if (state.get(PART) == BeltPart.PULLEY) {
 			if (world.isRemote)
 				return ActionResultType.SUCCESS;
-			world.setBlockState(context.getPos(), state.with(PART, Part.MIDDLE), 2);
+			world.setBlockState(context.getPos(), state.with(PART, BeltPart.MIDDLE), 2);
 			BeltTileEntity belt = BeltHelper.getSegmentTE(world, context.getPos());
 			if (belt != null) {
 				belt.detachKinetics();
@@ -516,8 +514,8 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 	}
 
 	private void updateNeighbouringTunnel(World world, BlockPos pos, BlockState beltState) {
-		boolean isEnd = beltState.get(PART) != Part.END;
-		if (isEnd && beltState.get(PART) != Part.START)
+		boolean isEnd = beltState.get(PART) != BeltPart.END;
+		if (isEnd && beltState.get(PART) != BeltPart.START)
 			return;
 		int offset = isEnd ? -1 : 1;
 		BlockPos tunnelPos = pos.offset(beltState.get(HORIZONTAL_FACING), offset)
@@ -527,24 +525,6 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 			((BeltTunnelBlock) adjacent).updateTunnel(world, tunnelPos);
 	}
 
-	public enum Slope implements IStringSerializable {
-		HORIZONTAL, UPWARD, DOWNWARD, VERTICAL, SIDEWAYS;
-
-		@Override
-		public String getName() {
-			return Lang.asId(name());
-		}
-	}
-
-	public enum Part implements IStringSerializable {
-		START, MIDDLE, END, PULLEY;
-
-		@Override
-		public String getName() {
-			return Lang.asId(name());
-		}
-	}
-
 	public static List<BlockPos> getBeltChain(World world, BlockPos controllerPos) {
 		List<BlockPos> positions = new LinkedList<>();
 
@@ -567,18 +547,18 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 
 	public static BlockPos nextSegmentPosition(BlockState state, BlockPos pos, boolean forward) {
 		Direction direction = state.get(HORIZONTAL_FACING);
-		Slope slope = state.get(SLOPE);
-		Part part = state.get(PART);
+		BeltSlope slope = state.get(SLOPE);
+		BeltPart part = state.get(PART);
 
 		int offset = forward ? 1 : -1;
 
-		if (part == Part.END && forward || part == Part.START && !forward)
+		if (part == BeltPart.END && forward || part == BeltPart.START && !forward)
 			return null;
-		if (slope == Slope.VERTICAL)
+		if (slope == BeltSlope.VERTICAL)
 			return pos.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? offset : -offset);
 		pos = pos.offset(direction, offset);
-		if (slope != Slope.HORIZONTAL && slope != Slope.SIDEWAYS)
-			return pos.up(slope == Slope.UPWARD ? offset : -offset);
+		if (slope != BeltSlope.HORIZONTAL && slope != BeltSlope.SIDEWAYS)
+			return pos.up(slope == BeltSlope.UPWARD ? offset : -offset);
 		return pos;
 	}
 
@@ -587,20 +567,20 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 			return true;
 		if (!belt.get(BeltBlock.CASING))
 			return false;
-		Part part = belt.get(BeltBlock.PART);
-		if (part != Part.MIDDLE && facing.getAxis() == belt.get(HORIZONTAL_FACING)
+		BeltPart part = belt.get(BeltBlock.PART);
+		if (part != BeltPart.MIDDLE && facing.getAxis() == belt.get(HORIZONTAL_FACING)
 			.rotateY()
 			.getAxis())
 			return false;
 
-		Slope slope = belt.get(BeltBlock.SLOPE);
-		if (slope != Slope.HORIZONTAL) {
-			if (slope == Slope.DOWNWARD && part == Part.END)
+		BeltSlope slope = belt.get(BeltBlock.SLOPE);
+		if (slope != BeltSlope.HORIZONTAL) {
+			if (slope == BeltSlope.DOWNWARD && part == BeltPart.END)
 				return true;
-			if (slope == Slope.UPWARD && part == Part.START)
+			if (slope == BeltSlope.UPWARD && part == BeltPart.START)
 				return true;
 			Direction beltSide = belt.get(HORIZONTAL_FACING);
-			if (slope == Slope.DOWNWARD)
+			if (slope == BeltSlope.DOWNWARD)
 				beltSide = beltSide.getOpposite();
 			if (beltSide == facing)
 				return false;
@@ -617,9 +597,9 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 	@Override
 	public ItemRequirement getRequiredItems(BlockState state) {
 		List<ItemStack> required = new ArrayList<>();
-		if (state.get(PART) != Part.MIDDLE)
+		if (state.get(PART) != BeltPart.MIDDLE)
 			required.add(AllBlocks.SHAFT.asStack());
-		if (state.get(PART) == Part.START)
+		if (state.get(PART) == BeltPart.START)
 			required.add(AllItems.BELT_CONNECTOR.asStack());
 		if (required.isEmpty())
 			return ItemRequirement.NONE;
@@ -630,15 +610,15 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
 	public BlockState rotate(BlockState state, Rotation rot) {
 		BlockState rotate = super.rotate(state, rot);
 
-		if (state.get(SLOPE) != Slope.VERTICAL)
+		if (state.get(SLOPE) != BeltSlope.VERTICAL)
 			return rotate;
 		if (state.get(HORIZONTAL_FACING)
 			.getAxisDirection() != rotate.get(HORIZONTAL_FACING)
 				.getAxisDirection()) {
-			if (state.get(PART) == Part.START)
-				return rotate.with(PART, Part.END);
-			if (state.get(PART) == Part.END)
-				return rotate.with(PART, Part.START);
+			if (state.get(PART) == BeltPart.START)
+				return rotate.with(PART, BeltPart.END);
+			if (state.get(PART) == BeltPart.END)
+				return rotate.with(PART, BeltPart.START);
 		}
 
 		return rotate;
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java
index e2e25b46b..7b5164156 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltGenerator.java
@@ -1,7 +1,5 @@
 package com.simibubi.create.content.contraptions.relays.belt;
 
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.foundation.data.SpecialBlockStateGen;
 import com.tterrag.registrate.providers.DataGenContext;
 import com.tterrag.registrate.providers.RegistrateBlockstateProvider;
@@ -18,18 +16,18 @@ public class BeltGenerator extends SpecialBlockStateGen {
 	@Override
 	protected int getXRotation(BlockState state) {
 		Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
-		Slope slope = state.get(BeltBlock.SLOPE);
-		return slope == Slope.VERTICAL ? 90
-			: slope == Slope.SIDEWAYS && direction.getAxisDirection() == AxisDirection.NEGATIVE ? 180 : 0;
+		BeltSlope slope = state.get(BeltBlock.SLOPE);
+		return slope == BeltSlope.VERTICAL ? 90
+			: slope == BeltSlope.SIDEWAYS && direction.getAxisDirection() == AxisDirection.NEGATIVE ? 180 : 0;
 	}
 
 	@Override
 	protected int getYRotation(BlockState state) {
 		Boolean casing = state.get(BeltBlock.CASING);
-		Slope slope = state.get(BeltBlock.SLOPE);
+		BeltSlope slope = state.get(BeltBlock.SLOPE);
 
-		boolean flip = casing && slope == Slope.UPWARD;
-		boolean rotate = casing && slope == Slope.VERTICAL;
+		boolean flip = casing && slope == BeltSlope.UPWARD;
+		boolean rotate = casing && slope == BeltSlope.VERTICAL;
 		Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
 		return horizontalAngle(direction) + (flip ? 180 : 0) + (rotate ? 90 : 0);
 	}
@@ -38,26 +36,26 @@ public class BeltGenerator extends SpecialBlockStateGen {
 	public <T extends Block> ModelFile getModel(DataGenContext<Block, T> ctx, RegistrateBlockstateProvider prov,
 		BlockState state) {
 		Boolean casing = state.get(BeltBlock.CASING);
-		BeltBlock.Part part = state.get(BeltBlock.PART);
+		BeltPart part = state.get(BeltBlock.PART);
 		Direction direction = state.get(BeltBlock.HORIZONTAL_FACING);
-		Slope slope = state.get(BeltBlock.SLOPE);
-		boolean downward = slope == Slope.DOWNWARD;
-		boolean diagonal = slope == Slope.UPWARD || downward;
-		boolean vertical = slope == Slope.VERTICAL;
-		boolean pulley = part == Part.PULLEY;
-		boolean sideways = slope == Slope.SIDEWAYS;
+		BeltSlope slope = state.get(BeltBlock.SLOPE);
+		boolean downward = slope == BeltSlope.DOWNWARD;
+		boolean diagonal = slope == BeltSlope.UPWARD || downward;
+		boolean vertical = slope == BeltSlope.VERTICAL;
+		boolean pulley = part == BeltPart.PULLEY;
+		boolean sideways = slope == BeltSlope.SIDEWAYS;
 		boolean negative = direction.getAxisDirection() == AxisDirection.NEGATIVE;
 
 		if (!casing && pulley)
-			part = Part.MIDDLE;
+			part = BeltPart.MIDDLE;
 
-		if ((vertical && negative || casing && downward || sideways && negative) && part != Part.MIDDLE && !pulley)
-			part = part == Part.END ? Part.START : Part.END;
+		if ((vertical && negative || casing && downward || sideways && negative) && part != BeltPart.MIDDLE && !pulley)
+			part = part == BeltPart.END ? BeltPart.START : BeltPart.END;
 
 		if (!casing && vertical)
-			slope = Slope.HORIZONTAL;
+			slope = BeltSlope.HORIZONTAL;
 		if (casing && vertical)
-			slope = Slope.SIDEWAYS;
+			slope = BeltSlope.SIDEWAYS;
 
 		String path = "block/" + (casing ? "belt_casing/" : "belt/");
 		String slopeName = slope.getName();
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java
index 226f2b026..90d18bd81 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltHelper.java
@@ -1,6 +1,5 @@
 package com.simibubi.create.content.contraptions.relays.belt;
 
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.foundation.utility.VecHelper;
 
 import net.minecraft.tileentity.TileEntity;
@@ -42,16 +41,16 @@ public class BeltHelper {
 	public static BlockPos getPositionForOffset(BeltTileEntity controller, int offset) {
 		BlockPos pos = controller.getPos();
 		Vec3i vec = controller.getBeltFacing().getDirectionVec();
-		Slope slope = controller.getBlockState().get(BeltBlock.SLOPE);
-		int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
+		BeltSlope slope = controller.getBlockState().get(BeltBlock.SLOPE);
+		int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0;
 
 		return pos.add(offset * vec.getX(), MathHelper.clamp(offset, 0, controller.beltLength - 1) * verticality,
 				offset * vec.getZ());
 	}
 	
 	public static Vec3d getVectorForOffset(BeltTileEntity controller, float offset) {
-		Slope slope = controller.getBlockState().get(BeltBlock.SLOPE);
-		int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
+		BeltSlope slope = controller.getBlockState().get(BeltBlock.SLOPE);
+		int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0;
 		float verticalMovement = verticality;
 		if (offset < .5)
 			verticalMovement = 0;
@@ -60,7 +59,7 @@ public class BeltHelper {
 		Vec3d vec = VecHelper.getCenterOf(controller.getPos());
 		Vec3d horizontalMovement = new Vec3d(controller.getBeltFacing().getDirectionVec()).scale(offset - .5f);
 		
-		if (slope == Slope.VERTICAL)
+		if (slope == BeltSlope.VERTICAL)
 			horizontalMovement = Vec3d.ZERO;
 		
 		vec = vec.add(horizontalMovement).add(0, verticalMovement, 0);
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java
new file mode 100644
index 000000000..df539fa25
--- /dev/null
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltPart.java
@@ -0,0 +1,14 @@
+package com.simibubi.create.content.contraptions.relays.belt;
+
+import com.simibubi.create.foundation.utility.Lang;
+
+import net.minecraft.util.IStringSerializable;
+
+public enum BeltPart implements IStringSerializable {
+	START, MIDDLE, END, PULLEY;
+
+	@Override
+	public String getName() {
+		return Lang.asId(name());
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java
index cde3ec183..fc42ce225 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltRenderer.java
@@ -12,7 +12,6 @@ import com.simibubi.create.AllSpriteShifts;
 import com.simibubi.create.CreateClient;
 import com.simibubi.create.content.contraptions.base.KineticTileEntity;
 import com.simibubi.create.content.contraptions.base.KineticTileEntityRenderer;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.transport.TransportedItemStack;
 import com.simibubi.create.foundation.tileEntity.renderer.SafeTileEntityRenderer;
 import com.simibubi.create.foundation.utility.AnimationTickHolder;
@@ -63,7 +62,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
 				.getAxisDirection()
 				.getOffset();
 			Direction facing = renderedState.get(BeltBlock.HORIZONTAL_FACING);
-			if (facing.getAxis() == Axis.X && renderedState.get(BeltBlock.SLOPE) != Slope.SIDEWAYS)
+			if (facing.getAxis() == Axis.X && renderedState.get(BeltBlock.SLOPE) != BeltSlope.SIDEWAYS)
 				speed = -speed;
 			int textureIndex = (int) ((speed * time / 36) % 16);
 			if (textureIndex < 0)
@@ -85,7 +84,7 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
 			MatrixStack modelTransform = new MatrixStack();
 			Direction dir = blockState.get(BeltBlock.HORIZONTAL_FACING)
 				.rotateY();
-			if (blockState.get(BeltBlock.SLOPE) == Slope.SIDEWAYS)
+			if (blockState.get(BeltBlock.SLOPE) == BeltSlope.SIDEWAYS)
 				dir = Direction.UP;
 			MatrixStacker msr = MatrixStacker.of(modelTransform);
 
@@ -120,9 +119,9 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
 		Vec3d beltStartOffset = new Vec3d(directionVec).scale(-.5)
 			.add(.5, 13 / 16f + .125f, .5);
 		ms.translate(beltStartOffset.x, beltStartOffset.y, beltStartOffset.z);
-		Slope slope = te.getBlockState()
+		BeltSlope slope = te.getBlockState()
 			.get(BeltBlock.SLOPE);
-		int verticality = slope == Slope.DOWNWARD ? -1 : slope == Slope.UPWARD ? 1 : 0;
+		int verticality = slope == BeltSlope.DOWNWARD ? -1 : slope == BeltSlope.UPWARD ? 1 : 0;
 		boolean slopeAlongX = te.getBeltFacing()
 			.getAxis() == Axis.X;
 
@@ -145,8 +144,8 @@ public class BeltRenderer extends SafeTileEntityRenderer<BeltTileEntity> {
 			verticalMovement = verticalMovement * (Math.min(offset, te.beltLength - .5f) - .5f);
 			Vec3d offsetVec = new Vec3d(directionVec).scale(offset)
 				.add(0, verticalMovement, 0);
-			boolean onSlope = slope != Slope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset;
-			boolean tiltForward = (slope == Slope.DOWNWARD ^ te.getBeltFacing()
+			boolean onSlope = slope != BeltSlope.HORIZONTAL && MathHelper.clamp(offset, .5f, te.beltLength - .5f) == offset;
+			boolean tiltForward = (slope == BeltSlope.DOWNWARD ^ te.getBeltFacing()
 				.getAxisDirection() == AxisDirection.POSITIVE) == (te.getBeltFacing()
 					.getAxis() == Axis.Z);
 			float slopeAngle = onSlope ? tiltForward ? -45 : 45 : 0;
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java
index 49005ee9f..07658e8da 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltShapes.java
@@ -6,8 +6,6 @@ import java.util.HashMap;
 import java.util.Map;
 
 import com.simibubi.create.AllShapes;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.foundation.utility.VoxelShaper;
 
 import net.minecraft.block.BlockState;
@@ -178,41 +176,41 @@ public class BeltShapes {
 	private static VoxelShape getBeltShape(BlockState state) {
 		Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
 		Axis axis = facing.getAxis();
-		Part part = state.get(BeltBlock.PART);
-		Slope slope = state.get(BeltBlock.SLOPE);
+		BeltPart part = state.get(BeltBlock.PART);
+		BeltSlope slope = state.get(BeltBlock.SLOPE);
 
 		//vertical
-		if (slope == Slope.VERTICAL) {
-			if (part == Part.MIDDLE || part == Part.PULLEY)
+		if (slope == BeltSlope.VERTICAL) {
+			if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY)
 				return VERTICAL_FULL.get(axis);
 			//vertical ending
-			return (part == Part.START ? VERTICAL_START : VERTICAL_END).get(facing);
+			return (part == BeltPart.START ? VERTICAL_START : VERTICAL_END).get(facing);
 		}
 
 		//flat part
-		if (slope == Slope.HORIZONTAL) {
-			if (part == Part.MIDDLE || part == Part.PULLEY)
+		if (slope == BeltSlope.HORIZONTAL) {
+			if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY)
 				return FLAT_FULL.get(axis);
 			//flat ending
-			return (part == Part.START ? FLAT_START : FLAT_END).get(facing);
+			return (part == BeltPart.START ? FLAT_START : FLAT_END).get(facing);
 		}
 		
 		//sideways part
-		if (slope == Slope.SIDEWAYS) {
-			if (part == Part.MIDDLE || part == Part.PULLEY)
+		if (slope == BeltSlope.SIDEWAYS) {
+			if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY)
 				return SIDE_FULL.get(axis);
 			//flat ending
-			return (part == Part.START ? SIDE_START : SIDE_END).get(facing);
+			return (part == BeltPart.START ? SIDE_START : SIDE_END).get(facing);
 		}
 
 		//slope
-		if (part == Part.MIDDLE || part == Part.PULLEY)
-			return (slope == Slope.DOWNWARD ? SLOPE_DESC : SLOPE_ASC).get(facing);
+		if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY)
+			return (slope == BeltSlope.DOWNWARD ? SLOPE_DESC : SLOPE_ASC).get(facing);
 		//sloped ending
-		if (part == Part.START)
-			return (slope == Slope.DOWNWARD ? SLOPE_DESC_START : SLOPE_ASC_START).get(facing);
-		if (part == Part.END)
-			return (slope == Slope.DOWNWARD ? SLOPE_DESC_END : SLOPE_ASC_END).get(facing);
+		if (part == BeltPart.START)
+			return (slope == BeltSlope.DOWNWARD ? SLOPE_DESC_START : SLOPE_ASC_START).get(facing);
+		if (part == BeltPart.END)
+			return (slope == BeltSlope.DOWNWARD ? SLOPE_DESC_END : SLOPE_ASC_END).get(facing);
 
 		//bad state
 		return VoxelShapes.empty();
@@ -223,25 +221,25 @@ public class BeltShapes {
 			return VoxelShapes.empty();
 
 		Direction facing = state.get(BeltBlock.HORIZONTAL_FACING);
-		Part part = state.get(BeltBlock.PART);
-		Slope slope = state.get(BeltBlock.SLOPE);
+		BeltPart part = state.get(BeltBlock.PART);
+		BeltSlope slope = state.get(BeltBlock.SLOPE);
 
-		if (slope == Slope.VERTICAL)
+		if (slope == BeltSlope.VERTICAL)
 			return VoxelShapes.empty();
-		if (slope == Slope.SIDEWAYS)
+		if (slope == BeltSlope.SIDEWAYS)
 			return VoxelShapes.empty();
 
-		if (slope == Slope.HORIZONTAL) {
+		if (slope == BeltSlope.HORIZONTAL) {
 			return AllShapes.CASING_11PX.get(Direction.UP);
 		}
 
-		if (part == Part.MIDDLE || part == Part.PULLEY)
-			return PARTIAL_CASING.get(slope == Slope.UPWARD ? facing : facing.getOpposite());
+		if (part == BeltPart.MIDDLE || part == BeltPart.PULLEY)
+			return PARTIAL_CASING.get(slope == BeltSlope.UPWARD ? facing : facing.getOpposite());
 
-		if (part == Part.START)
-			return slope == Slope.UPWARD ? AllShapes.CASING_11PX.get(Direction.UP) : PARTIAL_CASING.get(facing.getOpposite());
-		if (part == Part.END)
-			return slope == Slope.DOWNWARD ? AllShapes.CASING_11PX.get(Direction.UP) : PARTIAL_CASING.get(facing);
+		if (part == BeltPart.START)
+			return slope == BeltSlope.UPWARD ? AllShapes.CASING_11PX.get(Direction.UP) : PARTIAL_CASING.get(facing.getOpposite());
+		if (part == BeltPart.END)
+			return slope == BeltSlope.DOWNWARD ? AllShapes.CASING_11PX.get(Direction.UP) : PARTIAL_CASING.get(facing);
 
 		//something went wrong
 		return VoxelShapes.fullCube();
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java
new file mode 100644
index 000000000..8f934e10f
--- /dev/null
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltSlope.java
@@ -0,0 +1,14 @@
+package com.simibubi.create.content.contraptions.relays.belt;
+
+import com.simibubi.create.foundation.utility.Lang;
+
+import net.minecraft.util.IStringSerializable;
+
+public enum BeltSlope implements IStringSerializable {
+	HORIZONTAL, UPWARD, DOWNWARD, VERTICAL, SIDEWAYS;
+
+	@Override
+	public String getName() {
+		return Lang.asId(name());
+	}
+}
\ No newline at end of file
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java
index 8d7b2347e..fbade212a 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltTileEntity.java
@@ -1,10 +1,7 @@
 package com.simibubi.create.content.contraptions.relays.belt;
 
-import static com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part.END;
-import static com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part.MIDDLE;
-import static com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope.DOWNWARD;
-import static com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope.HORIZONTAL;
-import static com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope.UPWARD;
+import static com.simibubi.create.content.contraptions.relays.belt.BeltPart.MIDDLE;
+import static com.simibubi.create.content.contraptions.relays.belt.BeltSlope.HORIZONTAL;
 import static net.minecraft.util.Direction.AxisDirection.NEGATIVE;
 import static net.minecraft.util.Direction.AxisDirection.POSITIVE;
 
@@ -16,8 +13,6 @@ import java.util.function.Function;
 
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.content.contraptions.base.KineticTileEntity;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.transport.BeltInventory;
 import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler;
 import com.simibubi.create.content.contraptions.relays.belt.transport.BeltMovementHandler.TransportedEntityInfo;
@@ -286,7 +281,7 @@ public class BeltTileEntity extends KineticTileEntity {
 	public boolean hasPulley() {
 		if (!AllBlocks.BELT.has(getBlockState()))
 			return false;
-		return getBlockState().get(BeltBlock.PART) != Part.MIDDLE;
+		return getBlockState().get(BeltBlock.PART) != BeltPart.MIDDLE;
 	}
 
 	protected boolean isLastBelt() {
@@ -294,16 +289,16 @@ public class BeltTileEntity extends KineticTileEntity {
 			return false;
 
 		Direction direction = getBeltFacing();
-		if (getBlockState().get(BeltBlock.SLOPE) == Slope.VERTICAL)
+		if (getBlockState().get(BeltBlock.SLOPE) == BeltSlope.VERTICAL)
 			return false;
 
-		Part part = getBlockState().get(BeltBlock.PART);
+		BeltPart part = getBlockState().get(BeltBlock.PART);
 		if (part == MIDDLE)
 			return false;
 
 		boolean movingPositively = (getSpeed() > 0 == (direction.getAxisDirection()
 			.getOffset() == 1)) ^ direction.getAxis() == Axis.X;
-		return part == Part.START ^ movingPositively;
+		return part == BeltPart.START ^ movingPositively;
 	}
 
 	public Vec3i getMovementDirection(boolean firstHalf) {
@@ -320,8 +315,8 @@ public class BeltTileEntity extends KineticTileEntity {
 
 		final BlockState blockState = getBlockState();
 		final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
-		final Slope slope = blockState.get(BeltBlock.SLOPE);
-		final Part part = blockState.get(BeltBlock.PART);
+		final BeltSlope slope = blockState.get(BeltBlock.SLOPE);
+		final BeltPart part = blockState.get(BeltBlock.PART);
 		final Axis axis = beltFacing.getAxis();
 
 		Direction movementFacing = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
@@ -330,9 +325,9 @@ public class BeltTileEntity extends KineticTileEntity {
 			movementFacing = movementFacing.getOpposite();
 		Vec3i movement = movementFacing.getDirectionVec();
 
-		boolean slopeBeforeHalf = (part == END) == (beltFacing.getAxisDirection() == POSITIVE);
+		boolean slopeBeforeHalf = (part == BeltPart.END) == (beltFacing.getAxisDirection() == POSITIVE);
 		boolean onSlope = notHorizontal && (part == MIDDLE || slopeBeforeHalf == firstHalf || ignoreHalves);
-		boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? UPWARD : DOWNWARD);
+		boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? BeltSlope.UPWARD : BeltSlope.DOWNWARD);
 
 		if (!onSlope)
 			return movement;
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java
index e9aa45bbb..9f51af84f 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/item/BeltConnectorItem.java
@@ -9,8 +9,8 @@ import com.simibubi.create.AllBlocks;
 import com.simibubi.create.Create;
 import com.simibubi.create.content.contraptions.base.KineticTileEntity;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
+import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
 import com.simibubi.create.foundation.advancement.AllTriggers;
 import com.simibubi.create.foundation.config.AllConfigs;
@@ -118,7 +118,7 @@ public class BeltConnectorItem extends BlockItem {
 
 	public static void createBelts(World world, BlockPos start, BlockPos end) {
 
-		BeltBlock.Slope slope = getSlopeBetween(start, end);
+		BeltSlope slope = getSlopeBetween(start, end);
 		Direction facing = getFacingFromTo(start, end);
 
 		BlockPos diff = end.subtract(start);
@@ -130,13 +130,13 @@ public class BeltConnectorItem extends BlockItem {
 		BlockState beltBlock = AllBlocks.BELT.getDefaultState();
 
 		for (BlockPos pos : beltsToCreate) {
-			BeltBlock.Part part = pos.equals(start) ? Part.START : pos.equals(end) ? Part.END : Part.MIDDLE;
+			BeltPart part = pos.equals(start) ? BeltPart.START : pos.equals(end) ? BeltPart.END : BeltPart.MIDDLE;
 			BlockState shaftState = world.getBlockState(pos);
 			boolean pulley = ShaftBlock.isShaft(shaftState);
-			if (part == Part.MIDDLE && pulley)
-				part = Part.PULLEY;
+			if (part == BeltPart.MIDDLE && pulley)
+				part = BeltPart.PULLEY;
 			if (pulley && shaftState.get(ShaftBlock.AXIS) == Axis.Y)
-				slope = Slope.SIDEWAYS;
+				slope = BeltSlope.SIDEWAYS;
 			world.setBlockState(pos, beltBlock.with(BeltBlock.SLOPE, slope)
 				.with(BeltBlock.PART, part)
 				.with(BeltBlock.HORIZONTAL_FACING, facing), 3);
@@ -157,18 +157,18 @@ public class BeltConnectorItem extends BlockItem {
 		return Direction.getFacingFromAxis(axisDirection, beltAxis);
 	}
 
-	private static Slope getSlopeBetween(BlockPos start, BlockPos end) {
+	private static BeltSlope getSlopeBetween(BlockPos start, BlockPos end) {
 		BlockPos diff = end.subtract(start);
 
 		if (diff.getY() != 0) {
 			if (diff.getZ() != 0 || diff.getX() != 0)
-				return diff.getY() > 0 ? Slope.UPWARD : Slope.DOWNWARD;
-			return Slope.VERTICAL;
+				return diff.getY() > 0 ? BeltSlope.UPWARD : BeltSlope.DOWNWARD;
+			return BeltSlope.VERTICAL;
 		}
-		return Slope.HORIZONTAL;
+		return BeltSlope.HORIZONTAL;
 	}
 
-	private static List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, Slope slope, Direction direction) {
+	private static List<BlockPos> getBeltChainBetween(BlockPos start, BlockPos end, BeltSlope slope, Direction direction) {
 		List<BlockPos> positions = new LinkedList<>();
 		int limit = 1000;
 		BlockPos current = start;
@@ -176,14 +176,14 @@ public class BeltConnectorItem extends BlockItem {
 		do {
 			positions.add(current);
 
-			if (slope == Slope.VERTICAL) {
+			if (slope == BeltSlope.VERTICAL) {
 				current = current.up(direction.getAxisDirection() == AxisDirection.POSITIVE ? 1 : -1);
 				continue;
 			}
 
 			current = current.offset(direction);
-			if (slope != Slope.HORIZONTAL)
-				current = current.up(slope == Slope.UPWARD ? 1 : -1);
+			if (slope != BeltSlope.HORIZONTAL)
+				current = current.up(slope == BeltSlope.UPWARD ? 1 : -1);
 
 		} while (!current.equals(end) && limit-- > 0);
 
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java
index 17e843956..2efb20fdf 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltInventory.java
@@ -11,9 +11,9 @@ import java.util.function.Function;
 
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
 import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
 import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour;
 import com.simibubi.create.foundation.tileEntity.behaviour.belt.BeltProcessingBehaviour.ProcessingResult;
@@ -73,7 +73,7 @@ public class BeltInventory {
 		float beltSpeed = belt.getDirectionAwareBeltMovementSpeed();
 		Direction movementFacing = belt.getMovementFacing();
 		boolean horizontal = belt.getBlockState()
-			.get(BeltBlock.SLOPE) == Slope.HORIZONTAL;
+			.get(BeltBlock.SLOPE) == BeltSlope.HORIZONTAL;
 		float spacing = 1;
 		World world = belt.getWorld();
 		boolean onClient = world.isRemote;
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java
index e41aa44ee..cbea2b1dc 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltMovementHandler.java
@@ -9,9 +9,9 @@ import java.util.List;
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionEntity;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
+import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 
 import net.minecraft.block.BlockState;
 import net.minecraft.entity.Entity;
@@ -84,7 +84,7 @@ public class BeltMovementHandler {
 		}
 
 		// Too slow
-		boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != Slope.HORIZONTAL;
+		boolean notHorizontal = beltTe.getBlockState().get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL;
 		if (Math.abs(beltTe.getSpeed()) < 1)
 			return;
 
@@ -99,7 +99,7 @@ public class BeltMovementHandler {
 		}
 
 		final Direction beltFacing = blockState.get(BlockStateProperties.HORIZONTAL_FACING);
-		final Slope slope = blockState.get(BeltBlock.SLOPE);
+		final BeltSlope slope = blockState.get(BeltBlock.SLOPE);
 		final Axis axis = beltFacing.getAxis();
 		float movementSpeed = beltTe.getBeltMovementSpeed();
 		final Direction movementDirection = Direction.getFacingFromAxis(axis == Axis.X ? NEGATIVE : POSITIVE, axis);
@@ -112,14 +112,14 @@ public class BeltMovementHandler {
 		if (Math.abs(diffCenter) > 48 / 64f)
 			return;
 
-		Part part = blockState.get(BeltBlock.PART);
+		BeltPart part = blockState.get(BeltBlock.PART);
 		float top = 13 / 16f;
-		boolean onSlope = notHorizontal && (part == Part.MIDDLE || part == Part.PULLEY
-				|| part == (slope == Slope.UPWARD ? Part.END : Part.START) && entityIn.getY() - pos.getY() < top
-				|| part == (slope == Slope.UPWARD ? Part.START : Part.END) && entityIn.getY() - pos.getY() > top);
+		boolean onSlope = notHorizontal && (part == BeltPart.MIDDLE || part == BeltPart.PULLEY
+				|| part == (slope == BeltSlope.UPWARD ? BeltPart.END : BeltPart.START) && entityIn.getY() - pos.getY() < top
+				|| part == (slope == BeltSlope.UPWARD ? BeltPart.START : BeltPart.END) && entityIn.getY() - pos.getY() > top);
 
-		boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? Slope.DOWNWARD : Slope.UPWARD);
-		boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? Slope.UPWARD : Slope.DOWNWARD);
+		boolean movingDown = onSlope && slope == (movementFacing == beltFacing ? BeltSlope.DOWNWARD : BeltSlope.UPWARD);
+		boolean movingUp = onSlope && slope == (movementFacing == beltFacing ? BeltSlope.UPWARD : BeltSlope.DOWNWARD);
 
 		if (beltFacing.getAxis() == Axis.Z) {
 			boolean b = movingDown;
diff --git a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java
index 4fa3cca53..533cfcd25 100644
--- a/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java
+++ b/src/main/java/com/simibubi/create/content/contraptions/relays/belt/transport/BeltTunnelInteractionHandler.java
@@ -1,9 +1,9 @@
 package com.simibubi.create.content.contraptions.relays.belt.transport;
 
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
 import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelBlock;
 import com.simibubi.create.content.logistics.block.belts.tunnel.BeltTunnelTileEntity;
 import com.simibubi.create.content.logistics.block.belts.tunnel.BrassTunnelBlock;
@@ -60,7 +60,7 @@ public class BeltTunnelInteractionHandler {
 	public static void flapTunnel(BeltInventory beltInventory, int offset, Direction side, boolean inward) {
 		BeltTileEntity belt = beltInventory.belt;
 		if (belt.getBlockState()
-			.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
+			.get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL)
 			return;
 		BlockPos pos = BeltHelper.getPositionForOffset(belt, offset)
 			.up();
diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverBlock.java
index 3ca73f773..99949c701 100644
--- a/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverBlock.java
+++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/observer/BeltObserverBlock.java
@@ -3,8 +3,8 @@ package com.simibubi.create.content.logistics.block.belts.observer;
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.AllTileEntities;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
+import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.content.contraptions.wrench.IWrenchable;
 import com.simibubi.create.foundation.block.ITE;
 import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@@ -77,9 +77,9 @@ public class BeltObserverBlock extends HorizontalBlock
 
 		if (!AllBlocks.BELT.has(blockState))
 			return false;
-		if (blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
+		if (blockState.get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL)
 			return false;
-		if (blockState.get(BeltBlock.PART) != Part.MIDDLE)
+		if (blockState.get(BeltBlock.PART) != BeltPart.MIDDLE)
 			return false;
 		if (blockState.get(BeltBlock.HORIZONTAL_FACING).getAxis() == direction.getAxis())
 			return false;
@@ -99,7 +99,7 @@ public class BeltObserverBlock extends HorizontalBlock
 			BlockState blockState = context.getWorld().getBlockState(context.getPos().offset(face));
 			if (AllBlocks.BELT.has(blockState)
 					&& blockState.get(BlockStateProperties.HORIZONTAL_FACING).getAxis() != face.getAxis()
-					&& blockState.get(BeltBlock.SLOPE) == Slope.HORIZONTAL)
+					&& blockState.get(BeltBlock.SLOPE) == BeltSlope.HORIZONTAL)
 				if (preferredFacing == null)
 					preferredFacing = face;
 				else {
diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java
index f3ef9e2a6..b25c6d32b 100644
--- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java
+++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BeltTunnelBlock.java
@@ -3,7 +3,7 @@ package com.simibubi.create.content.logistics.block.belts.tunnel;
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.AllTileEntities;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.content.contraptions.wrench.IWrenchable;
 import com.simibubi.create.content.logistics.block.funnel.BeltFunnelBlock;
 import com.simibubi.create.foundation.block.ITE;
@@ -80,7 +80,7 @@ public class BeltTunnelBlock extends Block implements ITE<BeltTunnelTileEntity>,
 		BlockState blockState = worldIn.getBlockState(pos.down());
 		if (!AllBlocks.BELT.has(blockState))
 			return false;
-		if (blockState.get(BeltBlock.SLOPE) != Slope.HORIZONTAL)
+		if (blockState.get(BeltBlock.SLOPE) != BeltSlope.HORIZONTAL)
 			return false;
 		return true;
 	}
diff --git a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java
index e5bda8728..ada0f6279 100644
--- a/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java
+++ b/src/main/java/com/simibubi/create/content/logistics/block/belts/tunnel/BrassTunnelTileEntity.java
@@ -8,9 +8,13 @@ import javax.annotation.Nullable;
 import org.apache.commons.lang3.tuple.Pair;
 
 import com.simibubi.create.AllBlocks;
+import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
+import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
 import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
+import com.simibubi.create.foundation.tileEntity.behaviour.belt.DirectBeltInputBehaviour;
 import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBehaviour;
 import com.simibubi.create.foundation.tileEntity.behaviour.filtering.SidedFilteringBehaviour;
+import com.simibubi.create.foundation.utility.Iterate;
 import com.simibubi.create.foundation.utility.NBTHelper;
 
 import net.minecraft.block.BlockState;
@@ -44,6 +48,21 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
 		stackToDistribute = ItemStack.EMPTY;
 	}
 
+//	@Override
+//	public void tick() {
+//		super.tick();
+//
+//		if (stackToDistribute.isEmpty())
+//			return;
+//		if (distributionProgress == -1) {
+//			distributionTargets.clear();
+//			for (Pair<BrassTunnelTileEntity, Direction> pair : gatherValidOutputs()) {
+//				
+//			}
+//		}
+//
+//	}
+
 	@Override
 	public void initialize() {
 		if (filtering == null) {
@@ -52,7 +71,7 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
 		}
 		super.initialize();
 	}
-	
+
 	public boolean canInsert(Direction side, ItemStack stack) {
 		if (filtering != null && !filtering.test(side, stack))
 			return false;
@@ -62,7 +81,60 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
 			return false;
 		return true;
 	}
-	
+
+	public boolean onItemInserted(ItemStack stack) {
+		if (!connectedLeft && !connectedRight)
+			return false;
+		stackToDistribute = stack.copy();
+		sendData();
+		markDirty();
+		return true;
+	}
+
+	private List<Pair<BrassTunnelTileEntity, Direction>> gatherValidOutputs() {
+		List<Pair<BrassTunnelTileEntity, Direction>> validOutputs = new ArrayList<>();
+		addValidOutputsOf(this, validOutputs);
+		for (boolean left : Iterate.trueAndFalse) {
+			BrassTunnelTileEntity adjacent = this;
+			while (adjacent != null) {
+				if (!world.isAreaLoaded(adjacent.getPos(), 1))
+					return null;
+				adjacent = adjacent.getAdjacent(left);
+				if (adjacent != null)
+					addValidOutputsOf(adjacent, validOutputs);
+			}
+		}
+		return validOutputs;
+	}
+
+	private void addValidOutputsOf(BrassTunnelTileEntity tunnelTE,
+		List<Pair<BrassTunnelTileEntity, Direction>> validOutputs) {
+		BeltTileEntity below = BeltHelper.getSegmentTE(world, tunnelTE.pos.down());
+		if (below == null)
+			return;
+		if (below.getSpeed() != 0) {
+			Direction direction = below.getMovementFacing();
+			if (tunnelTE.flaps.containsKey(direction))
+				validOutputs.add(Pair.of(tunnelTE, direction));
+		}
+
+		BlockState blockState = getBlockState();
+		if (!AllBlocks.BRASS_TUNNEL.has(blockState))
+			return;
+		for (boolean left : Iterate.trueAndFalse) {
+			Axis axis = blockState.get(BrassTunnelBlock.HORIZONTAL_AXIS);
+			Direction baseDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
+			Direction direction = left ? baseDirection.rotateYCCW() : baseDirection.rotateY();
+			if (tunnelTE.flaps.containsKey(direction)) {
+				DirectBeltInputBehaviour inputBehaviour = TileEntityBehaviour.get(world, tunnelTE.pos.down()
+					.offset(direction), DirectBeltInputBehaviour.TYPE);
+				if (inputBehaviour.canInsertFromSide(direction))
+					validOutputs.add(Pair.of(tunnelTE, direction));
+			}
+		}
+
+	}
+
 	@Override
 	public void addBehavioursDeferred(List<TileEntityBehaviour> behaviours) {
 		super.addBehavioursDeferred(behaviours);
@@ -185,9 +257,9 @@ public class BrassTunnelTileEntity extends BeltTunnelTileEntity {
 		Axis axis = blockState.get(BrassTunnelBlock.HORIZONTAL_AXIS);
 		Direction baseDirection = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
 		Direction direction = leftSide ? baseDirection.rotateYCCW() : baseDirection.rotateY();
-
 		BlockPos adjacentPos = pos.offset(direction);
 		BlockState adjacentBlockState = world.getBlockState(adjacentPos);
+
 		if (!AllBlocks.BRASS_TUNNEL.has(adjacentBlockState))
 			return null;
 		if (adjacentBlockState.get(BrassTunnelBlock.HORIZONTAL_AXIS) != axis)
diff --git a/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java b/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java
index a685417fc..c106c0046 100644
--- a/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java
+++ b/src/main/java/com/simibubi/create/content/schematics/block/LaunchedItem.java
@@ -4,7 +4,7 @@ import java.util.Optional;
 
 import com.simibubi.create.AllBlocks;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
+import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
 import com.simibubi.create.content.contraptions.relays.belt.item.BeltConnectorItem;
 import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
 
@@ -172,7 +172,7 @@ public abstract class LaunchedItem {
 		@Override
 		void place(World world) {
 			// todo place belt
-			boolean isStart = state.get(BeltBlock.PART) == Part.START;
+			boolean isStart = state.get(BeltBlock.PART) == BeltPart.START;
 			BlockPos offset = BeltBlock.nextSegmentPosition(state, BlockPos.ZERO, isStart);
 			int i = length - 1;
 			Axis axis = state.get(BeltBlock.HORIZONTAL_FACING).rotateY().getAxis();
diff --git a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java
index e8c11e98b..c28ad8bc9 100644
--- a/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java
+++ b/src/main/java/com/simibubi/create/content/schematics/block/SchematicannonTileEntity.java
@@ -7,9 +7,9 @@ import com.simibubi.create.AllBlocks;
 import com.simibubi.create.AllItems;
 import com.simibubi.create.AllSoundEvents;
 import com.simibubi.create.content.contraptions.relays.belt.BeltBlock;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Part;
-import com.simibubi.create.content.contraptions.relays.belt.BeltBlock.Slope;
 import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
+import com.simibubi.create.content.contraptions.relays.belt.BeltPart;
+import com.simibubi.create.content.contraptions.relays.belt.BeltSlope;
 import com.simibubi.create.content.contraptions.relays.elementary.ShaftBlock;
 import com.simibubi.create.content.schematics.ItemRequirement;
 import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
@@ -481,10 +481,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
 		// is highest belt?
 		boolean isLastSegment = false;
 		Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
-		Slope slope = blockState.get(BeltBlock.SLOPE);
+		BeltSlope slope = blockState.get(BeltBlock.SLOPE);
 		boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE;
-		boolean start = blockState.get(BeltBlock.PART) == Part.START;
-		boolean end = blockState.get(BeltBlock.PART) == Part.END;
+		boolean start = blockState.get(BeltBlock.PART) == BeltPart.START;
+		boolean end = blockState.get(BeltBlock.PART) == BeltPart.END;
 
 		switch (slope) {
 		case DOWNWARD:
@@ -499,7 +499,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
 			isLastSegment = positive && end || !positive && start;
 		}
 		if (!isLastSegment)
-			blockState = (blockState.get(BeltBlock.PART) == Part.MIDDLE) ? Blocks.AIR.getDefaultState()
+			blockState = (blockState.get(BeltBlock.PART) == BeltPart.MIDDLE) ? Blocks.AIR.getDefaultState()
 				: AllBlocks.SHAFT.getDefaultState()
 					.with(ShaftBlock.AXIS, facing.rotateY()
 						.getAxis());