diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..1472a12c22f1f63098fa9cd97f7aa6ea7ba6e4c9
--- /dev/null
+++ b/README.md
@@ -0,0 +1,18 @@
+![logo](https://gitlab.insrt.uk/insert-mc/red.net/raw/master/res/logo.gif)
+
+# Red.NET
+
+> Minecraft mod which bridges web applications and redstone machines together.
+
+## Features
+
+* High customisability throughout different the mod.
+* Receiver block which lets you query web services.
+* Sender block which lets you send information out.
+- All features available on the wiki: [WIKI LINK](https://example.com)
+
+## Downloading
+
+You can find downloads in [tags section](https://gitlab.insrt.uk/insert-mc/red.net/tags)
+
+For more information about downloads, and for developer information [see the wiki.](https://gitlab.insrt.uk/insert-mc/red.net/wikis)
\ No newline at end of file
diff --git a/res/logo.gif b/res/logo.gif
new file mode 100644
index 0000000000000000000000000000000000000000..5bf52d74218d6d504eb4f241e1abdd22ab34b7df
Binary files /dev/null and b/res/logo.gif differ
diff --git a/res/logo.png b/res/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..1f79c8561a7c9467a9fa282ee0176521d0eb7241
Binary files /dev/null and b/res/logo.png differ
diff --git a/src/main/java/uk/insrt/minecraft/rednet/game/blocks/BlockReceiver.java b/src/main/java/uk/insrt/minecraft/rednet/game/blocks/BlockReceiver.java
index ed043e69f3d70095c3856b9287a64e8dceca59ef..a55482100bfb2714b16248bfef309214151d3e8f 100644
--- a/src/main/java/uk/insrt/minecraft/rednet/game/blocks/BlockReceiver.java
+++ b/src/main/java/uk/insrt/minecraft/rednet/game/blocks/BlockReceiver.java
@@ -1,5 +1,7 @@
 package uk.insrt.minecraft.rednet.game.blocks;
 
+import java.time.Instant;
+
 import net.minecraft.block.material.Material;
 import net.minecraft.block.properties.IProperty;
 import net.minecraft.block.properties.PropertyDirection;
@@ -8,17 +10,23 @@ import net.minecraft.block.state.BlockStateContainer;
 import net.minecraft.block.state.IBlockState;
 import net.minecraft.creativetab.CreativeTabs;
 import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
 import net.minecraft.item.ItemStack;
 import net.minecraft.util.BlockRenderLayer;
 import net.minecraft.util.EnumFacing;
+import net.minecraft.util.EnumHand;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.util.math.MathHelper;
+import net.minecraft.util.text.TextComponentString;
 import net.minecraft.world.IBlockAccess;
 import net.minecraft.world.World;
 import net.minecraftforge.fml.relauncher.Side;
 import net.minecraftforge.fml.relauncher.SideOnly;
+import uk.insrt.minecraft.inslib.Main;
 import uk.insrt.minecraft.inslib.game.BaseTileEntity;
+import uk.insrt.minecraft.inslib.helpers.MessageBuilder;
 import uk.insrt.minecraft.rednet.INF;
+import uk.insrt.minecraft.rednet.game.commands.CommandConfigureReceiver;
 import uk.insrt.minecraft.rednet.game.tiles.TileEntityReceiver;
 
 public class BlockReceiver extends BaseTileEntity<TileEntityReceiver> {
@@ -105,12 +113,49 @@ public class BlockReceiver extends BaseTileEntity<TileEntityReceiver> {
 	public int getWeakPower(IBlockState state, IBlockAccess worldIn, BlockPos pos, EnumFacing side) {
 		if (!(worldIn instanceof World)) return 0;
 		World world = (World) worldIn;
-		
+
 		TileEntityReceiver tile = getTileEntity(world, pos);
-		//
+		if (tile.isHigh()) {
+			int sides = tile.getSides();
+			int offset = ((EnumFacing) state.getValue(FACING)).getHorizontalIndex();
+			for (int i=0;i<4;i++) {
+				EnumFacing facing = EnumFacing.getHorizontal(i + offset);
+				int val = (sides >> i) & 3;
+				if (val == 1 && side.getHorizontalIndex() == facing.getHorizontalIndex()) {
+					return 15;
+				}
+			}
+		}
 		
 	    return 0;
 	}
+
+	@Override
+	public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) {
+		if (!world.isRemote) {
+			TileEntityReceiver tile = getTileEntity(world, pos);
+			if (player.isSneaking()) {
+				CommandConfigureReceiver.hashMap.put(player.getUniqueID(), tile);
+				player.sendMessage(new MessageBuilder("Selected receiver, do /confrc help for more information").getComponent());
+				return true;
+			}
+			String url = tile.getURL();
+			if (url.length() < 1) url = "<none specified>";
+			player.sendMessage(new TextComponentString("URL: " + url + ", outputting " + (tile.isHigh() ? "high" : "low") + " power!"));
+			String err = tile.getError();
+			if (err.length() > 0) {
+				player.sendMessage(new TextComponentString("Last error: (cleared on success)"));
+				player.sendMessage(new TextComponentString(err));
+			}
+			long last = tile.getLastRun();
+			if (last > 0) {
+				long calc = Instant.now().getEpochSecond() - last;
+				String s = calc == 1 ? "" : "s";
+				new MessageBuilder("Last run was " + calc + " second" + s + " ago!").send(player);
+			}
+		}
+		return true;
+	}
 	
 	/**
 	 * BLOCK STATES
@@ -125,16 +170,13 @@ public class BlockReceiver extends BaseTileEntity<TileEntityReceiver> {
 	public IBlockState getStateFromMeta(int meta) {
 		EnumFacing enumfacing = EnumFacing.getFront(meta);
 
-	    if (enumfacing.getAxis() == EnumFacing.Axis.Y)
-	    {
-	        enumfacing = EnumFacing.NORTH;
-	    }
+	    if (enumfacing.getAxis() == EnumFacing.Axis.Y) enumfacing = EnumFacing.NORTH;
 	    
 	    return this.getDefaultState().withProperty(FACING, enumfacing);
 	}
 	
 	private void orientateBlockState(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer) {
-		EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor((double)(placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3);
+		EnumFacing enumfacing = EnumFacing.getHorizontal(MathHelper.floor((double) (placer.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3);
 	    worldIn.setBlockState(pos, state.withProperty(FACING, enumfacing), 3);
 	}
 
diff --git a/src/main/java/uk/insrt/minecraft/rednet/game/commands/CommandConfigureReceiver.java b/src/main/java/uk/insrt/minecraft/rednet/game/commands/CommandConfigureReceiver.java
index cc5842cd427ec5734825199d7325e96c68ad1f5e..aac249158dd078726222bf16cba68bb11d3a4754 100644
--- a/src/main/java/uk/insrt/minecraft/rednet/game/commands/CommandConfigureReceiver.java
+++ b/src/main/java/uk/insrt/minecraft/rednet/game/commands/CommandConfigureReceiver.java
@@ -49,8 +49,7 @@ public class CommandConfigureReceiver implements ICommand {
 
 	@Override
 	public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
-		return;
-		/*World world = sender.getEntityWorld();
+		World world = sender.getEntityWorld();
 		if (world.isRemote) return;
 		UUID uuid = sender.getCommandSenderEntity().getUniqueID();
 		if (hashMap.containsKey(uuid)) {
@@ -105,7 +104,7 @@ public class CommandConfigureReceiver implements ICommand {
 			hashMap.remove(uuid);
 		} else {
 			sender.sendMessage(new TextComponentString("No receiver selected! Right-click top of receiver to select."));
-		}*/
+		}
 	}
 
 	@Override
diff --git a/src/main/java/uk/insrt/minecraft/rednet/game/tiles/TileEntityReceiver.java b/src/main/java/uk/insrt/minecraft/rednet/game/tiles/TileEntityReceiver.java
index fe8a818a811e28f247dfaf4f8eeec241e98a44cb..1c5f18df653172c0d8918a546d88ee8b944ca180 100644
--- a/src/main/java/uk/insrt/minecraft/rednet/game/tiles/TileEntityReceiver.java
+++ b/src/main/java/uk/insrt/minecraft/rednet/game/tiles/TileEntityReceiver.java
@@ -4,13 +4,16 @@ import java.io.BufferedReader;
 import java.io.InputStreamReader;
 import java.net.URL;
 import java.net.URLConnection;
+import java.time.Instant;
 
 import net.minecraft.block.state.IBlockState;
 import net.minecraft.nbt.NBTTagCompound;
 import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumFacing;
 import net.minecraft.util.ITickable;
 import net.minecraft.util.math.BlockPos;
 import net.minecraft.world.World;
+import uk.insrt.minecraft.inslib.Main;
 import uk.insrt.minecraft.rednet.game.blocks.BlockReceiver;
 
 public class TileEntityReceiver extends TileEntity implements ITickable {
@@ -27,17 +30,20 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 * TILE ENTITY
 	 */
 	
-	private String  URL;
-	private String  LAST_ERROR;
-	private boolean HIGH;
-	private boolean DISABLED;
-	private int     UPDATE_TICKS;
-	private int     SIDES;
+	// NBT values
+	private String  URL          = "";
+	private boolean HIGH         = false;
+	private boolean DISABLED     = false;
+	private int     UPDATE_TICKS = 0;
+	private int     SIDES        = 1 << 2;
+	
+	// Non-NBT values
+	private String  LAST_ERROR   = "";
+	private long    LAST_RUN     = 0;
 	
 	@Override
 	public NBTTagCompound writeToNBT(NBTTagCompound ntc) {
 		ntc.setString  ("url",         URL);
-		ntc.setString  ("lastError",   LAST_ERROR);
 		ntc.setBoolean ("high",        HIGH);
 		ntc.setBoolean ("disabled",    DISABLED);
 		ntc.setInteger ("updateTicks", UPDATE_TICKS);
@@ -52,7 +58,7 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 		DISABLED     = ntc.getBoolean ("disabled");
 		UPDATE_TICKS = ntc.getInteger ("updateTicks");
 		SIDES        = ntc.getInteger ("sides");
-		LAST_ERROR   = ntc.getString  ("lastError");
+		if (!ntc.hasKey("sides")) setSides();
 		super.readFromNBT(ntc);
 	}
 	
@@ -74,13 +80,23 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 */
 	
 	public void updateBlockState() {
-		IBlockState oldState = getBlockState();
-		world.setBlockState(pos, getBlockState());
-		world.notifyBlockUpdate(pos, oldState, getBlockState(), 0);
+		// ONLY UPDATE REMOTELY, ONLY THE SERVER HAS TILE ENTITY DATA!!!
+		if (world.isRemote) return;
+		BlockReceiver block = (BlockReceiver) blockType;
+		IBlockState state = getBlockState();
+		world.setBlockState(pos, state
+				.withProperty(block.SIDELEFT,   SIDES       & 3)
+				.withProperty(block.SIDEBACK,  (SIDES >> 2) & 3)
+				.withProperty(block.SIDERIGHT, (SIDES >> 4) & 3)
+				.withProperty(block.SIDEFRONT, (SIDES >> 6) & 3));
+		world.notifyBlockUpdate(pos, state, getBlockState(), 0);
+	}
+	
+	public void notifyRedstoneUpdate() {
+		world.notifyNeighborsOfStateChange(getPos(), getBlockType(), true);
 	}
 	
 	public IBlockState getBlockState() {
-		BlockReceiver block = (BlockReceiver) blockType;
 		return world.getBlockState(pos);
 	}
 	
@@ -88,9 +104,54 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 * TILE ENTITY
 	 */
 	
+	private int blockTicks = 0;
+	private int ticks = 0;
+	
 	@Override
 	public void update() {
-		//
+		// Only run remotely
+		if (world.isRemote) return;
+		// Update block state periodically until we are certain there are no issues.
+		if (blockTicks < 120) {
+			blockTicks++;
+			if (blockTicks % 40 == 0) {
+				updateBlockState();
+			}
+		}
+		// Time-keeping
+		ticks++;
+		boolean fire = false;
+		if (ticks > UPDATE_TICKS) {
+			ticks = 0;
+			fire = true;
+		}
+		// Get block
+		BlockReceiver block = (BlockReceiver) getBlockType();
+		IBlockState state = getBlockState();
+		int offset = ((EnumFacing) state.getValue(block.FACING)).getHorizontalIndex();
+		// Check for redstone
+		boolean disabled = isDisabled();
+		for (int i=0;i<4;i++) {
+			EnumFacing facing = EnumFacing.getHorizontal(i + offset - 1);
+			BlockPos sideBlock = pos.offset(facing);
+			boolean powered = world.isBlockPowered(sideBlock);
+			if (!powered) continue;
+			int side = (SIDES >> (i * 2)) & 3;
+			switch (side) {
+				case 2:
+					fire = true;
+					break;
+				case 3:
+					disabled = true; 
+					break;
+			}
+		}
+		// Make sure to disable if needs be
+		if (disabled != isDisabled()) setDisabled(disabled);
+		// Fire updates
+		if (fire && !DISABLED && UPDATE_TICKS > 0) {
+			fireUpdate();
+		}
 	}
 	
 	/**
@@ -98,13 +159,13 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 */
 	
 	public void fireUpdate() {
-		/*if (url.length() > 0) {
+		if (URL.length() > 0) {
 			if (!runningUpdate) {
 				runningUpdate = true;
 				Thread webUpdateThread = new WebUpdateThread();
 				webUpdateThread.start();
 			}
-		}*/
+		}
 	}
 
 	/***
@@ -123,6 +184,7 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	
 	class WebUpdateThread extends Thread {
 		public void run() {
+			updateRun();
 			try {
 				URL url = new URL(URL);
 		        URLConnection connection = url.openConnection();
@@ -136,9 +198,9 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 		        if (fullInput.contains("true")) {
 		        	setHigh(true);
 		        } else {
-		        	setHigh(false);
+		        	setHigh();
 		        }
-		        setError("");
+		        setError();
 			} catch (Exception e) {
 				runningUpdate = false;
 				setError(e.getMessage());
@@ -162,6 +224,7 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	public String getError() { return LAST_ERROR; }
 	public Boolean isHigh() { return HIGH; }
 	public Boolean isDisabled() { return DISABLED; }
+	public long getLastRun() { return LAST_RUN; }
 	public int getTicks() { return UPDATE_TICKS; }
 	public int getSides() { return SIDES; }
 	
@@ -170,9 +233,10 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 */
 	
 	public void setURL(String url) { URL = url; markDirty(); }
-	public void setError(String error) { LAST_ERROR = error; markDirty(); }
-	public void setHigh(Boolean high) { HIGH = high; markDirty(); updateBlockState(); }
+	public void setError(String error) { LAST_ERROR = error; }
+	public void setHigh(Boolean high) { HIGH = high; markDirty(); notifyRedstoneUpdate(); }
 	public void setDisabled(Boolean disabled) { DISABLED = disabled; markDirty(); }
+	public void updateRun(long run) { LAST_RUN = run; }
 	public void setTicks(int ticks) { UPDATE_TICKS = ticks; markDirty(); }
 	public void setSides(int sides) { SIDES = sides; markDirty(); updateBlockState(); }
 	
@@ -181,10 +245,11 @@ public class TileEntityReceiver extends TileEntity implements ITickable {
 	 */
 
 	public void setURL() { URL = ""; markDirty(); }
-	public void setError() { LAST_ERROR = ""; markDirty(); }
-	public void setHigh() { HIGH = false; markDirty(); updateBlockState(); }
+	public void setError() { LAST_ERROR = ""; }
+	public void setHigh() { HIGH = false; markDirty(); notifyRedstoneUpdate(); }
 	public void setDisabled() { DISABLED = false; markDirty(); }
+	public void updateRun() { LAST_RUN = Instant.now().getEpochSecond(); }
 	public void setTicks() { UPDATE_TICKS = 0; markDirty(); }
-	public void setSides() { SIDES = 0; markDirty(); updateBlockState(); }
+	public void setSides() { SIDES = 1 << 2; markDirty(); updateBlockState(); }
 	
 }