From 58d9e185caef8c120b771b22dcb42766cfde0f7e Mon Sep 17 00:00:00 2001 From: Chris Kearney <chris@kearneymail.com> Date: Mon, 27 Apr 2015 23:21:05 -0700 Subject: [PATCH] merchants and lots of new npc --- pom.xml | 209 +++++++++--------- .../comandante/creeper/Items/ItemType.java | 2 +- .../creeper/Items/ItemUseHandler.java | 6 +- .../java/com/comandante/creeper/Main.java | 88 +++++++- .../creeper/managers/GameManager.java | 28 ++- .../creeper/merchant/LloydBartender.java | 40 ++++ .../comandante/creeper/merchant/Merchant.java | 92 ++++++++ .../merchant/MerchantCommandHandler.java | 50 +++++ .../creeper/merchant/MerchantItemForSale.java | 27 +++ .../creeper/merchant/MerchantManager.java | 39 ++++ .../comandante/creeper/npc/DeathGriffin.java | 35 +++ .../comandante/creeper/npc/DemonSuccubus.java | 35 +++ .../creeper/npc/NightmareTroll.java | 35 +++ .../com/comandante/creeper/npc/NpcStats.java | 111 ++++++++++ .../comandante/creeper/npc/PhantomKnight.java | 35 +++ .../comandante/creeper/npc/PhantomOrc.java | 35 +++ .../comandante/creeper/npc/PhantomWizard.java | 35 +++ .../comandante/creeper/npc/RazorClawWolf.java | 35 +++ .../creeper/npc/TigerMonocerus.java | 35 +++ .../creeper/server/CreeperCommandHandler.java | 14 ++ .../creeper/server/CreeperSession.java | 18 ++ .../creeper/server/command/Command.java | 27 ++- .../creeper/server/command/TalkCommand.java | 54 +++++ .../creeper/server/command/WhoCommand.java | 1 - .../creeper/spawner/ItemSpawner.java | 3 + .../creeper/spawner/NpcSpawner.java | 3 + .../com/comandante/creeper/world/Room.java | 18 ++ .../comandante/creeper/world/RoomManager.java | 5 + .../creeper/world/WorldExporter.java | 1 + src/main/resources/log4j.properties | 22 ++ 30 files changed, 1009 insertions(+), 129 deletions(-) create mode 100644 src/main/java/com/comandante/creeper/merchant/LloydBartender.java create mode 100644 src/main/java/com/comandante/creeper/merchant/Merchant.java create mode 100644 src/main/java/com/comandante/creeper/merchant/MerchantCommandHandler.java create mode 100644 src/main/java/com/comandante/creeper/merchant/MerchantItemForSale.java create mode 100644 src/main/java/com/comandante/creeper/merchant/MerchantManager.java create mode 100644 src/main/java/com/comandante/creeper/npc/DeathGriffin.java create mode 100644 src/main/java/com/comandante/creeper/npc/DemonSuccubus.java create mode 100644 src/main/java/com/comandante/creeper/npc/NightmareTroll.java create mode 100644 src/main/java/com/comandante/creeper/npc/PhantomKnight.java create mode 100644 src/main/java/com/comandante/creeper/npc/PhantomOrc.java create mode 100644 src/main/java/com/comandante/creeper/npc/PhantomWizard.java create mode 100644 src/main/java/com/comandante/creeper/npc/RazorClawWolf.java create mode 100644 src/main/java/com/comandante/creeper/npc/TigerMonocerus.java create mode 100644 src/main/java/com/comandante/creeper/server/command/TalkCommand.java create mode 100644 src/main/resources/log4j.properties diff --git a/pom.xml b/pom.xml index dd19dc4c..8d8e31b4 100644 --- a/pom.xml +++ b/pom.xml @@ -2,106 +2,117 @@ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>com.comandante</groupId> - <artifactId>creeper</artifactId> - <version>0.1.0-SNAPSHOT</version> - <dependencies> - <dependency> - <groupId>com.google.guava</groupId> - <artifactId>guava</artifactId> - <version>17.0</version> - </dependency> - <dependency> - <groupId>io.netty</groupId> - <artifactId>netty</artifactId> - <version>3.6.9.Final</version> - </dependency> - <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>1.9</version> - </dependency> - <dependency> - <groupId>org.apache.commons</groupId> - <artifactId>commons-lang3</artifactId> - <version>3.3.2</version> - </dependency> - <dependency> - <groupId>org.fusesource.jansi</groupId> - <artifactId>jansi</artifactId> - <version>1.11</version> - </dependency> - <dependency> - <groupId>org.mapdb</groupId> - <artifactId>mapdb</artifactId> - <version>1.0.6</version> - </dependency> - <dependency> - <groupId>com.google.code.gson</groupId> - <artifactId>gson</artifactId> - <version>2.2.4</version> - </dependency> - <dependency> - <groupId>org.ow2.sirocco</groupId> - <artifactId>sirocco-text-table-formatter</artifactId> - <version>1.0</version> - </dependency> - <dependency> - <groupId>com.codahale.metrics</groupId> - <artifactId>metrics-core</artifactId> - <version>3.0.2</version> - </dependency> - <dependency> - <groupId>com.googlecode.concurrentlinkedhashmap</groupId> - <artifactId>concurrentlinkedhashmap-lru</artifactId> - <version>1.4</version> - </dependency> - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - <version>1.2.17</version> - </dependency> - </dependencies> + <modelVersion>4.0.0</modelVersion> + <groupId>com.comandante</groupId> + <artifactId>creeper</artifactId> + <version>0.1.0-SNAPSHOT</version> + <dependencies> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>17.0</version> + </dependency> + <dependency> + <groupId>io.netty</groupId> + <artifactId>netty</artifactId> + <version>3.6.9.Final</version> + </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.9</version> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>3.3.2</version> + </dependency> + <dependency> + <groupId>org.fusesource.jansi</groupId> + <artifactId>jansi</artifactId> + <version>1.11</version> + </dependency> + <dependency> + <groupId>org.mapdb</groupId> + <artifactId>mapdb</artifactId> + <version>1.0.6</version> + </dependency> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.2.4</version> + </dependency> + <dependency> + <groupId>org.ow2.sirocco</groupId> + <artifactId>sirocco-text-table-formatter</artifactId> + <version>1.0</version> + </dependency> + <dependency> + <groupId>io.dropwizard.metrics</groupId> + <artifactId>metrics-core</artifactId> + <version>3.1.2</version> + </dependency> + <dependency> + <groupId>io.dropwizard.metrics</groupId> + <artifactId>metrics-graphite</artifactId> + <version>3.1.2</version> + </dependency> + <dependency> + <groupId>com.googlecode.concurrentlinkedhashmap</groupId> + <artifactId>concurrentlinkedhashmap-lru</artifactId> + <version>1.4</version> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.17</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.7.12</version> + </dependency> + </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <version>3.1</version> - <configuration> - <source>1.7</source> - <target>1.7</target> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>2.3</version> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - <configuration> - <createDependencyReducedPom>false</createDependencyReducedPom> - <transformers> - <transformer - implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <manifestEntries> - <Main-Class>com.comandante.creeper.Main</Main-Class> - <Build-Number>0.1.0-SNAPSHOT</Build-Number> - </manifestEntries> - </transformer> - </transformers> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.1</version> + <configuration> + <source>1.7</source> + <target>1.7</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-shade-plugin</artifactId> + <version>2.3</version> + <executions> + <execution> + <phase>package</phase> + <goals> + <goal>shade</goal> + </goals> + <configuration> + <createDependencyReducedPom>false</createDependencyReducedPom> + <transformers> + <transformer + implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> + <manifestEntries> + <Main-Class>com.comandante.creeper.Main</Main-Class> + <Build-Number>0.1.0-SNAPSHOT</Build-Number> + </manifestEntries> + </transformer> + </transformers> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/src/main/java/com/comandante/creeper/Items/ItemType.java b/src/main/java/com/comandante/creeper/Items/ItemType.java index 566915ff..0756c1c8 100644 --- a/src/main/java/com/comandante/creeper/Items/ItemType.java +++ b/src/main/java/com/comandante/creeper/Items/ItemType.java @@ -21,7 +21,7 @@ public enum ItemType { BEER(2, Arrays.asList("beer", "can of beer", "b"), "a dented can of " + CYAN + "beer" + RESET, "a " + CYAN + "beer" + RESET + " lies on the ground, unopened", - "This beer looks sketch but you'll probably drink it anyways.", + "an ice cold " + CYAN + "beer" + RESET + " that restores 20 health" + RESET, true, 2, 60), diff --git a/src/main/java/com/comandante/creeper/Items/ItemUseHandler.java b/src/main/java/com/comandante/creeper/Items/ItemUseHandler.java index 3aa63c8a..871db8bf 100644 --- a/src/main/java/com/comandante/creeper/Items/ItemUseHandler.java +++ b/src/main/java/com/comandante/creeper/Items/ItemUseHandler.java @@ -1,6 +1,8 @@ package com.comandante.creeper.Items; +import com.codahale.metrics.MetricRegistry; +import com.comandante.creeper.Main; import com.comandante.creeper.managers.GameManager; import com.comandante.creeper.server.CreeperSession; @@ -26,9 +28,11 @@ public class ItemUseHandler { } private void processBeer() { - writeToRoom(gameManager.getPlayerManager().getPlayer(playerId).getPlayerName() + " drinks an ice cold cruiser." + "\r\n"); + String playerName = gameManager.getPlayerManager().getPlayer(playerId).getPlayerName(); + writeToRoom(playerName + " drinks an ice cold cruiser." + "\r\n"); writeToPlayer("20 health is restored."); gameManager.getPlayerManager().getPlayerMetadata(playerId).getStats().incrementHealth(20); + Main.metrics.counter(MetricRegistry.name(ItemUseHandler.class, playerName + "-beer-drank")).inc(); } private void processBook() { diff --git a/src/main/java/com/comandante/creeper/Main.java b/src/main/java/com/comandante/creeper/Main.java index 661bb877..c3fe8980 100644 --- a/src/main/java/com/comandante/creeper/Main.java +++ b/src/main/java/com/comandante/creeper/Main.java @@ -1,14 +1,22 @@ package com.comandante.creeper; +import com.codahale.metrics.JmxReporter; +import com.codahale.metrics.MetricFilter; +import com.codahale.metrics.MetricRegistry; +import com.codahale.metrics.graphite.Graphite; +import com.codahale.metrics.graphite.GraphiteReporter; +import com.codahale.metrics.graphite.PickledGraphite; import com.comandante.creeper.Items.Item; import com.comandante.creeper.Items.ItemType; import com.comandante.creeper.Items.Loot; import com.comandante.creeper.entity.EntityManager; import com.comandante.creeper.managers.GameManager; import com.comandante.creeper.managers.SessionManager; +import com.comandante.creeper.merchant.LloydBartender; +import com.comandante.creeper.merchant.Merchant; +import com.comandante.creeper.merchant.MerchantItemForSale; import com.comandante.creeper.npc.*; import com.comandante.creeper.player.PlayerManager; -import com.comandante.creeper.player.PlayerMetadata; import com.comandante.creeper.server.ChannelUtils; import com.comandante.creeper.server.CreeperCommandRegistry; import com.comandante.creeper.server.CreeperServer; @@ -17,14 +25,11 @@ import com.comandante.creeper.server.command.admin.*; import com.comandante.creeper.spawner.ItemSpawner; import com.comandante.creeper.spawner.NpcSpawner; import com.comandante.creeper.spawner.SpawnRule; -import com.comandante.creeper.stat.Stats; -import com.comandante.creeper.stat.StatsBuilder; import com.comandante.creeper.world.Area; import com.comandante.creeper.world.MapsManager; -import com.comandante.creeper.world.Room; import com.comandante.creeper.world.RoomManager; import com.comandante.creeper.world.WorldExporter; -import com.google.common.base.Optional; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.io.Files; import org.apache.commons.codec.binary.Base64; @@ -34,9 +39,9 @@ import org.mapdb.DBMaker; import java.io.File; import java.io.IOException; -import java.util.Iterator; +import java.net.InetSocketAddress; import java.util.Map; -import java.util.Set; +import java.util.concurrent.TimeUnit; public class Main { @@ -46,8 +51,22 @@ public class Main { private static final int PORT = 8080; public static final String MUD_NAME = "creeper"; + final public static MetricRegistry metrics = new MetricRegistry(); + public static void main(String[] args) throws Exception { + final JmxReporter jmxReporter = JmxReporter.forRegistry(metrics).build(); + jmxReporter.start(); + + final PickledGraphite pickledGraphite = new PickledGraphite(new InetSocketAddress("192.168.1.11", 2004)); + final GraphiteReporter reporter = GraphiteReporter.forRegistry(metrics) + .prefixedWith(MUD_NAME) + .convertRatesTo(TimeUnit.SECONDS) + .convertDurationsTo(TimeUnit.MILLISECONDS) + .filter(MetricFilter.ALL) + .build(pickledGraphite); + reporter.start(1, TimeUnit.MINUTES); + checkAndCreateWorld(); DB db = DBMaker.newFileDB(new File("world/creeper.mapdb")).closeOnJvmShutdown().encryptionEnable("creepandicrawl").make(); @@ -91,6 +110,8 @@ public class Main { creeperCommandRegistry.addCommand(new GoldCommand(gameManager)); creeperCommandRegistry.addCommand(new InfoCommand(gameManager)); creeperCommandRegistry.addCommand(new TeleportCommand(gameManager)); + creeperCommandRegistry.addCommand(new TalkCommand(gameManager)); + createNpcs(entityManager, gameManager); @@ -101,7 +122,7 @@ public class Main { } private static void startUpMessage(String message) { - System.out.println("[STARTUP] " + message); + //System.out.println("[STARTUP] " + message); log.info(message); } @@ -151,5 +172,54 @@ public class Main { entityManager.addEntity(new NpcSpawner(new StealthPanther(gameManager, new Loot(14, 22, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH5_ZONE), gameManager, new SpawnRule(10, 12, 3, 100))); entityManager.addEntity(new NpcSpawner(new StealthPanther(gameManager, new Loot(14, 22, Sets.<Item>newHashSet())), Sets.newHashSet(Area.NORTH6_ZONE), gameManager, new SpawnRule(10, 12, 3, 100))); - } + startUpMessage("Adding Phantom Knights"); + + PhantomKnight phantomKnight = new PhantomKnight(gameManager, new Loot(18, 26, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE5_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE6_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + entityManager.addEntity(new NpcSpawner(phantomKnight, Sets.newHashSet(Area.BLOODRIDGE7_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + + PhantomOrc phantomOrc = new PhantomOrc(gameManager, new Loot(16, 24, Sets.<Item>newHashSet())); + startUpMessage("Adding Phantom Orcs"); + entityManager.addEntity(new NpcSpawner(phantomOrc, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(phantomOrc, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + PhantomWizard phantomWizard = new PhantomWizard(gameManager, new Loot(16, 24, Sets.<Item>newHashSet())); + startUpMessage("Adding Phantom Wizards"); + entityManager.addEntity(new NpcSpawner(phantomWizard, Sets.newHashSet(Area.BLOODRIDGE4_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(phantomWizard, Sets.newHashSet(Area.BLOODRIDGE5_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + startUpMessage("Adding Demon Succubi"); + DemonSuccubus demonSuccubus = new DemonSuccubus(gameManager, new Loot(80, 100, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(demonSuccubus, Sets.newHashSet(Area.WESTERN9_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(demonSuccubus, Sets.newHashSet(Area.WESTERN10_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + startUpMessage("Adding Death Griffins"); + DeathGriffin deathGriffin = new DeathGriffin(gameManager, new Loot(60, 80, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(deathGriffin, Sets.newHashSet(Area.WESTERN8_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(deathGriffin, Sets.newHashSet(Area.WESTERN9_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + startUpMessage("Adding Nightmare Trolls"); + NightmareTroll nightmareTroll = new NightmareTroll(gameManager, new Loot(18, 26, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(nightmareTroll, Sets.newHashSet(Area.NORTH7_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(nightmareTroll, Sets.newHashSet(Area.NORTH8_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + startUpMessage("Adding Tiger Monoceruses"); + TigerMonocerus tigerMonocerus = new TigerMonocerus(gameManager, new Loot(20, 29, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(tigerMonocerus, Sets.newHashSet(Area.NORTH8_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(tigerMonocerus, Sets.newHashSet(Area.NORTH9_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + startUpMessage("Adding Razor-claw Wolves"); + RazorClawWolf razorClawWolf = new RazorClawWolf(gameManager, new Loot(18, 26, Sets.<Item>newHashSet())); + entityManager.addEntity(new NpcSpawner(razorClawWolf, Sets.newHashSet(Area.TOFT2_ZONE), gameManager, new SpawnRule(10, 6, 2, 100))); + entityManager.addEntity(new NpcSpawner(razorClawWolf, Sets.newHashSet(Area.TOFT3_ZONE), gameManager, new SpawnRule(10, 14, 2, 100))); + + Map<Integer, MerchantItemForSale> itemsForSale = Maps.newHashMap(); + MerchantItemForSale merchantItemForSale = new MerchantItemForSale(ItemType.BEER, 2); + itemsForSale.put(1, merchantItemForSale); + LloydBartender lloydBartender = new LloydBartender(gameManager, new Loot(18, 26, Sets.<Item>newHashSet()), itemsForSale); + gameManager.getRoomManager().addMerchant(64, lloydBartender); + + } } diff --git a/src/main/java/com/comandante/creeper/managers/GameManager.java b/src/main/java/com/comandante/creeper/managers/GameManager.java index 3f4c0a46..3be257f3 100644 --- a/src/main/java/com/comandante/creeper/managers/GameManager.java +++ b/src/main/java/com/comandante/creeper/managers/GameManager.java @@ -6,6 +6,7 @@ import com.comandante.creeper.Items.ItemDecayManager; import com.comandante.creeper.Items.LootManager; import com.comandante.creeper.entity.EntityManager; import com.comandante.creeper.fight.FightManager; +import com.comandante.creeper.merchant.Merchant; import com.comandante.creeper.npc.Npc; import com.comandante.creeper.player.Player; import com.comandante.creeper.player.PlayerManager; @@ -30,15 +31,15 @@ import static com.comandante.creeper.server.Color.*; public class GameManager { - public static String LOGO = " ▄████▄ ██▀███ ▓█████ ▓█████ ██▓███ ▓█████ ██▀███ \n" + - "▒██▀ ▀█ ▓██ ▒ ██▒▓█ ▀ ▓█ ▀ ▓██░ ██▒▓█ ▀ ▓██ ▒ ██▒\n" + - "▒▓█ ▄ ▓██ ░▄█ ▒▒███ ▒███ ▓██░ ██▓▒▒███ ▓██ ░▄█ ▒\n" + - "▒▓▓▄ ▄██▒▒██▀▀█▄ ▒▓█ ▄ ▒▓█ ▄ ▒██▄█▓▒ ▒▒▓█ ▄ ▒██▀▀█▄ \n" + - "▒ ▓███▀ ░░██▓ ▒██▒░▒████▒░▒████▒▒██▒ ░ ░░▒████▒░██▓ ▒██▒\n" + - "░ ░▒ ▒ ░░ ▒▓ ░▒▓░░░ ▒░ ░░░ ▒░ ░▒▓▒░ ░ ░░░ ▒░ ░░ ▒▓ ░▒▓░\n" + - " ░ ▒ ░▒ ░ ▒░ ░ ░ ░ ░ ░ ░░▒ ░ ░ ░ ░ ░▒ ░ ▒░\n" + - "░ ░░ ░ ░ ░ ░░ ░ ░░ ░ \n" + - "░ ░ ░ ░ ░ ░ ░ ░ ░ ░ \n" + + public static String LOGO = " ▄████▄ ██▀███ ▓█████ ▓█████ ██▓███ ▓█████ ██▀███ \r\n" + + "▒██▀ ▀█ ▓██ ▒ ██▒▓█ ▀ ▓█ ▀ ▓██░ ██▒▓█ ▀ ▓██ ▒ ██▒\r\n" + + "▒▓█ ▄ ▓██ ░▄█ ▒▒███ ▒███ ▓██░ ██▓▒▒███ ▓██ ░▄█ ▒\r\n" + + "▒▓▓▄ ▄██▒▒██▀▀█▄ ▒▓█ ▄ ▒▓█ ▄ ▒██▄█▓▒ ▒▒▓█ ▄ ▒██▀▀█▄ \r\n" + + "▒ ▓███▀ ░░██▓ ▒██▒░▒████▒░▒████▒▒██▒ ░ ░░▒████▒░██▓ ▒██▒\r\n" + + "░ ░▒ ▒ ░░ ▒▓ ░▒▓░░░ ▒░ ░░░ ▒░ ░▒▓▒░ ░ ░░░ ▒░ ░░ ▒▓ ░▒▓░\r\n" + + " ░ ▒ ░▒ ░ ▒░ ░ ░ ░ ░ ░ ░░▒ ░ ░ ░ ░ ░▒ ░ ▒░\r\n" + + "░ ░░ ░ ░ ░ ░░ ░ ░░ ░ \r\n" + + "░ ░ ░ ░ ░ ░ ░ ░ ░ ░ \r\n" + "░ "; public static String VERSION = "0.1-SNAPSHOT"; @@ -267,6 +268,11 @@ public class GameManager { // sb.append(playerCurrentRoom.getMapData().get()).append("\r\n"); // } sb.append(getExits(playerCurrentRoom, player)).append("\r\n"); + + Set<Merchant> merchants = playerCurrentRoom.getMerchants(); + for (Merchant merchant: merchants) { + sb.append(merchant.getColorName()).append(" is here.").append(RESET).append("\r\n"); + } for (String searchPlayerId : playerCurrentRoom.getPresentPlayerIds()) { if (searchPlayerId.equals(player.getPlayerId())) { continue; @@ -309,7 +315,9 @@ public class GameManager { public void acquireItem(Player player, String itemId) { Room playerCurrentRoom = roomManager.getPlayerCurrentRoom(player).get(); - playerCurrentRoom.getItemIds().remove(itemId); + if (playerCurrentRoom.getItemIds().contains(itemId)) { + playerCurrentRoom.getItemIds().remove(itemId); + } playerManager.addInventoryId(player.getPlayerId(), itemId); Item itemEntity = entityManager.getItemEntity(itemId); itemEntity.setWithPlayer(true); diff --git a/src/main/java/com/comandante/creeper/merchant/LloydBartender.java b/src/main/java/com/comandante/creeper/merchant/LloydBartender.java new file mode 100644 index 00000000..67b49e35 --- /dev/null +++ b/src/main/java/com/comandante/creeper/merchant/LloydBartender.java @@ -0,0 +1,40 @@ +package com.comandante.creeper.merchant; + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.npc.Npc; +import com.comandante.creeper.npc.NpcStats; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class LloydBartender extends Merchant { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "lloyd the bartender"; + private final static String welcomeMessage = " _ _ _______ ______ _ _______ \r\n" + + "( \\ ( \\ ( ___ )|\\ /|( __ \\ ( )( ____ \\\r\n" + + "| ( | ( | ( ) |( \\ / )| ( \\ )|/ | ( \\/\r\n" + + "| | | | | | | | \\ (_) / | | ) | | (_____ \r\n" + + "| | | | | | | | \\ / | | | | (_____ )\r\n" + + "| | | | | | | | ) ( | | ) | ) |\r\n" + + "| (____/\\| (____/\\| (___) | | | | (__/ ) /\\____) |\r\n" + + "(_______/(_______/(_______) \\_/ (______/ \\_______)\r\n" + + " "; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"lloyd", "bartender", "barkeep", "Lloyd", "LLOYD", NAME} + )); + + private final static String colorName = BOLD_ON + Color.CYAN + NAME + Color.RESET ; + + public LloydBartender(GameManager gameManager, Loot loot, Map<Integer, MerchantItemForSale> merchantItemForSales) { + super(gameManager, NAME, colorName, validTriggers, merchantItemForSales, welcomeMessage); + } +} diff --git a/src/main/java/com/comandante/creeper/merchant/Merchant.java b/src/main/java/com/comandante/creeper/merchant/Merchant.java new file mode 100644 index 00000000..fb6f3d67 --- /dev/null +++ b/src/main/java/com/comandante/creeper/merchant/Merchant.java @@ -0,0 +1,92 @@ +package com.comandante.creeper.merchant; + +import com.comandante.creeper.Items.Item; +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.entity.CreeperEntity; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.player.Player; +import com.comandante.creeper.stat.Stats; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; +import org.nocrala.tools.texttablefmt.BorderStyle; +import org.nocrala.tools.texttablefmt.ShownBorders; +import org.nocrala.tools.texttablefmt.Table; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +public abstract class Merchant extends CreeperEntity { + + private long lastPhraseTimestamp; + private final GameManager gameManager; + private final String name; + private final String colorName; + private final Set<String> validTriggers; + private final Map<Integer, MerchantItemForSale> merchantItemForSales; + private final String welcomeMessage; + + public Merchant(GameManager gameManager, String name, String colorName, Set<String> validTriggers, Map<Integer, MerchantItemForSale> merchantItemForSales, String welcomeMessage) { + this.gameManager = gameManager; + this.name = name; + this.colorName = colorName; + this.validTriggers = validTriggers; + this.merchantItemForSales = merchantItemForSales; + this.welcomeMessage = welcomeMessage; + } + + public String getMenu() { + Table t = new Table(3, BorderStyle.CLASSIC_COMPATIBLE, + ShownBorders.HEADER_FOOTER_FIRST_AND_LAST_COLLUMN); + t.setColumnWidth(0, 2, 5); + t.setColumnWidth(1, 5, 5); + t.setColumnWidth(2, 50, 69); + t.addCell("#"); + t.addCell("price"); + t.addCell("description"); + int i = 1; + Iterator<Map.Entry<Integer, MerchantItemForSale>> entries = merchantItemForSales.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry<Integer, MerchantItemForSale> next = entries.next(); + t.addCell(String.valueOf(next.getKey())); + t.addCell(String.valueOf(next.getValue().getCost())); + t.addCell(next.getValue().getItem().getItemDescription()); + i++; + } + return t.render(); + } + + @Override + public void run() { + + } + + public long getLastPhraseTimestamp() { + return lastPhraseTimestamp; + } + + public GameManager getGameManager() { + return gameManager; + } + + public String getName() { + return name; + } + + public String getColorName() { + return colorName; + } + + public Set<String> getValidTriggers() { + return validTriggers; + } + + public Map<Integer, MerchantItemForSale> getMerchantItemForSales() { + return merchantItemForSales; + } + + public String getWelcomeMessage() { + return welcomeMessage; + } +} diff --git a/src/main/java/com/comandante/creeper/merchant/MerchantCommandHandler.java b/src/main/java/com/comandante/creeper/merchant/MerchantCommandHandler.java new file mode 100644 index 00000000..0a9ef254 --- /dev/null +++ b/src/main/java/com/comandante/creeper/merchant/MerchantCommandHandler.java @@ -0,0 +1,50 @@ +package com.comandante.creeper.merchant; + +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.player.Player; +import com.comandante.creeper.server.CreeperSession; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.MessageEvent; +import org.jboss.netty.channel.SimpleChannelUpstreamHandler; + +import java.util.UUID; + +public class MerchantCommandHandler extends SimpleChannelUpstreamHandler { + + private final GameManager gameManager; + private final Merchant merchant; + private final MerchantManager merchantManager; + + public MerchantCommandHandler(GameManager gameManager, Merchant merchant) { + this.gameManager = gameManager; + this.merchant = merchant; + this.merchantManager = new MerchantManager(gameManager); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + CreeperSession creeperSession = (CreeperSession) e.getChannel().getAttachment(); + Player playerByUsername = gameManager.getPlayerManager().getPlayerByUsername(creeperSession.getUsername().get()); + try { + String message = (String) e.getMessage(); + String cmd = message; + if (message.contains(" ")) { + String[] split = message.split(" "); + cmd = split[0]; + Integer desiredItem = Integer.parseInt(split[1]); + if (cmd.equalsIgnoreCase("buy")) { + merchantManager.purchaseItem(merchant, desiredItem, playerByUsername); + } + } else if (cmd.equalsIgnoreCase("done")) { + gameManager.getChannelUtils().write(playerByUsername.getPlayerId(), "Thanks, COME AGAIN." + "\r\n"+ "\r\n"+ "\r\n", true); + e.getChannel().getPipeline().addLast(UUID.randomUUID().toString(), creeperSession.getGrabMerchant().get().getValue()); + return; + } + gameManager.getChannelUtils().write(playerByUsername.getPlayerId(), merchant.getMenu() + "\r\n"); + gameManager.getChannelUtils().write(playerByUsername.getPlayerId(), "\r\n[" + merchant.getName() + " (done to exit, buy <itemNo>)] "); + } finally { + e.getChannel().getPipeline().remove(ctx.getHandler()); + super.messageReceived(ctx, e); + } + } +} diff --git a/src/main/java/com/comandante/creeper/merchant/MerchantItemForSale.java b/src/main/java/com/comandante/creeper/merchant/MerchantItemForSale.java new file mode 100644 index 00000000..73880ba7 --- /dev/null +++ b/src/main/java/com/comandante/creeper/merchant/MerchantItemForSale.java @@ -0,0 +1,27 @@ +package com.comandante.creeper.merchant; + +import com.comandante.creeper.Items.Item; +import com.comandante.creeper.Items.ItemType; +import com.comandante.creeper.managers.GameManager; + +import java.util.Map; +import java.util.Set; + + +public class MerchantItemForSale { + private final ItemType itemType; + private final int cost; + + public MerchantItemForSale(ItemType itemType, int cost) { + this.itemType = itemType; + this.cost = cost; + } + + public ItemType getItem() { + return itemType; + } + + public int getCost() { + return cost; + } +} diff --git a/src/main/java/com/comandante/creeper/merchant/MerchantManager.java b/src/main/java/com/comandante/creeper/merchant/MerchantManager.java new file mode 100644 index 00000000..47e54e1f --- /dev/null +++ b/src/main/java/com/comandante/creeper/merchant/MerchantManager.java @@ -0,0 +1,39 @@ +package com.comandante.creeper.merchant; + + +import com.comandante.creeper.Items.Item; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.player.Player; + +import java.util.Iterator; +import java.util.Map; +import java.util.UUID; + +public class MerchantManager { + + private final GameManager gameManager; + + public MerchantManager(GameManager gameManager) { + this.gameManager = gameManager; + } + + public void purchaseItem(Merchant merchant, int itemNo, Player player) { + Iterator<Map.Entry<Integer, MerchantItemForSale>> merchantItemForSales = merchant.getMerchantItemForSales().entrySet().iterator(); + while (merchantItemForSales.hasNext()) { + Map.Entry<Integer, MerchantItemForSale> next = merchantItemForSales.next(); + if (next.getKey().equals(itemNo)) { + int price = next.getValue().getCost(); + int availableGold = gameManager.getPlayerManager().getPlayerMetadata(player.getPlayerId()).getGold(); + if (availableGold >= price) { + Item item = next.getValue().getItem().create(); + gameManager.getEntityManager().addItem(item); + gameManager.acquireItem(player, item.getItemId()); + gameManager.getPlayerManager().incrementGold(player.getPlayerId(), -price); + gameManager.getChannelUtils().write(player.getPlayerId(), "You have purchased: " + item.getItemName() + "\r\n"); + } else { + gameManager.getChannelUtils().write(player.getPlayerId(), "You can't afford: " + next.getValue().getItem().getItemName() + "\r\n"); + } + } + } + } +} diff --git a/src/main/java/com/comandante/creeper/npc/DeathGriffin.java b/src/main/java/com/comandante/creeper/npc/DeathGriffin.java new file mode 100644 index 00000000..c01b96df --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/DeathGriffin.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class DeathGriffin extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "death griffin"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"d", "death", "griffin","g", NAME} + )); + + private final static String colorName = "death" + BOLD_ON + Color.MAGENTA + " griffin" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public DeathGriffin(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.DEATH_GRIFFIN.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public DeathGriffin create(GameManager gameManager, Loot loot) { + return new DeathGriffin(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/DemonSuccubus.java b/src/main/java/com/comandante/creeper/npc/DemonSuccubus.java new file mode 100644 index 00000000..f968040d --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/DemonSuccubus.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class DemonSuccubus extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "demon succubus"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"d", "demon", "succubus","s", NAME} + )); + + private final static String colorName = "demon" + BOLD_ON + Color.MAGENTA + " succubus" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public DemonSuccubus(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.DEMON_SUCCUBUS.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public DemonSuccubus create(GameManager gameManager, Loot loot) { + return new DemonSuccubus(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/NightmareTroll.java b/src/main/java/com/comandante/creeper/npc/NightmareTroll.java new file mode 100644 index 00000000..89bde58d --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/NightmareTroll.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class NightmareTroll extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "nightmare troll"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"n", "nightmare", "troll","t", NAME} + )); + + private final static String colorName = "nightmare" + BOLD_ON + Color.MAGENTA + " troll" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public NightmareTroll(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.NIGHTMARE_TROLL.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public NightmareTroll create(GameManager gameManager, Loot loot) { + return new NightmareTroll(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/NpcStats.java b/src/main/java/com/comandante/creeper/npc/NpcStats.java index 2ad1673a..f92aeca4 100644 --- a/src/main/java/com/comandante/creeper/npc/NpcStats.java +++ b/src/main/java/com/comandante/creeper/npc/NpcStats.java @@ -136,5 +136,116 @@ public class NpcStats { .setNumberweaponOfRolls(1) .setExperience(510); + public final static StatsBuilder DEATH_GRIFFIN = new StatsBuilder() + .setStrength(55) + .setWillpower(30) + .setAim(24) + .setAgile(24) + .setArmorRating(20) + .setMeleSkill(19) + .setCurrentHealth(1000) + .setMaxHealth(1000) + .setWeaponRatingMin(20) + .setWeaponRatingMax(65) + .setNumberweaponOfRolls(1) + .setExperience(2100); + + public final static StatsBuilder DEMON_SUCCUBUS = new StatsBuilder() + .setStrength(70) + .setWillpower(35) + .setAim(14) + .setAgile(14) + .setArmorRating(25) + .setMeleSkill(19) + .setCurrentHealth(1200) + .setMaxHealth(1200) + .setWeaponRatingMin(35) + .setWeaponRatingMax(60) + .setNumberweaponOfRolls(1) + .setExperience(2600); + + public final static StatsBuilder TIGER_MONOCERUS = new StatsBuilder() + .setStrength(28) + .setWillpower(10) + .setAim(5) + .setAgile(9) + .setArmorRating(12) + .setMeleSkill(19) + .setCurrentHealth(600) + .setMaxHealth(600) + .setWeaponRatingMin(20) + .setWeaponRatingMax(36) + .setNumberweaponOfRolls(1) + .setExperience(800); + + public final static StatsBuilder NIGHTMARE_TROLL = new StatsBuilder() + .setStrength(34) + .setWillpower(7) + .setAim(6) + .setAgile(6) + .setArmorRating(18) + .setMeleSkill(8) + .setCurrentHealth(550) + .setMaxHealth(550) + .setWeaponRatingMin(5) + .setWeaponRatingMax(32) + .setNumberweaponOfRolls(1) + .setExperience(720); + + public final static StatsBuilder RAZORCLAW_WOLF = new StatsBuilder() + .setStrength(25) + .setWillpower(10) + .setAim(5) + .setAgile(9) + .setArmorRating(8) + .setMeleSkill(12) + .setCurrentHealth(500) + .setMaxHealth(500) + .setWeaponRatingMin(10) + .setWeaponRatingMax(27) + .setNumberweaponOfRolls(1) + .setExperience(600); + + public final static StatsBuilder PHANTOM_WIZARD = new StatsBuilder() + .setStrength(16) + .setWillpower(9) + .setAim(4) + .setAgile(5) + .setArmorRating(9) + .setMeleSkill(8) + .setCurrentHealth(400) + .setMaxHealth(400) + .setWeaponRatingMin(12) + .setWeaponRatingMax(25) + .setNumberweaponOfRolls(1) + .setExperience(510); + + public final static StatsBuilder PHANTOM_KNIGHT = new StatsBuilder() + .setStrength(28) + .setWillpower(5) + .setAim(5) + .setAgile(6) + .setArmorRating(14) + .setMeleSkill(8) + .setCurrentHealth(500) + .setMaxHealth(500) + .setWeaponRatingMin(10) + .setWeaponRatingMax(20) + .setNumberweaponOfRolls(1) + .setExperience(600); + + public final static StatsBuilder PHANTOM_ORC = new StatsBuilder() + .setStrength(23) + .setWillpower(4) + .setAim(5) + .setAgile(6) + .setArmorRating(11) + .setMeleSkill(8) + .setCurrentHealth(500) + .setMaxHealth(500) + .setWeaponRatingMin(10) + .setWeaponRatingMax(20) + .setNumberweaponOfRolls(1) + .setExperience(510); } diff --git a/src/main/java/com/comandante/creeper/npc/PhantomKnight.java b/src/main/java/com/comandante/creeper/npc/PhantomKnight.java new file mode 100644 index 00000000..e5746138 --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/PhantomKnight.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class PhantomKnight extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "phantom knight"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"p", "phantom", "knight","k", NAME} + )); + + private final static String colorName = "phantom" + BOLD_ON + Color.MAGENTA + " knight" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public PhantomKnight(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.PHANTOM_KNIGHT.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public PhantomKnight create(GameManager gameManager, Loot loot) { + return new PhantomKnight(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/PhantomOrc.java b/src/main/java/com/comandante/creeper/npc/PhantomOrc.java new file mode 100644 index 00000000..73b0c6fc --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/PhantomOrc.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class PhantomOrc extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "phantom orc"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"p", "phantom", "orc","o", NAME} + )); + + private final static String colorName = "phantom" + BOLD_ON + Color.MAGENTA + " orc" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public PhantomOrc(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.PHANTOM_ORC.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public PhantomOrc create(GameManager gameManager, Loot loot) { + return new PhantomOrc(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/PhantomWizard.java b/src/main/java/com/comandante/creeper/npc/PhantomWizard.java new file mode 100644 index 00000000..a733f635 --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/PhantomWizard.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class PhantomWizard extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "phantom wizard"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"p", "phantom", "wizard","w", NAME} + )); + + private final static String colorName = "phantom" + BOLD_ON + Color.MAGENTA + " wizard" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public PhantomWizard(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.PHANTOM_WIZARD.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public PhantomWizard create(GameManager gameManager, Loot loot) { + return new PhantomWizard(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/RazorClawWolf.java b/src/main/java/com/comandante/creeper/npc/RazorClawWolf.java new file mode 100644 index 00000000..5ccd3ce3 --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/RazorClawWolf.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class RazorClawWolf extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "razor-claw wolf"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"r", "razor-claw", "wolf","w", NAME} + )); + + private final static String colorName = "razor-claw" + BOLD_ON + Color.MAGENTA + " wolf" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public RazorClawWolf(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.RAZORCLAW_WOLF.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public RazorClawWolf create(GameManager gameManager, Loot loot) { + return new RazorClawWolf(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/npc/TigerMonocerus.java b/src/main/java/com/comandante/creeper/npc/TigerMonocerus.java new file mode 100644 index 00000000..e866f6a3 --- /dev/null +++ b/src/main/java/com/comandante/creeper/npc/TigerMonocerus.java @@ -0,0 +1,35 @@ +package com.comandante.creeper.npc; + + +import com.comandante.creeper.Items.Loot; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.server.Color; +import com.comandante.creeper.world.Area; +import com.google.common.base.Optional; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.comandante.creeper.server.Color.BOLD_ON; +import static com.comandante.creeper.server.Color.RESET; + +public class TigerMonocerus extends Npc { + private final static long phraseIntervalMs = 300000; + private final static String NAME = "tiger monocerus"; + private final static Set<String> validTriggers = new HashSet<String>(Arrays.asList(new String[] + {"t", "tiger", "monocerus","m", NAME} + )); + + private final static String colorName = "tiger" + BOLD_ON + Color.MAGENTA + " monocerus" + Color.RESET ; + private final static String dieMessage = "a " + colorName + " breathes his last breath in a pool of " + BOLD_ON + Color.RED + "blood" + RESET + "."; + + public TigerMonocerus(GameManager gameManager, Loot loot) { + super(gameManager, NAME, colorName, 0, NpcStats.TIGER_MONOCERUS.createStats(), dieMessage, Optional.<HashSet<Area>>absent(), validTriggers, loot); + } + + @Override + public TigerMonocerus create(GameManager gameManager, Loot loot) { + return new TigerMonocerus(gameManager, loot); + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/server/CreeperCommandHandler.java b/src/main/java/com/comandante/creeper/server/CreeperCommandHandler.java index 8a2a7351..e62c071c 100644 --- a/src/main/java/com/comandante/creeper/server/CreeperCommandHandler.java +++ b/src/main/java/com/comandante/creeper/server/CreeperCommandHandler.java @@ -1,7 +1,12 @@ package com.comandante.creeper.server; +import com.codahale.metrics.Counter; +import com.codahale.metrics.Meter; +import com.codahale.metrics.MetricRegistry; import com.comandante.creeper.Main; import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.merchant.Merchant; +import com.comandante.creeper.merchant.MerchantCommandHandler; import com.comandante.creeper.server.command.Command; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ExceptionEvent; @@ -11,6 +16,7 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler; public class CreeperCommandHandler extends SimpleChannelUpstreamHandler { private final GameManager gameManager; + private final Meter commandMeter = Main.metrics.meter(MetricRegistry.name(CreeperCommandHandler.class, "commands")); public CreeperCommandHandler(GameManager gameManager) { this.gameManager = gameManager; @@ -25,7 +31,15 @@ public class CreeperCommandHandler extends SimpleChannelUpstreamHandler { super.messageReceived(ctx, e); return; } + if (session.getGrabMerchant().isPresent()) { + Merchant merchant = session.getGrabMerchant().get().getKey(); + e.getChannel().getPipeline().addLast("executed_command", new MerchantCommandHandler(gameManager, merchant)); + super.messageReceived(ctx, e); + return; + } Command commandByTrigger = Main.creeperCommandRegistry.getCommandByTrigger(rootCommand); + Main.metrics.counter(MetricRegistry.name(CreeperCommandHandler.class, rootCommand + "-cmd")).inc(); + commandMeter.mark(); e.getChannel().getPipeline().addLast("executed_command", commandByTrigger); super.messageReceived(ctx, e); } diff --git a/src/main/java/com/comandante/creeper/server/CreeperSession.java b/src/main/java/com/comandante/creeper/server/CreeperSession.java index cfeba11e..9d026c7e 100644 --- a/src/main/java/com/comandante/creeper/server/CreeperSession.java +++ b/src/main/java/com/comandante/creeper/server/CreeperSession.java @@ -2,6 +2,7 @@ package com.comandante.creeper.server; import com.comandante.creeper.CreeperEntry; import com.comandante.creeper.fight.FightResults; +import com.comandante.creeper.merchant.Merchant; import com.comandante.creeper.server.command.Command; import com.google.common.base.Optional; @@ -19,6 +20,7 @@ public class CreeperSession { private Optional<Future<FightResults>> activeFight = Optional.absent(); private AtomicBoolean isAbleToDoAbility = new AtomicBoolean(false); private Optional<CreeperEntry<UUID, Command>> grabMultiLineInput = Optional.absent(); + private Optional<CreeperEntry<Merchant, Command>> grabMerchant = Optional.absent(); private final long sessionCreationTimestamp = System.currentTimeMillis(); private String lastMessage; @@ -104,4 +106,20 @@ public class CreeperSession { public void setGrabMultiLineInput(Optional<CreeperEntry<UUID, Command>> grabMultiLineInput) { this.grabMultiLineInput = grabMultiLineInput; } + + public AtomicBoolean getIsAbleToDoAbility() { + return isAbleToDoAbility; + } + + public void setIsAbleToDoAbility(AtomicBoolean isAbleToDoAbility) { + this.isAbleToDoAbility = isAbleToDoAbility; + } + + public Optional<CreeperEntry<Merchant, Command>> getGrabMerchant() { + return grabMerchant; + } + + public void setGrabMerchant(Optional<CreeperEntry<Merchant, Command>> grabMerchant) { + this.grabMerchant = grabMerchant; + } } diff --git a/src/main/java/com/comandante/creeper/server/command/Command.java b/src/main/java/com/comandante/creeper/server/command/Command.java index 9d1d23e1..09d7f5ab 100644 --- a/src/main/java/com/comandante/creeper/server/command/Command.java +++ b/src/main/java/com/comandante/creeper/server/command/Command.java @@ -77,7 +77,7 @@ public abstract class Command extends SimpleChannelUpstreamHandler { this.player = playerManager.getPlayer(extractPlayerId(creeperSession)); this.playerId = player.getPlayerId(); this.currentRoom = gameManager.getRoomManager().getPlayerCurrentRoom(player).get(); - this.mapMatrix = mapsManager.getFloorMatrixMaps().get(currentRoom.getFloorId()); + this.mapMatrix = mapsManager.getFloorMatrixMaps().get(currentRoom.getFloorId()); this.currentRoomCoords = mapMatrix.getCoords(currentRoom.getRoomId()); this.originalMessageParts = getOriginalMessageParts(e); this.playerMetadata = gameManager.getPlayerManager().getPlayerMetadata(playerId); @@ -85,11 +85,18 @@ public abstract class Command extends SimpleChannelUpstreamHandler { @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { - e.getChannel().getPipeline().remove(ctx.getHandler()); - String playerId = extractPlayerId(extractCreeperSession(e.getChannel())); - String prompt = gameManager.getPlayerManager().buildPrompt(playerId); - gameManager.getChannelUtils().write(playerId, prompt, true); - super.messageReceived(ctx, e); + try { + CreeperSession creeperSession = extractCreeperSession(e.getChannel()); + e.getChannel().getPipeline().remove(ctx.getHandler()); + if (creeperSession.getGrabMerchant().isPresent()) { + return; + } + String playerId = extractPlayerId(creeperSession); + String prompt = gameManager.getPlayerManager().buildPrompt(playerId); + gameManager.getChannelUtils().write(playerId, prompt, true); + } finally { + super.messageReceived(ctx, e); + } } public CreeperSession extractCreeperSession(Channel channel) { @@ -101,7 +108,7 @@ public abstract class Command extends SimpleChannelUpstreamHandler { return Main.createPlayerId(creeperSession.getUsername().get()); } - public String getRootCommand(MessageEvent e){ + public String getRootCommand(MessageEvent e) { String origMessage = (String) e.getMessage(); return origMessage.split(" ")[0].toLowerCase(); } @@ -123,7 +130,7 @@ public abstract class Command extends SimpleChannelUpstreamHandler { channelUtils.writeToRoom(playerId, msg); } - public void currentRoomLogic(){ + public void currentRoomLogic() { gameManager.currentRoomLogic(playerId); } @@ -134,4 +141,8 @@ public abstract class Command extends SimpleChannelUpstreamHandler { public String getPrompt() { return playerManager.buildPrompt(playerId); } + + public String getDescription() { + return description; + } } \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/server/command/TalkCommand.java b/src/main/java/com/comandante/creeper/server/command/TalkCommand.java new file mode 100644 index 00000000..f698e8c1 --- /dev/null +++ b/src/main/java/com/comandante/creeper/server/command/TalkCommand.java @@ -0,0 +1,54 @@ +package com.comandante.creeper.server.command; + + +import com.comandante.creeper.CreeperEntry; +import com.comandante.creeper.managers.GameManager; +import com.comandante.creeper.merchant.Merchant; +import com.comandante.creeper.player.Player; +import com.google.common.base.Joiner; +import com.google.common.base.Optional; +import org.jboss.netty.channel.ChannelHandlerContext; +import org.jboss.netty.channel.MessageEvent; + +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +import static com.comandante.creeper.server.Color.RESET; +import static com.comandante.creeper.server.Color.YELLOW; + +public class TalkCommand extends Command { + + final static List<String> validTriggers = Arrays.asList("talk"); + final static String description = "Talk to a merchant."; + + public TalkCommand(GameManager gameManager) { + super(gameManager, validTriggers, description); + } + + @Override + public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { + configure(e); + try { + if (creeperSession.getGrabMerchant().isPresent()) { + creeperSession.setGrabMerchant(Optional.<CreeperEntry<Merchant, Command>>absent()); + return; + } + originalMessageParts.remove(0); + String desiredMerchantTalk = Joiner.on(" ").join(originalMessageParts); + Set<Merchant> merchants = currentRoom.getMerchants(); + for (Merchant merchant: merchants) { + if (merchant.getValidTriggers().contains(desiredMerchantTalk)) { + write(merchant.getWelcomeMessage() + "\r\n"); + write(merchant.getMenu() + "\r\n"); + gameManager.getChannelUtils().write(playerId, "\r\n[" + merchant.getName() + " (done to exit, buy <itemNo>)] "); + creeperSession.setGrabMerchant(Optional.of( + new CreeperEntry<Merchant, Command>(merchant, this))); + } + } + } finally { + super.messageReceived(ctx, e); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/comandante/creeper/server/command/WhoCommand.java b/src/main/java/com/comandante/creeper/server/command/WhoCommand.java index 490f728d..a3c5f32c 100644 --- a/src/main/java/com/comandante/creeper/server/command/WhoCommand.java +++ b/src/main/java/com/comandante/creeper/server/command/WhoCommand.java @@ -28,7 +28,6 @@ public class WhoCommand extends Command { try { Table t = new Table(3, BorderStyle.CLASSIC_COMPATIBLE, ShownBorders.HEADER_AND_FIRST_COLLUMN); - t.setColumnWidth(0, 8, 14); t.setColumnWidth(1, 14, 16); t.setColumnWidth(2, 26, 26); diff --git a/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java b/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java index 78150bf5..0d7a9c2e 100644 --- a/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java +++ b/src/main/java/com/comandante/creeper/spawner/ItemSpawner.java @@ -1,7 +1,9 @@ package com.comandante.creeper.spawner; +import com.codahale.metrics.MetricRegistry; import com.comandante.creeper.Items.Item; import com.comandante.creeper.Items.ItemType; +import com.comandante.creeper.Main; import com.comandante.creeper.entity.CreeperEntity; import com.comandante.creeper.managers.GameManager; import com.comandante.creeper.world.Area; @@ -58,6 +60,7 @@ public class ItemSpawner extends CreeperEntity { Item item = spawnItemType.create(); gameManager.getEntityManager().addItem(item); gameManager.placeItemInRoom(room.getRoomId(), item.getItemId()); + Main.metrics.counter(MetricRegistry.name(ItemSpawner.class, item.getItemName() + "-spawn")).inc(); } private int counterNumberInArea() { diff --git a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java index cf9b4d20..eb555787 100644 --- a/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java +++ b/src/main/java/com/comandante/creeper/spawner/NpcSpawner.java @@ -1,6 +1,8 @@ package com.comandante.creeper.spawner; +import com.codahale.metrics.MetricRegistry; +import com.comandante.creeper.Main; import com.comandante.creeper.entity.CreeperEntity; import com.comandante.creeper.managers.GameManager; import com.comandante.creeper.npc.Npc; @@ -75,6 +77,7 @@ public class NpcSpawner extends CreeperEntity { Npc newNpc = npc.create(gameManager, npc.getLoot()); gameManager.getEntityManager().addEntity(newNpc); room.addPresentNpc(newNpc.getEntityId()); + Main.metrics.counter(MetricRegistry.name(NpcSpawner.class, npc.getName() + "-spawn")).inc(); } private Predicate<Room> getRoomsWithRoom() { diff --git a/src/main/java/com/comandante/creeper/world/Room.java b/src/main/java/com/comandante/creeper/world/Room.java index 87ce45cb..816f678c 100644 --- a/src/main/java/com/comandante/creeper/world/Room.java +++ b/src/main/java/com/comandante/creeper/world/Room.java @@ -1,6 +1,7 @@ package com.comandante.creeper.world; import com.comandante.creeper.entity.CreeperEntity; +import com.comandante.creeper.merchant.Merchant; import com.comandante.creeper.spawner.ItemSpawner; import com.google.common.base.Optional; import com.google.common.collect.Lists; @@ -40,6 +41,7 @@ public abstract class Room extends CreeperEntity { private Set<Area> areas = Sets.newConcurrentHashSet(); private Optional<String> mapData = Optional.absent(); private final Set<String> roomTags; + private final Set<Merchant> merchants = Sets.newConcurrentHashSet(); public Room(Integer roomId, String roomTitle, @@ -68,6 +70,22 @@ public abstract class Room extends CreeperEntity { this.enterExits = enterExits; } + public List<ItemSpawner> getItemSpawners() { + return itemSpawners; + } + + public void setItemSpawners(List<ItemSpawner> itemSpawners) { + this.itemSpawners = itemSpawners; + } + + public Set<Merchant> getMerchants() { + return merchants; + } + + public void addMerchant(Merchant merchant) { + merchants.add(merchant); + } + public Set<String> getRoomTags() { return roomTags; } diff --git a/src/main/java/com/comandante/creeper/world/RoomManager.java b/src/main/java/com/comandante/creeper/world/RoomManager.java index 4acdc970..fa7f3f1e 100644 --- a/src/main/java/com/comandante/creeper/world/RoomManager.java +++ b/src/main/java/com/comandante/creeper/world/RoomManager.java @@ -1,5 +1,6 @@ package com.comandante.creeper.world; +import com.comandante.creeper.merchant.Merchant; import com.comandante.creeper.npc.Npc; import com.comandante.creeper.player.Player; import com.google.common.base.Optional; @@ -41,6 +42,10 @@ public class RoomManager { } } + public void addMerchant(Integer roomId, Merchant merchant) { + getRoom(roomId).addMerchant(merchant); + } + public void tagRoom(Integer roomId, String tag) { getRoom(roomId).addTag(tag); } diff --git a/src/main/java/com/comandante/creeper/world/WorldExporter.java b/src/main/java/com/comandante/creeper/world/WorldExporter.java index e8be11cb..dd5ed253 100644 --- a/src/main/java/com/comandante/creeper/world/WorldExporter.java +++ b/src/main/java/com/comandante/creeper/world/WorldExporter.java @@ -110,6 +110,7 @@ public class WorldExporter { Map.Entry<String, String> next = iterator.next(); RemoteExit remoteExit = new RemoteExit(RemoteExit.Direction.ENTER, Integer.parseInt(next.getKey()), next.getValue()); basicRoomBuilder.addEnterExit(remoteExit); + mapMatrix.addRemote(roomModel.getRoomId(), remoteExit); } } configureExits(basicRoomBuilder, mapMatrix, roomModel.getRoomId()); diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties new file mode 100644 index 00000000..40b54e0b --- /dev/null +++ b/src/main/resources/log4j.properties @@ -0,0 +1,22 @@ +log4j.rootLogger=DEBUG, stdout, stderr + +# configure stdout +# set the conversion pattern of stdout +# Print the date in ISO 8601 format +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Threshold = INFO +log4j.appender.stdout.Target = System.out +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n +log4j.appender.stdout.filter.filter1=org.apache.log4j.varia.LevelRangeFilter +log4j.appender.stdout.filter.filter1.levelMin=TRACE +log4j.appender.stdout.filter.filter1.levelMax=INFO + +# configure stderr +# set the conversion pattern of stdout +# Print the date in ISO 8601 format +log4j.appender.stderr = org.apache.log4j.ConsoleAppender +log4j.appender.stderr.Threshold = WARN +log4j.appender.stderr.Target = System.err +log4j.appender.stderr.layout = org.apache.log4j.PatternLayout +log4j.appender.stderr.layout.ConversionPattern = %-5p %d [%t][%F:%L] : %m%n \ No newline at end of file -- GitLab