diff --git a/pom.xml b/pom.xml index 4d1a6be7e18ca297a7f0f602c8d825adbd6a54d9..9bfb2a047219548a0dbca0df1dd3ba747c9179b7 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,11 @@ <artifactId>commons-codec</artifactId> <version>20041127.091804</version> </dependency> + <dependency> + <groupId>org.fusesource.jansi</groupId> + <artifactId>jansi</artifactId> + <version>1.9</version> + </dependency> </dependencies> diff --git a/src/main/java/com/comandante/GameManager.java b/src/main/java/com/comandante/GameManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e7437740643fddecd77b3e0c69f80a6dfb3aa52f --- /dev/null +++ b/src/main/java/com/comandante/GameManager.java @@ -0,0 +1,123 @@ +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 50677f1be84229453e562aba92102bb6c0ee5bae..9f6b24c1294bd92ef0e5353b68b5710044911885 100644 --- a/src/main/java/com/comandante/Main.java +++ b/src/main/java/com/comandante/Main.java @@ -2,22 +2,30 @@ package com.comandante; import com.comandante.telnetserver.TelnetServer; import com.google.common.base.Optional; +import org.fusesource.jansi.Ansi; public class Main { public static void main(String[] args) throws Exception { - Room lobby = new Room(1, Optional.of(2), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), "This is the lobby."); - Room hallway = new Room(2, Optional.of(3), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(1), "This is the hallway."); - Room bedroom = new Room(3, Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(2), "This is the bedroom"); + Room lobby = new Room(1, Optional.of(2), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), + "This is the lobby. It's pretty empty and the paint still smells fresh."); + Room hallway = new Room(2, Optional.of(3), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(1), + "This is the hallway. It's long and hallway-ish with exposed wires and floorboards showing."); + Room bedroom = new Room(3, Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.<Integer>absent(), Optional.of(2), + "This is the bedroom. It's for sleeping."); - RoomManager roomManager = new RoomManager(); - roomManager.startUp(); + GameManager gameManager = new GameManager(); + gameManager.addRoom(lobby); + gameManager.addRoom(hallway); + gameManager.addRoom(bedroom); + + Ansi ansi = new Ansi(); + ansi.fg(Ansi.Color.RED); + String hello = ansi.render("hello").toString(); + System.out.println(hello); - roomManager.addRoom(lobby); - roomManager.addRoom(hallway); - roomManager.addRoom(bedroom); TelnetServer telnetServer = new TelnetServer(8080); - telnetServer.run(roomManager); + telnetServer.run(gameManager); } } diff --git a/src/main/java/com/comandante/Movement.java b/src/main/java/com/comandante/Movement.java index 4f8e01cda99a474e909edbea1f51cb16a76ecd1c..af83567937c39073208c2792c11d25c3c0c379b2 100644 --- a/src/main/java/com/comandante/Movement.java +++ b/src/main/java/com/comandante/Movement.java @@ -5,11 +5,13 @@ public class Movement { private final Player player; private final Integer sourceRoomId; private final Integer destinationRoomId; + private final String originalMovementCommand; - public Movement(Player player, Integer sourceRoomId, Integer destinationRoomId) { + public Movement(Player player, Integer sourceRoomId, Integer destinationRoomId, String originalMovementCommand) { this.player = player; this.sourceRoomId = sourceRoomId; this.destinationRoomId = destinationRoomId; + this.originalMovementCommand = originalMovementCommand; } public Integer getSourceRoomId() { @@ -23,4 +25,8 @@ public class Movement { public Player getPlayer() { return player; } + + public String getOriginalMovementCommand() { + return originalMovementCommand; + } } diff --git a/src/main/java/com/comandante/Room.java b/src/main/java/com/comandante/Room.java index 2bbbf5a21a2ee719c37c468743b7604fb2a8183f..cb6795882e6b5cd68a3f6bddaf8b7361436bc439 100644 --- a/src/main/java/com/comandante/Room.java +++ b/src/main/java/com/comandante/Room.java @@ -3,11 +3,14 @@ package com.comandante; import com.google.common.base.Optional; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; +import org.fusesource.jansi.Ansi; import java.util.Set; public class Room { + Ansi roomDescriptionText = new Ansi().fg(Ansi.Color.GREEN); + public Integer roomId; public Optional<Integer> northId; public Optional<Integer> westId; @@ -38,7 +41,7 @@ public class Room { } public String getRoomDescription() { - return roomDescription; + return new Ansi().fg(Ansi.Color.GREEN).render(roomDescription).toString() + new Ansi().reset().toString(); } public Integer getRoomId() { diff --git a/src/main/java/com/comandante/RoomManager.java b/src/main/java/com/comandante/RoomManager.java deleted file mode 100644 index 85739a532f50a04981ef1dcb1343186115df8c40..0000000000000000000000000000000000000000 --- a/src/main/java/com/comandante/RoomManager.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.comandante; - -import com.google.common.base.Optional; -import com.google.common.collect.Interners; -import com.google.common.util.concurrent.AbstractExecutionThreadService; - -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; - -public class RoomManager extends AbstractExecutionThreadService { - - ArrayBlockingQueue<Movement> movements = new ArrayBlockingQueue<Movement>(10000); - - private ConcurrentHashMap<Integer, Room> rooms = new ConcurrentHashMap<Integer, Room>(); - private ConcurrentHashMap<String, Player> players = new ConcurrentHashMap<String, Player>(); - - private AtomicBoolean isRunning = new AtomicBoolean(false); - - 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 updatePlayerMovement(Movement movement) throws InterruptedException { - movements.put(movement); - } - - public void _processMovment(Movement movement) { - synchronized (Interners.newStrongInterner()) { - rooms.get(movement.getSourceRoomId()).removePresentPlayer(movement.getPlayer()); - rooms.get(movement.getDestinationRoomId()).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(); - } - - @Override - protected void startUp() throws Exception { - isRunning.set(true); - } - - @Override - protected void shutDown() throws Exception { - isRunning.set(false); - - } - - @Override - protected void run() throws Exception { - while (isRunning.get()) { - Movement take = movements.take(); - _processMovment(take); - } - } -} diff --git a/src/main/java/com/comandante/SimpleGameAuthenticator.java b/src/main/java/com/comandante/SimpleGameAuthenticator.java index ae4dc969288faf894a836092de9b4a5269ab6d58..6c5d4bb32334a84931af9ffadd9ec2a5523ecd05 100644 --- a/src/main/java/com/comandante/SimpleGameAuthenticator.java +++ b/src/main/java/com/comandante/SimpleGameAuthenticator.java @@ -7,16 +7,17 @@ import java.util.Map; public class SimpleGameAuthenticator implements GameAuthenticator { - RoomManager roomManager; + GameManager gameManager; - public SimpleGameAuthenticator(RoomManager roomManager) { - this.roomManager = roomManager; + public SimpleGameAuthenticator(GameManager gameManager) { + this.gameManager = gameManager; } private static final Map<String, String> userMap; static { userMap = new HashMap<String, String>(); userMap.put("chris", "poop"); + userMap.put("brian", "poop"); } @Override @@ -29,11 +30,11 @@ public class SimpleGameAuthenticator implements GameAuthenticator { return false; } Player player = new Player(userName); - if (roomManager.doesPlayerExist(player)) { - roomManager.removePlayer(player); + if (gameManager.doesPlayerExist(player)) { + gameManager.removePlayer(player); } player.setChannel(channel); - roomManager.addPlayer(player); + gameManager.addPlayer(player); return true; } } diff --git a/src/main/java/com/comandante/telnetserver/TelnetServer.java b/src/main/java/com/comandante/telnetserver/TelnetServer.java index 2c3e15defb503ac813d491f203dbc34e931300ac..5a86cd768a0c87f78b944d76e5c3d06cdc28552f 100644 --- a/src/main/java/com/comandante/telnetserver/TelnetServer.java +++ b/src/main/java/com/comandante/telnetserver/TelnetServer.java @@ -1,7 +1,7 @@ package com.comandante.telnetserver; -import com.comandante.RoomManager; +import com.comandante.GameManager; import com.comandante.SimpleGameAuthenticator; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; @@ -17,10 +17,10 @@ public class TelnetServer { this.port = port; } - public void run(RoomManager roomManager) throws Exception { + public void run(GameManager gameManager) throws Exception { ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); - TelnetServerHandler handler = new TelnetServerHandler(new SimpleGameAuthenticator(roomManager), roomManager); + TelnetServerHandler handler = new TelnetServerHandler(new SimpleGameAuthenticator(gameManager), gameManager); bootstrap.setPipelineFactory(new TelnetServerPipelineFactory(handler)); bootstrap.bind(new InetSocketAddress(8080)); diff --git a/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java b/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java index 8719793f5c123bf04717e88d253e0ea98b0638e0..3393b5da577d6af4020f020c0e03d492765ce7d6 100644 --- a/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java +++ b/src/main/java/com/comandante/telnetserver/TelnetServerHandler.java @@ -1,10 +1,10 @@ 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.comandante.RoomManager; import com.google.common.base.Optional; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.ChannelEvent; @@ -17,11 +17,11 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class TelnetServerHandler extends SimpleChannelUpstreamHandler { GameAuthenticator gameAuthenticator; - RoomManager roomManager; + GameManager gameManager; - public TelnetServerHandler(GameAuthenticator gameAuthenticator, RoomManager roomManager) { + public TelnetServerHandler(GameAuthenticator gameAuthenticator, GameManager gameManager) { this.gameAuthenticator = gameAuthenticator; - this.roomManager = roomManager; + this.gameManager = gameManager; } @Override @@ -44,14 +44,13 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException { TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment(); - if(!telnetServerAuthState.isAuthed()) { + if (!telnetServerAuthState.isAuthed()) { doAuthentication(ctx, e); if (telnetServerAuthState.isAuthed()) { currentRoomLogic(ctx, e); } } else { processCommand(ctx, e); - currentRoomLogic(ctx, e); } } @@ -59,28 +58,59 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler { private void processCommand(ChannelHandlerContext ctx, MessageEvent e) throws InterruptedException { String command = (String) e.getMessage(); TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment(); - Player player = roomManager.getPlayer(new Player(telnetServerAuthState.getUsername().get())); - Room room = roomManager.getPlayerCurrentRoom(player).get(); + 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()); - roomManager._processMovment(movement); + 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()); - roomManager._processMovment(movement); + 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.getSouthId().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: "); + channel.write("-exits: "); if (room.getEastId().isPresent()) { channel.write("e(ast) "); } @@ -99,12 +129,18 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler { private void currentRoomLogic(ChannelHandlerContext ctx, MessageEvent e) { TelnetServerAuthState telnetServerAuthState = (TelnetServerAuthState) ctx.getAttachment(); Player player = new Player(telnetServerAuthState.getUsername().get()); - Optional<Room> playerCurrentRoom = roomManager.getPlayerCurrentRoom(player); + Optional<Room> playerCurrentRoom = gameManager.getPlayerCurrentRoom(player); if (!playerCurrentRoom.isPresent()) { - roomManager.addPlayerToLobby(roomManager.getPlayer(player)); - playerCurrentRoom = roomManager.getPlayerCurrentRoom(player); + 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()); }