diff --git a/pom.xml b/pom.xml
index 385ba752742415ecea427506a66e56edc838ca2b..73bd47763444bfc1afaf7d4897ba980fbeab1baf 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,7 +18,12 @@
         <dependency>
             <groupId>com.fossgalaxy.games</groupId>
             <artifactId>fireworks</artifactId>
-            <version>0.1</version>
+            <version>0.2-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.reflections</groupId>
+            <artifactId>reflections</artifactId>
+            <version>0.9.11</version>
         </dependency>
     </dependencies>
 
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/Envelope.java b/src/main/java/com/fossgalaxy/games/fireworks/Envelope.java
new file mode 100644
index 0000000000000000000000000000000000000000..6eed3aa668859b8f2e4732a1fad4f56fc06ffe1d
--- /dev/null
+++ b/src/main/java/com/fossgalaxy/games/fireworks/Envelope.java
@@ -0,0 +1,22 @@
+package com.fossgalaxy.games.fireworks;
+
+import com.fossgalaxy.games.fireworks.state.actions.Action;
+import com.fossgalaxy.games.fireworks.state.events.GameEvent;
+
+import java.io.Serializable;
+
+/**
+ * Created by webpigeon on 20/04/17.
+ */
+public class Envelope implements Serializable {
+    EnvoType type;
+    String gameID;
+    int playerID;
+    int nPlayers;
+    GameEvent event;
+
+    public Envelope(EnvoType reqAction) {
+        this.type = reqAction;
+
+    }
+}
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/EnvoType.java b/src/main/java/com/fossgalaxy/games/fireworks/EnvoType.java
new file mode 100644
index 0000000000000000000000000000000000000000..6978f86fb9fa4b3ce4502802cf067706a9bf84dc
--- /dev/null
+++ b/src/main/java/com/fossgalaxy/games/fireworks/EnvoType.java
@@ -0,0 +1,8 @@
+package com.fossgalaxy.games.fireworks;
+
+/**
+ * Created by webpigeon on 20/04/17.
+ */
+public enum EnvoType {
+    RECV_PLAYER_ID, RECV_GAMEEVENT, REQ_ACTION
+}
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/NetClient.java b/src/main/java/com/fossgalaxy/games/fireworks/NetClient.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7c5cc0c5ca3bf7d93b0fe365e35c30a146f4892
--- /dev/null
+++ b/src/main/java/com/fossgalaxy/games/fireworks/NetClient.java
@@ -0,0 +1,64 @@
+package com.fossgalaxy.games.fireworks;
+
+import com.fossgalaxy.games.fireworks.human.ui.UIPlayer;
+import com.fossgalaxy.games.fireworks.human.ui.pretty.HumanUIAgent;
+import com.fossgalaxy.games.fireworks.state.actions.Action;
+import com.fossgalaxy.games.fireworks.utils.AgentUtils;
+
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ * Created by webpigeon on 20/04/17.
+ */
+public class NetClient {
+
+    public static void main(String[] args) {
+
+        try (
+        Socket socket = new Socket("localhost", NetServer.FIREWORKS_SERVER_PORT);
+        ) {
+
+            UIPlayer player = new UIPlayer("iggi", new HumanUIAgent(), true);
+
+            //important, this MUST be the other way round to the server or they deadlock.
+            ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
+            ObjectInputStream is = new ObjectInputStream(socket.getInputStream());
+
+            boolean running = true;
+            while (running) {
+                try {
+                    Envelope envolope = (Envelope) is.readObject();
+                    switch (envolope.type) {
+                        case RECV_PLAYER_ID:
+                            player.setID(envolope.playerID, envolope.nPlayers);
+                            break;
+                        case RECV_GAMEEVENT:
+                            player.sendMessage(envolope.event);
+                            break;
+                        case REQ_ACTION:
+                            Action action = player.getAction();
+                            out.writeObject(action);
+                            out.flush();
+                    }
+
+                } catch (ClassNotFoundException e) {
+                    e.printStackTrace();
+                } catch (IOException ex) {
+                    System.out.println("Error communicating with server");
+                    player.onGameOver();
+                    running = false;
+                }
+            }
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+}
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/NetServer.java b/src/main/java/com/fossgalaxy/games/fireworks/NetServer.java
new file mode 100644
index 0000000000000000000000000000000000000000..84415c4b4f05370bbb5d6d11328d28fad90d7790
--- /dev/null
+++ b/src/main/java/com/fossgalaxy/games/fireworks/NetServer.java
@@ -0,0 +1,89 @@
+package com.fossgalaxy.games.fireworks;
+
+import com.fossgalaxy.games.fireworks.cluster.PredictorRunnerSingle;
+import com.fossgalaxy.games.fireworks.players.Player;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.Random;
+
+/**
+ * Created by webpigeon on 20/04/17.
+ */
+public class NetServer {
+    public static final int FIREWORKS_SERVER_PORT = 6491;
+    private GameRegistry registry = new GameRegistry();
+
+    public static void main(String[] args) throws FileNotFoundException {
+        boolean running = true;
+
+        Random r = new Random();
+        try (
+            PrintStream statOut = new PrintStream(new File(String.format("results-%d.txt", System.currentTimeMillis())));
+        ) {
+            try (ServerSocket serverSocket = new ServerSocket(FIREWORKS_SERVER_PORT)) {
+                System.out.println("Now accepting players");
+
+                while (running) {
+
+                    System.out.println("Waiting for players");
+
+                    String[] agentNames = new String[4];
+                    ServerNetworkPlayer[] networkPlayers = new ServerNetworkPlayer[4];
+
+
+                    for (int playerID = 0; playerID < agentNames.length; playerID++) {
+                        try {
+                            Socket socket = serverSocket.accept();
+
+                            ServerNetworkPlayer netPlayer = new ServerNetworkPlayer(socket);
+                            networkPlayers[playerID] = netPlayer;
+
+                            System.out.println("Player "+playerID+" has joined teh game");
+                        } catch (IOException ex) {
+                            //if this guy doesn't connect properly, we don't count them.
+                            ex.printStackTrace();
+                            System.out.println("Player "+playerID+" left the game :(");
+                            playerID--;
+                        }
+                    }
+
+                    System.out.println("The game is ready to start");
+
+                    playGame(agentNames, networkPlayers, r.nextLong(), statOut);
+
+                    System.out.println("The game has ended, play again?");
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        } catch (FileNotFoundException ex) {
+            System.out.println("so, here's what's happened. You've somehow got a timestamp with a forward slash in it.");
+            System.out.println("please don't do that... it's kinda silly.");
+            ex.printStackTrace();
+        }
+
+    }
+
+    public static void playGame(String[] agentNames, ServerNetworkPlayer[] players, long seed, PrintStream out) {
+        String gameID = "net-"+System.currentTimeMillis();
+
+        GameRunner runner = new GameRunner(gameID, players.length);
+        for (int i=0; i<players.length; i++) {
+            runner.addPlayer(players[i]);
+        }
+        GameStats result = runner.playGame(seed);
+        out.println( PredictorRunnerSingle.makeCSVLine(gameID, "network", "", "normal", agentNames, seed, result, "none") );
+        out.flush();
+
+        for (Player player : players) {
+            player.onGameOver();
+        }
+
+    }
+
+}
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/NetworkPlayer.java b/src/main/java/com/fossgalaxy/games/fireworks/NetworkPlayer.java
deleted file mode 100644
index e8b4eb6a8db6c957c1d89800cf04576d85832480..0000000000000000000000000000000000000000
--- a/src/main/java/com/fossgalaxy/games/fireworks/NetworkPlayer.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.fossgalaxy.games.fireworks;
-
-import com.fossgalaxy.games.fireworks.players.Player;
-import com.fossgalaxy.games.fireworks.state.actions.Action;
-import com.fossgalaxy.games.fireworks.state.events.GameEvent;
-
-/**
- * Created by webpigeon on 10/04/17.
- */
-public class NetworkPlayer implements Player {
-
-    @Override
-    public Action getAction() {
-        return null;
-    }
-
-    @Override
-    public void sendMessage(GameEvent msg) {
-
-    }
-
-    @Override
-    public void setID(int id, int nPlayers) {
-
-    }
-
-    @Override
-    public String getName() {
-        return null;
-    }
-}
diff --git a/src/main/java/com/fossgalaxy/games/fireworks/ServerNetworkPlayer.java b/src/main/java/com/fossgalaxy/games/fireworks/ServerNetworkPlayer.java
new file mode 100644
index 0000000000000000000000000000000000000000..f19937275b274c277cfb6e11cad5e6dc097121e9
--- /dev/null
+++ b/src/main/java/com/fossgalaxy/games/fireworks/ServerNetworkPlayer.java
@@ -0,0 +1,100 @@
+package com.fossgalaxy.games.fireworks;
+
+import com.fossgalaxy.games.fireworks.players.Player;
+import com.fossgalaxy.games.fireworks.state.actions.Action;
+import com.fossgalaxy.games.fireworks.state.events.GameEvent;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.Socket;
+
+/**
+ * Created by webpigeon on 10/04/17.
+ */
+public class ServerNetworkPlayer implements Player {
+    private Socket socket;
+    private ObjectInputStream scanner;
+    private ObjectOutputStream printStream;
+
+    private static final Envelope REQUEST_ACTION = new Envelope(EnvoType.REQ_ACTION);
+
+    public ServerNetworkPlayer(Socket socket) {
+        try {
+            this.socket = socket;
+
+            this.scanner = new ObjectInputStream(socket.getInputStream());
+            this.printStream = new ObjectOutputStream(socket.getOutputStream());
+
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Override
+    public Action getAction() {
+        try {
+            printStream.writeObject(REQUEST_ACTION);
+            printStream.flush();
+            return (Action)scanner.readObject();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public void sendMessage(GameEvent msg) {
+        try {
+            Envelope envelope = new Envelope(EnvoType.RECV_GAMEEVENT);
+            envelope.event = msg;
+            printStream.writeObject(envelope);
+            printStream.flush();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Override
+    public void setID(int id, int nPlayers) {
+        Envelope envelope = new Envelope(EnvoType.RECV_PLAYER_ID);
+        envelope.playerID = id;
+        envelope.nPlayers = nPlayers;
+
+        try {
+            printStream.writeObject(envelope);
+            printStream.flush();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    @Override
+    public String getName() {
+        return "player-"+socket.getInetAddress();
+    }
+
+    @Override
+    public void onGameOver() {
+        try {
+            scanner.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            printStream.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+
+        try {
+            socket.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+}