diff --git a/src/main/java/com/comandante/GameAuthenticator.java b/src/main/java/com/comandante/GameAuthenticator.java
deleted file mode 100644
index e55ea1689df4e68e82905027f0ec49c473a057d5..0000000000000000000000000000000000000000
--- a/src/main/java/com/comandante/GameAuthenticator.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.comandante;
-
-import org.jboss.netty.channel.Channel;
-
-public interface GameAuthenticator {
-
-    public boolean authenticatePlayer(String userName, String passWord, Channel channel);
-
-}
diff --git a/src/main/java/com/comandante/GameManager.java b/src/main/java/com/comandante/GameManager.java
deleted file mode 100644
index e7437740643fddecd77b3e0c69f80a6dfb3aa52f..0000000000000000000000000000000000000000
--- a/src/main/java/com/comandante/GameManager.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.comandante;
-
-import com.google.common.base.Optional;
-import com.google.common.collect.Interners;
-import org.fusesource.jansi.Ansi;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
-public class GameManager {
-
-    private ConcurrentHashMap<Integer, Room> rooms = new ConcurrentHashMap<Integer, Room>();
-    private ConcurrentHashMap<String, Player> players = new ConcurrentHashMap<String, Player>();
-
-    public void addRoom(Room room) {
-        rooms.put(room.roomId, room);
-    }
-
-    public Player addPlayer(Player player) {
-        return players.putIfAbsent(player.getPlayerId(), player);
-    }
-
-    public void removePlayer(Player player) {
-        if (getPlayer(player).getChannel() != null) {
-            getPlayer(player).getChannel().disconnect();
-        }
-        players.remove(player);
-        Iterator<Integer> iterator = rooms.keySet().iterator();
-        while (iterator.hasNext()) {
-            Integer next = iterator.next();
-            rooms.get(next).removePresentPlayer(player);
-        }
-    }
-
-    public boolean doesPlayerExist(Player player) {
-        for (Map.Entry<String, Player> stringPlayerEntry : players.entrySet()) {
-            Map.Entry pairs = (Map.Entry) stringPlayerEntry;
-            Player playerRetrieved = (Player) pairs.getValue();
-            if (playerRetrieved.getPlayerId().equals(player.getPlayerId())) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    public void gossip(Player sourcePlayer, String message) {
-        for (Map.Entry<String, Player> next : players.entrySet()) {
-            StringBuilder stringBuilder = new StringBuilder();
-            Player player = next.getValue();
-            if (player.getPlayerId().equals(sourcePlayer.getPlayerId())) {
-                stringBuilder.append(new Ansi().fg(Ansi.Color.WHITE).toString());
-            } else {
-                stringBuilder.append(new Ansi().fg(Ansi.Color.MAGENTA).toString());
-            }
-            stringBuilder.append("[").append(sourcePlayer.getPlayerName()).append("] ").append(message).append("\r\n");
-            stringBuilder.append(new Ansi().reset().toString());
-            player.getChannel().write(stringBuilder.toString());
-        }
-    }
-
-    public void say(Player sourcePlayer, String message) {
-        Optional<Room> playerCurrentRoom = getPlayerCurrentRoom(sourcePlayer);
-        Iterator<Player> iterator = playerCurrentRoom.get().getPresentPlayers().iterator();
-        while (iterator.hasNext()) {
-            StringBuilder stringBuilder = new StringBuilder();
-            Player player = iterator.next();
-            if (player.getPlayerId().equals(sourcePlayer.getPlayerId())) {
-                stringBuilder.append(new Ansi().fg(Ansi.Color.WHITE).toString());
-            } else {
-                stringBuilder.append(new Ansi().fg(Ansi.Color.RED).toString());
-            }
-            stringBuilder.append("<").append(sourcePlayer.getPlayerName()).append("> ").append(message).append("\r\n");
-            stringBuilder.append(new Ansi().reset().toString());
-            player.getChannel().write(stringBuilder.toString());
-        }
-    }
-
-    public void movePlayer(Movement movement) {
-        synchronized (Interners.newStrongInterner()) {
-            Room sourceRoom = rooms.get(movement.getSourceRoomId());
-            sourceRoom.removePresentPlayer(movement.getPlayer());
-            Iterator<Player> iterator = sourceRoom.getPresentPlayers().iterator();
-            while (iterator.hasNext()) {
-                Player next = iterator.next();
-                next.getChannel().write(movement.getPlayer().getPlayerName() + " used exit: " + movement.getOriginalMovementCommand() + ".\r\n");
-            }
-            Room destinationRoom = rooms.get(movement.getDestinationRoomId());
-            Iterator<Player> iterator1 = destinationRoom.getPresentPlayers().iterator();
-            while (iterator1.hasNext()) {
-                Player next = iterator1.next();
-                next.getChannel().write(movement.getPlayer().getPlayerName() + " arrived.\r\n");
-            }
-            destinationRoom.addPresentPlayer(movement.getPlayer());
-        }
-    }
-
-    public void addPlayerToLobby(Player player) {
-        rooms.get(1).addPresentPlayer(player);
-    }
-
-    public Player getPlayer(Player player) {
-        return players.get(player.getPlayerId());
-    }
-
-    public Optional<Room> getPlayerCurrentRoom(Player player) {
-        Iterator<Map.Entry<Integer, Room>> iterator = rooms.entrySet().iterator();
-        while (iterator.hasNext()) {
-            Map.Entry<Integer, Room> next = iterator.next();
-            Set<Player> presentPlayers = next.getValue().getPresentPlayers();
-            Iterator<Player> iterator1 = presentPlayers.iterator();
-            while (iterator1.hasNext()) {
-                Player next1 = iterator1.next();
-                if (next1.getPlayerId().equals(player.getPlayerId())) {
-                    return Optional.of(next.getValue());
-                }
-            }
-        }
-        return Optional.absent();
-    }
-
-}
diff --git a/src/main/java/com/comandante/Main.java b/src/main/java/com/comandante/Main.java
index 1beee2805aa65dbc12483916d7aa5f1ffda0e7b2..0df024d1f28cdcc47a395102ec8554053667732d 100644
--- a/src/main/java/com/comandante/Main.java
+++ b/src/main/java/com/comandante/Main.java
@@ -1,8 +1,11 @@
 package com.comandante;
 
-import com.comandante.telnetserver.TelnetServer;
+import com.comandante.managers.GameManager;
+import com.comandante.managers.PlayerManager;
+import com.comandante.managers.RoomManager;
+import com.comandante.model.Room;
+import com.comandante.server.CreeperServer;
 import com.google.common.base.Optional;
-import org.fusesource.jansi.Ansi;
 
 public class Main {
 
@@ -16,19 +19,17 @@ public class Main {
         Room janitorialCloset = new Room(6, Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(3), Optional.<Integer>absent(),
                 "You find yourself in the janitorial closet.  It smells like bleach.");
 
-        GameManager gameManager = new GameManager();
-        gameManager.addRoom(lobby);
-        gameManager.addRoom(hallway);
-        gameManager.addRoom(intake);
-        gameManager.addRoom(janitorialCloset);
+        RoomManager roomManager = new RoomManager();
+        roomManager.addRoom(lobby);
+        roomManager.addRoom(hallway);
+        roomManager.addRoom(intake);
+        roomManager.addRoom(janitorialCloset);
+        PlayerManager playerManager = new PlayerManager();
+        GameManager gameManager = new GameManager(roomManager, playerManager);
 
-        Ansi ansi = new Ansi();
-        ansi.fg(Ansi.Color.RED);
-        String hello = ansi.render("hello").toString();
-        System.out.println(hello);
+        CreeperServer creeperServer = new CreeperServer(8080);
+        creeperServer.run(gameManager);
 
-
-        TelnetServer telnetServer = new TelnetServer(8080);
-        telnetServer.run(gameManager);
+        System.out.println("Creeper started.");
     }
 }
diff --git a/src/main/java/com/comandante/command/CommandType.java b/src/main/java/com/comandante/command/CommandType.java
new file mode 100644
index 0000000000000000000000000000000000000000..27c5bf5d3b4691c4f927661d2c086551cb704446
--- /dev/null
+++ b/src/main/java/com/comandante/command/CommandType.java
@@ -0,0 +1,12 @@
+package com.comandante.command;
+
+import java.util.Set;
+
+public interface CommandType {
+    String getDescription();
+
+    Set<String> getValidCommandTriggers();
+
+    boolean isCaseSensitive();
+
+}
diff --git a/src/main/java/com/comandante/command/CommandTypeHelper.java b/src/main/java/com/comandante/command/CommandTypeHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..01f356323e8c0d492817f9c98e9e0c323734868f
--- /dev/null
+++ b/src/main/java/com/comandante/command/CommandTypeHelper.java
@@ -0,0 +1,37 @@
+package com.comandante.command;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Iterators;
+
+import java.util.Iterator;
+
+public class CommandTypeHelper {
+    public static CommandType getCommandType(CommandType[] commandTypes, String message) {
+        final String rootCommand = message.split(" ")[0];
+        for (CommandType commandType : commandTypes) {
+            Iterator<String> iterator = commandType.getValidCommandTriggers().iterator();
+            String searchString = null;
+            if (!commandType.isCaseSensitive()) {
+                iterator = Iterators.transform(iterator, new UpperCaseFunction<String, String>());
+                searchString = rootCommand.toUpperCase();
+            } else {
+                searchString = rootCommand;
+            }
+            while (iterator.hasNext()) {
+                String next = iterator.next();
+                if (next.equals(searchString)) {
+                    return commandType;
+                }
+            }
+        }
+        return DefaultCommandType.UNKNOWN;
+    }
+
+    static class UpperCaseFunction<F, T> implements Function<F, T> {
+        @Override
+        public Object apply(Object f) {
+            return f.toString().toUpperCase();
+        }
+    }
+
+}
diff --git a/src/main/java/com/comandante/command/DefaultCommandHandler.java b/src/main/java/com/comandante/command/DefaultCommandHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..b2d64ebf04706586710f3046bd5f50966ce079ca
--- /dev/null
+++ b/src/main/java/com/comandante/command/DefaultCommandHandler.java
@@ -0,0 +1,93 @@
+package com.comandante.command;
+
+
+import com.comandante.model.Movement;
+import com.comandante.managers.GameManager;
+import com.comandante.model.Player;
+import com.comandante.model.Room;
+import com.comandante.server.CreeperSessionState;
+import com.google.common.base.Optional;
+import org.jboss.netty.channel.MessageEvent;
+
+public class DefaultCommandHandler {
+
+    GameManager gameManager;
+    CreeperSessionState creeperSessionState;
+    MessageEvent event;
+
+    public DefaultCommandHandler(GameManager gameManager, CreeperSessionState creeperSessionState, MessageEvent event) {
+        this.gameManager = gameManager;
+        this.creeperSessionState = creeperSessionState;
+        this.event = event;
+    }
+
+    public void handle(DefaultCommandType cmdType) {
+        final String originalMessage = cmdType.getOriginalMessage();
+        final Player player = _player();
+        Optional<Movement> movementOptional = Optional.absent();
+        Room currentRoom = null;
+
+        switch(cmdType) {
+            case MOVE_NORTH:
+                currentRoom = _currentRoom();
+                if (!currentRoom.getNorthId().isPresent()) {
+                    event.getChannel().write("There's no northern exit.\r\n");
+                    break;
+                }
+                movementOptional = Optional.of(
+                        new Movement(player, currentRoom.getRoomId(), currentRoom.getNorthId().get(), cmdType));
+                break;
+            case MOVE_SOUTH:
+                currentRoom = _currentRoom();
+                if (!currentRoom.getSouthId().isPresent()) {
+                    event.getChannel().write("There's no southern exit.\r\n");
+                    break;
+                }
+                movementOptional = Optional.of(
+                        new Movement(player, currentRoom.getRoomId(), currentRoom.getSouthId().get(), cmdType));
+                break;
+            case MOVE_EAST:
+                currentRoom = _currentRoom();
+                if (!currentRoom.getEastId().isPresent()) {
+                    event.getChannel().write("There's no eastern exit.\r\n");
+                    break;
+                }
+                movementOptional = Optional.of(
+                        new Movement(player, currentRoom.getRoomId(), currentRoom.getEastId().get(), cmdType));
+                break;
+            case MOVE_WEST:
+                currentRoom = _currentRoom();
+                if (!currentRoom.getWestId().isPresent()) {
+                    event.getChannel().write("There's no western exit.\r\n");
+                    break;
+                }
+                movementOptional = Optional.of(
+                        new Movement(player, currentRoom.getRoomId(), currentRoom.getWestId().get(), cmdType));
+                break;
+            case SAY:
+                gameManager.say(player, originalMessage.replaceFirst("^say ", ""));
+                break;
+            case GOSSIP:
+                String s = originalMessage.replaceFirst("^gossip ", "");
+                gameManager.gossip(player, s);
+                break;
+            case UNKNOWN:
+                gameManager.currentRoomLogic(creeperSessionState, event);
+                break;
+        }
+
+        if (movementOptional.isPresent()) {
+            gameManager.movePlayer(movementOptional.get());
+            gameManager.currentRoomLogic(creeperSessionState, event);
+        }
+    }
+
+    private Player _player() {
+        return gameManager.getPlayerManager().getPlayer(creeperSessionState.getUsername().get());
+    }
+
+    private Room _currentRoom() {
+        return gameManager.getPlayerCurrentRoom(_player()).get();
+    }
+
+}
diff --git a/src/main/java/com/comandante/command/DefaultCommandType.java b/src/main/java/com/comandante/command/DefaultCommandType.java
new file mode 100644
index 0000000000000000000000000000000000000000..343d69ea2abef6eb84c6f77945c10d9c8e4282ce
--- /dev/null
+++ b/src/main/java/com/comandante/command/DefaultCommandType.java
@@ -0,0 +1,56 @@
+package com.comandante.command;
+
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public enum DefaultCommandType implements CommandType {
+    MOVE_NORTH(new HashSet<String>(Arrays.asList("n", "North")), false, "Move north."),
+    MOVE_SOUTH(new HashSet<String>(Arrays.asList("s", "South")), false, "Move south."),
+    MOVE_EAST(new HashSet<String>(Arrays.asList("e", "East")), false, "Move east."),
+    MOVE_WEST(new HashSet<String>(Arrays.asList("w", "West")), false, "Move west."),
+    SAY(new HashSet<String>(Arrays.asList("say")), true, "Say something to the current room."),
+    GOSSIP(new HashSet<String>(Arrays.asList("gossip")), true, "Gossip to the entire server."),
+    UNKNOWN(new HashSet<String>(Arrays.asList("gossip")), true, "Gossip to the entire server.");
+
+    private Set<String> validCommandTriggers;
+    private boolean caseSensitive;
+    private String description;
+    private String originalMessage;
+
+    DefaultCommandType(Set<String> triggers, boolean caseSensitive, String description) {
+        this.validCommandTriggers = triggers;
+        this.caseSensitive = caseSensitive;
+        this.description = description;
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public Set<String> getValidCommandTriggers() {
+        return validCommandTriggers;
+    }
+
+    public String getOriginalMessage() {
+        return originalMessage;
+    }
+
+    @Override
+    public boolean isCaseSensitive() {
+        return caseSensitive;
+    }
+
+    public void setOriginalMessage(String originalMessage) {
+        this.originalMessage = originalMessage;
+    }
+
+    public static CommandType getCommandTypeFromMessage(String message) {
+        DefaultCommandType commandType = (DefaultCommandType) CommandTypeHelper.getCommandType(DefaultCommandType.values(), message);
+        commandType.setOriginalMessage(message);
+        return commandType;
+    }
+}
diff --git a/src/main/java/com/comandante/managers/GameManager.java b/src/main/java/com/comandante/managers/GameManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..b79f2f4f203b6a76524a3cf084968121339ccf22
--- /dev/null
+++ b/src/main/java/com/comandante/managers/GameManager.java
@@ -0,0 +1,139 @@
+package com.comandante.managers;
+
+
+import com.comandante.model.Movement;
+import com.comandante.model.Player;
+import com.comandante.model.Room;
+import com.comandante.server.CreeperSessionState;
+import com.google.common.base.Optional;
+import com.google.common.collect.Interners;
+import org.fusesource.jansi.Ansi;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.MessageEvent;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+public class GameManager {
+
+    private final RoomManager roomManager;
+    private final PlayerManager playerManager;
+
+    public GameManager(RoomManager roomManager, PlayerManager playerManager) {
+        this.roomManager = roomManager;
+        this.playerManager = playerManager;
+    }
+
+    public RoomManager getRoomManager() {
+        return roomManager;
+    }
+
+    public PlayerManager getPlayerManager() {
+        return playerManager;
+    }
+
+    private static final Integer LOBBY_ID = 1;
+
+    public Optional<Room> getPlayerCurrentRoom(Player player) {
+        Iterator<Map.Entry<Integer, Room>> rooms = roomManager.getRooms();
+        while (rooms.hasNext()) {
+            Map.Entry<Integer, Room> next = rooms.next();
+            Room room = next.getValue();
+            for (Player searchPlayer : room.getPresentPlayers()) {
+                if (searchPlayer.getPlayerId().equals(player.getPlayerId())) {
+                    return Optional.of(room);
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    public void movePlayer(Movement movement) {
+        synchronized (Interners.newStrongInterner()) {
+            Room sourceRoom = roomManager.getRoom(movement.getSourceRoomId());
+            Room destinationRoom = roomManager.getRoom(movement.getDestinationRoomId());
+            sourceRoom.removePresentPlayer(movement.getPlayer());
+            for (Player next : sourceRoom.getPresentPlayers()) {
+                next.getChannel().write(movement.getPlayer().getPlayerName() + " used exit: " + movement.getOriginalMovementCommand() + ".\r\n");
+            }
+            for (Player next : destinationRoom.getPresentPlayers()) {
+                next.getChannel().write(movement.getPlayer().getPlayerName() + " arrived.\r\n");
+            }
+            destinationRoom.addPresentPlayer(movement.getPlayer());
+        }
+    }
+
+    public void placePlayerInLobby(Player player) {
+        roomManager.getRoom(LOBBY_ID).addPresentPlayer(player);
+    }
+
+    public void say(Player sourcePlayer, String message) {
+        Optional<Room> playerCurrentRoomOpt = getPlayerCurrentRoom(sourcePlayer);
+        if (!playerCurrentRoomOpt.isPresent()) {
+            throw new RuntimeException("playerCurrentRoom is missing!");
+        }
+
+        Room playerCurrentRoom = playerCurrentRoomOpt.get();
+        Set<Player> presentPlayers = playerCurrentRoom.getPresentPlayers();
+
+        for (Player presentPlayer : presentPlayers) {
+            StringBuilder stringBuilder = new StringBuilder();
+            if (presentPlayer.getPlayerId().equals(sourcePlayer.getPlayerId())) {
+                stringBuilder.append(new Ansi().fg(Ansi.Color.WHITE).toString());
+            } else {
+                stringBuilder.append(new Ansi().fg(Ansi.Color.RED).toString());
+            }
+            stringBuilder.append("<").append(sourcePlayer.getPlayerName()).append("> ").append(message).append("\r\n");
+            stringBuilder.append(new Ansi().reset().toString());
+            presentPlayer.getChannel().write(stringBuilder.toString());
+        }
+    }
+
+    public void gossip(Player sourcePlayer, String message) {
+        Iterator<Map.Entry<String, Player>> players = playerManager.getPlayers();
+        while (players.hasNext()) {
+            StringBuilder stringBuilder = new StringBuilder();
+            Player player = players.next().getValue();
+            if (player.getPlayerId().equals(sourcePlayer.getPlayerId())) {
+                stringBuilder.append(new Ansi().fg(Ansi.Color.WHITE).toString());
+            } else {
+                stringBuilder.append(new Ansi().fg(Ansi.Color.MAGENTA).toString());
+            }
+            stringBuilder.append("[").append(sourcePlayer.getPlayerName()).append("] ").append(message).append("\r\n");
+            stringBuilder.append(new Ansi().reset().toString());
+            player.getChannel().write(stringBuilder.toString());
+        }
+    }
+
+    private void printExits(Room room, Channel channel) {
+        channel.write("-exits: ");
+        if (room.getEastId().isPresent()) {
+            channel.write("e(ast) ");
+        }
+        if (room.getNorthId().isPresent()) {
+            channel.write("n(orth) ");
+        }
+        if (room.getSouthId().isPresent()) {
+            channel.write("s(outh). ");
+        }
+        if (room.getWestId().isPresent()) {
+            channel.write("w(est). ");
+        }
+        channel.write("\r\n");
+    }
+
+    public void currentRoomLogic(CreeperSessionState creeperSessionState, MessageEvent e) {
+        final Player player = playerManager.getPlayer(creeperSessionState.getUsername().get());
+        final Room playerCurrentRoom = getPlayerCurrentRoom(player).get();
+        e.getChannel().write(playerCurrentRoom.getRoomDescription() + "\r\n");
+        for (Player next : playerCurrentRoom.getPresentPlayers()) {
+            if (next.getPlayerId().equals(new Player(creeperSessionState.getUsername().get()).getPlayerId())) {
+                continue;
+            }
+            e.getChannel().write(next.getPlayerName() + " is here.\r\n");
+        }
+        printExits(playerCurrentRoom, e.getChannel());
+    }
+
+}
diff --git a/src/main/java/com/comandante/managers/PlayerManager.java b/src/main/java/com/comandante/managers/PlayerManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..56c8b3f2190dc59191d54e8b1eb8063c907ab838
--- /dev/null
+++ b/src/main/java/com/comandante/managers/PlayerManager.java
@@ -0,0 +1,41 @@
+package com.comandante.managers;
+
+
+import com.comandante.model.Player;
+import org.apache.commons.codec.binary.Base64;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class PlayerManager {
+
+    private ConcurrentHashMap<String, Player> players = new ConcurrentHashMap<String, Player>();
+
+    public Player addPlayer(Player player) {
+        return players.putIfAbsent(player.getPlayerId(), player);
+    }
+
+    public Player getPlayer(Player player) {
+        return players.get(player.getPlayerId());
+    }
+
+    public Player getPlayer(String username) {
+        return players.get(new String(Base64.encodeBase64(username.getBytes())));
+    }
+
+    public Iterator<java.util.Map.Entry<String, Player>> getPlayers() {
+        return players.entrySet().iterator();
+    }
+
+    public void removePlayer(String username) {
+        Player player = getPlayer(username);
+        if (player.getChannel() != null) {
+            player.getChannel().disconnect();
+        }
+        players.remove(player);
+    }
+
+    public boolean doesPlayerExist(String username) {
+       return players.containsKey(Base64.encodeBase64(username.getBytes()));
+    }
+}
diff --git a/src/main/java/com/comandante/managers/RoomManager.java b/src/main/java/com/comandante/managers/RoomManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..95bd1345d16e6474d4dac7cda167e1f2b4c3c5a4
--- /dev/null
+++ b/src/main/java/com/comandante/managers/RoomManager.java
@@ -0,0 +1,24 @@
+package com.comandante.managers;
+
+import com.comandante.model.Room;
+
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class RoomManager {
+
+    private ConcurrentHashMap<Integer, Room> rooms = new ConcurrentHashMap<Integer, Room>();
+
+    public void addRoom(Room room) {
+        rooms.put(room.roomId, room);
+    }
+
+    public Room getRoom(Integer roomId) {
+        return rooms.get(roomId);
+    }
+
+    public Iterator<java.util.Map.Entry<Integer, Room>> getRooms() {
+        return rooms.entrySet().iterator();
+    }
+
+}
diff --git a/src/main/java/com/comandante/Movement.java b/src/main/java/com/comandante/model/Movement.java
similarity index 73%
rename from src/main/java/com/comandante/Movement.java
rename to src/main/java/com/comandante/model/Movement.java
index af83567937c39073208c2792c11d25c3c0c379b2..3626548531e39e6c80f2a4454f0fc83fe1eaac5d 100644
--- a/src/main/java/com/comandante/Movement.java
+++ b/src/main/java/com/comandante/model/Movement.java
@@ -1,13 +1,15 @@
-package com.comandante;
+package com.comandante.model;
+
+import com.comandante.command.CommandType;
 
 public class Movement {
 
     private final Player player;
     private final Integer sourceRoomId;
     private final Integer destinationRoomId;
-    private final String originalMovementCommand;
+    private final CommandType originalMovementCommand;
 
-    public Movement(Player player, Integer sourceRoomId, Integer destinationRoomId, String originalMovementCommand) {
+    public Movement(Player player, Integer sourceRoomId, Integer destinationRoomId, CommandType originalMovementCommand) {
         this.player = player;
         this.sourceRoomId = sourceRoomId;
         this.destinationRoomId = destinationRoomId;
@@ -26,7 +28,7 @@ public class Movement {
         return player;
     }
 
-    public String getOriginalMovementCommand() {
+    public CommandType getOriginalMovementCommand() {
         return originalMovementCommand;
     }
 }
diff --git a/src/main/java/com/comandante/Player.java b/src/main/java/com/comandante/model/Player.java
similarity index 95%
rename from src/main/java/com/comandante/Player.java
rename to src/main/java/com/comandante/model/Player.java
index ae9b91646f6c598a483331bf4474425107fe5d7a..eef7d3584294e05a4f6ad2a7ab7c25545db230cf 100644
--- a/src/main/java/com/comandante/Player.java
+++ b/src/main/java/com/comandante/model/Player.java
@@ -1,4 +1,4 @@
-package com.comandante;
+package com.comandante.model;
 
 
 import org.apache.commons.codec.binary.Base64;
diff --git a/src/main/java/com/comandante/Room.java b/src/main/java/com/comandante/model/Room.java
similarity index 98%
rename from src/main/java/com/comandante/Room.java
rename to src/main/java/com/comandante/model/Room.java
index cb6795882e6b5cd68a3f6bddaf8b7361436bc439..5ece1a76115b30cda3fd63845df2a6301c3f0162 100644
--- a/src/main/java/com/comandante/Room.java
+++ b/src/main/java/com/comandante/model/Room.java
@@ -1,4 +1,4 @@
-package com.comandante;
+package com.comandante.model;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
diff --git a/src/main/java/com/comandante/server/CreeperAuthenticator.java b/src/main/java/com/comandante/server/CreeperAuthenticator.java
new file mode 100644
index 0000000000000000000000000000000000000000..7749325f9679a2a2fc4cb1ded0ade6b9dce4e9ab
--- /dev/null
+++ b/src/main/java/com/comandante/server/CreeperAuthenticator.java
@@ -0,0 +1,9 @@
+package com.comandante.server;
+
+import org.jboss.netty.channel.Channel;
+
+public interface CreeperAuthenticator {
+
+    public boolean authenticateAndRegisterPlayer(String userName, String passWord, Channel channel);
+
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServer.java b/src/main/java/com/comandante/server/CreeperServer.java
similarity index 58%
rename from src/main/java/com/comandante/telnetserver/TelnetServer.java
rename to src/main/java/com/comandante/server/CreeperServer.java
index 5a86cd768a0c87f78b944d76e5c3d06cdc28552f..81bfa1539f3a0157a15bd3c40de04022475a67ac 100644
--- a/src/main/java/com/comandante/telnetserver/TelnetServer.java
+++ b/src/main/java/com/comandante/server/CreeperServer.java
@@ -1,28 +1,25 @@
-package com.comandante.telnetserver;
+package com.comandante.server;
 
 
-import com.comandante.GameManager;
-import com.comandante.SimpleGameAuthenticator;
+import com.comandante.managers.GameManager;
 import org.jboss.netty.bootstrap.ServerBootstrap;
 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
 
 import java.net.InetSocketAddress;
 import java.util.concurrent.Executors;
 
-public class TelnetServer {
+public class CreeperServer {
 
     private final int port;
 
-    public TelnetServer(int port) {
+    public CreeperServer(int port) {
         this.port = port;
     }
 
     public void run(GameManager gameManager) throws Exception {
         ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
-
-        TelnetServerHandler handler = new TelnetServerHandler(new SimpleGameAuthenticator(gameManager), gameManager);
-        bootstrap.setPipelineFactory(new TelnetServerPipelineFactory(handler));
+        CreeperServerHandler handler = new CreeperServerHandler(new CreeperSimpleAuthenticator(gameManager), gameManager);
+        bootstrap.setPipelineFactory(new CreeperServerPipelineFactory(handler));
         bootstrap.bind(new InetSocketAddress(8080));
-
     }
 }
diff --git a/src/main/java/com/comandante/server/CreeperServerHandler.java b/src/main/java/com/comandante/server/CreeperServerHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..793bd53908934bd2007386a92f4c65ecb80660f0
--- /dev/null
+++ b/src/main/java/com/comandante/server/CreeperServerHandler.java
@@ -0,0 +1,87 @@
+package com.comandante.server;
+
+import com.comandante.command.DefaultCommandHandler;
+import com.comandante.command.DefaultCommandType;
+import com.comandante.managers.GameManager;
+import com.google.common.base.Optional;
+import org.jboss.netty.channel.ChannelEvent;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelStateEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
+
+public class CreeperServerHandler extends SimpleChannelUpstreamHandler {
+
+    CreeperAuthenticator creeperAuthenticator;
+    GameManager gameManager;
+
+    public CreeperServerHandler(CreeperAuthenticator creeperAuthenticator, GameManager gameManager) {
+        this.creeperAuthenticator = creeperAuthenticator;
+        this.gameManager = gameManager;
+    }
+
+    @Override
+    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
+        if (e instanceof ChannelStateEvent) {
+            System.err.println(e);
+        }
+        super.handleUpstream(ctx, e);
+    }
+
+    @Override
+    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
+        // Send greeting for a new connection.
+        e.getChannel().write("username: ");
+        CreeperSessionState creeperSessionState = new CreeperSessionState();
+        creeperSessionState.setState(CreeperSessionState.State.promptedForUsername);
+        ctx.setAttachment(creeperSessionState);
+    }
+
+    @Override
+    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
+        CreeperSessionState creeperSessionState = (CreeperSessionState) ctx.getAttachment();
+        if (!creeperSessionState.isAuthed()) {
+            doAuthentication(ctx, e);
+            if (creeperSessionState.isAuthed()) {
+                gameManager.currentRoomLogic(creeperSessionState, e);
+            }
+        } else {
+            DefaultCommandHandler cmdHandler = new DefaultCommandHandler(gameManager, creeperSessionState, e);
+            DefaultCommandType cmdType =
+                    (DefaultCommandType) DefaultCommandType.getCommandTypeFromMessage(((String) e.getMessage()));
+            cmdHandler.handle(cmdType);
+        }
+    }
+
+    private void doAuthentication(ChannelHandlerContext ctx, MessageEvent e) {
+        String message = (String) e.getMessage();
+        CreeperSessionState creeperSessionState = (CreeperSessionState) ctx.getAttachment();
+        if (creeperSessionState.getState().equals(CreeperSessionState.State.promptedForUsername)) {
+            creeperSessionState.setUsername(Optional.of(message));
+            creeperSessionState.setState(CreeperSessionState.State.promptedForPassword);
+            e.getChannel().write("password: ");
+            return;
+        }
+        if (creeperSessionState.getState().equals(CreeperSessionState.State.promptedForPassword)) {
+            creeperSessionState.setPassword(Optional.of(message));
+        }
+        boolean b = creeperAuthenticator.authenticateAndRegisterPlayer(creeperSessionState.getUsername().get(), creeperSessionState.getPassword().get(), e.getChannel());
+        if (!b) {
+            e.getChannel().write("Auth failed.\r\n");
+            e.getChannel().write("username: ");
+            creeperSessionState.setState(CreeperSessionState.State.promptedForUsername);
+        } else {
+            creeperSessionState.setAuthed(true);
+            creeperSessionState.setState(CreeperSessionState.State.authed);
+            e.getChannel().write("Welcome to bertha.\r\n");
+        }
+    }
+
+    @Override
+    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
+        e.getCause().printStackTrace();
+        e.getChannel().close();
+    }
+
+}
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java b/src/main/java/com/comandante/server/CreeperServerPipelineFactory.java
similarity index 84%
rename from src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java
rename to src/main/java/com/comandante/server/CreeperServerPipelineFactory.java
index 5f7b5739d09590cef748ef59fff395bfc113e792..6e0b291d0427531042c143128df356e91ab2f2aa 100644
--- a/src/main/java/com/comandante/telnetserver/TelnetServerPipelineFactory.java
+++ b/src/main/java/com/comandante/server/CreeperServerPipelineFactory.java
@@ -1,4 +1,4 @@
-package com.comandante.telnetserver;
+package com.comandante.server;
 
 
 import org.jboss.netty.channel.ChannelHandler;
@@ -10,11 +10,11 @@ import org.jboss.netty.handler.codec.frame.Delimiters;
 import org.jboss.netty.handler.codec.string.StringDecoder;
 import org.jboss.netty.handler.codec.string.StringEncoder;
 
-public class TelnetServerPipelineFactory implements ChannelPipelineFactory {
+public class CreeperServerPipelineFactory implements ChannelPipelineFactory {
 
     private final ChannelHandler handler;
 
-    public TelnetServerPipelineFactory(ChannelHandler handler) {
+    public CreeperServerPipelineFactory(ChannelHandler handler) {
         this.handler = handler;
     }
 
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java b/src/main/java/com/comandante/server/CreeperSessionState.java
similarity index 91%
rename from src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java
rename to src/main/java/com/comandante/server/CreeperSessionState.java
index f84f891ace426f7e453f12858fa2a6cb10d483a3..8dc4f7c2720975130b66b271f2f163491828a675 100644
--- a/src/main/java/com/comandante/telnetserver/TelnetServerAuthState.java
+++ b/src/main/java/com/comandante/server/CreeperSessionState.java
@@ -1,8 +1,8 @@
-package com.comandante.telnetserver;
+package com.comandante.server;
 
 import com.google.common.base.Optional;
 
-public class TelnetServerAuthState {
+public class CreeperSessionState {
 
     private Optional<String> username = Optional.absent();
     private Optional<String> password = Optional.absent();
@@ -12,7 +12,6 @@ public class TelnetServerAuthState {
     enum State {
         promptedForPassword,
         promptedForUsername,
-        failed,
         authed
     }
 
diff --git a/src/main/java/com/comandante/SimpleGameAuthenticator.java b/src/main/java/com/comandante/server/CreeperSimpleAuthenticator.java
similarity index 55%
rename from src/main/java/com/comandante/SimpleGameAuthenticator.java
rename to src/main/java/com/comandante/server/CreeperSimpleAuthenticator.java
index cf6580ea1a3eb525e15b54ce5eb77e22060df7dd..8b7ca74288ff05dcfdd582cc514c6b058d23d0a7 100644
--- a/src/main/java/com/comandante/SimpleGameAuthenticator.java
+++ b/src/main/java/com/comandante/server/CreeperSimpleAuthenticator.java
@@ -1,15 +1,17 @@
-package com.comandante;
+package com.comandante.server;
 
+import com.comandante.managers.GameManager;
+import com.comandante.model.Player;
 import org.jboss.netty.channel.Channel;
 
 import java.util.HashMap;
 import java.util.Map;
 
-public class SimpleGameAuthenticator implements GameAuthenticator {
+public class CreeperSimpleAuthenticator implements CreeperAuthenticator {
 
     GameManager gameManager;
 
-    public SimpleGameAuthenticator(GameManager gameManager) {
+    public CreeperSimpleAuthenticator(GameManager gameManager) {
         this.gameManager = gameManager;
     }
 
@@ -22,11 +24,10 @@ public class SimpleGameAuthenticator implements GameAuthenticator {
         userMap.put("test2", "poop");
         userMap.put("test3", "poop");
         userMap.put("test4", "poop");
-
     }
 
     @Override
-    public boolean authenticatePlayer(String userName, String passWord, Channel channel) {
+    public boolean authenticateAndRegisterPlayer(String userName, String passWord, Channel channel) {
         String userPassword = userMap.get(userName);
         if (userPassword == null) {
             return false;
@@ -34,12 +35,15 @@ public class SimpleGameAuthenticator implements GameAuthenticator {
         if (!userPassword.equals(passWord)) {
             return false;
         }
-        Player player = new Player(userName);
-        if (gameManager.doesPlayerExist(player)) {
-            gameManager.removePlayer(player);
+        if (gameManager.getPlayerManager().doesPlayerExist(userName)) {
+            gameManager.getPlayerManager().removePlayer(userName);
         }
+        Player player = new Player(userName);
         player.setChannel(channel);
-        gameManager.addPlayer(player);
+        if (!gameManager.getPlayerCurrentRoom(player).isPresent()) {
+            gameManager.placePlayerInLobby(player);
+        }
+        gameManager.getPlayerManager().addPlayer(player);
         return true;
     }
 }
diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java b/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java
deleted file mode 100644
index cfc5773bb5e7d1f50347295dba38e8c1b3461ed9..0000000000000000000000000000000000000000
--- a/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java
+++ /dev/null
@@ -1,177 +0,0 @@
-package com.comandante.telnetserver;
-
-import com.comandante.GameAuthenticator;
-import com.comandante.GameManager;
-import com.comandante.Movement;
-import com.comandante.Player;
-import com.comandante.Room;
-import com.google.common.base.Optional;
-import org.jboss.netty.channel.Channel;
-import org.jboss.netty.channel.ChannelEvent;
-import org.jboss.netty.channel.ChannelHandlerContext;
-import org.jboss.netty.channel.ChannelStateEvent;
-import org.jboss.netty.channel.ExceptionEvent;
-import org.jboss.netty.channel.MessageEvent;
-import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
-
-public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
-
-    GameAuthenticator gameAuthenticator;
-    GameManager gameManager;
-
-    public TelnetServerHandler(GameAuthenticator gameAuthenticator, GameManager gameManager) {
-        this.gameAuthenticator = gameAuthenticator;
-        this.gameManager = gameManager;
-    }
-
-    @Override
-    public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
-        if (e instanceof ChannelStateEvent) {
-            System.err.println(e);
-        }
-        super.handleUpstream(ctx, e);
-    }
-
-    @Override
-    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
-        // Send greeting for a new connection.
-        e.getChannel().write("username: ");
-        TelnetServerAuthState telnetServerAuthState = new TelnetServerAuthState();
-        telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForUsername);
-        ctx.setAttachment(telnetServerAuthState);
-    }
-
-    @Override
-    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
-        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
-        if (!telnetServerAuthState.isAuthed()) {
-            doAuthentication(ctx, e);
-            if (telnetServerAuthState.isAuthed()) {
-                currentRoomLogic(ctx, e);
-            }
-        } else {
-            processCommand(ctx, e);
-        }
-
-    }
-
-    private void processCommand(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException {
-        String command = (String) e.getMessage();
-        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
-        Player player = gameManager.getPlayer(new Player(telnetServerAuthState.getUsername().get()));
-        Room room = gameManager.getPlayerCurrentRoom(player).get();
-        if (command.equals("n")) {
-            if (room.getNorthId().isPresent()) {
-                Movement movement = new Movement(player, room.getRoomId(), room.getNorthId().get(), command);
-                gameManager.movePlayer(movement);
-                currentRoomLogic(ctx, e);
-            } else {
-                e.getChannel().write("There's no northern exit.\r\n");
-            }
-        }
-        if (command.equals("s")) {
-            if (room.getSouthId().isPresent()) {
-                Movement movement = new Movement(player, room.getRoomId(), room.getSouthId().get(), command);
-                gameManager.movePlayer(movement);
-                currentRoomLogic(ctx, e);
-            } else {
-                e.getChannel().write("There's no southern exit.\r\n");
-            }
-        }
-        if (command.equals("e")) {
-            if (room.getEastId().isPresent()) {
-                Movement movement = new Movement(player, room.getRoomId(), room.getEastId().get(), command);
-                gameManager.movePlayer(movement);
-                currentRoomLogic(ctx, e);
-            } else {
-                e.getChannel().write("There's no eastern exit.\r\n");
-            }
-        }
-        if (command.equals("w")) {
-            if (room.getSouthId().isPresent()) {
-                Movement movement = new Movement(player, room.getRoomId(), room.getWestId().get(), command);
-                gameManager.movePlayer(movement);
-                currentRoomLogic(ctx, e);
-            } else {
-                e.getChannel().write("There's no western exit.\r\n");
-            }
-        }
-        if (command.startsWith("say ")) {
-            String s = command.replaceFirst("^say ", "");
-            gameManager.say(player, s);
-        }
-        if (command.startsWith("gossip ")) {
-            String s = command.replaceFirst("^gossip ", "");
-            gameManager.gossip(player, s);
-        }
-        if (command.isEmpty()) {
-            currentRoomLogic(ctx, e);
-        }
-    }
-
-    private void printExits(Room room, Channel channel) {
-        channel.write("-exits: ");
-        if (room.getEastId().isPresent()) {
-            channel.write("e(ast) ");
-        }
-        if (room.getNorthId().isPresent()) {
-            channel.write("n(orth) ");
-        }
-        if (room.getSouthId().isPresent()) {
-            channel.write("s(outh). ");
-        }
-        if (room.getWestId().isPresent()) {
-            channel.write("w(est). ");
-        }
-        channel.write("\r\n");
-    }
-
-    private void currentRoomLogic(ChannelHandlerContext ctx, MessageEvent e) {
-        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
-        Player player = new Player(telnetServerAuthState.getUsername().get());
-        Optional<Room> playerCurrentRoom = gameManager.getPlayerCurrentRoom(player);
-        if (!playerCurrentRoom.isPresent()) {
-            gameManager.addPlayerToLobby(gameManager.getPlayer(player));
-            playerCurrentRoom = gameManager.getPlayerCurrentRoom(player);
-        }
-        e.getChannel().write(playerCurrentRoom.get().getRoomDescription() + "\r\n");
-        for (Player next : playerCurrentRoom.get().getPresentPlayers()) {
-            if (next.getPlayerId().equals(new Player(telnetServerAuthState.getUsername().get()).getPlayerId())) {
-                continue;
-            }
-            e.getChannel().write(next.getPlayerName() + " is here.\r\n");
-        }
-        printExits(playerCurrentRoom.get(), e.getChannel());
-    }
-
-    private void doAuthentication(ChannelHandlerContext ctx, MessageEvent e) {
-        String message = (String) e.getMessage();
-        TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment();
-        if (telnetServerAuthState.getState().equals(TelnetServerAuthState.State.promptedForUsername)) {
-            telnetServerAuthState.setUsername(Optional.of(message));
-            telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForPassword);
-            e.getChannel().write("password: ");
-            return;
-        }
-        if (telnetServerAuthState.getState().equals(TelnetServerAuthState.State.promptedForPassword)) {
-            telnetServerAuthState.setPassword(Optional.of(message));
-        }
-        boolean b = gameAuthenticator.authenticatePlayer(telnetServerAuthState.getUsername().get(), telnetServerAuthState.getPassword().get(), e.getChannel());
-        if (!b) {
-            e.getChannel().write("Auth failed.\r\n");
-            e.getChannel().write("username: ");
-            telnetServerAuthState.setState(TelnetServerAuthState.State.promptedForUsername);
-        } else {
-            telnetServerAuthState.setAuthed(true);
-            telnetServerAuthState.setState(TelnetServerAuthState.State.authed);
-            e.getChannel().write("Welcome to bertha.\r\n");
-        }
-    }
-
-    @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
-        e.getCause().printStackTrace();
-        e.getChannel().close();
-    }
-
-}